xonecode 0.2.0 → 0.5.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/README.md +49 -7
- package/THIRD_PARTY_NOTICES.md +128 -0
- package/apps/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/apps/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/apps/web/dist/assets/c-BIGW1oBm.js +1 -0
- package/apps/web/dist/assets/cpp-DddhVWhK.js +1 -0
- package/apps/web/dist/assets/csharp-DSvCPggb.js +1 -0
- package/apps/web/dist/assets/css-CLj8gQPS.js +1 -0
- package/apps/web/dist/assets/go-C27-OAKa.js +1 -0
- package/apps/web/dist/assets/html-CfGypltT.js +1 -0
- package/apps/web/dist/assets/index-BB3SamhR.css +1 -0
- package/apps/web/dist/assets/index-CFYAoHdw.js +477 -0
- package/apps/web/dist/assets/ini-BEwlwnbL.js +1 -0
- package/apps/web/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/apps/web/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/apps/web/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/apps/web/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/apps/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/apps/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/apps/web/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/apps/web/dist/assets/java-CylS5w8V.js +1 -0
- package/apps/web/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/apps/web/dist/assets/kotlin-BdnUsdx6.js +1 -0
- package/apps/web/dist/assets/less-B1dDrJ26.js +1 -0
- package/apps/web/dist/assets/lua-BaeVxFsk.js +1 -0
- package/apps/web/dist/assets/markdown-Cvjx9yec.js +1 -0
- package/apps/web/dist/assets/mdx-Cmh6b_Ma.js +1 -0
- package/apps/web/dist/assets/php-D_2--9WK.js +1 -0
- package/apps/web/dist/assets/python-B6aJPvgy.js +1 -0
- package/apps/web/dist/assets/ruby-DSHSDbk1.js +1 -0
- package/apps/web/dist/assets/rust-B1yitclQ.js +1 -0
- package/apps/web/dist/assets/scss-D5BDwBP9.js +1 -0
- package/apps/web/dist/assets/sql-CRqJ_cUM.js +1 -0
- package/apps/web/dist/assets/swift-C2oV4EkX.js +1 -0
- package/apps/web/dist/assets/toml-vGWfd6FD.js +1 -0
- package/apps/web/dist/assets/xml-sdJ4AIDG.js +1 -0
- package/apps/web/dist/assets/yaml-Buea-lGh.js +1 -0
- package/apps/web/dist/iconos/xonecode.png +0 -0
- package/apps/web/dist/index.html +20 -0
- package/dist/agent/agentesEnDisco.js +539 -0
- package/dist/agent/agentesEnDisco.js.map +1 -0
- package/dist/agent/arbolDeProyecto.js +245 -0
- package/dist/agent/arbolDeProyecto.js.map +1 -0
- package/dist/agent/artefactosEnDisco.js +139 -0
- package/dist/agent/artefactosEnDisco.js.map +1 -0
- package/dist/agent/aumentador.js +175 -0
- package/dist/agent/aumentador.js.map +1 -0
- package/dist/agent/authEnDisco.js +76 -1
- package/dist/agent/authEnDisco.js.map +1 -1
- package/dist/agent/busquedaRegex.js +92 -0
- package/dist/agent/busquedaRegex.js.map +1 -0
- package/dist/agent/catalogoModelos.js +345 -0
- package/dist/agent/catalogoModelos.js.map +1 -0
- package/dist/agent/checkpointer.js +127 -0
- package/dist/agent/checkpointer.js.map +1 -0
- package/dist/agent/cloudstudioClient.js +194 -0
- package/dist/agent/cloudstudioClient.js.map +1 -0
- package/dist/agent/cloudstudioMcp.js +722 -0
- package/dist/agent/cloudstudioMcp.js.map +1 -0
- package/dist/agent/configEnDisco.js +309 -11
- package/dist/agent/configEnDisco.js.map +1 -1
- package/dist/agent/consumoExterno.js +99 -0
- package/dist/agent/consumoExterno.js.map +1 -0
- package/dist/agent/descarga.js +149 -0
- package/dist/agent/descarga.js.map +1 -0
- package/dist/agent/diagnosticoDeTools.js +51 -0
- package/dist/agent/diagnosticoDeTools.js.map +1 -0
- package/dist/agent/dispositivosEnMaquina.js +596 -0
- package/dist/agent/dispositivosEnMaquina.js.map +1 -0
- package/dist/agent/escrituraDeCodex.js +134 -0
- package/dist/agent/escrituraDeCodex.js.map +1 -0
- package/dist/agent/escrituraDeOpencode.js +80 -0
- package/dist/agent/escrituraDeOpencode.js.map +1 -0
- package/dist/agent/escrituraExterna.js +742 -0
- package/dist/agent/escrituraExterna.js.map +1 -0
- package/dist/agent/gemini.js +81 -0
- package/dist/agent/gemini.js.map +1 -0
- package/dist/agent/git.js +83 -0
- package/dist/agent/git.js.map +1 -0
- package/dist/agent/gitSync.js +441 -0
- package/dist/agent/gitSync.js.map +1 -0
- package/dist/agent/hotswap.js +448 -0
- package/dist/agent/hotswap.js.map +1 -0
- package/dist/agent/instalacionEnMaquina.js +252 -0
- package/dist/agent/instalacionEnMaquina.js.map +1 -0
- package/dist/agent/instantanea.js +7 -10
- package/dist/agent/instantanea.js.map +1 -1
- package/dist/agent/interrupts.js +11 -2
- package/dist/agent/interrupts.js.map +1 -1
- package/dist/agent/juezDeTarea.js +345 -0
- package/dist/agent/juezDeTarea.js.map +1 -0
- package/dist/agent/lanzamientoEnMaquina.js +377 -0
- package/dist/agent/lanzamientoEnMaquina.js.map +1 -0
- package/dist/agent/manifiesto.js +59 -0
- package/dist/agent/manifiesto.js.map +1 -0
- package/dist/agent/memoriaDeProyecto.js +60 -0
- package/dist/agent/memoriaDeProyecto.js.map +1 -0
- package/dist/agent/modelos.js +105 -17
- package/dist/agent/modelos.js.map +1 -1
- package/dist/agent/modelosDeMotor.js +204 -0
- package/dist/agent/modelosDeMotor.js.map +1 -0
- package/dist/agent/paqueteDelProyecto.js +181 -0
- package/dist/agent/paqueteDelProyecto.js.map +1 -0
- package/dist/agent/perfiles.js +92 -31
- package/dist/agent/perfiles.js.map +1 -1
- package/dist/agent/persona.js +40 -0
- package/dist/agent/persona.js.map +1 -0
- package/dist/agent/procesosEnMaquina.js +204 -0
- package/dist/agent/procesosEnMaquina.js.map +1 -0
- package/dist/agent/proyecto.js +311 -13
- package/dist/agent/proyecto.js.map +1 -1
- package/dist/agent/puente.js +63 -6
- package/dist/agent/puente.js.map +1 -1
- package/dist/agent/resumenDeContexto.js +30 -0
- package/dist/agent/resumenDeContexto.js.map +1 -0
- package/dist/agent/resumenDeTool.js +64 -18
- package/dist/agent/resumenDeTool.js.map +1 -1
- package/dist/agent/sesionGit.js +481 -0
- package/dist/agent/sesionGit.js.map +1 -0
- package/dist/agent/settingsEnDisco.js +189 -0
- package/dist/agent/settingsEnDisco.js.map +1 -0
- package/dist/agent/subagenteCodex.js +368 -0
- package/dist/agent/subagenteCodex.js.map +1 -0
- package/dist/agent/subagenteExterno.js +423 -0
- package/dist/agent/subagenteExterno.js.map +1 -0
- package/dist/agent/subagenteOpencode.js +389 -0
- package/dist/agent/subagenteOpencode.js.map +1 -0
- package/dist/agent/subida.js +202 -0
- package/dist/agent/subida.js.map +1 -0
- package/dist/agent/tareasEnDisco.js +466 -0
- package/dist/agent/tareasEnDisco.js.map +1 -0
- package/dist/agent/turnoReal.js +663 -50
- package/dist/agent/turnoReal.js.map +1 -1
- package/dist/agent/versionEnDisco.js +48 -0
- package/dist/agent/versionEnDisco.js.map +1 -0
- package/dist/agent/xoneAgent.js +290 -49
- package/dist/agent/xoneAgent.js.map +1 -1
- package/dist/agent/zip.js +52 -0
- package/dist/agent/zip.js.map +1 -0
- package/dist/cli/acuseDeModelo.js +30 -0
- package/dist/cli/acuseDeModelo.js.map +1 -0
- package/dist/cli/aprobar.js +55 -2
- package/dist/cli/aprobar.js.map +1 -1
- package/dist/cli/config.js +9 -13
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/consola.js +750 -19
- package/dist/cli/consola.js.map +1 -1
- package/dist/cli/main.js +740 -81
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/markdown.js +188 -2
- package/dist/cli/markdown.js.map +1 -1
- package/dist/cli/run.js +32 -4
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/stdio.js +46 -19
- package/dist/cli/stdio.js.map +1 -1
- package/dist/cli/tema.js +96 -8
- package/dist/cli/tema.js.map +1 -1
- package/dist/cli/tokens.js +29 -0
- package/dist/cli/tokens.js.map +1 -0
- package/dist/cli/tui/app.js +171 -0
- package/dist/cli/tui/app.js.map +1 -0
- package/dist/cli/tui/aprobarTui.js +80 -0
- package/dist/cli/tui/aprobarTui.js.map +1 -0
- package/dist/cli/tui/barra.js +37 -0
- package/dist/cli/tui/barra.js.map +1 -0
- package/dist/cli/tui/correrTui.js +478 -0
- package/dist/cli/tui/correrTui.js.map +1 -0
- package/dist/cli/tui/entrada.js +166 -0
- package/dist/cli/tui/entrada.js.map +1 -0
- package/dist/cli/tui/filas.js +24 -0
- package/dist/cli/tui/filas.js.map +1 -0
- package/dist/cli/tui/logo.js +49 -0
- package/dist/cli/tui/logo.js.map +1 -0
- package/dist/cli/tui/pielTui.js +14 -0
- package/dist/cli/tui/pielTui.js.map +1 -0
- package/dist/cli/tui/raton.js +126 -0
- package/dist/cli/tui/raton.js.map +1 -0
- package/dist/cli/tui/sidebar.js +86 -0
- package/dist/cli/tui/sidebar.js.map +1 -0
- package/dist/cli/tui/store.js +143 -0
- package/dist/cli/tui/store.js.map +1 -0
- package/dist/cli/tui/tarjeta.js +19 -0
- package/dist/cli/tui/tarjeta.js.map +1 -0
- package/dist/cli/tui/temaInk.js +114 -0
- package/dist/cli/tui/temaInk.js.map +1 -0
- package/dist/cli/tui/transcript.js +254 -0
- package/dist/cli/tui/transcript.js.map +1 -0
- package/dist/cli/wizardInicial.js +240 -0
- package/dist/cli/wizardInicial.js.map +1 -0
- package/dist/core/actos.js +113 -0
- package/dist/core/actos.js.map +1 -0
- package/dist/core/adjuntos.js +97 -0
- package/dist/core/adjuntos.js.map +1 -0
- package/dist/core/agentes.js +227 -0
- package/dist/core/agentes.js.map +1 -0
- package/dist/core/artefactos.js +149 -0
- package/dist/core/artefactos.js.map +1 -0
- package/dist/core/cloudstudio.js +7 -0
- package/dist/core/cloudstudio.js.map +1 -0
- package/dist/core/config.js +212 -5
- package/dist/core/config.js.map +1 -1
- package/dist/core/contextos.js +53 -1
- package/dist/core/contextos.js.map +1 -1
- package/dist/core/descargas.js +106 -0
- package/dist/core/descargas.js.map +1 -0
- package/dist/core/descriptoresDeApp.js +279 -0
- package/dist/core/descriptoresDeApp.js.map +1 -0
- package/dist/core/dispositivos.js +466 -0
- package/dist/core/dispositivos.js.map +1 -0
- package/dist/core/entrega.js +141 -0
- package/dist/core/entrega.js.map +1 -0
- package/dist/core/entrelazar.js +90 -0
- package/dist/core/entrelazar.js.map +1 -0
- package/dist/core/esqueleto.js +10 -0
- package/dist/core/esqueleto.js.map +1 -1
- package/dist/core/modelos.js +235 -3
- package/dist/core/modelos.js.map +1 -1
- package/dist/core/notify.js +27 -9
- package/dist/core/notify.js.map +1 -1
- package/dist/core/planDeSubida.js +127 -0
- package/dist/core/planDeSubida.js.map +1 -0
- package/dist/core/ports.js +189 -1
- package/dist/core/ports.js.map +1 -1
- package/dist/core/puedeLanzarse.js +239 -0
- package/dist/core/puedeLanzarse.js.map +1 -0
- package/dist/core/rutaVirtual.js +42 -0
- package/dist/core/rutaVirtual.js.map +1 -0
- package/dist/core/settings.js +246 -0
- package/dist/core/settings.js.map +1 -0
- package/dist/core/tareas.js +230 -0
- package/dist/core/tareas.js.map +1 -0
- package/dist/core/textos.js +36 -0
- package/dist/core/textos.js.map +1 -0
- package/dist/core/turno.js +70 -10
- package/dist/core/turno.js.map +1 -1
- package/dist/core/version.js +31 -0
- package/dist/core/version.js.map +1 -0
- package/dist/vendor/tokenTracking.js +22 -1
- package/dist/vendor/tokenTracking.js.map +1 -1
- package/dist/web/servidor/arranque.js +3964 -0
- package/dist/web/servidor/arranque.js.map +1 -0
- package/dist/web/servidor/consolaDeTarea.js +161 -0
- package/dist/web/servidor/consolaDeTarea.js.map +1 -0
- package/dist/web/servidor/consolaWeb.js +389 -0
- package/dist/web/servidor/consolaWeb.js.map +1 -0
- package/dist/web/servidor/corredorDeTareas.js +1119 -0
- package/dist/web/servidor/corredorDeTareas.js.map +1 -0
- package/dist/web/servidor/pielWeb.js +269 -0
- package/dist/web/servidor/pielWeb.js.map +1 -0
- package/dist/web/servidor/servidor.js +257 -0
- package/dist/web/servidor/servidor.js.map +1 -0
- package/dist/web/servidor/sesiones.js +440 -0
- package/dist/web/servidor/sesiones.js.map +1 -0
- package/dist/web/servidor/transporte.js +169 -0
- package/dist/web/servidor/transporte.js.map +1 -0
- package/dist/web/servidor/vestibulo.js +1276 -0
- package/dist/web/servidor/vestibulo.js.map +1 -0
- package/package.json +30 -8
- package/skills/archify/LICENSE +22 -0
- package/skills/archify/SKILL.md +109 -0
- package/skills/archify/THIRD_PARTY_NOTICES.md +56 -0
- package/skills/archify/assets/template.html +14787 -0
- package/skills/archify/bin/archify.mjs +1990 -0
- package/skills/archify/bin/open-artifact.mjs +86 -0
- package/skills/archify/bin/preview.mjs +648 -0
- package/skills/archify/bin/visual-check.mjs +829 -0
- package/skills/archify/brand-marks/README.md +31 -0
- package/skills/archify/brand-marks/catalog.json +131 -0
- package/skills/archify/delta/architecture-delta.mjs +1214 -0
- package/skills/archify/examples/agent-run.lifecycle.json +71 -0
- package/skills/archify/examples/agent-tool-call.workflow.json +94 -0
- package/skills/archify/examples/async-job-roundtrip.sequence.json +61 -0
- package/skills/archify/examples/brand-aware-delivery.architecture.json +47 -0
- package/skills/archify/examples/cache-miss-request.sequence.json +81 -0
- package/skills/archify/examples/checkout-platform.base.architecture.json +31 -0
- package/skills/archify/examples/checkout-platform.head.architecture.json +31 -0
- package/skills/archify/examples/dataflow-product-analytics.html +14898 -0
- package/skills/archify/examples/deployment-release.lifecycle.json +49 -0
- package/skills/archify/examples/event-stream.dataflow.json +57 -0
- package/skills/archify/examples/incident-response.workflow.json +64 -0
- package/skills/archify/examples/lifecycle-agent-run.html +14847 -0
- package/skills/archify/examples/product-analytics.dataflow.json +76 -0
- package/skills/archify/examples/production-deployment.architecture.json +71 -0
- package/skills/archify/examples/release-delivery.workflow.json +62 -0
- package/skills/archify/examples/sequence-cache-miss-request.html +14913 -0
- package/skills/archify/examples/web-app-rendered.html +14862 -0
- package/skills/archify/examples/web-app.architecture.json +46 -0
- package/skills/archify/examples/workflow-agent-tool-call-rendered.html +14904 -0
- package/skills/archify/migrations/workflow-v2.mjs +279 -0
- package/skills/archify/package.json +17 -0
- package/skills/archify/recipes/scenarios.mjs +391 -0
- package/skills/archify/references/authoring-contract.md +198 -0
- package/skills/archify/references/brand-marks.md +69 -0
- package/skills/archify/references/delivery-contract.md +116 -0
- package/skills/archify/references/viewer-runtime.md +45 -0
- package/skills/archify/renderers/architecture/grid.mjs +62 -0
- package/skills/archify/renderers/architecture/render-architecture.mjs +1078 -0
- package/skills/archify/renderers/dataflow/README.md +104 -0
- package/skills/archify/renderers/dataflow/render-dataflow.mjs +483 -0
- package/skills/archify/renderers/lifecycle/README.md +115 -0
- package/skills/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
- package/skills/archify/renderers/sequence/README.md +114 -0
- package/skills/archify/renderers/sequence/render-sequence.mjs +453 -0
- package/skills/archify/renderers/shared/brand-marks.mjs +563 -0
- package/skills/archify/renderers/shared/cli.mjs +218 -0
- package/skills/archify/renderers/shared/desktop-readability.mjs +26 -0
- package/skills/archify/renderers/shared/diagnostics.mjs +127 -0
- package/skills/archify/renderers/shared/engineering-profiles.mjs +157 -0
- package/skills/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
- package/skills/archify/renderers/shared/generated-validators.mjs +13 -0
- package/skills/archify/renderers/shared/geometry.mjs +1423 -0
- package/skills/archify/renderers/shared/i18n.mjs +594 -0
- package/skills/archify/renderers/shared/layout-report.mjs +40 -0
- package/skills/archify/renderers/shared/legend.mjs +217 -0
- package/skills/archify/renderers/shared/output-path.mjs +321 -0
- package/skills/archify/renderers/shared/repository-evidence.mjs +235 -0
- package/skills/archify/renderers/shared/text-fit.mjs +49 -0
- package/skills/archify/renderers/shared/utils.mjs +232 -0
- package/skills/archify/renderers/shared/validator.mjs +86 -0
- package/skills/archify/renderers/workflow/README.md +223 -0
- package/skills/archify/renderers/workflow/render-workflow.mjs +35 -0
- package/skills/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
- package/skills/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
- package/skills/archify/schemas/README.md +211 -0
- package/skills/archify/schemas/architecture.schema.json +176 -0
- package/skills/archify/schemas/common.schema.json +115 -0
- package/skills/archify/schemas/dataflow.schema.json +243 -0
- package/skills/archify/schemas/lifecycle.schema.json +266 -0
- package/skills/archify/schemas/sequence.schema.json +223 -0
- package/skills/archify/schemas/workflow.schema.json +428 -0
- package/skills/archify/scripts/check-render-output.mjs +835 -0
- package/skills/archify/scripts/check-update.mjs +1667 -0
- package/skills/archify/scripts/render-examples.mjs +26 -0
- package/skills/archify/scripts/update-contract.mjs +182 -0
- package/skills/archify/skill-release.json +10 -0
- package/skills/artifacts-builder/SKILL.md +120 -0
- package/skills/artifacts-builder/reference/diagramas.md +123 -0
- package/skills/artifacts-builder/reference/estilo.md +123 -0
- package/skills/artifacts-builder/reference/exportar-pdf.md +56 -0
- package/skills/artifacts-builder/reference/graficas.md +22 -0
- package/skills/artifacts-builder/scripts/bundle_artifact.py +109 -0
- package/skills/artifacts-builder/scripts/validate_artifact.py +345 -0
- package/skills/xone-hotswap/SKILL.md +185 -0
- package/skills/xone-hotswap/references/comandos.md +706 -0
- package/skills/xone-hotswap/references/conexion-y-despliegue.md +226 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Las sesiones de un proyecto, en su `.xonecode/sesiones/`.
|
|
3
|
+
*
|
|
4
|
+
* Ahí y no en global porque la sesión es del proyecto, ya hay precedente
|
|
5
|
+
* (`conversation_history/` en `agent/memoriaDeProyecto.ts`), la carpeta está denegada
|
|
6
|
+
* entera al agente (`permisosDe`) y **no sube nunca** a CloudStudio — el mismo trato que
|
|
7
|
+
* `.xonecode/` recibe en todas partes de este repo.
|
|
8
|
+
*
|
|
9
|
+
* Se guardan **actos** (`core/actos.ts`), no `DomainEvent`. La distinción no es cosmética:
|
|
10
|
+
* ningún evento lleva el texto que escribió el usuario — `tool.detalle` es la única
|
|
11
|
+
* excepción, y es una lista blanca de campo de ruta, nunca prosa —, así que un fichero de
|
|
12
|
+
* eventos daría una sesión reabierta con respuestas y sin preguntas. Y por construcción no
|
|
13
|
+
* hay filtrado que hacer para cumplir «nada de diffs ni contenido de fichero»: el tipo
|
|
14
|
+
* `Acto` no tiene ningún campo que pueda llevarlos. El único sitio del sistema donde el
|
|
15
|
+
* contenido de un fichero viaja es el mensaje de aprobación
|
|
16
|
+
* (`consolaWeb.ts#aprobacionesTui`), que no es un acto y se suelta en cuanto hay decisión
|
|
17
|
+
* — nunca llega aquí.
|
|
18
|
+
*
|
|
19
|
+
* Reabrir ya NO es releer, y este fichero dejó de ser la única memoria. El hilo del agente
|
|
20
|
+
* vive en el checkpointer de SQLite del proyecto (`agent/checkpointer.ts`), indexado por el
|
|
21
|
+
* mismo id que titula estas entradas, así que una sesión reabierta continúa de verdad. Lo
|
|
22
|
+
* que sigue viviendo aquí es el TRANSCRIPT —lo que se pinta—, y son dos cosas distintas a
|
|
23
|
+
* propósito: un acto no puede llevar contenido de fichero ni argumentos de tool, y un
|
|
24
|
+
* checkpoint los lleva todos. Por eso el `.jsonl` puede viajar y el `.sqlite` no.
|
|
25
|
+
* `historica` deja de ser «se reabrió» y pasa a ser un hecho comprobado: se pregunta al
|
|
26
|
+
* checkpointer, y solo se marca si de ese hilo no queda memoria —una sesión de antes de que
|
|
27
|
+
* esto existiera, o una cuyo primer turno nunca corrió—. Fingir que la conversación continúa
|
|
28
|
+
* cuando el modelo no recuerda nada sería justo la clase de mentira muda que este repo evita
|
|
29
|
+
* (`bitacora.ts` es el mismo principio aplicado a los avisos de honestidad).
|
|
30
|
+
* `historica` no se escribe a disco — no es un campo de `EntradaIndice` ni del `.jsonl` —
|
|
31
|
+
* porque es un hecho del MOMENTO de reabrir, no del estado de la sesión: quien reabre
|
|
32
|
+
* decide en memoria cuándo el primer turno nuevo la desactiva, y persistir la marca
|
|
33
|
+
* obligaría a un segundo sitio a mantenerla sincronizada con ese momento.
|
|
34
|
+
*
|
|
35
|
+
* `indice.json` se reescribe entero (es pequeño, una entrada por sesión) con el mismo
|
|
36
|
+
* cuidado atómico que `agent/settingsEnDisco.ts#escribirAtomico` — temporal + `renameSync`,
|
|
37
|
+
* porque un `writeFileSync` a medias tras un crash dejaría corrompido el índice de TODAS
|
|
38
|
+
* las sesiones, no solo la que se estaba anotando. El `.jsonl` de una sesión, en cambio, se
|
|
39
|
+
* **anexa** (`appendFileSync`): reescribirlo entero en cada acto lo haría cuadrático en el
|
|
40
|
+
* número de actos de la sesión, y arriesgaría perder la sesión completa a un crash a mitad
|
|
41
|
+
* de escritura en vez de, como mucho, la última línea — que `reabrirSesion` ya tolera.
|
|
42
|
+
*/
|
|
43
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
44
|
+
import { randomUUID } from "node:crypto";
|
|
45
|
+
import { dirname, join } from "node:path";
|
|
46
|
+
import { acumularTotales, consumoDeLosActos } from "../../core/actos.js";
|
|
47
|
+
import { carpetaDeArtefactosDeSesion } from "../../core/artefactos.js";
|
|
48
|
+
import { segmentoSeguro } from "../../core/settings.js";
|
|
49
|
+
import { tituloDesde } from "../../core/textos.js";
|
|
50
|
+
/** Cuántos caracteres de la primera prosa del usuario se guardan como título. */
|
|
51
|
+
const LARGO_TITULO = 80;
|
|
52
|
+
/**
|
|
53
|
+
* El título automático de una sesión, a partir de su primera petición.
|
|
54
|
+
*
|
|
55
|
+
* Se movió a `core/textos.ts` cuando las TAREAS necesitaron el mismo título: `core/` no
|
|
56
|
+
* puede importar de `web/`, y una segunda copia habría divergido. Se reexporta con su
|
|
57
|
+
* nombre de siempre porque `anotarActo`, en este mismo fichero, y sus tests lo usan desde
|
|
58
|
+
* aquí.
|
|
59
|
+
*/
|
|
60
|
+
export { tituloDesde };
|
|
61
|
+
function carpetaSesiones(raiz) {
|
|
62
|
+
return join(raiz, ".xonecode", "sesiones");
|
|
63
|
+
}
|
|
64
|
+
function rutaIndice(raiz) {
|
|
65
|
+
return join(carpetaSesiones(raiz), "indice.json");
|
|
66
|
+
}
|
|
67
|
+
/** `crearSesion` genera el id con `randomUUID()`, pero `anotarActo` y `reabrirSesion` lo
|
|
68
|
+
* reciben tal cual llega del cliente por HTTP: sin esta guarda un id como `"../../.env"`
|
|
69
|
+
* compondría una ruta fuera de `sesiones/`. Misma función que usa `rutaDeWorkspace` en
|
|
70
|
+
* `core/settings.ts`, no una copia — dos copias es cómo diverge la guarda el día que una
|
|
71
|
+
* se corrija y la otra no.
|
|
72
|
+
*/
|
|
73
|
+
function rutaJsonl(raiz, id) {
|
|
74
|
+
return join(carpetaSesiones(raiz), `${segmentoSeguro(id, "id de sesión")}.jsonl`);
|
|
75
|
+
}
|
|
76
|
+
/** Una entrada que no es un objeto reconocible no cuenta: sin este filtro, un índice con
|
|
77
|
+
* basura colada (`[null]`, `[42]`) hace que `entradas.find` reviente en cuanto alguien lea
|
|
78
|
+
* `.id` de un elemento que no lo tiene.
|
|
79
|
+
*/
|
|
80
|
+
function esEntrada(v) {
|
|
81
|
+
return typeof v === "object" && v !== null && typeof v.id === "string";
|
|
82
|
+
}
|
|
83
|
+
/** Lee el índice para MOSTRARLO (`listarSesiones`); sin fichero o con JSON roto, una lista
|
|
84
|
+
* vacía — un índice no se puede reconstruir solo leyéndolo, así que fallar aquí no puede
|
|
85
|
+
* tumbar la reapertura de ninguna sesión (mismo principio que la línea corrupta del
|
|
86
|
+
* `.jsonl`, aplicado al índice). Nunca la uses como base de una ESCRITURA: ver
|
|
87
|
+
* `leerIndiceOAbortar`.
|
|
88
|
+
*/
|
|
89
|
+
function leerIndice(raiz) {
|
|
90
|
+
const ruta = rutaIndice(raiz);
|
|
91
|
+
if (!existsSync(ruta))
|
|
92
|
+
return [];
|
|
93
|
+
try {
|
|
94
|
+
const bruto = JSON.parse(readFileSync(ruta, "utf8"));
|
|
95
|
+
return Array.isArray(bruto) ? bruto.filter(esEntrada) : [];
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Un índice roto (JSON que no parsea, o que no es una lista) no se puede persistir como
|
|
102
|
+
* base: usar aquí la lista vacía que devuelve `leerIndice` para un JSON roto BORRARÍA del
|
|
103
|
+
* disco todas las sesiones que el índice roto todavía nombraba — el `.jsonl` de cada
|
|
104
|
+
* sesión sigue intacto, pero sin su entrada es irrecuperable. Misma disciplina que
|
|
105
|
+
* `settingsEnDisco.ts#leerCrudoOAbortar`: la lectura que alimenta una escritura PARA sin
|
|
106
|
+
* escribir ante JSON roto, en vez de recuperar el fichero por su cuenta.
|
|
107
|
+
*/
|
|
108
|
+
export class IndiceDeSesionesRoto extends Error {
|
|
109
|
+
}
|
|
110
|
+
function leerIndiceOAbortar(raiz) {
|
|
111
|
+
const ruta = rutaIndice(raiz);
|
|
112
|
+
if (!existsSync(ruta))
|
|
113
|
+
return [];
|
|
114
|
+
let bruto;
|
|
115
|
+
try {
|
|
116
|
+
bruto = JSON.parse(readFileSync(ruta, "utf8"));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
throw new IndiceDeSesionesRoto(`«${ruta}»: el JSON es inválido; no se sobrescribe. Edita el fichero a mano.`);
|
|
120
|
+
}
|
|
121
|
+
if (!Array.isArray(bruto)) {
|
|
122
|
+
throw new IndiceDeSesionesRoto(`«${ruta}»: el JSON raíz debe ser una lista; no se sobrescribe.`);
|
|
123
|
+
}
|
|
124
|
+
return bruto.filter(esEntrada);
|
|
125
|
+
}
|
|
126
|
+
/** Temporal + `renameSync`, igual que `settingsEnDisco.ts#escribirAtomico`: un rename es
|
|
127
|
+
* atómico y un `writeFileSync` directo no lo es, así que un crash a mitad de escritura
|
|
128
|
+
* dejaría el índice de TODAS las sesiones truncado en vez de solo la última entrada.
|
|
129
|
+
*/
|
|
130
|
+
function escribirIndice(raiz, entradas) {
|
|
131
|
+
const carpeta = carpetaSesiones(raiz);
|
|
132
|
+
mkdirSync(carpeta, { recursive: true });
|
|
133
|
+
const ruta = rutaIndice(raiz);
|
|
134
|
+
const temporal = join(carpeta, `.indice.json.${randomUUID()}.tmp`);
|
|
135
|
+
let descriptor;
|
|
136
|
+
try {
|
|
137
|
+
descriptor = openSync(temporal, "w");
|
|
138
|
+
writeFileSync(descriptor, JSON.stringify(entradas, null, 2) + "\n", "utf8");
|
|
139
|
+
closeSync(descriptor);
|
|
140
|
+
descriptor = undefined;
|
|
141
|
+
renameSync(temporal, ruta);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (descriptor !== undefined) {
|
|
145
|
+
try {
|
|
146
|
+
closeSync(descriptor);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// Un fallo al cerrar durante la recuperación no puede impedir borrar el temporal.
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
unlinkSync(temporal);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// Si no llegó a crearse, no hay nada que limpiar.
|
|
157
|
+
}
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** Crea una sesión nueva y devuelve su id. El id es `randomUUID()`: no compone rutas por
|
|
162
|
+
* construcción, pero pasa igualmente por `rutaJsonl` (vía `segmentoSeguro`) en cuanto se
|
|
163
|
+
* anota o se reabre — la guarda no distingue de dónde vino el id.
|
|
164
|
+
*/
|
|
165
|
+
/**
|
|
166
|
+
* Da de alta una sesión en el índice.
|
|
167
|
+
*
|
|
168
|
+
* El id ENTRA por parámetro desde que es también el `thread_id` del grafo
|
|
169
|
+
* (`agent/checkpointer.ts`): quien abre la consola lo decide al abrir, porque el hilo tiene
|
|
170
|
+
* que existir antes del primer turno, y esto solo escribe la entrada. Sin id se genera uno,
|
|
171
|
+
* que es lo que hacía siempre y lo que sigue valiendo para quien no tenga hilo.
|
|
172
|
+
*/
|
|
173
|
+
export function crearSesion(raiz, id = randomUUID(), tarea) {
|
|
174
|
+
const ahora = new Date().toISOString();
|
|
175
|
+
const entradas = leerIndiceOAbortar(raiz);
|
|
176
|
+
// La marca se escribe SOLO aquí, que es el único sitio donde se da de alta la entrada por
|
|
177
|
+
// el camino normal (`vestibulo.ts#volcar`, una vez por sesión) y donde se sabe por qué
|
|
178
|
+
// puerta se abrió. Ponerla en `anotarActo` la haría viajar en cada acto para decidir
|
|
179
|
+
// «solo si falta» en todos.
|
|
180
|
+
entradas.push({ id, titulo: "", creada: ahora, ultimoTurno: ahora, ...(tarea === undefined ? {} : { tarea }) });
|
|
181
|
+
escribirIndice(raiz, entradas);
|
|
182
|
+
return id;
|
|
183
|
+
}
|
|
184
|
+
/** Anexa un acto al `.jsonl` de la sesión y refresca su entrada en el índice: fija el
|
|
185
|
+
* título en el PRIMER acto `usuario` (y no se vuelve a tocar) y actualiza `ultimoTurno`
|
|
186
|
+
* en cada llamada, sea cual sea el tipo de acto.
|
|
187
|
+
*
|
|
188
|
+
* El anexado va ANTES de tocar el índice a propósito: si el índice está roto y
|
|
189
|
+
* `leerIndiceOAbortar` lanza, el acto ya quedó escrito. Un turno completo no se pierde
|
|
190
|
+
* solo porque el índice —que es prescindible, se puede reconstruir barriendo los
|
|
191
|
+
* `.jsonl`— esté corrompido.
|
|
192
|
+
*/
|
|
193
|
+
export function anotarActo(raiz, id, acto) {
|
|
194
|
+
const ruta = rutaJsonl(raiz, id);
|
|
195
|
+
mkdirSync(carpetaSesiones(raiz), { recursive: true });
|
|
196
|
+
appendFileSync(ruta, JSON.stringify(acto) + "\n", "utf8");
|
|
197
|
+
const ahora = new Date().toISOString();
|
|
198
|
+
const entradas = leerIndiceOAbortar(raiz);
|
|
199
|
+
let entrada = entradas.find((e) => e.id === id);
|
|
200
|
+
if (entrada === undefined) {
|
|
201
|
+
// Anotar sin haber pasado por `crearSesion` (no debería pasar por el flujo normal,
|
|
202
|
+
// pero un índice perdido o corrupto no puede tumbar la escritura del acto, que ya
|
|
203
|
+
// ocurrió arriba): se da de alta la entrada con lo que se sabe en este momento.
|
|
204
|
+
entrada = {
|
|
205
|
+
id,
|
|
206
|
+
titulo: acto.tipo === "usuario" ? tituloDesde(acto.texto) : "",
|
|
207
|
+
creada: ahora,
|
|
208
|
+
ultimoTurno: ahora,
|
|
209
|
+
};
|
|
210
|
+
entradas.push(entrada);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
if (entrada.titulo === "" && acto.tipo === "usuario")
|
|
214
|
+
entrada.titulo = tituloDesde(acto.texto);
|
|
215
|
+
entrada.ultimoTurno = ahora;
|
|
216
|
+
}
|
|
217
|
+
anotarConsumoDeActo(raiz, id, entrada, acto);
|
|
218
|
+
escribirIndice(raiz, entradas);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Suma al acumulado de una entrada lo que aporta este acto. Monótono: solo suma, nunca resta,
|
|
222
|
+
* y un acto que no trae consumo —o un `fin` de una sesión anterior a que se midiera— deja la
|
|
223
|
+
* entrada como estaba. **Un cero no se estampa**: ausente es «no consta», y escribir ceros ahí
|
|
224
|
+
* convertiría «no sé lo que gastó» en «no gastó nada».
|
|
225
|
+
*
|
|
226
|
+
* La regla que importa es qué hacer cuando la entrada TODAVÍA no trae acumulado, y no es sumar
|
|
227
|
+
* el delta: eso dejaría en el índice el gasto del ÚLTIMO turno con la forma de un total de la
|
|
228
|
+
* sesión —una sesión de 11k que hace un turno de 3k quedaría en 3k, y nadie lo notaría porque
|
|
229
|
+
* el número es plausible—. Ahí se relee el `.jsonl` —que ya lleva este acto dentro, porque el
|
|
230
|
+
* anexado va primero— y se suma la sesión entera. Es como mucho UNA lectura por sesión: en
|
|
231
|
+
* cuanto el acumulado consta, esto pasa a ser una suma de dos objetos.
|
|
232
|
+
*
|
|
233
|
+
* Se apoya en `reabrirSesion` y no en un lector propio: es el ÚNICO que sabe leer un `.jsonl`
|
|
234
|
+
* —saltando la línea trunca en vez de tumbar la lectura—, y un segundo lector sería un segundo
|
|
235
|
+
* sitio donde esa tolerancia puede dejar de estar.
|
|
236
|
+
*/
|
|
237
|
+
function anotarConsumoDeActo(raiz, id, entrada, acto) {
|
|
238
|
+
if (acto.tipo !== "fin" || acto.consumo === undefined)
|
|
239
|
+
return;
|
|
240
|
+
const bruto = entrada.consumo === undefined
|
|
241
|
+
? consumoDeLosActos(reabrirSesion(raiz, id).actos)
|
|
242
|
+
: acumularTotales(entrada.consumo, acto.consumo);
|
|
243
|
+
// `consumoDeLosActos` contesta «no consta» si el `.jsonl` no tiene ningún `fin` con consumo
|
|
244
|
+
// —una sesión entera anterior a esto—, y entonces no hay nada que estampar.
|
|
245
|
+
//
|
|
246
|
+
// Y se NORMALIZA con `acumularTotales`, pase por donde pase, para que la ventana no entre:
|
|
247
|
+
// la que trae `consumoDeLosActos` es la del último turno que midió, y dentro de un acumulado
|
|
248
|
+
// sería un «ahora» congelado que alguien leería como el de hoy. El `.jsonl` la sigue
|
|
249
|
+
// teniendo, que es donde se mide.
|
|
250
|
+
if (bruto !== undefined)
|
|
251
|
+
entrada.consumo = acumularTotales(undefined, bruto);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* SIEMBRA la marca de tarea en una sesión que ya estaba en el índice. Devuelve si la tocó.
|
|
255
|
+
*
|
|
256
|
+
* Existe por las sesiones de tarea anteriores a `EntradaIndice.tarea`: sin esto, la primera
|
|
257
|
+
* que hubo en cada proyecto se queda para siempre pintada como una conversación. La corre el
|
|
258
|
+
* corredor al arrancar, recorriendo su propia cola — o sea leyendo la autoridad sobre de
|
|
259
|
+
* quién es cada sesión, la misma que escribió el dato.
|
|
260
|
+
*
|
|
261
|
+
* **Es MONOTÓNICA, y de ahí sale que sea segura**: solo añade. No pisa una marca puesta —la
|
|
262
|
+
* del disco es la que escribió quien abrió la sesión— y no quita ninguna, así que no hay
|
|
263
|
+
* forma de que convierta una sesión de tarea en una conversación, que es el único fallo
|
|
264
|
+
* abierto posible por aquí. Correrla dos veces no hace nada la segunda.
|
|
265
|
+
*
|
|
266
|
+
* Y **no da de alta la entrada que falte**: la cola vive en `~/.xonecode/tareas` y el índice
|
|
267
|
+
* en el proyecto, así que una tarea puede nombrar una sesión que alguien borró; crearla la
|
|
268
|
+
* resucitaría en la barra apuntando a un `.jsonl` que ya no está.
|
|
269
|
+
*/
|
|
270
|
+
export function marcarTareaDeSesion(raiz, id, tarea) {
|
|
271
|
+
const entradas = leerIndiceOAbortar(raiz);
|
|
272
|
+
const entrada = entradas.find((e) => e.id === id);
|
|
273
|
+
if (entrada === undefined || entrada.tarea !== undefined)
|
|
274
|
+
return false;
|
|
275
|
+
entrada.tarea = tarea;
|
|
276
|
+
escribirIndice(raiz, entradas);
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
/** Cuántas sesiones rellena UNA pasada de `sembrarConsumosPendientes`. */
|
|
280
|
+
export const SESIONES_A_SEMBRAR = 12;
|
|
281
|
+
/** Y por encima de este tamaño no se siembra: la siembra es SÍNCRONA y corre en el bucle de
|
|
282
|
+
* eventos, así que un `.jsonl` enorme congelaría el servidor mientras lo lee. */
|
|
283
|
+
export const TOPE_DE_BYTES_DE_SIEMBRA = 4 * 1024 * 1024;
|
|
284
|
+
/**
|
|
285
|
+
* Rellena el acumulado de las sesiones que ya existían antes de que se estampara. Devuelve
|
|
286
|
+
* cuántas tocó, que es lo que decide si merece la pena reanunciar el alta.
|
|
287
|
+
*
|
|
288
|
+
* Existe porque sin ella la función nace VACÍA en todas las sesiones anteriores: el índice solo
|
|
289
|
+
* aprende el gasto de una sesión cuando alguien la usa, y las que nadie vuelve a abrir se
|
|
290
|
+
* quedarían sin cifra para siempre. Esto es una siembra de PRESENTACIÓN, y no sostiene ninguna
|
|
291
|
+
* corrección: si no llega a una sesión —por el tope de número, por el de bytes o porque su
|
|
292
|
+
* `.jsonl` se fue— lo peor que pasa es que no enseñe cifra hasta su próximo turno, y entonces
|
|
293
|
+
* enseñará la BUENA (`anotarConsumoDeActo` relee cuando no hay acumulado del que partir).
|
|
294
|
+
*
|
|
295
|
+
* **Es MONOTÓNICA, como `marcarTareaDeSesion` y por el mismo motivo**: solo mira las entradas
|
|
296
|
+
* que NO traen acumulado, así que no puede pisar el de ninguna, y correrla dos veces no hace
|
|
297
|
+
* nada la segunda. Devuelve 0 la segunda vez.
|
|
298
|
+
*
|
|
299
|
+
* **Y no da de alta la entrada que falte**, tampoco como la otra: un `.jsonl` sin entrada en el
|
|
300
|
+
* índice es una sesión que alguien borró, y resucitarla la devolvería a la barra apuntando a un
|
|
301
|
+
* fichero que ya no está.
|
|
302
|
+
*
|
|
303
|
+
* Va de las MÁS RECIENTES hacia atrás porque el tope de número tiene que elegir, y lo que se
|
|
304
|
+
* mira en la barra es lo último que se hizo. **UNA sola escritura** al final y no una por
|
|
305
|
+
* entrada: el índice se reescribe entero cada vez.
|
|
306
|
+
*/
|
|
307
|
+
export function sembrarConsumosPendientes(raiz) {
|
|
308
|
+
const entradas = leerIndiceOAbortar(raiz);
|
|
309
|
+
const pendientes = entradas
|
|
310
|
+
.filter((e) => e.consumo === undefined)
|
|
311
|
+
// `String(...)` porque `esEntrada` solo comprueba el `id`: un índice tocado a mano puede
|
|
312
|
+
// traer aquí lo que sea, y esto no es sitio para reventar por un campo mal escrito.
|
|
313
|
+
.sort((a, b) => String(b.ultimoTurno).localeCompare(String(a.ultimoTurno)))
|
|
314
|
+
.slice(0, SESIONES_A_SEMBRAR);
|
|
315
|
+
let sembradas = 0;
|
|
316
|
+
for (const entrada of pendientes) {
|
|
317
|
+
const ruta = rutaJsonl(raiz, entrada.id);
|
|
318
|
+
try {
|
|
319
|
+
if (!existsSync(ruta) || statSync(ruta).size > TOPE_DE_BYTES_DE_SIEMBRA)
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
continue; // Un `.jsonl` que no se puede ni medir no se siembra; no es un error.
|
|
324
|
+
}
|
|
325
|
+
const total = consumoDeLosActos(reabrirSesion(raiz, entrada.id).actos);
|
|
326
|
+
if (total === undefined)
|
|
327
|
+
continue;
|
|
328
|
+
// Y se NORMALIZA con `acumularTotales` igual que el estampado, por la MISMA razón y con la
|
|
329
|
+
// misma función: `consumoDeLosActos` se queda con la ventana del último `fin` que la traiga
|
|
330
|
+
// —es su contrato, y hace falta en la piel—, así que sin esto la siembra escribía en el
|
|
331
|
+
// índice un «cuánto ocupa el historial ahora» de un turno de anteayer. Nadie lo pinta hoy
|
|
332
|
+
// (la ventana va en su propio mensaje), que es justo por lo que no se notó: una cifra muerta
|
|
333
|
+
// en disco es una cifra que alguien leerá mañana creyendo que es la de hoy.
|
|
334
|
+
entrada.consumo = acumularTotales(undefined, total);
|
|
335
|
+
sembradas++;
|
|
336
|
+
}
|
|
337
|
+
if (sembradas > 0)
|
|
338
|
+
escribirIndice(raiz, entradas);
|
|
339
|
+
return sembradas;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Borra una sesión: su `.jsonl` y su entrada del índice. Devuelve si había algo que borrar.
|
|
343
|
+
*
|
|
344
|
+
* El fichero va PRIMERO y el índice después, al revés que en `anotarActo` y por el mismo
|
|
345
|
+
* razonamiento invertido: aquí lo que no se puede quedar a medias es una entrada de índice
|
|
346
|
+
* apuntando a un fichero que ya no está —la sesión saldría en la barra y reventaría al
|
|
347
|
+
* abrirla—. Al revés, un `.jsonl` huérfano no lo ve nadie: la barra se pinta con el índice.
|
|
348
|
+
*
|
|
349
|
+
* Un id desconocido devuelve `false` en vez de lanzar: borrar dos veces la misma sesión —dos
|
|
350
|
+
* pestañas abiertas, un doble clic— no es un error, y lo único que hay que saber es si
|
|
351
|
+
* quedaba algo.
|
|
352
|
+
*/
|
|
353
|
+
export function borrarSesion(raiz, id) {
|
|
354
|
+
const ruta = rutaJsonl(raiz, id);
|
|
355
|
+
const habia = existsSync(ruta);
|
|
356
|
+
if (habia)
|
|
357
|
+
unlinkSync(ruta);
|
|
358
|
+
// Y sus artefactos, que son de esta sesión y de nadie más. Sin esto, borrar una
|
|
359
|
+
// conversación dejaría en disco los diagramas que se dibujaron en ella, invisibles desde
|
|
360
|
+
// la interfaz — el mismo agujero que dejaba su hilo del checkpointer antes de
|
|
361
|
+
// `olvidarHilo`. `force` porque la carpeta solo existe si el agente escribió algo.
|
|
362
|
+
rmSync(dirname(carpetaDeArtefactosDeSesion(raiz, id)), { recursive: true, force: true });
|
|
363
|
+
const entradas = leerIndiceOAbortar(raiz);
|
|
364
|
+
const quedan = entradas.filter((e) => e.id !== id);
|
|
365
|
+
if (quedan.length === entradas.length)
|
|
366
|
+
return habia;
|
|
367
|
+
escribirIndice(raiz, quedan);
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Le pone nombre a una sesión. Devuelve si existía.
|
|
372
|
+
*
|
|
373
|
+
* Un título vacío se RECHAZA, y no es una validación de formulario: `anotarActo` fija el
|
|
374
|
+
* título en el primer acto de usuario y solo mientras esté vacío (`entrada.titulo === ""`).
|
|
375
|
+
* Dejarlo vacío devolvería la sesión al régimen automático, así que el siguiente turno la
|
|
376
|
+
* rebautizaría con la primera frase y el nombre que puso una persona desaparecería sin más.
|
|
377
|
+
* Se acota a `LARGO_TITULO` como los automáticos: la barra tiene el ancho que tiene.
|
|
378
|
+
*/
|
|
379
|
+
export function renombrarSesion(raiz, id, titulo) {
|
|
380
|
+
const limpio = titulo.trim().slice(0, LARGO_TITULO);
|
|
381
|
+
if (limpio === "")
|
|
382
|
+
return false;
|
|
383
|
+
const entradas = leerIndiceOAbortar(raiz);
|
|
384
|
+
const entrada = entradas.find((e) => e.id === id);
|
|
385
|
+
if (entrada === undefined)
|
|
386
|
+
return false;
|
|
387
|
+
entrada.titulo = limpio;
|
|
388
|
+
escribirIndice(raiz, entradas);
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Fija —o quita, con `undefined`— el dispositivo preferido de una sesión.
|
|
393
|
+
*
|
|
394
|
+
* Devuelve si había una entrada que tocar: una sesión cuyo id todavía no existe en el índice
|
|
395
|
+
* (nace al volcar el primer acto) no se puede anotar aquí, y quien llama tiene que guardarlo
|
|
396
|
+
* en memoria hasta entonces — decirlo con un `false` es mejor que crear una entrada a medias
|
|
397
|
+
* que la barra enseñaría como una sesión vacía.
|
|
398
|
+
*/
|
|
399
|
+
export function elegirDispositivo(raiz, id, dispositivo) {
|
|
400
|
+
const entradas = leerIndiceOAbortar(raiz);
|
|
401
|
+
const entrada = entradas.find((e) => e.id === id);
|
|
402
|
+
if (entrada === undefined)
|
|
403
|
+
return false;
|
|
404
|
+
if (dispositivo === undefined)
|
|
405
|
+
delete entrada.dispositivo;
|
|
406
|
+
else
|
|
407
|
+
entrada.dispositivo = dispositivo;
|
|
408
|
+
escribirIndice(raiz, entradas);
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
/** El índice completo, tal cual lo enseña la lista de sesiones del proyecto. */
|
|
412
|
+
export function listarSesiones(raiz) {
|
|
413
|
+
return leerIndice(raiz);
|
|
414
|
+
}
|
|
415
|
+
/** Relee una sesión entera. Una línea que no parsea (fichero truncado a mitad de un
|
|
416
|
+
* `appendFileSync`, por ejemplo por un crash) se SALTA en vez de tumbar la reapertura: una
|
|
417
|
+
* sesión que no se puede reabrir porque una línea se truncó es peor que una que reabre con
|
|
418
|
+
* una línea de menos.
|
|
419
|
+
*/
|
|
420
|
+
export function reabrirSesion(raiz, id) {
|
|
421
|
+
const ruta = rutaJsonl(raiz, id);
|
|
422
|
+
const actos = [];
|
|
423
|
+
if (existsSync(ruta)) {
|
|
424
|
+
for (const linea of readFileSync(ruta, "utf8").split("\n")) {
|
|
425
|
+
if (linea.trim() === "")
|
|
426
|
+
continue;
|
|
427
|
+
try {
|
|
428
|
+
actos.push(JSON.parse(linea));
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
// Línea corrupta: se salta, no se tumba la reapertura (ver comentario de cabecera).
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// El dispositivo preferido sale del ÍNDICE y no del `.jsonl`: es un dato de la sesión, no
|
|
436
|
+
// uno de sus actos, y reabrir tiene que devolverlo o la elección se perdería al releer.
|
|
437
|
+
const dispositivo = leerIndice(raiz).find((e) => e.id === id)?.dispositivo;
|
|
438
|
+
return { id, actos, historica: true, ...(dispositivo === undefined ? {} : { dispositivo }) };
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=sesiones.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sesiones.js","sourceRoot":"","sources":["../../../src/web/servidor/sesiones.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EACL,cAAc,EACd,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,MAAM,EACN,QAAQ,EACR,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,iFAAiF;AACjF,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAE,CAAC;AAoEvB,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,IAAY,EAAE,EAAU;IACzC,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,GAAG,cAAc,CAAC,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;AACpF,CAAC;AAGD;;;GAGG;AACH,SAAS,SAAS,CAAC,CAAU;IAC3B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,OAAQ,CAAsB,CAAC,EAAE,KAAK,QAAQ,CAAC;AAC/F,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9D,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;CAAG;AAElD,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,oBAAoB,CAAC,IAAI,IAAI,qEAAqE,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,oBAAoB,CAAC,IAAI,IAAI,wDAAwD,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,QAAyB;IAC7D,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,gBAAgB,UAAU,EAAE,MAAM,CAAC,CAAC;IACnE,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACrC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5E,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,UAAU,GAAG,SAAS,CAAC;QACvB,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,SAAS,CAAC,UAAU,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,kFAAkF;YACpF,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAAa,UAAU,EAAE,EAAE,KAAc;IACjF,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC1C,0FAA0F;IAC1F,uFAAuF;IACvF,qFAAqF;IACrF,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAChH,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAU,EAAE,IAAU;IAC7D,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACjC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAE1D,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,mFAAmF;QACnF,kFAAkF;QAClF,gFAAgF;QAChF,OAAO,GAAG;YACR,EAAE;YACF,MAAM,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;YAC9D,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,KAAK;SACnB,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/F,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC;IAC9B,CAAC;IACD,mBAAmB,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,mBAAmB,CAAC,IAAY,EAAE,EAAU,EAAE,OAAsB,EAAE,IAAU;IACvF,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO;IAC9D,MAAM,KAAK,GACT,OAAO,CAAC,OAAO,KAAK,SAAS;QAC3B,CAAC,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC;QAClD,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACrD,4FAA4F;IAC5F,4EAA4E;IAC5E,EAAE;IACF,2FAA2F;IAC3F,6FAA6F;IAC7F,qFAAqF;IACrF,kCAAkC;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,OAAO,GAAG,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,EAAU,EAAE,KAAa;IACzE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACvE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACtB,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC;kFACkF;AAClF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,QAAQ;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC;QACvC,yFAAyF;QACzF,oFAAoF;SACnF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;SAC1E,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;IAEhC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC;YACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,wBAAwB;gBAAE,SAAS;QACpF,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,sEAAsE;QAClF,CAAC;QACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACvE,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,2FAA2F;QAC3F,4FAA4F;QAC5F,wFAAwF;QACxF,0FAA0F;QAC1F,6FAA6F;QAC7F,4EAA4E;QAC5E,OAAO,CAAC,OAAO,GAAG,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACpD,SAAS,EAAE,CAAC;IACd,CAAC;IACD,IAAI,SAAS,GAAG,CAAC;QAAE,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,EAAU;IACnD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,KAAK;QAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IAC5B,gFAAgF;IAChF,yFAAyF;IACzF,8EAA8E;IAC9E,mFAAmF;IACnF,MAAM,CAAC,OAAO,CAAC,2BAA2B,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACpD,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,EAAU,EAAE,MAAc;IACtE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IACpD,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IACxB,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,EAAU,EAAE,WAA2C;IACrG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,WAAW,CAAC;;QACrD,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;IACvC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,EAAU;IACpD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,SAAS;YAClC,IAAI,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAS,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,oFAAoF;YACtF,CAAC;QACH,CAAC;IACH,CAAC;IACD,0FAA0F;IAC1F,wFAAwF;IACxF,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,CAAC;IAC3E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;AAC/F,CAAC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Las seis fases de un lanzamiento, EN ORDEN, y los cinco estados en que puede estar.
|
|
3
|
+
*
|
|
4
|
+
* **Se declaran aquí, en el cable, y no se importan de `agent/lanzamientoEnMaquina.ts`**, que es
|
|
5
|
+
* quien las recorre. El motivo es el de siempre en este fichero: el cable tiene su vocabulario
|
|
6
|
+
* CERRADO, y quien lo cierra es esta constante — la lista blanca del store del cliente y la
|
|
7
|
+
* validación del servidor se escriben contra ESTA lista, así que un valor que no esté aquí no
|
|
8
|
+
* llega a la pantalla. Importarlas ataría el contrato del cable al módulo que hoy lo cumple, y
|
|
9
|
+
* el día que ese módulo añada una fase el cable la aceptaría sin que nadie hubiera decidido si
|
|
10
|
+
* el cliente sabe pintarla.
|
|
11
|
+
*
|
|
12
|
+
* **Y por eso mismo hay un test que las ata** (`arranque.test.ts`: «las fases del cable son las
|
|
13
|
+
* que corre la máquina»): la lista de aquí no puede quedarse corta respecto de la de allí, o el
|
|
14
|
+
* recorrido se quedaría sin emitir justo la fase que alguien acaba de añadir.
|
|
15
|
+
*
|
|
16
|
+
* **`corriendo` no está en `EstadoDeLanzamiento` de la máquina, y aquí sí.** Allí el estado es un
|
|
17
|
+
* DESENLACE —cuatro formas de acabar—, porque `lanzarEnDispositivo` devuelve un resultado; aquí
|
|
18
|
+
* hay además un RECORRIDO EN VIVO, que es lo que permite que la pestaña enseñe en qué fase va
|
|
19
|
+
* en vez de un botón apagado sin explicación.
|
|
20
|
+
*/
|
|
21
|
+
export const FASES_DEL_LANZAMIENTO = [
|
|
22
|
+
"comprobando",
|
|
23
|
+
"empaquetando",
|
|
24
|
+
"subiendo",
|
|
25
|
+
"reiniciando",
|
|
26
|
+
"lanzando",
|
|
27
|
+
"comprobando-arranque",
|
|
28
|
+
];
|
|
29
|
+
export const ESTADOS_DEL_LANZAMIENTO = ["corriendo", "ok", "fallo", "cancelada", "colgada"];
|
|
30
|
+
/**
|
|
31
|
+
* Una `Tarea` del índice traducida a lo que viaja. **La raíz del proyecto se queda aquí.**
|
|
32
|
+
*
|
|
33
|
+
* **Vive en este fichero, exportada, y eso es el arreglo de F1.** Era una copia de campos a
|
|
34
|
+
* mano enterrada en el cierre de `montarRutas` (`arranque.ts`), a mil líneas del tipo que
|
|
35
|
+
* traduce y dentro de algo que todos sus tests doblan — o sea el patrón de fallo que
|
|
36
|
+
* `CLAUDE.md` documenta cinco veces en esta misma tanda: «si una regla de producción se
|
|
37
|
+
* compone dentro de algo que los tests simulan, esa regla no está probada: está escrita».
|
|
38
|
+
* `veredicto` se cayó aquí y en el store del cliente sin que nada se pusiera rojo. Ahora
|
|
39
|
+
* `transporte.test.ts` recorre los campos de `Tarea` y exige decisión explícita por cada
|
|
40
|
+
* uno.
|
|
41
|
+
*
|
|
42
|
+
* Campo a campo, y también DENTRO del veredicto: un `...tarea.veredicto` dejaría pasar sin
|
|
43
|
+
* nombrar el campo que alguien le añada mañana a `VeredictoDeTarea`.
|
|
44
|
+
*/
|
|
45
|
+
export function filaDeTarea(t) {
|
|
46
|
+
return {
|
|
47
|
+
id: t.id,
|
|
48
|
+
// El ID, que es con lo que la interfaz filtra; el nombre va aparte, para leer. La RAÍZ
|
|
49
|
+
// no viaja: es una ruta de la máquina.
|
|
50
|
+
proyecto: t.proyecto.id,
|
|
51
|
+
proyectoNombre: t.proyecto.nombre,
|
|
52
|
+
titulo: t.titulo,
|
|
53
|
+
peticion: t.peticion,
|
|
54
|
+
encargo: t.encargo,
|
|
55
|
+
adjuntos: t.adjuntos,
|
|
56
|
+
estado: t.estado,
|
|
57
|
+
creada: t.creada,
|
|
58
|
+
...(t.motivo === undefined ? {} : { motivo: t.motivo }),
|
|
59
|
+
...(t.sesion === undefined ? {} : { sesion: t.sesion }),
|
|
60
|
+
...(t.empezada === undefined ? {} : { empezada: t.empezada }),
|
|
61
|
+
...(t.acabada === undefined ? {} : { acabada: t.acabada }),
|
|
62
|
+
...(t.autorizadas === undefined ? {} : { autorizadas: t.autorizadas }),
|
|
63
|
+
...(t.feedback === undefined ? {} : { feedback: t.feedback }),
|
|
64
|
+
...(t.veredicto === undefined
|
|
65
|
+
? {}
|
|
66
|
+
: {
|
|
67
|
+
veredicto: {
|
|
68
|
+
veredicto: t.veredicto.veredicto,
|
|
69
|
+
resumen: t.veredicto.resumen,
|
|
70
|
+
...(t.veredicto.hallazgos === undefined ? {} : { hallazgos: t.veredicto.hallazgos }),
|
|
71
|
+
...(t.veredicto.salvedad === undefined ? {} : { salvedad: t.veredicto.salvedad }),
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
...(t.terminadaAMano === undefined ? {} : { terminadaAMano: t.terminadaAMano }),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Las clases de mensaje que SON el transcript, y las únicas que llegan a un mirón.
|
|
79
|
+
*
|
|
80
|
+
* Lista blanca y no negra: con una negra, la clase que alguien añada mañana al cable
|
|
81
|
+
* llegaría permitida a quien mira una tarea de fondo — y por ahí ya pasan hoy el
|
|
82
|
+
* mensaje `turno` que apagaría su compositor y el `aprobacion` que es el único mensaje con
|
|
83
|
+
* contenido de fichero dentro.
|
|
84
|
+
*
|
|
85
|
+
* **`lanzable` y `lanzamiento` NO entran aquí, y es una decisión, no un olvido.** El recorrido
|
|
86
|
+
* de un lanzamiento es un suceso de la MÁQUINA y del proyecto, no un renglón de la
|
|
87
|
+
* conversación: quien mira una tarea de fondo no tiene por qué ver las fases del lanzamiento de
|
|
88
|
+
* otra consola, y meterlo en esta lista sería exactamente lo que la lista blanca existe para
|
|
89
|
+
* impedir — colar por la puerta de atrás un mensaje que nadie decidió que fuera transcript. Se
|
|
90
|
+
* quedan fuera por la misma razón por la que se quedan fuera `instalacion`, `dispositivos` y
|
|
91
|
+
* `tareas`, que tampoco son la conversación.
|
|
92
|
+
*/
|
|
93
|
+
const ES_DE_TRANSCRIPT = new Set(["acto", "sustitucion", "reemision"]);
|
|
94
|
+
export function crearTransporte(actos) {
|
|
95
|
+
const traza = [];
|
|
96
|
+
const escuchasDeCorte = [];
|
|
97
|
+
/** Todos los clientes vivos. `Set` y no lista: conectar dos veces el MISMO sumidero
|
|
98
|
+
* —una reconexión que se solapa con su propio cierre— no puede duplicar sus mensajes. */
|
|
99
|
+
const sumideros = new Set();
|
|
100
|
+
/**
|
|
101
|
+
* Quien MIRA sin ser cliente. Ver `Transporte.mirar`: aparte del otro conjunto porque no
|
|
102
|
+
* cuenta como humano y porque no recibe todo lo que se emite.
|
|
103
|
+
*/
|
|
104
|
+
const mirones = new Set();
|
|
105
|
+
/**
|
|
106
|
+
* Hubo cliente alguna vez y todavía no se ha ido el último. Se lleva aparte del `Set`
|
|
107
|
+
* porque `conectar()` sin sumidero (los tests que no miran lo emitido) también cuenta
|
|
108
|
+
* como cliente: `eof()` mira esto, y decir que no hay nadie rechazaría sus aprobaciones.
|
|
109
|
+
*/
|
|
110
|
+
let hayCliente = false;
|
|
111
|
+
return {
|
|
112
|
+
conectar(enviar) {
|
|
113
|
+
hayCliente = true;
|
|
114
|
+
if (enviar !== undefined)
|
|
115
|
+
sumideros.add(enviar);
|
|
116
|
+
return [...actos()];
|
|
117
|
+
},
|
|
118
|
+
desconectar(enviar) {
|
|
119
|
+
if (enviar !== undefined) {
|
|
120
|
+
sumideros.delete(enviar);
|
|
121
|
+
// Queda alguien mirando: no se despierta a nadie ni se corta nada. Lo que se fue
|
|
122
|
+
// es una pestaña, no la conversación.
|
|
123
|
+
if (sumideros.size > 0)
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
sumideros.clear();
|
|
128
|
+
// Sin sumidero es «se van todos»: lo hace `cerrar()` y lo hace mudarse de consola.
|
|
129
|
+
// Un mirón de una consola que se abandona escribe en un socket que ya no está.
|
|
130
|
+
mirones.clear();
|
|
131
|
+
}
|
|
132
|
+
hayCliente = false;
|
|
133
|
+
for (const escucha of escuchasDeCorte)
|
|
134
|
+
escucha();
|
|
135
|
+
},
|
|
136
|
+
soltar(enviar) {
|
|
137
|
+
if (enviar === undefined)
|
|
138
|
+
sumideros.clear();
|
|
139
|
+
else
|
|
140
|
+
sumideros.delete(enviar);
|
|
141
|
+
},
|
|
142
|
+
conectado: () => hayCliente,
|
|
143
|
+
mirar(enviar) {
|
|
144
|
+
mirones.add(enviar);
|
|
145
|
+
return [...actos()];
|
|
146
|
+
},
|
|
147
|
+
dejarDeMirar(enviar) {
|
|
148
|
+
mirones.delete(enviar);
|
|
149
|
+
},
|
|
150
|
+
emitir(mensaje) {
|
|
151
|
+
if (mensaje.clase !== "aprobacion")
|
|
152
|
+
traza.push(mensaje);
|
|
153
|
+
// A TODOS los clientes vivos. Con una sola ranura, el último en conectar dejaba mudos
|
|
154
|
+
// a los anteriores sin decírselo.
|
|
155
|
+
for (const sumidero of sumideros)
|
|
156
|
+
sumidero(mensaje);
|
|
157
|
+
// Y a los mirones, solo el TRANSCRIPT. Ver `Transporte.mirar`.
|
|
158
|
+
if (!ES_DE_TRANSCRIPT.has(mensaje.clase))
|
|
159
|
+
return;
|
|
160
|
+
for (const miron of mirones)
|
|
161
|
+
miron(mensaje);
|
|
162
|
+
},
|
|
163
|
+
emitidos: () => traza,
|
|
164
|
+
alDesconectar(escucha) {
|
|
165
|
+
escuchasDeCorte.push(escucha);
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=transporte.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transporte.js","sourceRoot":"","sources":["../../../src/web/servidor/transporte.ts"],"names":[],"mappings":"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"}
|