xonecode 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/apps/web/dist/assets/{index-rqecK6s2.css → index-Boak51UP.css} +1 -1
  2. package/apps/web/dist/assets/index-Cg28x6nG.js +477 -0
  3. package/apps/web/dist/assets/{php-BBij3Lhc.js → php-Cu6F_QCJ.js} +1 -1
  4. package/apps/web/dist/assets/{ruby-Dq2YEaLo.js → ruby-BiqQPoC6.js} +1 -1
  5. package/apps/web/dist/index.html +2 -2
  6. package/dist/agent/cloudstudio/cloudstudioClient.js +10 -0
  7. package/dist/agent/cloudstudio/cloudstudioClient.js.map +1 -1
  8. package/dist/agent/cloudstudio/descarga.js +14 -4
  9. package/dist/agent/cloudstudio/descarga.js.map +1 -1
  10. package/dist/agent/cloudstudio/ramaActiva.js +11 -0
  11. package/dist/agent/cloudstudio/ramaActiva.js.map +1 -0
  12. package/dist/agent/cloudstudio/subida.js +13 -4
  13. package/dist/agent/cloudstudio/subida.js.map +1 -1
  14. package/dist/agent/config/catalogoModelos.js +45 -0
  15. package/dist/agent/config/catalogoModelos.js.map +1 -1
  16. package/dist/agent/config/modelos.js +103 -12
  17. package/dist/agent/config/modelos.js.map +1 -1
  18. package/dist/agent/config/mudanzaEnDisco.js +121 -0
  19. package/dist/agent/config/mudanzaEnDisco.js.map +1 -0
  20. package/dist/agent/config/selectorEnMaquina.js +45 -0
  21. package/dist/agent/config/selectorEnMaquina.js.map +1 -0
  22. package/dist/agent/config/settingsEnDisco.js +35 -0
  23. package/dist/agent/config/settingsEnDisco.js.map +1 -1
  24. package/dist/agent/dispositivos/juezVisual.js +152 -0
  25. package/dist/agent/dispositivos/juezVisual.js.map +1 -0
  26. package/dist/agent/dispositivos/sensorDeArranque.js +154 -0
  27. package/dist/agent/dispositivos/sensorDeArranque.js.map +1 -0
  28. package/dist/agent/exportarPdf.js +140 -0
  29. package/dist/agent/exportarPdf.js.map +1 -0
  30. package/dist/agent/grafo/criticaVisual.js +115 -0
  31. package/dist/agent/grafo/criticaVisual.js.map +1 -0
  32. package/dist/agent/grafo/navegacionXone.js +37 -4
  33. package/dist/agent/grafo/navegacionXone.js.map +1 -1
  34. package/dist/agent/grafo/perfiles.js +52 -9
  35. package/dist/agent/grafo/perfiles.js.map +1 -1
  36. package/dist/agent/grafo/proyecto.js +74 -7
  37. package/dist/agent/grafo/proyecto.js.map +1 -1
  38. package/dist/agent/grafo/skills.js +32 -0
  39. package/dist/agent/grafo/skills.js.map +1 -1
  40. package/dist/agent/grafo/xoneAgent.js +103 -13
  41. package/dist/agent/grafo/xoneAgent.js.map +1 -1
  42. package/dist/agent/navegacion/estilosEnDisco.js +110 -0
  43. package/dist/agent/navegacion/estilosEnDisco.js.map +1 -0
  44. package/dist/agent/navegacion/hechosEnDisco.js +26 -0
  45. package/dist/agent/navegacion/hechosEnDisco.js.map +1 -0
  46. package/dist/agent/navegacion/indiceEnDisco.js +15 -0
  47. package/dist/agent/navegacion/indiceEnDisco.js.map +1 -1
  48. package/dist/agent/subagentes/agentesEnDisco.js +85 -24
  49. package/dist/agent/subagentes/agentesEnDisco.js.map +1 -1
  50. package/dist/agent/subagentes/escrituraExterna.js +53 -0
  51. package/dist/agent/subagentes/escrituraExterna.js.map +1 -1
  52. package/dist/agent/subagentes/pluginDeSkills.js +99 -0
  53. package/dist/agent/subagentes/pluginDeSkills.js.map +1 -0
  54. package/dist/agent/subagentes/subagenteExterno.js +48 -0
  55. package/dist/agent/subagentes/subagenteExterno.js.map +1 -1
  56. package/dist/agent/subagentes/subagenteOpencode.js +53 -1
  57. package/dist/agent/subagentes/subagenteOpencode.js.map +1 -1
  58. package/dist/agent/tareas/juezDeTarea.js +1 -1
  59. package/dist/agent/tareas/juezDeTarea.js.map +1 -1
  60. package/dist/agent/tareas/tareasEnDisco.js +49 -0
  61. package/dist/agent/tareas/tareasEnDisco.js.map +1 -1
  62. package/dist/agent/turno/diagnosticoDeTools.js +5 -1
  63. package/dist/agent/turno/diagnosticoDeTools.js.map +1 -1
  64. package/dist/agent/turno/informeDeTraza.js +27 -4
  65. package/dist/agent/turno/informeDeTraza.js.map +1 -1
  66. package/dist/agent/turno/puente.js +24 -1
  67. package/dist/agent/turno/puente.js.map +1 -1
  68. package/dist/agent/turno/resumenDeContexto.js +88 -4
  69. package/dist/agent/turno/resumenDeContexto.js.map +1 -1
  70. package/dist/agent/turno/resumenDeTool.js +18 -0
  71. package/dist/agent/turno/resumenDeTool.js.map +1 -1
  72. package/dist/agent/turno/rubrica.js +91 -0
  73. package/dist/agent/turno/rubrica.js.map +1 -0
  74. package/dist/agent/turno/turnoReal.js +172 -11
  75. package/dist/agent/turno/turnoReal.js.map +1 -1
  76. package/dist/cli/consola.js +63 -0
  77. package/dist/cli/consola.js.map +1 -1
  78. package/dist/cli/main.js +51 -4
  79. package/dist/cli/main.js.map +1 -1
  80. package/dist/cli/run.js +8 -0
  81. package/dist/cli/run.js.map +1 -1
  82. package/dist/core/agentes.js +111 -9
  83. package/dist/core/agentes.js.map +1 -1
  84. package/dist/core/esfuerzo.js +141 -0
  85. package/dist/core/esfuerzo.js.map +1 -0
  86. package/dist/core/estilos.js +78 -0
  87. package/dist/core/estilos.js.map +1 -0
  88. package/dist/core/exportacion.js +140 -0
  89. package/dist/core/exportacion.js.map +1 -0
  90. package/dist/core/hechosDelProyecto.js +87 -0
  91. package/dist/core/hechosDelProyecto.js.map +1 -0
  92. package/dist/core/logDeDispositivo.js +143 -0
  93. package/dist/core/logDeDispositivo.js.map +1 -0
  94. package/dist/core/modelos.js +32 -0
  95. package/dist/core/modelos.js.map +1 -1
  96. package/dist/core/mudanzaDeWorkspace.js +93 -0
  97. package/dist/core/mudanzaDeWorkspace.js.map +1 -0
  98. package/dist/core/planes.js +70 -0
  99. package/dist/core/planes.js.map +1 -0
  100. package/dist/core/ports.js +4 -0
  101. package/dist/core/ports.js.map +1 -1
  102. package/dist/core/rubrica.js +90 -0
  103. package/dist/core/rubrica.js.map +1 -0
  104. package/dist/core/selectorDeCarpeta.js +87 -0
  105. package/dist/core/selectorDeCarpeta.js.map +1 -0
  106. package/dist/core/settings.js +54 -5
  107. package/dist/core/settings.js.map +1 -1
  108. package/dist/core/shellDeAgente.js +45 -0
  109. package/dist/core/shellDeAgente.js.map +1 -1
  110. package/dist/core/topeAgotado.js +69 -0
  111. package/dist/core/topeAgotado.js.map +1 -0
  112. package/dist/web/servidor/arranque.js +324 -9
  113. package/dist/web/servidor/arranque.js.map +1 -1
  114. package/dist/web/servidor/sesiones.js +30 -2
  115. package/dist/web/servidor/sesiones.js.map +1 -1
  116. package/dist/web/servidor/transporte.js.map +1 -1
  117. package/dist/web/servidor/vestibulo.js +55 -6
  118. package/dist/web/servidor/vestibulo.js.map +1 -1
  119. package/package.json +2 -1
  120. package/skills/xone-hotswap/SKILL.md +31 -9
  121. package/skills/xone-hotswap/scripts/xone-arrancar-android +202 -0
  122. package/skills/xone-hotswap/scripts/xone-captura-android +93 -0
  123. package/skills/xone-hotswap/scripts/xone-desplegar-android +28 -0
  124. package/skills/xone-hotswap/scripts/xone-hotswap +39 -9
  125. package/skills/xone-hotswap/scripts/xone-reiniciar-android +28 -0
  126. package/skills/xone-plan-builder/SKILL.md +22 -4
  127. package/skills/xone-spec-builder/SKILL.md +37 -7
  128. package/apps/web/dist/assets/index-DBZTodio.js +0 -477
@@ -0,0 +1,121 @@
1
+ /**
2
+ * La mudanza de una vez de las copias locales que siguen en el reparto VIEJO
3
+ * (`<base>/<entorno>/workspace/<proyecto>`) al de ahora (`<workspace>/<entorno>/<proyecto>`).
4
+ *
5
+ * **No es cosmética, y por eso se hace sola.** `dentroDelWorkspace` es lo que decide si el
6
+ * harness puede commitear al cerrar cada turno, y compara la raíz contra el workspace: con
7
+ * el reparto nuevo, una copia que se quedara en el sitio viejo dejaría de estar dentro y los
8
+ * commits por turno se pararían EN SILENCIO — que es exactamente el fallo mudo que este repo
9
+ * persigue en todas partes. Dejarlas donde están no era una opción; dejarlas y avisar,
10
+ * tampoco, porque el aviso saldría en cada arranque para siempre.
11
+ *
12
+ * La decisión de QUÉ se muda es pura y vive en `core/mudanzaDeWorkspace.ts`. Aquí solo está
13
+ * lo que toca disco: mover, reescribir los dos almacenes con raíces absolutas y CONTARLO.
14
+ */
15
+ import { existsSync, mkdirSync, readdirSync, renameSync, rmdirSync, unlinkSync } from "node:fs";
16
+ import { homedir } from "node:os";
17
+ import { dirname, join } from "node:path";
18
+ import { mudanzasPendientes, rutaMudada } from "../../core/mudanzaDeWorkspace.js";
19
+ import { remapearSinAprobacion } from "./settingsEnDisco.js";
20
+ import { remapearRaicesDeTareas } from "../tareas/tareasEnDisco.js";
21
+ import { BASURA_DEL_SO } from "../sesiones/gitSync.js";
22
+ /** Las CARPETAS que cuelgan de una ruta. Un fichero suelto no es un proyecto, y un
23
+ * `.DS_Store` es un nombre de segmento tan válido como cualquier otro. */
24
+ function carpetasDe(ruta) {
25
+ try {
26
+ return readdirSync(ruta, { withFileTypes: true })
27
+ .filter((e) => e.isDirectory())
28
+ .map((e) => e.name);
29
+ }
30
+ catch {
31
+ return [];
32
+ }
33
+ }
34
+ /**
35
+ * Retira una carpeta del reparto viejo que ya no pinta nada — y solo si NO queda nada del
36
+ * usuario dentro.
37
+ *
38
+ * `rmdir` no vacía carpetas, así que él solo ya es la garantía. Lo único que se borra antes
39
+ * es la BASURA DEL SO, y de la lista CERRADA que `gitSync.ts` ya mantiene para lo mismo: sin
40
+ * esto, un `.DS_Store` que Finder dejó al mirar la carpeta bastaba para que el husco vacío
41
+ * se quedara en `~/.xonecode` para siempre, que es justo lo que esta mudanza venía a quitar.
42
+ * Medido sobre un caso real: los dos husos tenían uno.
43
+ */
44
+ function retirarSiSobra(carpeta) {
45
+ try {
46
+ const dentro = readdirSync(carpeta);
47
+ if (dentro.length > 0 && dentro.every((n) => BASURA_DEL_SO.includes(n))) {
48
+ for (const basura of dentro)
49
+ unlinkSync(join(carpeta, basura));
50
+ }
51
+ rmdirSync(carpeta);
52
+ }
53
+ catch {
54
+ // No estaba vacía, o no estaba, o no se pudo tocar. En los tres casos no hay nada que
55
+ // hacer: la carpeta vieja de más es un adorno, no un fallo que contar.
56
+ }
57
+ }
58
+ export function mudarWorkspaceLegado(opciones) {
59
+ const mover = opciones.mover ?? renameSync;
60
+ const { mudanzas, chocadas } = mudanzasPendientes({
61
+ legado: opciones.legado,
62
+ workspace: opciones.workspace,
63
+ entornos: opciones.entornos,
64
+ existe: existsSync,
65
+ listar: carpetasDe,
66
+ });
67
+ if (mudanzas.length === 0 && chocadas.length === 0)
68
+ return { mudadas: 0, chocadas: 0 };
69
+ // Solo las que SE MOVIERON de verdad reescriben una ruta guardada: apuntar el índice a un
70
+ // sitio donde la carpeta no llegó a estar es peor que no tocarlo.
71
+ const hechas = [];
72
+ for (const mudanza of mudanzas) {
73
+ try {
74
+ mkdirSync(dirname(mudanza.hacia), { recursive: true });
75
+ mover(mudanza.desde, mudanza.hacia);
76
+ hechas.push(mudanza);
77
+ }
78
+ catch (error) {
79
+ const motivo = error instanceof Error ? error.message : String(error);
80
+ opciones.escribir(`no se pudo mudar «${mudanza.proyecto}» (${mudanza.entorno}): ${motivo}\n`);
81
+ }
82
+ }
83
+ if (hechas.length > 0) {
84
+ const traducir = (raiz) => rutaMudada(raiz, hechas);
85
+ // Un fallo de cualquiera de los dos no puede tumbar el arranque de la consola: las
86
+ // copias ya están mudadas, y lo que queda es un ajuste que se vuelve a poner a mano.
87
+ for (const [que, remapear] of [
88
+ // Las dos toman su raíz por parámetros que NO significan lo mismo: `casa` es el HOME
89
+ // (`rutaSettings` le añade `.xonecode`) y la base de las tareas es ya la carpeta
90
+ // `.xonecode`. Se traduce aquí, a la vista, en vez de fiarse de que los dos nombres
91
+ // que se parecen quieran decir lo mismo.
92
+ ["la cola de tareas", () => remapearRaicesDeTareas(join(opciones.casa ?? homedir(), ".xonecode"), traducir)],
93
+ ["las autorizaciones sin aprobación", () => remapearSinAprobacion(opciones.casa, traducir)],
94
+ ]) {
95
+ try {
96
+ remapear();
97
+ }
98
+ catch (error) {
99
+ const motivo = error instanceof Error ? error.message : String(error);
100
+ opciones.escribir(`las copias se mudaron, pero no se pudo actualizar ${que}: ${motivo}\n`);
101
+ }
102
+ }
103
+ // La carpeta vieja se retira SOLO si quedó vacía, y eso lo garantiza `rmdir` por
104
+ // construcción: nunca vacía nada. Un `notas.txt` del usuario ahí dentro la deja en pie,
105
+ // que es la respuesta correcta.
106
+ for (const entorno of new Set(hechas.map((m) => m.entorno))) {
107
+ for (const carpeta of [join(opciones.legado, entorno, "workspace"), join(opciones.legado, entorno)]) {
108
+ retirarSiSobra(carpeta);
109
+ }
110
+ }
111
+ opciones.escribir(`${hechas.length} ${hechas.length === 1 ? "copia local mudada" : "copias locales mudadas"} al workspace: ` +
112
+ `${hechas.map((m) => `${m.proyecto} (${m.entorno})`).join(", ")}\n`);
113
+ }
114
+ for (const choque of chocadas) {
115
+ // Callarlo dejaría dos copias del mismo proyecto y a nadie sabiendo cuál mira la consola.
116
+ opciones.escribir(`«${choque.proyecto}» (${choque.entorno}) NO se mudó: ya hay una copia en el workspace. ` +
117
+ `La vieja sigue donde estaba y no se ha tocado.\n`);
118
+ }
119
+ return { mudadas: hechas.length, chocadas: chocadas.length };
120
+ }
121
+ //# sourceMappingURL=mudanzaEnDisco.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mudanzaEnDisco.js","sourceRoot":"","sources":["../../../src/agent/config/mudanzaEnDisco.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Abrir el selector de carpeta NATIVO de esta máquina. La regla de QUÉ comando y cómo se lee
3
+ * su respuesta es pura y vive en `core/selectorDeCarpeta.ts`; aquí solo está lanzarlo.
4
+ */
5
+ import { execFile } from "node:child_process";
6
+ import { carpetaDeLaSalida, comandoDelSelector, TOPE_DEL_SELECTOR_MS, } from "../../core/selectorDeCarpeta.js";
7
+ /** ¿Hay selector en este sistema? Es lo que decide si se OFRECE el botón: un botón que no
8
+ * hace nada es peor que no tenerlo, y el campo de texto ya resuelve el caso. */
9
+ export function haySelectorDeCarpeta(plataforma = process.platform) {
10
+ return comandoDelSelector(plataforma) !== undefined;
11
+ }
12
+ /**
13
+ * La carpeta que la persona elija, o AUSENTE.
14
+ *
15
+ * **Ausente lo cubre todo lo que no es una elección**: cancelar, que el comando no esté, que
16
+ * falle, o que se agote el tope. No se distinguen a propósito — `osascript` sale con código 1
17
+ * tanto si cierras el diálogo como si revienta, así que afirmar cuál de las dos fue sería
18
+ * inventarlo. Lo que la pantalla necesita saber es si hay carpeta nueva, y eso sí se sabe.
19
+ *
20
+ * **Nunca LANZA.** Esto cuelga de un mensaje del cable, y una excepción aquí subiría por el
21
+ * manejador de la petición.
22
+ */
23
+ export async function elegirCarpetaEnMaquina(opciones) {
24
+ const comando = comandoDelSelector(opciones?.plataforma ?? process.platform, opciones?.desde);
25
+ if (comando === undefined)
26
+ return undefined;
27
+ const lanzar = opciones?.lanzar ?? lanzarDeVerdad;
28
+ try {
29
+ return carpetaDeLaSalida(await lanzar(comando));
30
+ }
31
+ catch {
32
+ // Cancelar sale por aquí (código 1), igual que un fallo de verdad. Ver arriba.
33
+ return undefined;
34
+ }
35
+ }
36
+ function lanzarDeVerdad(comando) {
37
+ return new Promise((resolver, rechazar) => {
38
+ execFile(comando.programa, [...comando.argumentos],
39
+ // `timeout` mata el proceso al vencer: un diálogo que nadie cierra no puede dejar un
40
+ // proceso vivo para siempre. `windowsHide` no pinta en los dos sistemas que esto
41
+ // soporta, pero tampoco estorba.
42
+ { timeout: TOPE_DEL_SELECTOR_MS, windowsHide: true }, (error, salida) => (error === null ? resolver(salida) : rechazar(error)));
43
+ });
44
+ }
45
+ //# sourceMappingURL=selectorEnMaquina.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectorEnMaquina.js","sourceRoot":"","sources":["../../../src/agent/config/selectorEnMaquina.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GAErB,MAAM,iCAAiC,CAAC;AAEzC;iFACiF;AACjF,MAAM,UAAU,oBAAoB,CAAC,aAAqB,OAAO,CAAC,QAAQ;IACxE,OAAO,kBAAkB,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC;AACtD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAI5C;IACC,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,EAAE,UAAU,IAAI,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9F,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,MAAM,GAAG,QAAQ,EAAE,MAAM,IAAI,cAAc,CAAC;IAClD,IAAI,CAAC;QACH,OAAO,iBAAiB,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;QAC/E,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,OAA0B;IAChD,OAAO,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE;QACxC,QAAQ,CACN,OAAO,CAAC,QAAQ,EAChB,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;QACvB,qFAAqF;QACrF,iFAAiF;QACjF,iCAAiC;QACjC,EAAE,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,IAAI,EAAE,EACpD,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CACzE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -178,6 +178,41 @@ export function guardarConcurrenciaDeTareas(casa, concurrencia) {
178
178
  escribirAtomico(ruta, JSON.stringify(fusionado, null, 2) + "\n");
179
179
  return { ruta };
180
180
  }
181
+ /**
182
+ * Reescribe las claves de `sinAprobacion` cuando una copia local se ha mudado de sitio.
183
+ *
184
+ * Son rutas ABSOLUTAS de raíz de proyecto, así que una mudanza las deja apuntando a una
185
+ * carpeta que ya no está: la autorización de escribir sin preguntar dejaría de aplicarse en
186
+ * silencio. Es la dirección segura —se vuelve a preguntar— pero es un ajuste que el dueño de
187
+ * la máquina dio por puesto, y perderlo sin decir nada es el fallo mudo de siempre.
188
+ *
189
+ * Misma disciplina que el resto del fichero: la base es el objeto CRUDO, un JSON roto PARA
190
+ * sin escribir, y cero cambios no escribe nada. Devuelve cuántas claves se tradujeron.
191
+ */
192
+ export function remapearSinAprobacion(casa, traducir) {
193
+ const ruta = rutaSettings(casa ?? homedir());
194
+ if (!existsSync(ruta))
195
+ return 0;
196
+ const crudo = leerCrudoOAbortar(ruta);
197
+ const previo = crudo.sinAprobacion;
198
+ if (!esObjeto(previo))
199
+ return 0;
200
+ let cambiadas = 0;
201
+ const salida = {};
202
+ for (const [clave, valor] of Object.entries(previo)) {
203
+ const nueva = traducir(clave);
204
+ if (nueva === undefined) {
205
+ salida[clave] = valor;
206
+ continue;
207
+ }
208
+ cambiadas += 1;
209
+ salida[nueva] = valor;
210
+ }
211
+ if (cambiadas === 0)
212
+ return 0;
213
+ escribirAtomico(ruta, JSON.stringify({ ...crudo, sinAprobacion: salida }, null, 2) + "\n");
214
+ return cambiadas;
215
+ }
181
216
  /** Guarda solo la base del workspace, sin tocar la lista de entornos. */
182
217
  export function guardarWorkspace(casa, base) {
183
218
  const ruta = rutaSettings(casa ?? homedir());
@@ -1 +1 @@
1
- {"version":3,"file":"settingsEnDisco.js","sourceRoot":"","sources":["../../../src/agent/config/settingsEnDisco.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settingsEnDisco.js","sourceRoot":"","sources":["../../../src/agent/config/settingsEnDisco.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAIL,8BAA8B,EAC9B,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,cAAc,GAAG,WAAW,CAAC;AAEnC,wFAAwF;AACxF,MAAM,OAAO,oBAAqB,SAAQ,KAAK;CAAG;AAElD,uGAAuG;AACvG,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,OAAO,EAAE;IACnD,OAAO,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,OAAO,EAAE;IACrD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACzE,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC1B,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,IAAI,+CAA+C,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;SACjG,CAAC;IACJ,CAAC;IACD,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,oFAAoF;QACpF,MAAM,IAAI,oBAAoB,CAC5B,IAAI,IAAI,qEAAqE,CAC9E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,oBAAoB,CAC5B,IAAI,IAAI,iFAAiF,CAC1F,CAAC;IACJ,CAAC;IACD,iFAAiF;IACjF,yFAAyF;IACzF,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,SAAiB;IACtD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,uFAAuF;IACvF,yCAAyC;IACzC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,UAAU,EAAE,MAAM,CAAC,CAAC;IACxE,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC7C,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAC7C,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,UAAU,GAAG,SAAS,CAAC;QACvB,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,SAAS,CAAC,UAAU,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,kFAAkF;YACpF,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,cAAc,CAAC,IAAwB,EAAE,OAAgB;IACvE,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAC7C,CAAC;IACF,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAG,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,CAAC;IACpE,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAwB,EAAE,OAA8B;IAC1F,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;IACrG,MAAM,SAAS,GACb,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QAC9B,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC;QACjF,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IACzC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAwB,EACxB,IAAY,EACZ,aAAsB;IAEtB,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,IAAI,KAAK,CAAC,aAAa,KAAK,IAAI;QACpF,CAAC,CAAE,KAAK,CAAC,aAAyC;QAClD,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,SAAS,GAAG,aAAa;QAC7B,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE;QAC7B,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;IAC3E,MAAM,SAAS,GACb,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC;QACjC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC;QAClF,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;IAC7C,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAAwB,EAAE,YAAoB;IACxF,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,8BAA8B,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,CAAC;IAC9D,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAwB,EACxB,QAA8C;IAE9C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC;IACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAC;IAEhC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;YACtB,SAAS;QACX,CAAC;QACD,SAAS,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,IAAI,SAAS,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3F,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,IAAwB,EAAE,IAAY;IACrE,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAChD,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,152 @@
1
+ import { objetoDe } from "../tareas/juezDeTarea.js";
2
+ /** El papel del juez, el mismo que el de tareas. `core/modelos.ts` lo reserva para esto. */
3
+ export const PAPEL_DEL_JUEZ_VISUAL = "afilado";
4
+ /**
5
+ * Cuántas observaciones se conservan y cuánto ocupa cada una.
6
+ *
7
+ * Del mismo orden que las del juez de tareas, y por lo mismo: esto acaba en una tarjeta o en
8
+ * un mensaje de reparación, no en un informe. No se acota para poder compararlo —no se puede,
9
+ * ver la cabecera— sino para que quepa.
10
+ */
11
+ export const TOPE_DE_OBSERVACIONES = 8;
12
+ const TOPE_DE_OBSERVACION = 200;
13
+ /**
14
+ * Cuántas pantallas puede pedir de una vez.
15
+ *
16
+ * Tiene tope por lo mismo que `TOPE_REPARACIONES`: su salida NO es estable —seis vueltas sobre
17
+ * la misma captura dieron 4, 2, 4, 5, 3 y 5 observaciones— así que sin acotarlo pediría
18
+ * pantallas mientras alguien se las traiga, y cada una es un despliegue y una navegación.
19
+ */
20
+ export const TOPE_DE_PETICIONES = 3;
21
+ /**
22
+ * Lo que vale como pantalla pedida: un NOMBRE de colección, no una frase.
23
+ *
24
+ * Sin esto, «mándame otra foto de la pantalla anterior» entraría en la lista y quien tenga que
25
+ * ir a buscarla no sabría a dónde. Es la misma clase de criba que la del nombre de un AVD: lo
26
+ * que va a ser un argumento se cierra por FORMA.
27
+ */
28
+ const NOMBRE_DE_PANTALLA = /^[A-Za-z_][A-Za-z0-9_]*$/;
29
+ /** No se pudo PREGUNTAR: no hay modelo, no hay clave, no hay red. */
30
+ export class ErrorDelJuezVisual extends Error {
31
+ constructor(motivo) {
32
+ super(`no se pudo consultar al crítico visual (papel «${PAPEL_DEL_JUEZ_VISUAL}»): ${motivo}`);
33
+ this.name = "ErrorDelJuezVisual";
34
+ }
35
+ }
36
+ /**
37
+ * Lo que se le pide, y está escrito para que conteste lo que puede saber.
38
+ *
39
+ * «No digas la causa» no es modestia: es lo único que separa una observación útil —«el texto
40
+ * de los botones sale cortado»— de una pista falsa —«está rotado 180°»—, y lo segundo es lo
41
+ * que contestó las tres veces que se midió.
42
+ */
43
+ export const PROMPT_VISUAL = [
44
+ "Eres un revisor VISUAL de la pantalla de una app móvil. Mira la captura y di SOLO lo que se",
45
+ "ve mal, sin diagnosticar: describe lo que se ve, no la causa ni cómo arreglarlo. Quien lo",
46
+ "lea tiene el código delante y tú no.",
47
+ "",
48
+ "Busca defectos OBJETIVOS: texto cortado, que se sale o ilegible; controles solapados o fuera",
49
+ "de la pantalla; alineaciones rotas; huecos que no cuadran; algo que no se puede leer por",
50
+ "contraste. NO opines de gustos, de la paleta ni de la marca.",
51
+ "",
52
+ "Si no ves ningún defecto, dilo con la lista vacía.",
53
+ "",
54
+ "Si para dictaminar necesitas ver OTRA pantalla, pídela en `necesito` por el NOMBRE de su",
55
+ "colección y nada más (por ejemplo «Productos»), no con una frase. Alguien irá a por ella.",
56
+ "Si con lo que tienes te basta, déjalo vacío.",
57
+ "",
58
+ 'Contesta SOLO este JSON: {"veredicto":"verde"|"rojo","hallazgos":["lo que se ve", …],"necesito":["Coleccion", …]}',
59
+ ].join("\n");
60
+ /**
61
+ * Le enseña la captura al modelo y devuelve su veredicto.
62
+ *
63
+ * `invocar` entra por parámetro, así que `npm test` no le pregunta a ningún modelo — el mismo
64
+ * molde que `JuezDeTareaPort`.
65
+ */
66
+ export async function juzgarPantalla(imagen, contexto, invocar) {
67
+ const prompt = `${PROMPT_VISUAL}\n\nLa captura es de la pantalla «${contexto.pantalla}».`;
68
+ let texto;
69
+ try {
70
+ texto = await invocar(PAPEL_DEL_JUEZ_VISUAL, prompt, imagen);
71
+ }
72
+ catch (error) {
73
+ throw new ErrorDelJuezVisual(error instanceof Error ? error.message : String(error));
74
+ }
75
+ const objeto = objetoDe(texto);
76
+ if (objeto === undefined)
77
+ return { veredicto: "indeterminado", observaciones: [], necesito: [] };
78
+ const observaciones = (Array.isArray(objeto["hallazgos"]) ? objeto["hallazgos"] : [])
79
+ .filter((o) => typeof o === "string" && o.trim() !== "")
80
+ .slice(0, TOPE_DE_OBSERVACIONES)
81
+ .map((o) => (o.length > TOPE_DE_OBSERVACION ? `${o.slice(0, TOPE_DE_OBSERVACION - 1)}…` : o));
82
+ const necesito = (Array.isArray(objeto["necesito"]) ? objeto["necesito"] : [])
83
+ .filter((n) => typeof n === "string" && NOMBRE_DE_PANTALLA.test(n.trim()))
84
+ .map((n) => n.trim())
85
+ .slice(0, TOPE_DE_PETICIONES);
86
+ const dicho = objeto["veredicto"];
87
+ /**
88
+ * **Un VERDE que todavía pide pantallas no es un verde.** Misma dirección que «un
89
+ * verificador que no corrió no es verde» (`core/entrega.ts`): lo que deja pasar algo no se
90
+ * puede decir sobre lo que no se ha mirado. Lo que pide NO se tira, que es justo lo que hay
91
+ * que ir a buscar.
92
+ */
93
+ if (dicho === "verde") {
94
+ return necesito.length === 0
95
+ ? { veredicto: "verde", observaciones, necesito }
96
+ : { veredicto: "indeterminado", observaciones, necesito };
97
+ }
98
+ /**
99
+ * Un rojo sin nada que enseñar no se puede actuar: quien lo reciba no sabe qué mirar. Es la
100
+ * misma regla que «un verde sin resumen» del juez de tareas, por el otro lado.
101
+ */
102
+ if (dicho === "rojo" && observaciones.length > 0)
103
+ return { veredicto: "rojo", observaciones, necesito };
104
+ return { veredicto: "indeterminado", observaciones, necesito };
105
+ }
106
+ /**
107
+ * El `invocar` de PRODUCCIÓN, sobre `ModelosPort`.
108
+ *
109
+ * La imagen viaja como un bloque `image_url` con un `data:` dentro de un `HumanMessage`, que
110
+ * es la forma multimodal que entienden los tres proveedores a través de langchain. Se mide
111
+ * aquí y no en el módulo puro porque esto toca el SDK.
112
+ *
113
+ * **La misma asimetría de `juezDeTarea#invocarConModelos`, y por la misma medida**: construir
114
+ * el modelo falla antes de tocar la red y con un mensaje escrito para leerse, así que ése se
115
+ * CONSERVA; de la llamada solo se conserva el NOMBRE del error, porque ahí los SDK devuelven
116
+ * el cuerpo remoto y con él cabeceras y claves redactadas.
117
+ */
118
+ export function invocarVisualConModelos(modelos) {
119
+ return async (papel, prompt, imagen) => {
120
+ let modelo;
121
+ try {
122
+ modelo = modelos.paraPapel(papel);
123
+ }
124
+ catch (error) {
125
+ throw new ErrorDelJuezVisual(error instanceof Error ? error.message : String(error));
126
+ }
127
+ if (typeof modelo !== "object" ||
128
+ modelo === null ||
129
+ typeof modelo.invoke !== "function") {
130
+ throw new ErrorDelJuezVisual(`el modelo del papel «${papel}» no se puede invocar aquí`);
131
+ }
132
+ const { HumanMessage } = await import("@langchain/core/messages");
133
+ const { textoDe } = await import("../turno/puente.js");
134
+ try {
135
+ const respuesta = await modelo.invoke([
136
+ new HumanMessage({
137
+ content: [
138
+ { type: "text", text: prompt },
139
+ { type: "image_url", image_url: { url: `data:${imagen.mime};base64,${imagen.base64}` } },
140
+ ],
141
+ }),
142
+ ]);
143
+ // El MISMO extractor que el puente del stream y que el juez de tareas: dos reglas para
144
+ // sacar el texto de un mensaje son dos reglas que divergen.
145
+ return textoDe(respuesta);
146
+ }
147
+ catch (error) {
148
+ throw new ErrorDelJuezVisual(error instanceof Error ? error.name : "error de la llamada");
149
+ }
150
+ };
151
+ }
152
+ //# sourceMappingURL=juezVisual.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"juezVisual.js","sourceRoot":"","sources":["../../../src/agent/dispositivos/juezVisual.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * El APARATO como sensor del bucle de reparación: ¿qué dice la app al arrancar?
3
+ *
4
+ * Es la tercera fuente de hallazgos, y contesta una pregunta que las otras dos no pueden.
5
+ * `xone-simulator validate` mira la estructura y `smoke` ejecuta el ciclo de vida en un
6
+ * runtime de Node; ninguno de los dos sabe si la app ARRANCA en un Android de verdad, con su
7
+ * SQLite, sus recursos y su Rhino. Medido sobre AppDemo: el simulador daba verde y el aparato
8
+ * decía `Invalid resource ID 0x6000000N` cinco veces distintas.
9
+ *
10
+ * CUATRO REGLAS, y las cuatro salieron de medir:
11
+ *
12
+ * - **Despliega SIEMPRE antes de leer.** Sin eso el log sería de la versión anterior del
13
+ * proyecto, y devolverle al agente errores que ya arregló es la peor clase de feedback:
14
+ * plausible y falso. El despliegue en caliente costó 5 s sobre un `pixel8`.
15
+ * - **El buffer se vacía ANTES de reiniciar.** Es lo que ya hace `xone-desplegar-android` por
16
+ * su cuenta y por el mismo motivo: si no, lo que se lee es la excepción del intento
17
+ * anterior, que es la forma más fácil de creer que algo sigue roto cuando ya no lo está.
18
+ * - **Sin aparato es fallo del ENTORNO, no un rojo.** La misma familia que
19
+ * `ErrorDelSimulador`: un informe rojo diría «tu proyecto está mal» cuando lo que pasa es
20
+ * que no hay móvil enchufado. Y **no se arranca uno solo**: levantar un emulador cuesta
21
+ * minutos de la máquina de alguien, y esa decisión no la toma un sensor — para eso está
22
+ * `xone-arrancar-android`, que el agente puede llamar.
23
+ * - **Solo ve la pantalla de ENTRADA, y se declara.** El despliegue reinicia la app, así que
24
+ * lo que se lee es lo que pasa al arrancar. Para tener hallazgos de una colección concreta
25
+ * hay que NAVEGAR hasta ella, y eso es trabajo del `device-controller` dentro del turno, no
26
+ * de un sensor automático.
27
+ *
28
+ * Todo entra por dependencias: `npm test` no puede necesitar un aparato.
29
+ */
30
+ import { execFile } from "node:child_process";
31
+ import { existsSync } from "node:fs";
32
+ import { join } from "node:path";
33
+ import { hallazgosDeLog } from "../../core/logDeDispositivo.js";
34
+ import { RAIZ_SKILLS } from "../grafo/skills.js";
35
+ import { localizadorDeAndroid, TOPES_MS } from "./dispositivosEnMaquina.js";
36
+ import { parsearAdbDevices } from "../../core/dispositivos.js";
37
+ /** No se pudo PREGUNTARLE al aparato. Entorno, no proyecto. */
38
+ export class ErrorDelAparato extends Error {
39
+ constructor(motivo) {
40
+ super(motivo);
41
+ this.name = "ErrorDelAparato";
42
+ }
43
+ }
44
+ /**
45
+ * Despliega y devuelve lo que el aparato dijo, en la forma que el bucle ya consume.
46
+ *
47
+ * **Verde es que no hay hallazgos DE LA APP.** Lo de la plataforma viaja en el informe —no se
48
+ * tira nunca, ver `core/logDeDispositivo.ts`— pero como `warning`, así que no pinta el turno
49
+ * de rojo: son quejas de Android sobre sí mismo y nadie las puede arreglar desde un `.xne`.
50
+ */
51
+ export async function arranqueEnDispositivo(raiz, deps) {
52
+ if (!(await deps.hayAparato())) {
53
+ throw new ErrorDelAparato("no hay ningún aparato conectado, así que no se ha podido probar el arranque");
54
+ }
55
+ await deps.limpiarLog();
56
+ const despliegue = await deps.desplegar(raiz);
57
+ if (!despliegue.ok) {
58
+ /**
59
+ * Que el despliegue falle NO es un proyecto roto: puede ser el túnel, el canal o que el
60
+ * host no esté instalado. Se lanza, y quien llama lo dice como aviso — igual que el
61
+ * binario del simulador que falta.
62
+ */
63
+ throw new ErrorDelAparato(`no se pudo desplegar en el aparato: ${despliegue.detalle}`);
64
+ }
65
+ const { aHallazgosDelTurno } = hallazgosDeLog(await deps.leerLog());
66
+ const hallazgos = aHallazgosDelTurno();
67
+ return { verde: !hallazgos.some((h) => h.severidad === "error"), hallazgos };
68
+ }
69
+ /** El host de XOne en Android. Vive aquí y en los scripts de la skill, que son otro proceso. */
70
+ const PAQUETE = "com.xone.android.framework";
71
+ /**
72
+ * Cuánto se le da al despliegue. El script hace la cadena entera —túnel, ZIP, subida,
73
+ * reinicio, lanzamiento y comprobación de que la app está VIVA— y sobre un `pixel8` en
74
+ * caliente tardó 5 s con un proyecto de 6,8 MB. El tope es para el caso frío con un proyecto
75
+ * grande, y por debajo del tope de reloj de un comando del harness.
76
+ */
77
+ export const TOPE_DE_DESPLIEGUE_MS = 300_000;
78
+ /**
79
+ * El sensor de verdad: `adb` para el log y el script de la skill para el despliegue.
80
+ *
81
+ * **El despliegue NO se reimplementa aquí.** `xone-desplegar-android` ya es la cadena medida
82
+ * —y la única que sabe que hay que reiniciar con `SetupActivity` y no con `.mainEntry`, y que
83
+ * el ZIP va sin `.xonecode`—. Reescribirla sería un segundo sitio donde esa secuencia puede
84
+ * divergir, que es como este repo se ha roto siempre.
85
+ */
86
+ export function sensorDeArranqueReal() {
87
+ const { enSdk } = localizadorDeAndroid({
88
+ plataforma: process.platform,
89
+ entorno: process.env,
90
+ home: process.env["HOME"] ?? "",
91
+ existe: (ruta) => existsSync(ruta),
92
+ });
93
+ const adb = enSdk("adb", "platform-tools");
94
+ const correr = (binario, args, ms) => new Promise((resolver, rechazar) => {
95
+ execFile(binario, args, { timeout: ms, maxBuffer: 64 * 1024 * 1024 }, (error, stdout) => {
96
+ if (error !== null)
97
+ rechazar(error);
98
+ else
99
+ resolver(stdout);
100
+ });
101
+ });
102
+ const exigirAdb = () => {
103
+ if (adb === undefined)
104
+ throw new ErrorDelAparato("no encuentro «adb»: ni en el PATH ni en el SDK");
105
+ return adb;
106
+ };
107
+ return {
108
+ hayAparato: async () => {
109
+ try {
110
+ return parsearAdbDevices(await correr(exigirAdb(), ["devices"], TOPES_MS.adb)).some((d) => d.estado === "conectado");
111
+ }
112
+ catch {
113
+ // No poder preguntar no es «no hay»: se dice arriba, con su motivo.
114
+ throw new ErrorDelAparato("no se pudo preguntar a adb qué aparatos hay");
115
+ }
116
+ },
117
+ limpiarLog: async () => {
118
+ await correr(exigirAdb(), ["logcat", "-c"], TOPES_MS.adb);
119
+ },
120
+ desplegar: async (raiz) => {
121
+ const script = join(RAIZ_SKILLS, "xone-hotswap", "scripts", "xone-desplegar-android");
122
+ if (!existsSync(script))
123
+ return { ok: false, detalle: "falta xone-desplegar-android en el paquete" };
124
+ try {
125
+ // El `cwd` es la raíz del proyecto: el script empaqueta lo que hay ahí.
126
+ await new Promise((resolver, rechazar) => {
127
+ execFile(process.execPath, [script], { cwd: raiz, timeout: TOPE_DE_DESPLIEGUE_MS, maxBuffer: 16 * 1024 * 1024 }, (error) => (error === null ? resolver() : rechazar(error)));
128
+ });
129
+ return { ok: true, detalle: "" };
130
+ }
131
+ catch (error) {
132
+ // Una línea, no el volcado: esto va a un aviso del turno.
133
+ const texto = error instanceof Error ? error.message : String(error);
134
+ return { ok: false, detalle: texto.split("\n")[0] ?? "falló el despliegue" };
135
+ }
136
+ },
137
+ leerLog: async () => {
138
+ const pid = (await correr(exigirAdb(), ["shell", "pidof", PAQUETE], TOPES_MS.adb))
139
+ .trim()
140
+ .split(/\s+/)[0];
141
+ if (pid === undefined || pid === "") {
142
+ /**
143
+ * La app NO está viva tras desplegar. Es un hecho del proyecto y no del entorno —el
144
+ * despliegue dijo que sí—, así que no se lanza: se devuelve lo que haya sin acotar por
145
+ * PID, que es donde estará la traza de la muerte. Filtrar por un PID que ya no existe
146
+ * se llevaría por delante justo esa traza.
147
+ */
148
+ return correr(exigirAdb(), ["logcat", "-d", "-t", "400"], TOPES_MS.adb);
149
+ }
150
+ return correr(exigirAdb(), ["logcat", "-d", "--pid", pid], TOPES_MS.adb);
151
+ },
152
+ };
153
+ }
154
+ //# sourceMappingURL=sensorDeArranque.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensorDeArranque.js","sourceRoot":"","sources":["../../../src/agent/dispositivos/sensorDeArranque.ts"],"names":[],"mappings":"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"}