chocolatito-code 1.6.5 → 1.6.7

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.
@@ -4,23 +4,6 @@ export interface PermissionPromptResult {
4
4
  userFeedback?: string;
5
5
  }
6
6
  export declare function setAutoApprove(value: boolean): void;
7
- /**
8
- * DIALOGO DE PERMISO
9
- *
10
- * La version anterior tenia dos fallos visibles en cuanto se usaba:
11
- *
12
- * 1. Al mover la seleccion subia el cursor 12 lineas fijas, pero la caja mide
13
- * entre 10 y 14 segun cuantos detalles tenga. Cada flecha dejaba media caja
14
- * huerfana en pantalla, y por eso salian marcos vacios apilados.
15
- *
16
- * 2. El titulo llevaba un simbolo de anchura ambigua. El terminal lo pinta
17
- * ocupando dos columnas y el calculo del ancho contaba una, asi que el borde
18
- * derecho quedaba descuadrado justo en esa linea.
19
- *
20
- * Aqui se dibuja la caja a mano, con anchura conocida, y se repinta subiendo
21
- * exactamente las lineas que se escribieron.
22
- */
23
- export declare function askToolPermission(toolName: string, args: Record<string, any>, cwd?: string): Promise<PermissionPromptResult>;
24
7
  export declare const PERMISSION_OPTIONS: {
25
8
  label: string;
26
9
  hint: string;
@@ -33,3 +16,13 @@ export declare const PERMISSION_OPTIONS: {
33
16
  * derecho no se ve leyendo el codigo, solo ejecutandolo.
34
17
  */
35
18
  export declare function buildPermissionBox(toolName: string, args: Record<string, any>, cwd: string, selectedIndex: number, width?: number): string[];
19
+ /**
20
+ * Se pide el terminal prestado antes de abrir esto.
21
+ *
22
+ * Con el árbol de Ink montado hay un dueño de la pantalla, y esta función es de
23
+ * las que necesitan el teclado para ellas solas: escribe directo a stdout y abre
24
+ * su propia lectura de teclas. Sin el préstamo, las dos cuentas de filas se pisan
25
+ * y el marco de Ink no se recupera. Sin árbol, `conElTerminalPrestado` ejecuta la
26
+ * tarea tal cual y no cuesta nada. Ver ui/ink/prestamo.ts.
27
+ */
28
+ export declare function askToolPermission(toolName: string, args: Record<string, any>, cwd?: string): Promise<PermissionPromptResult>;
@@ -3,6 +3,7 @@ import process from "node:process";
3
3
  import chalk from "chalk";
4
4
  import { cycleMode, describeMode, getMode, modeAnnouncement } from "./modes.js";
5
5
  import { isOutsideProject, isSvgSource } from "../config/permissions.js";
6
+ import { conElTerminalPrestado } from "./ink/prestamo.js";
6
7
  /**
7
8
  * Aprobacion automatica: se activa con --yes / -y o con la variable de entorno
8
9
  * CHOCOLATITO_AUTO_APPROVE. Pensada para modo no interactivo y CI.
@@ -27,7 +28,7 @@ export function setAutoApprove(value) {
27
28
  * Aqui se dibuja la caja a mano, con anchura conocida, y se repinta subiendo
28
29
  * exactamente las lineas que se escribieron.
29
30
  */
30
- export async function askToolPermission(toolName, args, cwd = process.cwd()) {
31
+ async function askToolPermissionDirecto(toolName, args, cwd = process.cwd()) {
31
32
  if (autoApprove) {
32
33
  return { approved: true };
33
34
  }
@@ -351,3 +352,15 @@ function details(toolName, args, cwd, width) {
351
352
  out.push({ text: "", length: 0 });
352
353
  return out;
353
354
  }
355
+ /**
356
+ * Se pide el terminal prestado antes de abrir esto.
357
+ *
358
+ * Con el árbol de Ink montado hay un dueño de la pantalla, y esta función es de
359
+ * las que necesitan el teclado para ellas solas: escribe directo a stdout y abre
360
+ * su propia lectura de teclas. Sin el préstamo, las dos cuentas de filas se pisan
361
+ * y el marco de Ink no se recupera. Sin árbol, `conElTerminalPrestado` ejecuta la
362
+ * tarea tal cual y no cuesta nada. Ver ui/ink/prestamo.ts.
363
+ */
364
+ export function askToolPermission(toolName, args, cwd = process.cwd()) {
365
+ return conElTerminalPrestado(() => askToolPermissionDirecto(toolName, args, cwd));
366
+ }
@@ -219,10 +219,24 @@ function anotar(nombre, lineas) {
219
219
  * veces por segundo y la barra de escribir casi nunca cambia entre dos.
220
220
  */
221
221
  export function fijarSeccion(nombre, lineas) {
222
- if (!pieUsable())
223
- return;
224
- if (anotar(nombre, lineas))
225
- repintar("");
222
+ // DELEGA, Y ESO ARREGLA UN FALLO GORDO
223
+ //
224
+ // Antes empezaba con `if (!pieUsable()) return;`, o sea que con el pie apagado
225
+ // -que es exactamente lo que pasa cuando manda el arbol de Ink- esta funcion no
226
+ // hacia NADA. Ni guardaba la seccion ni avisaba a quien la pinta.
227
+ //
228
+ // Dos consecuencias, las dos visibles:
229
+ //
230
+ // - La linea de razonamiento (el 💭) es el unico sitio que llama aqui
231
+ // (ui/reasoningStream.ts:122). Con el arbol montado no salia nunca.
232
+ // - `quitarSeccion` pasa por aqui. Asi que `quitarSeccion("spinner")` al
233
+ // acabar el turno tampoco hacia nada: el "✳ Trabajando…" se quedaba
234
+ // puesto para siempre, mucho despues de que el agente hubiera terminado.
235
+ // Eso es lo que se ve como "se queda trabado".
236
+ //
237
+ // `fijarSecciones` ya distingue bien las dos cosas -guardar y avisar SIEMPRE,
238
+ // pintar solo si el pie esta encendido-, asi que aqui basta con delegar.
239
+ fijarSecciones([[nombre, lineas]]);
226
240
  }
227
241
  /**
228
242
  * Varias secciones de una vez, con UN solo repintado.
@@ -312,6 +326,14 @@ export function soltarPie() {
312
326
  return;
313
327
  secciones.clear();
314
328
  repintar("");
329
+ // Y se avisa, que si no el arbol sigue pintando una barra que ya no existe
330
+ // hasta que otra cosa cualquiera le haga redibujar.
331
+ for (const cb of alCambiarElPie) {
332
+ try {
333
+ cb();
334
+ }
335
+ catch { }
336
+ }
315
337
  }
316
338
  /**
317
339
  * Olvida el estado sin tocar la pantalla.
@@ -28,10 +28,12 @@ export interface OpcionDeLista {
28
28
  detalle?: string;
29
29
  }
30
30
  /**
31
- * Enseña la lista y devuelve el id elegido. `null` si se sale con Esc.
31
+ * Se pide el terminal prestado antes de abrir esto.
32
32
  *
33
- * Sin terminal no hay nada que elegir: devuelve null en el acto en vez de
34
- * quedarse esperando una tecla que no va a llegar nunca. Es lo que pasaria al
35
- * correrlo desde un script o dentro de las pruebas.
33
+ * Con el árbol de Ink montado hay un dueño de la pantalla, y esta función es de
34
+ * las que necesitan el teclado para ellas solas: escribe directo a stdout y abre
35
+ * su propia lectura de teclas. Sin el préstamo, las dos cuentas de filas se pisan
36
+ * y el marco de Ink no se recupera. Sin árbol, `conElTerminalPrestado` ejecuta la
37
+ * tarea tal cual y no cuesta nada. Ver ui/ink/prestamo.ts.
36
38
  */
37
39
  export declare function elegirDeLista(titulo: string, opciones: OpcionDeLista[], indiceInicial?: number): Promise<string | null>;
@@ -2,6 +2,7 @@ import chalk from "chalk";
2
2
  import process from "node:process";
3
3
  import readline from "node:readline";
4
4
  import { dibujar } from "./salida.js";
5
+ import { conElTerminalPrestado } from "./ink/prestamo.js";
5
6
  /**
6
7
  * Enseña la lista y devuelve el id elegido. `null` si se sale con Esc.
7
8
  *
@@ -9,7 +10,7 @@ import { dibujar } from "./salida.js";
9
10
  * quedarse esperando una tecla que no va a llegar nunca. Es lo que pasaria al
10
11
  * correrlo desde un script o dentro de las pruebas.
11
12
  */
12
- export async function elegirDeLista(titulo, opciones, indiceInicial = 0) {
13
+ async function elegirDeListaDirecto(titulo, opciones, indiceInicial = 0) {
13
14
  if (opciones.length === 0)
14
15
  return null;
15
16
  if (!process.stdin.isTTY)
@@ -89,3 +90,15 @@ export async function elegirDeLista(titulo, opciones, indiceInicial = 0) {
89
90
  process.stdin.on("keypress", alPulsar);
90
91
  });
91
92
  }
93
+ /**
94
+ * Se pide el terminal prestado antes de abrir esto.
95
+ *
96
+ * Con el árbol de Ink montado hay un dueño de la pantalla, y esta función es de
97
+ * las que necesitan el teclado para ellas solas: escribe directo a stdout y abre
98
+ * su propia lectura de teclas. Sin el préstamo, las dos cuentas de filas se pisan
99
+ * y el marco de Ink no se recupera. Sin árbol, `conElTerminalPrestado` ejecuta la
100
+ * tarea tal cual y no cuesta nada. Ver ui/ink/prestamo.ts.
101
+ */
102
+ export function elegirDeLista(titulo, opciones, indiceInicial = 0) {
103
+ return conElTerminalPrestado(() => elegirDeListaDirecto(titulo, opciones, indiceInicial));
104
+ }
@@ -1,60 +1,60 @@
1
- {
2
- "manifest_version": 3,
3
- "minimum_chrome_version": "102",
4
- "name": "Chocolatito Code",
5
- "version": "1.6.5",
6
- "description": "Deja que Chocolatito Code trabaje dentro de tu Chrome, en segundo plano y con tus sesiones ya iniciadas.",
7
- "permissions": [
8
- "tabs",
9
- "tabGroups",
10
- "scripting",
11
- "debugger",
12
- "webNavigation",
13
- "storage",
14
- "downloads"
15
- ],
16
- "host_permissions": [
17
- "<all_urls>"
18
- ],
19
- "icons": {
20
- "16": "iconos/16.png",
21
- "32": "iconos/32.png",
22
- "48": "iconos/48.png",
23
- "128": "iconos/128.png"
24
- },
25
- "background": {
26
- "service_worker": "background.js"
27
- },
28
- "content_scripts": [
29
- {
30
- "matches": [
31
- "<all_urls>"
32
- ],
33
- "js": [
34
- "content.js"
35
- ],
36
- "run_at": "document_idle",
37
- "all_frames": true
38
- }
39
- ],
40
- "action": {
41
- "default_title": "Chocolatito Code",
42
- "default_popup": "popup.html",
43
- "default_icon": {
44
- "16": "iconos/16.png",
45
- "32": "iconos/32.png",
46
- "48": "iconos/48.png"
47
- }
48
- },
49
- "web_accessible_resources": [
50
- {
51
- "resources": [
52
- "iconos/*",
53
- "fuentes/*"
54
- ],
55
- "matches": [
56
- "<all_urls>"
57
- ]
58
- }
59
- ]
60
- }
1
+ {
2
+ "manifest_version": 3,
3
+ "minimum_chrome_version": "102",
4
+ "name": "Chocolatito Code",
5
+ "version": "1.6.7",
6
+ "description": "Deja que Chocolatito Code trabaje dentro de tu Chrome, en segundo plano y con tus sesiones ya iniciadas.",
7
+ "permissions": [
8
+ "tabs",
9
+ "tabGroups",
10
+ "scripting",
11
+ "debugger",
12
+ "webNavigation",
13
+ "storage",
14
+ "downloads"
15
+ ],
16
+ "host_permissions": [
17
+ "<all_urls>"
18
+ ],
19
+ "icons": {
20
+ "16": "iconos/16.png",
21
+ "32": "iconos/32.png",
22
+ "48": "iconos/48.png",
23
+ "128": "iconos/128.png"
24
+ },
25
+ "background": {
26
+ "service_worker": "background.js"
27
+ },
28
+ "content_scripts": [
29
+ {
30
+ "matches": [
31
+ "<all_urls>"
32
+ ],
33
+ "js": [
34
+ "content.js"
35
+ ],
36
+ "run_at": "document_idle",
37
+ "all_frames": true
38
+ }
39
+ ],
40
+ "action": {
41
+ "default_title": "Chocolatito Code",
42
+ "default_popup": "popup.html",
43
+ "default_icon": {
44
+ "16": "iconos/16.png",
45
+ "32": "iconos/32.png",
46
+ "48": "iconos/48.png"
47
+ }
48
+ },
49
+ "web_accessible_resources": [
50
+ {
51
+ "resources": [
52
+ "iconos/*",
53
+ "fuentes/*"
54
+ ],
55
+ "matches": [
56
+ "<all_urls>"
57
+ ]
58
+ }
59
+ ]
60
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chocolatito-code",
3
- "version": "1.6.5",
3
+ "version": "1.6.7",
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": {
@@ -1,49 +0,0 @@
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;
@@ -1,92 +0,0 @@
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
- }