xonecode 0.31.0 → 0.34.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-ChyJtiiz.js → EditorDeFichero-Cj0knNmP.js} +1 -1
- package/apps/web/dist/assets/index-Ga8fTlWp.js +499 -0
- package/apps/web/dist/assets/{index-IptObD2z.css → index-R3kXj69E.css} +1 -1
- package/apps/web/dist/assets/{php-B91ZcS-9.js → php-MVUx_K96.js} +1 -1
- package/apps/web/dist/assets/{ruby-DrxrTSz0.js → ruby-n-r-AXdi.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/dist/agent/config/fuentesEnRed.js +80 -0
- package/dist/agent/config/fuentesEnRed.js.map +1 -0
- package/dist/agent/config/modelosDeMotor.js +4 -2
- package/dist/agent/config/modelosDeMotor.js.map +1 -1
- package/dist/agent/config/settingsEnDisco.js +26 -0
- package/dist/agent/config/settingsEnDisco.js.map +1 -1
- package/dist/agent/dispositivos/cajasDeMaqueta.js +218 -0
- package/dist/agent/dispositivos/cajasDeMaqueta.js.map +1 -0
- package/dist/agent/dispositivos/geometriaEnDisco.js +107 -0
- package/dist/agent/dispositivos/geometriaEnDisco.js.map +1 -0
- package/dist/agent/dispositivos/juezVisual.js +84 -3
- package/dist/agent/dispositivos/juezVisual.js.map +1 -1
- package/dist/agent/grafo/criticaVisual.js +246 -11
- package/dist/agent/grafo/criticaVisual.js.map +1 -1
- package/dist/agent/grafo/fuentesDeGoogle.js +133 -0
- package/dist/agent/grafo/fuentesDeGoogle.js.map +1 -0
- package/dist/agent/grafo/incorporarAdjunto.js +52 -42
- package/dist/agent/grafo/incorporarAdjunto.js.map +1 -1
- package/dist/agent/grafo/lectorDeReferencias.js +21 -0
- package/dist/agent/grafo/lectorDeReferencias.js.map +1 -1
- package/dist/agent/grafo/perfiles.js +2 -0
- package/dist/agent/grafo/perfiles.js.map +1 -1
- package/dist/agent/motores/motoresLocales.js +429 -0
- package/dist/agent/motores/motoresLocales.js.map +1 -0
- package/dist/agent/motores/trueforge/capacidades.js +9 -6
- package/dist/agent/motores/trueforge/capacidades.js.map +1 -1
- package/dist/agent/motores/trueforge/informesDeHijos.js +39 -7
- package/dist/agent/motores/trueforge/informesDeHijos.js.map +1 -1
- package/dist/agent/motores/trueforge/memoriaDeEspecialistas.js +75 -37
- package/dist/agent/motores/trueforge/memoriaDeEspecialistas.js.map +1 -1
- package/dist/agent/motores/trueforge/memoriaTrueforge.js +24 -4
- package/dist/agent/motores/trueforge/memoriaTrueforge.js.map +1 -1
- package/dist/agent/motores/trueforge/modeloLangchain.js +28 -4
- package/dist/agent/motores/trueforge/modeloLangchain.js.map +1 -1
- package/dist/agent/motores/trueforge/proponerTareas.js +67 -0
- package/dist/agent/motores/trueforge/proponerTareas.js.map +1 -0
- package/dist/agent/motores/trueforge/sesionTrueforge.js +133 -13
- package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
- package/dist/agent/motores/trueforge/toolsDeFichero.js +24 -6
- package/dist/agent/motores/trueforge/toolsDeFichero.js.map +1 -1
- package/dist/agent/sesiones/adjuntosDeSesion.js +192 -5
- package/dist/agent/sesiones/adjuntosDeSesion.js.map +1 -1
- package/dist/agent/subagentes/agentesEnDisco.js +12 -4
- package/dist/agent/subagentes/agentesEnDisco.js.map +1 -1
- package/dist/agent/subagentes/ejecutableEnWindows.js +139 -0
- package/dist/agent/subagentes/ejecutableEnWindows.js.map +1 -0
- package/dist/agent/subagentes/subagenteCodex.js +7 -2
- package/dist/agent/subagentes/subagenteCodex.js.map +1 -1
- package/dist/agent/subagentes/subagenteOpencode.js +12 -5
- package/dist/agent/subagentes/subagenteOpencode.js.map +1 -1
- package/dist/agent/tareas/aumentador.js +4 -3
- package/dist/agent/tareas/aumentador.js.map +1 -1
- package/dist/agent/turno/informeDeTraza.js +2 -1
- package/dist/agent/turno/informeDeTraza.js.map +1 -1
- package/dist/agent/turno/interrupts.js +12 -0
- package/dist/agent/turno/interrupts.js.map +1 -1
- package/dist/agent/turno/resumenDeTool.js +4 -0
- package/dist/agent/turno/resumenDeTool.js.map +1 -1
- package/dist/agent/turno/turnoReal.js +3 -0
- package/dist/agent/turno/turnoReal.js.map +1 -1
- package/dist/cli/consola.js.map +1 -1
- package/dist/cli/main.js +2 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/tui/transcript.js +5 -0
- package/dist/cli/tui/transcript.js.map +1 -1
- package/dist/core/actos.js.map +1 -1
- package/dist/core/adjuntos.js +10 -2
- package/dist/core/adjuntos.js.map +1 -1
- package/dist/core/agentes.js +10 -0
- package/dist/core/agentes.js.map +1 -1
- package/dist/core/analisisDeSesion.js +1 -1
- package/dist/core/analisisDeSesion.js.map +1 -1
- package/dist/core/descripcionDePantalla.js +367 -0
- package/dist/core/descripcionDePantalla.js.map +1 -0
- package/dist/core/estiloMedido.js +352 -0
- package/dist/core/estiloMedido.js.map +1 -0
- package/dist/core/fuentes.js +174 -0
- package/dist/core/fuentes.js.map +1 -0
- package/dist/core/geometriaDePantalla.js +537 -0
- package/dist/core/geometriaDePantalla.js.map +1 -0
- package/dist/core/motoresLocales.js +128 -0
- package/dist/core/motoresLocales.js.map +1 -0
- package/dist/core/notify.js +4 -0
- package/dist/core/notify.js.map +1 -1
- package/dist/core/nucleoXone.js +6 -6
- package/dist/core/nucleoXone.js.map +1 -1
- package/dist/core/ports.js +35 -0
- package/dist/core/ports.js.map +1 -1
- package/dist/core/repartoDeEncargo.js +87 -0
- package/dist/core/repartoDeEncargo.js.map +1 -0
- package/dist/core/settings.js +5 -0
- package/dist/core/settings.js.map +1 -1
- package/dist/core/shellDeAgente.js +36 -0
- package/dist/core/shellDeAgente.js.map +1 -1
- package/dist/core/tareas.js +7 -0
- package/dist/core/tareas.js.map +1 -1
- package/dist/core/turno.js +15 -0
- package/dist/core/turno.js.map +1 -1
- package/dist/core/zipDeAdjunto.js +79 -0
- package/dist/core/zipDeAdjunto.js.map +1 -0
- package/dist/web/servidor/arranque.js +201 -13
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/consolaWeb.js +5 -0
- package/dist/web/servidor/consolaWeb.js.map +1 -1
- package/dist/web/servidor/interrupcion.js +52 -0
- package/dist/web/servidor/interrupcion.js.map +1 -0
- package/dist/web/servidor/pielWeb.js +36 -0
- package/dist/web/servidor/pielWeb.js.map +1 -1
- package/dist/web/servidor/transporte.js +1 -0
- package/dist/web/servidor/transporte.js.map +1 -1
- package/dist/web/servidor/vestibulo.js +30 -2
- package/dist/web/servidor/vestibulo.js.map +1 -1
- package/package.json +1 -1
- package/skills/xone-development/SKILL.md +2 -1
- package/skills/xone-development/references/css/buenas-practicas-y-parser.md +2 -1
- package/skills/xone-development/references/css/de-una-maqueta-a-xone.md +83 -0
- package/skills/xone-development/references/css/patrones-material-y-temas.md +15 -13
- package/skills/xone-development/references/css/propiedades-y-herencia.md +2 -2
- package/skills/xone-development/references/css/selectores-unidades-colores.md +8 -3
- package/skills/xone-development/references/indice-completo.md +1 -0
- package/skills/xone-development/references/xml-ui/atributos-coll-group-frame.md +4 -4
- package/skills/xone-development/references/xml-ui/nodos-group-y-frame.md +4 -4
- package/skills/xone-hotswap/lib/geometria.mjs +147 -0
- package/skills/xone-hotswap/scripts/xone-captura-android +6 -0
- package/skills/xone-hotswap/scripts/xone-hotswap +8 -0
- package/skills/xone-hotswap/scripts/xone-recargar-android +15 -0
- package/apps/web/dist/assets/index-CFIrUOmW.js +0 -499
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { TOPE_DE_PREGUNTAS_CONTESTADAS_SOLAS, opcionRecomendada } from "../../../core/modoDeEscritura.js";
|
|
27
27
|
import { claseDeTrabajo } from "../../../core/esfuerzo.js";
|
|
28
|
-
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
28
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
29
29
|
import { join } from "node:path";
|
|
30
30
|
import winston from "winston";
|
|
31
31
|
import { AgentThread, AgentThreadOrchestrator, EventType, NOOP_AGENT_TRACING, askUserQuestion, contextCompaction, dynamicSubAgents } from "./trueforge.js";
|
|
@@ -59,16 +59,17 @@ import { anuncioDeSkills } from "./skillsTrueforge.js";
|
|
|
59
59
|
import { capabilitiesDe, capacidadDeFecha, capacidadDeFicheros, capacidadDeAvisoDeVueltas, capacidadDeInstrucciones, capacidadDeNotas, capacidadDeConectores, capacidadDePropias, capacidadDeRecortes, capacidadesDelEspecialista, clasesDeTools, toolsDe, } from "./capacidades.js";
|
|
60
60
|
import { crearConectoresDeSesion, tarjetaDeRemota } from "./toolsDeConectores.js";
|
|
61
61
|
import { CONECTOR_STITCH, crearTraerDeStitch } from "./traerDeStitch.js";
|
|
62
|
+
import { crearProponerTareas, REPARTIR_EN_TAREAS } from "./proponerTareas.js";
|
|
62
63
|
import { esDeLaMaqueta } from "../../../core/stitch.js";
|
|
63
64
|
import { recibeConectores } from "../../../core/conectores.js";
|
|
64
65
|
import { buscarMaqueta, medirContraMaqueta, resumenDeMedida, textoDeMedidaAutomatica, ultimaCaptura } from "./medidaAutomatica.js";
|
|
65
|
-
import { anotarEscritura, capacidadDeInformesDeHijos, escrituraConExito, textoDelInforme } from "./informesDeHijos.js";
|
|
66
|
+
import { anotarEscritura, capacidadDeInformesDeHijos, esEscrituraBinaria, escrituraConExito, textoDelInforme } from "./informesDeHijos.js";
|
|
66
67
|
import { crearDiagnosticoDeTools } from "../../turno/diagnosticoDeTools.js";
|
|
67
68
|
import { encenderTrazaDeErrores } from "../../trazaDeErroresEnDisco.js";
|
|
68
69
|
import { anotarPaso } from "../../../core/trazaDeErrores.js";
|
|
69
70
|
import { entornoConDepuracion } from "../../turno/depuracion.js";
|
|
70
71
|
import { detalleDe, parametrosDe } from "../../turno/resumenDeTool.js";
|
|
71
|
-
import { apartarMemoria, cargarMemoria, fotoSaneada, guardarMemoria, textoDeMemoriaDescartada } from "./memoriaTrueforge.js";
|
|
72
|
+
import { apartarMemoria, cargarMemoria, fotoSaneada, guardarMemoria, saldarColgadas, textoDeInterrupcion, textoDeMemoriaDescartada } from "./memoriaTrueforge.js";
|
|
72
73
|
import { crearNota, sobrantes } from "./notas.js";
|
|
73
74
|
import { crearMemoriaDeEspecialistas } from "./memoriaDeEspecialistas.js";
|
|
74
75
|
import { crearEsperas } from "./esperas.js";
|
|
@@ -83,6 +84,7 @@ import { hechosDelProyectoDe } from "../../navegacion/hechosEnDisco.js";
|
|
|
83
84
|
import { conHechosDelProyecto } from "../../../core/hechosDelProyecto.js";
|
|
84
85
|
import { crearBusquedaRegex } from "../../grafo/busquedaRegex.js";
|
|
85
86
|
import { crearBuscarIcono, recibeBuscarIcono } from "../../grafo/buscarIcono.js";
|
|
87
|
+
import { crearBuscarFuente, crearTraerFuente, recibeFuentes } from "../../grafo/fuentesDeGoogle.js";
|
|
86
88
|
import { crearGenerarFondoSvg, recibeGenerarFondo } from "../../grafo/generarFondoSvg.js";
|
|
87
89
|
import { crearCopiarArtefacto } from "../../grafo/copiarArtefacto.js";
|
|
88
90
|
import { crearMarcarCriteriosDelPlan } from "../../grafo/marcarCriteriosDelPlan.js";
|
|
@@ -92,10 +94,13 @@ import { crearCriticaVisual } from "../../grafo/criticaVisual.js";
|
|
|
92
94
|
import { crearCompararCapturas } from "../../grafo/compararCapturas.js";
|
|
93
95
|
import { crearAtributosXone, NOMBRE_ATRIBUTOS_XONE } from "../../grafo/atributosXone.js";
|
|
94
96
|
import { crearDiferenciaDeCapturas } from "../../grafo/diferenciaDeCapturas.js";
|
|
95
|
-
import { crearLectorDeReferencias } from "../../grafo/lectorDeReferencias.js";
|
|
97
|
+
import { crearLectorDeReferencias, crearLocalizadorDeHtmlDeMaqueta } from "../../grafo/lectorDeReferencias.js";
|
|
98
|
+
import { cajasDeMaqueta, medidasDeImagen, viewportDeMaqueta } from "../../dispositivos/cajasDeMaqueta.js";
|
|
99
|
+
import { geometriaDeCaptura } from "../../dispositivos/geometriaEnDisco.js";
|
|
100
|
+
import { decodificarImagen } from "../../dispositivos/decodificarImagen.js";
|
|
96
101
|
import { crearDescribirImagen } from "../../grafo/describirImagen.js";
|
|
97
102
|
import { crearTraerDeLaMaquina } from "../../grafo/traerDeLaMaquina.js";
|
|
98
|
-
import { invocarVisualConModelos } from "../../dispositivos/juezVisual.js";
|
|
103
|
+
import { describirPantalla, invocarVisualConModelos } from "../../dispositivos/juezVisual.js";
|
|
99
104
|
import { estilosDeDisco, indiceEnDisco } from "../../navegacion/indiceEnDisco.js";
|
|
100
105
|
/** El hilo raíz de TrueForge. Se llama así en la librería y no se elige. */
|
|
101
106
|
const HILO_RAIZ = "main";
|
|
@@ -269,7 +274,7 @@ export function textoDelBucle(llama, opciones = {}) {
|
|
|
269
274
|
...(puedeDiseñar
|
|
270
275
|
? [
|
|
271
276
|
"El LAYOUT y el CSS son TUYOS: si la pantalla se ve mal, lo arreglas tú, no se lo pasas a nadie ni lo devuelves al que te",
|
|
272
|
-
"encargó. `designer-xone` solo hace RECURSOS —iconos de una biblioteca y fondos SVG en `icons/`—: pídeselos juntos, con para",
|
|
277
|
+
"encargó. `designer-xone` solo hace RECURSOS —iconos de una biblioteca y fondos SVG en `icons/`, y las fuentes en `fonts/`—: pídeselos juntos, con para",
|
|
273
278
|
"qué control, tamaño en píxeles y colores, y usa los nombres que te devuelva. No le pidas que toque el `.xne` ni el CSS: no puede.",
|
|
274
279
|
"Los recursos te llegan con una TABLA (fichero → control → atributo → tamaño → si lleva el símbolo dentro): úsala y no abras",
|
|
275
280
|
"los SVG para enterarte de lo que ya dice.",
|
|
@@ -291,8 +296,18 @@ export function textoDelBucle(llama, opciones = {}) {
|
|
|
291
296
|
"de la tarea en el `TASKS.md` comprobadas, (2) la app arranca y hace lo que pide, y (3) con diseño, la distancia que mide",
|
|
292
297
|
"`comparar_capturas` por debajo del 10 % en vertical y en horizontal, que ENCAJE en la pantalla (cada borde del contenido a",
|
|
293
298
|
"un 3 % o menos del de la maqueta: que llegue a los lados y abajo como ella), y el crítico sin diferencias de forma ni de estructura.",
|
|
294
|
-
|
|
295
|
-
|
|
299
|
+
// Con el puerto de fuentes la tipografía SÍ se reproduce: se trae a `fonts/` (`fuentesDeGoogle.ts`). Sin él, sigue fuera.
|
|
300
|
+
...(opciones.conFuentes === true
|
|
301
|
+
? [
|
|
302
|
+
"Lo que XOne NO puede reproducir no cuenta y no lo persigas: el desenfoque de fondo y las animaciones; una sombra o un",
|
|
303
|
+
"degradado se aproximan con un SVG. La TIPOGRAFÍA del diseño sí: si la maqueta declara una fuente, sus .ttf van a `fonts/`",
|
|
304
|
+
"(pídeselos a designer-xone con los recursos, o tráelos tú con `buscar_fuente`/`traer_fuente`) y se usa con `fontname`;",
|
|
305
|
+
"para verla en el aparato hay que DESPLEGAR entero. Tienes TRES vueltas de corregir y volver a comprobar para",
|
|
306
|
+
]
|
|
307
|
+
: [
|
|
308
|
+
"Lo que XOne NO puede reproducir no cuenta y no lo persigas: las tipografías del diseño (no hay .ttf), el desenfoque de fondo y",
|
|
309
|
+
"las animaciones; una sombra o un degradado se aproximan con un SVG. Tienes TRES vueltas de corregir y volver a comprobar para",
|
|
310
|
+
]),
|
|
296
311
|
"llegar; si al agotarlas algo",
|
|
297
312
|
"sigue sin cumplirse, devuelve el trabajo diciendo QUÉ falta, con lo que midieron el crítico y la medida tal cual. Devolver antes",
|
|
298
313
|
"porque «ya funciona» es dejar el trabajo a medias. Al devolver cuenta lo que se midió: el juicio final no es tuyo, y el arnés",
|
|
@@ -326,7 +341,9 @@ export function notaDeDelegacion(agentes, opciones = {}) {
|
|
|
326
341
|
"cada encargo a developer-xone lleva el CRITERIO ESCRITO y MEDIBLE: qué casillas del plan tiene que dejar comprobadas, qué",
|
|
327
342
|
"tiene que hacer la app, y, si hay diseño, que la distancia de `comparar_capturas` quede por debajo del 10 % en vertical y en",
|
|
328
343
|
"horizontal, que ENCAJE en la pantalla (cada borde a un 3 % o menos del de la maqueta) y que el crítico no señale diferencias de forma o de estructura (di dónde está la maqueta). No se puede pedir",
|
|
329
|
-
|
|
344
|
+
opciones.conFuentes === true
|
|
345
|
+
? "lo que XOne no reproduce —el desenfoque de fondo, las animaciones—; la tipografía del diseño sí (sus .ttf a `fonts/`). Sin criterio, devolverá el"
|
|
346
|
+
: "lo que XOne no reproduce —las tipografías del diseño, el desenfoque de fondo, las animaciones—. Sin criterio, devolverá el",
|
|
330
347
|
"trabajo en cuanto funcione. No le encargues a device-controller comprobar SU",
|
|
331
348
|
"trabajo, ni a designer-xone lo visual de su pantalla (designer-xone no puede tocar un `.xne` ni el CSS): llama tú al diseñador",
|
|
332
349
|
"para los RECURSOS que la pantalla necesite, antes del desarrollador. Lo que developer-xone te devuelva es lo que él vio y midió, no un veredicto: el juicio final es tuyo y del arnés.",
|
|
@@ -472,6 +489,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
472
489
|
/** Lo que escribió cada hijo en su encargo, quién lo llamó, y los informes que esperan a ese padre (`informesDeHijos.ts`). */
|
|
473
490
|
const escritosDeCadaHilo = new Map();
|
|
474
491
|
const padreDeHilo = new Map();
|
|
492
|
+
/** Qué hijo nació de cada `create_sub_agent` del raíz (id de la llamada → hilo): la foto a mitad de turno lo nombra. */
|
|
493
|
+
const hiloDeLlamadaDelRaiz = new Map();
|
|
475
494
|
const informesPendientes = new Map();
|
|
476
495
|
/** Las escrituras pedidas y aún sin respuesta, por hilo e id: la respuesta de una aprobada llega en OTRO `paso`. */
|
|
477
496
|
const escriturasEnVuelo = new Map();
|
|
@@ -494,9 +513,17 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
494
513
|
/** Lo que el agente dejó en `/artefactos/` y aún no se ha anunciado: un artefacto se escribe
|
|
495
514
|
* SIN aprobación, así que tiene que ANUNCIARSE, como en deepagents. */
|
|
496
515
|
const artefactosPorAnunciar = [];
|
|
516
|
+
/** Las propuestas de reparto (`proponer_tareas`) que aún no se han anunciado: van a la persona como evento. */
|
|
517
|
+
const propuestasPorAnunciar = [];
|
|
497
518
|
/** Las IMÁGENES que dejó el turno en curso, para el crítico de pantalla. Se vacía al empezar
|
|
498
519
|
* cada turno: una captura de antes enseña la pantalla de antes. */
|
|
499
520
|
let capturasDelTurno = [];
|
|
521
|
+
function* propuestasPendientes() {
|
|
522
|
+
while (propuestasPorAnunciar.length > 0) {
|
|
523
|
+
const p = propuestasPorAnunciar.shift();
|
|
524
|
+
yield { tipo: "propuesta-de-tareas", motivo: p.motivo, tareas: p.tareas };
|
|
525
|
+
}
|
|
526
|
+
}
|
|
500
527
|
const anotarArtefacto = (a) => {
|
|
501
528
|
artefactosPorAnunciar.push(a);
|
|
502
529
|
// La MAQUETA traída (`/artefactos/diseno/`) no es una captura del aparato: el crítico de pantalla
|
|
@@ -636,6 +663,11 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
636
663
|
...(carpeta === undefined ? {} : { artefactos: carpeta }),
|
|
637
664
|
...(opciones.adjuntos === undefined ? {} : { adjuntos: opciones.adjuntos }),
|
|
638
665
|
});
|
|
666
|
+
const localizadorDeHtml = crearLocalizadorDeHtmlDeMaqueta({
|
|
667
|
+
raiz,
|
|
668
|
+
...(carpeta === undefined ? {} : { artefactos: carpeta }),
|
|
669
|
+
...(opciones.adjuntos === undefined ? {} : { adjuntos: opciones.adjuntos }),
|
|
670
|
+
});
|
|
639
671
|
/** El crítico y la medida, con las MISMAS piezas para quien las tenga: el raíz, y con el bucle encendido el desarrollador. */
|
|
640
672
|
const herramientasDeJuicio = () => carpeta === undefined
|
|
641
673
|
? []
|
|
@@ -643,8 +675,28 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
643
675
|
crearCriticaVisual({
|
|
644
676
|
leerArtefacto: async (nombre) => readFileSync(join(carpeta, nombre)),
|
|
645
677
|
invocar: invocarVisualConModelos({ paraPapel: (p) => modelos.paraPapel(p) }),
|
|
678
|
+
// La maqueta y la captura, cada una descrita SOLA con el mismo esquema: geometría y luego estilo.
|
|
679
|
+
describirPantalla: (imagen, existen) => describirPantalla(imagen, invocarVisualConModelos({ paraPapel: (p) => modelos.paraPapel(p) }), existen),
|
|
680
|
+
// El estilo de cada control se MIDE en sus píxeles: hace falta sacarlos de la imagen.
|
|
681
|
+
decodificar: decodificarImagen,
|
|
682
|
+
// El informe se queda junto a la captura, para poder auditar qué se le dijo al agente.
|
|
683
|
+
guardarInforme: async (nombre, informe) => {
|
|
684
|
+
mkdirSync(carpetaDeHotswap(carpeta), { recursive: true });
|
|
685
|
+
writeFileSync(join(carpetaDeHotswap(carpeta), `${nombre.replace(/\.[A-Za-z0-9]{2,4}$/, "")}.critica.txt`), informe, "utf8");
|
|
686
|
+
},
|
|
646
687
|
// La maqueta casi nunca está en /artefactos/: la trae la persona (/adjuntos/) o vive en /diseno/.
|
|
647
688
|
leerReferencia: lectorDeReferencias,
|
|
689
|
+
// La GEOMETRÍA: el árbol guardado con la captura, y las cajas de la maqueta si trae `code.html`.
|
|
690
|
+
// Por nombre y, si se renombró o convirtió (`sips … --out menu.png`), por los PÍXELES de la original (`geometriaEnDisco.ts`).
|
|
691
|
+
leerGeometria: async (nombre) => geometriaDeCaptura(carpetaDeHotswap(carpeta), nombre, { carpetaDeArtefactos: carpeta, decodificar: decodificarImagen }),
|
|
692
|
+
cajasDeMaqueta: async (imagen, bytes) => {
|
|
693
|
+
const html = localizadorDeHtml(imagen);
|
|
694
|
+
const medidas = medidasDeImagen(bytes);
|
|
695
|
+
if (html === undefined || medidas === undefined)
|
|
696
|
+
return undefined;
|
|
697
|
+
const { ancho, alto } = viewportDeMaqueta(medidas.ancho, medidas.alto);
|
|
698
|
+
return cajasDeMaqueta(html, ancho, alto);
|
|
699
|
+
},
|
|
648
700
|
}),
|
|
649
701
|
// Medir la estructura contra la maqueta: la otra mitad del crítico, con el raíz como él.
|
|
650
702
|
crearCompararCapturas({ leerArtefacto: async (nombre) => readFileSync(join(carpeta, nombre)), leerReferencia: lectorDeReferencias }),
|
|
@@ -692,6 +744,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
692
744
|
...herramientasDeJuicio(),
|
|
693
745
|
...(carpeta === undefined ? [] : [crearTraerDeLaMaquina({ carpeta, alEscribir: anotarArtefacto })]),
|
|
694
746
|
...traerDeStitch(),
|
|
747
|
+
...(opciones.puedeProponerTareas === true
|
|
748
|
+
? [crearProponerTareas((p) => void propuestasPorAnunciar.push(p))]
|
|
749
|
+
: []),
|
|
695
750
|
];
|
|
696
751
|
const propiasDe = (agente) => [
|
|
697
752
|
crearBusquedaRegex(backend),
|
|
@@ -716,6 +771,14 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
716
771
|
...(opciones.iconos !== undefined && recibeBuscarIcono(agente)
|
|
717
772
|
? [crearBuscarIcono(opciones.iconos)]
|
|
718
773
|
: []),
|
|
774
|
+
// Las fuentes de la maqueta (Google Fonts) a `fonts/`: al desarrollador y al diseñador (`recibeFuentes`), con el
|
|
775
|
+
// puerto. `traer_fuente` ESCRIBE un binario: `capacidadesDelEspecialista` la pone en `requireApprovalForTools`.
|
|
776
|
+
...(opciones.fuentes !== undefined && recibeFuentes(agente)
|
|
777
|
+
? [
|
|
778
|
+
crearBuscarFuente(opciones.fuentes),
|
|
779
|
+
crearTraerFuente(opciones.fuentes, { raiz, perfil: agente }),
|
|
780
|
+
]
|
|
781
|
+
: []),
|
|
719
782
|
// Fondos SVG: pura y sin red, sin puerto; a quien escribe el proyecto, como deepagents.
|
|
720
783
|
...(recibeGenerarFondo(agente) ? [crearGenerarFondoSvg()] : []),
|
|
721
784
|
// ¿Cambió la zona tras el toque? Al conductor, que es quien saca las capturas: comprueba una
|
|
@@ -886,6 +949,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
886
949
|
const hiloDelPadre = params.parent?.thread_id;
|
|
887
950
|
if (hiloDelPadre !== undefined && hiloDelPadre !== "")
|
|
888
951
|
padreDeHilo.set(params.threadId, hiloDelPadre);
|
|
952
|
+
const llamadaDelPadre = params.parent?.tool_call_id;
|
|
953
|
+
if (hiloDelPadre === HILO_RAIZ && llamadaDelPadre !== undefined)
|
|
954
|
+
hiloDeLlamadaDelRaiz.set(llamadaDelPadre, params.threadId);
|
|
889
955
|
nacimientoDeHilo.set(params.threadId, Date.now());
|
|
890
956
|
quienEs.set(params.threadId, agente?.nombre ?? params.request.name);
|
|
891
957
|
if (agente !== undefined)
|
|
@@ -930,7 +996,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
930
996
|
"",
|
|
931
997
|
nota,
|
|
932
998
|
anuncioDeSkills(agente, catalogo),
|
|
933
|
-
...(conBucleDelDesarrollador && (agente.llama?.length ?? 0) > 0 ? ["", textoDelBucle(agente.llama ?? [], { conCritica: carpeta !== undefined })] : []),
|
|
999
|
+
...(conBucleDelDesarrollador && (agente.llama?.length ?? 0) > 0 ? ["", textoDelBucle(agente.llama ?? [], { conCritica: carpeta !== undefined, conFuentes: opciones.fuentes !== undefined })] : []),
|
|
934
1000
|
]
|
|
935
1001
|
.filter((l) => l !== undefined)
|
|
936
1002
|
.join("\n")
|
|
@@ -1025,7 +1091,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1025
1091
|
hijosConMemoria.clear();
|
|
1026
1092
|
const definicion = {
|
|
1027
1093
|
modelClient: llm,
|
|
1028
|
-
instruction: [IDIOMA_DE_LA_RESPUESTA, SIN_HABLAR_DEL_HARNESS, promptOrquestador(especialistas()), notaDeDelegacion(especialistas(), { conIconos: opciones.iconos !== undefined, conComparacion: carpeta !== undefined, conMemoria: conMemoriaDeEspecialistas, conBucle: conBucleDelDesarrollador, conEsperas })].filter((l) => l !== "").join("\n\n"),
|
|
1094
|
+
instruction: [IDIOMA_DE_LA_RESPUESTA, SIN_HABLAR_DEL_HARNESS, promptOrquestador(especialistas()), notaDeDelegacion(especialistas(), { conIconos: opciones.iconos !== undefined, conFuentes: opciones.fuentes !== undefined, conComparacion: carpeta !== undefined, conMemoria: conMemoriaDeEspecialistas, conBucle: conBucleDelDesarrollador, conEsperas }), opciones.puedeProponerTareas === true ? REPARTIR_EN_TAREAS : ""].filter((l) => l !== "").join("\n\n"),
|
|
1029
1095
|
// Por TURNO, porque el raíz se rehace desde su foto al final de cada uno (ver `turno`).
|
|
1030
1096
|
iterationLimit: LIMITE_DE_LLAMADAS_DEL_RAIZ,
|
|
1031
1097
|
};
|
|
@@ -1086,6 +1152,51 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1086
1152
|
* de terminal no lo pasa, la misma regla que el checkpoint de deepagents.
|
|
1087
1153
|
*/
|
|
1088
1154
|
const persistir = opciones.hilo !== undefined;
|
|
1155
|
+
/**
|
|
1156
|
+
* **La foto A MITAD de turno.** La del `finally` no basta: un corte DURO —el proceso muere, sin
|
|
1157
|
+
* cierre ordenado— no pasa por él, y medido en el incidente que lo motiva, un turno de 45 minutos
|
|
1158
|
+
* se perdió entero, mensaje de la persona incluido, aunque los ficheros sí habían cambiado.
|
|
1159
|
+
* deepagents no lo sufre: su checkpointer guarda cada paso.
|
|
1160
|
+
*
|
|
1161
|
+
* Se guarda en cada añadido del RAÍZ —el primero es el mensaje de la persona— y cada vez que un
|
|
1162
|
+
* hijo completa una escritura, porque lo escrito no toca el contexto del raíz y la foto lo nombra.
|
|
1163
|
+
* `toSnapshot()` es seguro aquí: la librería SUSTITUYE el contexto (`concat`), nunca lo muta, y
|
|
1164
|
+
* guardar es atómico. Las tool calls abiertas se saldan con el texto de una INTERRUPCIÓN
|
|
1165
|
+
* (`textoDeInterrupcion`), no con el de un turno cortado: tras un corte, «vuelve a pedirlo»
|
|
1166
|
+
* duplicaría lo que el especialista ya dejó en el disco. El turno que acaba bien la PISA con la
|
|
1167
|
+
* del `finally`, así que esta foto solo se lee si el proceso murió. Nunca tumba un turno.
|
|
1168
|
+
*/
|
|
1169
|
+
let ultimaAMitad;
|
|
1170
|
+
const escritosDeLaRama = (hijo) => {
|
|
1171
|
+
const deLaRama = (h) => {
|
|
1172
|
+
for (let actual = h; actual !== undefined; actual = padreDeHilo.get(actual))
|
|
1173
|
+
if (actual === hijo)
|
|
1174
|
+
return true;
|
|
1175
|
+
return false;
|
|
1176
|
+
};
|
|
1177
|
+
return [...new Set([...escritosDeCadaHilo].filter(([h]) => deLaRama(h)).flatMap(([, cambios]) => [...cambios.keys()]))];
|
|
1178
|
+
};
|
|
1179
|
+
const guardarAMitad = () => {
|
|
1180
|
+
if (!persistir || raizActual === undefined)
|
|
1181
|
+
return;
|
|
1182
|
+
const foto = raizActual.toSnapshot();
|
|
1183
|
+
const escritos = [...escritosDeCadaHilo.values()].reduce((n, cambios) => n + cambios.size, 0);
|
|
1184
|
+
if (ultimaAMitad?.context === foto.context && ultimaAMitad.escritos === escritos)
|
|
1185
|
+
return;
|
|
1186
|
+
ultimaAMitad = { context: foto.context, escritos };
|
|
1187
|
+
const textoDe = (id) => {
|
|
1188
|
+
const hijo = hiloDeLlamadaDelRaiz.get(id);
|
|
1189
|
+
if (hijo === undefined)
|
|
1190
|
+
return textoDeInterrupcion({ escritos: [] });
|
|
1191
|
+
return textoDeInterrupcion({ especialista: especialistaDeHilo.get(hijo) ?? quienEs.get(hijo) ?? hijo, escritos: escritosDeLaRama(hijo) });
|
|
1192
|
+
};
|
|
1193
|
+
try {
|
|
1194
|
+
guardarMemoria(raiz, hilo, { ...foto, context: saldarColgadas(foto.context, undefined, textoDe) });
|
|
1195
|
+
}
|
|
1196
|
+
catch {
|
|
1197
|
+
// Sin la foto de a mitad el turno sigue: lo peor es lo de antes, perderlo si el proceso muere.
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1089
1200
|
/** El aviso de una memoria que existía y no se entendió: sale en el PRIMER turno y se gasta. */
|
|
1090
1201
|
let avisoDeMemoria;
|
|
1091
1202
|
/**
|
|
@@ -1153,6 +1264,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1153
1264
|
async function* paso(lote, senal, pendientes, preguntas = []) {
|
|
1154
1265
|
for await (const _ of orquestador.send(lote))
|
|
1155
1266
|
void _;
|
|
1267
|
+
// Lo que acaba de entrar en el raíz —el mensaje de la persona, una aprobación, una reparación—
|
|
1268
|
+
// ya está a salvo antes de la primera llamada al modelo.
|
|
1269
|
+
guardarAMitad();
|
|
1156
1270
|
const llamadas = new Map();
|
|
1157
1271
|
// El razonamiento de los especialistas, juntado por hilo hasta que su mensaje se completa.
|
|
1158
1272
|
const pensamientos = new Map();
|
|
@@ -1161,6 +1275,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1161
1275
|
while (!r.done) {
|
|
1162
1276
|
const evento = r.value;
|
|
1163
1277
|
const deHilo = evento.thread_id ?? HILO_RAIZ;
|
|
1278
|
+
if (deHilo === HILO_RAIZ && evento.type === "internal.agent.context.append")
|
|
1279
|
+
guardarAMitad();
|
|
1164
1280
|
if (evento.type === "internal.agent.context.append" && Array.isArray(evento.output)) {
|
|
1165
1281
|
for (const m of evento.output) {
|
|
1166
1282
|
for (const t of m.tool_calls ?? []) {
|
|
@@ -1172,8 +1288,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1172
1288
|
args = {};
|
|
1173
1289
|
}
|
|
1174
1290
|
llamadas.set(claveDe(deHilo, t.id), { nombre: t.function.name, args });
|
|
1175
|
-
if (t.function.name === "write_file" || t.function.name === "edit_file")
|
|
1291
|
+
if (t.function.name === "write_file" || t.function.name === "edit_file" || esEscrituraBinaria(t.function.name)) {
|
|
1176
1292
|
escriturasEnVuelo.set(claveDe(deHilo, t.id), { nombre: t.function.name, args });
|
|
1293
|
+
}
|
|
1177
1294
|
if (t.function.name === "xone_critica_visual")
|
|
1178
1295
|
ultimaCriticaDeHilo.set(deHilo, Date.now());
|
|
1179
1296
|
// La traza: la MISMA lista blanca que el evento (`detalleDe`, `parametrosDe`), nunca
|
|
@@ -1201,11 +1318,12 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1201
1318
|
const escritura = escriturasEnVuelo.get(claveDe(deHilo, evento.tool_call_id));
|
|
1202
1319
|
if (escritura !== undefined) {
|
|
1203
1320
|
escriturasEnVuelo.delete(claveDe(deHilo, evento.tool_call_id));
|
|
1204
|
-
if (deHilo !== HILO_RAIZ && escrituraConExito(evento.content)) {
|
|
1321
|
+
if (deHilo !== HILO_RAIZ && escrituraConExito(evento.content, escritura.nombre)) {
|
|
1205
1322
|
const cambios = escritosDeCadaHilo.get(deHilo) ?? new Map();
|
|
1206
1323
|
anotarEscritura(cambios, escritura.nombre, escritura.args);
|
|
1207
1324
|
escritosDeCadaHilo.set(deHilo, cambios);
|
|
1208
1325
|
ultimaEscrituraDeHilo.set(deHilo, Date.now());
|
|
1326
|
+
guardarAMitad();
|
|
1209
1327
|
}
|
|
1210
1328
|
}
|
|
1211
1329
|
}
|
|
@@ -1280,8 +1398,10 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1280
1398
|
yield* eventos;
|
|
1281
1399
|
while (artefactosPorAnunciar.length > 0)
|
|
1282
1400
|
yield { tipo: "artefacto", artefacto: artefactosPorAnunciar.shift() };
|
|
1401
|
+
yield* propuestasPendientes();
|
|
1283
1402
|
r = await it.next();
|
|
1284
1403
|
}
|
|
1404
|
+
yield* propuestasPendientes();
|
|
1285
1405
|
const resultado = r.value;
|
|
1286
1406
|
for (const accion of resultado.required_actions ?? []) {
|
|
1287
1407
|
// Dos interrupciones distintas, y no se mezclan: una APROBACIÓN decide sobre una escritura
|