xonecode 0.38.41 → 0.39.2
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/{EditorDeFichero-B5qtmfKO.js → EditorDeFichero-BeWDctgN.js} +1 -1
- package/apps/web/dist/assets/{index-C6XoIOQg.js → index-B-6cDRAV.js} +20 -20
- package/apps/web/dist/assets/{php-I6JfbNBQ.js → php-D3QdOnb8.js} +1 -1
- package/apps/web/dist/assets/{ruby-DlqXDLOX.js → ruby-DDAcW-Z2.js} +1 -1
- package/apps/web/dist/index.html +1 -1
- package/dist/agent/cloudstudio/cloudstudioClient.d.ts +29 -0
- package/dist/agent/cloudstudio/cloudstudioMcp.d.ts +414 -0
- package/dist/agent/cloudstudio/conexionDeServidor.d.ts +37 -0
- package/dist/agent/cloudstudio/conexionDeServidor.js +63 -0
- package/dist/agent/cloudstudio/conexionDeServidor.js.map +1 -0
- package/dist/agent/cloudstudio/crearRama.d.ts +15 -0
- package/dist/agent/cloudstudio/crearRama.js +16 -0
- package/dist/agent/cloudstudio/crearRama.js.map +1 -0
- package/dist/agent/cloudstudio/descarga.d.ts +44 -0
- package/dist/agent/cloudstudio/manifiesto.d.ts +25 -0
- package/dist/agent/cloudstudio/ramaActiva.d.ts +24 -0
- package/dist/agent/cloudstudio/subida.d.ts +61 -0
- package/dist/agent/cloudstudio/subida.js +7 -1
- package/dist/agent/cloudstudio/subida.js.map +1 -1
- package/dist/agent/cloudstudio/validarTrasDescarga.d.ts +13 -0
- package/dist/agent/cloudstudio/zip.d.ts +13 -0
- package/dist/agent/conectores/conectoresEnDisco.d.ts +47 -0
- package/dist/agent/conectores/gestorJira.d.ts +50 -0
- package/dist/agent/conectores/gestorNotion.d.ts +45 -0
- package/dist/agent/conectores/proveedorDeConector.d.ts +43 -0
- package/dist/agent/conectores/servicioDeConectores.d.ts +112 -0
- package/dist/agent/config/authEnDisco.d.ts +43 -0
- package/dist/agent/config/catalogoModelos.d.ts +79 -0
- package/dist/agent/config/configEnDisco.d.ts +235 -0
- package/dist/agent/config/crearProyecto.d.ts +20 -0
- package/dist/agent/config/diagnosticoDeNodeEnMaquina.d.ts +44 -0
- package/dist/agent/config/ecoDeRazonamiento.d.ts +104 -0
- package/dist/agent/config/entorno.d.ts +83 -0
- package/dist/agent/config/fuentesEnRed.d.ts +12 -0
- package/dist/agent/config/gemini.d.ts +5 -0
- package/dist/agent/config/iconosEnRed.d.ts +10 -0
- package/dist/agent/config/identidadEnDisco.d.ts +27 -0
- package/dist/agent/config/modelos.d.ts +77 -0
- package/dist/agent/config/modelosDeMotor.d.ts +52 -0
- package/dist/agent/config/mudanzaEnDisco.d.ts +99 -0
- package/dist/agent/config/persona.d.ts +1 -0
- package/dist/agent/config/selectorEnMaquina.d.ts +35 -0
- package/dist/agent/config/settingsEnDisco.d.ts +206 -0
- package/dist/agent/config/versionEnDisco.d.ts +17 -0
- package/dist/agent/dispositivos/arranqueDeEmulador.d.ts +60 -0
- package/dist/agent/dispositivos/cajasDeMaqueta.d.ts +61 -0
- package/dist/agent/dispositivos/decodificarImagen.d.ts +21 -0
- package/dist/agent/dispositivos/descargaDeHerramientas.d.ts +44 -0
- package/dist/agent/dispositivos/dispositivosEnMaquina.d.ts +161 -0
- package/dist/agent/dispositivos/geometriaEnDisco.d.ts +17 -0
- package/dist/agent/dispositivos/hotswap.d.ts +194 -0
- package/dist/agent/dispositivos/instalacionEnMaquina.d.ts +156 -0
- package/dist/agent/dispositivos/juezVisual.d.ts +144 -0
- package/dist/agent/dispositivos/lanzamientoEnMaquina.d.ts +197 -0
- package/dist/agent/dispositivos/paqueteDelProyecto.d.ts +28 -0
- package/dist/agent/dispositivos/procesosEnMaquina.d.ts +154 -0
- package/dist/agent/dispositivos/recargaEnAparato.d.ts +30 -0
- package/dist/agent/dispositivos/sensorDeArranque.d.ts +42 -0
- package/dist/agent/exportarPdf.d.ts +72 -0
- package/dist/agent/grafo/aprendido.d.ts +28 -0
- package/dist/agent/grafo/arbolDeProyecto.d.ts +205 -0
- package/dist/agent/grafo/artefactosEnDisco.d.ts +35 -0
- package/dist/agent/grafo/atributosXone.d.ts +31 -0
- package/dist/agent/grafo/buscarIcono.d.ts +32 -0
- package/dist/agent/grafo/busquedaRegex.d.ts +56 -0
- package/dist/agent/grafo/codificacionDelProyecto.d.ts +7 -0
- package/dist/agent/grafo/compararCapturas.d.ts +22 -0
- package/dist/agent/grafo/copiarArtefacto.d.ts +64 -0
- package/dist/agent/grafo/criticaVisual.d.ts +60 -0
- package/dist/agent/grafo/describirImagen.d.ts +79 -0
- package/dist/agent/grafo/diferenciaDeCapturas.d.ts +33 -0
- package/dist/agent/grafo/ejecucionCancelable.d.ts +45 -0
- package/dist/agent/grafo/escriturasEnSerie.d.ts +31 -0
- package/dist/agent/grafo/excluirTools.d.ts +37 -0
- package/dist/agent/grafo/fuentesDeGoogle.d.ts +37 -0
- package/dist/agent/grafo/generarFondoSvg.d.ts +52 -0
- package/dist/agent/grafo/incorporarAdjunto.d.ts +98 -0
- package/dist/agent/grafo/lectorDeReferencias.d.ts +28 -0
- package/dist/agent/grafo/marcarCriteriosDelPlan.d.ts +47 -0
- package/dist/agent/grafo/memoriaDeProyecto.d.ts +15 -0
- package/dist/agent/grafo/navegacionXone.d.ts +60 -0
- package/dist/agent/grafo/opcionesDeFicheros.d.ts +23 -0
- package/dist/agent/grafo/perfiles.d.ts +225 -0
- package/dist/agent/grafo/proyecto.d.ts +450 -0
- package/dist/agent/grafo/skills.d.ts +181 -0
- package/dist/agent/grafo/traerDeLaMaquina.d.ts +60 -0
- package/dist/agent/grafo/unirSecciones.d.ts +20 -0
- package/dist/agent/grafo/validacionXone.d.ts +35 -0
- package/dist/agent/grafo/validarFicheroXone.d.ts +33 -0
- package/dist/agent/grafo/xoneAgent.d.ts +166 -0
- package/dist/agent/motores/motoresLocales.d.ts +87 -0
- package/dist/agent/motores/trueforge/capacidades.d.ts +183 -0
- package/dist/agent/motores/trueforge/convertirAP.d.ts +38 -0
- package/dist/agent/motores/trueforge/detencion.d.ts +70 -0
- package/dist/agent/motores/trueforge/esperas.d.ts +38 -0
- package/dist/agent/motores/trueforge/eventosTrueforge.d.ts +56 -0
- package/dist/agent/motores/trueforge/informesDeHijos.d.ts +48 -0
- package/dist/agent/motores/trueforge/medidaAutomatica.d.ts +37 -0
- package/dist/agent/motores/trueforge/medidaAutomatica.js +4 -2
- package/dist/agent/motores/trueforge/medidaAutomatica.js.map +1 -1
- package/dist/agent/motores/trueforge/memoriaDeEspecialistas.d.ts +60 -0
- package/dist/agent/motores/trueforge/memoriaTrueforge.d.ts +131 -0
- package/dist/agent/motores/trueforge/metricasTrueforge.d.ts +45 -0
- package/dist/agent/motores/trueforge/modeloExterno.d.ts +9 -0
- package/dist/agent/motores/trueforge/modeloLangchain.d.ts +69 -0
- package/dist/agent/motores/trueforge/notas.d.ts +48 -0
- package/dist/agent/motores/trueforge/proponerTareas.d.ts +30 -0
- package/dist/agent/motores/trueforge/recortes.d.ts +47 -0
- package/dist/agent/motores/trueforge/resumenSeguro.d.ts +33 -0
- package/dist/agent/motores/trueforge/sesionTrueforge.d.ts +273 -0
- package/dist/agent/motores/trueforge/sesionTrueforge.js +32 -15
- package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
- package/dist/agent/motores/trueforge/skillsTrueforge.d.ts +16 -0
- package/dist/agent/motores/trueforge/toolsDeConectores.d.ts +36 -0
- package/dist/agent/motores/trueforge/toolsDeFichero.d.ts +146 -0
- package/dist/agent/motores/trueforge/toolsPropias.d.ts +38 -0
- package/dist/agent/motores/trueforge/traerDeStitch.d.ts +63 -0
- package/dist/agent/motores/trueforge/trueforge.d.ts +35 -0
- package/dist/agent/navegacion/estilosEnDisco.d.ts +41 -0
- package/dist/agent/navegacion/hechosEnDisco.d.ts +19 -0
- package/dist/agent/navegacion/indiceEnDisco.d.ts +50 -0
- package/dist/agent/navegacion/modeloDeProyecto.d.ts +86 -0
- package/dist/agent/planesEnDisco.d.ts +18 -0
- package/dist/agent/publicarPlan.d.ts +20 -0
- package/dist/agent/raizDelPaquete.d.ts +9 -0
- package/dist/agent/remoto/ngrokEnMaquina.d.ts +44 -0
- package/dist/agent/remoto/puenteWebSocket.d.ts +59 -0
- package/dist/agent/remoto/tunelNgrok.d.ts +31 -0
- package/dist/agent/renombrarSobre.d.ts +14 -0
- package/dist/agent/sesiones/adjuntosDeSesion.d.ts +64 -0
- package/dist/agent/sesiones/baseDeFichero.d.ts +9 -0
- package/dist/agent/sesiones/checkpointer.d.ts +146 -0
- package/dist/agent/sesiones/git.d.ts +66 -0
- package/dist/agent/sesiones/gitSync.d.ts +264 -0
- package/dist/agent/sesiones/memoriaDeHilo.d.ts +4 -0
- package/dist/agent/sesiones/modeloDelCambio.d.ts +7 -0
- package/dist/agent/sesiones/parcheEnTexto.d.ts +9 -0
- package/dist/agent/sesiones/sesionGit.d.ts +155 -0
- package/dist/agent/subagentes/actividadDeCodex.d.ts +8 -0
- package/dist/agent/subagentes/agentesEnDisco.d.ts +198 -0
- package/dist/agent/subagentes/consumoExterno.d.ts +83 -0
- package/dist/agent/subagentes/ejecutableEnWindows.d.ts +53 -0
- package/dist/agent/subagentes/escrituraDeCodex.d.ts +94 -0
- package/dist/agent/subagentes/escrituraDeOpencode.d.ts +67 -0
- package/dist/agent/subagentes/escrituraExterna.d.ts +419 -0
- package/dist/agent/subagentes/pluginDeSkills.d.ts +84 -0
- package/dist/agent/subagentes/subagenteCodex.d.ts +76 -0
- package/dist/agent/subagentes/subagenteExterno.d.ts +169 -0
- package/dist/agent/subagentes/subagenteOpencode.d.ts +126 -0
- package/dist/agent/tareas/aumentador.d.ts +99 -0
- package/dist/agent/tareas/juezDeTarea.d.ts +64 -0
- package/dist/agent/tareas/reflejoEnElGestor.d.ts +38 -0
- package/dist/agent/tareas/sondeoDelGestor.d.ts +49 -0
- package/dist/agent/tareas/tareasEnDisco.d.ts +141 -0
- package/dist/agent/trazaDeErroresEnDisco.d.ts +10 -0
- package/dist/agent/turno/depuracion.d.ts +1 -0
- package/dist/agent/turno/diagnosticoDeTools.d.ts +124 -0
- package/dist/agent/turno/ficherosDelProyecto.d.ts +10 -0
- package/dist/agent/turno/guionizado.d.ts +18 -0
- package/dist/agent/turno/informeDeTraza.d.ts +220 -0
- package/dist/agent/turno/inspectorDePrompt.d.ts +150 -0
- package/dist/agent/turno/instantanea.d.ts +16 -0
- package/dist/agent/turno/interrupts.d.ts +54 -0
- package/dist/agent/turno/juezDelTurnoConModelo.d.ts +26 -0
- package/dist/agent/turno/mensajes.d.ts +23 -0
- package/dist/agent/turno/normalizar.d.ts +15 -0
- package/dist/agent/turno/puente.d.ts +196 -0
- package/dist/agent/turno/registroDeFallos.d.ts +39 -0
- package/dist/agent/turno/resumenDeContexto.d.ts +269 -0
- package/dist/agent/turno/resumenDeTool.d.ts +33 -0
- package/dist/agent/turno/rubrica.d.ts +35 -0
- package/dist/agent/turno/sesionReal.d.ts +89 -0
- package/dist/agent/turno/textoDeTool.d.ts +19 -0
- package/dist/agent/turno/turnoReal.d.ts +210 -0
- package/dist/agent/turno/verificacion.d.ts +85 -0
- package/dist/agent/turno/verificador.d.ts +66 -0
- package/dist/bin.d.ts +2 -0
- package/dist/cli/acuseDeModelo.d.ts +18 -0
- package/dist/cli/aprobar.d.ts +162 -0
- package/dist/cli/config.d.ts +17 -0
- package/dist/cli/consola.d.ts +473 -0
- package/dist/cli/describe.d.ts +7 -0
- package/dist/cli/doctor.d.ts +8 -0
- package/dist/cli/fuentesDeDisco.d.ts +25 -0
- package/dist/cli/main.d.ts +291 -0
- package/dist/cli/markdown.d.ts +126 -0
- package/dist/cli/panel.d.ts +38 -0
- package/dist/cli/podar.d.ts +38 -0
- package/dist/cli/run.d.ts +30 -0
- package/dist/cli/spinner.d.ts +37 -0
- package/dist/cli/stdio.d.ts +94 -0
- package/dist/cli/tema.d.ts +68 -0
- package/dist/cli/tokens.d.ts +16 -0
- package/dist/cli/traza.d.ts +19 -0
- package/dist/cli/tui/app.d.ts +23 -0
- package/dist/cli/tui/aprobarTui.d.ts +46 -0
- package/dist/cli/tui/barra.d.ts +43 -0
- package/dist/cli/tui/correrTui.d.ts +119 -0
- package/dist/cli/tui/entrada.d.ts +14 -0
- package/dist/cli/tui/filas.d.ts +13 -0
- package/dist/cli/tui/logo.d.ts +20 -0
- package/dist/cli/tui/pielTui.d.ts +15 -0
- package/dist/cli/tui/raton.d.ts +68 -0
- package/dist/cli/tui/sidebar.d.ts +63 -0
- package/dist/cli/tui/store.d.ts +102 -0
- package/dist/cli/tui/tarjeta.d.ts +8 -0
- package/dist/cli/tui/temaInk.d.ts +67 -0
- package/dist/cli/tui/transcript.d.ts +32 -0
- package/dist/cli/verify.d.ts +9 -0
- package/dist/cli/wizardInicial.d.ts +59 -0
- package/dist/core/actos.d.ts +437 -0
- package/dist/core/adjuntos.d.ts +77 -0
- package/dist/core/agentes.d.ts +353 -0
- package/dist/core/analisisDeSesion.d.ts +63 -0
- package/dist/core/aprendido.d.ts +41 -0
- package/dist/core/artefactos.d.ts +74 -0
- package/dist/core/atributosXone.d.ts +53 -0
- package/dist/core/bitacora.d.ts +21 -0
- package/dist/core/cloudstudio.d.ts +168 -0
- package/dist/core/codificacion.d.ts +81 -0
- package/dist/core/comandoExterno.d.ts +49 -0
- package/dist/core/compararCapturas.d.ts +136 -0
- package/dist/core/conectores.d.ts +296 -0
- package/dist/core/config.d.ts +148 -0
- package/dist/core/contextos.d.ts +54 -0
- package/dist/core/convertirAP.d.ts +56 -0
- package/dist/core/copiaDeAvd.d.ts +44 -0
- package/dist/core/cssBienFormado.d.ts +22 -0
- package/dist/core/deps.d.ts +28 -0
- package/dist/core/descargas.d.ts +61 -0
- package/dist/core/descripcionDePantalla.d.ts +121 -0
- package/dist/core/descriptoresDeApp.d.ts +108 -0
- package/dist/core/diagnosticoDeNode.d.ts +51 -0
- package/dist/core/diff.d.ts +26 -0
- package/dist/core/diffDeColecciones.d.ts +54 -0
- package/dist/core/disenoVinculado.d.ts +17 -0
- package/dist/core/dispositivoDeSesion.d.ts +22 -0
- package/dist/core/dispositivoElegido.d.ts +17 -0
- package/dist/core/dispositivos.d.ts +469 -0
- package/dist/core/entrega.d.ts +341 -0
- package/dist/core/entrelazar.d.ts +48 -0
- package/dist/core/esfuerzo.d.ts +120 -0
- package/dist/core/esqueleto.d.ts +38 -0
- package/dist/core/estiloMedido.d.ts +70 -0
- package/dist/core/estilos.d.ts +76 -0
- package/dist/core/events.d.ts +218 -0
- package/dist/core/exportacion.d.ts +88 -0
- package/dist/core/fallos.d.ts +79 -0
- package/dist/core/fondosSvg.d.ts +115 -0
- package/dist/core/fotoDeColecciones.d.ts +45 -0
- package/dist/core/fuentes.d.ts +96 -0
- package/dist/core/geometriaDePantalla.d.ts +171 -0
- package/dist/core/gestorDeTareas.d.ts +295 -0
- package/dist/core/hechosDelProyecto.d.ts +70 -0
- package/dist/core/hotswap.d.ts +30 -0
- package/dist/core/iconos.d.ts +86 -0
- package/dist/core/identidadDeProveedor.d.ts +20 -0
- package/dist/core/idiomaDeLaRespuesta.d.ts +26 -0
- package/dist/core/imagenesDeDocumento.d.ts +40 -0
- package/dist/core/jsParaRhino.d.ts +3 -0
- package/dist/core/juezDelTurno.d.ts +95 -0
- package/dist/core/logDeDispositivo.d.ts +67 -0
- package/dist/core/memoria.d.ts +18 -0
- package/dist/core/metodoDeComparacionVisual.d.ts +20 -0
- package/dist/core/modelos.d.ts +198 -0
- package/dist/core/modoDeEscritura.d.ts +155 -0
- package/dist/core/motor.d.ts +43 -0
- package/dist/core/motoresLocales.d.ts +113 -0
- package/dist/core/mudanzaDeWorkspace.d.ts +112 -0
- package/dist/core/navegacion.d.ts +172 -0
- package/dist/core/notify.d.ts +77 -0
- package/dist/core/nucleoXone.d.ts +28 -0
- package/dist/core/panorama.d.ts +68 -0
- package/dist/core/paqueteDeSoporte.d.ts +100 -0
- package/dist/core/planDeSubida.d.ts +56 -0
- package/dist/core/planes.d.ts +53 -0
- package/dist/core/podaDeCheckpoint.d.ts +75 -0
- package/dist/core/ports.d.ts +1034 -0
- package/dist/core/puedeLanzarse.d.ts +181 -0
- package/dist/core/puertosDeAvd.d.ts +59 -0
- package/dist/core/recargaEnCaliente.d.ts +52 -0
- package/dist/core/referenciasDeImagen.d.ts +36 -0
- package/dist/core/remoto.d.ts +76 -0
- package/dist/core/repartoDeEncargo.d.ts +80 -0
- package/dist/core/rubrica.d.ts +78 -0
- package/dist/core/rutaVirtual.d.ts +29 -0
- package/dist/core/selectorDeCarpeta.d.ts +59 -0
- package/dist/core/serieDeEscrituras.d.ts +58 -0
- package/dist/core/settings.d.ts +421 -0
- package/dist/core/shellDeAgente.d.ts +177 -0
- package/dist/core/skills.d.ts +129 -0
- package/dist/core/stitch.d.ts +114 -0
- package/dist/core/tareas.d.ts +412 -0
- package/dist/core/tareasDelPlan.d.ts +123 -0
- package/dist/core/tareasEnElGestor.d.ts +117 -0
- package/dist/core/textos.d.ts +8 -0
- package/dist/core/topeAgotado.d.ts +55 -0
- package/dist/core/traerDeLaMaquina.d.ts +33 -0
- package/dist/core/trazaDeErrores.d.ts +83 -0
- package/dist/core/tunel.d.ts +45 -0
- package/dist/core/turno.d.ts +154 -0
- package/dist/core/validacionDeEscritura.d.ts +95 -0
- package/dist/core/verificacionDeSubida.d.ts +14 -0
- package/dist/core/version.d.ts +35 -0
- package/dist/core/xmlBienFormado.d.ts +23 -0
- package/dist/core/zipDeAdjunto.d.ts +28 -0
- package/dist/core/zipDeSkill.d.ts +74 -0
- package/dist/lib/tareaAutonoma.d.ts +36 -0
- package/dist/lib/tareaAutonoma.js +259 -0
- package/dist/lib/tareaAutonoma.js.map +1 -0
- package/dist/lib.d.ts +31 -0
- package/dist/lib.js +28 -0
- package/dist/lib.js.map +1 -0
- package/dist/vendor/hitl.d.ts +69 -0
- package/dist/vendor/skillLoaders/catalog.d.ts +27 -0
- package/dist/vendor/sqliteSaver.d.ts +22 -0
- package/dist/vendor/tokenTracking.d.ts +22 -0
- package/dist/web/servidor/arranque.d.ts +1372 -0
- package/dist/web/servidor/consolaDeTarea.d.ts +166 -0
- package/dist/web/servidor/consolaWeb.d.ts +142 -0
- package/dist/web/servidor/corredorDeTareas.d.ts +395 -0
- package/dist/web/servidor/datosDeCierre.d.ts +4 -0
- package/dist/web/servidor/interrupcion.d.ts +39 -0
- package/dist/web/servidor/pielWeb.d.ts +32 -0
- package/dist/web/servidor/puenteRemoto.d.ts +80 -0
- package/dist/web/servidor/servidor.d.ts +53 -0
- package/dist/web/servidor/sesiones.d.ts +342 -0
- package/dist/web/servidor/soporte.d.ts +65 -0
- package/dist/web/servidor/soporte.js +2 -0
- package/dist/web/servidor/soporte.js.map +1 -1
- package/dist/web/servidor/transporte.d.ts +2751 -0
- package/dist/web/servidor/vestibulo.d.ts +952 -0
- package/dist/web/servidor/visorOpenui.d.ts +33 -0
- package/package.json +9 -1
|
@@ -0,0 +1,2751 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE del servidor al cliente, `POST /accion` del cliente al servidor.
|
|
3
|
+
*
|
|
4
|
+
* No es WebSocket a propósito: aquí hay UN stream, no un mux de streams lógicos con
|
|
5
|
+
* decenas de clientes hablando a la vez. Con SSE la reconexión es trivial porque el
|
|
6
|
+
* servidor guarda la lista de actos y la reemite entera; con WS habría que reimplementar
|
|
7
|
+
* generaciones y reanudación para no ganar nada.
|
|
8
|
+
*
|
|
9
|
+
* La regla que gobierna este fichero: **el contenido de fichero y el diff viajan en UN
|
|
10
|
+
* solo mensaje**, `aprobacion`, que es el paso donde el humano DECIDE sobre ellos. Ni los
|
|
11
|
+
* actos ni la traza de emisión los tocan, y por eso `emitir` no registra ese mensaje: lo
|
|
12
|
+
* guarda quien lo tiene en vuelo, que lo suelta en cuanto hay decisión.
|
|
13
|
+
*/
|
|
14
|
+
import type { PlanEnDisco } from "../../agent/planesEnDisco.js";
|
|
15
|
+
import type { EsquemaDelProyecto, MapeoDeEstados, TareaDelGestor, TransicionDelGestor, Vinculo } from "../../core/gestorDeTareas.js";
|
|
16
|
+
import type { CambiosDeUnaColeccion } from "../../core/diffDeColecciones.js";
|
|
17
|
+
import type { FotoDeColecciones } from "../../core/fotoDeColecciones.js";
|
|
18
|
+
import type { InformeDeDispositivos, NombreDeHerramienta } from "../../core/dispositivos.js";
|
|
19
|
+
import type { AjustesDeDispositivos } from "../../core/settings.js";
|
|
20
|
+
import type { Acto, ConsumoDeTurno, ConsumoPorModelo } from "../../core/actos.js";
|
|
21
|
+
import type { Tarea } from "../../core/tareas.js";
|
|
22
|
+
import type { PendienteDeAprobacion } from "../../core/events.js";
|
|
23
|
+
import type { LineaDeDiff } from "../../core/diff.js";
|
|
24
|
+
import type { SelectorDeConsola } from "../../cli/consola.js";
|
|
25
|
+
import type { DecisionDeConsola } from "../../cli/aprobar.js";
|
|
26
|
+
import type { OpcionDeEntorno, PasoDelVestibulo } from "./vestibulo.js";
|
|
27
|
+
import type { DispositivoElegido } from "./sesiones.js";
|
|
28
|
+
import type { Esfuerzo } from "../../core/esfuerzo.js";
|
|
29
|
+
import type { ConectorDelCable, DefinicionDeConector, FilaDeCatalogo } from "../../core/conectores.js";
|
|
30
|
+
import type { EstadoDeMotorLocal } from "../../core/motoresLocales.js";
|
|
31
|
+
import type { DiagnosticoDeNode } from "../../core/diagnosticoDeNode.js";
|
|
32
|
+
/** El vínculo del proyecto con su gestor, tal como cruza el cable: el del `config.json` más el
|
|
33
|
+
* nombre del sitio si esta ejecución ya lo sabe (lo dijo `sitios()`), y el del PROYECTO si ya
|
|
34
|
+
* lo nombró el gestor (IXCODE-15: en Notion `proyecto` es un `collection://…` que no se lee).
|
|
35
|
+
* Ausente = no consta. */
|
|
36
|
+
/** El vínculo tal como cruza: con su mapeo de estados y el interruptor del disparo (la puerta 2), que se editan en el panel. */
|
|
37
|
+
export type VinculoDelCable = Vinculo & {
|
|
38
|
+
nombreDelSitio?: string;
|
|
39
|
+
nombreDelProyecto?: string;
|
|
40
|
+
estados?: MapeoDeEstados;
|
|
41
|
+
automatico?: boolean;
|
|
42
|
+
revisarEncargo?: boolean;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* El informe de `core/dispositivos.ts`. **La `ruta` de cada herramienta solo cruza para
|
|
46
|
+
* `adb`/`emulator`** —la excepción declarada, igual que el workspace— y se quita en el
|
|
47
|
+
* código (`arranque.ts#sinRutas`) para `xcrun`/`devicectl`, que se quedan en el host: este
|
|
48
|
+
* cable puede ir por un túnel (`--anfitrion`) y esas dos nunca tuvieron un motivo para
|
|
49
|
+
* cruzarlo.
|
|
50
|
+
*/
|
|
51
|
+
export type InformeDeDispositivosDelCable = InformeDeDispositivos;
|
|
52
|
+
/**
|
|
53
|
+
* Una sesión tal como viaja dentro del alta de un proyecto. **Sin la raíz**: la fila de la
|
|
54
|
+
* barra no la pinta, y una ruta de la máquina no cruza este cable (`sinRutas`).
|
|
55
|
+
* Redeclarada en `apps/web/src/tipos.ts`, como `TareaDelCable`.
|
|
56
|
+
*
|
|
57
|
+
* Tiene nombre propio, y no es cosmético: `tipos.test.ts` comprueba que los campos de los dos
|
|
58
|
+
* lados son los MISMOS, y una fila escrita dentro de otra interfaz no se puede comparar —
|
|
59
|
+
* el test la ve como parte del alta y no como un tipo. Nombrarla es lo que hace posible que
|
|
60
|
+
* un campo que se añada en el host y no en el cliente salga rojo en vez de quedarse mudo.
|
|
61
|
+
*/
|
|
62
|
+
export interface SesionDelCable {
|
|
63
|
+
id: string;
|
|
64
|
+
titulo: string;
|
|
65
|
+
/**
|
|
66
|
+
* Cuándo se tocó por última vez, en ISO. Es lo que ordena la lista y lo que la barra pinta
|
|
67
|
+
* a la derecha de cada fila. Ausente = el índice no lo dice (una entrada corrupta): la fila
|
|
68
|
+
* se pinta sin sello y se ordena la última.
|
|
69
|
+
*/
|
|
70
|
+
ultimoTurno?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Esta conversación la abrió una TAREA de fondo, no una persona (`EntradaIndice.tarea`).
|
|
73
|
+
* Viaja un booleano y no el id: la fila lleva una marca y no el nombre de la tarea, así que
|
|
74
|
+
* el id se queda en el host.
|
|
75
|
+
*
|
|
76
|
+
* **Ausente es «no consta», no «es un chat»**: no la lleva ninguna sesión anterior a esta
|
|
77
|
+
* marca. Se pinta liso porque liso es lo conservador, no porque conste que sea de una
|
|
78
|
+
* persona — igual que `compartido` en un proyecto.
|
|
79
|
+
*/
|
|
80
|
+
deTarea?: true;
|
|
81
|
+
/**
|
|
82
|
+
* Esa conversación tiene un turno EN MARCHA ahora mismo, sea o no la que se está mirando.
|
|
83
|
+
* Es lo que hace visible que cambiar de sesión ya no interrumpe nada: el agente sigue
|
|
84
|
+
* trabajando en la de antes y la barra lo dice.
|
|
85
|
+
*
|
|
86
|
+
* Va en el ALTA y no en un mensaje propio porque el alta se reemite en los dos flancos de
|
|
87
|
+
* cada turno —de cualquiera de las consolas vivas—, que es exactamente cuando esto cambia.
|
|
88
|
+
*
|
|
89
|
+
* **Ausente es «no consta que esté trabajando»**, y eso incluye dos casos que no se pueden
|
|
90
|
+
* distinguir desde aquí: la sesión no tiene consola viva, o la tiene y está ociosa. Para lo
|
|
91
|
+
* que la barra pinta da igual; afirmar lo contrario, no.
|
|
92
|
+
*/
|
|
93
|
+
trabajando?: true;
|
|
94
|
+
/**
|
|
95
|
+
* Lo que ha gastado la sesión ENTERA: los deltas de sus turnos, sumados. Es un ACUMULADO,
|
|
96
|
+
* así que solo crece, y no lleva `ventana` —«cuánto ocupa el historial ahora» es una
|
|
97
|
+
* pregunta de la sesión ABIERTA, y congelada en una cerrada sería un «ahora» de hace días
|
|
98
|
+
* (lo quita `core/actos.ts#acumularTotales`)—.
|
|
99
|
+
*
|
|
100
|
+
* **Ausente es «no consta», nunca cero**: no lo trae ninguna sesión anterior a esto que la
|
|
101
|
+
* siembra no haya alcanzado. Un `{0,0}` afirmaría que la sesión salió gratis, y con él la
|
|
102
|
+
* barra pintaría un `↑0 ↓0` que nadie ha medido.
|
|
103
|
+
*/
|
|
104
|
+
consumo?: ConsumoDeTurno;
|
|
105
|
+
/**
|
|
106
|
+
* La CLAVE del ticket de Jira al que quedó ligada esta sesión (`"IXCODE-12"`), si tiene
|
|
107
|
+
* uno (`EntradaIndice.ticket`, IXCODE-11). Solo la clave, y no el objeto entero: es lo
|
|
108
|
+
* único que la fila de la barra tiene que pintar; el conector y el sitio se quedan en el
|
|
109
|
+
* host hasta que algo necesite componer la URL pública.
|
|
110
|
+
*/
|
|
111
|
+
ticket?: string;
|
|
112
|
+
/**
|
|
113
|
+
* IXCODE-15: el CONECTOR de ese ticket (`"jira"`, `"notion"`), solo con `ticket`. Es con quien
|
|
114
|
+
* se cierra la tarea —no con el gestor vinculado ahora—, y de él sale el rótulo «Cerrar en …».
|
|
115
|
+
*/
|
|
116
|
+
ticketConector?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Las seis fases de un lanzamiento, EN ORDEN, y los cinco estados en que puede estar.
|
|
120
|
+
*
|
|
121
|
+
* **Se declaran aquí, en el cable, y no se importan de `agent/dispositivos/lanzamientoEnMaquina.ts`**, que es
|
|
122
|
+
* quien las recorre. El motivo es el de siempre en este fichero: el cable tiene su vocabulario
|
|
123
|
+
* CERRADO, y quien lo cierra es esta constante — la lista blanca del store del cliente y la
|
|
124
|
+
* validación del servidor se escriben contra ESTA lista, así que un valor que no esté aquí no
|
|
125
|
+
* llega a la pantalla. Importarlas ataría el contrato del cable al módulo que hoy lo cumple, y
|
|
126
|
+
* el día que ese módulo añada una fase el cable la aceptaría sin que nadie hubiera decidido si
|
|
127
|
+
* el cliente sabe pintarla.
|
|
128
|
+
*
|
|
129
|
+
* **Y por eso mismo hay un test que las ata** (`arranque.test.ts`: «las fases del cable son las
|
|
130
|
+
* que corre la máquina»): la lista de aquí no puede quedarse corta respecto de la de allí, o el
|
|
131
|
+
* recorrido se quedaría sin emitir justo la fase que alguien acaba de añadir.
|
|
132
|
+
*
|
|
133
|
+
* **`corriendo` no está en `EstadoDeLanzamiento` de la máquina, y aquí sí.** Allí el estado es un
|
|
134
|
+
* DESENLACE —cuatro formas de acabar—, porque `lanzarEnDispositivo` devuelve un resultado; aquí
|
|
135
|
+
* hay además un RECORRIDO EN VIVO, que es lo que permite que la pestaña enseñe en qué fase va
|
|
136
|
+
* en vez de un botón apagado sin explicación.
|
|
137
|
+
*/
|
|
138
|
+
export declare const FASES_DEL_LANZAMIENTO: readonly ["comprobando", "empaquetando", "subiendo", "reiniciando", "lanzando", "comprobando-arranque"];
|
|
139
|
+
export type FaseDelLanzamiento = (typeof FASES_DEL_LANZAMIENTO)[number];
|
|
140
|
+
export declare const ESTADOS_DEL_LANZAMIENTO: readonly ["corriendo", "ok", "fallo", "cancelada", "colgada"];
|
|
141
|
+
export type EstadoDelLanzamiento = (typeof ESTADOS_DEL_LANZAMIENTO)[number];
|
|
142
|
+
export type MensajeAlCliente = {
|
|
143
|
+
clase: "acto";
|
|
144
|
+
acto: Acto;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* SUSTITUYE el último acto del cliente. Existe porque `pielWeb.alActo` avisa también
|
|
148
|
+
* de ACTUALIZACIONES: el cierre de una racha de tools reemplaza a su apertura dentro
|
|
149
|
+
* del mismo acto `herramientas` (`core/actos.ts#conLineaDeTool`). Un cliente que
|
|
150
|
+
* anexara a ciegas enseñaría las dos líneas para siempre.
|
|
151
|
+
*
|
|
152
|
+
* Solo se emite cuando el acto que cambia ES el último; si algo se escribió después,
|
|
153
|
+
* el transporte manda una `reemision` entera — sustituir «el último» tocaría otro acto.
|
|
154
|
+
*/
|
|
155
|
+
| {
|
|
156
|
+
clase: "sustitucion";
|
|
157
|
+
acto: Acto;
|
|
158
|
+
}
|
|
159
|
+
/** El transcript completo: lo que recibe quien (re)conecta, y el arreglo de cualquier desajuste. */
|
|
160
|
+
| {
|
|
161
|
+
clase: "reemision";
|
|
162
|
+
actos: Acto[];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* La sesión remota: el interruptor (`habilitado`, de `settings.remoto` o `XONECODE_REMOTO=1`, que
|
|
166
|
+
* es `porEntorno` y no se apaga desde Ajustes) y el estado del puente. La `url` lleva
|
|
167
|
+
* el SECRETO en el fragmento: es el TERCER secreto del cable, tras `leerSecreto` y el `codigo` de `motorLocal`, y por eso
|
|
168
|
+
* `remoto` no está en la lista de salida del puente (`core/remoto.ts`).
|
|
169
|
+
*/
|
|
170
|
+
| {
|
|
171
|
+
clase: "remoto";
|
|
172
|
+
estado: "apagada" | "abriendo" | "activa" | "reconectando" | "error";
|
|
173
|
+
habilitado?: boolean;
|
|
174
|
+
porEntorno?: true;
|
|
175
|
+
url?: string;
|
|
176
|
+
moviles?: number;
|
|
177
|
+
motivo?: string;
|
|
178
|
+
/** Por dónde sale: el servidor manda siempre la vía en vigor; un cliente que no la reciba (servidor antiguo) la lee como ngrok. */
|
|
179
|
+
via?: "servidor" | "ngrok";
|
|
180
|
+
/**
|
|
181
|
+
* Lo medido de ngrok, solo si el diálogo lo necesita. `cuenta` = hay authtoken en SU
|
|
182
|
+
* configuración (nunca el token ni la ruta, que no cruzan). `instalado` = el SDK de ngrok, que viene con
|
|
183
|
+
* xonecode, CARGA: no hay receta para instalarlo aparte.
|
|
184
|
+
* `motivo` = por qué falló la última acción de ngrok (authtoken o dominio): SOLO un texto
|
|
185
|
+
* fijo nuestro (`MOTIVOS_DEL_TUNEL` o el rechazo del dominio), nunca lo tecleado ni lo que
|
|
186
|
+
* contestó ngrok. Lo quita la siguiente acción que sale bien.
|
|
187
|
+
*/
|
|
188
|
+
ngrok?: {
|
|
189
|
+
instalado: boolean;
|
|
190
|
+
cuenta: boolean;
|
|
191
|
+
dominio?: string;
|
|
192
|
+
motivo?: string;
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* El saludo, SUELTO del `alta`. `agent/config/persona.ts#nombreDePersona` no depende de
|
|
197
|
+
* ninguna cuenta ni de ningún login —es `git config`/`os.userInfo()`, local y ya
|
|
198
|
+
* resuelto al construir el vestíbulo—, pero el `alta` solo se manda DESPUÉS de que
|
|
199
|
+
* `conducirCuenta()` termina (`arranque.ts#anunciarAlta`), que puede tardar lo que
|
|
200
|
+
* tarde un humano en elegir modelo y teclear una clave. Sin este mensaje, medido: la
|
|
201
|
+
* pantalla decía «Hola» a secas durante TODO el paso de cuenta, con el nombre ya
|
|
202
|
+
* resuelto y sin ningún sitio por el que viajar hasta que la cuenta se resolviera —
|
|
203
|
+
* un saludo que se sabe y no se dice. Se manda una vez, al conectar, antes de
|
|
204
|
+
* `conducirCuenta()`. `alta.nombre` (más abajo) sigue llevando el MISMO dato — no
|
|
205
|
+
* porque quede alguna conexión sin ver este mensaje (el SSE arranca de cero en cada
|
|
206
|
+
* conexión y siempre lo manda primero), sino porque quitarlo de `alta` cambiaría ese
|
|
207
|
+
* contrato y su test, y eso no es parte de este arreglo.
|
|
208
|
+
*/
|
|
209
|
+
| {
|
|
210
|
+
clase: "bienvenida";
|
|
211
|
+
nombre?: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Una pregunta a la que hay que contestar.
|
|
215
|
+
*
|
|
216
|
+
* **`decision` es la FORMA, y ausente significa texto libre**, que es lo que ha sido
|
|
217
|
+
* siempre: el cliente pinta un campo y lo que se teclea vuelve como `respuesta`. Con
|
|
218
|
+
* `decision` puesta la respuesta es sí o no y no se teclea nada — la tarjeta enseña
|
|
219
|
+
* `lineas` (el plan de la subida, las mismas líneas que ya fueron por `acto` de sistema)
|
|
220
|
+
* y dos botones, y contesta por la MISMA puerta de siempre: `"s"` autoriza y el resto
|
|
221
|
+
* rechaza (`interpretAnswer`).
|
|
222
|
+
*
|
|
223
|
+
* No se deduce del enunciado: el `[s/N]` es sintaxis, y una piel rica que lo leyera para
|
|
224
|
+
* decidir si pone botones se rompería el día que alguien reescriba el prompt — con un
|
|
225
|
+
* editor donde hacía falta un botón, o con dos botones sobre una pregunta abierta, y sin
|
|
226
|
+
* ningún error que lo delate.
|
|
227
|
+
*/
|
|
228
|
+
| {
|
|
229
|
+
clase: "pregunta";
|
|
230
|
+
texto: string;
|
|
231
|
+
decision?: DecisionDeConsola;
|
|
232
|
+
} | {
|
|
233
|
+
clase: "selector";
|
|
234
|
+
selector: SelectorDeConsola;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Los modelos: cuál está en vigor, cuál queda por defecto, y qué se puede elegir.
|
|
238
|
+
*
|
|
239
|
+
* **Son DOS preguntas y por eso son dos campos.** `actual` es lo que resuelve el papel
|
|
240
|
+
* `trabajo` con las fuentes de la sesión ABIERTA, no lo que diga un fichero: `/modelo`
|
|
241
|
+
* cambia el modelo en caliente sin escribir nada, así que releer la configuración
|
|
242
|
+
* contaría lo de antes. Ausente = no hay sesión de proyecto y por tanto no hay modelo en
|
|
243
|
+
* vigor que afirmar — el cliente enseña «Elige modelo» en vez de inventarse una fila, que
|
|
244
|
+
* es la regla del harness de DeepSeek: «no stale row is synthesized».
|
|
245
|
+
*
|
|
246
|
+
* `porDefecto` es otra cosa: el que usarán las sesiones NUEVAS, resuelto contra el
|
|
247
|
+
* `config.json` global. Existe porque el compositor y Ajustes no preguntan lo mismo —una
|
|
248
|
+
* sesión puede llevar encima un `/modelo` en caliente y el defecto seguir siendo otro—, y
|
|
249
|
+
* meterlos en un campo solo enseñaría una de las dos como si fuera la otra. Y se manda
|
|
250
|
+
* TAMBIÉN sin sesión abierta, que es justo donde se configura: sin él, Ajustes diría «sin
|
|
251
|
+
* elegir» sobre una máquina que sí tiene un defecto escrito.
|
|
252
|
+
*
|
|
253
|
+
* `modelos` de un proveedor viaja SOLO cuando alguien lo ha pedido (`clase: "catalogo"`):
|
|
254
|
+
* el catálogo es una llamada de red por proveedor y consultarlos todos al conectar sería
|
|
255
|
+
* gastar cinco peticiones para pintar un menú que quizá nadie abra. `error` es el fallo
|
|
256
|
+
* de ESE proveedor y no tumba a los demás — se lista inservible y el resto sigue
|
|
257
|
+
* elegible.
|
|
258
|
+
*/
|
|
259
|
+
| {
|
|
260
|
+
clase: "modelos";
|
|
261
|
+
actual?: string;
|
|
262
|
+
porDefecto?: string;
|
|
263
|
+
proveedores: ProveedorDeModelos[];
|
|
264
|
+
/**
|
|
265
|
+
* Qué esfuerzo admite el modelo EN VIGOR y cuál está puesto en la sesión.
|
|
266
|
+
*
|
|
267
|
+
* Viaja con los modelos y no en un mensaje propio porque cambia en los mismos
|
|
268
|
+
* instantes: los niveles dependen del modelo, así que un `/modelo` que no lo trajera
|
|
269
|
+
* dejaría la pastilla ofreciendo los del modelo de antes. Mismo motivo por el que la
|
|
270
|
+
* ventana de contexto viaja dentro de `consumo`.
|
|
271
|
+
*
|
|
272
|
+
* Ausente = no hay nada que afirmar (sin sesión, o el modelo no lo admite), y
|
|
273
|
+
* entonces la pastilla no se pinta.
|
|
274
|
+
*/
|
|
275
|
+
esfuerzo?: {
|
|
276
|
+
niveles: Esfuerzo[];
|
|
277
|
+
actual?: Esfuerzo;
|
|
278
|
+
nota?: string;
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Los proyectos de UN entorno registrado, en respuesta a la acción «proyectos» de un
|
|
283
|
+
* mensaje de entorno. Lleva el `entorno` dentro porque el cliente los guarda por
|
|
284
|
+
* entorno: son las casillas de una pestaña concreta de Ajustes, y una lista sin dueño se
|
|
285
|
+
* acabaría pintando bajo el nombre de otro servidor.
|
|
286
|
+
*
|
|
287
|
+
* **`proyectos` ausente y `error` puesto no es una lista vacía**: «no se pudo preguntar»
|
|
288
|
+
* no es «este entorno no tiene proyectos», y la pestaña tiene que poder decir lo primero
|
|
289
|
+
* en vez de afirmar lo segundo. El fallo es de ESE entorno y no tumba a los demás —la
|
|
290
|
+
* regla del catálogo de modelos: un desvío, no un callejón—, así que tampoco se pinta un
|
|
291
|
+
* aviso global ni se toca el entorno activo.
|
|
292
|
+
*
|
|
293
|
+
* No va en el `alta` a propósito, aunque `registrados` viaje ahí: el alta se reemite en
|
|
294
|
+
* los dos flancos de cada turno, y meter estas listas dentro obligaría a cachearlas en el
|
|
295
|
+
* proceso. Sin caché hay UNA sola fuente, así que la pestaña no puede contradecir a la
|
|
296
|
+
* barra cuando alguien cree un proyecto en Studio.
|
|
297
|
+
*/
|
|
298
|
+
| {
|
|
299
|
+
clase: "proyectosDeEntorno";
|
|
300
|
+
entorno: string;
|
|
301
|
+
proyectos?: ProyectoDeEntorno[];
|
|
302
|
+
error?: string;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Cómo fue el último alta o baja de proveedor personalizado.
|
|
306
|
+
*
|
|
307
|
+
* El motivo viaja EN un mensaje propio y no por `informar`, por lo mismo que el aviso
|
|
308
|
+
* del selector durante el alta: la ventana de ajustes no pinta el transcript, así que un
|
|
309
|
+
* fallo contado como acto de sistema sería mudo justo donde hay que leerlo. `hecho` es
|
|
310
|
+
* lo que deja al formulario cerrarse solo cuando la cosa salió bien.
|
|
311
|
+
*/
|
|
312
|
+
| {
|
|
313
|
+
clase: "proveedor";
|
|
314
|
+
hecho: boolean;
|
|
315
|
+
motivo?: string;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Hay un turno EN VUELO, o dejó de haberlo.
|
|
319
|
+
*
|
|
320
|
+
* El cliente lo necesita para dos cosas que no puede deducir sin mentir: apagar el
|
|
321
|
+
* compositor mientras el agente trabaja —mandar una segunda petición encima solo la
|
|
322
|
+
* encola sin decirlo— y convertir la flecha de enviar en un botón de parar. Deducirlo de
|
|
323
|
+
* los actos (¿llegó un `fin` después del último `usuario`?) fallaría justo cuando importa:
|
|
324
|
+
* un turno que revienta no siempre deja `fin`.
|
|
325
|
+
*/
|
|
326
|
+
/** `detenible`: el turno en marcha admite DETENER y replanificar. Ausente = no. */
|
|
327
|
+
| {
|
|
328
|
+
clase: "turno";
|
|
329
|
+
activo: boolean;
|
|
330
|
+
detenible?: true;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Lo que lleva consumido la sesión, en sus DOS cuentas.
|
|
334
|
+
*
|
|
335
|
+
* Separadas y no sumadas: los del grafo van contra la clave de API del usuario y los del
|
|
336
|
+
* agente externo contra su suscripción del producto. Sumar tokens es defendible; sumar su
|
|
337
|
+
* coste sería la cifra que miente, así que aquí solo viajan tokens y viajan aparte.
|
|
338
|
+
*
|
|
339
|
+
* Se emite en cada cambio y también al conectar, porque una pestaña que llega a mitad de
|
|
340
|
+
* sesión no vio los anteriores. Ausente = no consta (no hay sesión, o es el de pega) y
|
|
341
|
+
* entonces el cliente NO pinta un cero.
|
|
342
|
+
*/
|
|
343
|
+
| {
|
|
344
|
+
clase: "consumo";
|
|
345
|
+
modelo: {
|
|
346
|
+
entrada: number;
|
|
347
|
+
salida: number;
|
|
348
|
+
cache: number;
|
|
349
|
+
};
|
|
350
|
+
externo: {
|
|
351
|
+
entrada: number;
|
|
352
|
+
salida: number;
|
|
353
|
+
cache: number;
|
|
354
|
+
};
|
|
355
|
+
/**
|
|
356
|
+
* Cuánto ocupa la VENTANA ahora, y su tope si se sabe. Otra pregunta que los
|
|
357
|
+
* acumulados: aquéllos dicen lo que la sesión ha costado y esto cuánto margen queda.
|
|
358
|
+
*
|
|
359
|
+
* `tope` ausente es «no se sabe», y entonces no se pinta denominador ni porcentaje —
|
|
360
|
+
* con Ollama no hay tope A PROPÓSITO (cada modelo local trae el suyo), y un
|
|
361
|
+
* porcentaje sobre un número inventado es una mentira con forma de cifra.
|
|
362
|
+
*/
|
|
363
|
+
ventana: {
|
|
364
|
+
usado: number;
|
|
365
|
+
tope?: number;
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* Lo mismo, POR MODELO: un especialista puede correr en otro modelo que el raíz. Ausente =
|
|
369
|
+
* no consta (una sesión de antes, o un motor que no lo mide); lo gastado antes de medirlo
|
|
370
|
+
* llega bajo `SIN_DESGLOSE`, así que las filas suman el total.
|
|
371
|
+
*/
|
|
372
|
+
porModelo?: ConsumoPorModelo;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Se está ABRIENDO algo: una sesión, o un proyecto que además hay que descargar.
|
|
376
|
+
*
|
|
377
|
+
* Lo dice el SERVIDOR y no lo deduce el cliente, por el mismo motivo que `turno`: solo
|
|
378
|
+
* este lado sabe cuándo empieza y cuándo acaba, y aquí el rango va de «unos cientos de
|
|
379
|
+
* milisegundos» (abrir una copia local: foto de git, checkpointer, sesiones) a «minutos»
|
|
380
|
+
* (descargar el proyecto entero). Deducirlo de que llegue un `alta` nuevo fallaría justo
|
|
381
|
+
* cuando importa: un fallo al abrir también anuncia alta, y una apertura sobre el
|
|
382
|
+
* proyecto que YA estaba activo no cambia nada en él.
|
|
383
|
+
*
|
|
384
|
+
* `activo: false` es el otro flanco y va en un `finally`, así que salir por un error
|
|
385
|
+
* también lo apaga — un indicador de actividad que se queda encendido para siempre es
|
|
386
|
+
* peor que no tenerlo.
|
|
387
|
+
*/
|
|
388
|
+
| {
|
|
389
|
+
clase: "abriendo";
|
|
390
|
+
activo: boolean;
|
|
391
|
+
/** Qué se está abriendo, para poder señalarlo en su fila. Solo con `activo`. */
|
|
392
|
+
proyecto?: string;
|
|
393
|
+
sesion?: string;
|
|
394
|
+
/**
|
|
395
|
+
* El entorno que se está MUDANDO, cuando lo que viaja no es una apertura sino un
|
|
396
|
+
* cambio de entorno activo.
|
|
397
|
+
*
|
|
398
|
+
* Va aparte de `proyecto` y no en su lugar porque el cambio de entorno no abre nada
|
|
399
|
+
* del árbol: vacía la lista entera y la vuelve a traer del otro servidor. Y es un
|
|
400
|
+
* campo y no un `activo: true` pelado porque el cliente tiene que poder ENSEÑAR el
|
|
401
|
+
* que se ha pedido: sin eso el `<select>`, que va controlado por el `alta` —y el
|
|
402
|
+
* `alta` solo llega al final—, se queda clavado en el valor viejo durante toda la
|
|
403
|
+
* espera, y la elección se lee como que no ha entrado. Medido: 1,5 s.
|
|
404
|
+
*/
|
|
405
|
+
entorno?: string;
|
|
406
|
+
/** Además hay que BAJARLO: es la espera larga, y la que hay que decir con palabras. */
|
|
407
|
+
descargando?: true;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Los subagentes dados de alta, para la ventana de ajustes.
|
|
411
|
+
*
|
|
412
|
+
* Se manda entero cada vez que cambia —son pocos y pequeños— en vez de mandar deltas:
|
|
413
|
+
* una lista de cinco elementos no justifica un protocolo de diferencias, y un delta
|
|
414
|
+
* perdido dejaría la ventana enseñando un agente que ya no existe.
|
|
415
|
+
*
|
|
416
|
+
* `problemas` son los `.md` que no se pudieron leer, con su motivo. Van por el cable y no
|
|
417
|
+
* solo al log del servidor porque quien los tiene que arreglar está mirando ESTA ventana:
|
|
418
|
+
* un agente que no aparece y nadie dice por qué se lee como que la aplicación lo perdió.
|
|
419
|
+
*/
|
|
420
|
+
| {
|
|
421
|
+
clase: "agentes";
|
|
422
|
+
agentes: AgenteDelCable[];
|
|
423
|
+
problemas: string[];
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Las skills en vigor, para la ventana de ajustes y para el editor de un subagente.
|
|
427
|
+
*
|
|
428
|
+
* Se manda entera cada vez que cambia —son pocas y el cuerpo solo viaja de las del
|
|
429
|
+
* usuario— en vez de mandar deltas, por lo mismo que `agentes`: un delta perdido dejaría
|
|
430
|
+
* la ventana enseñando una skill que ya no existe, y un subagente marcando una casilla que
|
|
431
|
+
* no tiene detrás ningún fichero.
|
|
432
|
+
*
|
|
433
|
+
* `problemas` son las carpetas que no se pudieron leer, con su motivo, y significa SOLO
|
|
434
|
+
* eso: que una del usuario tape a una de serie no es un problema, es la forma de afinarla
|
|
435
|
+
* sin editar donde el `npm install` la pisaría.
|
|
436
|
+
*/
|
|
437
|
+
| {
|
|
438
|
+
clase: "skills";
|
|
439
|
+
skills: SkillDelCable[];
|
|
440
|
+
problemas: string[];
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* El cuerpo de UNA skill, pedido a mano (`clase: "cuerpoDeSkill"` del cliente).
|
|
444
|
+
*
|
|
445
|
+
* Va aparte y no dentro del `skills` por lo que ese tipo explica: las de serie son
|
|
446
|
+
* ficheros grandes y mandarlas todas en la ráfaga de bienvenida cuesta cientos de
|
|
447
|
+
* kilobytes para un formulario que nadie puede guardar. Aquí se paga solo la que se abre.
|
|
448
|
+
*
|
|
449
|
+
* `cuerpo` ausente = no se pudo leer, y entonces se DICE: una ficha que se abre en blanco
|
|
450
|
+
* se lee como que la skill está vacía.
|
|
451
|
+
*/
|
|
452
|
+
| {
|
|
453
|
+
clase: "cuerpoDeSkill";
|
|
454
|
+
nombre: string;
|
|
455
|
+
cuerpo?: string;
|
|
456
|
+
error?: string;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* La cola de tareas entera. Va a TODOS los clientes, como la foto de la máquina y por lo
|
|
460
|
+
* mismo: la cola es de la máquina. `corriendoAqui` es falso en el segundo proceso, y es lo
|
|
461
|
+
* que deja decir que este kanban no avanza.
|
|
462
|
+
*
|
|
463
|
+
* **Y `ejecutaOtroProceso` es la otra mitad, porque «no soy yo» y «no hay nadie»
|
|
464
|
+
* significan lo contrario**: el primero manda a esperar —una tarea creada aquí arrancará
|
|
465
|
+
* cuando ese proceso mire la cola— y el segundo dice que no va a pasar nada hasta que
|
|
466
|
+
* alguna consola tome el relevo. Con un solo booleano, el aviso mandaba a esperar a un
|
|
467
|
+
* proceso que puede no existir. **Ausente = no se sabe** (el cerrojo ni se pudo mirar, o
|
|
468
|
+
* esta ejecución no tiene corredor), y entonces no se afirma ninguna de las dos.
|
|
469
|
+
* **El pid no viaja**: es un dato de la máquina y no le dice nada a quien lo lee.
|
|
470
|
+
*/
|
|
471
|
+
| {
|
|
472
|
+
clase: "tareas";
|
|
473
|
+
lista: TareaDelCable[];
|
|
474
|
+
concurrencia: number;
|
|
475
|
+
corriendoAqui: boolean;
|
|
476
|
+
ejecutaOtroProceso?: boolean;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Dónde se bajan las copias locales: la ruta ENTERA.
|
|
480
|
+
*
|
|
481
|
+
* **Es la excepción NOMBRADA a `sinRutas`**, y la única del cable. No se puede esquivar:
|
|
482
|
+
* el campo de Ajustes tiene que enseñar la carpeta que hay puesta, y una ruta que no se
|
|
483
|
+
* enseña no se puede comprobar ni elegir. Se probó a mandarla abreviada con `~` para que el
|
|
484
|
+
* caso normal no llevara el nombre de la cuenta del sistema, y no se sostiene: la cabecera
|
|
485
|
+
* de esta misma consola ya saluda por el nombre del usuario (`clase: "bienvenida"`), así que
|
|
486
|
+
* el `~` no tapaba nada que no estuviera ya y a cambio dejaba en pantalla una ruta que no se
|
|
487
|
+
* puede leer de un vistazo.
|
|
488
|
+
*
|
|
489
|
+
* Va en la ráfaga de bienvenida por lo mismo que los modelos y las skills: Ajustes se
|
|
490
|
+
* puede abrir en cuanto conecta, y un campo vacío se lee como «no hay nada puesto».
|
|
491
|
+
*/
|
|
492
|
+
| {
|
|
493
|
+
clase: "workspace";
|
|
494
|
+
ruta: string;
|
|
495
|
+
puedeElegir?: boolean;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* La carpeta que la persona eligió en el diálogo del sistema, para PONERLA EN EL CAMPO —
|
|
499
|
+
* no para guardarla. `ruta` AUSENTE = no eligió ninguna (canceló, o no se pudo abrir el
|
|
500
|
+
* diálogo), y entonces el campo se queda como estaba.
|
|
501
|
+
*
|
|
502
|
+
* **Elegir y guardar son dos actos, y por eso son dos mensajes.** Guardar desde el propio
|
|
503
|
+
* diálogo dejaría el ajuste escrito antes de que nadie hubiera leído la ruta entera, y en
|
|
504
|
+
* un campo cuyo único trabajo es que la ruta se pueda leer eso sería quitarle el trabajo.
|
|
505
|
+
*/
|
|
506
|
+
| {
|
|
507
|
+
clase: "carpetaElegida";
|
|
508
|
+
ruta?: string;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Cómo va la MUDANZA de las copias al cambiar el workspace, y cómo acabó. `progreso` mientras
|
|
512
|
+
* dura (fase, y el proyecto por NOMBRE y entorno: ninguna ruta de la máquina), `resultado`
|
|
513
|
+
* una vez al final. Los dos ausentes no viajan nunca.
|
|
514
|
+
*/
|
|
515
|
+
| {
|
|
516
|
+
clase: "mudanzaDeWorkspace";
|
|
517
|
+
progreso?: {
|
|
518
|
+
fase: "comprobar" | "copiar" | "verificar" | "borrar";
|
|
519
|
+
proyecto?: string;
|
|
520
|
+
entorno?: string;
|
|
521
|
+
indice?: number;
|
|
522
|
+
total?: number;
|
|
523
|
+
};
|
|
524
|
+
resultado?: {
|
|
525
|
+
estado: "hecho";
|
|
526
|
+
mudadas: number;
|
|
527
|
+
restos: string[];
|
|
528
|
+
avisos: string[];
|
|
529
|
+
} | {
|
|
530
|
+
estado: "rechazado";
|
|
531
|
+
motivo: string;
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* La casilla «Depurar» de Ajustes > General: si las dos trazas opt-in van encendidas sin
|
|
536
|
+
* variable de entorno. Va en la ráfaga de bienvenida por lo mismo que el workspace.
|
|
537
|
+
*
|
|
538
|
+
* `activa` es el valor YA RESUELTO (`core/settings.ts#depuracionActiva`): ausente en
|
|
539
|
+
* `settings.json` llega como `true`, la omisión de esta etapa de pruebas.
|
|
540
|
+
*/
|
|
541
|
+
| {
|
|
542
|
+
clase: "depuracion";
|
|
543
|
+
activa: boolean;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* El modo con que NACEN las sesiones nuevas en cualquier proyecto (IXCODE-31, Ajustes >
|
|
547
|
+
* General). Va en la ráfaga de bienvenida por lo mismo que «Depurar». Ya RESUELTO: ausente en
|
|
548
|
+
* `settings.json` llega como `supervisado`. El de cada proyecto, que gana sobre éste, viaja en
|
|
549
|
+
* la foto del resumen (`FotoDelResumen.modoDeEscritura`).
|
|
550
|
+
*/
|
|
551
|
+
| {
|
|
552
|
+
clase: "modoPorDefecto";
|
|
553
|
+
modo: "supervisado" | "autonomo";
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* El aparato con que NACEN las sesiones nuevas, de una persona y de una tarea (IXCODE-51,
|
|
557
|
+
* Ajustes > General). Va en la ráfaga por lo mismo que el modo. Sin `dispositivo` = ninguno
|
|
558
|
+
* elegido, que no es lo mismo que no recibir el mensaje (entonces el control no se pinta).
|
|
559
|
+
*/
|
|
560
|
+
| {
|
|
561
|
+
clase: "dispositivoPorDefecto";
|
|
562
|
+
dispositivo?: DispositivoElegido;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* El catálogo de conectores MCP y los que esta consola tiene AÑADIDOS, para la sección de
|
|
566
|
+
* Ajustes. Va en la ráfaga de bienvenida por lo mismo que el workspace: Ajustes se puede
|
|
567
|
+
* abrir en cuanto conecta, y solo si la opción `conectores` está puesta — «un control sin
|
|
568
|
+
* dato detrás no se pinta».
|
|
569
|
+
*
|
|
570
|
+
* `catalogo` viaja SIN la `url` de cada servidor: no hace falta en pantalla, y así no hay
|
|
571
|
+
* una ruta remota que discutir por este cable.
|
|
572
|
+
*
|
|
573
|
+
* `ilegible`/`error` son los mismos campos que da `ServicioDeConectores.lista()`. Un fallo
|
|
574
|
+
* NO va por `informar`, que no llega al navegador desde el vestíbulo, y Ajustes se abre sin
|
|
575
|
+
* proyecto.
|
|
576
|
+
*/
|
|
577
|
+
| {
|
|
578
|
+
clase: "conectores";
|
|
579
|
+
catalogo: FilaDeCatalogo[];
|
|
580
|
+
conectores: ConectorDelCable[];
|
|
581
|
+
desconocidos: string[];
|
|
582
|
+
ilegible?: true;
|
|
583
|
+
error?: string;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Cómo fue la última augmentación pedida (`{clase:"tarea", accion:"augmentar"}`): el
|
|
587
|
+
* encargo que propone el modelo, o por qué no se pudo. Nunca los dos a la vez.
|
|
588
|
+
*/
|
|
589
|
+
| {
|
|
590
|
+
clase: "tarea";
|
|
591
|
+
accion: "augmentado";
|
|
592
|
+
encargo: string;
|
|
593
|
+
} | {
|
|
594
|
+
clase: "tarea";
|
|
595
|
+
accion: "augmentado";
|
|
596
|
+
error: string;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Un trozo del transcript de la sesión de una TAREA que alguien está mirando en vivo.
|
|
600
|
+
*
|
|
601
|
+
* **No es un segundo registro** (decisión 3 del diseño): son los MISMOS actos que se
|
|
602
|
+
* guardan en el `.jsonl` de esa sesión, los mismos que se leen al abrirla después. La
|
|
603
|
+
* lista sale de los actos y nunca del disco, igual que la de artefactos.
|
|
604
|
+
*
|
|
605
|
+
* Va SOLO al cliente que lo pidió y no a todos: el transcript de una tarea no puede
|
|
606
|
+
* aparecer en el chat de quien está trabajando en otra cosa. Y lleva el `tarea` delante
|
|
607
|
+
* porque por el mismo cable puede llegar el transcript de la sesión propia: sin la
|
|
608
|
+
* etiqueta, los actos de una tarea de fondo se mezclarían con la conversación.
|
|
609
|
+
*
|
|
610
|
+
* Los tres `via` son los tres mensajes del transcript de siempre, con otro nombre:
|
|
611
|
+
* `todos` es la reemisión entera (al empezar a mirar y cuando el servidor reemite),
|
|
612
|
+
* `alta` un acto nuevo al final, y `sustitucion` el último que cambió (el cierre de una
|
|
613
|
+
* racha de tools sustituye a su apertura). `actos` es SIEMPRE una lista: con `alta` y
|
|
614
|
+
* `sustitucion`, de un solo elemento — un campo opcional por cada forma habría sido un
|
|
615
|
+
* «ausente no es vacío» de más en la lista blanca del store.
|
|
616
|
+
*/
|
|
617
|
+
| {
|
|
618
|
+
clase: "mirada";
|
|
619
|
+
tarea: string;
|
|
620
|
+
via: "todos" | "alta" | "sustitucion";
|
|
621
|
+
actos: Acto[];
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Qué hay en la MÁQUINA para probar la app: el sistema, las herramientas de Android e
|
|
625
|
+
* iOS (adb, emulator, xcrun/simctl, devicectl) con su estado, y a qué dispositivos y
|
|
626
|
+
* simuladores se llega (`core/dispositivos.ts`).
|
|
627
|
+
*
|
|
628
|
+
* Es una FOTO con su hora (`medido`), no un estado en vivo: se toma al conectar el primer
|
|
629
|
+
* cliente y cuando alguien pide actualizarla (el mensaje «dispositivos» del cliente). No se
|
|
630
|
+
* sondea en bucle porque `adb devices` arranca el demonio de adb y `xcrun` puede tardar
|
|
631
|
+
* segundos — un panel que se refresca solo cada pocos segundos lanzaría procesos en la
|
|
632
|
+
* máquina del usuario sin que nadie lo pidiera.
|
|
633
|
+
*/
|
|
634
|
+
| {
|
|
635
|
+
clase: "dispositivos";
|
|
636
|
+
informe: InformeDeDispositivosDelCable;
|
|
637
|
+
/**
|
|
638
|
+
* Cómo acabó el último «Arrancar» de un emulador, si hubo uno.
|
|
639
|
+
*
|
|
640
|
+
* Viaja CON la foto nueva a propósito: el resultado de arrancar no es el código de
|
|
641
|
+
* salida de `emulator` —que vuelve enseguida— sino que el aparato APAREZCA, y eso es lo
|
|
642
|
+
* que dice la foto. Así las dos cosas llegan juntas y no se pueden leer desfasadas.
|
|
643
|
+
*
|
|
644
|
+
* **Ausente = no se ha pedido ninguno**, que no es «salió bien». Y un `ok: false` trae
|
|
645
|
+
* su línea: un botón que no hace nada y no lo dice es lo que esto viene a evitar.
|
|
646
|
+
*/
|
|
647
|
+
arranque?: {
|
|
648
|
+
avd: string;
|
|
649
|
+
ok: boolean;
|
|
650
|
+
detalle: string;
|
|
651
|
+
};
|
|
652
|
+
/**
|
|
653
|
+
* Qué dispositivo tiene elegido CADA consola abierta, y de qué proyecto es: con dos
|
|
654
|
+
* proyectos sobre dos emuladores, la pastilla del chat avisa «lo usa Tienda» en el aparato ajeno.
|
|
655
|
+
* `proyecto` es el nombre de su carpeta —el que enseña la barra—, nunca una ruta. Una
|
|
656
|
+
* consola sin dispositivo elegido no aparece.
|
|
657
|
+
*/
|
|
658
|
+
enUso?: {
|
|
659
|
+
id: string;
|
|
660
|
+
proyecto: string;
|
|
661
|
+
}[];
|
|
662
|
+
/**
|
|
663
|
+
* Qué destinos se miran (`core/settings.ts#AjustesDeDispositivos`). Viaja CON la
|
|
664
|
+
* foto porque las dos cosas se leen juntas: una herramienta «desactivada» solo se
|
|
665
|
+
* entiende sabiendo qué interruptor la apagó. **Ausente = nadie ha elegido**, y
|
|
666
|
+
* entonces se miran todos; un `false` es una elección.
|
|
667
|
+
*/
|
|
668
|
+
ajustes: AjustesDeDispositivos;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Los ficheros que ESTA sesión ha tocado, y el parche de uno.
|
|
672
|
+
*
|
|
673
|
+
* `via` no es decoración, y son TRES cosas distintas: «git» es «comparado, y esto es lo
|
|
674
|
+
* que hay»; «sin-empezar» es que la sesión todavía no ha volcado ningún acto, así que no
|
|
675
|
+
* ha tocado nada y se sabe; «sin-marca» es que NO se sabe —la sesión se abrió sin git
|
|
676
|
+
* usable, o antes de que esto existiera—. Fundir las tres en una lista vacía haría que
|
|
677
|
+
* «todavía no has hecho nada» y «no se puede saber» se leyeran igual, y la segunda haría
|
|
678
|
+
* creer que un turno no escribió cuando lo que pasa es que no hay con qué comparar.
|
|
679
|
+
*/
|
|
680
|
+
/**
|
|
681
|
+
* Lo que ha tocado la sesión. `via` dice CÓMO se ha medido, y desde el 10-09-2026 son
|
|
682
|
+
* cuatro y no tres: `git` es atribución por COMMIT (lo que hizo esta sesión) y
|
|
683
|
+
* `desde-apertura` es la medida vieja —todo lo que ha cambiado en la copia desde que se
|
|
684
|
+
* abrió, de quien sea—, que es lo único posible en una sesión sin sello. Colapsarlas
|
|
685
|
+
* dejaría la pestaña rotulada «Sesión» sobre el trabajo de una tarea de fondo, que es el
|
|
686
|
+
* fallo que se vio en pantalla.
|
|
687
|
+
*/
|
|
688
|
+
| {
|
|
689
|
+
clase: "revision";
|
|
690
|
+
via: "git" | "desde-apertura" | "sin-marca" | "sin-empezar";
|
|
691
|
+
ficheros: FicheroTocado[];
|
|
692
|
+
/** Commits de OTRAS sesiones entre los de esta: la lista es exacta, un parche puede
|
|
693
|
+
* traer hunks ajenos. Ausente = ninguno, o no se pudo medir. */
|
|
694
|
+
mezclados?: number;
|
|
695
|
+
} | {
|
|
696
|
+
clase: "parche";
|
|
697
|
+
ruta: string;
|
|
698
|
+
texto: string;
|
|
699
|
+
recortado: boolean;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* TODO lo pendiente de subir a CloudStudio del proyecto abierto (la pestaña Sincronización del
|
|
703
|
+
* panel), o por qué no se pudo medir. Lo que git aún no sigue va marcado `sinCommitear`.
|
|
704
|
+
*/
|
|
705
|
+
| {
|
|
706
|
+
clase: "pendientesDeSubida";
|
|
707
|
+
ficheros?: FicheroTocado[];
|
|
708
|
+
error?: string;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* El diff de UN fichero pendiente contra CloudStudio. `negado` = la ruta no se enseña (la
|
|
712
|
+
* regla del lector), y entonces no viaja texto.
|
|
713
|
+
*/
|
|
714
|
+
| {
|
|
715
|
+
clase: "parcheDeSubida";
|
|
716
|
+
ruta: string;
|
|
717
|
+
texto: string;
|
|
718
|
+
recortado: boolean;
|
|
719
|
+
negado?: string;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Lo que cambió en el MODELO de un `.xne` de Revisión (`core/diffDeColecciones.ts`), entre el
|
|
723
|
+
* mismo «antes» que su parche y ahora. Sin `cambios` y con `error` si no se pudo
|
|
724
|
+
* reconstruir; `cambios` vacío es «ningún cambio que el modelo vea».
|
|
725
|
+
*/
|
|
726
|
+
| {
|
|
727
|
+
clase: "modeloDelCambio";
|
|
728
|
+
ruta: string;
|
|
729
|
+
cambios?: CambiosDeUnaColeccion[];
|
|
730
|
+
error?: string;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* El árbol del proyecto abierto (pestaña Ficheros): rutas relativas, ordenadas y ya
|
|
734
|
+
* filtradas por la misma regla que ve el agente (`agent/grafo/arbolDeProyecto.ts`). `error`
|
|
735
|
+
* solo si no se pudo listar, y entonces `rutas` va vacía. Y el contenido de UN fichero,
|
|
736
|
+
* de solo lectura: sin `texto` si es binario o si la ruta se rechazó, con el motivo.
|
|
737
|
+
*/
|
|
738
|
+
| {
|
|
739
|
+
clase: "arbol";
|
|
740
|
+
rutas: string[];
|
|
741
|
+
recortado: boolean;
|
|
742
|
+
error?: string;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* El modelo XOne del proyecto abierto (pestaña Colecciones), del MISMO índice que
|
|
746
|
+
* `xone_navegacion`: rutas virtuales y nombres, nunca rutas de la máquina. Sin `foto` y con
|
|
747
|
+
* `error` si no se pudo leer.
|
|
748
|
+
*/
|
|
749
|
+
| {
|
|
750
|
+
clase: "colecciones";
|
|
751
|
+
foto?: FotoDeColecciones;
|
|
752
|
+
error?: string;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Los planes del proyecto abierto (`.xonecode/planes/`, pestaña Planes): sus ficheros, las
|
|
756
|
+
* tareas leídas de su `TASKS.md` y el texto de su `PLAN.md`. Es lo que el plan DICE —estado y
|
|
757
|
+
* casillas las marca el modelo—. Sin `planes` y con `error` si no se pudo leer.
|
|
758
|
+
*/
|
|
759
|
+
| {
|
|
760
|
+
clase: "planes";
|
|
761
|
+
planes?: PlanEnDisco[];
|
|
762
|
+
error?: string;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* El gestor de tareas del proyecto abierto (IXCODE-11, panel del proyecto): UN mensaje con
|
|
766
|
+
* campos opcionales, como `planes`, y cada acción del cliente rellena el suyo. `error` dice
|
|
767
|
+
* QUÉ acción falló, porque el panel espera la respuesta de una en concreto. Nunca viaja un
|
|
768
|
+
* correo, un token ni una ruta de la máquina: del asignado, solo el nombre visible.
|
|
769
|
+
*/
|
|
770
|
+
| {
|
|
771
|
+
clase: "gestor";
|
|
772
|
+
/** `admiteMias` (IXCODE-15): si el gestor VINCULADO sabe filtrar «asignadas a mí». Se
|
|
773
|
+
* decidió AL VINCULAR y se lee del `config.json`, sin red. Viaja SIEMPRE con vínculo y
|
|
774
|
+
* nunca sin él. */
|
|
775
|
+
estado?: {
|
|
776
|
+
conectores: string[];
|
|
777
|
+
vinculo?: VinculoDelCable;
|
|
778
|
+
admiteMias?: boolean;
|
|
779
|
+
};
|
|
780
|
+
sitios?: {
|
|
781
|
+
conector: string;
|
|
782
|
+
lista: {
|
|
783
|
+
id: string;
|
|
784
|
+
nombre: string;
|
|
785
|
+
}[];
|
|
786
|
+
};
|
|
787
|
+
proyectos?: {
|
|
788
|
+
sitio: string;
|
|
789
|
+
lista: {
|
|
790
|
+
clave: string;
|
|
791
|
+
nombre: string;
|
|
792
|
+
}[];
|
|
793
|
+
};
|
|
794
|
+
/** IXCODE-15: la respuesta de `buscarProyectos`, con el `texto` que se buscó (para no
|
|
795
|
+
* pintar una respuesta vieja). En Notion `proyecto` es el id de la BASE: se manda a
|
|
796
|
+
* `describir`, NO a `vincular`. */
|
|
797
|
+
busqueda?: {
|
|
798
|
+
conector: string;
|
|
799
|
+
texto: string;
|
|
800
|
+
lista: {
|
|
801
|
+
proyecto: string;
|
|
802
|
+
nombre: string;
|
|
803
|
+
ruta?: string;
|
|
804
|
+
}[];
|
|
805
|
+
};
|
|
806
|
+
/** IXCODE-15: la respuesta de `describir`. `pedido` es lo que se mandó; con `esquema`, lo
|
|
807
|
+
* que hay que mandar a `vincular` es `esquema.proyecto` (el data source ya resuelto). Con
|
|
808
|
+
* `motivo`, esa base no vale como gestor —la acción salió bien; no es un `error`—. */
|
|
809
|
+
descripcion?: {
|
|
810
|
+
conector: string;
|
|
811
|
+
pedido: string;
|
|
812
|
+
} & ({
|
|
813
|
+
esquema: EsquemaDelProyecto;
|
|
814
|
+
} | {
|
|
815
|
+
motivo: string;
|
|
816
|
+
});
|
|
817
|
+
/** `cuando`: la hora del SERVIDOR a la que se preguntó, para decir «hace N min».
|
|
818
|
+
* `mias` viaja SOLO cuando la lista es la de «asignadas a mí»: el cliente pinta lo que
|
|
819
|
+
* el servidor contestó, no lo que pidió. */
|
|
820
|
+
pendientes?: {
|
|
821
|
+
cuando: number;
|
|
822
|
+
texto?: string;
|
|
823
|
+
mias?: true;
|
|
824
|
+
lista: TareaDelGestor[];
|
|
825
|
+
};
|
|
826
|
+
/** La descripción de UNA tarea, para desplegarla en su fila antes de empezar. De solo
|
|
827
|
+
* LECTURA: solo la clave y el texto, nada más de la ficha. */
|
|
828
|
+
ficha?: {
|
|
829
|
+
clave: string;
|
|
830
|
+
descripcion: string;
|
|
831
|
+
};
|
|
832
|
+
/** El texto que el compositor PROPONE: lo envía la persona, no sale solo. */
|
|
833
|
+
borrador?: {
|
|
834
|
+
clave: string;
|
|
835
|
+
texto: string;
|
|
836
|
+
};
|
|
837
|
+
/**
|
|
838
|
+
* Las transiciones disponibles de una tarea (Task 10, IXCODE-11), para «empezar» —con
|
|
839
|
+
* `transicion`— y para «cerrar». `propuesta` es el id que `transicionPropuesta` sugiere
|
|
840
|
+
* (la persona puede elegir otra o ninguna); ausente si ninguna encaja.
|
|
841
|
+
*/
|
|
842
|
+
transiciones?: {
|
|
843
|
+
clave: string;
|
|
844
|
+
para: "empezar" | "cerrar";
|
|
845
|
+
lista: TransicionDelGestor[];
|
|
846
|
+
propuesta?: string;
|
|
847
|
+
};
|
|
848
|
+
/**
|
|
849
|
+
* El comentario de cierre PROPUESTO para la tarea de la sesión ABIERTA: lo compone
|
|
850
|
+
* `comentarioDeCierre` desde lo que el harness sabe de la sesión (`datosDeCierre`). La
|
|
851
|
+
* persona lo EDITA antes de mandar `cerrar`; nada se escribe todavía.
|
|
852
|
+
*/
|
|
853
|
+
cierre?: {
|
|
854
|
+
clave: string;
|
|
855
|
+
comentario: string;
|
|
856
|
+
};
|
|
857
|
+
/**
|
|
858
|
+
* El resultado de `cerrar`: se llega aquí solo si `comentar` no falló —si falla, sale
|
|
859
|
+
* `error` en su lugar, así que `comento` es siempre `true`—, y `transicion` viaja SOLO
|
|
860
|
+
* si además se aplicó una. Si la transición pedida FALLÓ, su motivo va en
|
|
861
|
+
* `falloDeTransicion` (y `transicion` no viaja): el comentario ya está escrito, y un
|
|
862
|
+
* `error` a secas invitaría a repetir el cierre y comentar dos veces.
|
|
863
|
+
*/
|
|
864
|
+
cerrado?: {
|
|
865
|
+
clave: string;
|
|
866
|
+
comento: boolean;
|
|
867
|
+
transicion?: string;
|
|
868
|
+
falloDeTransicion?: string;
|
|
869
|
+
};
|
|
870
|
+
/** `clave` solo en el de `ficha`: dice de QUÉ tarea es la descripción que no se pudo leer.
|
|
871
|
+
* IXCODE-15: `texto` solo en el de `buscarProyectos` (QUÉ búsqueda falló) y `pedido` solo en
|
|
872
|
+
* el de `describir` (QUÉ base): el cliente no pinta el fallo de una búsqueda o base que ya
|
|
873
|
+
* no tiene delante. */
|
|
874
|
+
error?: {
|
|
875
|
+
accion: string;
|
|
876
|
+
motivo: string;
|
|
877
|
+
clave?: string;
|
|
878
|
+
texto?: string;
|
|
879
|
+
pedido?: string;
|
|
880
|
+
};
|
|
881
|
+
} | ({
|
|
882
|
+
clase: "fichero";
|
|
883
|
+
} & FicheroDelProyecto)
|
|
884
|
+
/**
|
|
885
|
+
* La respuesta a guardar un fichero desde el editor de la pestaña Ficheros: con `huella` se
|
|
886
|
+
* escribió y esa es la nueva; con `error`, no se tocó nada. Va a TODOS los clientes: otra pestaña
|
|
887
|
+
* con el mismo fichero abierto se entera de que el disco cambió.
|
|
888
|
+
*/
|
|
889
|
+
| {
|
|
890
|
+
clase: "ficheroGuardado";
|
|
891
|
+
ruta: string;
|
|
892
|
+
id: string;
|
|
893
|
+
huella?: string;
|
|
894
|
+
error?: string;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Lo que pasó al llevar un fichero guardado al aparato de la sesión (recarga en caliente). Va
|
|
898
|
+
* SIEMPRE después de su `ficheroGuardado` y aparte: el guardado no depende del aparato. `texto`
|
|
899
|
+
* es la frase hecha (`core/recargaEnCaliente.ts#textoDeRecarga`); `tipo`, cómo se aplicó.
|
|
900
|
+
*/
|
|
901
|
+
| {
|
|
902
|
+
clase: "recargaEnAparato";
|
|
903
|
+
ruta: string;
|
|
904
|
+
estado: "aplicada" | "relanzar" | "relanzada" | "sin-app" | "desplegando" | "desplegada" | "ocupado" | "no-aplica" | "fallo";
|
|
905
|
+
tipo?: "coleccion" | "js" | "css" | "relanzar" | "no-aplica";
|
|
906
|
+
texto: string;
|
|
907
|
+
}
|
|
908
|
+
/** La base de comparación de un fichero, para las marcas del margen del editor. */
|
|
909
|
+
| ({
|
|
910
|
+
clase: "baseDeFichero";
|
|
911
|
+
} & BaseDelFichero)
|
|
912
|
+
/**
|
|
913
|
+
* El estado de sincronización del proyecto abierto (pestaña CloudStudio). Los campos van en
|
|
914
|
+
* `EstadoDeSync`, aquí arriba, para poder compararlos con los del cliente.
|
|
915
|
+
*/
|
|
916
|
+
| ({
|
|
917
|
+
clase: "sync";
|
|
918
|
+
} & EstadoDeSync)
|
|
919
|
+
/**
|
|
920
|
+
* El contenido de un ARTEFACTO de la sesión, con la MISMA forma que un fichero del
|
|
921
|
+
* proyecto — a propósito: así los visores del cliente son los de la pestaña Ficheros y no
|
|
922
|
+
* una segunda familia de componentes para lo mismo. La `ruta` que trae es la VIRTUAL
|
|
923
|
+
* (`/artefactos/<nombre>`), que es la que el cliente ya conoce por el acto.
|
|
924
|
+
*
|
|
925
|
+
* El HTML no viaja por aquí para VERSE —eso lo pinta un iframe contra `GET /artefacto`,
|
|
926
|
+
* que es la única forma de darle un documento—, sino para leer su fuente cuando se pide.
|
|
927
|
+
*/
|
|
928
|
+
| ({
|
|
929
|
+
clase: "artefacto";
|
|
930
|
+
} & FicheroDelProyecto)
|
|
931
|
+
/**
|
|
932
|
+
* Cómo va el paso de receta que se está EJECUTANDO, o cómo acabó.
|
|
933
|
+
*
|
|
934
|
+
* Va a TODOS los clientes, como la foto de la máquina y por lo mismo: la máquina es la
|
|
935
|
+
* misma para todos, y un `sdkmanager` corriendo lo está para las dos pestañas. `lineas` es
|
|
936
|
+
* la COLA del log —lo último, no todo—: un `sdkmanager` verboso son miles de líneas y el
|
|
937
|
+
* cable no es un sitio donde guardarlas.
|
|
938
|
+
*/
|
|
939
|
+
| {
|
|
940
|
+
clase: "instalacion";
|
|
941
|
+
receta: string;
|
|
942
|
+
paso: number;
|
|
943
|
+
titulo: string;
|
|
944
|
+
estado: "corriendo" | "ok" | "fallo" | "cancelada" | "colgada";
|
|
945
|
+
lineas: string[];
|
|
946
|
+
ms: number;
|
|
947
|
+
motivo?: string;
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* El veredicto de «¿se puede lanzar la app del proyecto abierto, en su dispositivo?».
|
|
951
|
+
*
|
|
952
|
+
* **Va a la consola que lo PIDIÓ, no a todos los clientes** — la regla contraria a
|
|
953
|
+
* `dispositivos` e `instalacion`, y no por descuido: la máquina es la misma para todos, pero
|
|
954
|
+
* el PROYECTO no. Es el reparto de `revision` y `arbol`: se pide, se contesta, y NO entra en
|
|
955
|
+
* la ráfaga de bienvenida, porque una pestaña que acaba de abrirse no tiene por qué recibir
|
|
956
|
+
* el veredicto de un proyecto que a lo mejor ya no es el suyo.
|
|
957
|
+
*
|
|
958
|
+
* **`faltas` son FRASES ya escritas** (`core/puedeLanzarse.ts#motivoDeBloqueo`), no las causas
|
|
959
|
+
* crudas: el cliente no es fuente sobre qué se puede lanzar, y componer aquí «falta el
|
|
960
|
+
* framework en tal dispositivo» sería una segunda redacción de la misma regla, que es donde
|
|
961
|
+
* las dos divergen. `listo` es `faltas.length === 0` y viaja igualmente porque es lo que
|
|
962
|
+
* decide si el botón se pinta.
|
|
963
|
+
*/
|
|
964
|
+
| {
|
|
965
|
+
clase: "lanzable";
|
|
966
|
+
/** El nombre del proyecto abierto. Un SEGMENTO, no una ruta: `sinRutas`. */
|
|
967
|
+
proyecto: string;
|
|
968
|
+
listo: boolean;
|
|
969
|
+
/** Vacío cuando `listo`. Una LISTA y no la primera: se arregla lo que falta una a una. */
|
|
970
|
+
faltas: string[];
|
|
971
|
+
/**
|
|
972
|
+
* El nombre de la app, el que dice el `name=` de `app.ini`. Ausente = no consta, y sin
|
|
973
|
+
* él no hay a qué lanzar: `launchApplication` la pide por nombre.
|
|
974
|
+
*/
|
|
975
|
+
app?: string;
|
|
976
|
+
/**
|
|
977
|
+
* El dispositivo de la sesión tal y como salió de la última MEDIDA —id, nombre,
|
|
978
|
+
* plataforma y clase, y nada más—, que es la foto que ya viaja en `alta.dispositivoActivo`
|
|
979
|
+
* y en `sesiones[].dispositivo`. Ausente = ninguno elegido, o uno que ya no está.
|
|
980
|
+
*/
|
|
981
|
+
dispositivo?: DispositivoElegido;
|
|
982
|
+
/**
|
|
983
|
+
* CUÁNDO se midió esto. Un veredicto sin fecha es una promesa sin fecha: el framework se
|
|
984
|
+
* mide al conectar y al pulsar «volver a mirar», así que un «todo listo» de hace media
|
|
985
|
+
* hora sobre un aparato que se acaba de desenchufar es exactamente el botón muerto que
|
|
986
|
+
* esta pestaña existe para no pintar.
|
|
987
|
+
*/
|
|
988
|
+
medido: string;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Cómo va el lanzamiento de la app, o cómo acabó. Va a la consola que lo pidió, por lo mismo
|
|
992
|
+
* que `lanzable`.
|
|
993
|
+
*
|
|
994
|
+
* **`lineas` es la COLA del recorrido y no todo**: lo que suelta `adb` al subir un ZIP son
|
|
995
|
+
* miles de líneas, y este cable no es un sitio donde guardarlas. `ms` son los milisegundos
|
|
996
|
+
* desde que arrancó, y viaja porque un recorrido sin tiempo se lee como un cuelgue.
|
|
997
|
+
*
|
|
998
|
+
* `motivo` solo cuando lo hay: en `ok` no hay nada que decir, y un `motivo: ""` invitaría a
|
|
999
|
+
* pintar una línea vacía al lado del visto bueno.
|
|
1000
|
+
*/
|
|
1001
|
+
| {
|
|
1002
|
+
clase: "lanzamiento";
|
|
1003
|
+
/** El nombre del proyecto, si se sabe CUÁL. Ausente = no había ninguno que nombrar. */
|
|
1004
|
+
proyecto?: string;
|
|
1005
|
+
dispositivo?: DispositivoElegido;
|
|
1006
|
+
fase: FaseDelLanzamiento;
|
|
1007
|
+
estado: EstadoDelLanzamiento;
|
|
1008
|
+
lineas: string[];
|
|
1009
|
+
ms: number;
|
|
1010
|
+
motivo?: string;
|
|
1011
|
+
}
|
|
1012
|
+
/** Lo que ofrece un motor externo. `error` en vez de una lista vacía muda: un desplegable
|
|
1013
|
+
* vacío sin motivo se lee como que la ventana está rota. */
|
|
1014
|
+
| {
|
|
1015
|
+
clase: "modelosDeMotor";
|
|
1016
|
+
motor: string;
|
|
1017
|
+
modelos: {
|
|
1018
|
+
id: string;
|
|
1019
|
+
nombre: string;
|
|
1020
|
+
}[];
|
|
1021
|
+
error?: string;
|
|
1022
|
+
}
|
|
1023
|
+
/** El diagnóstico de Node de Ajustes → General (`core/diagnosticoDeNode.ts`): una foto, sin rutas de la máquina. */
|
|
1024
|
+
| {
|
|
1025
|
+
clase: "diagnosticoNode";
|
|
1026
|
+
diagnostico: DiagnosticoDeNode;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* El diseño vinculado de un proyecto: `vinculo` (null = sin vínculo), los `proyectos` de Stitch para elegir, las
|
|
1030
|
+
* `pantallas` con miniatura, o un `error`. Cada mensaje trae solo lo que se pidió. `proyecto` = de qué proyecto XOne.
|
|
1031
|
+
*/
|
|
1032
|
+
| {
|
|
1033
|
+
clase: "diseno";
|
|
1034
|
+
proyecto?: string;
|
|
1035
|
+
vinculo?: {
|
|
1036
|
+
proyecto: string;
|
|
1037
|
+
nombre: string;
|
|
1038
|
+
} | null;
|
|
1039
|
+
proyectos?: {
|
|
1040
|
+
name: string;
|
|
1041
|
+
title: string;
|
|
1042
|
+
}[];
|
|
1043
|
+
pantallas?: {
|
|
1044
|
+
name: string;
|
|
1045
|
+
title: string;
|
|
1046
|
+
miniatura?: string;
|
|
1047
|
+
}[];
|
|
1048
|
+
error?: string;
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* La foto de los motores locales (Claude Code, Codex, OpenCode) para Ajustes → Motores locales:
|
|
1052
|
+
* si están, con qué sesión, la última prueba y el login en curso. Entera en cada cambio, como
|
|
1053
|
+
* `dispositivos`. Ni rutas, ni el correo de la cuenta, ni el enlace de autorización.
|
|
1054
|
+
*/
|
|
1055
|
+
| {
|
|
1056
|
+
clase: "motoresLocales";
|
|
1057
|
+
motores: EstadoDeMotorLocal[];
|
|
1058
|
+
} | {
|
|
1059
|
+
clase: "secreto";
|
|
1060
|
+
pregunta: string;
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* El alta que FALTA, para el wizard del navegador. `pasos` sale de
|
|
1064
|
+
* `vestibulo.ts#pasosPendientes`, que los calcula preguntándole al sistema y nunca a una
|
|
1065
|
+
* marca de «primer arranque»; vacío significa que no hay alta que hacer y el cliente no
|
|
1066
|
+
* pinta el wizard — pero puede seguir sin haber proyecto abierto, ver `proyectoAbierto`
|
|
1067
|
+
* más abajo. Cambio de rumbo del usuario: «proyecto» ya NO puede aparecer en `pasos`
|
|
1068
|
+
* (sigue siendo un `paso` válido del lado del `MensajeDelCliente`, para abrir uno desde
|
|
1069
|
+
* la barra lateral, pero no bloquea la entrada al dashboard).
|
|
1070
|
+
*
|
|
1071
|
+
* `proyectos` y `ramas` llegan vacíos hasta que hay entorno (y proyecto) elegidos: son
|
|
1072
|
+
* dos consultas a CloudStudio y no se pueden inventar. Lista vacía es «todavía no lo
|
|
1073
|
+
* sé», que es la verdad, y no un dato de relleno.
|
|
1074
|
+
*
|
|
1075
|
+
* **La clave de API NO viaja aquí.** El paso de cuenta lo conduce
|
|
1076
|
+
* `vestibulo.pasoDeCuenta()` sobre `seleccionar` y `leerSecreto`, así que la clave sigue
|
|
1077
|
+
* entrando por el mensaje de clase «secreto» y por ninguno más — el mismo trato que
|
|
1078
|
+
* documentan `consolaWeb.ts#leerSecreto` y la cabecera de `Wizard.tsx`.
|
|
1079
|
+
*/
|
|
1080
|
+
| {
|
|
1081
|
+
clase: "alta";
|
|
1082
|
+
pasos: PasoDelVestibulo[];
|
|
1083
|
+
/**
|
|
1084
|
+
* **Qué está preparando el arranque AHORA. Ausente = ya está listo.**
|
|
1085
|
+
*
|
|
1086
|
+
* Existe porque `proyectos: []` no distingue «todavía no lo he preguntado» de «no hay
|
|
1087
|
+
* ninguno», y de esa ambigüedad salía un Escritorio que entraba vacío y se rellenaba
|
|
1088
|
+
* delante del usuario. Con este campo el cliente se queda en el lienzo hasta que el
|
|
1089
|
+
* arranque termina, y mientras puede DECIR qué hace en vez de estar un segundo y medio
|
|
1090
|
+
* en silencio.
|
|
1091
|
+
*
|
|
1092
|
+
* Es la FASE y no un booleano por lo mismo que `Fase` en el turno: un «espera» sin
|
|
1093
|
+
* decir a qué se parece a estar colgado. Y va como texto ya redactado por el servidor,
|
|
1094
|
+
* que es quien sabe el nombre del entorno al que está llamando.
|
|
1095
|
+
*
|
|
1096
|
+
* Lo que acota la espera es un PLAZO (`MS_DE_PREPARACION`), no la confianza en que el
|
|
1097
|
+
* MCP conteste: si no contesta, se entra igual y el `aviso` dice por qué. Medido: con
|
|
1098
|
+
* un MCP que descarta paquetes, sin plazo el lienzo se queda para siempre.
|
|
1099
|
+
*/
|
|
1100
|
+
preparando?: string;
|
|
1101
|
+
proveedores: {
|
|
1102
|
+
id: string;
|
|
1103
|
+
nombre: string;
|
|
1104
|
+
}[];
|
|
1105
|
+
entornos: OpcionDeEntorno[];
|
|
1106
|
+
/**
|
|
1107
|
+
* Los entornos REGISTRADOS de verdad (`settings.json`), que no son los OFRECIDOS de
|
|
1108
|
+
* `entornos` —esa es la lista fija de los dos oficiales más «otro», y sirve para
|
|
1109
|
+
* prerrellenar la URL del alta—. Hacía falta desde que el registro deduce la
|
|
1110
|
+
* identidad del host: un on-premise registrado no aparece en la ofrecida por ningún
|
|
1111
|
+
* lado, y la barra lateral llevaba enseñando la ofrecida como si fuera ésta.
|
|
1112
|
+
*/
|
|
1113
|
+
registrados: EntornoRegistrado[];
|
|
1114
|
+
/**
|
|
1115
|
+
* El id del proyecto ABIERTO ahora mismo, y el de su sesión.
|
|
1116
|
+
*
|
|
1117
|
+
* `proyectoAbierto` (booleano, más abajo) dice SI hay uno; estos dicen CUÁL, que es
|
|
1118
|
+
* otra pregunta y la que necesita la barra para marcar la fila. Se resuelven
|
|
1119
|
+
* comparando la raíz de la consola abierta con la que le tocaría a cada proyecto
|
|
1120
|
+
* (`raizDeProyecto`), no guardando un id aparte: dos fuentes para lo mismo divergen
|
|
1121
|
+
* en cuanto una se olvide de actualizarse.
|
|
1122
|
+
*
|
|
1123
|
+
* `sesionActiva` puede faltar con un proyecto abierto, y no es un fallo: el id de
|
|
1124
|
+
* sesión no existe hasta que se vuelca el primer acto (`ConsolaDeProyecto.sesion`),
|
|
1125
|
+
* así que una sesión recién empezada todavía no tiene nada que marcar — igual que
|
|
1126
|
+
* tampoco aparece en la lista de sesiones guardadas.
|
|
1127
|
+
*/
|
|
1128
|
+
proyectoActivo?: string;
|
|
1129
|
+
sesionActiva?: string;
|
|
1130
|
+
/**
|
|
1131
|
+
* Con qué dispositivo trabaja la sesión abierta. Ausente = ninguno elegido.
|
|
1132
|
+
*
|
|
1133
|
+
* Viaja la FOTO y no solo el id porque los ids no son estables —`emulator-5554` es un
|
|
1134
|
+
* puerto, y un teléfono se desenchufa—: al reabrir una sesión, el selector puede decir
|
|
1135
|
+
* «iPhone 16 · no está ahora» en vez de un serial crudo o nada. Si está a mano AHORA
|
|
1136
|
+
* no se manda: eso lo resuelve el cliente contra la última medida, que es la única que
|
|
1137
|
+
* lo sabe en este instante.
|
|
1138
|
+
*/
|
|
1139
|
+
dispositivoActivo?: {
|
|
1140
|
+
id: string;
|
|
1141
|
+
nombre: string;
|
|
1142
|
+
plataforma: "android" | "ios";
|
|
1143
|
+
clase: "emulador" | "simulador" | "fisico";
|
|
1144
|
+
};
|
|
1145
|
+
/**
|
|
1146
|
+
* La sesión abierta es una RELECTURA: se reabrió y del hilo no queda memoria
|
|
1147
|
+
* (`ConsolaDeProyecto.historica`, que lo PREGUNTA al checkpointer del proyecto en vez
|
|
1148
|
+
* de darlo por hecho — una sesión con checkpoint continúa y no lleva esta marca; la
|
|
1149
|
+
* llevan las de antes de que hubiera checkpointer y aquellas cuyo primer turno nunca
|
|
1150
|
+
* llegó a correr). Deja de serlo en el primer turno nuevo,
|
|
1151
|
+
* y el alta se reanuncia en ese flanco. Solo viaja cuando es cierto: ausente es «no».
|
|
1152
|
+
* Sin esto el cliente pintaba una conversación y un compositor activo como si se
|
|
1153
|
+
* pudiera seguir hablando, que es lo que el propio `CLAUDE.md` dice que no pasa.
|
|
1154
|
+
*/
|
|
1155
|
+
historica?: boolean;
|
|
1156
|
+
/**
|
|
1157
|
+
* El modo de escritura de la SESIÓN abierta: `supervisado` (cada escritura con su
|
|
1158
|
+
* diff) o `autonomo` (se aplican solas). Ver `core/modoDeEscritura.ts`.
|
|
1159
|
+
*
|
|
1160
|
+
* **Ausente = no hay sesión abierta**, y por eso la pastilla no se pinta: un control
|
|
1161
|
+
* sin dato detrás no se pinta. Nunca significa «supervisado» — una sesión abierta
|
|
1162
|
+
* siempre trae el suyo, porque el servidor resuelve la omisión antes de emitir.
|
|
1163
|
+
*
|
|
1164
|
+
* Viaja en el alta y no solo en el aviso del turno porque quien se sienta hoy tiene
|
|
1165
|
+
* que saber en qué modo está ANTES de pedir nada, no después con los ficheros ya
|
|
1166
|
+
* cambiados. Y viaja el MODO y no un booleano porque es lo que la pastilla pinta.
|
|
1167
|
+
*/
|
|
1168
|
+
modoDeEscritura?: "supervisado" | "autonomo";
|
|
1169
|
+
/**
|
|
1170
|
+
* Lo que YA estaba sin commitear en el proyecto cuando se abrió esta consola
|
|
1171
|
+
* (`agent/sesiones/gitSync.ts#trabajoSinCommitear`, medido en el instante de abrir).
|
|
1172
|
+
*
|
|
1173
|
+
* Ausente = no hay nada que decir, y son las tres respuestas que se callan a
|
|
1174
|
+
* propósito: el árbol estaba limpio, no hay git con qué mirar (todo proyecto
|
|
1175
|
+
* OFFLINE), o la medida falló. Ninguna de las tres es un aviso.
|
|
1176
|
+
*
|
|
1177
|
+
* Va la lista y no un número: quien lo lee tiene que poder reconocer si eso es suyo,
|
|
1178
|
+
* de otra sesión o de una tarea, y un contador a secas es el aviso que enseña a
|
|
1179
|
+
* ignorar los avisos. `ficheros` viene ACOTADA —el alta se reemite en los dos flancos
|
|
1180
|
+
* de cada turno y la frase no puede llevar trescientos nombres— y `total` es la cifra
|
|
1181
|
+
* entera, que es lo que impide leer los que caben como si fueran todos.
|
|
1182
|
+
*
|
|
1183
|
+
* La medida es del instante de ABRIR y no cambia con los reanuncios, a propósito: así
|
|
1184
|
+
* no puede contar como «de otro» lo que esta misma sesión —o esta tarea— acabe de
|
|
1185
|
+
* escribir.
|
|
1186
|
+
*/
|
|
1187
|
+
trabajoAlAbrir?: {
|
|
1188
|
+
ficheros: string[];
|
|
1189
|
+
total: number;
|
|
1190
|
+
};
|
|
1191
|
+
/**
|
|
1192
|
+
* De qué entorno son los `proyectos` de este mensaje. Ausente = todavía de ninguno
|
|
1193
|
+
* (nadie ha elegido y no había ninguno registrado que poblar). El cliente lo NECESITA
|
|
1194
|
+
* para no tener que asumir «el primero de la lista», que es lo que hacía y era una
|
|
1195
|
+
* suposición que se rompía en cuanto había dos.
|
|
1196
|
+
*/
|
|
1197
|
+
entornoActivo?: string;
|
|
1198
|
+
/**
|
|
1199
|
+
* Los proyectos del entorno, con las SESIONES que ya tiene su copia local (vacío si
|
|
1200
|
+
* no se ha bajado nunca). Van en el mismo mensaje porque la barra los pinta juntos:
|
|
1201
|
+
* un proyecto sin sus sesiones es una fila que no se puede abrir por donde se dejó.
|
|
1202
|
+
*/
|
|
1203
|
+
proyectos: {
|
|
1204
|
+
id: string;
|
|
1205
|
+
nombre: string;
|
|
1206
|
+
/**
|
|
1207
|
+
* Compartido CONTIGO por otra persona (`shared` de `studio_list_projects`).
|
|
1208
|
+
* **Ausente no es «es tuyo»**: es que el servidor no lo dijo, y entonces no se
|
|
1209
|
+
* pinta etiqueta ninguna — afirmar que todos son propios porque un endpoint viejo
|
|
1210
|
+
* calló sería la clase de dato inventado que esta consola no consiente.
|
|
1211
|
+
*
|
|
1212
|
+
* Es un booleano y NO el correo del propietario, que viaja en la misma respuesta
|
|
1213
|
+
* (`suser`): para distinguir lo propio de lo compartido basta con esto, y quién lo
|
|
1214
|
+
* compartió es un dato de una persona que esta pantalla no necesita.
|
|
1215
|
+
*/
|
|
1216
|
+
compartido?: boolean;
|
|
1217
|
+
/** Fecha ISO del último acceso (`last` de `studio_list_projects`). Ausente = no
|
|
1218
|
+
* consta — no todos los proyectos lo traen. */
|
|
1219
|
+
ultimoAcceso?: string;
|
|
1220
|
+
sesiones?: SesionDelCable[];
|
|
1221
|
+
/** La copia local YA existe: se puede abrir sin bajar nada ni preguntar rama. */
|
|
1222
|
+
local?: boolean;
|
|
1223
|
+
/** La rama de la que se bajó la copia local. Ausente = sin copia, o no consta. */
|
|
1224
|
+
rama?: string;
|
|
1225
|
+
/**
|
|
1226
|
+
* La copia local tiene un icono de app que se puede enseñar (`app.ini`), servido por
|
|
1227
|
+
* `RUTA_ICONO_DEL_PROYECTO`. Un booleano y no la ruta: ninguna ruta sale del host.
|
|
1228
|
+
* Ausente = sin copia, sin icono, o no consta; la barra pinta entonces la carpeta.
|
|
1229
|
+
*/
|
|
1230
|
+
icono?: true;
|
|
1231
|
+
/**
|
|
1232
|
+
* Alguna sesión de este proyecto tiene un turno EN MARCHA ahora mismo.
|
|
1233
|
+
*
|
|
1234
|
+
* No se DERIVA de `sesiones[].trabajando`, y ahí está el motivo de que exista: una
|
|
1235
|
+
* sesión nueva no tiene fila en el índice hasta que vuelca su primer acto —o sea al
|
|
1236
|
+
* final del turno—, así que el caso más común (abrir, pedir algo, irse a otro
|
|
1237
|
+
* proyecto) no habría marcado ni la fila ni el proyecto, y en la barra no se vería
|
|
1238
|
+
* nada en ninguna parte.
|
|
1239
|
+
*
|
|
1240
|
+
* De aquí cuelga además que las OTRAS sesiones de ese proyecto no se puedan abrir
|
|
1241
|
+
* mientras dure: una copia de trabajo no aguanta dos conversaciones, y el servidor
|
|
1242
|
+
* lo declina (`motivoDeProyectoTrabajando`). Decirlo antes del clic es lo que evita
|
|
1243
|
+
* el botón muerto.
|
|
1244
|
+
*/
|
|
1245
|
+
trabajando?: true;
|
|
1246
|
+
}[];
|
|
1247
|
+
ramas: string[];
|
|
1248
|
+
/** El id del proyecto del que son las `ramas`. Ausente = no hay ramas, o no consta. */
|
|
1249
|
+
ramasDe?: string;
|
|
1250
|
+
/**
|
|
1251
|
+
* Qué falló en el paso anterior. Ausente = no falló nada.
|
|
1252
|
+
*
|
|
1253
|
+
* Viaja EN el alta y no solo como acto porque el fallo pertenece al paso que lo
|
|
1254
|
+
* produjo. Medido en el navegador: el acto de sistema aterriza en la Trayectoria —la
|
|
1255
|
+
* pestaña que el usuario no está mirando— mientras el wizard repinta el mismo paso
|
|
1256
|
+
* sin una palabra, que es exactamente el fallo mudo que se quería quitar.
|
|
1257
|
+
*/
|
|
1258
|
+
aviso?: string;
|
|
1259
|
+
/**
|
|
1260
|
+
* El saludo (`agent/config/persona.ts#nombreDePersona`). Viaja SUELTO en este mensaje, no
|
|
1261
|
+
* dentro de ningún acto: `Bienvenida.tsx` lo pinta y nada más, así que no entra en
|
|
1262
|
+
* el `.jsonl` de una sesión ni en el transcript. Ausente = sin nombre que saludar.
|
|
1263
|
+
*/
|
|
1264
|
+
nombre?: string;
|
|
1265
|
+
/**
|
|
1266
|
+
* Si hay un proyecto abierto AHORA MISMO en esta conexión. Hace falta desde que el
|
|
1267
|
+
* paso de proyecto salió del alta: antes, `pasos: []` solo pasaba con un proyecto
|
|
1268
|
+
* ya abierto, y esa implicación bastaba para que el cliente supiera si pintar la
|
|
1269
|
+
* maqueta completa o el alta. Ahora `pasos: []` pasa en cuanto cuenta y entorno
|
|
1270
|
+
* están resueltos, CON o SIN proyecto abierto —el proyecto se elige en la barra—,
|
|
1271
|
+
* así que hace falta decirlo aparte para que el centro sepa si esperar una elección
|
|
1272
|
+
* o pintar la sesión de verdad.
|
|
1273
|
+
*/
|
|
1274
|
+
proyectoAbierto: boolean;
|
|
1275
|
+
/**
|
|
1276
|
+
* El `modo` del `.xonecode/config.json` del proyecto abierto, para la pastilla de
|
|
1277
|
+
* la cabecera. **Ausente cuando no se sabe**, y eso incluye tres casos que no se
|
|
1278
|
+
* distinguen desde aquí: no hay proyecto abierto, el fichero no se pudo leer, o
|
|
1279
|
+
* lleva un valor que no es ninguno de los dos. Ausente NO significa «offline»:
|
|
1280
|
+
* pintar «offline» sobre un fichero que no se pudo leer sería afirmar lo que no se
|
|
1281
|
+
* sabe, que es la misma clase de mentira que un alias de color inventado. Es lo
|
|
1282
|
+
* único que se le extrae al config: ni la URL del entorno, ni el proyecto, ni la
|
|
1283
|
+
* rama, que son datos del despliegue y no tienen por qué acabar en el transcript.
|
|
1284
|
+
*/
|
|
1285
|
+
modo?: "offline" | "cloud";
|
|
1286
|
+
}
|
|
1287
|
+
/** El ÚNICO mensaje que lleva contenido de fichero: es el paso donde se DECIDE sobre él. */
|
|
1288
|
+
| {
|
|
1289
|
+
clase: "aprobacion";
|
|
1290
|
+
pendientes: PendienteDeAprobacion[];
|
|
1291
|
+
ficheros: Record<string, string>;
|
|
1292
|
+
diffs: Record<string, LineaDeDiff[]>;
|
|
1293
|
+
};
|
|
1294
|
+
/**
|
|
1295
|
+
* Un proveedor, tal y como lo ve el selector de modelos.
|
|
1296
|
+
*
|
|
1297
|
+
* `credencial` es literal y tiene TRES valores porque hay tres cosas distintas que decir:
|
|
1298
|
+
* «puesta» solo si la credencial está confirmada, «falta» solo si se sabe que no está, y
|
|
1299
|
+
* «nativa» para quien no necesita ninguna (Ollama local). Pintarle un punto rojo a Ollama
|
|
1300
|
+
* sería inventarse un problema, y uno verde, un permiso.
|
|
1301
|
+
*/
|
|
1302
|
+
/**
|
|
1303
|
+
* Un entorno ya registrado, con la elección de qué proyectos suyos se enseñan.
|
|
1304
|
+
*
|
|
1305
|
+
* `proyectos` AUSENTE no es «ninguno»: es que nadie lo ha dicho, y entonces la barra aplica
|
|
1306
|
+
* su omisión (los primeros `PROYECTOS_POR_OMISION`). Una lista vacía sí es una elección.
|
|
1307
|
+
*/
|
|
1308
|
+
export interface EntornoRegistrado extends OpcionDeEntorno {
|
|
1309
|
+
proyectos?: string[];
|
|
1310
|
+
/** Los fijados arriba de la barra (`Entorno.fijados`). Ausente = ninguno. */
|
|
1311
|
+
fijados?: string[];
|
|
1312
|
+
/** Cuántas carpetas de proyecto tiene en el workspace. Ausente = no se pudo mirar, que no
|
|
1313
|
+
* es cero: con cero la casilla de borrarlas no se ofrece. */
|
|
1314
|
+
copias?: number;
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Un proyecto de un entorno, para elegir si se enseña. Es menos de lo que lleva un proyecto
|
|
1318
|
+
* del `alta`: sin `sesiones`, porque una sesión es de la COPIA LOCAL y aquí solo se decide
|
|
1319
|
+
* qué aparece en la barra. Lo que no hace falta, no viaja.
|
|
1320
|
+
*/
|
|
1321
|
+
export interface ProyectoDeEntorno {
|
|
1322
|
+
id: string;
|
|
1323
|
+
nombre: string;
|
|
1324
|
+
/** Compartido contigo por otra persona. Ausente no es «es tuyo»: es que no se dijo. */
|
|
1325
|
+
compartido?: boolean;
|
|
1326
|
+
/** Fecha ISO del último acceso (`last` de `studio_list_projects`). Ausente = no consta. */
|
|
1327
|
+
ultimoAcceso?: string;
|
|
1328
|
+
}
|
|
1329
|
+
/** Un fichero de la sesión. `mas`/`menos` faltan en un binario: git no cuenta líneas ahí, y
|
|
1330
|
+
* poner cero diría que no cambió nada. */
|
|
1331
|
+
export interface FicheroTocado {
|
|
1332
|
+
ruta: string;
|
|
1333
|
+
clase: "nuevo" | "modificado" | "borrado";
|
|
1334
|
+
mas?: number;
|
|
1335
|
+
menos?: number;
|
|
1336
|
+
/** Hay cambios en este fichero que nadie ha commiteado, así que no se pueden atribuir a
|
|
1337
|
+
* esta sesión ni a otra (`agent/sesiones/sesionGit.ts#FicheroDeSesion`). Viaja para poder DECIRLO
|
|
1338
|
+
* en la fila: el turno en vuelo commitea al terminar, y esta es la única marca que
|
|
1339
|
+
* distingue «lo escribió esta sesión» de «esto está aquí y no consta de quién es». */
|
|
1340
|
+
sinCommitear?: true;
|
|
1341
|
+
/**
|
|
1342
|
+
* ¿Sigue pendiente de subir a CloudStudio? Lo decide el SERVIDOR en la misma foto que la
|
|
1343
|
+
* lista (`arranque.ts#marcarPendientes`), no el cliente cruzando dos mensajes que llegan en
|
|
1344
|
+
* momentos distintos. AUSENTE = no se pudo medir (proyecto sin CloudStudio, o la medida
|
|
1345
|
+
* falló), y entonces Revisión enseña todo en vez de esconder sobre una pregunta sin contestar.
|
|
1346
|
+
*/
|
|
1347
|
+
pendiente?: boolean;
|
|
1348
|
+
}
|
|
1349
|
+
/** Un fichero del proyecto tal como viaja. Redeclarado en `apps/web/src/tipos.ts`. */
|
|
1350
|
+
export interface FicheroDelProyecto {
|
|
1351
|
+
/** La ruta tal como se pidió, nunca la resuelta en disco. */
|
|
1352
|
+
ruta: string;
|
|
1353
|
+
texto?: string;
|
|
1354
|
+
recortado: boolean;
|
|
1355
|
+
binario: boolean;
|
|
1356
|
+
bytes: number;
|
|
1357
|
+
codificacion?: "utf-8" | "latin1";
|
|
1358
|
+
/**
|
|
1359
|
+
* El MIME, solo si la ruta es una imagen que el visor sabe pintar. Viaja aunque los bytes
|
|
1360
|
+
* NO vengan: es lo que distingue «una imagen demasiado grande» de «un binario cualquiera».
|
|
1361
|
+
*/
|
|
1362
|
+
mime?: string;
|
|
1363
|
+
/** La imagen entera, si cupo en el tope. Nunca recortada: media imagen no se abre. */
|
|
1364
|
+
base64?: string;
|
|
1365
|
+
/**
|
|
1366
|
+
* Solo en un markdown que enlaza imágenes del proyecto: el texto con esos enlaces apuntando a la
|
|
1367
|
+
* ruta que las sirve, para la VISTA (`arbolDeProyecto.ts#vistaDeMarkdown`). `texto` es la fuente.
|
|
1368
|
+
*/
|
|
1369
|
+
vista?: string;
|
|
1370
|
+
/**
|
|
1371
|
+
* El sha256 de los bytes en disco, solo con el texto ENTERO en UTF-8
|
|
1372
|
+
* (`arbolDeProyecto.ts#huellaDeContenido`). Vuelve al guardar: si el disco ya no coincide, no se
|
|
1373
|
+
* escribe nada.
|
|
1374
|
+
*/
|
|
1375
|
+
huella?: string;
|
|
1376
|
+
error?: string;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* La versión de un fichero contra la que el editor pinta sus marcas (`agent/sesiones/baseDeFichero.ts`).
|
|
1380
|
+
* `texto` = había una versión; `vacio` = en esa base no existía; `sinBase` = no hay con qué comparar,
|
|
1381
|
+
* y por qué. Redeclarado en `apps/web/src/tipos.ts`.
|
|
1382
|
+
*/
|
|
1383
|
+
export interface BaseDelFichero {
|
|
1384
|
+
ruta: string;
|
|
1385
|
+
base: "sesion" | "commit";
|
|
1386
|
+
texto?: string;
|
|
1387
|
+
vacio?: true;
|
|
1388
|
+
sinBase?: string;
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* El estado de sincronización del proyecto abierto (pestaña CloudStudio): de qué rama es y
|
|
1392
|
+
* cuántos ficheros quedan por subir. Redeclarado en `apps/web/src/tipos.ts`.
|
|
1393
|
+
*
|
|
1394
|
+
* **`proyecto` y `rama` ausentes no son «cero pendientes»**: son «este proyecto no está dado
|
|
1395
|
+
* de alta en CloudStudio» —o le falta la rama del alta—, que es un estado y no un contador a
|
|
1396
|
+
* cero. Son las dos preguntas que la pestaña tiene que poder contestar por separado, y por
|
|
1397
|
+
* eso no se rellenan con cadenas vacías.
|
|
1398
|
+
*
|
|
1399
|
+
* `pendientes` se mide contra la ref de seguimiento que dejó la última descarga
|
|
1400
|
+
* (`refs/remotes/cloudstudio/<rama>`), que es LA MISMA cuenta que da `/sync estado` —
|
|
1401
|
+
* `agent/sesiones/gitSync.ts#cambiosPendientes`, el mismo que decide qué sube el plan—. `error` solo
|
|
1402
|
+
* cuando no se pudo medir, y entonces `pendientes` no viene: un cero que nadie ha contado es
|
|
1403
|
+
* la cifra inventada de siempre.
|
|
1404
|
+
*
|
|
1405
|
+
* Es interfaz con nombre y no campos sueltos dentro de la unión por lo de siempre: los
|
|
1406
|
+
* campos de un mensaje EMBEBIDO en otro no se pueden comparar con `camposDeInterfaz`, y ese
|
|
1407
|
+
* es el test que vigila que el cliente no se quede con la mitad del contrato.
|
|
1408
|
+
*/
|
|
1409
|
+
/**
|
|
1410
|
+
* La foto del resumen de un proyecto, tal como vuelve en la respuesta de `accion: "resumen"`.
|
|
1411
|
+
*
|
|
1412
|
+
* `tareas` son los IDS de las tareas de la cola cuya raíz es la de este proyecto: la tarea no
|
|
1413
|
+
* lleva su entorno, así que filtrarla por id en el cliente dejaría pasar la de otro entorno.
|
|
1414
|
+
* `sync` es la MISMA medida que la banda de CloudStudio (`lecturaDeSync`), y AUSENTE cuando no
|
|
1415
|
+
* hay copia bajada — que no es lo mismo que «nada por subir».
|
|
1416
|
+
*/
|
|
1417
|
+
export interface FotoDelResumen {
|
|
1418
|
+
tareas: string[];
|
|
1419
|
+
sync?: EstadoDeSync;
|
|
1420
|
+
/**
|
|
1421
|
+
* El modo con que nacen las sesiones nuevas de ESTE proyecto (IXCODE-31). Presente solo con
|
|
1422
|
+
* copia bajada —sin ella no hay `config.json` que lo guarde—; `proyecto` ausente dentro es
|
|
1423
|
+
* «como el global», que no es lo mismo que no saberlo.
|
|
1424
|
+
*/
|
|
1425
|
+
modoDeEscritura?: {
|
|
1426
|
+
proyecto?: "supervisado" | "autonomo";
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
export interface EstadoDeSync {
|
|
1430
|
+
proyecto?: string;
|
|
1431
|
+
rama?: string;
|
|
1432
|
+
pendientes?: number;
|
|
1433
|
+
/**
|
|
1434
|
+
* De los `pendientes`, cuántos tocó ESTA sesión.
|
|
1435
|
+
*
|
|
1436
|
+
* Existe porque `pendientes` se mide contra la rama y la lista de Revisión contra la
|
|
1437
|
+
* sesión: son dos referencias distintas, así que las dos cifras pueden no tocarse. Medido
|
|
1438
|
+
* en el AppDemo del usuario el 16-09-2026, mirando la pantalla: la banda decía «3 ficheros
|
|
1439
|
+
* por subir» y la sesión de delante había hecho UN cambio —borrar un fichero que otra
|
|
1440
|
+
* había creado, así que el alta y el borrado se anulaban— que no entraba en el plan NI
|
|
1441
|
+
* PODÍA ENTRAR. Los dos números no discrepaban: eran de dos trabajos sin nada en común.
|
|
1442
|
+
*
|
|
1443
|
+
* **Ausente no es cero, y la diferencia es la de siempre.** Ausente = no se puede atribuir
|
|
1444
|
+
* (sin sesión abierta, o una sesión sin sello, que es la que solo se puede medir «desde que
|
|
1445
|
+
* abriste» y ahí dentro está el trabajo de cualquiera). Cero = se atribuyó y NINGUNO de los
|
|
1446
|
+
* pendientes es suyo, que es un hecho medido y justo el que hace falta para entender la
|
|
1447
|
+
* pantalla. Rellenar lo ausente con un cero diría «esta sesión no ha hecho nada» sobre una
|
|
1448
|
+
* sesión de la que no se sabe qué hizo.
|
|
1449
|
+
*/
|
|
1450
|
+
deLaSesion?: number;
|
|
1451
|
+
error?: string;
|
|
1452
|
+
}
|
|
1453
|
+
/**
|
|
1454
|
+
* Una tarea tal como viaja. **Sin la raíz del proyecto**: viajan su id y su nombre, que es
|
|
1455
|
+
* lo que la interfaz necesita — la ruta se queda en el host, igual que `Herramienta.ruta` de
|
|
1456
|
+
* `xcrun`/`devicectl` (`adb`/`emulator` sí cruzan, ver `InformeDeDispositivosDelCable`).
|
|
1457
|
+
* Redeclarada en `apps/web/src/tipos.ts`.
|
|
1458
|
+
*/
|
|
1459
|
+
export interface TareaDelCable {
|
|
1460
|
+
id: string;
|
|
1461
|
+
proyecto: string;
|
|
1462
|
+
proyectoNombre: string;
|
|
1463
|
+
titulo: string;
|
|
1464
|
+
peticion: string;
|
|
1465
|
+
encargo: string;
|
|
1466
|
+
adjuntos: {
|
|
1467
|
+
nombre: string;
|
|
1468
|
+
bytes: number;
|
|
1469
|
+
mime?: string;
|
|
1470
|
+
}[];
|
|
1471
|
+
estado: "nuevo" | "en-proceso" | "requiere-atencion" | "terminada";
|
|
1472
|
+
motivo?: string;
|
|
1473
|
+
sesion?: string;
|
|
1474
|
+
/** El id de la tarea ANTERIOR de su cadena (`Tarea.tras`): esta no arranca hasta que aquella termine. */
|
|
1475
|
+
tras?: string;
|
|
1476
|
+
creada: string;
|
|
1477
|
+
empezada?: string;
|
|
1478
|
+
acabada?: string;
|
|
1479
|
+
/**
|
|
1480
|
+
* Lo que la tarea AUTORIZÓ escribir sin que nadie lo aprobara, con ruta relativa al
|
|
1481
|
+
* proyecto (`core/tareas.ts#Tarea.autorizadas`). **No es lo mismo que lo que cambió en el
|
|
1482
|
+
* disco** —una ruta que las guardas de sitio rechazan sale aquí sin haberse escrito—: la
|
|
1483
|
+
* verdad sobre el disco la tiene la pestaña Revisión, con la ref de esta `sesion`. Ausente
|
|
1484
|
+
* = no consta (la tarea no llegó a correr un turno); `[]` = corrió y no autorizó ninguna.
|
|
1485
|
+
*/
|
|
1486
|
+
autorizadas?: string[];
|
|
1487
|
+
/**
|
|
1488
|
+
* El historial de lo que el desarrollador contestó mientras la tarea esperaba feedback
|
|
1489
|
+
* (`core/tareas.ts#Tarea.feedback`). Ausente = nunca se le pidió nada. `consumido` dice
|
|
1490
|
+
* si ya se le mandó al agente en un turno.
|
|
1491
|
+
*/
|
|
1492
|
+
feedback?: {
|
|
1493
|
+
texto: string;
|
|
1494
|
+
creado: string;
|
|
1495
|
+
consumido: boolean;
|
|
1496
|
+
}[];
|
|
1497
|
+
/**
|
|
1498
|
+
* El veredicto del juez de QA (`core/entrega.ts#VeredictoDeTarea`), y con él la
|
|
1499
|
+
* SALVEDAD: con qué condición de menos se entregó.
|
|
1500
|
+
*
|
|
1501
|
+
* **Sin esto, «Terminada» no distingue tres cosas distintas** —F1 de la revisión final—:
|
|
1502
|
+
* que el juez la aprobó con el verificador en verde, que se entregó SIN NADA que
|
|
1503
|
+
* verificar (una tarea de solo lectura: la salvedad), y —con `terminadaAMano`— que la dio
|
|
1504
|
+
* por buena una persona. El campo se guardaba en el índice de tareas desde que existe la
|
|
1505
|
+
* puerta de entrega y se quedaba en el host: la mitad del contrato en `core/` y en disco,
|
|
1506
|
+
* y la mitad que una persona lee sin cablear.
|
|
1507
|
+
*
|
|
1508
|
+
* **Y viaja completo porque no puede llevar nada más que texto para leer.** Medido en
|
|
1509
|
+
* `agent/tareas/juezDeTarea.ts#promptDelJuez`: el juez recibe el encargo, las rutas RELATIVAS de
|
|
1510
|
+
* lo autorizado y los hallazgos del verificador (código, fichero relativo, línea,
|
|
1511
|
+
* mensaje) — no hay un solo `readFile` en ese módulo, así que su prosa no puede citar el
|
|
1512
|
+
* contenido de un fichero ni una ruta de la máquina. El `resumen` ya cruzaba el cable de
|
|
1513
|
+
* todos modos: para un veredicto rojo va dentro del `motivo`.
|
|
1514
|
+
*/
|
|
1515
|
+
veredicto?: {
|
|
1516
|
+
veredicto: "verde" | "rojo" | "indeterminado";
|
|
1517
|
+
resumen: string;
|
|
1518
|
+
hallazgos?: string[];
|
|
1519
|
+
salvedad?: string;
|
|
1520
|
+
};
|
|
1521
|
+
/**
|
|
1522
|
+
* La dio por buena una PERSONA («Dar por bueno»), no la puerta de entrega
|
|
1523
|
+
* (`core/tareas.ts#Tarea.terminadaAMano`). Ausente = no consta.
|
|
1524
|
+
*/
|
|
1525
|
+
terminadaAMano?: boolean;
|
|
1526
|
+
/**
|
|
1527
|
+
* Con qué se CERRÓ (`core/entrega.ts#cierreDeLaEntrega`): lo crítico y las observaciones, lo que dice el comentario
|
|
1528
|
+
* de cierre del ticket. Ausente = se entregó sin nada que decir (o se cerró antes de que existiera).
|
|
1529
|
+
*/
|
|
1530
|
+
cierre?: {
|
|
1531
|
+
criticos: string[];
|
|
1532
|
+
observaciones: string[];
|
|
1533
|
+
};
|
|
1534
|
+
/**
|
|
1535
|
+
* El ticket del gestor de tareas en el que vive (`core/tareas.ts#TicketDeTarea`). Cruzan la CLAVE, el conector (de él
|
|
1536
|
+
* sale el nombre que se enseña: «Jira»), el enlace y el aviso de lo último que no se pudo escribir; el `sitio` y el
|
|
1537
|
+
* `proyecto` del gestor se quedan en el host, como los de una sesión ligada a un ticket.
|
|
1538
|
+
*/
|
|
1539
|
+
ticket?: {
|
|
1540
|
+
clave: string;
|
|
1541
|
+
conector: string;
|
|
1542
|
+
url?: string;
|
|
1543
|
+
aviso?: string;
|
|
1544
|
+
};
|
|
1545
|
+
/** La pantalla de Stitch elegida para la tarea: su `name` y su título (no es una ruta de la máquina). */
|
|
1546
|
+
pantallaDeStitch?: {
|
|
1547
|
+
name: string;
|
|
1548
|
+
titulo: string;
|
|
1549
|
+
proyecto?: string;
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Una `Tarea` del índice traducida a lo que viaja. **La raíz del proyecto se queda aquí.**
|
|
1554
|
+
*
|
|
1555
|
+
* **Vive en este fichero, exportada, y eso es el arreglo de F1.** Era una copia de campos a
|
|
1556
|
+
* mano enterrada en el cierre de `montarRutas` (`arranque.ts`), a mil líneas del tipo que
|
|
1557
|
+
* traduce y dentro de algo que todos sus tests doblan — o sea el patrón de fallo que
|
|
1558
|
+
* `CLAUDE.md` documenta cinco veces en esta misma tanda: «si una regla de producción se
|
|
1559
|
+
* compone dentro de algo que los tests simulan, esa regla no está probada: está escrita».
|
|
1560
|
+
* `veredicto` se cayó aquí y en el store del cliente sin que nada se pusiera rojo. Ahora
|
|
1561
|
+
* `transporte.test.ts` recorre los campos de `Tarea` y exige decisión explícita por cada
|
|
1562
|
+
* uno.
|
|
1563
|
+
*
|
|
1564
|
+
* Campo a campo, y también DENTRO del veredicto: un `...tarea.veredicto` dejaría pasar sin
|
|
1565
|
+
* nombrar el campo que alguien le añada mañana a `VeredictoDeTarea`.
|
|
1566
|
+
*/
|
|
1567
|
+
export declare function filaDeTarea(t: Tarea): TareaDelCable;
|
|
1568
|
+
export interface ProveedorDeModelos {
|
|
1569
|
+
id: string;
|
|
1570
|
+
/**
|
|
1571
|
+
* Cómo se ESCRIBE, que no es el id. Lo pone el servidor (`core/modelos.ts#nombreDeProveedor`)
|
|
1572
|
+
* y no el cliente: capitalizar un id en el navegador daría «Xai» y «Ollama-cloud».
|
|
1573
|
+
*/
|
|
1574
|
+
nombre: string;
|
|
1575
|
+
credencial: "puesta" | "falta" | "nativa";
|
|
1576
|
+
/**
|
|
1577
|
+
* La credencial está en `auth.json` — o sea, es NUESTRA y se puede borrar desde la
|
|
1578
|
+
* interfaz. Una que solo viene del entorno no lleva esta marca: desexportar la shell de
|
|
1579
|
+
* nadie no está a nuestro alcance, y ofrecer un botón que no puede cumplir sería peor
|
|
1580
|
+
* que no ofrecerlo. Misma disciplina que el harness de DeepSeek, que solo retira la
|
|
1581
|
+
* credencial cuya referencia puede demostrar suya.
|
|
1582
|
+
*/
|
|
1583
|
+
enFichero?: boolean;
|
|
1584
|
+
/** Lo declaró el usuario (`custom:<slug>`), no viene de serie. */
|
|
1585
|
+
personalizado?: boolean;
|
|
1586
|
+
/** Su URL base, SOLO en los personalizados: es lo que tecleó el usuario y lo que hay que
|
|
1587
|
+
* ver al lado de su clave para saber a dónde va. Los de serie la tienen en el repo. */
|
|
1588
|
+
baseUrl?: string;
|
|
1589
|
+
/** Ausente = todavía no se ha consultado su catálogo. Vacío = lo dijo y no ofrece nada. */
|
|
1590
|
+
/**
|
|
1591
|
+
* Los modelos que sirve, con los niveles de ESFUERZO que admite cada uno.
|
|
1592
|
+
*
|
|
1593
|
+
* `esfuerzos` lo calcula el SERVIDOR con la tabla de `core/esfuerzo.ts`: la frontera
|
|
1594
|
+
* prohíbe que el cliente importe de `src/`, y una copia declarada de una tabla que crece
|
|
1595
|
+
* cada vez que se mide un modelo nuevo es un sitio donde quedarse viejo en silencio.
|
|
1596
|
+
* Ausente = ese modelo no admite ninguno, y entonces no se pinta el control.
|
|
1597
|
+
*/
|
|
1598
|
+
modelos?: {
|
|
1599
|
+
id: string;
|
|
1600
|
+
nombre?: string;
|
|
1601
|
+
esfuerzos?: Esfuerzo[];
|
|
1602
|
+
}[];
|
|
1603
|
+
/** El catálogo de ESTE proveedor falló. Nunca lleva la clave ni el cuerpo remoto. */
|
|
1604
|
+
error?: string;
|
|
1605
|
+
}
|
|
1606
|
+
export type MensajeDelCliente =
|
|
1607
|
+
/**
|
|
1608
|
+
* `detener`: el botón DETENER y replanificar — `texto` puede ir vacío.
|
|
1609
|
+
* `adjuntos` (IXCODE-7): los NOMBRES que ya se subieron con `POST /adjunto?para=sesion` antes
|
|
1610
|
+
* de mandar este mensaje — nunca bytes por el cable, el molde de siempre.
|
|
1611
|
+
*/
|
|
1612
|
+
{
|
|
1613
|
+
clase: "prosa";
|
|
1614
|
+
texto: string;
|
|
1615
|
+
detener?: true;
|
|
1616
|
+
adjuntos?: string[];
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* «Ponme este modelo», dicho por un control de la interfaz: `proveedor/modelo` y nada
|
|
1620
|
+
* más.
|
|
1621
|
+
*
|
|
1622
|
+
* El cliente NO manda comandos. Podría mandar la prosa `/modelo <id>` —es el mismo
|
|
1623
|
+
* efecto— y estuvo escrito así un rato, pero eso son dos mentiras pequeñas: el transcript
|
|
1624
|
+
* se apunta un acto de USUARIO que nadie tecleó (y de ahí sale el título de la sesión), y
|
|
1625
|
+
* la interfaz queda hablando en la sintaxis de otra piel. Lo que viaja es la intención;
|
|
1626
|
+
* CÓMO se aplica es cosa del servidor, y hoy es reusando el manejador de `COMANDOS` que
|
|
1627
|
+
* ya comparten el terminal y la TUI — la función se comparte, la sintaxis no se exporta.
|
|
1628
|
+
*/
|
|
1629
|
+
| {
|
|
1630
|
+
clase: "modelo";
|
|
1631
|
+
id: string;
|
|
1632
|
+
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Cuánto razona el modelo de esta sesión. `nivel` ausente = quitarlo.
|
|
1635
|
+
*
|
|
1636
|
+
* La INTENCIÓN y no la sintaxis, como el modelo: el servidor la aplica encolando el
|
|
1637
|
+
* manejador de `/esfuerzo` que ya comparten el terminal y la TUI. Mandar la prosa
|
|
1638
|
+
* apuntaría en el transcript un acto de usuario que nadie tecleó.
|
|
1639
|
+
*
|
|
1640
|
+
* El nivel NO se comprueba aquí contra el modelo en vigor: se guarda en la sesión y
|
|
1641
|
+
* `construirModelo` lo omite mientras no aplique. Así, cambiar de modelo a uno que sí lo
|
|
1642
|
+
* admite lo recupera solo, en vez de obligar a volver a elegirlo.
|
|
1643
|
+
*/
|
|
1644
|
+
| {
|
|
1645
|
+
clase: "esfuerzo";
|
|
1646
|
+
nivel?: Esfuerzo;
|
|
1647
|
+
}
|
|
1648
|
+
/**
|
|
1649
|
+
* El MODO DE ESCRITURA de la sesión abierta: supervisado o autónomo.
|
|
1650
|
+
*
|
|
1651
|
+
* La INTENCIÓN y no la sintaxis, como el modelo y el esfuerzo: el servidor la aplica
|
|
1652
|
+
* encolando el manejador de `/aprobacion` que ya comparten el terminal y la TUI. Un
|
|
1653
|
+
* segundo camino para lo mismo es donde el hueco de política podría reabrirse.
|
|
1654
|
+
*
|
|
1655
|
+
* Lo que el modo gobierna son las escrituras LOCALES: la subida a CloudStudio conserva
|
|
1656
|
+
* su plan y su aprobación en los dos modos, y las guardas de RUTA no se tocan.
|
|
1657
|
+
*/
|
|
1658
|
+
| {
|
|
1659
|
+
clase: "modoDeEscritura";
|
|
1660
|
+
modo: "supervisado" | "autonomo";
|
|
1661
|
+
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Abrir una sesión de un proyecto: la que se nombra, o una NUEVA si no se nombra ninguna.
|
|
1664
|
+
*
|
|
1665
|
+
* Es la acción de la barra lateral, y no pasa por el alta: si la copia local ya existe no
|
|
1666
|
+
* hay nada que dar de alta ni rama que preguntar — se abre y ya. Si no existe, el
|
|
1667
|
+
* servidor contesta con las ramas por el camino del alta, que es el que sabe bajarla.
|
|
1668
|
+
*/
|
|
1669
|
+
| {
|
|
1670
|
+
clase: "sesion";
|
|
1671
|
+
proyecto: string;
|
|
1672
|
+
sesion?: string;
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Lo que se hace con una sesión GUARDADA desde el menú de su fila: borrarla o ponerle
|
|
1676
|
+
* nombre. Va aparte de abrir (arriba) y no como un campo opcional de aquel, porque son
|
|
1677
|
+
* verbos distintos con consecuencias distintas: uno abre y los otros dos escriben en el
|
|
1678
|
+
* índice del proyecto — y borrar, además, puede cerrar la consola si es la sesión abierta.
|
|
1679
|
+
*
|
|
1680
|
+
* `titulo` solo lo lleva «renombrar», y vacío se rechaza en el servidor: dejar el título en
|
|
1681
|
+
* blanco devolvería la sesión al régimen automático y el siguiente turno la rebautizaría
|
|
1682
|
+
* con la primera frase, borrando en silencio el nombre que puso una persona.
|
|
1683
|
+
*/
|
|
1684
|
+
| {
|
|
1685
|
+
clase: "sesionAccion";
|
|
1686
|
+
accion: "borrar";
|
|
1687
|
+
proyecto: string;
|
|
1688
|
+
sesion: string;
|
|
1689
|
+
} | {
|
|
1690
|
+
clase: "sesionAccion";
|
|
1691
|
+
accion: "renombrar";
|
|
1692
|
+
proyecto: string;
|
|
1693
|
+
sesion: string;
|
|
1694
|
+
titulo: string;
|
|
1695
|
+
}
|
|
1696
|
+
/** Qué proyectos de un entorno se enseñan en la barra. Lista vacía = ninguno, que es una
|
|
1697
|
+
* elección; para volver a la omisión no hay mensaje, porque no hay «deshacer» que pedir. */
|
|
1698
|
+
| {
|
|
1699
|
+
clase: "entorno";
|
|
1700
|
+
accion: "visibles";
|
|
1701
|
+
entorno: string;
|
|
1702
|
+
proyectos: string[];
|
|
1703
|
+
}
|
|
1704
|
+
/** Qué proyectos de un entorno van FIJADOS arriba de la barra, en su grupo. La lista
|
|
1705
|
+
* ENTERA, no un «fija este»: el cliente la compone y el servidor la guarda tal cual, el
|
|
1706
|
+
* mismo trato que `visibles`. Vacía = ninguno fijado. */
|
|
1707
|
+
| {
|
|
1708
|
+
clase: "entorno";
|
|
1709
|
+
accion: "fijados";
|
|
1710
|
+
entorno: string;
|
|
1711
|
+
proyectos: string[];
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* Borrar la COPIA LOCAL de un proyecto del entorno activo: vuelve a «sin descargar», y con
|
|
1715
|
+
* ella se van sus sesiones, su historial, sus artefactos y lo que no se haya subido.
|
|
1716
|
+
*
|
|
1717
|
+
* `proyecto` es el ID del listado, no una ruta: la carpeta la compone el servidor a partir
|
|
1718
|
+
* del nombre que ÉL tiene para ese id. Contesta **409 con `{ motivo }`** si no se puede
|
|
1719
|
+
* ahora (un turno en vuelo, una tarea de fondo sin terminar), igual que `olvidar`.
|
|
1720
|
+
*/
|
|
1721
|
+
| {
|
|
1722
|
+
clase: "copiaLocal";
|
|
1723
|
+
accion: "borrar";
|
|
1724
|
+
proyecto: string;
|
|
1725
|
+
}
|
|
1726
|
+
/** Abrir la carpeta de la copia local en el explorador de ficheros de la máquina del
|
|
1727
|
+
* servidor. Mismo trato que `borrar`: el ID, nunca una ruta; 409 con `{ motivo }` si no. */
|
|
1728
|
+
| {
|
|
1729
|
+
clase: "copiaLocal";
|
|
1730
|
+
accion: "abrirCarpeta";
|
|
1731
|
+
proyecto: string;
|
|
1732
|
+
}
|
|
1733
|
+
/** Pedir la FOTO del resumen del proyecto. Contesta 200 con un `FotoDelResumen` en la propia
|
|
1734
|
+
* respuesta, o 409 con `{ motivo }`. Mismo trato que `borrar`: el ID, nunca una ruta. */
|
|
1735
|
+
| {
|
|
1736
|
+
clase: "copiaLocal";
|
|
1737
|
+
accion: "resumen";
|
|
1738
|
+
proyecto: string;
|
|
1739
|
+
}
|
|
1740
|
+
/** Fijar —o quitar, sin `modo`— el modo con que nacen las sesiones nuevas de este proyecto
|
|
1741
|
+
* (IXCODE-31). 200 con `{ proyecto? }`, 409 con `{ motivo }` sin copia o con un id ajeno, y
|
|
1742
|
+
* 400 con un modo que no existe. Mismo trato que `resumen`: el ID, nunca una ruta. */
|
|
1743
|
+
| {
|
|
1744
|
+
clase: "copiaLocal";
|
|
1745
|
+
accion: "modoDeEscritura";
|
|
1746
|
+
proyecto: string;
|
|
1747
|
+
modo?: "supervisado" | "autonomo";
|
|
1748
|
+
}
|
|
1749
|
+
/** Fijar el modo con que nacen las sesiones nuevas en cualquier proyecto (Ajustes > General). */
|
|
1750
|
+
| {
|
|
1751
|
+
clase: "modoPorDefecto";
|
|
1752
|
+
modo: "supervisado" | "autonomo";
|
|
1753
|
+
}
|
|
1754
|
+
/** Fijar —o quitar, sin `id`— el aparato de las sesiones nuevas (IXCODE-51). Solo el ID: el resto
|
|
1755
|
+
* sale de la última MEDIDA, como en la pastilla. */
|
|
1756
|
+
| {
|
|
1757
|
+
clase: "dispositivoPorDefecto";
|
|
1758
|
+
id?: string;
|
|
1759
|
+
}
|
|
1760
|
+
/** LEER una conversación sin abrirle consola (IXCODE-36): 200 con `{actos}`, o 409 con `{motivo}`. */
|
|
1761
|
+
| {
|
|
1762
|
+
clase: "leerSesion";
|
|
1763
|
+
proyecto: string;
|
|
1764
|
+
sesion: string;
|
|
1765
|
+
}
|
|
1766
|
+
/** La pestaña Soporte: chats y tareas del proyecto con su análisis previo (`soporte.ts`). */
|
|
1767
|
+
| {
|
|
1768
|
+
clase: "soporte";
|
|
1769
|
+
accion: "listar";
|
|
1770
|
+
proyecto: string;
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* Quitar un entorno registrado. El servidor contesta **409 con `{ motivo }`** si no se puede
|
|
1774
|
+
* ahora (un proyecto suyo abierto, una tarea sin terminar): la negativa vive allí, y así el
|
|
1775
|
+
* cliente la enseña sin llevar una copia de la regla. Sus copias locales se quedan.
|
|
1776
|
+
*/
|
|
1777
|
+
| {
|
|
1778
|
+
clase: "entorno";
|
|
1779
|
+
accion: "olvidar";
|
|
1780
|
+
entorno: string;
|
|
1781
|
+
/** Borrar además `<workspace>/<entorno>/` entera. Solo con la casilla marcada y el
|
|
1782
|
+
* nombre escrito; ausente = las copias se quedan. */
|
|
1783
|
+
borrarCopias?: boolean;
|
|
1784
|
+
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Ponerle NOMBRE a un entorno registrado: el alias con el que se lee en la barra y en su
|
|
1787
|
+
* pestaña de Ajustes. Se escribe a mano porque hasta ahora el nombre lo deducía el
|
|
1788
|
+
* servidor al conectarse, y el «Otro» de un on-premise se quedaba con su host por nombre
|
|
1789
|
+
* para siempre.
|
|
1790
|
+
*
|
|
1791
|
+
* **El `id` NO viaja**: es lo que identifica al entorno —segmento de su carpeta en el
|
|
1792
|
+
* workspace, hueco de sus credenciales— y renombrar no lo toca, así que el cable no puede
|
|
1793
|
+
* ni sugerir que cambie.
|
|
1794
|
+
*
|
|
1795
|
+
* El servidor contesta **409 con `{ motivo }`** si el nombre no vale, igual que `olvidar`.
|
|
1796
|
+
* La regla es SUYA (`core/settings.ts#motivoDeNombreDeEntornoInaceptable`) y la vuelve a
|
|
1797
|
+
* aplicar aunque el cliente ya la tenga —la frontera prohíbe compartir el módulo, así que
|
|
1798
|
+
* `Ajustes.tsx` lleva su copia DECLARADA, para poder avisar mientras se teclea—: la copia
|
|
1799
|
+
* es comodidad, y la negativa que manda es esta, con su motivo en la mano. Dos entornos con
|
|
1800
|
+
* el mismo nombre SÍ se admiten; que se repitan se advierte en la pantalla, que es donde se
|
|
1801
|
+
* ven los dos.
|
|
1802
|
+
*/
|
|
1803
|
+
| {
|
|
1804
|
+
clase: "entorno";
|
|
1805
|
+
accion: "renombrar";
|
|
1806
|
+
entorno: string;
|
|
1807
|
+
nombre: string;
|
|
1808
|
+
}
|
|
1809
|
+
/** Cambiar de entorno ACTIVO: el de cuyos proyectos se habla. Trae su listado consigo. */
|
|
1810
|
+
| {
|
|
1811
|
+
clase: "entorno";
|
|
1812
|
+
accion: "activo";
|
|
1813
|
+
entorno: string;
|
|
1814
|
+
}
|
|
1815
|
+
/**
|
|
1816
|
+
* «Dime qué proyectos tiene ESTE entorno», sin hacerlo activo. Es lo que necesita la
|
|
1817
|
+
* pestaña de un entorno en Ajustes para poder marcar sus casillas, y la diferencia con
|
|
1818
|
+
* `activo` es justo lo que la hace usable: abrir Ajustes a elegir proyectos es MIRAR, y
|
|
1819
|
+
* mudar el entorno activo le cambiaría la barra lateral —y los proyectos de los que se
|
|
1820
|
+
* habla— a quien esté trabajando en otro servidor.
|
|
1821
|
+
*
|
|
1822
|
+
* Se pide al abrir esa pestaña y no antes, por lo mismo que el catálogo de un proveedor
|
|
1823
|
+
* (`clase: "catalogo"`): cada uno es una conexión con CloudStudio (OAuth + `initialize` +
|
|
1824
|
+
* `studio_list_projects`), y consultarlos todos al conectar sería gastar una petición por
|
|
1825
|
+
* entorno para pintar unas casillas que quizá nadie abra. La respuesta es
|
|
1826
|
+
* `proyectosDeEntorno`, con su lista o con su `error`.
|
|
1827
|
+
*/
|
|
1828
|
+
| {
|
|
1829
|
+
clase: "entorno";
|
|
1830
|
+
accion: "proyectos";
|
|
1831
|
+
entorno: string;
|
|
1832
|
+
}
|
|
1833
|
+
/**
|
|
1834
|
+
* La respuesta a una `pregunta`. `seleccion` solo la manda el diálogo de una decisión
|
|
1835
|
+
* `seleccionable` (la subida a CloudStudio): las rutas que la persona dejó marcadas.
|
|
1836
|
+
* Ausente = el plan entero, o una pregunta que no deja elegir.
|
|
1837
|
+
*/
|
|
1838
|
+
| {
|
|
1839
|
+
clase: "respuesta";
|
|
1840
|
+
texto: string;
|
|
1841
|
+
seleccion?: string[];
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* La respuesta a `seleccionar`. **Sin `id` (o con `id: null`) es CANCELAR**, que es
|
|
1845
|
+
* exactamente lo que `seleccionar` ya devuelve al desconectarse y al vencer su plazo — en
|
|
1846
|
+
* el terminal cancelar es una salida de primera clase («número, Enter cancela»), así que
|
|
1847
|
+
* la web no puede tener menos. Se aprovecha esta clase en vez de añadir otra: el contrato
|
|
1848
|
+
* del cable no crece y la traducción a `undefined` vive en un solo sitio
|
|
1849
|
+
* (`consolaWeb.ts#recibir`). `undefined` viaja como la AUSENCIA del campo, porque
|
|
1850
|
+
* `JSON.stringify` descarta las claves con ese valor; `null` se admite porque es lo que
|
|
1851
|
+
* escribiría un cliente que lo serialice explícitamente, y dice lo mismo.
|
|
1852
|
+
*
|
|
1853
|
+
* Un `id` vacío o desconocido NO es cancelar: es un id que no existe, y así se lo pasa a
|
|
1854
|
+
* quien llamó. Traducirlo aquí a cancelación convertiría el bug de un cliente en un
|
|
1855
|
+
* usuario que se echó atrás.
|
|
1856
|
+
*/
|
|
1857
|
+
| {
|
|
1858
|
+
clase: "eleccion";
|
|
1859
|
+
id?: string | null;
|
|
1860
|
+
} | {
|
|
1861
|
+
clase: "secreto";
|
|
1862
|
+
valor: string;
|
|
1863
|
+
}
|
|
1864
|
+
/**
|
|
1865
|
+
* Un paso del alta, resuelto por el wizard. Es UNA clase y no tres porque los tres son
|
|
1866
|
+
* el mismo trámite —el alta— y quien la atiende es un solo sitio (`web/servidor/arranque.ts`);
|
|
1867
|
+
* tres clases obligarían a mantener tres ramas del cable de acuerdo entre sí sin ganar
|
|
1868
|
+
* nada.
|
|
1869
|
+
*
|
|
1870
|
+
* Con `paso` «proyecto» y SIN `rama` no se abre nada: significa «he elegido proyecto,
|
|
1871
|
+
* dime sus ramas», y el servidor contesta con otro mensaje de alta con `ramas` llenas.
|
|
1872
|
+
* Es lo que evita inventarse las ramas del primer proyecto de la lista antes de que
|
|
1873
|
+
* nadie haya elegido — el mismo «lista vacía, no dato inventado» del otro extremo.
|
|
1874
|
+
*
|
|
1875
|
+
* Aquí NO hay campo para la clave de API: el paso de cuenta va por «secreto».
|
|
1876
|
+
*/
|
|
1877
|
+
| {
|
|
1878
|
+
clase: "alta";
|
|
1879
|
+
paso: PasoDelVestibulo;
|
|
1880
|
+
entorno?: {
|
|
1881
|
+
id: string;
|
|
1882
|
+
nombre: string;
|
|
1883
|
+
url: string;
|
|
1884
|
+
};
|
|
1885
|
+
proyecto?: string;
|
|
1886
|
+
rama?: string;
|
|
1887
|
+
}
|
|
1888
|
+
/**
|
|
1889
|
+
* El valor es el `Decision["type"]` que el pendiente declara en `decisionesPermitidas`,
|
|
1890
|
+
* no una respuesta tecleada: el cliente son botones. `consolaWeb` lo traduce a la
|
|
1891
|
+
* respuesta que `interpretAnswer` entiende, en vez de comparar cadenas por su cuenta.
|
|
1892
|
+
*/
|
|
1893
|
+
/**
|
|
1894
|
+
* «Dime qué modelos sirve este proveedor.» Se pide al abrir el menú de ese proveedor y no
|
|
1895
|
+
* antes: cada uno es una llamada de red. La respuesta es otro mensaje `modelos` con ese
|
|
1896
|
+
* proveedor ya relleno — o con su `error` puesto, que también es una respuesta.
|
|
1897
|
+
*/
|
|
1898
|
+
| {
|
|
1899
|
+
clase: "catalogo";
|
|
1900
|
+
proveedor: string;
|
|
1901
|
+
}
|
|
1902
|
+
/**
|
|
1903
|
+
* Vuelve a mirar qué dispositivos y simuladores hay. La respuesta viaja por el SSE como
|
|
1904
|
+
* `dispositivos`, a todos los clientes: la máquina es la misma para todos.
|
|
1905
|
+
*/
|
|
1906
|
+
| {
|
|
1907
|
+
clase: "dispositivos";
|
|
1908
|
+
/**
|
|
1909
|
+
* Con `ajustes` se GUARDAN antes de volver a medir; sin ellos solo se vuelve a medir.
|
|
1910
|
+
* Es el mismo mensaje para las dos cosas porque configurar sin remedir dejaría la
|
|
1911
|
+
* pantalla enseñando la foto de la configuración anterior.
|
|
1912
|
+
*/
|
|
1913
|
+
ajustes?: AjustesDeDispositivos;
|
|
1914
|
+
/**
|
|
1915
|
+
* Instala una herramienta que falta, y después se vuelve a medir. El comando NO viaja
|
|
1916
|
+
* del cliente: viaja el NOMBRE de la herramienta y el servidor decide qué lanzar
|
|
1917
|
+
* (`INSTALADORES`, tabla cerrada) — un comando que llegue por el cable es una shell
|
|
1918
|
+
* abierta en la máquina del usuario.
|
|
1919
|
+
*/
|
|
1920
|
+
instalar?: NombreDeHerramienta;
|
|
1921
|
+
/**
|
|
1922
|
+
* Abre la carpeta que contiene el binario de esta herramienta en el explorador del
|
|
1923
|
+
* SISTEMA donde corre la consola — el mismo límite que el selector de carpeta del
|
|
1924
|
+
* workspace: con la consola por un túnel, el botón no sirve. Solo `adb`/`emulator`
|
|
1925
|
+
* tienen una ruta que abrir; no vuelve a medir ni cambia ningún estado.
|
|
1926
|
+
*/
|
|
1927
|
+
abrirRuta?: NombreDeHerramienta;
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Con qué dispositivo trabaja la sesión abierta. Viaja el ID y nada más: el servidor lo
|
|
1931
|
+
* resuelve contra la última medida y guarda la foto — un nombre que llegue del cliente no
|
|
1932
|
+
* es una fuente sobre la máquina. Sin `id`, se quita la elección.
|
|
1933
|
+
*/
|
|
1934
|
+
| {
|
|
1935
|
+
clase: "dispositivo";
|
|
1936
|
+
id?: string;
|
|
1937
|
+
}
|
|
1938
|
+
/**
|
|
1939
|
+
* «Arranca este AVD.» El nombre y nada más: el servidor comprueba que esté en SU última
|
|
1940
|
+
* medida antes de ejecutar nada, así que por aquí no entra un nombre a ciegas.
|
|
1941
|
+
*
|
|
1942
|
+
* La respuesta es el `dispositivos` de siempre, con la foto nueva y el `arranque` dentro:
|
|
1943
|
+
* arrancar acaba en una medida, no en un acuse.
|
|
1944
|
+
*/
|
|
1945
|
+
| {
|
|
1946
|
+
clase: "arrancarEmulador";
|
|
1947
|
+
avd: string;
|
|
1948
|
+
}
|
|
1949
|
+
/**
|
|
1950
|
+
* «Crea un AVD con este nombre.» El servidor valida el nombre (forma, y que no exista en SU
|
|
1951
|
+
* última medida) antes de lanzar `avdmanager`, y lo cuenta como un paso de receta
|
|
1952
|
+
* (`instalacion` con `receta: "crear-avd"`): comparten el cerrojo, uno a la vez.
|
|
1953
|
+
*/
|
|
1954
|
+
| {
|
|
1955
|
+
clase: "crearEmulador";
|
|
1956
|
+
nombre: string;
|
|
1957
|
+
base?: string;
|
|
1958
|
+
conDatos?: boolean;
|
|
1959
|
+
}
|
|
1960
|
+
/** Elimina un AVD por su nombre: el servidor lo comprueba contra SU medida (existe, no es el único, está apagado). */
|
|
1961
|
+
| {
|
|
1962
|
+
clase: "eliminarEmulador";
|
|
1963
|
+
avd: string;
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* Lo de UN AVD: el puerto local del túnel de hotswap y si arranca sin ventana. El AVD tiene
|
|
1967
|
+
* que estar en la última medida y el puerto no puede ser de otro; la respuesta es el
|
|
1968
|
+
* `dispositivos` de siempre, con los `ajustes` nuevos.
|
|
1969
|
+
*/
|
|
1970
|
+
| {
|
|
1971
|
+
clase: "ajusteDeAvd";
|
|
1972
|
+
avd: string;
|
|
1973
|
+
puerto?: number;
|
|
1974
|
+
sinVentana?: boolean;
|
|
1975
|
+
}
|
|
1976
|
+
/** «Para este emulador.» El ID de la medida, y solo si es un emulador; después se remide. */
|
|
1977
|
+
| {
|
|
1978
|
+
clase: "pararEmulador";
|
|
1979
|
+
id: string;
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* VERIFICAR la conexión con un dispositivo: hablarle y esperar respuesta.
|
|
1983
|
+
*
|
|
1984
|
+
* Viaja el ID y nada más, la misma regla que `dispositivo`: el servidor lo resuelve contra
|
|
1985
|
+
* la última MEDIDA y de ahí saca la plataforma y la clase, que son las que deciden qué
|
|
1986
|
+
* comando se lanza. Un id que no esté en la medida se ignora — es una foto vieja del
|
|
1987
|
+
* cliente, no un error.
|
|
1988
|
+
*
|
|
1989
|
+
* **Es un mensaje propio y no un campo de `dispositivos`**, aunque las dos cosas acaben
|
|
1990
|
+
* emitiendo el informe: `dispositivos` significa «vuelve a MEDIR», y una medida nueva se
|
|
1991
|
+
* lleva por construcción todas las verificaciones —viven con la foto—. O sea que meterlo
|
|
1992
|
+
* ahí habría borrado la verificación que se acaba de hacer.
|
|
1993
|
+
*/
|
|
1994
|
+
| {
|
|
1995
|
+
clase: "conexion";
|
|
1996
|
+
id: string;
|
|
1997
|
+
}
|
|
1998
|
+
/**
|
|
1999
|
+
* La credencial de un proveedor, desde la ventana de ajustes.
|
|
2000
|
+
*
|
|
2001
|
+
* «pedir» hace que el servidor PREGUNTE por ella (`leerSecreto`), así que la clave sigue
|
|
2002
|
+
* viajando por el ÚNICO mensaje del cable que la lleva («secreto») y este mensaje no la
|
|
2003
|
+
* toca. «borrar» la quita de `auth.json`.
|
|
2004
|
+
*
|
|
2005
|
+
* Podría haber viajado como la prosa `/provider <id>`, que es el mismo diálogo, pero esa
|
|
2006
|
+
* ruta necesita el lazo de `correrConsola` — y el lazo solo existe con un proyecto
|
|
2007
|
+
* abierto. La ventana de ajustes se abre antes, así que tiene su propio mensaje.
|
|
2008
|
+
*/
|
|
2009
|
+
| {
|
|
2010
|
+
clase: "credencial";
|
|
2011
|
+
accion: "pedir" | "borrar";
|
|
2012
|
+
proveedor: string;
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Dar de alta o retirar un proveedor de modelos PERSONALIZADO: un endpoint compatible
|
|
2016
|
+
* con OpenAI que declara el usuario.
|
|
2017
|
+
*
|
|
2018
|
+
* La clave NO viaja aquí. El alta escribe nombre y URL en el `config.json` global, y la
|
|
2019
|
+
* credencial se pone después con el mismo `{clase:"credencial", accion:"pedir"}` que los
|
|
2020
|
+
* de serie — o sea, por el único mensaje del cable que la lleva. Que sean dos pasos y no
|
|
2021
|
+
* un formulario de tres campos es deliberado: un tercer campo con la clave dentro sería
|
|
2022
|
+
* un segundo camino para lo mismo, y el que menos garantías da.
|
|
2023
|
+
*
|
|
2024
|
+
* El identificador no se teclea: lo deriva el servidor del nombre
|
|
2025
|
+
* (`core/modelos.ts#slugDesdeNombre`). La baja va por ese identificador, que es lo que
|
|
2026
|
+
* la fila conoce.
|
|
2027
|
+
*/
|
|
2028
|
+
| {
|
|
2029
|
+
clase: "proveedor";
|
|
2030
|
+
accion: "alta";
|
|
2031
|
+
nombre: string;
|
|
2032
|
+
baseUrl: string;
|
|
2033
|
+
} | {
|
|
2034
|
+
clase: "proveedor";
|
|
2035
|
+
accion: "baja";
|
|
2036
|
+
slug: string;
|
|
2037
|
+
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Dar de alta, cambiar o borrar un subagente.
|
|
2040
|
+
*
|
|
2041
|
+
* `ambito` decide en qué carpeta se escribe, y viaja explícito en vez de deducirse de si
|
|
2042
|
+
* hay proyecto abierto: con uno abierto valen las dos, y adivinar cuál quiere el usuario
|
|
2043
|
+
* es cómo un «revisor» que quería para todos los proyectos acaba escondido en uno.
|
|
2044
|
+
*/
|
|
2045
|
+
| {
|
|
2046
|
+
clase: "agente";
|
|
2047
|
+
/**
|
|
2048
|
+
* `restaurar` devuelve un agente de serie a como lo entregamos, y ocupa el sitio del
|
|
2049
|
+
* `borrar` en esos: borrarlo no lo resiembra —la marca recuerda que se entregó—, así
|
|
2050
|
+
* que era perderlo para siempre. El servidor RECHAZA un `borrar` de uno de serie:
|
|
2051
|
+
* esconderle el icono al cliente es presentación, no una guarda.
|
|
2052
|
+
*/
|
|
2053
|
+
accion: "guardar" | "borrar" | "restaurar";
|
|
2054
|
+
ambito: "global" | "proyecto";
|
|
2055
|
+
agente: AgenteDelCable;
|
|
2056
|
+
/**
|
|
2057
|
+
* El nombre de ANTES, solo en un renombrado. Ausente = el nombre no cambia, que es lo
|
|
2058
|
+
* que manda un alta y una edición normal.
|
|
2059
|
+
*
|
|
2060
|
+
* Va en el `guardar` y no en una cuarta acción porque renombrar ES guardar: el
|
|
2061
|
+
* formulario permite cambiar el nombre y la descripción en la misma pulsación, y dos
|
|
2062
|
+
* mensajes serían dos escrituras que pueden quedarse a medias. Lo decide el servidor
|
|
2063
|
+
* comparándolo con `agente.nombre`: si son iguales, no hay renombrado.
|
|
2064
|
+
*/
|
|
2065
|
+
renombrandoDe?: string;
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Dar de alta, cambiar o borrar una skill del USUARIO.
|
|
2069
|
+
*
|
|
2070
|
+
* El mismo molde que `agente`, y las dos diferencias no son de forma:
|
|
2071
|
+
*
|
|
2072
|
+
* - **No hay `restaurar`.** Una skill de serie vive dentro del paquete instalado y nunca
|
|
2073
|
+
* se copia a la casa del usuario, así que no hay marca que recordar ni nada que
|
|
2074
|
+
* reponer: lo que la consola ofrece sobre una de serie es COPIARLA, que es un `guardar`
|
|
2075
|
+
* normal con otro nombre.
|
|
2076
|
+
* - **El servidor RECHAZA guardar o borrar con el nombre de una de serie.** Esconderle el
|
|
2077
|
+
* botón al cliente es presentación, no una guarda; la barrera está aquí.
|
|
2078
|
+
*/
|
|
2079
|
+
| {
|
|
2080
|
+
clase: "skill";
|
|
2081
|
+
accion: "guardar" | "borrar";
|
|
2082
|
+
ambito: "global" | "proyecto";
|
|
2083
|
+
skill: SkillDelCable;
|
|
2084
|
+
/** El nombre de ANTES, solo en un renombrado. Ausente = no cambia. Como en `agente`. */
|
|
2085
|
+
renombrandoDe?: string;
|
|
2086
|
+
}
|
|
2087
|
+
/** El cuerpo de una skill, bajo demanda: al abrir su ficha o al copiar una de serie. */
|
|
2088
|
+
| {
|
|
2089
|
+
clase: "cuerpoDeSkill";
|
|
2090
|
+
nombre: string;
|
|
2091
|
+
}
|
|
2092
|
+
/** Parar el turno en vuelo. Aborta el `stream` del grafo (`SesionReal.cancelar`) y deja
|
|
2093
|
+
* la sesión viva: es parar ESTO, no cerrar la conversación. */
|
|
2094
|
+
| {
|
|
2095
|
+
clase: "cancelar";
|
|
2096
|
+
}
|
|
2097
|
+
/** La sesión remota: encenderla, revocar su enlace (apagar y volver a encender) o apagarla. */
|
|
2098
|
+
| {
|
|
2099
|
+
clase: "remoto";
|
|
2100
|
+
accion: "encender" | "revocar" | "apagar";
|
|
2101
|
+
}
|
|
2102
|
+
/** El interruptor de Ajustes: escribe `remoto.habilitado`; desactivar apaga antes lo encendido. */
|
|
2103
|
+
| {
|
|
2104
|
+
clase: "remoto";
|
|
2105
|
+
accion: "habilitar";
|
|
2106
|
+
valor: boolean;
|
|
2107
|
+
}
|
|
2108
|
+
/** Elegir la vía (solo apagada o en error), pedir el authtoken de ngrok (llega por `leerSecreto`) o fijar su dominio. */
|
|
2109
|
+
| {
|
|
2110
|
+
clase: "remoto";
|
|
2111
|
+
accion: "via";
|
|
2112
|
+
via: "servidor" | "ngrok";
|
|
2113
|
+
}
|
|
2114
|
+
/** Con `authtoken`, el tecleado en Ajustes; sin él, se pide por `leerSecreto`. Es un SECRETO del cable:
|
|
2115
|
+
* no se apunta, no se devuelve y no sale más que hacia `guardarAuthtoken`. */
|
|
2116
|
+
| {
|
|
2117
|
+
clase: "remoto";
|
|
2118
|
+
accion: "authtoken";
|
|
2119
|
+
authtoken?: string;
|
|
2120
|
+
} | {
|
|
2121
|
+
clase: "remoto";
|
|
2122
|
+
accion: "dominio";
|
|
2123
|
+
dominio: string;
|
|
2124
|
+
}
|
|
2125
|
+
/** Pide lo que la sesión abierta ha tocado, o el parche de un fichero concreto. */
|
|
2126
|
+
| {
|
|
2127
|
+
clase: "revision";
|
|
2128
|
+
ruta?: string;
|
|
2129
|
+
}
|
|
2130
|
+
/** Lo pendiente de subir (sin `ruta`) o el diff de uno (con `ruta`). */
|
|
2131
|
+
| {
|
|
2132
|
+
clase: "pendientesDeSubida";
|
|
2133
|
+
ruta?: string;
|
|
2134
|
+
}
|
|
2135
|
+
/** Pide el diff SEMÁNTICO de un `.xne` de Revisión. */
|
|
2136
|
+
| {
|
|
2137
|
+
clase: "modeloDelCambio";
|
|
2138
|
+
ruta: string;
|
|
2139
|
+
}
|
|
2140
|
+
/** Pide el árbol del proyecto abierto, o el contenido de una ruta relativa a su raíz. */
|
|
2141
|
+
| {
|
|
2142
|
+
clase: "arbol";
|
|
2143
|
+
}
|
|
2144
|
+
/** Pide la foto del modelo XOne del proyecto abierto (pestaña Colecciones). */
|
|
2145
|
+
| {
|
|
2146
|
+
clase: "colecciones";
|
|
2147
|
+
}
|
|
2148
|
+
/** Pide los planes del proyecto abierto (pestaña Planes). */
|
|
2149
|
+
| {
|
|
2150
|
+
clase: "planes";
|
|
2151
|
+
}
|
|
2152
|
+
/**
|
|
2153
|
+
* El gestor de tareas del proyecto abierto (IXCODE-11). Leer (`estado`, `sitios`,
|
|
2154
|
+
* `proyectos`, `pendientes`), vincular y desvincular el proyecto del gestor, marcar qué
|
|
2155
|
+
* conectores usa, y `empezar`: abre una sesión NUEVA ligada a esa tarea y contesta con el
|
|
2156
|
+
* borrador para el compositor. Nada de esto escribe en el gestor todavía.
|
|
2157
|
+
*/
|
|
2158
|
+
| {
|
|
2159
|
+
clase: "gestor";
|
|
2160
|
+
accion: "estado";
|
|
2161
|
+
} | {
|
|
2162
|
+
clase: "gestor";
|
|
2163
|
+
accion: "sitios";
|
|
2164
|
+
conector: string;
|
|
2165
|
+
} | {
|
|
2166
|
+
clase: "gestor";
|
|
2167
|
+
accion: "proyectos";
|
|
2168
|
+
conector: string;
|
|
2169
|
+
sitio: string;
|
|
2170
|
+
}
|
|
2171
|
+
/** IXCODE-15, de solo LECTURA: buscar proyectos por texto (Notion: sus bases). */
|
|
2172
|
+
| {
|
|
2173
|
+
clase: "gestor";
|
|
2174
|
+
accion: "buscarProyectos";
|
|
2175
|
+
conector: string;
|
|
2176
|
+
texto: string;
|
|
2177
|
+
}
|
|
2178
|
+
/** IXCODE-15, de solo LECTURA: lo que se entiende del esquema de un proyecto antes de vincularlo. */
|
|
2179
|
+
| {
|
|
2180
|
+
clase: "gestor";
|
|
2181
|
+
accion: "describir";
|
|
2182
|
+
conector: string;
|
|
2183
|
+
proyecto: string;
|
|
2184
|
+
} | {
|
|
2185
|
+
clase: "gestor";
|
|
2186
|
+
accion: "vincular";
|
|
2187
|
+
conector: string;
|
|
2188
|
+
sitio: string;
|
|
2189
|
+
proyecto: string;
|
|
2190
|
+
} | {
|
|
2191
|
+
clase: "gestor";
|
|
2192
|
+
accion: "desvincular";
|
|
2193
|
+
}
|
|
2194
|
+
/** Los estados del flujo del proyecto vinculado y el mapeo propuesto, contestados en la respuesta (la puerta 2). */
|
|
2195
|
+
| {
|
|
2196
|
+
clase: "gestor";
|
|
2197
|
+
accion: "estadosDelFlujo";
|
|
2198
|
+
}
|
|
2199
|
+
/** Guardar el mapeo de estados y el interruptor del disparo del vínculo (la puerta 2). */
|
|
2200
|
+
| {
|
|
2201
|
+
clase: "gestor";
|
|
2202
|
+
accion: "ajustarVinculo";
|
|
2203
|
+
estados: MapeoDeEstados;
|
|
2204
|
+
automatico: boolean;
|
|
2205
|
+
revisarEncargo?: boolean;
|
|
2206
|
+
} | {
|
|
2207
|
+
clase: "gestor";
|
|
2208
|
+
accion: "usarConector";
|
|
2209
|
+
conector: string;
|
|
2210
|
+
usar: boolean;
|
|
2211
|
+
} | {
|
|
2212
|
+
clase: "gestor";
|
|
2213
|
+
accion: "pendientes";
|
|
2214
|
+
texto?: string;
|
|
2215
|
+
mias?: boolean;
|
|
2216
|
+
}
|
|
2217
|
+
/** La descripción de una tarea (la fila desplegada del panel). De solo LECTURA. */
|
|
2218
|
+
| {
|
|
2219
|
+
clase: "gestor";
|
|
2220
|
+
accion: "ficha";
|
|
2221
|
+
clave: string;
|
|
2222
|
+
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Task 10 (IXCODE-11): las ÚNICAS cuatro acciones que ESCRIBEN en Jira, siempre por un
|
|
2225
|
+
* mensaje EXPLÍCITO del cliente —la persona aprobó una tarjeta—, nunca solas. `transiciones`
|
|
2226
|
+
* es de solo LECTURA (pide la lista); `empezar` con `transicion` transiciona ANTES de abrir
|
|
2227
|
+
* la sesión; `borradorDeCierre` también es de solo lectura (compone el texto, no lo manda);
|
|
2228
|
+
* `cerrar` comenta y, si hay `transicion`, transiciona.
|
|
2229
|
+
*/
|
|
2230
|
+
| {
|
|
2231
|
+
clase: "gestor";
|
|
2232
|
+
accion: "transiciones";
|
|
2233
|
+
clave: string;
|
|
2234
|
+
para: "empezar" | "cerrar";
|
|
2235
|
+
} | {
|
|
2236
|
+
clase: "gestor";
|
|
2237
|
+
accion: "empezar";
|
|
2238
|
+
clave: string;
|
|
2239
|
+
transicion?: string;
|
|
2240
|
+
} | {
|
|
2241
|
+
clase: "gestor";
|
|
2242
|
+
accion: "borradorDeCierre";
|
|
2243
|
+
} | {
|
|
2244
|
+
clase: "gestor";
|
|
2245
|
+
accion: "cerrar";
|
|
2246
|
+
comentario: string;
|
|
2247
|
+
transicion?: string;
|
|
2248
|
+
} | {
|
|
2249
|
+
clase: "fichero";
|
|
2250
|
+
ruta: string;
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Guardar lo que la persona editó. La única escritura del cliente en un fichero del proyecto:
|
|
2254
|
+
* sin tarjeta de aprobación porque lo teclea ella, con las guardas de ruta de leer y negada con
|
|
2255
|
+
* un turno o una tarea en marcha en esa raíz. `huella` es la del fichero que se cargó, y
|
|
2256
|
+
* `proyecto` el `proyectoActivo` con que se ABRIÓ la edición: si el foco ya es otro, se niega.
|
|
2257
|
+
*/
|
|
2258
|
+
| {
|
|
2259
|
+
clase: "guardarFichero";
|
|
2260
|
+
ruta: string;
|
|
2261
|
+
texto: string;
|
|
2262
|
+
huella: string;
|
|
2263
|
+
id: string;
|
|
2264
|
+
proyecto: string;
|
|
2265
|
+
/** Tras guardar, llevarlo al aparato de la sesión. Nunca hace fallar el guardado. */
|
|
2266
|
+
recargar?: true;
|
|
2267
|
+
}
|
|
2268
|
+
/** Pedir la base de comparación de un fichero: la foto del inicio de la sesión o el último commit. */
|
|
2269
|
+
| {
|
|
2270
|
+
clase: "baseDeFichero";
|
|
2271
|
+
ruta: string;
|
|
2272
|
+
base: "sesion" | "commit";
|
|
2273
|
+
}
|
|
2274
|
+
/**
|
|
2275
|
+
* La sincronización con CloudStudio del proyecto abierto (pestaña CloudStudio).
|
|
2276
|
+
* `estado` pide la medida; `subir` y `bajar` son las dos acciones de `/sync`.
|
|
2277
|
+
*
|
|
2278
|
+
* Viaja la INTENCIÓN, no la sintaxis: el servidor las aplica encolando `/sync <accion>`
|
|
2279
|
+
* en el lazo (`arranque.ts#atenderSync`), así que el plan, la guarda de árbol sucio y la
|
|
2280
|
+
* aprobación salen por donde ya salían — la aprobación es la pregunta de siempre, que es
|
|
2281
|
+
* la que autoriza la escritura. Un `git push` desde el cliente no existiría ni aunque
|
|
2282
|
+
* quisiéramos: la copia la mueve `agent/cloudstudio/subida.ts` llamando a las tools MCP.
|
|
2283
|
+
*/
|
|
2284
|
+
| {
|
|
2285
|
+
clase: "sync";
|
|
2286
|
+
accion: "estado" | "subir" | "bajar";
|
|
2287
|
+
}
|
|
2288
|
+
/**
|
|
2289
|
+
* El contenido de un artefacto de la sesión abierta. Se pide por NOMBRE y no por ruta: la
|
|
2290
|
+
* carpeta la compone el servidor con el id del hilo, y aceptar una ruta del cliente sería
|
|
2291
|
+
* abrir a negociación justo la parte que es una barrera.
|
|
2292
|
+
*/
|
|
2293
|
+
/** Con `proyecto` y `sesion`: el de esa conversación, que se LEE sin consola, contestado en la propia respuesta. */
|
|
2294
|
+
| {
|
|
2295
|
+
clase: "artefacto";
|
|
2296
|
+
nombre: string;
|
|
2297
|
+
proyecto?: string;
|
|
2298
|
+
sesion?: string;
|
|
2299
|
+
}
|
|
2300
|
+
/**
|
|
2301
|
+
* Ejecuta —o cancela— un paso de una receta de instalación.
|
|
2302
|
+
*
|
|
2303
|
+
* Viajan el NOMBRE de la receta y el NÚMERO del paso, nunca un comando ni un binario: un
|
|
2304
|
+
* comando que llegue del cliente es una shell abierta en la máquina del usuario. Qué se
|
|
2305
|
+
* lanza lo decide una tabla cerrada del host (`agent/dispositivos/instalacionEnMaquina.ts`).
|
|
2306
|
+
*/
|
|
2307
|
+
| {
|
|
2308
|
+
clase: "receta";
|
|
2309
|
+
id: string;
|
|
2310
|
+
paso: number;
|
|
2311
|
+
accion: "ejecutar" | "cancelar";
|
|
2312
|
+
}
|
|
2313
|
+
/** Los modelos que ofrece un MOTOR externo, para el desplegable de un subagente. Se pide
|
|
2314
|
+
* bajo demanda: el de Codex se le pregunta a él, y eso arranca un proceso. */
|
|
2315
|
+
| {
|
|
2316
|
+
clase: "modelosDeMotor";
|
|
2317
|
+
motor: string;
|
|
2318
|
+
}
|
|
2319
|
+
/** Medir el diagnóstico de Node (Ajustes → General, «Comprobar»). */
|
|
2320
|
+
| {
|
|
2321
|
+
clase: "diagnosticoNode";
|
|
2322
|
+
}
|
|
2323
|
+
/** El diseño vinculado (Stitch): leer, listar proyectos, vincular, desvincular o listar sus pantallas. */
|
|
2324
|
+
| {
|
|
2325
|
+
clase: "diseno";
|
|
2326
|
+
accion: "estado" | "proyectos" | "desvincular" | "pantallas";
|
|
2327
|
+
proyecto?: string;
|
|
2328
|
+
} | {
|
|
2329
|
+
clase: "diseno";
|
|
2330
|
+
accion: "vincular";
|
|
2331
|
+
proyecto?: string;
|
|
2332
|
+
vinculo: {
|
|
2333
|
+
proyecto: string;
|
|
2334
|
+
nombre: string;
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
/**
|
|
2338
|
+
* Una acción sobre un motor local. La INTENCIÓN, no el comando: qué binario y con qué
|
|
2339
|
+
* argumentos lo decide el servidor (`agent/motores/motoresLocales.ts`). `codigo` es el que la
|
|
2340
|
+
* web de Claude enseña al terminar cuando el navegador no pudo volver solo: va al `stdin` del
|
|
2341
|
+
* `auth login` en curso y a ningún otro sitio.
|
|
2342
|
+
*/
|
|
2343
|
+
| {
|
|
2344
|
+
clase: "motorLocal";
|
|
2345
|
+
accion: "medir" | "probar" | "login" | "codigo" | "cancelar" | "navegador" | "consola" | "modelo";
|
|
2346
|
+
motor?: string;
|
|
2347
|
+
modo?: "claudeai" | "console";
|
|
2348
|
+
codigo?: string;
|
|
2349
|
+
/** Con `accion: "modelo"`: el elegido (`proveedor/modelo`); ausente o vacío lo quita. */
|
|
2350
|
+
modelo?: string;
|
|
2351
|
+
}
|
|
2352
|
+
/**
|
|
2353
|
+
* Las acciones sobre una tarea. Viaja el ID del proyecto y su nombre, NUNCA su raíz: es
|
|
2354
|
+
* una ruta de la máquina, y el cable puede ir por un túnel.
|
|
2355
|
+
*/
|
|
2356
|
+
/**
|
|
2357
|
+
* `borrador` es el identificador bajo el que ya se subieron los adjuntos por
|
|
2358
|
+
* `POST /adjunto` — los bytes tienen que estar en disco ANTES de crear la tarea, porque
|
|
2359
|
+
* crear la encola y el corredor puede arrancarla en el acto. El servidor lo ADOPTA como
|
|
2360
|
+
* id de la tarea si es un segmento llano y no es ya una tarea; los adjuntos los lee del
|
|
2361
|
+
* disco, nunca de lo que diga el cliente.
|
|
2362
|
+
*/
|
|
2363
|
+
| {
|
|
2364
|
+
clase: "tarea";
|
|
2365
|
+
accion: "crear";
|
|
2366
|
+
proyecto: string;
|
|
2367
|
+
peticion: string; /** Vacío o ausente = lo prepara el servidor al encolar. */
|
|
2368
|
+
encargo?: string;
|
|
2369
|
+
borrador?: string;
|
|
2370
|
+
pantallaDeStitch?: {
|
|
2371
|
+
name: string;
|
|
2372
|
+
titulo: string;
|
|
2373
|
+
};
|
|
2374
|
+
} | {
|
|
2375
|
+
clase: "tarea";
|
|
2376
|
+
accion: "augmentar";
|
|
2377
|
+
proyecto: string;
|
|
2378
|
+
peticion: string;
|
|
2379
|
+
borrador?: string;
|
|
2380
|
+
pantallaDeStitch?: {
|
|
2381
|
+
name: string;
|
|
2382
|
+
titulo: string;
|
|
2383
|
+
};
|
|
2384
|
+
}
|
|
2385
|
+
/**
|
|
2386
|
+
* Una PROPUESTA de tareas encadenadas (el acto `propuesta-de-tareas`): encolarla en orden o
|
|
2387
|
+
* descartarla. Viaja el id de la propuesta y, al encolar, los encargos que la persona revisó (la
|
|
2388
|
+
* petición del orquestador, que no se vuelve a redactar), UNO por tarea y en orden; títulos, peticiones y adjuntos los saca el servidor del
|
|
2389
|
+
* acto, nunca del cliente. Encolar contesta en la propia respuesta: `{encoladas, faltan?}` o 409
|
|
2390
|
+
* con `{motivo}`.
|
|
2391
|
+
*/
|
|
2392
|
+
/** `enChat`: se descarta para hacerlo en ESTA conversación; el cliente manda luego la prosa que lo pide. */
|
|
2393
|
+
| {
|
|
2394
|
+
clase: "tarea";
|
|
2395
|
+
accion: "descartarPropuesta";
|
|
2396
|
+
proyecto: string;
|
|
2397
|
+
propuesta: string;
|
|
2398
|
+
enChat?: true;
|
|
2399
|
+
} | {
|
|
2400
|
+
clase: "tarea";
|
|
2401
|
+
accion: "crearEncadenadas";
|
|
2402
|
+
proyecto: string;
|
|
2403
|
+
propuesta: string;
|
|
2404
|
+
encargos: string[];
|
|
2405
|
+
}
|
|
2406
|
+
/**
|
|
2407
|
+
* «Se edita la tarea y se agrega el feedback del usuario» (§0 del diseño): la respuesta a
|
|
2408
|
+
* una tarea «esperando feedback», que la devuelve al lazo en su MISMO hilo. Es su propia
|
|
2409
|
+
* variante y no un tercer campo opcional en `reintentar` porque lleva `texto` y las otras
|
|
2410
|
+
* tres no llevan nada — un campo que solo tiene sentido en una de cuatro acciones es la
|
|
2411
|
+
* misma mentira por omisión que una lista vacía rellenada.
|
|
2412
|
+
*/
|
|
2413
|
+
| {
|
|
2414
|
+
clase: "tarea";
|
|
2415
|
+
accion: "feedback";
|
|
2416
|
+
id: string;
|
|
2417
|
+
texto: string;
|
|
2418
|
+
}
|
|
2419
|
+
/**
|
|
2420
|
+
* «Continuar» una tarea aparcada sin escribir nada (entra en su hilo `TEXTO_DE_CONTINUAR`), y «Arrancar ahora» una
|
|
2421
|
+
* `nuevo` que no espera a ninguna anterior: la persona CEDE el proyecto —se cierra su consola de ahí si no está
|
|
2422
|
+
* trabajando— y la tarea arranca. Las dos contestan 409 con `{motivo}` si no se puede.
|
|
2423
|
+
*/
|
|
2424
|
+
| {
|
|
2425
|
+
clase: "tarea";
|
|
2426
|
+
accion: "continuar";
|
|
2427
|
+
id: string;
|
|
2428
|
+
} | {
|
|
2429
|
+
clase: "tarea";
|
|
2430
|
+
accion: "arrancarAhora";
|
|
2431
|
+
id: string;
|
|
2432
|
+
}
|
|
2433
|
+
/** Editar el encargo de una tarea que todavía no ha arrancado (IXCODE-52). 204, o 409 con `{motivo}`. */
|
|
2434
|
+
| {
|
|
2435
|
+
clase: "tarea";
|
|
2436
|
+
accion: "encargo";
|
|
2437
|
+
id: string;
|
|
2438
|
+
encargo: string;
|
|
2439
|
+
peticion?: string;
|
|
2440
|
+
pantallaDeStitch?: {
|
|
2441
|
+
name: string;
|
|
2442
|
+
titulo: string;
|
|
2443
|
+
} | null;
|
|
2444
|
+
}
|
|
2445
|
+
/** Volver a preparar el encargo desde la petición editada, SIN guardarlo (IXCODE-53). 200 con `{encargo}`, o 409 con `{motivo}`. */
|
|
2446
|
+
| {
|
|
2447
|
+
clase: "tarea";
|
|
2448
|
+
accion: "regenerarEncargo";
|
|
2449
|
+
id: string;
|
|
2450
|
+
peticion: string;
|
|
2451
|
+
}
|
|
2452
|
+
/** Con qué gestor vivirá una tarea nueva de ese proyecto: contestado en la propia respuesta, `{gestor?: {conector, proyecto}}`. */
|
|
2453
|
+
| {
|
|
2454
|
+
clase: "tarea";
|
|
2455
|
+
accion: "destino";
|
|
2456
|
+
proyecto: string;
|
|
2457
|
+
}
|
|
2458
|
+
/** «Mirar ahora»: una pasada del sondeo del gestor (la puerta 2), contestada con lo que hizo. */
|
|
2459
|
+
| {
|
|
2460
|
+
clase: "tarea";
|
|
2461
|
+
accion: "mirarGestor";
|
|
2462
|
+
}
|
|
2463
|
+
/** PARAR una tarea en marcha sin borrarla (IXCODE-50): queda aparcada con su conversación. 204, o 409 con `{motivo}`. */
|
|
2464
|
+
| {
|
|
2465
|
+
clase: "tarea";
|
|
2466
|
+
accion: "parar";
|
|
2467
|
+
id: string;
|
|
2468
|
+
} | {
|
|
2469
|
+
clase: "tarea";
|
|
2470
|
+
accion: "reintentar" | "descartar" | "terminar";
|
|
2471
|
+
id: string;
|
|
2472
|
+
}
|
|
2473
|
+
/** Cambia el tope de concurrencia de la cola de tareas. */
|
|
2474
|
+
| {
|
|
2475
|
+
clase: "tareas";
|
|
2476
|
+
concurrencia: number;
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Elige dónde se bajan las copias locales. Acepta `~/…` y absolutas; la regla de qué vale
|
|
2480
|
+
* es `core/settings.ts#motivoDeWorkspaceInaceptable`, y se aplica en el SERVIDOR además de
|
|
2481
|
+
* en la pantalla — el cliente lleva su copia DECLARADA, como la de la URL de un entorno y
|
|
2482
|
+
* la del slug de un subagente, porque la frontera prohíbe compartir módulo.
|
|
2483
|
+
*
|
|
2484
|
+
* **MUDA lo que ya está bajado** (`vestibulo.mudarWorkspace`), en dos actos: `planear`
|
|
2485
|
+
* contesta en la PROPIA respuesta qué se movería o por qué no se puede, sin tocar nada; sin
|
|
2486
|
+
* `accion` (o con `aplicar`) se cambia de verdad, y el recorrido llega por
|
|
2487
|
+
* `mudanzaDeWorkspace`.
|
|
2488
|
+
*/
|
|
2489
|
+
| {
|
|
2490
|
+
clase: "workspace";
|
|
2491
|
+
ruta: string;
|
|
2492
|
+
accion?: "planear" | "aplicar";
|
|
2493
|
+
}
|
|
2494
|
+
/** Cambia la casilla «Depurar» de Ajustes > General. */
|
|
2495
|
+
| {
|
|
2496
|
+
clase: "depuracion";
|
|
2497
|
+
activa: boolean;
|
|
2498
|
+
}
|
|
2499
|
+
/** Abre el selector de carpeta NATIVO **de la máquina donde corre la consola** — ver
|
|
2500
|
+
* `core/selectorDeCarpeta.ts` para por qué no lo puede poner el navegador. */
|
|
2501
|
+
| {
|
|
2502
|
+
clase: "elegirCarpeta";
|
|
2503
|
+
}
|
|
2504
|
+
/**
|
|
2505
|
+
* Empezar (`ver: true`) o dejar de mirar en vivo lo que hace una tarea.
|
|
2506
|
+
*
|
|
2507
|
+
* **`cliente` es lo que hace que esto sea por CLIENTE y no una emisión a todos.** El SSE
|
|
2508
|
+
* y el `POST /accion` son dos peticiones distintas, así que el único sitio con un sumidero
|
|
2509
|
+
* en la mano es la ruta del SSE: sin un identificador, el servidor no podría saber a qué
|
|
2510
|
+
* pestaña engancharle la mirada, y tendría que mandarle el transcript de la tarea a todo
|
|
2511
|
+
* el mundo. Lo elige el cliente —una vez por conexión— igual que elige el id de una tarea
|
|
2512
|
+
* al subirle un adjunto por `POST /adjunto`, y se valida como un segmento llano; uno que
|
|
2513
|
+
* no conste es un fallo de lookup y no un error que contar.
|
|
2514
|
+
*
|
|
2515
|
+
* `ver` es explícito y no «ausente = dejar de mirar»: son dos intenciones opuestas y
|
|
2516
|
+
* confundirlas dejaría un sumidero enganchado a un turno que nadie mira.
|
|
2517
|
+
*/
|
|
2518
|
+
| {
|
|
2519
|
+
clase: "mirar";
|
|
2520
|
+
tarea: string;
|
|
2521
|
+
ver: boolean;
|
|
2522
|
+
cliente: string;
|
|
2523
|
+
}
|
|
2524
|
+
/**
|
|
2525
|
+
* Vuelve a MEDIR si se puede lanzar la app del proyecto abierto, y contesta con un `lanzable`.
|
|
2526
|
+
*
|
|
2527
|
+
* Sin datos, y no es una comodidad: el veredicto se compone de la elección de dispositivo de
|
|
2528
|
+
* la SESIÓN, de la última medida de la máquina y de los descriptores del PROYECTO abierto —
|
|
2529
|
+
* tres cosas que el navegador no tiene y sobre las que no es fuente. Que el cliente pudiera
|
|
2530
|
+
* mandar «lanza el proyecto X en el aparato Y» sería abrir a negociación justo lo que decide
|
|
2531
|
+
* si se lanza o no.
|
|
2532
|
+
*/
|
|
2533
|
+
| {
|
|
2534
|
+
clase: "revisarLanzamiento";
|
|
2535
|
+
}
|
|
2536
|
+
/**
|
|
2537
|
+
* Lanza la app del proyecto abierto en el dispositivo de la sesión.
|
|
2538
|
+
*
|
|
2539
|
+
* **Sin datos tampoco, y aquí es la regla entera**: ni el dispositivo, ni el nombre de la app,
|
|
2540
|
+
* ni una ruta, ni siquiera el proyecto — los tres primeros son datos sobre la máquina y sobre
|
|
2541
|
+
* el proyecto, y el cuarto lo resuelve el servidor de la consola que atiende. Y el servidor
|
|
2542
|
+
* **revalida antes de empezar**: entre el veredicto y este clic pueden pasar minutos, y un
|
|
2543
|
+
* `lanzarApp` sobre un proyecto que ya no cumple se contesta con un `lanzamiento` en `fallo`,
|
|
2544
|
+
* no lanzando a ciegas.
|
|
2545
|
+
*/
|
|
2546
|
+
| {
|
|
2547
|
+
clase: "lanzarApp";
|
|
2548
|
+
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Para el lanzamiento en curso. Es parar ESTO, no cerrar nada — la misma distinción que
|
|
2551
|
+
* `cancelar` con un turno: el recorrido queda en `cancelada` con lo que ya se había contado.
|
|
2552
|
+
*
|
|
2553
|
+
* Un lanzamiento a la vez por consola, así que no lleva id: no hay dos entre los que elegir.
|
|
2554
|
+
*/
|
|
2555
|
+
| {
|
|
2556
|
+
clase: "cancelarLanzamiento";
|
|
2557
|
+
}
|
|
2558
|
+
/**
|
|
2559
|
+
* Llevar un fichero ya guardado al aparato de la sesión. `probar`: si la app no corre, desplegar
|
|
2560
|
+
* el proyecto entero (lo de Ejecutar). `relanzar`: relanzar la app (lo que pide un CSS).
|
|
2561
|
+
*/
|
|
2562
|
+
| {
|
|
2563
|
+
clase: "recargarEnAparato";
|
|
2564
|
+
ruta: string;
|
|
2565
|
+
probar?: true;
|
|
2566
|
+
relanzar?: true;
|
|
2567
|
+
}
|
|
2568
|
+
/**
|
|
2569
|
+
* Una acción sobre UN conector: añadirlo, quitarlo, probarlo, autorizarlo, desconectarlo o
|
|
2570
|
+
* darlo de alta a mano. Una `accion` que no sea una de esas seis se rechaza con 400 y no hace
|
|
2571
|
+
* nada.
|
|
2572
|
+
*
|
|
2573
|
+
* **Son DOS formas y no una con campos opcionales**, porque `crear` no lleva `id`: el id lo
|
|
2574
|
+
* DERIVA el servidor del nombre (y por eso tampoco se puede elegir desde fuera, que sería
|
|
2575
|
+
* dejar que el cliente nombre una clave de fichero). Su `definicion` viaja sin comprobar por
|
|
2576
|
+
* tipo —un cliente puede mentir sobre lo que el tipo promete— y quien la mira de verdad es
|
|
2577
|
+
* `definicionDelCable` en el servidor.
|
|
2578
|
+
*
|
|
2579
|
+
* El resultado NO viaja en la respuesta: `probar` y `autorizar` corren en segundo plano
|
|
2580
|
+
* (red, o esperar al navegador) y lo que cambien llega por el `conectores` que sigue, vía
|
|
2581
|
+
* `alCambiar` del servicio — el mismo molde que `dispositivo`/`conexion`.
|
|
2582
|
+
*/
|
|
2583
|
+
| {
|
|
2584
|
+
clase: "conector";
|
|
2585
|
+
accion: "crear";
|
|
2586
|
+
definicion: DefinicionDeConector;
|
|
2587
|
+
} | {
|
|
2588
|
+
clase: "conector";
|
|
2589
|
+
accion: "anadir" | "quitar" | "probar" | "autorizar" | "desconectar";
|
|
2590
|
+
id: string;
|
|
2591
|
+
} | {
|
|
2592
|
+
clase: "decision";
|
|
2593
|
+
decisiones: Record<string, string>;
|
|
2594
|
+
};
|
|
2595
|
+
/**
|
|
2596
|
+
* Un subagente tal y como viaja: los campos del `.md` y de dónde salió.
|
|
2597
|
+
*
|
|
2598
|
+
* `origen` es de solo lectura —lo pone el servidor al leer— y sirve para que la ventana
|
|
2599
|
+
* pueda decir si un agente viene del global o del proyecto, que es lo que explica por qué
|
|
2600
|
+
* editarlo aquí no afecta a los demás proyectos.
|
|
2601
|
+
*/
|
|
2602
|
+
export interface AgenteDelCable {
|
|
2603
|
+
nombre: string;
|
|
2604
|
+
descripcion: string;
|
|
2605
|
+
motor: string;
|
|
2606
|
+
modelo?: string;
|
|
2607
|
+
soloLectura: boolean;
|
|
2608
|
+
/**
|
|
2609
|
+
* Si puede EJECUTAR comandos en la máquina. **Ausente es que no**: es una capacidad, y una
|
|
2610
|
+
* capacidad que se concede por omisión es la que nadie decidió conceder.
|
|
2611
|
+
*
|
|
2612
|
+
* Solo tiene efecto con `motor: "modelo"`; en los tres externos la shell está cerrada a
|
|
2613
|
+
* propósito y esto no la abre, así que la ventana lo dice en vez de pintar una casilla
|
|
2614
|
+
* marcada que no hace nada.
|
|
2615
|
+
*/
|
|
2616
|
+
ejecucion?: boolean;
|
|
2617
|
+
/**
|
|
2618
|
+
* Cuánto razona su modelo antes de contestar. Ausente = no se manda el parámetro.
|
|
2619
|
+
*
|
|
2620
|
+
* Solo tiene efecto con `motor: "modelo"`: en los tres externos el modelo lo construye el
|
|
2621
|
+
* hijo en su proceso y un campo nuestro no llega hasta allí. Qué niveles admite depende
|
|
2622
|
+
* del modelo elegido (`core/esfuerzo.ts`), y por eso la ventana lo pinta pegado a él.
|
|
2623
|
+
*/
|
|
2624
|
+
esfuerzo?: Esfuerzo;
|
|
2625
|
+
skills: string[];
|
|
2626
|
+
instrucciones: string;
|
|
2627
|
+
origen?: string;
|
|
2628
|
+
/**
|
|
2629
|
+
* De quién es el fichero, que NO es lo mismo que `origen` —esa es la carpeta— y decide qué
|
|
2630
|
+
* botón lleva la tarjeta: ausente, la papelera; `modificada`, «Restaurar el de serie».
|
|
2631
|
+
* Los tres estados y su porqué, en `core/agentes.ts#AgenteCargado`.
|
|
2632
|
+
*/
|
|
2633
|
+
semilla?: "intacta" | "modificada";
|
|
2634
|
+
}
|
|
2635
|
+
/**
|
|
2636
|
+
* Una skill tal como viaja: nunca su carpeta, que es una ruta de la máquina (`sinRutas`).
|
|
2637
|
+
*
|
|
2638
|
+
* **`cuerpo` solo lo llevan las del usuario, y su ausencia significa «esta no se edita».**
|
|
2639
|
+
* Las de serie son nueve ficheros que pueden pasar de veinte mil caracteres cada uno: si
|
|
2640
|
+
* viajaran todas en la ráfaga de bienvenida, abrir la consola costaría cientos de kilobytes
|
|
2641
|
+
* para rellenar un formulario que nadie puede guardar. Se piden una a una cuando alguien
|
|
2642
|
+
* quiere verlas o copiarlas (`clase: "cuerpoDeSkill"`), que es cuando el coste se justifica.
|
|
2643
|
+
*
|
|
2644
|
+
* `origen` dice de DÓNDE sale y es de solo lectura: separa las dos pestañas y explica por
|
|
2645
|
+
* qué editar la del proyecto no toca a los demás proyectos. `ficheros` son los anexos por
|
|
2646
|
+
* NOMBRE y sin contenido — una skill puede ser una carpeta entera, y una ventana que solo
|
|
2647
|
+
* enseña el `SKILL.md` haría creer que editarlo es editarla toda.
|
|
2648
|
+
*/
|
|
2649
|
+
export interface SkillDelCable {
|
|
2650
|
+
nombre: string;
|
|
2651
|
+
descripcion: string;
|
|
2652
|
+
origen: "serie" | "global" | "proyecto";
|
|
2653
|
+
tokens: number;
|
|
2654
|
+
ficheros: string[];
|
|
2655
|
+
/**
|
|
2656
|
+
* El frontmatter del `SKILL.md` tal cual, sin los `---`.
|
|
2657
|
+
*
|
|
2658
|
+
* Viaja SIEMPRE —también en las de serie— y no con el cuerpo, porque son cuatro líneas y
|
|
2659
|
+
* es lo que contesta «qué declara este fichero»: `description` no es lo único que puede
|
|
2660
|
+
* haber ahí (`archify` lleva `license` y un bloque `metadata`), y enseñar solo la
|
|
2661
|
+
* descripción haría creer que eso es todo. Al guardar vuelve, y `escribirSkill` conserva
|
|
2662
|
+
* las claves que no entendemos en vez de borrárselas al usuario en silencio.
|
|
2663
|
+
*/
|
|
2664
|
+
frontmatter?: string;
|
|
2665
|
+
/** Ausente en las de serie, y en la que se está creando. Ver arriba. */
|
|
2666
|
+
cuerpo?: string;
|
|
2667
|
+
}
|
|
2668
|
+
/** A dónde escribe el SSE. Ausente = no hay nadie al otro lado. */
|
|
2669
|
+
export type Sumidero = (mensaje: MensajeAlCliente) => void;
|
|
2670
|
+
export interface Transporte {
|
|
2671
|
+
/**
|
|
2672
|
+
* Un cliente abre el SSE. Devuelve los actos que hay que reemitirLE: quien registra la
|
|
2673
|
+
* ruta los manda como una `reemision` con su propia escritura —solo a ese sumidero—, así
|
|
2674
|
+
* que esto NO los emite; hacerlo se los mandaría también a los demás clientes, que ya
|
|
2675
|
+
* tienen el transcript.
|
|
2676
|
+
*
|
|
2677
|
+
* **Se admite más de uno.** Antes había UNA ranura y el último en conectar desplazaba al
|
|
2678
|
+
* anterior en silencio: la pestaña vieja se quedaba con el SSE abierto y sin recibir
|
|
2679
|
+
* nada, así que su interfaz se congelaba en el último estado que le llegó —medido con
|
|
2680
|
+
* una pestaña local y otra por un túnel: el menú de modelos se quedaba en «consultando…»
|
|
2681
|
+
* para siempre porque la respuesta se la llevaba la otra—. Un servidor que acepta la
|
|
2682
|
+
* conexión tiene que hablarle.
|
|
2683
|
+
*/
|
|
2684
|
+
conectar(enviar?: Sumidero): readonly Acto[];
|
|
2685
|
+
/**
|
|
2686
|
+
* Un SSE se cae, o se cierra una pestaña. Con el sumidero se dice CUÁL se va; sin él se
|
|
2687
|
+
* van todos (es lo que hace `cerrar`).
|
|
2688
|
+
*
|
|
2689
|
+
* Fail-closed sigue significando lo mismo, pero sobre el conjunto: quien espera respuesta
|
|
2690
|
+
* deja de esperar cuando se va el ÚLTIMO cliente, no el primero. Cortar a la primera baja
|
|
2691
|
+
* rechazaría la aprobación que otra pestaña abierta todavía tiene delante.
|
|
2692
|
+
*/
|
|
2693
|
+
desconectar(enviar?: Sumidero): void;
|
|
2694
|
+
/**
|
|
2695
|
+
* El cable se MUDA a otra consola: se sueltan los sumideros y NADA más.
|
|
2696
|
+
*
|
|
2697
|
+
* La diferencia con `desconectar` es toda la razón de que exista, y es de significado, no
|
|
2698
|
+
* de implementación: `desconectar` afirma «se ha ido el humano» —despierta con la cadena
|
|
2699
|
+
* vacía a todo el que esperaba respuesta y da por rechazada la aprobación que hubiera
|
|
2700
|
+
* delante—, y eso es cierto cuando el SSE se cae y FALSO cuando alguien cambia de sesión
|
|
2701
|
+
* en la barra teniendo esta con un turno corriendo: la persona sigue ahí, mirando otra
|
|
2702
|
+
* cosa. Con `soltar`, `conectado()` sigue diciendo que hay alguien —así que su aprobación
|
|
2703
|
+
* espera su plazo en vez de rechazarse sola— y lo que se emita mientras tanto no llega a
|
|
2704
|
+
* ningún socket, que es exactamente lo que se quiere: los actos de un turno de segundo
|
|
2705
|
+
* plano no pueden aparecer en la conversación que se está mirando.
|
|
2706
|
+
*
|
|
2707
|
+
* Los MIRONES no se sueltan: los quita `dejarDeMirar`, y aquí la consola no se cierra
|
|
2708
|
+
* —su socket sigue vivo—, al contrario que en `desconectar()` sin sumidero.
|
|
2709
|
+
*/
|
|
2710
|
+
soltar(enviar?: Sumidero): void;
|
|
2711
|
+
/** ¿Queda alguien al otro lado? Es lo que `consolaWeb.eof()` usa para saber si hay humano. */
|
|
2712
|
+
conectado(): boolean;
|
|
2713
|
+
/**
|
|
2714
|
+
* Alguien MIRA lo que esta consola pinta, sin ser su cliente. Devuelve el transcript de
|
|
2715
|
+
* ese instante, igual que `conectar` y por lo mismo: emitirlo aquí se lo mandaría también
|
|
2716
|
+
* a los demás, que ya lo tienen.
|
|
2717
|
+
*
|
|
2718
|
+
* Es un conjunto APARTE del de los clientes, y las dos diferencias son el motivo de que
|
|
2719
|
+
* exista en vez de reusar `conectar`:
|
|
2720
|
+
* - **No cuenta como cliente**, así que `conectado()` —y con él `consolaWeb.eof()`— sigue
|
|
2721
|
+
* diciendo la verdad. Medido antes de escribir esto: con un `conectar` de más, el
|
|
2722
|
+
* `eof()` de la consola de una tarea de fondo pasaba de `true` a `false`, o sea «hay un
|
|
2723
|
+
* humano al que preguntar». Y no lo hay: esta vista es de SOLO lectura, no tiene
|
|
2724
|
+
* compositor y nadie puede contestar una pregunta ni aprobar una escritura desde ahí.
|
|
2725
|
+
* Irse el último mirón tampoco dispara `alDesconectar`: no ha dejado a nadie sin
|
|
2726
|
+
* contestar.
|
|
2727
|
+
* - **Recibe SOLO el transcript** (`acto`, `sustitucion`, `reemision`). Por el transporte
|
|
2728
|
+
* de una consola de tarea viaja además el mensaje `turno` de los flancos —lo emite el
|
|
2729
|
+
* envoltorio del ejecutor sin mirar `alCable`, medido—, y ese mensaje apagaría el
|
|
2730
|
+
* compositor de quien mira por un turno que no es suyo. La lista es BLANCA a propósito:
|
|
2731
|
+
* una clase nueva no llega a un mirón hasta que alguien la nombre aquí.
|
|
2732
|
+
*/
|
|
2733
|
+
mirar(enviar: Sumidero): readonly Acto[];
|
|
2734
|
+
/** Se va UN mirón. Los demás siguen: dos personas pueden mirar la misma tarea. */
|
|
2735
|
+
dejarDeMirar(enviar: Sumidero): void;
|
|
2736
|
+
/**
|
|
2737
|
+
* Produce un mensaje: lo anota en la traza y, si hay cliente, lo escribe. Anota aunque
|
|
2738
|
+
* no haya nadie porque la traza cuenta lo que el servidor PRODUJO — que es lo que los
|
|
2739
|
+
* tests de «esto no viaja» tienen que poder mirar.
|
|
2740
|
+
*/
|
|
2741
|
+
emitir(mensaje: MensajeAlCliente): void;
|
|
2742
|
+
/**
|
|
2743
|
+
* La traza de todo lo producido MENOS la aprobación. No es una lista arbitraria: es la
|
|
2744
|
+
* frontera del invariante — el contenido de fichero está en el mensaje de aprobación y
|
|
2745
|
+
* en ninguna otra clase de mensaje, y así un test lo puede afirmar sobre todo el resto.
|
|
2746
|
+
*/
|
|
2747
|
+
emitidos(): readonly MensajeAlCliente[];
|
|
2748
|
+
/** Se llama al desconectar: por aquí se despierta a todo el que esperaba respuesta. */
|
|
2749
|
+
alDesconectar(escucha: () => void): void;
|
|
2750
|
+
}
|
|
2751
|
+
export declare function crearTransporte(actos: () => readonly Acto[]): Transporte;
|