@getparallel/parx 0.4.3 → 0.5.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.
@@ -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
+ }
package/dist/config.js CHANGED
@@ -92,6 +92,10 @@ export function leerAjustes(dir = carpetaDeConfiguracion()) {
92
92
  out.modo = MODO_VIEJO[a.modo];
93
93
  if (typeof a.avisos === 'boolean')
94
94
  out.avisos = a.avisos;
95
+ if (typeof a.raton === 'boolean')
96
+ out.raton = a.raton;
97
+ if (typeof a.animacion === 'boolean')
98
+ out.animacion = a.animacion;
95
99
  const k = a.consejos;
96
100
  if (k && typeof k === 'object') {
97
101
  const n = (x) => (typeof x === 'number' && Number.isFinite(x) && x >= 0 ? Math.floor(x) : 0);
package/dist/consejos.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { capacidades } from "./marca.js";
2
2
  import { t } from "./textos.js";
3
- export const CONSEJOS = ['menu', 'modo', 'una', 'bash', 'imagen', 'historial', 'pegar', 'deshacer', 'modelo', 'carriles', 'parar', 'cola', 'bandeja', 'raton', 'informe', 'mision', 'ensenar', 'saldo', 'cuenta', 'agents'];
3
+ export const CONSEJOS = ['menu', 'modo', 'una', 'bash', 'imagen', 'historial', 'pegar', 'deshacer', 'modelo', 'carriles', 'parar', 'cola', 'bandeja', 'raton', 'informe', 'mision', 'ensenar', 'saldo', 'cuenta', 'agents', 'arroba'];
4
4
  export function consejo(id) {
5
5
  const u = capacidades().unicode;
6
6
  const tecla = {
@@ -24,6 +24,7 @@ export function consejo(id) {
24
24
  bash: '!',
25
25
  bandeja: '/inbox',
26
26
  raton: 'Click',
27
+ arroba: '@',
27
28
  };
28
29
  return { tecla: tecla[id], texto: t(`tip.${id}`) };
29
30
  }
@@ -3,6 +3,7 @@ import { dirname, join, relative } from 'node:path';
3
3
  import { contarCambios, diffDeLineas } from "./diff.js";
4
4
  import { cuantos, t } from "./textos.js";
5
5
  import { c } from "./marca.js";
6
+ import { elipsis } from "./actividad.js";
6
7
  import { estaDentro, familiaDeComando, nivelDeComando, resolverRuta, rutaReal } from "./seguridad.js";
7
8
  import { ejecutarComando, recortar } from "./shell.js";
8
9
  const nulable = (tipo, descripcion) => ({ type: [tipo, 'null'], description: descripcion });
@@ -211,7 +212,15 @@ export function etiquetaDeComando(comando) {
211
212
  return t('hace.instalar');
212
213
  const primera = c1.split(/\s*(?:&&|\|\||;|\|)\s*/)[0] ?? c1;
213
214
  const corto = primera.split(/\s+/).filter((p) => !/^[A-Z_]+=/.test(p)).slice(0, 3).join(' ');
214
- return t('hace.ejecutar', { comando: corto.length > 28 ? `${corto.slice(0, 27)}…` : corto });
215
+ return t('hace.ejecutar', { comando: corto.length > 28 ? `${corto.slice(0, 27)}${elipsis()}` : corto });
216
+ }
217
+ export function rutaParaLaBarra(ruta) {
218
+ const r = ruta.trim().replace(/^\.\/(?=.)/, '') || '.';
219
+ if (r.length <= 30)
220
+ return r;
221
+ const partes = r.split(/[\\/]/).filter(Boolean);
222
+ const cola = partes.slice(-2).join('/');
223
+ return cola.length <= 30 ? `${elipsis()}/${cola}` : `${elipsis()}/${partes[partes.length - 1]}`;
215
224
  }
216
225
  export function etiquetaDeTanda(llamadas) {
217
226
  if (!llamadas.length)
@@ -225,7 +234,7 @@ export function etiquetaDeTanda(llamadas) {
225
234
  }
226
235
  });
227
236
  const nombres = llamadas.map((l) => l.name);
228
- const base = (p) => String(p ?? '.').split(/[\\/]/).filter(Boolean).pop() ?? '.';
237
+ const base = (p) => rutaParaLaBarra(String(p ?? '.'));
229
238
  const cmd = nombres.indexOf('run_command');
230
239
  if (cmd !== -1)
231
240
  return { texto: etiquetaDeComando(String(args[cmd].command ?? '')), anim: 'tren' };
@@ -244,9 +253,14 @@ export function etiquetaDeTanda(llamadas) {
244
253
  const b = nombres.indexOf('search');
245
254
  if (b !== -1) {
246
255
  const patron = String(args[b].pattern ?? '');
247
- return { texto: t('hace.buscar', { patron: patron.length > 24 ? `${patron.slice(0, 23)}…` : patron }), anim: 'lectura' };
256
+ if (!patron.trim())
257
+ return { texto: t('hace.buscar_ficheros'), anim: 'lectura' };
258
+ return { texto: t('hace.buscar', { patron: patron.length > 24 ? `${patron.slice(0, 23)}${elipsis()}` : patron }), anim: 'lectura' };
248
259
  }
249
- return { texto: t('hace.listar', { ruta: base(args[0].path ?? '.') }), anim: 'lectura' };
260
+ const l = nombres.indexOf('list_files');
261
+ if (l !== -1)
262
+ return { texto: t('hace.listar', { ruta: base(args[l].path ?? '.') }), anim: 'lectura' };
263
+ return { texto: t('hace.generico'), anim: 'ruta' };
250
264
  }
251
265
  export async function ejecutarHerramienta(nombre, argumentos, ctx) {
252
266
  let a;
@@ -0,0 +1,85 @@
1
+ export const LARGO_MAXIMO_CONSULTA = 30;
2
+ export function normalizar(texto) {
3
+ return texto.normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCase();
4
+ }
5
+ export function detectarArroba(texto, cursor) {
6
+ if (cursor < 1 || cursor > texto.length)
7
+ return null;
8
+ const antes = texto.slice(0, cursor);
9
+ const arroba = antes.lastIndexOf('@');
10
+ if (arroba < 0)
11
+ return null;
12
+ const previo = arroba === 0 ? '' : antes[arroba - 1];
13
+ if (previo !== '' && !/\s/.test(previo))
14
+ return null;
15
+ const consulta = antes.slice(arroba + 1);
16
+ if (consulta.length > LARGO_MAXIMO_CONSULTA)
17
+ return null;
18
+ if (/\n|\s\s|^\s/.test(consulta))
19
+ return null;
20
+ return { inicio: arroba, consulta };
21
+ }
22
+ export function mencionTerminada(consulta, conexiones) {
23
+ if (!/\s$/.test(consulta))
24
+ return false;
25
+ const q = normalizar(consulta.trim());
26
+ return conexiones.some((c) => normalizar(c.nombre) === q || normalizar(c.provider) === q);
27
+ }
28
+ export function filtrarConexiones(conexiones, consulta) {
29
+ return puntuar(conexiones, consulta)
30
+ .sort((a, b) => a.p - b.p || a.c.nombre.localeCompare(b.c.nombre))
31
+ .map((x) => x.c);
32
+ }
33
+ function puntuar(conexiones, consulta) {
34
+ const q = normalizar(consulta.trim());
35
+ const puntuados = [];
36
+ for (const c of conexiones) {
37
+ const nombre = normalizar(c.nombre);
38
+ const clave = normalizar(c.provider);
39
+ let p = -1;
40
+ if (!q || nombre.startsWith(q) || clave.startsWith(q))
41
+ p = 0;
42
+ else if (nombre.split(/[\s._-]+/).some((w) => w.startsWith(q)) || clave.split('_').some((w) => w.startsWith(q)))
43
+ p = 1;
44
+ else if (nombre.includes(q) || clave.includes(q))
45
+ p = 2;
46
+ if (p >= 0)
47
+ puntuados.push({ c, p });
48
+ }
49
+ return puntuados;
50
+ }
51
+ export function conexionesQueSalen(conexiones, consulta, max = 40) {
52
+ return puntuar(conexiones, consulta)
53
+ .sort((a, b) => a.p - b.p || Number(b.c.conectada) - Number(a.c.conectada) || a.c.nombre.localeCompare(b.c.nombre))
54
+ .slice(0, max)
55
+ .map((x) => x.c);
56
+ }
57
+ export function mencionEnLaCaja(unidades, cursor) {
58
+ if (unidades[0] === '!')
59
+ return null;
60
+ const antes = unidades.slice(0, Math.max(0, Math.min(cursor, unidades.length)));
61
+ let arroba = -1;
62
+ for (let i = antes.length - 1; i >= 0; i--) {
63
+ const u = antes[i];
64
+ if (u === '@') {
65
+ arroba = i;
66
+ break;
67
+ }
68
+ if (u.length !== 1 || antes.length - i > LARGO_MAXIMO_CONSULTA + 1)
69
+ return null;
70
+ }
71
+ if (arroba < 0)
72
+ return null;
73
+ const previo = arroba === 0 ? '' : antes[arroba - 1];
74
+ if (previo !== '' && (previo.length !== 1 || !/\s/.test(previo)))
75
+ return null;
76
+ const consulta = antes.slice(arroba + 1).join('');
77
+ return detectarArroba(`@${consulta}`, consulta.length + 1) ? { inicio: arroba, consulta } : null;
78
+ }
79
+ export function insertarMencion(unidades, inicio, cursor, nombre) {
80
+ const despues = unidades.slice(cursor);
81
+ const separador = despues[0] === ' ' ? [] : [' '];
82
+ const etiqueta = [...Array.from(`@${nombre}`), ...separador];
83
+ const nuevas = [...unidades.slice(0, inicio), ...etiqueta, ...despues];
84
+ return { unidades: nuevas, cursor: inicio + etiqueta.length + (separador.length ? 0 : 1) };
85
+ }
package/dist/textos.js CHANGED
@@ -19,8 +19,9 @@ export const TEXTOS = {
19
19
  'tui.si_ediciones': 'Yes, allow all edits',
20
20
  'tui.si_ediciones_corto': 'All edits',
21
21
  'tui.una_vez': 'Yes, this once',
22
- 'tui.atajos': 'Shift+Tab mode · ↑ ↓ history · ! runs a shell command · Esc stops a task · Ctrl+C twice exits · Ctrl+L redraws',
22
+ 'tui.atajos': 'Shift+Tab mode · ↑ ↓ history · ! runs a shell command · Esc stops a task · any key shows the whole answer · Ctrl+C twice exits · Ctrl+L redraws',
23
23
  'tui.atajos_raton': 'Click any option or button · wheel or PgUp/PgDn scrolls · End jumps to the bottom · Shift+drag selects text (Option in iTerm2, Fn in Terminal) · /mouse off gives the mouse back to the terminal',
24
+ 'tui.atajos_arroba': '@ names one of your Parallel apps · one that is not connected opens its Connect page',
24
25
  'tui.al_fondo': 'Jump to bottom',
25
26
  'tui.nuevas': '{n} new',
26
27
  'bash.ejemplo': 'A shell command, run in the project folder',
@@ -53,6 +54,46 @@ export const TEXTOS = {
53
54
  'bandeja.despacio': 'Too many answers at once. Try again in a minute.',
54
55
  'bandeja.no_disponible': 'Your missions are not reachable from parx yet.',
55
56
  'bandeja.abrir': 'Open in the browser: {url}',
57
+ 'arroba.conectada': 'Connected',
58
+ 'arroba.conectar': 'Connect',
59
+ 'arroba.abriendo': 'Connect {nombre} in your browser: {url}',
60
+ 'arroba.despues': 'Then type @ again: it shows up as connected.',
61
+ 'misiones.titulo': 'Pick a mission',
62
+ 'misiones.mirando': 'Looking at your missions',
63
+ 'misiones.nada': 'You have no missions yet. Start one with /mission <goal>.',
64
+ 'misiones.sin_coincidencias': 'No mission matches “{q}”.',
65
+ 'misiones.volver': 'Back',
66
+ 'misiones.progreso': '{estado} · {n}%',
67
+ 'misiones.esperan': '{n} waiting',
68
+ 'misiones.abierta': 'Opened in your browser: {url}',
69
+ 'misiones.pausada': '“{titulo}” paused',
70
+ 'misiones.reanudada': '“{titulo}” is running again',
71
+ 'misiones.no_se_puede': 'That mission cannot do that right now.',
72
+ 'misiones.no_existe': 'That mission no longer exists.',
73
+ 'misiones.compartida': 'Read-only link, copied to the clipboard: {url}',
74
+ 'misiones.compartida_sin_copiar': 'Read-only link: {url}',
75
+ 'misiones.sin_compartir': 'Sharing is not available right now.',
76
+ 'misiones.resultado': 'Result',
77
+ 'misiones.meta': 'Goal',
78
+ 'misiones.objetivo': '{etiqueta}: {valor} of {meta}',
79
+ 'misiones.sin_objetivo': 'Not measured yet',
80
+ 'misiones.el_plan': 'Plan',
81
+ 'misiones.plan': '{estado} · {n}% done',
82
+ 'misiones.ver_resultados': 'Results: {url}',
83
+ 'misiones.actividad': 'Activity',
84
+ 'misiones.sin_actividad': 'Nothing yet: the agents have not started.',
85
+ 'misiones.ver_actividad': 'All of it: {url}',
86
+ 'misiones.no_disponible': 'Your missions are not reachable from parx yet.',
87
+ 'misiones.despacio': 'Too many at once. Try again in a minute.',
88
+ 'plantillas.titulo': 'Start from a template',
89
+ 'plantillas.mirando': 'Looking at the templates',
90
+ 'plantillas.nada': 'No templates right now.',
91
+ 'plantillas.sin_coincidencias': 'No template matches “{q}”.',
92
+ 'plantillas.propia': 'Yours',
93
+ 'plantillas.lista': 'Written below as a mission: review it and press Enter.',
94
+ 'ir.abriendo': 'Opening {que} in your browser: {url}',
95
+ 'ir.conexiones': 'your connections',
96
+ 'ir.ajustes': 'your settings',
56
97
  'modo.ask': 'Ask',
57
98
  'modo.auto': 'Auto',
58
99
  'modo.read': 'Read only',
@@ -76,21 +117,22 @@ export const TEXTOS = {
76
117
  'carpeta.lista': 'Allowed folders: {lista}',
77
118
  'carpeta.ninguna': 'Only the project folder. Add one with /folder <path>.',
78
119
  'carpeta.no_existe': 'That folder does not exist: {ruta}',
79
- 'trabajo.ruta': 'Tracing the route',
80
- 'trabajo.carriles': 'On the rails',
81
- 'trabajo.puntos': 'Connecting the dots',
82
- 'trabajo.numeros': 'Running the numbers',
83
- 'trabajo.afinar': 'Fine-tuning',
84
- 'trabajo.agujas': 'Switching tracks',
85
- 'trabajo.mapa': 'Reading the map',
86
- 'trabajo.estacion': 'Nearing the station',
120
+ 'trabajo.pensando': 'Thinking',
121
+ 'trabajo.planear': 'Planning the steps',
122
+ 'trabajo.resultados': 'Looking at the results',
123
+ 'trabajo.siguiente': 'Deciding the next step',
124
+ 'trabajo.sigue': 'Still thinking',
125
+ 'trabajo.servidor': 'Waiting for the server',
126
+ 'hace.respuesta': 'Writing the answer',
127
+ 'hace.generico': 'Working',
128
+ 'hace.buscar_ficheros': 'Searching files',
87
129
  'hace.leer': 'Reading {n} files',
88
130
  'hace.leer_uno': 'Reading {ruta}',
89
131
  'hace.listar': 'Looking around {ruta}',
90
132
  'hace.buscar': 'Searching for {patron}',
91
133
  'hace.escribir': 'Writing {ruta}',
92
134
  'hace.editar': 'Editing {ruta}',
93
- 'hace.cambios': 'Changing {n} files',
135
+ 'hace.cambios': 'Editing {n} files',
94
136
  'hace.tests': 'Running tests',
95
137
  'hace.build': 'Building',
96
138
  'hace.instalar': 'Installing',
@@ -181,6 +223,12 @@ export const TEXTOS = {
181
223
  'repl.adios': 'See you.',
182
224
  'repl.registro': 'Log of this session: {ruta}',
183
225
  'repl.nueva': 'New conversation.',
226
+ 'nueva.parar': 'Stop and start new?',
227
+ 'nueva.parar_detalle': 'parx is working. This stops it and clears the conversation.',
228
+ 'nueva.si': 'Stop and start new',
229
+ 'nueva.no': 'Keep working',
230
+ 'animacion.on': 'Answers are written out as they arrive. Any key shows the rest at once.',
231
+ 'animacion.off': 'Answers appear whole, at once. /animation on to turn it back on.',
184
232
  'repl.desconocido': 'Unknown command. Type /help.',
185
233
  'repl.deshecho': 'Undone: {ruta}',
186
234
  'repl.nada_que_deshacer': 'Nothing to undo.',
@@ -235,6 +283,7 @@ export const TEXTOS = {
235
283
  'tip.bash': 'Runs a shell command right here; parx sees the output',
236
284
  'tip.bandeja': 'Answer what your missions are waiting for',
237
285
  'tip.raton': 'Click options; Shift+drag selects text',
286
+ 'tip.arroba': 'Names one of your apps; a new one opens Connect',
238
287
  };
239
288
  export function cuantos(n, uno, varios, ninguno) {
240
289
  if (n === 0 && ninguno)
@@ -252,15 +301,20 @@ export const COMANDOS = [
252
301
  ['folder', 'Let parx work in another folder'],
253
302
  ['lanes', 'Run 2 or 3 tasks at once'],
254
303
  ['mission', 'Keep it running on Parallel, phone alert when done'],
304
+ ['missions', 'Pick a mission and control it from here'],
255
305
  ['inbox', 'Answer what your missions are waiting for'],
256
306
  ['report', 'Plain summary to paste in email or WhatsApp'],
257
307
  ['teach', 'Explain each step, like a teacher'],
308
+ ['templates', 'Start a mission from a template'],
258
309
  ['undo', 'Undo the last change to a file'],
259
310
  ['new', 'Start a new conversation'],
260
311
  ['balance', 'Your account and your Actions'],
312
+ ['connections', 'Connect your apps (opens the browser)'],
313
+ ['settings', 'Your account and preferences (browser)'],
261
314
  ['notify', 'Desktop notifications: on or off'],
262
315
  ['tips', 'Tips when it opens: on or off'],
263
316
  ['mouse', 'Clicks and wheel in parx: on or off'],
317
+ ['animation', 'Answers written out as they arrive: on or off'],
264
318
  ['log', 'Where the log of what it does is kept'],
265
319
  ['exit', 'Leave parx'],
266
320
  ];
@@ -268,11 +322,17 @@ export const ALIAS_COMANDO = {
268
322
  help: 'help', '?': 'help', ayuda: 'help',
269
323
  mode: 'mode', modo: 'mode',
270
324
  model: 'model', modelo: 'model',
325
+ strength: 'model',
271
326
  folder: 'folder', 'add-folder': 'folder', carpeta: 'folder', dir: 'folder',
272
327
  lanes: 'lanes', carriles: 'lanes',
273
328
  mission: 'mission', mision: 'mission', misión: 'mission',
329
+ missions: 'missions', misiones: 'missions',
274
330
  inbox: 'inbox', bandeja: 'inbox', approvals: 'inbox', waiting: 'inbox',
331
+ templates: 'templates', template: 'templates', plantillas: 'templates',
332
+ connections: 'connections', conexiones: 'connections', apps: 'connections',
333
+ settings: 'settings', ajustes: 'settings', preferences: 'settings',
275
334
  mouse: 'mouse', raton: 'mouse', ratón: 'mouse',
335
+ animation: 'animation', animations: 'animation', animacion: 'animation', animación: 'animation',
276
336
  report: 'report', informe: 'report',
277
337
  teach: 'teach', class: 'teach', clase: 'teach',
278
338
  undo: 'undo', deshacer: 'undo',
@@ -283,6 +343,7 @@ export const ALIAS_COMANDO = {
283
343
  log: 'log', registro: 'log',
284
344
  exit: 'exit', quit: 'exit', salir: 'exit',
285
345
  };
346
+ export const ALIAS_DESDE = { strength: 2 };
286
347
  export const ALIAS_SI_NO = {
287
348
  on: 'si', yes: 'si', y: 'si', '1': 'si', si: 'si', 'sí': 'si',
288
349
  off: 'no', no: 'no', n: 'no', '0': 'no',
@@ -304,6 +365,7 @@ export const USO = [
304
365
  ' --dir <folder> the project folder (default: current)',
305
366
  ' --ascii plain characters only (also NO_COLOR for no color)',
306
367
  ' --no-mouse leave the mouse to the terminal (no clicks or wheel in parx)',
368
+ ' --no-animation show answers whole, without writing them out',
307
369
  ' --version, --help',
308
370
  '',
309
371
  'Sign in:',