xonecode 0.20.3 → 0.22.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 (88) hide show
  1. package/apps/web/dist/assets/index-5rtynJV_.js +490 -0
  2. package/apps/web/dist/assets/index-Cq6c6WEF.css +1 -0
  3. package/apps/web/dist/assets/{php-CDg2Quc0.js → php-BTFUgUDo.js} +1 -1
  4. package/apps/web/dist/assets/{ruby-DlFaAWQT.js → ruby-BKKiBtJK.js} +1 -1
  5. package/apps/web/dist/index.html +2 -2
  6. package/dist/agent/conectores/servicioDeConectores.js +86 -45
  7. package/dist/agent/conectores/servicioDeConectores.js.map +1 -1
  8. package/dist/agent/config/modelos.js +4 -0
  9. package/dist/agent/config/modelos.js.map +1 -1
  10. package/dist/agent/config/mudanzaEnDisco.js +237 -3
  11. package/dist/agent/config/mudanzaEnDisco.js.map +1 -1
  12. package/dist/agent/config/selectorEnMaquina.js +3 -2
  13. package/dist/agent/config/selectorEnMaquina.js.map +1 -1
  14. package/dist/agent/config/settingsEnDisco.js +76 -2
  15. package/dist/agent/config/settingsEnDisco.js.map +1 -1
  16. package/dist/agent/dispositivos/arranqueDeEmulador.js +27 -3
  17. package/dist/agent/dispositivos/arranqueDeEmulador.js.map +1 -1
  18. package/dist/agent/dispositivos/instalacionEnMaquina.js +240 -29
  19. package/dist/agent/dispositivos/instalacionEnMaquina.js.map +1 -1
  20. package/dist/agent/dispositivos/lanzamientoEnMaquina.js +12 -17
  21. package/dist/agent/dispositivos/lanzamientoEnMaquina.js.map +1 -1
  22. package/dist/agent/grafo/proyecto.js +91 -50
  23. package/dist/agent/grafo/proyecto.js.map +1 -1
  24. package/dist/agent/motores/trueforge/capacidades.js +22 -0
  25. package/dist/agent/motores/trueforge/capacidades.js.map +1 -1
  26. package/dist/agent/motores/trueforge/medidaAutomatica.js +16 -3
  27. package/dist/agent/motores/trueforge/medidaAutomatica.js.map +1 -1
  28. package/dist/agent/motores/trueforge/modeloLangchain.js +7 -1
  29. package/dist/agent/motores/trueforge/modeloLangchain.js.map +1 -1
  30. package/dist/agent/motores/trueforge/sesionTrueforge.js +135 -14
  31. package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
  32. package/dist/agent/motores/trueforge/toolsDeConectores.js +128 -0
  33. package/dist/agent/motores/trueforge/toolsDeConectores.js.map +1 -0
  34. package/dist/agent/motores/trueforge/traerDeStitch.js +142 -0
  35. package/dist/agent/motores/trueforge/traerDeStitch.js.map +1 -0
  36. package/dist/agent/subagentes/consumoExterno.js +15 -8
  37. package/dist/agent/subagentes/consumoExterno.js.map +1 -1
  38. package/dist/agent/subagentes/escrituraExterna.js +69 -2
  39. package/dist/agent/subagentes/escrituraExterna.js.map +1 -1
  40. package/dist/agent/subagentes/subagenteExterno.js +17 -1
  41. package/dist/agent/subagentes/subagenteExterno.js.map +1 -1
  42. package/dist/agent/turno/turnoReal.js +1 -0
  43. package/dist/agent/turno/turnoReal.js.map +1 -1
  44. package/dist/cli/main.js +5 -2
  45. package/dist/cli/main.js.map +1 -1
  46. package/dist/core/actos.js +44 -1
  47. package/dist/core/actos.js.map +1 -1
  48. package/dist/core/agentes.js +13 -2
  49. package/dist/core/agentes.js.map +1 -1
  50. package/dist/core/comandoExterno.js +69 -0
  51. package/dist/core/comandoExterno.js.map +1 -0
  52. package/dist/core/conectores.js +148 -3
  53. package/dist/core/conectores.js.map +1 -1
  54. package/dist/core/copiaDeAvd.js +111 -0
  55. package/dist/core/copiaDeAvd.js.map +1 -0
  56. package/dist/core/mudanzaDeWorkspace.js +105 -15
  57. package/dist/core/mudanzaDeWorkspace.js.map +1 -1
  58. package/dist/core/ports.js +28 -0
  59. package/dist/core/ports.js.map +1 -1
  60. package/dist/core/puertosDeAvd.js +64 -0
  61. package/dist/core/puertosDeAvd.js.map +1 -0
  62. package/dist/core/selectorDeCarpeta.js +88 -9
  63. package/dist/core/selectorDeCarpeta.js.map +1 -1
  64. package/dist/core/settings.js +60 -1
  65. package/dist/core/settings.js.map +1 -1
  66. package/dist/core/shellDeAgente.js +11 -0
  67. package/dist/core/shellDeAgente.js.map +1 -1
  68. package/dist/core/stitch.js +114 -0
  69. package/dist/core/stitch.js.map +1 -0
  70. package/dist/web/servidor/arranque.js +523 -52
  71. package/dist/web/servidor/arranque.js.map +1 -1
  72. package/dist/web/servidor/consolaDeTarea.js +4 -1
  73. package/dist/web/servidor/consolaDeTarea.js.map +1 -1
  74. package/dist/web/servidor/pielWeb.js +3 -1
  75. package/dist/web/servidor/pielWeb.js.map +1 -1
  76. package/dist/web/servidor/transporte.js.map +1 -1
  77. package/dist/web/servidor/vestibulo.js +154 -48
  78. package/dist/web/servidor/vestibulo.js.map +1 -1
  79. package/package.json +1 -1
  80. package/skills/xone-hotswap/SKILL.md +26 -10
  81. package/skills/xone-hotswap/lib/dispositivo.mjs +97 -3
  82. package/skills/xone-hotswap/references/conexion-y-despliegue.md +27 -15
  83. package/skills/xone-hotswap/scripts/xone-arrancar-android +9 -2
  84. package/skills/xone-hotswap/scripts/xone-desplegar-android +12 -6
  85. package/skills/xone-hotswap/scripts/xone-hotswap +32 -10
  86. package/skills/xone-hotswap/scripts/xone-reiniciar-android +23 -7
  87. package/apps/web/dist/assets/index-40sIfNsT.js +0 -485
  88. package/apps/web/dist/assets/index-BYTna8Os.css +0 -1
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Qué `Bash` se le deja correr a un agente EXTERNO (Claude Code) que declara `ejecucion: true`.
3
+ *
4
+ * En los motores externos la shell está cerrada: lo que el hijo ejecuta va directo a la máquina,
5
+ * sin nuestras guardas. La excepción es ESTRECHA a propósito: una sola llamada a uno de los
6
+ * scripts de las skills que el agente declara (`xone-hotswap`, `xone-log-android`…), por su
7
+ * NOMBRE, con argumentos que la shell no puede reinterpretar. Todo lo demás se deniega.
8
+ *
9
+ * La gramática sale de cómo se llaman de verdad (`skills/xone-hotswap/SKILL.md`): palabras
10
+ * sueltas (`--app MiApp`, `name=MAP_BT_ACEPTAR`, `--`, nombres de fichero) y, para un texto con
11
+ * espacios, comillas SIMPLES —dentro de ellas la shell no expande nada—. Se rechaza lo demás:
12
+ * comillas dobles, `$`, backticks, `\`, comodines, `~`, `{}`, `#`, redirecciones, tuberías,
13
+ * encadenados, saltos de línea y una asignación `VAR=` delante.
14
+ */
15
+ /**
16
+ * Un argumento: palabra suelta, con como mucho UN tramo entre comillas simples al final
17
+ * (`--texto='hola mundo'`, `'dos palabras'`). Dentro de las comillas simples la shell no expande
18
+ * nada; fuera, solo caracteres que no interpreta.
19
+ */
20
+ const ARGUMENTO = /^[A-Za-z0-9_./:=,@%+-]*(?:'[^'\n\r]*')?$/;
21
+ /** Parte el comando en argumentos por los espacios de FUERA de las comillas, o `undefined` si una no cierra. */
22
+ function palabras(comando) {
23
+ const salida = [];
24
+ let actual = "";
25
+ let enComillas = false;
26
+ for (const c of comando) {
27
+ if (c === "'")
28
+ enComillas = !enComillas;
29
+ if (c === " " && !enComillas) {
30
+ if (actual !== "")
31
+ salida.push(actual);
32
+ actual = "";
33
+ continue;
34
+ }
35
+ actual += c;
36
+ }
37
+ if (enComillas)
38
+ return undefined;
39
+ if (actual !== "")
40
+ salida.push(actual);
41
+ return salida;
42
+ }
43
+ /**
44
+ * El motivo por el que ese comando NO se deja correr, o `undefined` si se deja. `scripts` son los
45
+ * nombres (sin ruta) de los ejecutables de las skills del agente. El motivo dice la forma que sí
46
+ * vale: sin eso el modelo reintenta con `./scripts/…` o con la ruta de la variable.
47
+ */
48
+ export function motivoDeComandoExternoInaceptable(comando, scripts) {
49
+ const forma = `Solo puedes correr UNO de tus scripts, por su nombre y sin ruta (${scripts.join(", ")}), ` +
50
+ "con argumentos sueltos o entre comillas simples: nada de ;, &&, |, >, $, comillas dobles ni rutas al script.";
51
+ if (scripts.length === 0)
52
+ return "este agente no tiene scripts que correr";
53
+ const limpio = comando.trim();
54
+ if (limpio === "" || /[\n\r\t]/.test(limpio))
55
+ return forma;
56
+ const partes = palabras(limpio);
57
+ if (partes === undefined || partes.length === 0)
58
+ return forma;
59
+ const [programa, ...argumentos] = partes;
60
+ if (programa === undefined || !/^[A-Za-z0-9_-]+$/.test(programa) || !scripts.includes(programa)) {
61
+ return `«${programa ?? ""}» no es uno de tus scripts. ${forma}`;
62
+ }
63
+ for (const a of argumentos) {
64
+ if (a === "" || !ARGUMENTO.test(a))
65
+ return `El argumento «${a}» no se admite. ${forma}`;
66
+ }
67
+ return undefined;
68
+ }
69
+ //# sourceMappingURL=comandoExterno.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comandoExterno.js","sourceRoot":"","sources":["../../src/core/comandoExterno.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;GAIG;AACH,MAAM,SAAS,GAAG,0CAA0C,CAAC;AAE7D,gHAAgH;AAChH,SAAS,QAAQ,CAAC,OAAe;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG;YAAE,UAAU,GAAG,CAAC,UAAU,CAAC;QACxC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,MAAM,KAAK,EAAE;gBAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvC,MAAM,GAAG,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QACD,MAAM,IAAI,CAAC,CAAC;IACd,CAAC;IACD,IAAI,UAAU;QAAE,OAAO,SAAS,CAAC;IACjC,IAAI,MAAM,KAAK,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iCAAiC,CAAC,OAAe,EAAE,OAA0B;IAC3F,MAAM,KAAK,GACT,oEAAoE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;QAC3F,8GAA8G,CAAC;IACjH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,yCAAyC,CAAC;IAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,MAAM,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC;IACzC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChG,OAAO,IAAI,QAAQ,IAAI,EAAE,+BAA+B,KAAK,EAAE,CAAC;IAClE,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,OAAO,iBAAiB,CAAC,mBAAmB,KAAK,EAAE,CAAC;IAC1F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -9,9 +9,11 @@
9
9
  * abajo —estado, prueba, autorización, botones— nada sabe de qué familia viene: es lo que
10
10
  * hace que un servidor añadido a mano se comporte como Jira.
11
11
  *
12
- * **Todavía no llegan a ningún agente.** Esta pieza es la conexión y la configuración; qué
13
- * agente recibe sus tools, y con qué política de aprobación, es la pieza siguiente.
12
+ * **Llegan a los agentes de TrueForge** por `ConectoresPort` (`agent/motores/trueforge/
13
+ * toolsDeConectores.ts`): qué conectores (`conectoresParaElAgente`), a quién (`recibeConectores`)
14
+ * y qué ve el modelo (`esquemaParaElModelo`, `resultadoRecortado`) se decide aquí, puro.
14
15
  */
16
+ import { CARPETA_DE_ICONOS } from "./iconos.js";
15
17
  import { motivoDeEndpointInaceptable, motivoDeSlugInaceptable, PREFIJO_PERSONALIZADO, slugDesdeNombre } from "./modelos.js";
16
18
  /**
17
19
  * El literal, comprobado por VALOR: es lo que llega por el cable, donde puede mentir.
@@ -28,7 +30,8 @@ export function esAutenticacionDeConector(valor) {
28
30
  /**
29
31
  * Medido contra los tres servidores el 24-09-2026: deepwiki contesta `listTools` sin
30
32
  * credenciales; Notion y Atlassian publican `registration_endpoint` y S256, y aceptan un
31
- * cliente público con `redirect_uri` en loopback. El transporte NO se declara: se prueba
33
+ * cliente público con `redirect_uri` en loopback. Stitch (30-09-2026) lleva la clave en su propia
34
+ * cabecera y se comprueba con una llamada, ver `cabeceraDeClave`. El transporte NO se declara: se prueba
32
35
  * `streamable-http` y, si no, `sse`, como hace TrueForge.
33
36
  */
34
37
  export const CATALOGO_DE_CONECTORES = [
@@ -53,6 +56,17 @@ export const CATALOGO_DE_CONECTORES = [
53
56
  descripcion: "Busca páginas, lee contenido, consulta bases de datos y crea páginas.",
54
57
  autenticacion: "oauth",
55
58
  },
59
+ {
60
+ id: "stitch",
61
+ nombre: "Stitch",
62
+ url: "https://stitch.googleapis.com/mcp",
63
+ descripcion: "Diseña pantallas con Google Stitch y lee sus proyectos, pantallas y sistemas de diseño.",
64
+ autenticacion: "api-key",
65
+ cabeceraDeClave: "X-Goog-Api-Key",
66
+ comprobacion: "list_projects",
67
+ fueraDelAgente: ["delete_project", "create_design_system", "update_design_system"],
68
+ camposFueraDelResultado: { list_projects: ["designTheme", "screenInstances", "thumbnailScreenshot", "metadata"] },
69
+ },
56
70
  ];
57
71
  export function conectorDelCatalogo(id) {
58
72
  return CATALOGO_DE_CONECTORES.find((c) => c.id === id);
@@ -162,6 +176,12 @@ export function estadoDeConector(conector, hayCredencial) {
162
176
  export const TTL_DE_AUTORIZACION_MS = 10 * 60 * 1000;
163
177
  /** Conectar + listar tools: más que esto es «no responde». */
164
178
  export const TOPE_DE_CONEXION_MS = 30 * 1000;
179
+ /**
180
+ * Una llamada de un AGENTE a una tool: generar una pantalla en Stitch tarda minutos (medido: casi
181
+ * dos), y con el tope de conexión el agente veía un fallo de algo que sí terminaba. El SDK tiene su
182
+ * PROPIO tope por petición (60 s por omisión), así que este valor se le pasa también a él.
183
+ */
184
+ export const TOPE_DE_LLAMADA_MS = 10 * 60 * 1000;
165
185
  /** La ruta del callback. PÚBLICA: la redirección llega sin cookie (`SameSite=Strict`). */
166
186
  export const RUTA_CALLBACK_MCP = "/mcp/oauth/callback";
167
187
  /**
@@ -188,4 +208,129 @@ export function interpretarCallback(query, pendientes, ahora) {
188
208
  return { ok: false, motivo: "la respuesta no trae código de autorización" };
189
209
  return { ok: true, id: pendiente.id, code };
190
210
  }
211
+ /**
212
+ * Qué conectores del proyecto llegan a un AGENTE: los marcados en su `config.json`
213
+ * (`conectores`), que sigan AÑADIDOS y que esta consola sepa nombrar — y NUNCA el del gestor de
214
+ * tareas vinculado, aunque esté en la misma lista (vincular lo marca): en Jira y en Notion escribe
215
+ * el HARNESS, con su tarjeta, nunca el agente. El orden es el de los marcados; un id repetido
216
+ * sale una vez.
217
+ */
218
+ export function conectoresParaElAgente(entrada) {
219
+ const vistos = new Set();
220
+ const salida = [];
221
+ for (const id of entrada.marcados) {
222
+ if (vistos.has(id) || id === entrada.gestor || !entrada.anadidos.includes(id))
223
+ continue;
224
+ const fila = entrada.catalogo.find((c) => c.id === id);
225
+ if (fila === undefined)
226
+ continue;
227
+ vistos.add(id);
228
+ const deCodigo = conectorDelCatalogo(id);
229
+ salida.push({ id, nombre: fila.nombre, fueraDelAgente: deCodigo?.fueraDelAgente ?? [], camposFueraDelResultado: deCodigo?.camposFueraDelResultado ?? {} });
230
+ }
231
+ return salida;
232
+ }
233
+ /** Lo que admite un nombre de función en los proveedores de modelos: `^[a-zA-Z0-9_-]{1,64}$`. */
234
+ export const LARGO_MAXIMO_DE_NOMBRE_DE_TOOL = 64;
235
+ /**
236
+ * Cómo se llama la tool `tool` del conector `id` DENTRO del agente: `stitch__list_projects`. El
237
+ * prefijo evita que dos conectores con una tool del mismo nombre se pisen, y dice de dónde viene.
238
+ * Un `custom:acme` lleva `:`, que un proveedor rechaza como nombre de función: todo lo que no sea
239
+ * `[a-zA-Z0-9_-]` pasa a `_`. Recortado al máximo; devuelve `undefined` si ni así cabe algo que
240
+ * identifique a la tool (un prefijo que ya ocupa el máximo).
241
+ */
242
+ export function nombreDeToolDeConector(id, tool) {
243
+ const limpio = (t) => t.replace(/[^a-zA-Z0-9_-]/g, "_");
244
+ const nombre = `${limpio(id)}__${limpio(tool)}`;
245
+ return nombre.length <= LARGO_MAXIMO_DE_NOMBRE_DE_TOOL ? nombre : undefined;
246
+ }
247
+ /**
248
+ * Qué tools de los conectores recibe un ESPECIALISTA: todas, solo quien hace los RECURSOS —su
249
+ * `escribeEn` cubre `icons/`, de los de serie `designer-xone`—, que es quien diseña; el resto,
250
+ * ninguna. Regla de DATO, no una lista de nombres. Estrecha a propósito: las tools de un conector
251
+ * viajan en CADA llamada del agente que las recibe (las de Stitch, miles de tokens). El raíz recibe
252
+ * solo las de LECTURA, y eso lo decide la sesión: es de solo lectura por permisos.
253
+ */
254
+ export function recibeConectores(a) {
255
+ if (a.soloLectura || a.ejecucion === true)
256
+ return false;
257
+ const carpetas = a.escribeEn ?? [];
258
+ return carpetas.some((c) => `/${CARPETA_DE_ICONOS}/`.startsWith(c.endsWith("/") ? c : `${c}/`));
259
+ }
260
+ /** Cuántos `$ref` anidados se incrustan antes de cortar: un esquema recursivo no puede colgar esto. */
261
+ export const PROFUNDIDAD_MAXIMA_DE_REF = 8;
262
+ /**
263
+ * El esquema de una tool tal como se le puede dar a CUALQUIER proveedor de modelos. Medido con
264
+ * Stitch y Gemini: los esquemas de Google llevan claves propias (`x-google-identifier`,
265
+ * `x-google-enum-descriptions`…) y la API de Gemini RECHAZA la petición entera por una sola —el
266
+ * turno moría antes de empezar—. Se quitan las claves `x-…` (son anotaciones, no restricciones) y
267
+ * se INCRUSTA cada `$ref` local (`#/$defs/…`), que no todos los proveedores siguen; `$defs` sale
268
+ * con ellos. Dentro de `properties` las claves son NOMBRES de campo y no se tocan. Puro: no
269
+ * modifica lo que recibe.
270
+ */
271
+ export function esquemaParaElModelo(esquema) {
272
+ const defs = (esquema["$defs"] ?? {});
273
+ const limpiar = (nodo, profundidad) => {
274
+ if (Array.isArray(nodo))
275
+ return nodo.map((n) => limpiar(n, profundidad));
276
+ if (nodo === null || typeof nodo !== "object")
277
+ return nodo;
278
+ const o = nodo;
279
+ const ref = o["$ref"];
280
+ if (typeof ref === "string" && ref.startsWith("#/$defs/")) {
281
+ const destino = defs[ref.slice("#/$defs/".length)];
282
+ const { $ref: _ref, ...resto } = o;
283
+ if (destino === undefined || profundidad >= PROFUNDIDAD_MAXIMA_DE_REF)
284
+ return limpiar({ type: "object", ...resto }, profundidad);
285
+ return limpiar({ ...destino, ...resto }, profundidad + 1);
286
+ }
287
+ const salida = {};
288
+ for (const [clave, valor] of Object.entries(o)) {
289
+ if (clave.startsWith("x-") || clave === "$defs" || clave === "$schema")
290
+ continue;
291
+ salida[clave] =
292
+ clave === "properties" && valor !== null && typeof valor === "object" && !Array.isArray(valor)
293
+ ? Object.fromEntries(Object.entries(valor).map(([nombre, v]) => [nombre, limpiar(v, profundidad)]))
294
+ : limpiar(valor, profundidad);
295
+ }
296
+ return salida;
297
+ };
298
+ return limpiar(esquema, 0);
299
+ }
300
+ /**
301
+ * El resultado de una tool sin los `campos` que el catálogo le recorta (`camposFueraDelResultado`),
302
+ * a cualquier profundidad, con una línea al final que dice cuáles faltan —que el agente no los dé
303
+ * por inexistentes—. Lo que no es JSON, o no trae ninguno, vuelve TAL CUAL.
304
+ */
305
+ export function resultadoRecortado(texto, campos) {
306
+ if (campos.length === 0)
307
+ return texto;
308
+ let datos;
309
+ try {
310
+ datos = JSON.parse(texto);
311
+ }
312
+ catch {
313
+ return texto;
314
+ }
315
+ const fuera = new Set(campos);
316
+ const quitados = new Set();
317
+ const podar = (n) => {
318
+ if (Array.isArray(n))
319
+ return n.map(podar);
320
+ if (n === null || typeof n !== "object")
321
+ return n;
322
+ const salida = {};
323
+ for (const [k, v] of Object.entries(n)) {
324
+ if (fuera.has(k))
325
+ quitados.add(k);
326
+ else
327
+ salida[k] = podar(v);
328
+ }
329
+ return salida;
330
+ };
331
+ const podado = podar(datos);
332
+ if (quitados.size === 0)
333
+ return texto;
334
+ return `${JSON.stringify(podado)}\n(recortado por el harness: sin ${[...quitados].join(", ")}; el detalle de uno, con la tool que lo lee entero)`;
335
+ }
191
336
  //# sourceMappingURL=conectores.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"conectores.js","sourceRoot":"","sources":["../../src/core/conectores.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"conectores.js","sourceRoot":"","sources":["../../src/core/conectores.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Las reglas PURAS de «Nuevo emulador a partir de uno existente»: qué se lee de un AVD base y qué
3
+ * se copia al nuevo. El disco y `avdmanager` viven en `agent/dispositivos/instalacionEnMaquina.ts`.
4
+ *
5
+ * Dos modos, y la diferencia es cuánto de la base viaja:
6
+ * - CONFIGURACIÓN: `avdmanager` crea un AVD vacío con la imagen y el perfil de la base, y se le
7
+ * pone encima el `config.ini` de la base (RAM, disco…). Vale con la base encendida.
8
+ * - CLON: se copia la carpeta entera (lo instalado), salvo lo que `seCopiaEnClon` excluye. La base
9
+ * tiene que estar apagada: sus discos están bloqueados mientras corre.
10
+ */
11
+ /** Las líneas `clave=valor` de un `.ini` de AVD. Sin `=` o en blanco se ignoran; el valor va tal cual. */
12
+ export function leerIni(texto) {
13
+ const r = new Map();
14
+ for (const linea of texto.split(/\r?\n/)) {
15
+ const i = linea.indexOf("=");
16
+ if (i <= 0)
17
+ continue;
18
+ r.set(linea.slice(0, i).trim(), linea.slice(i + 1).trim());
19
+ }
20
+ return r;
21
+ }
22
+ const FORMA_DE_SYSDIR = /^system-images\/([^/;\s]+)\/([^/;\s]+)\/([^/;\s]+)\/?$/;
23
+ /**
24
+ * El paquete de imagen para `avdmanager -k`, de `image.sysdir.1`:
25
+ * `system-images/android-35/google_apis/arm64-v8a/` → `system-images;android-35;google_apis;arm64-v8a`.
26
+ * Sin esa forma no se adivina nada: `undefined`.
27
+ */
28
+ export function paqueteDeImagen(config) {
29
+ const m = FORMA_DE_SYSDIR.exec(config.get("image.sysdir.1") ?? "");
30
+ return m === null ? undefined : `system-images;${m[1]};${m[2]};${m[3]}`;
31
+ }
32
+ const FORMA_DE_PERFIL = /^[A-Za-z0-9._-]+$/;
33
+ /** El perfil de teléfono (`-d`) de la base: `hw.device.name`, si tiene forma de un nombre de perfil. */
34
+ export function perfilDeTelefono(config) {
35
+ const p = config.get("hw.device.name");
36
+ return p !== undefined && FORMA_DE_PERFIL.test(p) ? p : undefined;
37
+ }
38
+ /**
39
+ * El `<nombre>.ini` del clon: el de la base con `path` y `path.rel` apuntando a la carpeta nueva.
40
+ * Lo demás (`target`, codificación…) se conserva. Si la base no traía alguna de las dos claves se
41
+ * AÑADE: un `.ini` sin `path` no lo encuentra nadie.
42
+ */
43
+ export function iniDeClon(iniBase, nombre, carpetaAvd) {
44
+ const nuevas = { path: carpetaAvd, "path.rel": `avd/${nombre}.avd` };
45
+ const puestas = new Set();
46
+ const lineas = iniBase.split(/\r?\n/).filter((l, i, todas) => !(l === "" && i === todas.length - 1));
47
+ const salida = lineas.map((linea) => {
48
+ const i = linea.indexOf("=");
49
+ const clave = i > 0 ? linea.slice(0, i).trim() : undefined;
50
+ if (clave !== undefined && clave in nuevas) {
51
+ puestas.add(clave);
52
+ return `${clave}=${nuevas[clave]}`;
53
+ }
54
+ return linea;
55
+ });
56
+ for (const [clave, valor] of Object.entries(nuevas))
57
+ if (!puestas.has(clave))
58
+ salida.push(`${clave}=${valor}`);
59
+ return `${salida.join("\n")}\n`;
60
+ }
61
+ /** Ficheros sueltos de la carpeta de un AVD que NO viajan al clon: son de la última ejecución del original. */
62
+ const FICHEROS_QUE_NO_SE_COPIAN = new Set([
63
+ "hardware-qemu.ini", // lleva la ruta absoluta del original, tres veces; el emulador lo regenera
64
+ "emu-launch-params.txt", // ídem
65
+ "read-snapshot.txt",
66
+ "snapshot.trace",
67
+ "tmpAdbCmds",
68
+ "bootcompleted.ini",
69
+ ]);
70
+ /**
71
+ * ¿Entra en el clon esta ruta, relativa a la carpeta del AVD (separada por `/` o `\`)? Lista NEGRA:
72
+ * los `.lock` en cualquier nivel (el original los tiene cogidos) y los ficheros de la última
73
+ * ejecución. `snapshots/` SÍ viaja (medido): al parar, el emulador guarda la memoria en la
74
+ * instantánea, y lo que aún no se volcó al disco solo vive ahí; sin ella, el clon ve un disco a
75
+ * medias (un fichero escrito salía con 0 bytes). Hay que reescribirles la identidad
76
+ * (`hardwareIniDeClon`) o el emulador las rechaza.
77
+ */
78
+ export function seCopiaEnClon(relativa) {
79
+ const partes = relativa.split(/[\\/]/).filter((p) => p !== "" && p !== ".");
80
+ if (partes.length === 0)
81
+ return true;
82
+ const ultimo = partes[partes.length - 1];
83
+ if (ultimo.endsWith(".lock"))
84
+ return false;
85
+ return !(partes.length === 1 && FICHEROS_QUE_NO_SE_COPIAN.has(ultimo));
86
+ }
87
+ /**
88
+ * El `hardware.ini` de una instantánea del clon, con la identidad del original cambiada por la del
89
+ * clon (medido: con solo las rutas el emulador rechaza la instantánea —«cannot load snapshot»—; con
90
+ * las dos cosas la carga). Formato `clave = valor`, con espacios. Solo se tocan:
91
+ * - `avd.name` y `avd.id`, si valen exactamente la base;
92
+ * - en cualquier otro valor, los segmentos de ruta `<base>.avd` EXACTOS (entre `/` o `\`, o al
93
+ * final), nunca el nombre suelto: la base podría aparecer dentro de otra palabra.
94
+ */
95
+ export function hardwareIniDeClon(texto, base, nombre) {
96
+ const escapada = base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
97
+ const segmento = new RegExp(`(^|[\\\\/])${escapada}\\.avd(?=[\\\\/]|$)`, "g");
98
+ return texto
99
+ .split("\n")
100
+ .map((linea) => {
101
+ const m = /^(\s*)([^=\s][^=]*?)(\s*=\s*)(.*?)(\r?)$/.exec(linea);
102
+ if (m === null)
103
+ return linea;
104
+ const [, sangria, clave, igual, valor, cr] = m;
105
+ if (clave === "avd.name" || clave === "avd.id")
106
+ return `${sangria}${clave}${igual}${valor === base ? nombre : valor}${cr}`;
107
+ return `${sangria}${clave}${igual}${valor.replace(segmento, `$1${nombre}.avd`)}${cr}`;
108
+ })
109
+ .join("\n");
110
+ }
111
+ //# sourceMappingURL=copiaDeAvd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copiaDeAvd.js","sourceRoot":"","sources":["../../src/core/copiaDeAvd.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { posix } from "node:path";
2
- import { rutaDeWorkspace } from "./settings.js";
1
+ import { posix, win32 } from "node:path";
2
+ import { esRutaDeWindows, rutaDeWorkspace } from "./settings.js";
3
3
  /**
4
4
  * El literal que vivía en MEDIO del reparto: `<base>/<entorno>/workspace/<proyecto>`.
5
5
  *
@@ -12,16 +12,30 @@ export const CARPETA_DEL_REPARTO_VIEJO = "workspace";
12
12
  function esSegmentoLlano(valor) {
13
13
  return valor !== "" && valor !== "." && valor !== ".." && !/[/\\]/.test(valor);
14
14
  }
15
- function normalizar(ruta) {
16
- return posix.normalize(ruta).replace(/\/+$/, "");
15
+ /**
16
+ * Los segmentos de una ruta, con la barra invertida de Windows como separador cuando la ruta
17
+ * es de Windows. Con `posix` a secas, `C:\Users\…` era UN segmento y ni la guarda de anidadas
18
+ * ni `rutaMudada` veían nada dentro de nada.
19
+ */
20
+ function segmentos(ruta) {
21
+ const windows = esRutaDeWindows(ruta);
22
+ const barras = windows ? ruta.replace(/\\/g, "/") : ruta;
23
+ return posix.normalize(barras).replace(/(?<=.)\/+$/, "").split("/");
24
+ }
25
+ /** Dos segmentos son el mismo: en Windows sin distinguir mayúsculas, como su disco. */
26
+ function mismoSegmento(a, b, windows) {
27
+ return windows ? a.toLowerCase() === b.toLowerCase() : a === b;
28
+ }
29
+ /** ¿`prefijo` es la ruta `ruta` o una antepasada suya? Por SEGMENTOS, nunca por texto. */
30
+ function empiezaPor(ruta, prefijo, windows) {
31
+ return prefijo.length <= ruta.length && prefijo.every((seg, i) => mismoSegmento(seg, ruta[i], windows));
17
32
  }
18
33
  /** ¿Son la misma ruta, o una es antepasada de la otra? Por SEGMENTOS, nunca por texto. */
19
34
  function unaCuelgaDeLaOtra(a, b) {
20
- const uno = normalizar(a).split("/");
21
- const otro = normalizar(b).split("/");
22
- const corto = uno.length <= otro.length ? uno : otro;
23
- const largo = corto === uno ? otro : uno;
24
- return corto.every((seg, i) => largo[i] === seg);
35
+ const windows = esRutaDeWindows(a) || esRutaDeWindows(b);
36
+ const uno = segmentos(a);
37
+ const otro = segmentos(b);
38
+ return empiezaPor(uno, otro, windows) || empiezaPor(otro, uno, windows);
25
39
  }
26
40
  /**
27
41
  * Qué copias locales siguen en el reparto viejo y adónde van.
@@ -82,15 +96,91 @@ export function mudanzasPendientes(opciones) {
82
96
  * entrada para decidir si reescribe el fichero.
83
97
  */
84
98
  export function rutaMudada(ruta, mudanzas) {
85
- const partes = normalizar(ruta).split("/");
99
+ const partes = segmentos(ruta);
86
100
  for (const mudanza of mudanzas) {
87
- const origen = normalizar(mudanza.desde).split("/");
88
- if (partes.length < origen.length)
89
- continue;
90
- if (!origen.every((seg, i) => partes[i] === seg))
101
+ const windows = esRutaDeWindows(ruta) || esRutaDeWindows(mudanza.desde);
102
+ const origen = segmentos(mudanza.desde);
103
+ if (!empiezaPor(partes, origen, windows))
91
104
  continue;
92
- return posix.join(normalizar(mudanza.hacia), ...partes.slice(origen.length));
105
+ // Con las reglas del DESTINO: una base de Windows se compone con `\`.
106
+ return (esRutaDeWindows(mudanza.hacia) ? win32 : posix).join(mudanza.hacia, ...partes.slice(origen.length));
93
107
  }
94
108
  return undefined;
95
109
  }
110
+ /**
111
+ * Una ruta traducida a través de VARIAS mudanzas, en el orden en que ocurrieron: cada tanda
112
+ * es el plan de un cambio de base, y la salida de una es la entrada de la siguiente.
113
+ *
114
+ * Existe porque `rutaMudada` coge la PRIMERA coincidencia, que dentro de UN plan es correcto
115
+ * (sus orígenes no se solapan) y entre varios no: con ir de A a B y volver a A, una lista plana
116
+ * traducía `A/…` a `B/…` —la ida— aunque la vuelta ya había vaciado `B`, y abrir el proyecto
117
+ * abría una carpeta que no existe. Encadenadas, `A/…` va a `B/…` y vuelve a `A/…`.
118
+ */
119
+ export function rutaTrasLasMudanzas(ruta, tandas) {
120
+ let actual = ruta;
121
+ for (const tanda of tandas)
122
+ actual = rutaMudada(actual, tanda) ?? actual;
123
+ return actual;
124
+ }
125
+ /**
126
+ * Qué copias hay que MUDAR al cambiar el workspace de `desde` a `hacia`, o por qué no se
127
+ * puede — antes de tocar nada.
128
+ *
129
+ * **Se listan las carpetas REALES** `<desde>/<entorno>/<proyecto>`, no los entornos
130
+ * registrados: quitar un entorno de Ajustes no borra sus copias, y una mudanza que solo mirara
131
+ * la lista las dejaría huérfanas en la base vieja. Lo OCULTO no es un proyecto —las lápidas
132
+ * `.<proyecto>.borrando-…` que un borrado a medias deja (`borrarCopiaDeProyecto`) y las
133
+ * carpetas temporales de una mudanza cortada—, y se queda fuera.
134
+ *
135
+ * Tres noes, y todos antes de copiar un byte:
136
+ * - **una base cuelga de la otra** (o son la misma): copiar una carpeta dentro de sí misma no
137
+ * termina, y al revés la base vieja pasaría a parecer un entorno de la nueva;
138
+ * - **dentro de la casa de xonecode** (`~/.xonecode`), salvo su `workspace` de omisión: ahí
139
+ * viven `tareas/`, `agentes/` y `auth.json`, y un entorno llamado igual se mezclaría con
140
+ * ellos;
141
+ * - **un destino que ya existe**: se NIEGA ENTERO, nunca se pisa. En esa carpeta puede haber
142
+ * otra historia de git y otro checkpoint, y mudar la mitad dejaría el workspace partido.
143
+ */
144
+ export function planDeCambioDeBase(opciones) {
145
+ const { desde, hacia, casaXonecode } = opciones;
146
+ if (unaCuelgaDeLaOtra(desde, hacia)) {
147
+ return {
148
+ mudanzas: [],
149
+ motivo: "la carpeta nueva no puede estar dentro de la de ahora, ni al revés: elige una que no cuelgue de la otra",
150
+ };
151
+ }
152
+ const windows = esRutaDeWindows(hacia) || esRutaDeWindows(casaXonecode);
153
+ const nueva = segmentos(hacia);
154
+ const casa = segmentos(casaXonecode);
155
+ const deOmision = segmentos((esRutaDeWindows(casaXonecode) ? win32 : posix).join(casaXonecode, "workspace"));
156
+ if (empiezaPor(nueva, casa, windows) && !empiezaPor(nueva, deOmision, windows)) {
157
+ return {
158
+ mudanzas: [],
159
+ motivo: "esa carpeta es la de la configuración de XOneCode (tareas, agentes, credenciales): elige otra fuera de ella",
160
+ };
161
+ }
162
+ const mudanzas = [];
163
+ const ocupadas = [];
164
+ const separador = esRutaDeWindows(desde) ? win32 : posix;
165
+ for (const entorno of opciones.listar(desde)) {
166
+ if (!esSegmentoLlano(entorno) || entorno.startsWith("."))
167
+ continue;
168
+ for (const proyecto of opciones.listar(separador.join(desde, entorno))) {
169
+ if (!esSegmentoLlano(proyecto) || proyecto.startsWith("."))
170
+ continue;
171
+ const mudanza = { entorno, proyecto, desde: separador.join(desde, entorno, proyecto), hacia: rutaDeWorkspace(hacia, entorno, proyecto) };
172
+ if (opciones.existe(mudanza.hacia))
173
+ ocupadas.push(`${proyecto} (${entorno})`);
174
+ else
175
+ mudanzas.push(mudanza);
176
+ }
177
+ }
178
+ if (ocupadas.length > 0) {
179
+ return {
180
+ mudanzas: [],
181
+ motivo: `en la carpeta nueva ya hay ${ocupadas.length === 1 ? "una copia" : "copias"} de ${ocupadas.join(", ")}: no se pisa nada, así que no se muda ninguna`,
182
+ };
183
+ }
184
+ return { mudanzas };
185
+ }
96
186
  //# sourceMappingURL=mudanzaDeWorkspace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mudanzaDeWorkspace.js","sourceRoot":"","sources":["../../src/core/mudanzaDeWorkspace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mudanzaDeWorkspace.js","sourceRoot":"","sources":["../../src/core/mudanzaDeWorkspace.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@
8
8
  * Este fichero es TypeScript puro: no importa langchain, langgraph, deepagents, MCP,
9
9
  * Ink ni React. La frontera está probada en `core/imports.test.ts`.
10
10
  */
11
+ import { sumarPorModelo } from "./actos.js";
11
12
  /**
12
13
  * La marca de «esto es un doble», y por qué es un Symbol y no un booleano.
13
14
  *
@@ -59,6 +60,7 @@ export function consumoPersistible(c) {
59
60
  modelo: { ...c.modelo },
60
61
  externo: { ...c.externo },
61
62
  ...(c.contexto === 0 ? {} : { ventana: c.contexto }),
63
+ ...(c.porModelo === undefined ? {} : { porModelo: sumarPorModelo({}, c.porModelo) }),
62
64
  };
63
65
  }
64
66
  /**
@@ -74,6 +76,7 @@ export function consumoDeLaSesion(c) {
74
76
  modelo: { ...c.modelo },
75
77
  externo: { ...c.externo },
76
78
  contexto: c.ventana ?? 0,
79
+ ...(c.porModelo === undefined ? {} : { porModelo: sumarPorModelo({}, c.porModelo) }),
77
80
  };
78
81
  }
79
82
  /**
@@ -377,4 +380,29 @@ export class IconosEnMemoria {
377
380
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${tamano}" height="${tamano}" viewBox="0 0 24 24"><path fill="${color}" d="M0 0h24v24H0z"/></svg>`;
378
381
  }
379
382
  }
383
+ /** El doble: conectores fijos, sin red. `llamadas` deja ver qué llegó; `fallo` simula la red caída. */
384
+ export class ConectoresEnMemoria {
385
+ conectores;
386
+ fallo;
387
+ [ES_DOBLE] = true;
388
+ llamadas = [];
389
+ constructor(conectores = {}, fallo) {
390
+ this.conectores = conectores;
391
+ this.fallo = fallo;
392
+ }
393
+ delProyecto() {
394
+ return Object.entries(this.conectores).map(([id, c]) => ({ id, nombre: c.nombre, fueraDelAgente: [], camposFueraDelResultado: {} }));
395
+ }
396
+ async tools(id) {
397
+ if (this.fallo !== undefined)
398
+ throw new Error(this.fallo);
399
+ return this.conectores[id]?.tools ?? [];
400
+ }
401
+ async llamar(id, nombre, args, opciones) {
402
+ this.llamadas.push({ id, nombre, args, ...(opciones?.topeMs === undefined ? {} : { topeMs: opciones.topeMs }) });
403
+ if (this.fallo !== undefined)
404
+ throw new Error(this.fallo);
405
+ return this.conectores[id]?.respuesta ?? "";
406
+ }
407
+ }
380
408
  //# sourceMappingURL=ports.js.map