@getparallel/parx 0.4.4 → 0.6.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/CHANGELOG.md +16 -0
- package/README.md +21 -6
- package/dist/actualizar.js +2 -1
- package/dist/agente.js +82 -2
- package/dist/api.js +32 -0
- package/dist/cli.js +385 -36
- package/dist/comandos.js +71 -0
- package/dist/config.js +4 -0
- package/dist/consejos.js +2 -1
- package/dist/estimacion.js +118 -0
- package/dist/firmas.js +55 -0
- package/dist/marca.js +56 -19
- package/dist/menciones.js +85 -0
- package/dist/par.js +355 -0
- package/dist/remoto.js +284 -0
- package/dist/tar.js +99 -0
- package/dist/textos.js +95 -6
- package/dist/tui.js +132 -15
- package/dist/ui.js +35 -2
- package/dist/versiones.js +341 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6,15 +6,18 @@ import { basename, resolve } from 'node:path';
|
|
|
6
6
|
import { parseArgs } from 'node:util';
|
|
7
7
|
import { randomUUID } from 'node:crypto';
|
|
8
8
|
import { ALIAS_COMANDO, ALIAS_SI_NO, COMANDOS, t, USO } from "./textos.js";
|
|
9
|
-
import { c, colorDeModo, fijarCapacidades, sep, signo, SIMBOLOS } from "./marca.js";
|
|
9
|
+
import { c, capacidades, colorDeModo, fijarCapacidades, sep, signo, sinColor, SIMBOLOS } from "./marca.js";
|
|
10
10
|
import { guardarAjustes, leerAjustes, migrarCarpetaVieja, VERSION } from "./config.js";
|
|
11
11
|
import { MODELO_POR_DEFECTO, MODELOS, modeloDe, nombreDeModelo } from "./modelos.js";
|
|
12
|
-
import { correoVisible, crearMision, ErrorDeParallel, leerBandeja, leerCuenta, quienEs, responderBandeja, verMision } from "./api.js";
|
|
13
|
-
import { comoHasEntrado, credencialesActivas, entrar, formaDeLaOpcion, salir } from "./cuenta.js";
|
|
14
|
-
import {
|
|
12
|
+
import { cicloDeMision, compartirMision, correoVisible, crearMision, equipo, ErrorDeParallel, leerBandeja, leerConexiones, leerCuenta, leerMisionDeLaCuenta, leerMisiones, leerPlantillas, quienEs, responderBandeja, verMision, } from "./api.js";
|
|
13
|
+
import { abrirNavegador, comoHasEntrado, credencialesActivas, entrar, formaDeLaOpcion, salir } from "./cuenta.js";
|
|
14
|
+
import { accionesDeUnaMision, filtrarPorTitulo, hace } from "./comandos.js";
|
|
15
|
+
import { hacerTarea, mensajeDeError, nuevaSesion, reiniciarConversacion } from "./agente.js";
|
|
15
16
|
import { deshacerUltimo, permitirCarpeta } from "./herramientas.js";
|
|
16
17
|
import { Registro } from "./registro.js";
|
|
17
18
|
import { Pantalla } from "./ui.js";
|
|
19
|
+
import { Remoto } from "./remoto.js";
|
|
20
|
+
import { qrEnTexto } from "./qr.js";
|
|
18
21
|
import { acciones, bloqueDeBienvenida, bloqueDeLaPersona, bloqueDeTabla, duracion, Superficie } from "./tui.js";
|
|
19
22
|
import { CONSEJOS, cambiarConsejos, consejo, elegirConsejos, ordenDeConsejos } from "./consejos.js";
|
|
20
23
|
import { anchoDe, recortarMedio } from "./texto.js";
|
|
@@ -23,9 +26,9 @@ import { avisarEnElEscritorio, debeAvisar } from "./notificar.js";
|
|
|
23
26
|
import { copiarAlPortapapeles, escribirInforme, textoParaPegar } from "./informe.js";
|
|
24
27
|
import { objetivoDeMision } from "./mision.js";
|
|
25
28
|
import { ejecutarCarriles, MAX_CARRILES } from "./carriles.js";
|
|
26
|
-
import { spawnSync } from 'node:child_process';
|
|
27
29
|
import { ejecutarBash, textoParaElAgente } from "./bash.js";
|
|
28
|
-
import { comprobarDeFondo, esMasNueva, ordenDeActualizar, rutaDelCli, ultimaPublicada, versionNuevaConocida } from "./actualizar.js";
|
|
30
|
+
import { comprobarDeFondo, ENTRE_COMPROBACIONES_MS, esMasNueva, ordenDeActualizar, rutaDelCli, ultimaPublicada, versionNuevaConocida } from "./actualizar.js";
|
|
31
|
+
import { autoactualizarApagada, confirmarArranque, gestorPermiteAutoactualizar, lanzarLaMasNueva, prepararVersion } from "./versiones.js";
|
|
29
32
|
function opciones() {
|
|
30
33
|
return parseArgs({
|
|
31
34
|
allowPositionals: true,
|
|
@@ -45,6 +48,7 @@ function opciones() {
|
|
|
45
48
|
'no-mouse': { type: 'boolean' },
|
|
46
49
|
'no-animation': { type: 'boolean' },
|
|
47
50
|
animation: { type: 'boolean' },
|
|
51
|
+
remote: { type: 'boolean' },
|
|
48
52
|
version: { type: 'boolean', short: 'v' },
|
|
49
53
|
help: { type: 'boolean', short: 'h' },
|
|
50
54
|
browser: { type: 'boolean' },
|
|
@@ -69,15 +73,38 @@ function rutaCorta(ruta, max = 48) {
|
|
|
69
73
|
const corta = ruta.startsWith(casa) ? `~${ruta.slice(casa.length)}` : ruta;
|
|
70
74
|
return recortarMedio(corta, max);
|
|
71
75
|
}
|
|
76
|
+
let lineaDeVersiones = null;
|
|
77
|
+
function novedadParaLaPantalla() {
|
|
78
|
+
if (lineaDeVersiones)
|
|
79
|
+
return lineaDeVersiones;
|
|
80
|
+
if (!autoactualizarApagada())
|
|
81
|
+
return undefined;
|
|
82
|
+
const nueva = versionNuevaConocida();
|
|
83
|
+
return nueva ? t('update.disponible', { version: nueva }) : undefined;
|
|
84
|
+
}
|
|
72
85
|
function cabeceraCorta(lineas = []) {
|
|
73
86
|
process.stdout.write(`\n ${c.violeta(signo())} ${c.negrita('parx')} ${c.gris(VERSION)}\n`);
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
lineas = [c.gris(
|
|
87
|
+
const novedad = novedadParaLaPantalla();
|
|
88
|
+
if (novedad)
|
|
89
|
+
lineas = [c.gris(novedad), ...lineas];
|
|
77
90
|
for (const l of lineas)
|
|
78
91
|
process.stdout.write(` ${l}\n`);
|
|
79
92
|
process.stdout.write('\n');
|
|
80
93
|
}
|
|
94
|
+
async function mantenerAlDia(registro) {
|
|
95
|
+
try {
|
|
96
|
+
const nueva = await comprobarDeFondo();
|
|
97
|
+
if (!nueva || autoactualizarApagada() || !gestorPermiteAutoactualizar(ordenDeActualizar(rutaDelCli()).gestor))
|
|
98
|
+
return;
|
|
99
|
+
const r = await prepararVersion(nueva);
|
|
100
|
+
if (!r.ok)
|
|
101
|
+
registro?.apuntar('actualizacion', { version: nueva, motivo: r.motivo });
|
|
102
|
+
else if (!r.yaEstaba)
|
|
103
|
+
registro?.apuntar('actualizacion', { version: nueva, preparada: true });
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
}
|
|
107
|
+
}
|
|
81
108
|
export function nombreDeModo(m) {
|
|
82
109
|
return t(`modo.${m}`);
|
|
83
110
|
}
|
|
@@ -92,7 +119,7 @@ export function modosEnColor() {
|
|
|
92
119
|
return `${nombres.slice(0, 3).join(', ')} or ${nombres[3]}`;
|
|
93
120
|
}
|
|
94
121
|
function ayudaDeComandos() {
|
|
95
|
-
return bloqueDeTabla([['!', t('tip.bash')], ...COMANDOS.map(([k, d]) => [`/${k}`, k === 'mode' ? modosEnColor() : d])], { pie: `${t('tui.atajos')}\n${t('tui.atajos_raton')}` });
|
|
122
|
+
return bloqueDeTabla([['!', t('tip.bash')], ...COMANDOS.map(([k, d]) => [`/${k}`, k === 'mode' ? modosEnColor() : d])], { pie: `${t('tui.atajos')}\n${t('tui.atajos_arroba')}\n${t('tui.atajos_raton')}` });
|
|
96
123
|
}
|
|
97
124
|
async function cuentaOError(cred, pantalla) {
|
|
98
125
|
try {
|
|
@@ -113,7 +140,7 @@ async function actualizar() {
|
|
|
113
140
|
process.stdout.write(`${t('update.npx')}\n`);
|
|
114
141
|
return 0;
|
|
115
142
|
}
|
|
116
|
-
if (gestor === 'desarrollo'
|
|
143
|
+
if (gestor === 'desarrollo') {
|
|
117
144
|
process.stdout.write(`${t('update.desarrollo')}\n`);
|
|
118
145
|
return 0;
|
|
119
146
|
}
|
|
@@ -126,14 +153,13 @@ async function actualizar() {
|
|
|
126
153
|
process.stdout.write(`${t('update.al_dia', { version: VERSION })}\n`);
|
|
127
154
|
return 0;
|
|
128
155
|
}
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
process.stderr.write(`${c.error('✗')} ${t('update.fallo', { orden: texto })}\n`);
|
|
156
|
+
const aMano = (orden ?? ['npm', 'install', '-g', '@getparallel/parx@latest']).map((p) => (/\s/.test(p) ? `"${p}"` : p)).join(' ');
|
|
157
|
+
const r = await prepararVersion(ultima);
|
|
158
|
+
if (!r.ok) {
|
|
159
|
+
process.stderr.write(`${c.error('✗')} ${t(r.motivo === 'firma' ? 'update.firma' : 'update.no_se_pudo', { version: ultima, orden: aMano })}\n`);
|
|
134
160
|
return 1;
|
|
135
161
|
}
|
|
136
|
-
process.stdout.write(`${c.violeta('✓')} ${t('update.
|
|
162
|
+
process.stdout.write(`${c.violeta('✓')} ${t(r.yaEstaba ? 'update.ya_preparada' : 'update.preparada', { version: ultima })}${r.novedad ? c.gris(`${sep()}${r.novedad}`) : ''}\n`);
|
|
137
163
|
return 0;
|
|
138
164
|
}
|
|
139
165
|
async function principal() {
|
|
@@ -151,6 +177,9 @@ async function principal() {
|
|
|
151
177
|
process.stdout.write(`parx ${VERSION}\n`);
|
|
152
178
|
return 0;
|
|
153
179
|
}
|
|
180
|
+
const estreno = confirmarArranque();
|
|
181
|
+
if (estreno)
|
|
182
|
+
lineaDeVersiones = estreno.novedad ? t('update.actualizado_con', { version: estreno.version, novedad: estreno.novedad }) : t('update.actualizado', { version: estreno.version });
|
|
154
183
|
if (v.help) {
|
|
155
184
|
cabeceraCorta();
|
|
156
185
|
process.stdout.write(`${USO}\n`);
|
|
@@ -161,7 +190,7 @@ async function principal() {
|
|
|
161
190
|
const solo = positionals.length === 1 && !v.lanes;
|
|
162
191
|
if (solo && ['update', 'upgrade'].includes(primero))
|
|
163
192
|
return actualizar();
|
|
164
|
-
void
|
|
193
|
+
void mantenerAlDia();
|
|
165
194
|
if (solo && ['login', 'entrar', 'switch'].includes(primero)) {
|
|
166
195
|
cabeceraCorta();
|
|
167
196
|
await entrar((l) => pantalla.escribir(l), { forma: formaPedida(v) });
|
|
@@ -241,6 +270,8 @@ async function principal() {
|
|
|
241
270
|
lecturas: [],
|
|
242
271
|
jaula: Boolean(v.sandbox),
|
|
243
272
|
});
|
|
273
|
+
if (cuenta.tarifa)
|
|
274
|
+
sesion.tarifas = cuenta.tarifa;
|
|
244
275
|
for (const f of v['add-folder'] ?? []) {
|
|
245
276
|
const ok = permitirCarpeta(sesion.ctx, f);
|
|
246
277
|
if (!ok)
|
|
@@ -269,6 +300,8 @@ async function principal() {
|
|
|
269
300
|
let control = new AbortController();
|
|
270
301
|
let ocupado = false;
|
|
271
302
|
let superficie = null;
|
|
303
|
+
let remoto = null;
|
|
304
|
+
let deFueraPendientes = 0;
|
|
272
305
|
let bienvenida;
|
|
273
306
|
let consejosDeEntrada = [];
|
|
274
307
|
const confirmarNuevaEnMarcha = async () => {
|
|
@@ -282,15 +315,7 @@ async function principal() {
|
|
|
282
315
|
control.abort();
|
|
283
316
|
};
|
|
284
317
|
const empezarDeNuevo = () => {
|
|
285
|
-
sesion
|
|
286
|
-
sesion.diario = [];
|
|
287
|
-
sesion.id = randomUUID();
|
|
288
|
-
sesion.ultimaTarea = undefined;
|
|
289
|
-
sesion.ctx.hechos = { ficheros: [], comandos: [] };
|
|
290
|
-
sesion.ctx.permitidos.clear();
|
|
291
|
-
sesion.ctx.deshacer.length = 0;
|
|
292
|
-
if (sesion.ctx.lecturas)
|
|
293
|
-
sesion.ctx.lecturas.length = 0;
|
|
318
|
+
reiniciarConversacion(sesion);
|
|
294
319
|
registro.apuntar('nueva', {});
|
|
295
320
|
pantalla.reiniciar();
|
|
296
321
|
if (superficie)
|
|
@@ -306,6 +331,14 @@ async function principal() {
|
|
|
306
331
|
superficie.terminar(despedida());
|
|
307
332
|
else
|
|
308
333
|
pantalla.escribir(despedida());
|
|
334
|
+
if (remoto?.encendido) {
|
|
335
|
+
const salida = setTimeout(() => process.exit(0), 1500);
|
|
336
|
+
void remoto.cerrar().finally(() => {
|
|
337
|
+
clearTimeout(salida);
|
|
338
|
+
process.exit(0);
|
|
339
|
+
});
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
309
342
|
process.exit(0);
|
|
310
343
|
};
|
|
311
344
|
const alCtrlC = () => {
|
|
@@ -347,6 +380,13 @@ async function principal() {
|
|
|
347
380
|
superficie?.trabajar(() => control.abort());
|
|
348
381
|
const inicio = Date.now();
|
|
349
382
|
let seguir = true;
|
|
383
|
+
if (remoto?.encendido) {
|
|
384
|
+
remoto.fijarModo(nombreDeModo(sesion.ctx.modo), nombreDeModelo(sesion.modelo));
|
|
385
|
+
remoto.evento('tu', { texto: texto.replace(/^\u2060/, ''), desde: deFueraPendientes > 0 ? 'movil' : 'ordenador' });
|
|
386
|
+
if (deFueraPendientes > 0)
|
|
387
|
+
deFueraPendientes--;
|
|
388
|
+
remoto.fijarEstado('trabajando', texto.replace(/^\u2060/, ''));
|
|
389
|
+
}
|
|
350
390
|
try {
|
|
351
391
|
seguir = await hacerTarea(sesion, texto, control.signal, imagenes);
|
|
352
392
|
if (sesion.disponibles !== undefined && sesion.disponibles !== null)
|
|
@@ -355,10 +395,93 @@ async function principal() {
|
|
|
355
395
|
finally {
|
|
356
396
|
ocupado = false;
|
|
357
397
|
superficie?.descansar();
|
|
398
|
+
remoto?.fijarEstado('libre', null);
|
|
358
399
|
}
|
|
359
400
|
quizaAvisar(t('aviso.termino', { tarea: texto.replace(/\s+/g, ' ').slice(0, 80) }), Date.now() - inicio);
|
|
360
401
|
return seguir;
|
|
361
402
|
};
|
|
403
|
+
const encenderRemoto = async (enseñarQR = true) => {
|
|
404
|
+
if (!superficie) {
|
|
405
|
+
pantalla.escribir(t('remoto.solo_interactiva'));
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
if (remoto?.encendido && remoto.url) {
|
|
409
|
+
const url = remoto.url;
|
|
410
|
+
soloAqui(() => enseñarEnlace(url, enseñarQR));
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
const nuevo = new Remoto({
|
|
414
|
+
servidor: cred.servidor,
|
|
415
|
+
token: cred.token,
|
|
416
|
+
alMensaje: (texto) => {
|
|
417
|
+
soloAqui(() => pantalla.escribir(c.gris(`${t('remoto.del_movil')}:`)));
|
|
418
|
+
deFueraPendientes++;
|
|
419
|
+
superficie?.mandarDesdeFuera(texto);
|
|
420
|
+
},
|
|
421
|
+
alParar: () => {
|
|
422
|
+
if (!ocupado)
|
|
423
|
+
return;
|
|
424
|
+
control.abort();
|
|
425
|
+
pantalla.aviso(t('remoto.parado'));
|
|
426
|
+
},
|
|
427
|
+
alApagarse: (motivo) => {
|
|
428
|
+
pantalla.espejo = null;
|
|
429
|
+
remoto = null;
|
|
430
|
+
pantalla.aviso(motivo === 'web' ? t('remoto.cortado_web') : motivo === 'sesion' ? t('remoto.sesion') : t('remoto.no_disponible'));
|
|
431
|
+
superficie?.pintar();
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
try {
|
|
435
|
+
const r = await nuevo.abrir({ equipo: equipo().equipo, version: equipo().version, carpeta: basename(raiz), modelo: nombreDeModelo(sesion.modelo), modo: nombreDeModo(sesion.ctx.modo) });
|
|
436
|
+
remoto = nuevo;
|
|
437
|
+
registro.apuntar('remoto', { encendido: true });
|
|
438
|
+
enseñarEnlace(r.url, enseñarQR);
|
|
439
|
+
pantalla.espejo = nuevo;
|
|
440
|
+
}
|
|
441
|
+
catch (e) {
|
|
442
|
+
if (e instanceof ErrorDeParallel) {
|
|
443
|
+
if (e.codigo === 'sin_acceso')
|
|
444
|
+
pantalla.error(t('remoto.no_disponible'));
|
|
445
|
+
else if (e.codigo === 'sesion')
|
|
446
|
+
pantalla.error(t('remoto.sesion'));
|
|
447
|
+
else if (e.detalle.includes('demasiados'))
|
|
448
|
+
pantalla.error(t('remoto.demasiados'));
|
|
449
|
+
else
|
|
450
|
+
pantalla.error(t('remoto.sin_red', { motivo: e.codigo === 'red' ? 'no connection' : e.detalle || e.codigo }));
|
|
451
|
+
}
|
|
452
|
+
else
|
|
453
|
+
throw e;
|
|
454
|
+
}
|
|
455
|
+
superficie?.pintar();
|
|
456
|
+
};
|
|
457
|
+
const soloAqui = (f) => {
|
|
458
|
+
const e = pantalla.espejo;
|
|
459
|
+
pantalla.espejo = null;
|
|
460
|
+
try {
|
|
461
|
+
f();
|
|
462
|
+
}
|
|
463
|
+
finally {
|
|
464
|
+
pantalla.espejo = e;
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
const enseñarEnlace = (url, conQR) => {
|
|
468
|
+
pantalla.escribir(t('remoto.on', { url: c.marca(url) }));
|
|
469
|
+
pantalla.escribir(c.gris(t('remoto.detalle')));
|
|
470
|
+
const caps = capacidades();
|
|
471
|
+
const qr = conQR ? qrEnTexto(url, { color: caps.color > 0, unicode: caps.unicode }) : null;
|
|
472
|
+
if (qr && caps.ancho >= sinColor(qr[0]).length + 4) {
|
|
473
|
+
pantalla.escribir(c.gris(t('remoto.escanea')));
|
|
474
|
+
pantalla.bloque(() => ['', ...qr.map((l) => ` ${l}`), '']);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
const apagarRemoto = async () => {
|
|
478
|
+
const r = remoto;
|
|
479
|
+
remoto = null;
|
|
480
|
+
pantalla.espejo = null;
|
|
481
|
+
if (r)
|
|
482
|
+
await r.cerrar();
|
|
483
|
+
registro.apuntar('remoto', { encendido: false });
|
|
484
|
+
};
|
|
362
485
|
const carriles = async (tareas) => {
|
|
363
486
|
if (tareas.length < 2) {
|
|
364
487
|
pantalla.escribir(t('carriles.min'));
|
|
@@ -433,6 +556,25 @@ async function principal() {
|
|
|
433
556
|
extra: sesion.ensenar ? 'Teach' : undefined,
|
|
434
557
|
esperando: esperandoEnBandeja ?? 0,
|
|
435
558
|
});
|
|
559
|
+
let conexionesAl = 0;
|
|
560
|
+
let conexionesViejas = true;
|
|
561
|
+
let sinConexiones = false;
|
|
562
|
+
const cargarConexiones = async () => {
|
|
563
|
+
if (sinConexiones)
|
|
564
|
+
return;
|
|
565
|
+
conexionesAl = Date.now();
|
|
566
|
+
conexionesViejas = false;
|
|
567
|
+
try {
|
|
568
|
+
const r = await leerConexiones(cred.servidor, cred.token);
|
|
569
|
+
superficie?.fijarConexiones(r.conexiones);
|
|
570
|
+
}
|
|
571
|
+
catch (e) {
|
|
572
|
+
if (e instanceof ErrorDeParallel && (e.codigo === 'sin_acceso' || e.codigo === 'sesion'))
|
|
573
|
+
sinConexiones = true;
|
|
574
|
+
else
|
|
575
|
+
conexionesViejas = true;
|
|
576
|
+
}
|
|
577
|
+
};
|
|
436
578
|
if (interactiva) {
|
|
437
579
|
superficie = new Superficie({
|
|
438
580
|
entrada: process.stdin,
|
|
@@ -452,6 +594,17 @@ async function principal() {
|
|
|
452
594
|
avisarEnElEscritorio({ titulo: 'parx', texto: t('aviso.te_necesita', { pregunta: texto }) });
|
|
453
595
|
},
|
|
454
596
|
alNuevaEnMarcha: () => void confirmarNuevaEnMarcha(),
|
|
597
|
+
alArroba: () => {
|
|
598
|
+
if (conexionesViejas || Date.now() - conexionesAl > 60_000)
|
|
599
|
+
void cargarConexiones();
|
|
600
|
+
},
|
|
601
|
+
alConectar: (x) => {
|
|
602
|
+
abrirNavegador(x.url);
|
|
603
|
+
registro.apuntar('conectar', { provider: x.provider });
|
|
604
|
+
pantalla.escribir(t('arroba.abriendo', { nombre: x.nombre, url: c.marca(x.url) }));
|
|
605
|
+
pantalla.escribir(c.gris(t('arroba.despues')));
|
|
606
|
+
conexionesViejas = true;
|
|
607
|
+
},
|
|
455
608
|
});
|
|
456
609
|
const s = superficie;
|
|
457
610
|
process.on('exit', () => s.restaurarDeUrgencia());
|
|
@@ -476,15 +629,14 @@ async function principal() {
|
|
|
476
629
|
quien: quien.includes('@') ? quien : (quien.split(/\s+/)[0] ?? ''),
|
|
477
630
|
carpeta: rutaCorta(raiz, 60),
|
|
478
631
|
plan: cuenta.plan,
|
|
479
|
-
novedad: (
|
|
480
|
-
const nueva = versionNuevaConocida();
|
|
481
|
-
return nueva ? t('update.disponible', { version: nueva }) : undefined;
|
|
482
|
-
})(),
|
|
632
|
+
novedad: novedadParaLaPantalla(),
|
|
483
633
|
peligro: () => sesion.ctx.modo === 'bypass',
|
|
484
634
|
});
|
|
485
635
|
superficie.iniciar(bienvenida, consejosDeEntrada);
|
|
486
636
|
if (quiereBypass)
|
|
487
637
|
await confirmarBypass();
|
|
638
|
+
if (v.remote || ajustes.remoto)
|
|
639
|
+
void encenderRemoto(Boolean(v.remote));
|
|
488
640
|
const mirarBandeja = async () => {
|
|
489
641
|
if (ocupado)
|
|
490
642
|
return;
|
|
@@ -504,6 +656,12 @@ async function principal() {
|
|
|
504
656
|
const relojBandeja = setInterval(() => void mirarBandeja(), 90_000);
|
|
505
657
|
relojBandeja.unref();
|
|
506
658
|
void mirarBandeja();
|
|
659
|
+
void cargarConexiones();
|
|
660
|
+
const relojVersiones = setInterval(() => {
|
|
661
|
+
if (!ocupado)
|
|
662
|
+
void mantenerAlDia(registro);
|
|
663
|
+
}, ENTRE_COMPROBACIONES_MS);
|
|
664
|
+
relojVersiones.unref();
|
|
507
665
|
}
|
|
508
666
|
const leerLinea = async (ejemplo = null) => {
|
|
509
667
|
if (superficie)
|
|
@@ -640,6 +798,147 @@ async function principal() {
|
|
|
640
798
|
elegida = Math.min(elegida, lista.length - 1);
|
|
641
799
|
}
|
|
642
800
|
};
|
|
801
|
+
const pedir = async (texto, fn, errores = {}) => {
|
|
802
|
+
ocupado = true;
|
|
803
|
+
control = new AbortController();
|
|
804
|
+
superficie?.trabajar(() => control.abort());
|
|
805
|
+
pantalla.espera(texto, 'ruta', true);
|
|
806
|
+
try {
|
|
807
|
+
return await fn(control.signal);
|
|
808
|
+
}
|
|
809
|
+
catch (e) {
|
|
810
|
+
if (!(e instanceof ErrorDeParallel))
|
|
811
|
+
throw e;
|
|
812
|
+
const clave = errores[e.codigo === 'servidor' ? e.detalle.slice(0, 3) : e.codigo];
|
|
813
|
+
if (clave)
|
|
814
|
+
pantalla.aviso(t(clave));
|
|
815
|
+
else if (e.codigo !== 'interrumpido')
|
|
816
|
+
pantalla.error(mensajeDeError(e));
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
finally {
|
|
820
|
+
pantalla.pararEspera();
|
|
821
|
+
ocupado = false;
|
|
822
|
+
superficie?.descansar();
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
const notaDeMision = (m) => [t('misiones.progreso', { estado: m.texto || m.estado, n: m.progreso }), m.pendientes ? t('misiones.esperan', { n: m.pendientes }) : ''].filter(Boolean).join(sep());
|
|
826
|
+
const erroresDeMision = { sin_acceso: 'misiones.no_existe', '409': 'misiones.no_se_puede', '429': 'misiones.despacio' };
|
|
827
|
+
const unaMision = async (inicial) => {
|
|
828
|
+
let m = inicial;
|
|
829
|
+
let elegida = 0;
|
|
830
|
+
for (;;) {
|
|
831
|
+
const acciones = accionesDeUnaMision(m.estado);
|
|
832
|
+
const j = await superficie.elegir(m.titulo, [...acciones.map((a) => ({ etiqueta: a.etiqueta, nota: a.nota })), { etiqueta: t('misiones.volver') }], {
|
|
833
|
+
vertical: true,
|
|
834
|
+
detalle: notaDeMision(m),
|
|
835
|
+
elegida,
|
|
836
|
+
});
|
|
837
|
+
if (j === null)
|
|
838
|
+
return 'salir';
|
|
839
|
+
if (j >= acciones.length)
|
|
840
|
+
return 'volver';
|
|
841
|
+
elegida = j;
|
|
842
|
+
const a = acciones[j];
|
|
843
|
+
registro.apuntar('mision_accion', { accion: a.slug });
|
|
844
|
+
if (a.id === 'abrir') {
|
|
845
|
+
abrirNavegador(m.url);
|
|
846
|
+
pantalla.escribir(t('misiones.abierta', { url: c.marca(m.url) }));
|
|
847
|
+
}
|
|
848
|
+
else if (a.id === 'pausar' || a.id === 'reanudar') {
|
|
849
|
+
const accion = a.id;
|
|
850
|
+
const r = await pedir(t('misiones.mirando'), (s) => cicloDeMision(cred.servidor, cred.token, m.id, accion, s), erroresDeMision);
|
|
851
|
+
if (r) {
|
|
852
|
+
pantalla.escribir(`${c.ok(SIMBOLOS.hecho)} ${t(accion === 'pausar' ? 'misiones.pausada' : 'misiones.reanudada', { titulo: m.titulo })}`);
|
|
853
|
+
const otra = await leerMisiones(cred.servidor, cred.token).catch(() => null);
|
|
854
|
+
m = otra?.misiones.find((x) => x.id === m.id) ?? { ...m, estado: r.estado };
|
|
855
|
+
elegida = 0;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
else if (a.id === 'compartir') {
|
|
859
|
+
const r = await pedir(t('misiones.mirando'), (s) => compartirMision(cred.servidor, cred.token, m.id, s), { ...erroresDeMision, '503': 'misiones.sin_compartir' });
|
|
860
|
+
if (r)
|
|
861
|
+
pantalla.escribir(t(copiarAlPortapapeles(r.url) ? 'misiones.compartida' : 'misiones.compartida_sin_copiar', { url: c.marca(r.url) }));
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
const r = await pedir(t('misiones.mirando'), (s) => leerMisionDeLaCuenta(cred.servidor, cred.token, m.id, s), erroresDeMision);
|
|
865
|
+
if (!r)
|
|
866
|
+
continue;
|
|
867
|
+
const d = r.mision;
|
|
868
|
+
const titulo = `${a.id === 'resultado' ? t('misiones.resultado') : t('misiones.actividad')}${sep()}${d.titulo}`;
|
|
869
|
+
if (a.id === 'resultado') {
|
|
870
|
+
const filas = [
|
|
871
|
+
[t('misiones.meta'), d.objetivo ? t('misiones.objetivo', { etiqueta: d.objetivo.etiqueta, valor: d.objetivo.valor.toLocaleString('en-US'), meta: d.objetivo.meta.toLocaleString('en-US') }) : t('misiones.sin_objetivo')],
|
|
872
|
+
[t('misiones.el_plan'), t('misiones.plan', { estado: d.texto || d.estado, n: d.progreso })],
|
|
873
|
+
];
|
|
874
|
+
pantalla.bloque(bloqueDeTabla(filas, { titulo, pie: t('misiones.ver_resultados', { url: d.resultados }), sangria: 2 }));
|
|
875
|
+
}
|
|
876
|
+
else {
|
|
877
|
+
pantalla.bloque(bloqueDeTabla(d.actividad.map((x) => [hace(x.cuando), x.texto]), { titulo, pie: d.actividad.length ? t('misiones.ver_actividad', { url: d.url }) : t('misiones.sin_actividad'), sangria: 2 }));
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
const misiones = async (filtro) => {
|
|
883
|
+
const leer = () => pedir(t('misiones.mirando'), (s) => leerMisiones(cred.servidor, cred.token, s), { sin_acceso: 'misiones.no_disponible', '429': 'misiones.despacio' });
|
|
884
|
+
let r = await leer();
|
|
885
|
+
if (!r)
|
|
886
|
+
return;
|
|
887
|
+
if (!r.misiones.length) {
|
|
888
|
+
pantalla.escribir(t('misiones.nada'));
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
let lista = filtrarPorTitulo(r.misiones, filtro);
|
|
892
|
+
if (!lista.length) {
|
|
893
|
+
pantalla.escribir(t('misiones.sin_coincidencias', { q: filtro }));
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
if (!superficie) {
|
|
897
|
+
for (const m of lista)
|
|
898
|
+
pantalla.escribir(`${m.titulo}${c.gris(`${sep()}${notaDeMision(m)}`)} ${c.gris(m.url)}`);
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
let elegida = 0;
|
|
902
|
+
for (;;) {
|
|
903
|
+
const i = await superficie.elegir(t('misiones.titulo'), lista.map((m) => ({ etiqueta: m.titulo, nota: notaDeMision(m) })), { vertical: true, elegida });
|
|
904
|
+
if (i === null)
|
|
905
|
+
return;
|
|
906
|
+
elegida = i;
|
|
907
|
+
if ((await unaMision(lista[i])) === 'salir')
|
|
908
|
+
return;
|
|
909
|
+
r = await leer();
|
|
910
|
+
if (!r)
|
|
911
|
+
return;
|
|
912
|
+
lista = filtrarPorTitulo(r.misiones, filtro);
|
|
913
|
+
if (!lista.length)
|
|
914
|
+
return;
|
|
915
|
+
elegida = Math.min(elegida, lista.length - 1);
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
const plantillas = async (filtro) => {
|
|
919
|
+
const r = await pedir(t('plantillas.mirando'), (s) => leerPlantillas(cred.servidor, cred.token, s), { sin_acceso: 'misiones.no_disponible', '429': 'misiones.despacio' });
|
|
920
|
+
if (!r)
|
|
921
|
+
return;
|
|
922
|
+
if (!r.plantillas.length) {
|
|
923
|
+
pantalla.escribir(t('plantillas.nada'));
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
const lista = filtrarPorTitulo(r.plantillas, filtro);
|
|
927
|
+
if (!lista.length) {
|
|
928
|
+
pantalla.escribir(t('plantillas.sin_coincidencias', { q: filtro }));
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
if (!superficie) {
|
|
932
|
+
for (const p of lista)
|
|
933
|
+
pantalla.escribir(`${p.titulo}${p.resumen ? c.gris(`${sep()}${p.resumen}`) : ''}`);
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
const i = await superficie.elegir(t('plantillas.titulo'), lista.map((p) => ({ etiqueta: p.titulo, nota: p.propia ? t('plantillas.propia') : p.resumen })), { vertical: true });
|
|
937
|
+
if (i === null)
|
|
938
|
+
return;
|
|
939
|
+
superficie.ponerEnLaCaja(`/mission ${lista[i].objetivo.replace(/\s+/g, ' ').trim()}`);
|
|
940
|
+
pantalla.escribir(c.gris(t('plantillas.lista')));
|
|
941
|
+
};
|
|
643
942
|
const bash = async (comando) => {
|
|
644
943
|
if (!comando)
|
|
645
944
|
return;
|
|
@@ -846,6 +1145,23 @@ async function principal() {
|
|
|
846
1145
|
await bandeja();
|
|
847
1146
|
superficie?.pintar();
|
|
848
1147
|
break;
|
|
1148
|
+
case 'missions':
|
|
1149
|
+
await misiones(resto);
|
|
1150
|
+
superficie?.pintar();
|
|
1151
|
+
break;
|
|
1152
|
+
case 'templates':
|
|
1153
|
+
await plantillas(resto);
|
|
1154
|
+
superficie?.pintar();
|
|
1155
|
+
break;
|
|
1156
|
+
case 'connections':
|
|
1157
|
+
case 'settings': {
|
|
1158
|
+
const url = `${cred.servidor.replace(/\/$/, '')}/${cmd}`;
|
|
1159
|
+
abrirNavegador(url);
|
|
1160
|
+
if (cmd === 'connections')
|
|
1161
|
+
conexionesViejas = true;
|
|
1162
|
+
pantalla.escribir(t('ir.abriendo', { que: t(cmd === 'connections' ? 'ir.conexiones' : 'ir.ajustes'), url: c.marca(url) }));
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
849
1165
|
case 'mouse': {
|
|
850
1166
|
const si = ALIAS_SI_NO[arg] ?? (superficie?.conRaton ? 'no' : 'si');
|
|
851
1167
|
guardarAjustes({ raton: si === 'si' });
|
|
@@ -863,6 +1179,33 @@ async function principal() {
|
|
|
863
1179
|
pantalla.escribir(pantalla.animar ? t('animacion.on') : t('animacion.off'));
|
|
864
1180
|
break;
|
|
865
1181
|
}
|
|
1182
|
+
case 'remote': {
|
|
1183
|
+
if (arg === 'off' || ALIAS_SI_NO[arg] === 'no' || arg === 'never') {
|
|
1184
|
+
await apagarRemoto();
|
|
1185
|
+
if (leerAjustes().remoto)
|
|
1186
|
+
guardarAjustes({ remoto: false });
|
|
1187
|
+
pantalla.escribir(t('remoto.off'));
|
|
1188
|
+
superficie?.pintar();
|
|
1189
|
+
break;
|
|
1190
|
+
}
|
|
1191
|
+
if (arg === 'always' || arg === 'siempre') {
|
|
1192
|
+
guardarAjustes({ remoto: true });
|
|
1193
|
+
await encenderRemoto(true);
|
|
1194
|
+
pantalla.escribir(c.gris(t('remoto.siempre')));
|
|
1195
|
+
break;
|
|
1196
|
+
}
|
|
1197
|
+
await encenderRemoto(true);
|
|
1198
|
+
break;
|
|
1199
|
+
}
|
|
1200
|
+
case 'autoupdate': {
|
|
1201
|
+
const si = ALIAS_SI_NO[arg] ?? (autoactualizarApagada() ? 'si' : 'no');
|
|
1202
|
+
guardarAjustes({ autoactualizar: si === 'si' });
|
|
1203
|
+
registro.apuntar('autoactualizar', { encendido: si === 'si' });
|
|
1204
|
+
pantalla.escribir(si === 'si' ? t('autoupdate.on') : t('autoupdate.off'));
|
|
1205
|
+
if (si === 'si')
|
|
1206
|
+
void mantenerAlDia(registro);
|
|
1207
|
+
break;
|
|
1208
|
+
}
|
|
866
1209
|
case 'undo': {
|
|
867
1210
|
const r2 = deshacerUltimo(sesion.ctx);
|
|
868
1211
|
pantalla.escribir(r2 ? t('repl.deshecho', { ruta: r2 }) : t('repl.nada_que_deshacer'));
|
|
@@ -922,10 +1265,16 @@ async function principal() {
|
|
|
922
1265
|
return 0;
|
|
923
1266
|
}
|
|
924
1267
|
if (!process.env.PARX_PRUEBAS) {
|
|
925
|
-
|
|
926
|
-
if (
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1268
|
+
lanzarLaMasNueva().then((lanzamiento) => {
|
|
1269
|
+
if (lanzamiento.lanzada)
|
|
1270
|
+
return;
|
|
1271
|
+
if (lanzamiento.retirada)
|
|
1272
|
+
lineaDeVersiones = t('update.no_arranco', { version: lanzamiento.retirada, actual: VERSION });
|
|
1273
|
+
principal().then((codigo) => process.exit(codigo), (e) => {
|
|
1274
|
+
if (e instanceof ErrorDeParallel && e.codigo === 'interrumpido')
|
|
1275
|
+
process.exit(130);
|
|
1276
|
+
process.stderr.write(`${c.error('✗')} ${e instanceof ErrorDeParallel ? mensajeDeError(e) : e instanceof Error ? e.message : String(e)}\n`);
|
|
1277
|
+
process.exit(1);
|
|
1278
|
+
});
|
|
930
1279
|
});
|
|
931
1280
|
}
|
package/dist/comandos.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export const DE_LA_WEB = {
|
|
2
|
+
plantillas: { slug: 'templates', parx: 'templates', como: 'nuevo', porque: 'Pick one and it is written as /mission <goal> in the input, to review and send.' },
|
|
3
|
+
adjuntar: { slug: 'attach', parx: null, como: 'no', porque: 'parx already reads the files of your project; images go in by dragging them into the window.' },
|
|
4
|
+
fuerza: { slug: 'strength', parx: 'model', como: 'alias', porque: 'In parx the strength is the model: Swift, Stride or Summit.' },
|
|
5
|
+
dictar: { slug: 'dictate', parx: null, como: 'no', porque: 'A terminal has no microphone of its own; the dictation of your system still types into it.' },
|
|
6
|
+
nueva: { slug: 'new', parx: 'new', como: 'choque', porque: 'parx keeps /new as a new conversation; a new mission is /mission.' },
|
|
7
|
+
misiones: { slug: 'missions', parx: 'missions', como: 'nuevo', porque: 'Your missions; pick one to open, pause or resume, share, see its result or its activity.' },
|
|
8
|
+
conexiones: { slug: 'connections', parx: 'connections', como: 'nuevo', porque: 'Opens your connections on getparallel.net.' },
|
|
9
|
+
ajustes: { slug: 'settings', parx: 'settings', como: 'nuevo', porque: 'Opens your settings on getparallel.net.' },
|
|
10
|
+
abrir: { slug: 'open', parx: null, como: 'en_misiones', porque: 'Inside /missions.' },
|
|
11
|
+
pausar: { slug: 'pause', parx: null, como: 'en_misiones', porque: 'Inside /missions, only for a running mission.' },
|
|
12
|
+
reanudar: { slug: 'resume', parx: null, como: 'en_misiones', porque: 'Inside /missions, only for a paused mission.' },
|
|
13
|
+
compartir: { slug: 'share', parx: null, como: 'en_misiones', porque: 'Inside /missions.' },
|
|
14
|
+
resultado: { slug: 'result', parx: null, como: 'en_misiones', porque: 'Inside /missions.' },
|
|
15
|
+
actividad: { slug: 'activity', parx: null, como: 'en_misiones', porque: 'Inside /missions.' },
|
|
16
|
+
ayuda: { slug: 'help', parx: 'help', como: 'ya', porque: 'parx already had /help.' },
|
|
17
|
+
};
|
|
18
|
+
export const ACCIONES_DE_MISION = [
|
|
19
|
+
{ id: 'abrir', slug: 'open', etiqueta: 'Open', nota: 'In the browser' },
|
|
20
|
+
{ id: 'pausar', slug: 'pause', etiqueta: 'Pause', nota: 'Stop the agents' },
|
|
21
|
+
{ id: 'reanudar', slug: 'resume', etiqueta: 'Resume', nota: 'Pick up where it was' },
|
|
22
|
+
{ id: 'compartir', slug: 'share', etiqueta: 'Share', nota: 'Read-only link, copied' },
|
|
23
|
+
{ id: 'resultado', slug: 'result', etiqueta: 'Result', nota: 'How the goal is going' },
|
|
24
|
+
{ id: 'actividad', slug: 'activity', etiqueta: 'Activity', nota: 'What the agents did' },
|
|
25
|
+
];
|
|
26
|
+
export function accionDeMisionPosible(id, estado) {
|
|
27
|
+
if (id === 'pausar')
|
|
28
|
+
return estado === 'active' || estado === 'at_risk';
|
|
29
|
+
if (id === 'reanudar')
|
|
30
|
+
return estado === 'paused';
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
export function accionesDeUnaMision(estado) {
|
|
34
|
+
return ACCIONES_DE_MISION.filter((a) => accionDeMisionPosible(a.id, estado));
|
|
35
|
+
}
|
|
36
|
+
export function normalizar(texto) {
|
|
37
|
+
return texto.normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCase();
|
|
38
|
+
}
|
|
39
|
+
export function filtrarPorTitulo(lista, consulta) {
|
|
40
|
+
const q = normalizar(consulta.trim());
|
|
41
|
+
if (!q)
|
|
42
|
+
return [...lista];
|
|
43
|
+
const puntuados = [];
|
|
44
|
+
lista.forEach((x, i) => {
|
|
45
|
+
const titulo = normalizar(x.titulo);
|
|
46
|
+
let p = -1;
|
|
47
|
+
if (titulo.startsWith(q))
|
|
48
|
+
p = 0;
|
|
49
|
+
else if (titulo.split(/[\s._-]+/).some((w) => w.startsWith(q)))
|
|
50
|
+
p = 1;
|
|
51
|
+
else if (titulo.includes(q))
|
|
52
|
+
p = 2;
|
|
53
|
+
if (p >= 0)
|
|
54
|
+
puntuados.push({ x, p, i });
|
|
55
|
+
});
|
|
56
|
+
return puntuados.sort((a, b) => a.p - b.p || a.i - b.i).map((v) => v.x);
|
|
57
|
+
}
|
|
58
|
+
export function hace(iso, ahora = Date.now()) {
|
|
59
|
+
const ms = ahora - new Date(iso).getTime();
|
|
60
|
+
if (!Number.isFinite(ms))
|
|
61
|
+
return '';
|
|
62
|
+
const min = Math.floor(ms / 60_000);
|
|
63
|
+
if (min < 1)
|
|
64
|
+
return 'just now';
|
|
65
|
+
if (min < 60)
|
|
66
|
+
return `${min}m ago`;
|
|
67
|
+
const h = Math.floor(min / 60);
|
|
68
|
+
if (h < 24)
|
|
69
|
+
return `${h}h ago`;
|
|
70
|
+
return `${Math.floor(h / 24)}d ago`;
|
|
71
|
+
}
|