chocolatito-code 1.4.2 → 1.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.
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import { codigoDeSalida, EXIT_OK, EXIT_FALLO, EXIT_USO, EXIT_LICENCIA } from "./
15
15
  import { showBanner, animateStartupBanner, showHelp, showEffortMenu } from "./ui/banner.js";
16
16
  import { fijarMotor } from "./ui/motorActual.js";
17
17
  import { elegirDeLista } from "./ui/selector.js";
18
+ import { entrarEnPantallaFija, pantallaFijaPedida } from "./ui/pantalla.js";
18
19
  import { reafirmarModoCrudo } from "./ui/keyboardGuard.js";
19
20
  import { askInteractivePrompt, SLASH_COMMANDS } from "./ui/prompt.js";
20
21
  import { changeDir } from "./tools/changeDir.js";
@@ -235,6 +236,11 @@ ${nodeViejo}
235
236
  const hookManager = new HookManager(context.cwd);
236
237
  const sessionManager = new SessionManager();
237
238
  const sessionId = `session_${Date.now()}`;
239
+ // La barra de abajo solo puede quedarse clavada si el programa toma la
240
+ // pantalla entera. Se pide con CHOCOLATITO_PANTALLA=fija y se paga con el
241
+ // historial del terminal: ver ui/pantalla.ts.
242
+ if (pantallaFijaPedida())
243
+ entrarEnPantallaFija();
238
244
  let currentModel = DEFAULT_ESPECTRO;
239
245
  // La barra de estado lo lee de aqui. Fijarlo al arrancar y no solo al
240
246
  // cambiarlo: si no, hasta el primer /effort la barra no dice nada.
@@ -0,0 +1,49 @@
1
+ /**
2
+ * LO QUE HA SALIDO POR PANTALLA, GUARDADO EN MEMORIA
3
+ *
4
+ * POR QUE HACE FALTA
5
+ *
6
+ * En la pantalla normal el historial lo lleva el terminal: sale una línea, se va
7
+ * hacia arriba, y la rueda del ratón la recupera. Por eso la barra de abajo sube
8
+ * con el scroll: es una línea más del historial, no una capa encima.
9
+ *
10
+ * En la pantalla alternativa —la que usan vim o htop— el terminal NO guarda
11
+ * nada. A cambio, la barra se queda clavada de verdad. Pero si nadie recuerda lo
12
+ * que salió, la conversación desaparece en cuanto pasa de una pantalla, que sería
13
+ * mucho peor que el problema que se quiere resolver.
14
+ *
15
+ * Así que aquí se guarda. Es el precio de tener la barra fija: el historial deja
16
+ * de ser del terminal y pasa a ser nuestro.
17
+ *
18
+ * POR QUE SE GUARDA POR LÍNEAS Y NO EL FLUJO CRUDO
19
+ *
20
+ * Lo que llega trae códigos de color y a veces medio renglón sin terminar. Para
21
+ * poder pintar "las últimas N líneas" hay que saber dónde acaba cada una, así
22
+ * que se parte por saltos y el resto sin terminar se queda esperando al suyo.
23
+ * Los colores se conservan tal cual: recortarlos aquí sería pintar la
24
+ * conversación en gris.
25
+ */
26
+ /** Añade lo que se acaba de escribir. Acepta trozos a medio renglón. */
27
+ export declare function apuntar(texto: string): void;
28
+ /**
29
+ * Todas las líneas, con el resto sin terminar como última.
30
+ *
31
+ * Se incluye a propósito: mientras el modelo escribe una frase larga, el resto
32
+ * ES lo que está saliendo. Ocultarlo hasta el salto haría que la respuesta
33
+ * apareciera a tirones, un renglón entero de golpe.
34
+ */
35
+ export declare function todas(): string[];
36
+ export declare function cuantas(): number;
37
+ /** Se llama en cada escritura, para que quien pinte se entere. */
38
+ export declare function alEscribir(cb: () => void): () => void;
39
+ export declare function vaciar(): void;
40
+ /**
41
+ * La ventana visible: `alto` líneas terminando `desdeElFinal` por encima del
42
+ * final.
43
+ *
44
+ * `desdeElFinal` es cuánto se ha subido con el scroll. Cero es el fondo, que es
45
+ * donde se está mientras se trabaja.
46
+ */
47
+ export declare function ventana(alto: number, desdeElFinal?: number): string[];
48
+ /** Cuánto se puede subir todavía. Sirve para no pasarse del principio. */
49
+ export declare function tope(alto: number): number;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * LO QUE HA SALIDO POR PANTALLA, GUARDADO EN MEMORIA
3
+ *
4
+ * POR QUE HACE FALTA
5
+ *
6
+ * En la pantalla normal el historial lo lleva el terminal: sale una línea, se va
7
+ * hacia arriba, y la rueda del ratón la recupera. Por eso la barra de abajo sube
8
+ * con el scroll: es una línea más del historial, no una capa encima.
9
+ *
10
+ * En la pantalla alternativa —la que usan vim o htop— el terminal NO guarda
11
+ * nada. A cambio, la barra se queda clavada de verdad. Pero si nadie recuerda lo
12
+ * que salió, la conversación desaparece en cuanto pasa de una pantalla, que sería
13
+ * mucho peor que el problema que se quiere resolver.
14
+ *
15
+ * Así que aquí se guarda. Es el precio de tener la barra fija: el historial deja
16
+ * de ser del terminal y pasa a ser nuestro.
17
+ *
18
+ * POR QUE SE GUARDA POR LÍNEAS Y NO EL FLUJO CRUDO
19
+ *
20
+ * Lo que llega trae códigos de color y a veces medio renglón sin terminar. Para
21
+ * poder pintar "las últimas N líneas" hay que saber dónde acaba cada una, así
22
+ * que se parte por saltos y el resto sin terminar se queda esperando al suyo.
23
+ * Los colores se conservan tal cual: recortarlos aquí sería pintar la
24
+ * conversación en gris.
25
+ */
26
+ /** Tope de líneas recordadas. Más allá, se olvidan las de arriba. */
27
+ const MAXIMO = Number(process.env.CHOCOLATITO_HISTORIAL_LINEAS || 5000);
28
+ let lineas = [];
29
+ let resto = "";
30
+ const oyentes = [];
31
+ /** Añade lo que se acaba de escribir. Acepta trozos a medio renglón. */
32
+ export function apuntar(texto) {
33
+ if (!texto)
34
+ return;
35
+ const completo = resto + texto.replace(/\r\n/g, "\n");
36
+ const partes = completo.split("\n");
37
+ // El último trozo no lleva salto: todavía no es una línea terminada.
38
+ resto = partes.pop() ?? "";
39
+ for (const l of partes)
40
+ lineas.push(l);
41
+ if (lineas.length > MAXIMO)
42
+ lineas = lineas.slice(lineas.length - MAXIMO);
43
+ for (const cb of oyentes) {
44
+ try {
45
+ cb();
46
+ }
47
+ catch { }
48
+ }
49
+ }
50
+ /**
51
+ * Todas las líneas, con el resto sin terminar como última.
52
+ *
53
+ * Se incluye a propósito: mientras el modelo escribe una frase larga, el resto
54
+ * ES lo que está saliendo. Ocultarlo hasta el salto haría que la respuesta
55
+ * apareciera a tirones, un renglón entero de golpe.
56
+ */
57
+ export function todas() {
58
+ return resto ? [...lineas, resto] : lineas;
59
+ }
60
+ export function cuantas() {
61
+ return todas().length;
62
+ }
63
+ /** Se llama en cada escritura, para que quien pinte se entere. */
64
+ export function alEscribir(cb) {
65
+ oyentes.push(cb);
66
+ return () => {
67
+ const i = oyentes.indexOf(cb);
68
+ if (i >= 0)
69
+ oyentes.splice(i, 1);
70
+ };
71
+ }
72
+ export function vaciar() {
73
+ lineas = [];
74
+ resto = "";
75
+ }
76
+ /**
77
+ * La ventana visible: `alto` líneas terminando `desdeElFinal` por encima del
78
+ * final.
79
+ *
80
+ * `desdeElFinal` es cuánto se ha subido con el scroll. Cero es el fondo, que es
81
+ * donde se está mientras se trabaja.
82
+ */
83
+ export function ventana(alto, desdeElFinal = 0) {
84
+ const todo = todas();
85
+ const fin = Math.max(0, todo.length - Math.max(0, desdeElFinal));
86
+ const inicio = Math.max(0, fin - Math.max(1, alto));
87
+ return todo.slice(inicio, fin);
88
+ }
89
+ /** Cuánto se puede subir todavía. Sirve para no pasarse del principio. */
90
+ export function tope(alto) {
91
+ return Math.max(0, cuantas() - Math.max(1, alto));
92
+ }
@@ -1,10 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useMemo, useRef } from "react";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
3
3
  import { Box, Text, useApp, useInput, useStdout } from "ink";
4
4
  import { buildPromptFrame } from "../marco.js";
5
5
  import { cycleMode } from "../modes.js";
6
6
  import { aplicarOpcion, archivosDelProyecto, leerHistorial, mencionEnCurso, opcionesDelDesplegable, } from "../entrada.js";
7
7
  import { esGrande, guardarPegado, marcaQueTerminaEn } from "../pegados.js";
8
+ import { alEscribir, tope, ventana } from "../historial.js";
9
+ import { enPantallaFija } from "../pantalla.js";
8
10
  /** Marca del cursor. Ink esconde el de verdad, así que este se dibuja. */
9
11
  const CARET = "█";
10
12
  export function Prompt({ alEnviar, alCancelar, cwd, promptSymbol, avisos, }) {
@@ -13,8 +15,22 @@ export function Prompt({ alEnviar, alCancelar, cwd, promptSymbol, avisos, }) {
13
15
  const [texto, setTexto] = useState("");
14
16
  const [cursor, setCursor] = useState(0);
15
17
  const [elegido, setElegido] = useState(0);
18
+ /** Contador para forzar un dibujado cuando cambia algo de fuera de React. */
19
+ const [, setRedibujar] = useState(0);
16
20
  const historial = useRef(leerHistorial());
17
21
  const [posHistorial, setPosHistorial] = useState(historial.current.length);
22
+ // Cuanto se ha subido con Re Pag. Cero es el fondo, que es donde se esta
23
+ // mientras se trabaja. Solo se usa en pantalla fija.
24
+ const [subido, setSubido] = useState(0);
25
+ const fija = enPantallaFija();
26
+ // En pantalla fija el terminal ya no guarda nada: lo que sale lo pintamos
27
+ // nosotros, asi que hay que repintar en cada escritura del agente. El
28
+ // historial vive fuera de React y React no puede adivinar que ha crecido.
29
+ useEffect(() => {
30
+ if (!fija)
31
+ return;
32
+ return alEscribir(() => setRedibujar((n) => n + 1));
33
+ }, [fija]);
18
34
  // Se escanea UNA vez por prompt, no en cada tecla: recorrer el proyecto entero
19
35
  // por cada letra se nota en cuanto el proyecto pasa de mediano.
20
36
  const archivos = useMemo(() => {
@@ -27,6 +43,27 @@ export function Prompt({ alEnviar, alCancelar, cwd, promptSymbol, avisos, }) {
27
43
  }, [cwd]);
28
44
  const opciones = opcionesDelDesplegable(texto, cursor, archivos);
29
45
  const indice = opciones.length > 0 ? ((elegido % opciones.length) + opciones.length) % opciones.length : 0;
46
+ const cols = Math.max(20, stdout?.columns || 80);
47
+ const rows = stdout?.rows || 24;
48
+ // El cursor se dibuja: Ink esconde el del terminal.
49
+ const conCaret = texto.slice(0, cursor) + CARET + texto.slice(cursor);
50
+ const marco = buildPromptFrame({
51
+ cols,
52
+ rows,
53
+ promptSymbol,
54
+ input: conCaret,
55
+ cursorIndex: cursor,
56
+ items: opciones,
57
+ selectedIndex: indice,
58
+ });
59
+ // Filas que le quedan a la conversacion una vez puesta la barra. En pantalla
60
+ // fija es lo que se pinta; en la normal no se usa, que ahi el historial es del
61
+ // terminal.
62
+ // Cuando se ha subido, una fila se va en el aviso de que se esta mirando
63
+ // atras. Sin descontarla, el arbol mide una fila mas que la ventana y el
64
+ // terminal desplaza: la barra dejaria de estar clavada justo al usar el scroll,
65
+ // que es para lo que existe este modo.
66
+ const altoDelTexto = Math.max(1, rows - marco.lines.length - (subido > 0 ? 1 : 0));
30
67
  function enviar() {
31
68
  const orden = texto.trim();
32
69
  if (!orden)
@@ -35,6 +72,15 @@ export function Prompt({ alEnviar, alCancelar, cwd, promptSymbol, avisos, }) {
35
72
  exit();
36
73
  }
37
74
  useInput((entrada, tecla) => {
75
+ // ----------------------------------------------- recorrer lo que salio
76
+ //
77
+ // Solo Re Pag y Av Pag. Las flechas y los caracteres son para escribir:
78
+ // robarselos aqui dejaria al usuario sin poder teclear.
79
+ if (fija && (tecla.pageUp || tecla.pageDown)) {
80
+ const salto = Math.max(1, Math.floor(altoDelTexto / 2));
81
+ setSubido((n) => tecla.pageUp ? Math.min(tope(altoDelTexto), n + salto) : Math.max(0, n - salto));
82
+ return;
83
+ }
38
84
  // ------------------------------------------------------------- salir
39
85
  if (tecla.ctrl && entrada === "c") {
40
86
  alCancelar();
@@ -44,6 +90,11 @@ export function Prompt({ alEnviar, alCancelar, cwd, promptSymbol, avisos, }) {
44
90
  // ------------------------------------------- cambiar el modo de permisos
45
91
  if (tecla.tab && tecla.shift) {
46
92
  cycleMode();
93
+ // El modo NO vive en el estado de React: lo guarda modes.ts, que lo
94
+ // comparten el prompt, el vigilante de teclas y el dialogo de permisos.
95
+ // Sin este empujon, React no tiene motivo para volver a dibujar y la barra
96
+ // se queda anunciando el modo anterior mientras el de verdad ya cambio.
97
+ setRedibujar((n) => n + 1);
47
98
  return;
48
99
  }
49
100
  // ------------------------------------------------------------- enviar
@@ -164,18 +215,14 @@ export function Prompt({ alEnviar, alCancelar, cwd, promptSymbol, avisos, }) {
164
215
  setElegido(0);
165
216
  }
166
217
  });
167
- const cols = Math.max(20, stdout?.columns || 80);
168
- const rows = stdout?.rows || 24;
169
- // El cursor se dibuja: Ink esconde el del terminal.
170
- const conCaret = texto.slice(0, cursor) + CARET + texto.slice(cursor);
171
- const marco = buildPromptFrame({
172
- cols,
173
- rows,
174
- promptSymbol,
175
- input: conCaret,
176
- cursorIndex: cursor,
177
- items: opciones,
178
- selectedIndex: indice,
179
- });
180
- return (_jsxs(Box, { flexDirection: "column", children: [avisos.map((a, i) => (_jsx(Text, { children: a }, `aviso-${i}`))), marco.lines.map((linea, i) => (_jsx(Text, { children: linea }, i)))] }));
218
+ if (!fija) {
219
+ return (_jsxs(Box, { flexDirection: "column", children: [avisos.map((a, i) => (_jsx(Text, { children: a }, `aviso-${i}`))), marco.lines.map((linea, i) => (_jsx(Text, { children: linea }, i)))] }));
220
+ }
221
+ // PANTALLA FIJA: el arbol ocupa la ventana entera y la barra va la ultima, asi
222
+ // que no puede moverse. Lo de arriba se rellena con huecos cuando hay poca
223
+ // conversacion; sin eso la barra subiria a media pantalla, que es justo la
224
+ // queja que este modo viene a resolver.
225
+ const visible = ventana(altoDelTexto, subido);
226
+ const huecos = Math.max(0, altoDelTexto - visible.length);
227
+ return (_jsxs(Box, { flexDirection: "column", height: rows, children: [Array.from({ length: huecos }, (_, i) => (_jsx(Text, { children: " " }, `hueco-${i}`))), visible.map((linea, i) => (_jsx(Text, { children: linea }, `h-${i}`))), subido > 0 && (_jsx(Text, { dimColor: true, children: ` ↑ ${subido} lineas mas arriba · Av Pag para volver al final` })), marco.lines.map((linea, i) => (_jsx(Text, { children: linea }, `b-${i}`)))] }));
181
228
  }
@@ -90,6 +90,22 @@ export async function preguntarConInk(promptSymbol = "❯", cwd = process.cwd())
90
90
  instancia.waitUntilExit().then(() => {
91
91
  escribirTardio = null;
92
92
  limpiarPegados();
93
+ // EL PROGRAMA SE CERRABA SOLO AL ELEGIR /effort
94
+ //
95
+ // Ink desreferencia stdin al desmontarse (stdin.unref) para no dejar el
96
+ // proceso vivo por una entrada que ya nadie escucha. Muy razonable... pero
97
+ // lo que viene DESPUES del prompt tambien lee el teclado: el menu de
98
+ // /effort, el dialogo de permisos. Con stdin sin referencia, esos se
99
+ // quedan esperando una tecla mientras Node ve el bucle de eventos vacio y
100
+ // se cierra.
101
+ //
102
+ // Visto por el usuario: escribia "/efor", pulsaba Enter sobre la
103
+ // recomendacion, y Chocolatito desaparecia dejandolo en la ruta de la
104
+ // consola. Ni error ni despedida: como si nunca hubiera estado.
105
+ //
106
+ // Se vuelve a referenciar aqui, que es el punto por el que se pasa SIEMPRE
107
+ // al cerrar el prompt, venga la orden de donde venga.
108
+ process.stdin.ref?.();
93
109
  // Si el árbol muere sin haber entregado nada -una excepción, un Ctrl+C
94
110
  // del sistema-, la promesa no puede quedarse colgada: el bucle se
95
111
  // detendría para siempre sin decir por qué.
@@ -0,0 +1,19 @@
1
+ export declare function pantallaFijaPedida(): boolean;
2
+ /**
3
+ * Enciende o apaga el modo a mano, SIN tocar el terminal.
4
+ *
5
+ * Las pruebas lo necesitan: entrar de verdad escribiria la secuencia de la
6
+ * pantalla alternativa en la consola de quien corre las pruebas y le dejaria el
7
+ * informe en una pantalla que desaparece al acabar.
8
+ */
9
+ export declare function forzarPantallaFija(valor: boolean | null): void;
10
+ export declare function enPantallaFija(): boolean;
11
+ export declare function entrarEnPantallaFija(): void;
12
+ /**
13
+ * Devuelve el terminal como estaba.
14
+ *
15
+ * Se llama al salir del programa, y también si algo revienta: quedarse en la
16
+ * pantalla alternativa deja al usuario en una consola en blanco sin su prompt,
17
+ * y la única salida es cerrar la ventana.
18
+ */
19
+ export declare function salirDePantallaFija(): void;
@@ -0,0 +1,84 @@
1
+ import process from "node:process";
2
+ import { redirigirDibujo } from "./salida.js";
3
+ import { apuntar } from "./historial.js";
4
+ /**
5
+ * LA PANTALLA ALTERNATIVA
6
+ *
7
+ * La barra de abajo sube al hacer scroll porque ES una línea del historial del
8
+ * terminal, no una capa encima. Ninguna secuencia de escape la clava ahí; lo
9
+ * único que lo consigue es que el programa tome la pantalla entera, como hacen
10
+ * vim o htop.
11
+ *
12
+ * QUÉ CAMBIA AL ENTRAR
13
+ *
14
+ * El terminal deja de guardar historial: la rueda del ratón no sirve y al salir
15
+ * la sesión desaparece de la consola. Por eso, mientras dura, TODO lo que se
16
+ * imprime se guarda en memoria (historial.ts) y lo pinta el árbol de Ink.
17
+ *
18
+ * Y por eso hay que interceptar también `console.log`. Aquí no vale con desviar
19
+ * el conducto de dibujo: media docena de sitios —el arranque, la licencia, los
20
+ * avisos— siguen imprimiendo directo, y en la pantalla alternativa eso escribe
21
+ * encima de lo que Ink acaba de dibujar y descuadra el árbol entero.
22
+ *
23
+ * ES UN MODO, NO EL COMPORTAMIENTO NORMAL
24
+ *
25
+ * Cambiar el historial del terminal por uno propio es un intercambio de verdad,
26
+ * no una mejora: quien use mucho la rueda del ratón para releer sale perdiendo.
27
+ * Se activa con CHOCOLATITO_PANTALLA=fija.
28
+ */
29
+ const ENTRAR = "\x1b[?1049h";
30
+ const SALIR = "\x1b[?1049l";
31
+ let dentro = false;
32
+ let logOriginal = null;
33
+ export function pantallaFijaPedida() {
34
+ return process.env.CHOCOLATITO_PANTALLA === "fija";
35
+ }
36
+ /** `null` = manda el estado real. Las pruebas lo fuerzan. */
37
+ let forzado = null;
38
+ /**
39
+ * Enciende o apaga el modo a mano, SIN tocar el terminal.
40
+ *
41
+ * Las pruebas lo necesitan: entrar de verdad escribiria la secuencia de la
42
+ * pantalla alternativa en la consola de quien corre las pruebas y le dejaria el
43
+ * informe en una pantalla que desaparece al acabar.
44
+ */
45
+ export function forzarPantallaFija(valor) {
46
+ forzado = valor;
47
+ }
48
+ export function enPantallaFija() {
49
+ return forzado ?? dentro;
50
+ }
51
+ export function entrarEnPantallaFija() {
52
+ if (dentro || !process.stdout.isTTY)
53
+ return;
54
+ dentro = true;
55
+ process.stdout.write(ENTRAR);
56
+ // Lo que se dibujaba en el terminal pasa a ser historial nuestro.
57
+ redirigirDibujo((texto) => apuntar(texto));
58
+ logOriginal = console.log;
59
+ console.log = (...args) => {
60
+ apuntar(args.map((a) => (typeof a === "string" ? a : String(a))).join(" ") + "\n");
61
+ };
62
+ }
63
+ /**
64
+ * Devuelve el terminal como estaba.
65
+ *
66
+ * Se llama al salir del programa, y también si algo revienta: quedarse en la
67
+ * pantalla alternativa deja al usuario en una consola en blanco sin su prompt,
68
+ * y la única salida es cerrar la ventana.
69
+ */
70
+ export function salirDePantallaFija() {
71
+ if (!dentro)
72
+ return;
73
+ dentro = false;
74
+ if (logOriginal) {
75
+ console.log = logOriginal;
76
+ logOriginal = null;
77
+ }
78
+ redirigirDibujo(null);
79
+ try {
80
+ process.stdout.write(SALIR);
81
+ }
82
+ catch { }
83
+ }
84
+ process.on("exit", salirDePantallaFija);
@@ -24,6 +24,16 @@ export async function elegirDeLista(titulo, opciones, indiceInicial = 0) {
24
24
  if (process.stdin.setRawMode)
25
25
  process.stdin.setRawMode(true);
26
26
  process.stdin.resume();
27
+ // Y referenciado, no solo reanudado. Son cosas distintas: `resume` hace que
28
+ // lleguen los datos, `ref` hace que Node considere que hay trabajo
29
+ // pendiente. Sin lo segundo, este menu se queda esperando una tecla
30
+ // mientras el proceso ve el bucle de eventos vacio y se cierra solo.
31
+ //
32
+ // No es hipotetico: paso justo aqui. Ink desreferencia stdin al desmontar el
33
+ // prompt, y al abrir este menu Chocolatito desaparecia dejando al usuario en
34
+ // la ruta de la consola. Se arreglo tambien alli, pero este menu no tiene
35
+ // por que depender de quien haya corrido antes.
36
+ process.stdin.ref?.();
27
37
  /** Filas del ultimo dibujo. Se repinta encima, sin dejar restos. */
28
38
  let filas = 0;
29
39
  function pintar() {
@@ -2,7 +2,7 @@
2
2
  "manifest_version": 3,
3
3
  "minimum_chrome_version": "102",
4
4
  "name": "Chocolatito Code",
5
- "version": "1.4.2",
5
+ "version": "1.5.0",
6
6
  "description": "Deja que Chocolatito Code trabaje dentro de tu Chrome, en segundo plano y con tus sesiones ya iniciadas.",
7
7
  "permissions": [
8
8
  "tabs",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chocolatito-code",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Agente autónomo de programación para la terminal, con control real del ordenador y del navegador. Desarrollado por Chocolatito.",
5
5
  "type": "module",
6
6
  "bin": {