xonecode 0.38.2 → 0.38.5

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 (28) hide show
  1. package/apps/web/dist/assets/{EditorDeFichero-x5qYcQEQ.js → EditorDeFichero-Bgy1gslC.js} +1 -1
  2. package/apps/web/dist/assets/{index-DZea9YBh.js → index-3ULaaFD-.js} +86 -86
  3. package/apps/web/dist/assets/index-DVkE8VSW.css +1 -0
  4. package/apps/web/dist/assets/{php-BNj56OOc.js → php-D_cRJn_2.js} +1 -1
  5. package/apps/web/dist/assets/{ruby-BtHXxdlK.js → ruby-C1ETrNOC.js} +1 -1
  6. package/apps/web/dist/index.html +2 -2
  7. package/dist/agent/config/settingsEnDisco.js +44 -4
  8. package/dist/agent/config/settingsEnDisco.js.map +1 -1
  9. package/dist/core/dispositivoDeSesion.js +2 -7
  10. package/dist/core/dispositivoDeSesion.js.map +1 -1
  11. package/dist/core/dispositivoElegido.js +22 -0
  12. package/dist/core/dispositivoElegido.js.map +1 -0
  13. package/dist/core/puertosDeAvd.js +53 -8
  14. package/dist/core/puertosDeAvd.js.map +1 -1
  15. package/dist/core/settings.js +21 -1
  16. package/dist/core/settings.js.map +1 -1
  17. package/dist/web/servidor/arranque.js +72 -14
  18. package/dist/web/servidor/arranque.js.map +1 -1
  19. package/dist/web/servidor/transporte.js.map +1 -1
  20. package/dist/web/servidor/vestibulo.js +2 -1
  21. package/dist/web/servidor/vestibulo.js.map +1 -1
  22. package/package.json +1 -1
  23. package/skills/xone-hotswap/SKILL.md +4 -2
  24. package/skills/xone-hotswap/lib/dispositivo.mjs +106 -1
  25. package/skills/xone-hotswap/scripts/xone-desplegar-android +3 -1
  26. package/skills/xone-hotswap/scripts/xone-hotswap +4 -1
  27. package/skills/xone-hotswap/scripts/xone-reiniciar-android +3 -1
  28. package/apps/web/dist/assets/index-BE1a4adS.css +0 -1
@@ -57,7 +57,7 @@ import { motivoDeDominioInaceptable } from "../../core/tunel.js";
57
57
  import { instalarHerramientaDeDispositivos, verificarDispositivo } from "../../agent/dispositivos/dispositivosEnMaquina.js";
58
58
  import { arrancarEmulador, pararEmulador } from "../../agent/dispositivos/arranqueDeEmulador.js";
59
59
  import { borrarAvd, clonarAvd, correrPasoDeReceta, crearAvd } from "../../agent/dispositivos/instalacionEnMaquina.js";
60
- import { asignarPuertosPendientes, motivoDeNombreDeAvdInaceptable, motivoDePuertoInaceptable, puertoDeAvd, PUERTO_DEL_HOTSWAP, } from "../../core/puertosDeAvd.js";
60
+ import { asignarPuertosDeFisicos, asignarPuertosPendientes, motivoDeNombreDeAvdInaceptable, motivoDePuertoInaceptable, puertoDeDispositivo, } from "../../core/puertosDeAvd.js";
61
61
  import { abrirCarpetaDelSistema, abrirDirectorioDelSistema } from "../../agent/config/selectorEnMaquina.js";
62
62
  import { recargarFicheroDelProyecto, relanzarEnAparato, } from "../../agent/dispositivos/recargaEnAparato.js";
63
63
  import { textoDeRecarga } from "../../core/recargaEnCaliente.js";
@@ -73,7 +73,7 @@ import { borrarCredencial, guardarCredencial } from "../../agent/config/authEnDi
73
73
  import { borrarProveedorPersonalizado, guardarProveedorPersonalizado, proveedoresPersonalizados, } from "../../agent/config/configEnDisco.js";
74
74
  import { crearCheckpointerDeProyecto, mantenimientoDelCheckpointer, } from "../../agent/sesiones/checkpointer.js";
75
75
  import { resumenDePoda } from "../../core/podaDeCheckpoint.js";
76
- import { cargarSettings, guardarConcurrenciaDeTareas, guardarDepurar, guardarModoPorDefecto, guardarAjustesDeRemoto as guardarAjustesDeRemotoEnDisco, guardarWorkspace as guardarWorkspaceEnDisco, guardarDispositivos, guardarAjusteDeAvd, quitarAjustesDeAvd, guardarPuertosAsignados, guardarEntorno as guardarEntornoEnDisco, olvidarEntornoDeSettings, copiasDeEntorno, borrarCopiasDeEntorno, } from "../../agent/config/settingsEnDisco.js";
76
+ import { cargarSettings, guardarConcurrenciaDeTareas, guardarDepurar, guardarModoPorDefecto, guardarDispositivoPorDefecto, guardarAjustesDeRemoto as guardarAjustesDeRemotoEnDisco, guardarWorkspace as guardarWorkspaceEnDisco, guardarDispositivos, guardarAjusteDeAvd, quitarAjustesDeAvd, guardarPuertosAsignados, guardarPuertosDeFisicos, guardarEntorno as guardarEntornoEnDisco, olvidarEntornoDeSettings, copiasDeEntorno, borrarCopiasDeEntorno, } from "../../agent/config/settingsEnDisco.js";
77
77
  import { dentroDelWorkspace, depuracionActiva, expandirConCasa, mismaRuta, motivoParaNoOlvidarEntorno, motivoDeNombreDeEntornoInaceptable, motivoDeWorkspaceInaceptable, } from "../../core/settings.js";
78
78
  import { esModoDeEscritura, MODO_POR_OMISION, } from "../../core/modoDeEscritura.js";
79
79
  import { megasDeLasMudanzas, mudarWorkspaceLegado } from "../../agent/config/mudanzaEnDisco.js";
@@ -1282,6 +1282,8 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
1282
1282
  const depuracion = mensajeDeDepuracion();
1283
1283
  // El modo de las sesiones nuevas (IXCODE-31), por lo mismo: está en Ajustes > General.
1284
1284
  const modoPorDefecto = mensajeDeModoPorDefecto();
1285
+ // Y el aparato de las sesiones nuevas (IXCODE-51), en la misma sección.
1286
+ const dispositivoPorDefecto = mensajeDeDispositivoPorDefecto();
1285
1287
  // Y los conectores MCP, tras el workspace y por la misma regla: solo si esta ejecución
1286
1288
  // los monta, y entonces la ventana de Ajustes no se abre con la sección en blanco.
1287
1289
  const conectores = mensajeDeConectores();
@@ -1310,6 +1312,8 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
1310
1312
  cliente(depuracion);
1311
1313
  if (modoPorDefecto !== undefined)
1312
1314
  cliente(modoPorDefecto);
1315
+ if (dispositivoPorDefecto !== undefined)
1316
+ cliente(dispositivoPorDefecto);
1313
1317
  // La sesión remota, SIEMPRE que esta ejecución la monta: con `habilitado`, que es lo que
1314
1318
  // pinta el interruptor de Ajustes (y, apagado, no hay botón en el chat). Un puente abierto
1315
1319
  // con el interruptor quitado a mano en `settings.json` sale igual, para poder apagarlo.
@@ -1499,6 +1503,12 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
1499
1503
  const modo = opciones.modoPorDefectoGlobal?.();
1500
1504
  return modo === undefined ? undefined : { clase: "modoPorDefecto", modo };
1501
1505
  };
1506
+ const mensajeDeDispositivoPorDefecto = () => {
1507
+ if (opciones.dispositivoPorDefecto === undefined)
1508
+ return undefined;
1509
+ const dispositivo = opciones.dispositivoPorDefecto();
1510
+ return { clase: "dispositivoPorDefecto", ...(dispositivo === undefined ? {} : { dispositivo }) };
1511
+ };
1502
1512
  /**
1503
1513
  * El servicio de conectores, construido UNA VEZ al montar — no en cada mensaje, porque es
1504
1514
  * quien guarda en memoria las pruebas y las autorizaciones pendientes (`servicioDeConectores.ts`).
@@ -2027,6 +2037,17 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
2027
2037
  informar(`no se pudieron guardar los puertos de los emuladores (${codigoDe(error)})`);
2028
2038
  }
2029
2039
  }
2040
+ // Y los móviles físicos (IXCODE-32), DESPUÉS y releyendo: un AVD recién sembrado y un móvil
2041
+ // nuevo no pueden llevarse el mismo puerto.
2042
+ const fisicos = asignarPuertosDeFisicos(informeDeDispositivos.dispositivos.filter((d) => d.plataforma === "android" && d.clase === "fisico").map((d) => d.id), ajustesDeDispositivos());
2043
+ if (fisicos !== undefined && opciones.guardarPuertosDeFisicos !== undefined) {
2044
+ try {
2045
+ opciones.guardarPuertosDeFisicos(fisicos);
2046
+ }
2047
+ catch (error) {
2048
+ informar(`no se pudieron guardar los puertos de los móviles (${codigoDe(error)})`);
2049
+ }
2050
+ }
2030
2051
  emitir({
2031
2052
  ...mensajeDeDispositivos(informeDeDispositivos),
2032
2053
  ...(ultimoArranque === undefined ? {} : { arranque: ultimoArranque }),
@@ -3375,12 +3396,12 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
3375
3396
  dispositivo: medida.dispositivo,
3376
3397
  raiz: medida.abierto.raiz,
3377
3398
  app: medida.app,
3378
- // El puerto LOCAL del túnel es el de SU AVD: con dos emuladores y el mismo puerto,
3379
- // el `adb forward` del segundo le quita el túnel al primero sin error. Un físico no
3380
- // tiene AVD y va por el de fábrica, que es lo que hace el lanzador sin puerto.
3381
- ...(medida.dispositivo.avd === undefined
3382
- ? {}
3383
- : { puerto: puertoDeAvd(ajustesDeDispositivos(), medida.dispositivo.avd) }),
3399
+ // El puerto LOCAL del túnel es el de SU aparato: con dos aparatos y el mismo puerto,
3400
+ // el `adb forward` del segundo le quita el túnel al primero sin error. Un físico
3401
+ // tiene el suyo por su serie (IXCODE-32): antes iba al 8443 del primer AVD.
3402
+ ...(medida.dispositivo.plataforma === "android"
3403
+ ? { puerto: puertoDeDispositivo(ajustesDeDispositivos(), medida.dispositivo) }
3404
+ : {}),
3384
3405
  }, { alFase });
3385
3406
  trabajo.cancelar = enCurso.cancelar;
3386
3407
  const resultado = await enCurso.terminado;
@@ -4143,7 +4164,7 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
4143
4164
  return { motivo: "app.ini no dice el nombre de la app (name=)" };
4144
4165
  return {
4145
4166
  serie: dispositivo.id,
4146
- puerto: dispositivo.avd === undefined ? PUERTO_DEL_HOTSWAP : puertoDeAvd(ajustesDeDispositivos(), dispositivo.avd),
4167
+ puerto: puertoDeDispositivo(ajustesDeDispositivos(), dispositivo),
4147
4168
  app,
4148
4169
  };
4149
4170
  };
@@ -5812,17 +5833,19 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
5812
5833
  await medirNgrokYAnunciar();
5813
5834
  };
5814
5835
  /**
5815
- * El authtoken entra por `leerSecreto` —la MISMA puerta que una clave de API— y sale solo hacia
5816
- * `ngrok config add-authtoken`. Vacío es cancelar: no se llama a nadie ni se dice nada.
5836
+ * El authtoken entra TECLEADO en Ajustes (campo de contraseña, petición suya) o, sin él, por
5837
+ * `leerSecreto` —la MISMA puerta que una clave de API—, y sale solo hacia `guardarAuthtoken`
5838
+ * (`~/.xonecode/ngrok.json`, 0600). Nunca se apunta, ni en `informar` ni en un error, y nunca vuelve
5839
+ * al cliente: lo que vuelve es la MEDIDA (`cuenta`). Vacío es cancelar: no se llama a nadie.
5817
5840
  */
5818
- const pedirAuthtoken = async () => {
5841
+ const pedirAuthtoken = async (tecleado) => {
5819
5842
  const guardar = opciones.remoto?.guardarAuthtoken;
5820
5843
  if (guardar === undefined) {
5821
5844
  informar("sesión remota: esta ejecución no puede guardar el authtoken de ngrok");
5822
5845
  return;
5823
5846
  }
5824
5847
  const consola = vestibulo.proyectoAbierto()?.consola.consola ?? vestibulo.consola.consola;
5825
- const token = (await consola.leerSecreto("authtoken de ngrok: ")).trim();
5848
+ const token = (tecleado ?? (await consola.leerSecreto("authtoken de ngrok: "))).trim();
5826
5849
  if (token === "")
5827
5850
  return;
5828
5851
  let resultado;
@@ -6539,6 +6562,25 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
6539
6562
  respuesta.end();
6540
6563
  return;
6541
6564
  }
6565
+ if (typeof mensaje === "object" && mensaje !== null && mensaje.clase === "dispositivoPorDefecto") {
6566
+ // Como la pastilla: el cliente manda el ID y el resto sale de la última MEDIDA. Un id que no
6567
+ // está en ella no se guarda (es una foto vieja del cliente); se reemite lo que hay.
6568
+ const pedido = mensaje.id;
6569
+ if (pedido === undefined)
6570
+ opciones.guardarDispositivoPorDefecto?.(undefined);
6571
+ else if (typeof pedido === "string") {
6572
+ const d = informeDeDispositivos?.dispositivos.find((x) => x.id === pedido);
6573
+ if (d !== undefined) {
6574
+ opciones.guardarDispositivoPorDefecto?.({ id: d.id, nombre: d.nombre, plataforma: d.plataforma, clase: d.clase });
6575
+ }
6576
+ }
6577
+ const m = mensajeDeDispositivoPorDefecto();
6578
+ if (m !== undefined)
6579
+ emitir(m);
6580
+ respuesta.writeHead(204);
6581
+ respuesta.end();
6582
+ return;
6583
+ }
6542
6584
  if (typeof mensaje === "object" && mensaje !== null && mensaje.clase === "depuracion" && typeof mensaje.activa === "boolean") {
6543
6585
  opciones.guardarDepuracion?.(mensaje.activa);
6544
6586
  emitirDepuracion();
@@ -6674,7 +6716,7 @@ export function montarRutas(servidor, vestibulo, opciones = {}) {
6674
6716
  else if (mensaje.accion === "dominio")
6675
6717
  atenderDominioRemoto(mensaje.dominio);
6676
6718
  else if (mensaje.accion === "authtoken")
6677
- void pedirAuthtoken().catch(contar);
6719
+ void pedirAuthtoken(typeof mensaje.authtoken === "string" ? mensaje.authtoken : undefined).catch(contar);
6678
6720
  }
6679
6721
  respuesta.writeHead(204);
6680
6722
  respuesta.end();
@@ -7443,6 +7485,7 @@ export function emuladoresCableados(opciones = {}) {
7443
7485
  guardarAjusteDeAvd: (avd, cambio) => void guardarAjusteDeAvd(opciones.casa, avd, cambio),
7444
7486
  quitarAjustesDeAvd: (avd) => void quitarAjustesDeAvd(opciones.casa, avd),
7445
7487
  guardarPuertosAsignados: (asignados) => void guardarPuertosAsignados(opciones.casa, asignados),
7488
+ guardarPuertosDeFisicos: (asignados) => void guardarPuertosDeFisicos(opciones.casa, asignados),
7446
7489
  };
7447
7490
  }
7448
7491
  /**
@@ -7487,6 +7530,17 @@ export function ajusteDeModoPorDefectoCableado(opciones = {}) {
7487
7530
  guardarModoDelProyecto: (raiz, modo) => guardarProyecto(raiz, modo),
7488
7531
  };
7489
7532
  }
7533
+ /**
7534
+ * El aparato con que NACEN las sesiones nuevas (IXCODE-51), cableado contra `settings.json`.
7535
+ * Extraída por el patrón de fallo de siempre: la lectura va al vestíbulo (cada apertura) y a
7536
+ * Ajustes, y las dos tienen que leer el MISMO fichero que escribe el guardado.
7537
+ */
7538
+ export function ajusteDeDispositivoPorDefectoCableado(opciones = {}) {
7539
+ return {
7540
+ dispositivoPorDefecto: () => cargarSettings(opciones.casa).settings.dispositivoPorDefecto,
7541
+ guardarDispositivoPorDefecto: (dispositivo) => void guardarDispositivoPorDefecto(opciones.casa, dispositivo),
7542
+ };
7543
+ }
7490
7544
  /**
7491
7545
  * La opción `conectores` de `montarRutas`, cableada — extraída por el MISMO motivo que
7492
7546
  * `ajusteDeWorkspaceCableado`: un literal inline dentro de `arrancarConsolaWeb` no quedaría
@@ -7916,6 +7970,8 @@ export async function arrancarConsolaWeb(opciones) {
7916
7970
  // El modo con que nacen las sesiones nuevas (IXCODE-31), con la MISMA disciplina. El
7917
7971
  // lector por raíz va al vestíbulo (`vestibuloReal`); aquí, los de Ajustes y del panel.
7918
7972
  ...(({ modoPorDefecto: _paraElVestibulo, ...resto }) => resto)(ajusteDeModoPorDefectoCableado()),
7973
+ // El aparato de las sesiones nuevas (IXCODE-51), con la MISMA disciplina.
7974
+ ...ajusteDeDispositivoPorDefectoCableado(),
7919
7975
  // Los conectores MCP, con la MISMA disciplina: la composición extraída y probada
7920
7976
  // (`ajusteDeConectoresCableado`), nunca un literal aquí dentro.
7921
7977
  // Y el gestor de tareas (IXCODE-11) llama por ESE mismo servicio: los dos salen de
@@ -8178,6 +8234,8 @@ function vestibuloReal(opciones, servidor, escribir, informar, conectores) {
8178
8234
  fuentes,
8179
8235
  // Con qué modo nace una sesión nueva (IXCODE-31): el del proyecto de ESA raíz, si no el global.
8180
8236
  modoPorDefecto: ajusteDeModoPorDefectoCableado().modoPorDefecto,
8237
+ // Y con qué aparato (IXCODE-51): también una tarea, que sin él iba al emulador.
8238
+ dispositivoPorDefecto: ajusteDeDispositivoPorDefectoCableado().dispositivoPorDefecto,
8181
8239
  // Se resuelve UNA vez, aquí, y no en cada `anunciarAlta`: `git config`/`os.userInfo`
8182
8240
  // no cambian a media conexión, y repetir el subproceso en cada anuncio del alta sería
8183
8241
  // gastar sin motivo. Nunca viaja hacia CloudStudio ni hacia ningún acto —