xonecode 0.35.0 → 0.37.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.
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/apps/web/dist/assets/{EditorDeFichero-CGZ6uZPa.js → EditorDeFichero-DoFEF88O.js} +1 -1
- package/apps/web/dist/assets/index-DRNhZyYF.css +1 -0
- package/apps/web/dist/assets/index-WcouJw-n.js +506 -0
- package/apps/web/dist/assets/{php-DTPkbJvq.js → php-D_qKPndv.js} +1 -1
- package/apps/web/dist/assets/{ruby-D1wBOK7G.js → ruby-Dbo7pTDa.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/dist/agent/config/settingsEnDisco.js +30 -0
- package/dist/agent/config/settingsEnDisco.js.map +1 -1
- package/dist/agent/motores/trueforge/sesionTrueforge.js +39 -1
- package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
- package/dist/agent/remoto/ngrokEnMaquina.js +103 -0
- package/dist/agent/remoto/ngrokEnMaquina.js.map +1 -0
- package/dist/agent/remoto/puenteWebSocket.js +175 -0
- package/dist/agent/remoto/puenteWebSocket.js.map +1 -0
- package/dist/agent/remoto/tunelNgrok.js +158 -0
- package/dist/agent/remoto/tunelNgrok.js.map +1 -0
- package/dist/core/idiomaDeLaRespuesta.js +38 -0
- package/dist/core/idiomaDeLaRespuesta.js.map +1 -0
- package/dist/core/panorama.js +93 -0
- package/dist/core/panorama.js.map +1 -0
- package/dist/core/ports.js +100 -0
- package/dist/core/ports.js.map +1 -1
- package/dist/core/remoto.js +117 -0
- package/dist/core/remoto.js.map +1 -0
- package/dist/core/settings.js +83 -0
- package/dist/core/settings.js.map +1 -1
- package/dist/core/tunel.js +101 -0
- package/dist/core/tunel.js.map +1 -0
- package/dist/web/servidor/arranque.js +587 -71
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/consolaWeb.js +52 -2
- package/dist/web/servidor/consolaWeb.js.map +1 -1
- package/dist/web/servidor/puenteRemoto.js +272 -0
- package/dist/web/servidor/puenteRemoto.js.map +1 -0
- package/dist/web/servidor/transporte.js.map +1 -1
- package/dist/web/servidor/vestibulo.js +39 -1
- package/dist/web/servidor/vestibulo.js.map +1 -1
- package/node_modules/@xone/xonecode-remoto/dist/base64url.d.ts +2 -0
- package/node_modules/@xone/xonecode-remoto/dist/base64url.js +19 -0
- package/node_modules/@xone/xonecode-remoto/dist/cifrado.d.ts +25 -0
- package/node_modules/@xone/xonecode-remoto/dist/cifrado.js +75 -0
- package/node_modules/@xone/xonecode-remoto/dist/contenido.d.ts +121 -0
- package/node_modules/@xone/xonecode-remoto/dist/contenido.js +191 -0
- package/node_modules/@xone/xonecode-remoto/dist/index.d.ts +6 -0
- package/node_modules/@xone/xonecode-remoto/dist/index.js +6 -0
- package/node_modules/@xone/xonecode-remoto/dist/servidor/salas.d.ts +46 -0
- package/node_modules/@xone/xonecode-remoto/dist/servidor/salas.js +128 -0
- package/node_modules/@xone/xonecode-remoto/dist/servidor/servidor.d.ts +31 -0
- package/node_modules/@xone/xonecode-remoto/dist/servidor/servidor.js +198 -0
- package/node_modules/@xone/xonecode-remoto/dist/sobre.d.ts +53 -0
- package/node_modules/@xone/xonecode-remoto/dist/sobre.js +69 -0
- package/node_modules/@xone/xonecode-remoto/dist/url.d.ts +12 -0
- package/node_modules/@xone/xonecode-remoto/dist/url.js +35 -0
- package/node_modules/@xone/xonecode-remoto/dist/version.d.ts +2 -0
- package/node_modules/@xone/xonecode-remoto/dist/version.js +2 -0
- package/node_modules/@xone/xonecode-remoto/package.json +41 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/index-Bfa2gK3J.css +1 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/index-qBo9eRDN.js +77 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/node_modules/@xone/xonecode-remoto/web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/node_modules/@xone/xonecode-remoto/web/index.html +14 -0
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +22 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +530 -0
- package/node_modules/ws/lib/receiver.js +743 -0
- package/node_modules/ws/lib/sender.js +607 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +562 -0
- package/node_modules/ws/lib/websocket.js +1407 -0
- package/node_modules/ws/package.json +74 -0
- package/node_modules/ws/wrapper.mjs +21 -0
- package/package.json +7 -1
- package/apps/web/dist/assets/index-BBQH-l_3.css +0 -1
- package/apps/web/dist/assets/index-DqYXrrxo.js +0 -499
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngrokEnMaquina.js","sourceRoot":"","sources":["../../../src/agent/remoto/ngrokEnMaquina.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
export const NOMBRE_DEL_PAQUETE = "@xone/xonecode-remoto";
|
|
2
|
+
/** `undefined` = el paquete no está instalado: quien llama lo dice, aquí no se propaga el error. */
|
|
3
|
+
export async function cargarModuloRemoto(importar = (n) => import(n)) {
|
|
4
|
+
// En una VARIABLE `string`: un literal haría que tsc y los empaquetadores lo resolvieran.
|
|
5
|
+
const nombre = NOMBRE_DEL_PAQUETE;
|
|
6
|
+
try {
|
|
7
|
+
return (await importar(nombre));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* La subruta del paquete con el PUENTE (el relé que `xonecode-server` corre en la nube), para la
|
|
15
|
+
* vía «túnel local»: xonecode lo arranca en loopback y ngrok lo publica (`tunelNgrok.ts`). Vive
|
|
16
|
+
* aquí para que el nombre del paquete siga en UN fichero.
|
|
17
|
+
*/
|
|
18
|
+
export const NOMBRE_DEL_SERVIDOR = `${NOMBRE_DEL_PAQUETE}/servidor`;
|
|
19
|
+
/**
|
|
20
|
+
* `undefined` = el paquete no está, o es una versión sin el puente (sin la subruta, o sin
|
|
21
|
+
* `arrancarServidor`): quien llama lo dice con su texto fijo.
|
|
22
|
+
*/
|
|
23
|
+
export async function cargarServidorRemoto(importar = (n) => import(n)) {
|
|
24
|
+
const nombre = NOMBRE_DEL_SERVIDOR;
|
|
25
|
+
try {
|
|
26
|
+
const m = (await importar(nombre));
|
|
27
|
+
return m !== null && typeof m === "object" && typeof m.arrancarServidor === "function" ? m : undefined;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Motivos del relé que acaban la sesión, con texto FIJO: lo que el relé diga no cruza el cable. */
|
|
34
|
+
const MOTIVOS = {
|
|
35
|
+
version: "la versión del protocolo no casa: actualiza xonecode",
|
|
36
|
+
"sala-ocupada": "esa sala ya tiene un anfitrión",
|
|
37
|
+
ritmo: "el puente cortó la conexión por exceso de mensajes",
|
|
38
|
+
"mensaje-ilegible": "el puente no entendió un mensaje",
|
|
39
|
+
};
|
|
40
|
+
const MOTIVO_DE_TAMANO = "un mensaje superó el tamaño máximo del puente";
|
|
41
|
+
/**
|
|
42
|
+
* Lo que `cerrar` espera, como mucho, a que el relé cierre el socket tras el «cerrar». Sin tope,
|
|
43
|
+
* un relé que no contesta colgaría el apagado; con él, lo peor es el comportamiento de antes.
|
|
44
|
+
*/
|
|
45
|
+
export const TOPE_DE_CIERRE_MS = 2_000;
|
|
46
|
+
/** Código de cierre WebSocket de «mensaje demasiado grande»: el relé cierra así, sin `error`. */
|
|
47
|
+
const CIERRE_MENSAJE_GRANDE = 1009;
|
|
48
|
+
export function crearPuenteWebSocket(modulo, opciones = {}) {
|
|
49
|
+
const esperas = opciones.esperasMs ?? [1_000, 2_000, 5_000, 10_000, 30_000];
|
|
50
|
+
const topeDeCierre = opciones.topeDeCierreMs ?? TOPE_DE_CIERRE_MS;
|
|
51
|
+
return {
|
|
52
|
+
async abrir(servidor, escuchas) {
|
|
53
|
+
const { sala, secreto } = modulo.generarCredenciales();
|
|
54
|
+
// UN canal cifrado por encendido, conservado en las reconexiones: uno nuevo al reconectar
|
|
55
|
+
// dejaría al relé repetir mensajes viejos del móvil.
|
|
56
|
+
const canal = await modulo.crearCanal({ secreto, sala, rol: "anfitrion" });
|
|
57
|
+
const url = modulo.urlDeSesion(modulo.baseHttpDe(servidor), sala, secreto);
|
|
58
|
+
let ws;
|
|
59
|
+
let cerrado = false;
|
|
60
|
+
let intento = 0;
|
|
61
|
+
let cola = Promise.resolve();
|
|
62
|
+
/**
|
|
63
|
+
* Lo que SALE, también en cola: el canal toma la secuencia al llamar a `cifrar` y el móvil
|
|
64
|
+
* descarta toda secuencia que no supere la última, así que cifrar en paralelo y mandar al
|
|
65
|
+
* terminar perdía un mensaje (una `reemision` o una `aprobacion` grandes, adelantadas por
|
|
66
|
+
* uno pequeño). Cifrar Y mandar van en el orden de llamada; un paso que falla no bloquea.
|
|
67
|
+
*/
|
|
68
|
+
let envios = Promise.resolve();
|
|
69
|
+
let temporizador;
|
|
70
|
+
const acabar = (motivo) => {
|
|
71
|
+
cerrado = true;
|
|
72
|
+
escuchas.alEstado({ estado: "cerrada", motivo });
|
|
73
|
+
};
|
|
74
|
+
const conectar = () => {
|
|
75
|
+
const socket = new WebSocket(servidor);
|
|
76
|
+
ws = socket;
|
|
77
|
+
socket.onopen = () => {
|
|
78
|
+
intento = 0;
|
|
79
|
+
socket.send(JSON.stringify({ t: "abrir", sala, v: modulo.VERSION_DEL_PROTOCOLO }));
|
|
80
|
+
};
|
|
81
|
+
const procesar = async (ev) => {
|
|
82
|
+
if (cerrado || ws !== socket)
|
|
83
|
+
return;
|
|
84
|
+
let s;
|
|
85
|
+
try {
|
|
86
|
+
s = JSON.parse(String(ev.data));
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (s.t === "abierta")
|
|
92
|
+
escuchas.alEstado({ estado: "abierta", url });
|
|
93
|
+
else if (s.t === "presencia" && Array.isArray(s.moviles))
|
|
94
|
+
escuchas.alPresencia(s.moviles.filter((x) => typeof x === "string"));
|
|
95
|
+
else if (s.t === "dato" && typeof s.de === "string" && typeof s.carga === "string") {
|
|
96
|
+
let claro;
|
|
97
|
+
try {
|
|
98
|
+
claro = await canal.descifrar(s.carga);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return; // lo que no descifra no es del móvil: se descarta
|
|
102
|
+
}
|
|
103
|
+
if (claro !== undefined && !cerrado)
|
|
104
|
+
escuchas.alMensaje(s.de, claro);
|
|
105
|
+
}
|
|
106
|
+
else if (s.t === "error" && typeof s.motivo === "string" && s.motivo in MOTIVOS) {
|
|
107
|
+
acabar(MOTIVOS[s.motivo]);
|
|
108
|
+
socket.close();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
// En orden de llegada: el canal real descarta lo que no supera la última secuencia vista,
|
|
112
|
+
// y descifrar en paralelo desordenaría los mensajes legítimos del móvil.
|
|
113
|
+
socket.onmessage = (ev) => {
|
|
114
|
+
cola = cola.then(() => procesar(ev)).catch(() => { });
|
|
115
|
+
};
|
|
116
|
+
socket.onclose = (ev) => {
|
|
117
|
+
if (cerrado || ws !== socket)
|
|
118
|
+
return;
|
|
119
|
+
if (ev.code === CIERRE_MENSAJE_GRANDE) {
|
|
120
|
+
acabar(MOTIVO_DE_TAMANO);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
escuchas.alEstado({ estado: "reconectando" });
|
|
124
|
+
const espera = esperas[Math.min(intento, esperas.length - 1)];
|
|
125
|
+
intento += 1;
|
|
126
|
+
temporizador = setTimeout(() => {
|
|
127
|
+
if (!cerrado)
|
|
128
|
+
conectar();
|
|
129
|
+
}, espera);
|
|
130
|
+
};
|
|
131
|
+
// Un fallo de conexión llega también como `close`: aquí solo se evita que `error` sobre.
|
|
132
|
+
socket.onerror = () => { };
|
|
133
|
+
};
|
|
134
|
+
conectar();
|
|
135
|
+
return {
|
|
136
|
+
enviar(para, mensaje) {
|
|
137
|
+
const paso = envios.then(async () => {
|
|
138
|
+
const socket = ws;
|
|
139
|
+
if (cerrado || socket?.readyState !== WebSocket.OPEN)
|
|
140
|
+
return;
|
|
141
|
+
const carga = await canal.cifrar(mensaje);
|
|
142
|
+
if (cerrado || socket.readyState !== WebSocket.OPEN)
|
|
143
|
+
return;
|
|
144
|
+
socket.send(JSON.stringify(para === undefined ? { t: "dato", carga } : { t: "dato", para, carga }));
|
|
145
|
+
});
|
|
146
|
+
envios = paso.catch(() => { });
|
|
147
|
+
return paso;
|
|
148
|
+
},
|
|
149
|
+
cerrar() {
|
|
150
|
+
cerrado = true;
|
|
151
|
+
if (temporizador !== undefined)
|
|
152
|
+
clearTimeout(temporizador);
|
|
153
|
+
const socket = ws;
|
|
154
|
+
if (socket === undefined || socket.readyState === WebSocket.CLOSED)
|
|
155
|
+
return Promise.resolve();
|
|
156
|
+
// El relé contesta al «cerrar» avisando a los móviles y cortando: cuando el socket se
|
|
157
|
+
// cierra, ese aviso ya salió. Quien mate después lo que hay en medio (ngrok) no lo pierde.
|
|
158
|
+
const cerrandose = new Promise((resolver) => {
|
|
159
|
+
const tope = setTimeout(resolver, topeDeCierre);
|
|
160
|
+
tope.unref?.();
|
|
161
|
+
socket.addEventListener("close", () => {
|
|
162
|
+
clearTimeout(tope);
|
|
163
|
+
resolver();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
if (socket.readyState === WebSocket.OPEN)
|
|
167
|
+
socket.send(JSON.stringify({ t: "cerrar" }));
|
|
168
|
+
socket.close();
|
|
169
|
+
return cerrandose;
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=puenteWebSocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"puenteWebSocket.js","sourceRoot":"","sources":["../../../src/agent/remoto/puenteWebSocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { MOTIVOS_DEL_TUNEL, motivoDeDominioInaceptable, motivoDeSalidaDeNgrok, servidorDeTunel } from "../../core/tunel.js";
|
|
2
|
+
import { authtokenDeNgrok, cargarSdkReal } from "./ngrokEnMaquina.js";
|
|
3
|
+
import { cargarServidorRemoto } from "./puenteWebSocket.js";
|
|
4
|
+
/** Lo que se espera a que ngrok dé la dirección pública. */
|
|
5
|
+
export const TOPE_DE_TUNEL_MS = 30_000;
|
|
6
|
+
/** Lo que se espera a que el SDK reconecte tras perder la conexión, antes de dar el túnel por caído. */
|
|
7
|
+
export const ESPERA_DE_RECONEXION_MS = 30_000;
|
|
8
|
+
class FalloDelTunel extends Error {
|
|
9
|
+
}
|
|
10
|
+
/** El motivo de un error del SDK, por su CÓDIGO y nunca por su texto. */
|
|
11
|
+
function motivoDeErrorDelSdk(error) {
|
|
12
|
+
const codigo = error?.errorCode;
|
|
13
|
+
return MOTIVOS_DEL_TUNEL[motivoDeSalidaDeNgrok(typeof codigo === "string" ? [codigo] : [])];
|
|
14
|
+
}
|
|
15
|
+
export function crearTunelNgrok(deps = {}) {
|
|
16
|
+
const cargarServidor = deps.cargarServidor ?? (() => cargarServidorRemoto());
|
|
17
|
+
const cargarSdk = deps.cargarSdk ?? cargarSdkReal;
|
|
18
|
+
const authtoken = deps.authtoken ?? (() => authtokenDeNgrok());
|
|
19
|
+
const topeMs = deps.topeMs ?? TOPE_DE_TUNEL_MS;
|
|
20
|
+
const esperaDeReconexionMs = deps.esperaDeReconexionMs ?? ESPERA_DE_RECONEXION_MS;
|
|
21
|
+
return {
|
|
22
|
+
async abrir({ dominio }) {
|
|
23
|
+
if (dominio !== undefined && motivoDeDominioInaceptable(dominio) !== undefined) {
|
|
24
|
+
throw new FalloDelTunel(MOTIVOS_DEL_TUNEL.dominio);
|
|
25
|
+
}
|
|
26
|
+
const sdk = await cargarSdk();
|
|
27
|
+
if (sdk === undefined)
|
|
28
|
+
throw new FalloDelTunel(MOTIVOS_DEL_TUNEL.noInstalado);
|
|
29
|
+
const token = authtoken();
|
|
30
|
+
if (token === undefined)
|
|
31
|
+
throw new FalloDelTunel(MOTIVOS_DEL_TUNEL.autenticacion);
|
|
32
|
+
const modulo = await cargarServidor();
|
|
33
|
+
if (modulo === undefined)
|
|
34
|
+
throw new FalloDelTunel(MOTIVOS_DEL_TUNEL.paqueteViejo);
|
|
35
|
+
let puente;
|
|
36
|
+
try {
|
|
37
|
+
puente = await modulo.arrancarServidor({ puerto: 0 });
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
throw new FalloDelTunel(MOTIVOS_DEL_TUNEL.puente);
|
|
41
|
+
}
|
|
42
|
+
let puenteCerrado;
|
|
43
|
+
const cerrarPuente = () => (puenteCerrado ??= puente.cerrar().catch(() => { }));
|
|
44
|
+
// `host:puerto` tal como escucha el puente (127.0.0.1), y no «localhost», que puede resolver a ::1 y dejar a ngrok
|
|
45
|
+
// sin nadie al otro lado.
|
|
46
|
+
const destino = new URL(puente.urlHttp).host;
|
|
47
|
+
let cerrando = false;
|
|
48
|
+
let caida;
|
|
49
|
+
const caidas = [];
|
|
50
|
+
let reconexion;
|
|
51
|
+
let tunel;
|
|
52
|
+
let tunelCerrado;
|
|
53
|
+
const cerrarTunel = () => (tunelCerrado ??= (tunel?.close() ?? Promise.resolve()).catch(() => { }));
|
|
54
|
+
/** Un oyente que lanza no tumba la consola ni deja sin aviso a los demás. */
|
|
55
|
+
const avisar = (f, motivo) => {
|
|
56
|
+
if (cerrando)
|
|
57
|
+
return;
|
|
58
|
+
try {
|
|
59
|
+
f(motivo);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// es de quien escucha
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const darPorCaido = () => {
|
|
66
|
+
if (cerrando || caida !== undefined)
|
|
67
|
+
return;
|
|
68
|
+
caida = cerrarTunel()
|
|
69
|
+
.then(() => cerrarPuente())
|
|
70
|
+
.then(() => MOTIVOS_DEL_TUNEL.seCerro);
|
|
71
|
+
void caida.then((m) => {
|
|
72
|
+
for (const f of caidas.splice(0))
|
|
73
|
+
avisar(f, m);
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const alCambiarEstado = (estado) => {
|
|
77
|
+
if (estado === "closed") {
|
|
78
|
+
if (reconexion === undefined && !cerrando) {
|
|
79
|
+
reconexion = setTimeout(darPorCaido, esperaDeReconexionMs);
|
|
80
|
+
reconexion.unref?.();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (estado === "connected" && reconexion !== undefined) {
|
|
84
|
+
clearTimeout(reconexion);
|
|
85
|
+
reconexion = undefined;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
let tope;
|
|
89
|
+
let agotado = false;
|
|
90
|
+
try {
|
|
91
|
+
const abierto = sdk.forward({
|
|
92
|
+
addr: destino,
|
|
93
|
+
authtoken: token,
|
|
94
|
+
...(dominio === undefined ? {} : { domain: dominio }),
|
|
95
|
+
onStatusChange: alCambiarEstado,
|
|
96
|
+
});
|
|
97
|
+
// Si llega DESPUÉS del tope, se cierra: nadie lo va a usar.
|
|
98
|
+
void abierto.then((t) => {
|
|
99
|
+
if (agotado)
|
|
100
|
+
void t.close().catch(() => { });
|
|
101
|
+
}, () => { });
|
|
102
|
+
tunel = await Promise.race([
|
|
103
|
+
abierto,
|
|
104
|
+
new Promise((_, rechazar) => {
|
|
105
|
+
tope = setTimeout(() => {
|
|
106
|
+
agotado = true;
|
|
107
|
+
rechazar(new FalloDelTunel(MOTIVOS_DEL_TUNEL.sinDireccion));
|
|
108
|
+
}, topeMs);
|
|
109
|
+
}),
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
cerrando = true;
|
|
114
|
+
await cerrarPuente();
|
|
115
|
+
throw error instanceof FalloDelTunel ? error : new FalloDelTunel(motivoDeErrorDelSdk(error));
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
if (tope !== undefined)
|
|
119
|
+
clearTimeout(tope);
|
|
120
|
+
}
|
|
121
|
+
let servidor;
|
|
122
|
+
try {
|
|
123
|
+
const publica = tunel.url();
|
|
124
|
+
if (publica === null)
|
|
125
|
+
throw new Error("sin dirección");
|
|
126
|
+
servidor = servidorDeTunel(publica);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
cerrando = true;
|
|
130
|
+
await cerrarTunel();
|
|
131
|
+
await cerrarPuente();
|
|
132
|
+
throw new FalloDelTunel(MOTIVOS_DEL_TUNEL.sinDireccion);
|
|
133
|
+
}
|
|
134
|
+
let cerrado;
|
|
135
|
+
return {
|
|
136
|
+
servidor,
|
|
137
|
+
cerrar: () => (cerrado ??= (async () => {
|
|
138
|
+
cerrando = true;
|
|
139
|
+
caidas.length = 0;
|
|
140
|
+
if (reconexion !== undefined)
|
|
141
|
+
clearTimeout(reconexion);
|
|
142
|
+
await cerrarTunel();
|
|
143
|
+
await cerrarPuente();
|
|
144
|
+
})()),
|
|
145
|
+
alCaer: (f) => {
|
|
146
|
+
if (cerrando)
|
|
147
|
+
return;
|
|
148
|
+
if (caida !== undefined) {
|
|
149
|
+
void caida.then((m) => avisar(f, m));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
caidas.push(f);
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=tunelNgrok.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunelNgrok.js","sourceRoot":"","sources":["../../../src/agent/remoto/tunelNgrok.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **Una respuesta que se fue al CHINO**, medida con reglas de código y no con otro modelo.
|
|
3
|
+
*
|
|
4
|
+
* Medido en Maset: tras un turno largo, `deepseek-flash` escribió la respuesta FINAL entera en chino, con su propio
|
|
5
|
+
* razonamiento diciendo justo antes «write the final answer in Spanish». La regla del idioma (`IDIOMA_DE_LA_RESPUESTA`)
|
|
6
|
+
* le había llegado y la había entendido: es una deriva del modelo, no un prompt que falte, así que el arreglo es código.
|
|
7
|
+
* Solo se reconoce el chino (lo único visto); una deriva a otro idioma no la ve esta regla.
|
|
8
|
+
*/
|
|
9
|
+
/** Ideogramas CJK unificados: el chino escrito. El japonés los usa también, y entonces se mira la petición. */
|
|
10
|
+
const HAN = /[㐀-䶿一-鿿]/gu;
|
|
11
|
+
/** Letras de cualquier escritura: la base contra la que se mide la proporción. */
|
|
12
|
+
const LETRA = /\p{L}/gu;
|
|
13
|
+
/** Por debajo de esto no se juzga: un nombre de producto en chino no es una respuesta en chino. */
|
|
14
|
+
export const MINIMO_DE_IDEOGRAMAS = 20;
|
|
15
|
+
/** Qué parte de las letras de la respuesta tienen que ser ideogramas para darla por escrita en chino. */
|
|
16
|
+
export const PROPORCION_EN_CHINO = 0.3;
|
|
17
|
+
function proporcionHan(texto) {
|
|
18
|
+
const han = texto.match(HAN)?.length ?? 0;
|
|
19
|
+
const letras = texto.match(LETRA)?.length ?? 0;
|
|
20
|
+
return { han, proporcion: letras === 0 ? 0 : han / letras };
|
|
21
|
+
}
|
|
22
|
+
/** ¿La respuesta está escrita en chino y quien pide NO escribe en chino? Una petición con ideogramas no se corrige. */
|
|
23
|
+
export function respuestaEnChinoSinPedirlo(respuesta, peticion) {
|
|
24
|
+
const r = proporcionHan(respuesta);
|
|
25
|
+
if (r.han < MINIMO_DE_IDEOGRAMAS || r.proporcion < PROPORCION_EN_CHINO)
|
|
26
|
+
return false;
|
|
27
|
+
return (peticion.match(HAN)?.length ?? 0) === 0;
|
|
28
|
+
}
|
|
29
|
+
/** Hasta dónde se cita el mensaje del usuario en la orden de reescribir: lo justo para que se vea su idioma. */
|
|
30
|
+
export const TOPE_DE_CITA_DEL_USUARIO = 200;
|
|
31
|
+
/** El mensaje que le devuelve al modelo su respuesta para que la reescriba, sin herramientas y sin cambiar el contenido. */
|
|
32
|
+
export function textoDeReescritura(peticion) {
|
|
33
|
+
const cita = peticion.trim().slice(0, TOPE_DE_CITA_DEL_USUARIO);
|
|
34
|
+
return ("[Aviso del harness] Tu última respuesta salió escrita en chino, y el usuario no escribe en chino. Reescríbela ENTERA " +
|
|
35
|
+
"en el idioma en que te escribe el usuario, sin cambiar su contenido, sin añadir nada y sin llamar a ninguna herramienta. " +
|
|
36
|
+
`Su mensaje empezaba así: «${cita}»`);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=idiomaDeLaRespuesta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idiomaDeLaRespuesta.js","sourceRoot":"","sources":["../../src/core/idiomaDeLaRespuesta.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+GAA+G;AAC/G,MAAM,GAAG,GAAG,YAAY,CAAC;AACzB,kFAAkF;AAClF,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB,mGAAmG;AACnG,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,yGAAyG;AACzG,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IAC/C,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED,uHAAuH;AACvH,MAAM,UAAU,0BAA0B,CAAC,SAAiB,EAAE,QAAgB;IAC5E,MAAM,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,CAAC,GAAG,GAAG,oBAAoB,IAAI,CAAC,CAAC,UAAU,GAAG,mBAAmB;QAAE,OAAO,KAAK,CAAC;IACrF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,gHAAgH;AAChH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C,4HAA4H;AAC5H,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC;IAChE,OAAO,CACL,uHAAuH;QACvH,2HAA2H;QAC3H,6BAA6B,IAAI,GAAG,CACrC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** Cuántas tareas terminadas viajan (las más recientes por `acabada`). */
|
|
2
|
+
export const TAREAS_TERMINADAS_EN_PANORAMA = 5;
|
|
3
|
+
export const CARACTERES_DE_TITULO = 120;
|
|
4
|
+
export const CARACTERES_DE_MOTIVO = 400;
|
|
5
|
+
/** Líneas de diff por fichero; pasadas esas, se recorta y se marca `recortada`. */
|
|
6
|
+
export const LINEAS_DE_DIFF_EN_PANORAMA = 200;
|
|
7
|
+
/** El feedback que el móvil manda a una tarea se recorta a esto. */
|
|
8
|
+
export const CARACTERES_DE_FEEDBACK = 4000;
|
|
9
|
+
/** Como mucho una vez por este intervalo se manda un panorama nuevo a los móviles. */
|
|
10
|
+
export const INTERVALO_DE_PANORAMA_MS = 1000;
|
|
11
|
+
const URGENCIA = { "esperando-aprobacion": 0, "esperando-respuesta": 1, trabajando: 2, parada: 3 };
|
|
12
|
+
const ORDEN_DE_TAREA = { "requiere-atencion": 0, "en-proceso": 1, nuevo: 2, terminada: 3 };
|
|
13
|
+
const recortarTexto = (t, tope) => (t.length <= tope ? t : `${t.slice(0, Math.max(0, tope - 1))}…`);
|
|
14
|
+
function estadoDe(c) {
|
|
15
|
+
if (c.aprobacion !== undefined)
|
|
16
|
+
return "esperando-aprobacion";
|
|
17
|
+
if (c.preguntaPendiente)
|
|
18
|
+
return "esperando-respuesta";
|
|
19
|
+
if (c.turnoEnVuelo)
|
|
20
|
+
return "trabajando";
|
|
21
|
+
return "parada";
|
|
22
|
+
}
|
|
23
|
+
function aprobacionRecortada(a) {
|
|
24
|
+
let recortada = false;
|
|
25
|
+
const diffs = {};
|
|
26
|
+
for (const [id, lineas] of Object.entries(a.diffs)) {
|
|
27
|
+
if (lineas.length > LINEAS_DE_DIFF_EN_PANORAMA) {
|
|
28
|
+
diffs[id] = lineas.slice(0, LINEAS_DE_DIFF_EN_PANORAMA);
|
|
29
|
+
recortada = true;
|
|
30
|
+
}
|
|
31
|
+
else
|
|
32
|
+
diffs[id] = lineas;
|
|
33
|
+
}
|
|
34
|
+
return { pendientes: a.pendientes, ficheros: a.ficheros, diffs, ...(recortada ? { recortada: true } : {}) };
|
|
35
|
+
}
|
|
36
|
+
function tareaRecortada(t) {
|
|
37
|
+
const { motivo, ...resto } = t;
|
|
38
|
+
return {
|
|
39
|
+
...resto,
|
|
40
|
+
titulo: recortarTexto(t.titulo, CARACTERES_DE_TITULO),
|
|
41
|
+
...(t.estado === "requiere-atencion" && motivo !== undefined ? { motivo: recortarTexto(motivo, CARACTERES_DE_MOTIVO) } : {}),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const cmp = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
45
|
+
/**
|
|
46
|
+
* Pone cada tarea con `tras` justo detrás de su anterior, si esa viaja también. Tolera ciclos.
|
|
47
|
+
* Una anterior TERMINADA ya no retiene (`siguientesAEjecutar`): la siguiente se queda en su bloque
|
|
48
|
+
* de prioridad y no se va al de las terminadas. Y una tarea que se nombra a sí misma no se mueve.
|
|
49
|
+
*/
|
|
50
|
+
function respetandoTras(lista) {
|
|
51
|
+
const salida = [...lista];
|
|
52
|
+
for (let pasada = 0; pasada < lista.length; pasada++) {
|
|
53
|
+
let movida = false;
|
|
54
|
+
for (const t of [...salida]) {
|
|
55
|
+
if (t.tras === undefined || t.tras === t.id)
|
|
56
|
+
continue;
|
|
57
|
+
const iAnterior = salida.findIndex((x) => x.id === t.tras);
|
|
58
|
+
const iT = salida.indexOf(t);
|
|
59
|
+
if (iAnterior === -1 || salida[iAnterior].estado === "terminada" || iT > iAnterior)
|
|
60
|
+
continue;
|
|
61
|
+
salida.splice(iT, 1);
|
|
62
|
+
salida.splice(salida.findIndex((x) => x.id === t.tras) + 1, 0, t);
|
|
63
|
+
movida = true;
|
|
64
|
+
}
|
|
65
|
+
if (!movida)
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
return salida;
|
|
69
|
+
}
|
|
70
|
+
export function componerPanorama(entrada) {
|
|
71
|
+
const consolas = entrada.consolas
|
|
72
|
+
.map((c) => ({
|
|
73
|
+
id: c.id,
|
|
74
|
+
proyecto: c.proyecto,
|
|
75
|
+
...(c.sesion !== undefined ? { sesion: c.sesion } : {}),
|
|
76
|
+
foco: c.foco,
|
|
77
|
+
estado: estadoDe(c),
|
|
78
|
+
...(c.ultimaActividad !== undefined ? { ultimaActividad: c.ultimaActividad } : {}),
|
|
79
|
+
...(c.aprobacion !== undefined ? { aprobacion: aprobacionRecortada(c.aprobacion) } : {}),
|
|
80
|
+
}))
|
|
81
|
+
.sort((a, b) => Number(b.foco) - Number(a.foco) || URGENCIA[a.estado] - URGENCIA[b.estado]);
|
|
82
|
+
const vivas = entrada.tareas
|
|
83
|
+
.filter((t) => t.estado !== "terminada")
|
|
84
|
+
.sort((a, b) => ORDEN_DE_TAREA[a.estado] - ORDEN_DE_TAREA[b.estado] || cmp(a.creada, b.creada));
|
|
85
|
+
const terminadas = entrada.tareas
|
|
86
|
+
.filter((t) => t.estado === "terminada")
|
|
87
|
+
.sort((a, b) => cmp(b.acabada ?? b.creada, a.acabada ?? a.creada))
|
|
88
|
+
.slice(0, TAREAS_TERMINADAS_EN_PANORAMA);
|
|
89
|
+
const tareas = respetandoTras([...vivas, ...terminadas]).map(tareaRecortada);
|
|
90
|
+
const esperando = consolas.reduce((n, c) => n + (c.aprobacion?.pendientes.length ?? 0), 0) + tareas.filter((t) => t.estado === "requiere-atencion").length;
|
|
91
|
+
return { clase: "panorama", consolas, tareas, esperando };
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=panorama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panorama.js","sourceRoot":"","sources":["../../src/core/panorama.ts"],"names":[],"mappings":"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"}
|
package/dist/core/ports.js
CHANGED
|
@@ -460,4 +460,104 @@ export class ConectoresEnMemoria {
|
|
|
460
460
|
return this.conectores[id]?.respuesta ?? "";
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
|
+
/** El doble: deja al test hacer de servidor y de móviles, y apunta lo enviado. */
|
|
464
|
+
export class PuenteRemotoEnMemoria {
|
|
465
|
+
[ES_DOBLE] = true;
|
|
466
|
+
aperturas = [];
|
|
467
|
+
enviados = [];
|
|
468
|
+
cerrados = 0;
|
|
469
|
+
/**
|
|
470
|
+
* Un registro POR canal abierto: el real tiene sockets viejos que aún pueden hablar tras
|
|
471
|
+
* cerrarse o reemplazarse, y sin poder disparar eventos de uno viejo ese fallo no se probaría.
|
|
472
|
+
*/
|
|
473
|
+
canales = [];
|
|
474
|
+
async abrir(servidor, escuchas) {
|
|
475
|
+
this.aperturas.push(servidor);
|
|
476
|
+
const registro = { servidor, escuchas, cerrado: false, enviados: [] };
|
|
477
|
+
this.canales.push(registro);
|
|
478
|
+
return {
|
|
479
|
+
enviar: async (para, mensaje) => {
|
|
480
|
+
this.enviados.push({ para, mensaje });
|
|
481
|
+
registro.enviados.push({ para, mensaje });
|
|
482
|
+
},
|
|
483
|
+
cerrar: async () => {
|
|
484
|
+
registro.cerrado = true;
|
|
485
|
+
this.cerrados += 1;
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
ultimo() {
|
|
490
|
+
return this.canales.at(-1)?.escuchas;
|
|
491
|
+
}
|
|
492
|
+
/** Lo que haría el servidor real; sin índice, sobre el canal MÁS RECIENTE. */
|
|
493
|
+
abierta(url = "https://remoto.example/r/SALA#SECRETO", canal) {
|
|
494
|
+
(canal === undefined ? this.ultimo() : this.canales[canal]?.escuchas)?.alEstado({ estado: "abierta", url });
|
|
495
|
+
}
|
|
496
|
+
presencia(...moviles) {
|
|
497
|
+
this.ultimo()?.alPresencia(moviles);
|
|
498
|
+
}
|
|
499
|
+
presenciaDe(canal, ...moviles) {
|
|
500
|
+
this.canales[canal]?.escuchas.alPresencia(moviles);
|
|
501
|
+
}
|
|
502
|
+
delMovil(de, mensaje) {
|
|
503
|
+
this.ultimo()?.alMensaje(de, mensaje);
|
|
504
|
+
}
|
|
505
|
+
cerrada(motivo, canal) {
|
|
506
|
+
(canal === undefined ? this.ultimo() : this.canales[canal]?.escuchas)?.alEstado(motivo === undefined ? { estado: "cerrada" } : { estado: "cerrada", motivo });
|
|
507
|
+
}
|
|
508
|
+
reconectando(canal) {
|
|
509
|
+
(canal === undefined ? this.ultimo() : this.canales[canal]?.escuchas)?.alEstado({ estado: "reconectando" });
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
/** El doble: apunta aperturas y cierres, y deja al test elegir la dirección, un fallo o la caída. */
|
|
513
|
+
export class TunelEnMemoria {
|
|
514
|
+
[ES_DOBLE] = true;
|
|
515
|
+
aperturas = [];
|
|
516
|
+
cerrados = 0;
|
|
517
|
+
/** El `servidor` que devuelve la próxima apertura. */
|
|
518
|
+
servidor = "wss://tunel.example/ws";
|
|
519
|
+
/** Con valor, la próxima apertura LANZA con este motivo (y se consume). */
|
|
520
|
+
fallo;
|
|
521
|
+
/** Un registro por túnel abierto: cerrado o caído ya no avisa, como el real. */
|
|
522
|
+
tuneles = [];
|
|
523
|
+
async abrir(o) {
|
|
524
|
+
this.aperturas.push({ ...o });
|
|
525
|
+
if (this.fallo !== undefined) {
|
|
526
|
+
const motivo = this.fallo;
|
|
527
|
+
this.fallo = undefined;
|
|
528
|
+
throw new Error(motivo);
|
|
529
|
+
}
|
|
530
|
+
const registro = { escuchas: [], cerrado: false, caido: undefined };
|
|
531
|
+
this.tuneles.push(registro);
|
|
532
|
+
return {
|
|
533
|
+
servidor: this.servidor,
|
|
534
|
+
cerrar: async () => {
|
|
535
|
+
if (registro.cerrado)
|
|
536
|
+
return;
|
|
537
|
+
registro.cerrado = true;
|
|
538
|
+
registro.escuchas.length = 0;
|
|
539
|
+
this.cerrados += 1;
|
|
540
|
+
},
|
|
541
|
+
alCaer: (f) => {
|
|
542
|
+
if (registro.cerrado)
|
|
543
|
+
return;
|
|
544
|
+
if (registro.caido !== undefined) {
|
|
545
|
+
const motivo = registro.caido;
|
|
546
|
+
queueMicrotask(() => f(motivo));
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
registro.escuchas.push(f);
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
/** Lo que haría ngrok al salir solo; sin índice, el túnel MÁS RECIENTE. Una vez por túnel. */
|
|
554
|
+
caer(motivo, tunel) {
|
|
555
|
+
const registro = tunel === undefined ? this.tuneles.at(-1) : this.tuneles[tunel];
|
|
556
|
+
if (registro === undefined || registro.cerrado || registro.caido !== undefined)
|
|
557
|
+
return;
|
|
558
|
+
registro.caido = motivo;
|
|
559
|
+
for (const f of registro.escuchas.splice(0))
|
|
560
|
+
f(motivo);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
463
563
|
//# sourceMappingURL=ports.js.map
|