chocolatito-code 1.6.6 → 1.6.8

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.
Files changed (76) hide show
  1. package/README.md +437 -341
  2. package/dist/agent/context.d.ts +6 -0
  3. package/dist/agent/context.js +69 -2
  4. package/dist/agent/loop.js +8 -0
  5. package/dist/agent/toolGate.js +13 -7
  6. package/dist/agent/verifier.js +2 -1
  7. package/dist/config/permissions.d.ts +17 -0
  8. package/dist/config/permissions.js +47 -7
  9. package/dist/config/plataforma.d.ts +62 -0
  10. package/dist/config/plataforma.js +109 -0
  11. package/dist/config/updater.js +4 -1
  12. package/dist/hooks/manager.js +2 -1
  13. package/dist/index.js +164 -39
  14. package/dist/memory/manager.d.ts +15 -5
  15. package/dist/memory/manager.js +146 -29
  16. package/dist/servidor/captura.d.ts +36 -0
  17. package/dist/servidor/captura.js +74 -0
  18. package/dist/servidor/pagina.d.ts +27 -0
  19. package/dist/servidor/pagina.js +268 -0
  20. package/dist/servidor/puente.d.ts +34 -0
  21. package/dist/servidor/puente.js +115 -0
  22. package/dist/servidor/servidor.d.ts +61 -0
  23. package/dist/servidor/servidor.js +249 -0
  24. package/dist/sessions/manager.d.ts +8 -0
  25. package/dist/sessions/manager.js +44 -0
  26. package/dist/sessions/resume.d.ts +12 -0
  27. package/dist/sessions/resume.js +10 -0
  28. package/dist/tools/backgroundTask.d.ts +64 -0
  29. package/dist/tools/backgroundTask.js +264 -0
  30. package/dist/tools/browserExtension.d.ts +2 -1
  31. package/dist/tools/browserExtension.js +48 -0
  32. package/dist/tools/computerUse.js +51 -9
  33. package/dist/tools/definitions.js +93 -1
  34. package/dist/tools/gitAudit.d.ts +41 -0
  35. package/dist/tools/gitAudit.js +282 -0
  36. package/dist/tools/runCommand.js +5 -2
  37. package/dist/tools/runner.js +36 -2
  38. package/dist/tools/safety.d.ts +1 -0
  39. package/dist/tools/safety.js +3 -0
  40. package/dist/tools/todoTool.d.ts +2 -0
  41. package/dist/tools/todoTool.js +29 -0
  42. package/dist/tools/toolDefsComputer.js +9 -0
  43. package/dist/tools/win/hostScript.js +7 -2
  44. package/dist/ui/comandos.js +2 -0
  45. package/dist/ui/ink/App.d.ts +0 -23
  46. package/dist/ui/ink/App.js +86 -57
  47. package/dist/ui/ink/Prompt.d.ts +16 -6
  48. package/dist/ui/ink/Prompt.js +37 -62
  49. package/dist/ui/ink/montarApp.d.ts +34 -0
  50. package/dist/ui/ink/montarApp.js +93 -1
  51. package/dist/ui/ink/prestamo.d.ts +63 -0
  52. package/dist/ui/ink/prestamo.js +92 -0
  53. package/dist/ui/ink/teclado.d.ts +48 -0
  54. package/dist/ui/ink/teclado.js +96 -0
  55. package/dist/ui/ink/transcripcion.d.ts +114 -0
  56. package/dist/ui/ink/transcripcion.js +180 -0
  57. package/dist/ui/interrupt.js +4 -1
  58. package/dist/ui/loopPrompt.d.ts +6 -7
  59. package/dist/ui/loopPrompt.js +14 -1
  60. package/dist/ui/marco.d.ts +3 -0
  61. package/dist/ui/marco.js +22 -3
  62. package/dist/ui/pantalla.d.ts +45 -17
  63. package/dist/ui/pantalla.js +150 -92
  64. package/dist/ui/permissionPrompt.d.ts +19 -17
  65. package/dist/ui/permissionPrompt.js +44 -1
  66. package/dist/ui/pieFijo.d.ts +1 -1
  67. package/dist/ui/pieFijo.js +27 -5
  68. package/dist/ui/renderer.js +8 -0
  69. package/dist/ui/selector.d.ts +6 -4
  70. package/dist/ui/selector.js +14 -1
  71. package/extension/background.js +80 -0
  72. package/extension/content.js +106 -0
  73. package/extension/manifest.json +3 -2
  74. package/package.json +3 -2
  75. package/dist/ui/historial.d.ts +0 -49
  76. package/dist/ui/historial.js +0 -92
@@ -0,0 +1,180 @@
1
+ /**
2
+ * LA CONVERSACIÓN, EN CAMINO AL HISTORIAL DEL TERMINAL
3
+ *
4
+ * QUÉ SUSTITUYE, Y POR QUÉ
5
+ *
6
+ * Antes esto era `historial.ts`: un buffer en memoria con las últimas 5000
7
+ * líneas, que hacía falta porque la pantalla alternativa deja al terminal sin
8
+ * historial propio. Aquí no hay pantalla alternativa. Lo que se escribe entra en
9
+ * el historial DEL TERMINAL —el de verdad, el de la rueda del ratón— a través de
10
+ * `<Static>` de Ink, y esto es solo la cinta transportadora que lo lleva hasta
11
+ * allí.
12
+ *
13
+ * POR QUÉ HAY QUE PARTIR EN LÍNEAS
14
+ *
15
+ * `<Static>` emite un elemento y lo da por escrito para siempre: una vez fuera,
16
+ * ni Ink ni nadie puede volver a tocarlo, porque ya es texto del terminal. Así
17
+ * que solo puede entrar lo que está terminado. El modelo, en cambio, escribe a
18
+ * chorros que cortan a mitad de palabra.
19
+ *
20
+ * Aquí se separan las dos cosas: lo que ya tiene su salto de línea pasa a
21
+ * `<Static>` y se vuelve permanente; el trozo que cuelga se queda en `resto` y
22
+ * lo pinta la zona de abajo, que sí se repinta. Cuando llega el salto, el resto
23
+ * entero cruza al otro lado. Visto desde fuera es una línea que se va
24
+ * escribiendo, sin saltos ni parpadeos.
25
+ *
26
+ * LAS DOS REGLAS DE <STATIC>, QUE NO SON NEGOCIABLES
27
+ *
28
+ * Están medidas en `node_modules/ink/build/components/Static.js:11-20`, que es
29
+ * todo el mecanismo: guarda un índice, renderiza `items.slice(indice)` y en el
30
+ * commit siguiente adelanta el índice a `items.length`. No compara nada.
31
+ *
32
+ * 1. La lista SOLO crece. Un `splice`, un `filter` o un vaciado hacen retroceder
33
+ * el índice, y todo lo que se añada por encima se REIMPRIME: la conversación
34
+ * sale duplicada en el historial del terminal y ya no hay forma de borrarla.
35
+ * 2. Cada elemento necesita `key` propia y estable. React reutiliza nodos por
36
+ * posición, y la lista que ve cambia de longitud en cada commit; sin `key`
37
+ * acabas emitiendo el texto de otro. Por eso cada línea lleva su `id`.
38
+ *
39
+ * Y POR QUÉ EXISTE `base`
40
+ *
41
+ * Cuando el árbol se desmonta y se vuelve a montar —un diálogo de permisos que
42
+ * necesita el teclado para él solo— el `<Static>` nuevo empieza de cero y
43
+ * volvería a escribir la conversación entera. Pero en la pantalla normal esas
44
+ * líneas siguen ahí, en el terminal, que no se ha borrado. `base` marca por
45
+ * dónde iba, y el montaje nuevo solo recibe lo que aún no se ha pintado.
46
+ */
47
+ /** Lo que se ha ido escribiendo, en orden. Solo se añade al final. */
48
+ let lineas = [];
49
+ /** Cuántas de esas ya están escritas en el terminal. Solo cambia al remontar. */
50
+ let base = 0;
51
+ /** El trozo sin terminar. Todavía no puede cruzar a <Static>. */
52
+ let resto = "";
53
+ let siguienteId = 1;
54
+ const oyentes = [];
55
+ function avisar() {
56
+ for (const cb of oyentes) {
57
+ try {
58
+ cb();
59
+ }
60
+ catch { }
61
+ }
62
+ }
63
+ /**
64
+ * Entra texto del agente. Acepta trozos a media línea, que es lo normal.
65
+ *
66
+ * El `\r` suelto se descarta con su línea: en un flujo de markdown no es un
67
+ * retorno de carro de verdad, viene de un `\r\n` partido por la mitad entre dos
68
+ * trozos, y dejarlo pasar mete una línea vacía por cada salto.
69
+ */
70
+ export function anotar(texto) {
71
+ if (!texto)
72
+ return;
73
+ const completo = resto + String(texto).replace(/\r\n/g, "\n");
74
+ const partes = completo.split("\n");
75
+ resto = partes.pop() ?? "";
76
+ for (const l of partes) {
77
+ lineas.push({ id: siguienteId++, texto: l });
78
+ }
79
+ avisar();
80
+ }
81
+ /** Lo último que se entregó, para no rehacerlo en cada dibujado. */
82
+ let entregado = [];
83
+ let entregadoLargo = -1;
84
+ let entregadoBase = -1;
85
+ /**
86
+ * Las líneas que <Static> todavía no ha escrito.
87
+ *
88
+ * DEVUELVE UN ARRAY NUEVO CADA VEZ QUE HAY ALGO NUEVO, Y NO ES UN CAPRICHO
89
+ *
90
+ * Este fue el fallo que dejó la conversación entera sin escribirse, y costó
91
+ * encontrarlo porque no parecía un fallo: la primera versión devolvía el array
92
+ * interno tal cual, al que `anotar` le hace `push`.
93
+ *
94
+ * <Static> memoriza lo que va a emitir con `useMemo(() => items.slice(index),
95
+ * [items, index])` (Static.js:12-14). Con la MISMA referencia de array y el
96
+ * mismo índice, React da por buena la memoria y devuelve lo de antes: el `[]`
97
+ * del primer dibujado. El array crecía, la pantalla no. Nada de emitir de más
98
+ * ni de menos: sencillamente no se emitía NUNCA.
99
+ *
100
+ * Así que la referencia tiene que cambiar cuando cambia el contenido. Se
101
+ * reconstruye solo cuando ha crecido de verdad —una vez por línea terminada, no
102
+ * una por dibujado—, que a treinta fotogramas por segundo es la diferencia entre
103
+ * reconstruirlo treinta veces por segundo o ninguna mientras nadie escribe.
104
+ */
105
+ export function pendientes() {
106
+ if (lineas.length !== entregadoLargo || base !== entregadoBase) {
107
+ entregado = lineas.slice(base);
108
+ entregadoLargo = lineas.length;
109
+ entregadoBase = base;
110
+ }
111
+ return entregado;
112
+ }
113
+ /** El trozo que cuelga, el que pinta la zona de abajo. */
114
+ export function colgando() {
115
+ return resto;
116
+ }
117
+ /**
118
+ * "Lo de hasta aquí ya está en el terminal."
119
+ *
120
+ * Se llama SOLO justo antes de desmontar el árbol. Llamarlo con el árbol vivo
121
+ * encogería la lista que ve <Static>, que es la regla 1 de arriba.
122
+ */
123
+ export function darPorPintado() {
124
+ base = lineas.length;
125
+ }
126
+ export function alCambiar(cb) {
127
+ oyentes.push(cb);
128
+ return () => {
129
+ const i = oyentes.indexOf(cb);
130
+ if (i >= 0)
131
+ oyentes.splice(i, 1);
132
+ };
133
+ }
134
+ /** Para las pruebas. En producción la conversación no se tira nunca. */
135
+ export function vaciarTranscripcion() {
136
+ lineas = [];
137
+ base = 0;
138
+ resto = "";
139
+ siguienteId = 1;
140
+ entregado = [];
141
+ entregadoLargo = -1;
142
+ entregadoBase = -1;
143
+ }
144
+ /** Cuántas líneas terminadas van. Para las pruebas y para medir. */
145
+ export function cuantasLineas() {
146
+ return lineas.length;
147
+ }
148
+ const SOLO_COLOR = /\x1b\[[0-9;]*m/g;
149
+ /**
150
+ * Recorta el trozo que cuelga para que quepa en las filas que le tocan.
151
+ *
152
+ * NO ES COSMÉTICO, ES LA RED DE SEGURIDAD DEL RENDIMIENTO
153
+ *
154
+ * En Windows, si el bloque de abajo llega a medir lo que la ventana, Ink deja de
155
+ * repintar por diferencias y pasa a `clearTerminal` + reimprimir la conversación
156
+ * ENTERA en cada fotograma (ink.js:100-102 y 769). Con el spinner a 30 por
157
+ * segundo eso es parpadeo, historial perdido y coste creciente con la sesión.
158
+ *
159
+ * El caso que lo dispara: un párrafo largo sin un solo salto de línea. Mientras
160
+ * no lo termine, ese párrafo entero es "lo que cuelga".
161
+ *
162
+ * Cuando hay que recortar se quitan también los colores: cortar una cadena por
163
+ * el medio parte los códigos de escape y lo que sale es basura de colores
164
+ * enganchada al resto de la sesión. Es un trozo que en cuanto llegue su salto de
165
+ * línea se reemplaza por la línea entera y bien pintada, así que el recorte no
166
+ * dura ni un parpadeo.
167
+ */
168
+ export function recortarCola(texto, cols, filas) {
169
+ if (!texto)
170
+ return [];
171
+ const ancho = Math.max(1, cols);
172
+ const techo = Math.max(0, filas);
173
+ if (techo === 0)
174
+ return [];
175
+ const visible = texto.replace(SOLO_COLOR, "");
176
+ if (Math.ceil(visible.length / ancho) <= techo)
177
+ return [texto];
178
+ const pelado = visible.slice(-(ancho * techo));
179
+ return [pelado];
180
+ }
@@ -177,7 +177,10 @@ export class InterruptWatcher {
177
177
  }
178
178
  else {
179
179
  this.stop();
180
- process.stdout.write("\n");
180
+ // `dibujar` y no `process.stdout.write`: con el arbol montado, una
181
+ // escritura cruda es una fila que Ink no cuenta, y el borrado del marco
182
+ // al salir se come una linea de la conversacion.
183
+ dibujar("\n");
181
184
  process.exit(0);
182
185
  }
183
186
  return;
@@ -5,13 +5,12 @@ export interface RespuestaDeBucle {
5
5
  indicacion?: string;
6
6
  }
7
7
  /**
8
- * Que hacer cuando el agente lleva tres vueltas haciendo exactamente lo mismo.
8
+ * Se pide el terminal prestado antes de abrir esto.
9
9
  *
10
- * Sin terminal —CI, `chocolatito "tarea"`, un cron— se PARA. Es lo contrario de
11
- * lo que hace el dialogo de permisos, que ante la duda deniega para no tocar
12
- * nada, y el motivo es que aqui el riesgo es el opuesto: no hay nada que
13
- * proteger del agente, hay una cuota que proteger de un bucle que nadie esta
14
- * mirando. Parar no mata el turno: le devuelve al modelo un mensaje explicando
15
- * el atasco, y el turno sigue.
10
+ * Con el árbol de Ink montado hay un dueño de la pantalla, y esta función es de
11
+ * las que necesitan el teclado para ellas solas: escribe directo a stdout y abre
12
+ * su propia lectura de teclas. Sin el préstamo, las dos cuentas de filas se pisan
13
+ * y el marco de Ink no se recupera. Sin árbol, `conElTerminalPrestado` ejecuta la
14
+ * tarea tal cual y no cuesta nada. Ver ui/ink/prestamo.ts.
16
15
  */
17
16
  export declare function preguntarPorBucle(aviso: AvisoDeBucle): Promise<RespuestaDeBucle>;
@@ -1,6 +1,7 @@
1
1
  import readline from "node:readline";
2
2
  import process from "node:process";
3
3
  import chalk from "chalk";
4
+ import { conElTerminalPrestado } from "./ink/prestamo.js";
4
5
  /**
5
6
  * Que hacer cuando el agente lleva tres vueltas haciendo exactamente lo mismo.
6
7
  *
@@ -11,7 +12,7 @@ import chalk from "chalk";
11
12
  * mirando. Parar no mata el turno: le devuelve al modelo un mensaje explicando
12
13
  * el atasco, y el turno sigue.
13
14
  */
14
- export async function preguntarPorBucle(aviso) {
15
+ async function preguntarPorBucleDirecto(aviso) {
15
16
  const cabecera = chalk.yellow(`\n↻ Parece un bucle: `) +
16
17
  chalk.white(`"${aviso.herramienta}"`) +
17
18
  chalk.yellow(` lleva ${aviso.repeticiones} llamadas identicas con el mismo resultado.`);
@@ -57,3 +58,15 @@ export async function preguntarPorBucle(aviso) {
57
58
  });
58
59
  });
59
60
  }
61
+ /**
62
+ * Se pide el terminal prestado antes de abrir esto.
63
+ *
64
+ * Con el árbol de Ink montado hay un dueño de la pantalla, y esta función es de
65
+ * las que necesitan el teclado para ellas solas: escribe directo a stdout y abre
66
+ * su propia lectura de teclas. Sin el préstamo, las dos cuentas de filas se pisan
67
+ * y el marco de Ink no se recupera. Sin árbol, `conElTerminalPrestado` ejecuta la
68
+ * tarea tal cual y no cuesta nada. Ver ui/ink/prestamo.ts.
69
+ */
70
+ export function preguntarPorBucle(aviso) {
71
+ return conElTerminalPrestado(() => preguntarPorBucleDirecto(aviso));
72
+ }
@@ -13,6 +13,7 @@ export interface PromptFrameOptions {
13
13
  cursorIndex?: number;
14
14
  items?: DropdownItem[];
15
15
  selectedIndex?: number;
16
+ taskWidget?: string;
16
17
  }
17
18
  export interface PromptFrame {
18
19
  /** Lineas LOGICAS. Cualquiera puede ocupar mas de una fila fisica. */
@@ -32,4 +33,6 @@ export interface PromptFrame {
32
33
  * aritmetica de filas se hace UNA vez sobre las mismas lineas que se pintan, en
33
34
  * lugar de estimarse por otro lado y descuadrarse.
34
35
  */
36
+ /** Cuantas sugerencias se ensenan como mucho. Ver la nota en el desplegable. */
37
+ export declare const MAXIMO_DEL_DESPLEGABLE = 8;
35
38
  export declare function buildPromptFrame(opts: PromptFrameOptions): PromptFrame;
package/dist/ui/marco.js CHANGED
@@ -55,6 +55,8 @@ function truncatePlain(text, width) {
55
55
  * aritmetica de filas se hace UNA vez sobre las mismas lineas que se pintan, en
56
56
  * lugar de estimarse por otro lado y descuadrarse.
57
57
  */
58
+ /** Cuantas sugerencias se ensenan como mucho. Ver la nota en el desplegable. */
59
+ export const MAXIMO_DEL_DESPLEGABLE = 8;
58
60
  export function buildPromptFrame(opts) {
59
61
  const cols = Math.max(20, opts.cols || 80);
60
62
  const viewportRows = Math.max(6, opts.rows || 24);
@@ -95,7 +97,22 @@ export function buildPromptFrame(opts) {
95
97
  // Sin contarla, el desplegable pide una fila mas de las que caben y el marco
96
98
  // se sale por arriba de la ventana.
97
99
  const room = Math.max(1, viewportRows - 1 - (2 + 1 + inputRows + 1 + 1));
98
- const shown = Math.min(items.length, room);
100
+ // Y ademas un tope propio, mas bajo que lo que cabe.
101
+ //
102
+ // POR QUE NO SE DEJA CRECER HASTA LLENAR LA VENTANA
103
+ //
104
+ // Con solo "/" hay dieciocho comandos. En una consola de 24 filas eso hacia un
105
+ // marco de veinte, o sea que al escribir UNA barra la caja se comia la pantalla
106
+ // entera y tapaba la conversacion; y a la letra siguiente se encogia a nueve.
107
+ // Cada tecla movia veinte filas arriba y abajo.
108
+ //
109
+ // Eso es feo, y ademas es el terreno donde aparecen los fallos de repintado: un
110
+ // marco que crece hasta el borde obliga al terminal a desplazar, y a partir de
111
+ // ahi Ink borra contando filas que ya no son suyas.
112
+ //
113
+ // Ocho es lo que se ve de un vistazo sin buscar. Y el desplegable filtra segun
114
+ // escribes, asi que llegar al que quieres son dos letras, no dieciocho lineas.
115
+ const shown = Math.min(items.length, room, MAXIMO_DEL_DESPLEGABLE);
99
116
  const dropdownOffset = shown > 0 && items.length > shown
100
117
  ? Math.min(Math.max(0, selectedIndex - Math.floor(shown / 2)), items.length - shown)
101
118
  : 0;
@@ -197,7 +214,9 @@ export function buildPromptFrame(opts) {
197
214
  // Dos, no una. Con una, la caja seguia leyendose pegada a lo de arriba: "pusiste
198
215
  // una linea de espacio, que sea bien pues". Con dos se separa de verdad, y es
199
216
  // el mismo aire que hay al arrancar entre el zorro y el aviso.
200
- const lines = ["", "", bar, inputLine, ...dropdownLines, bar, footerLine];
217
+ const widgetLines = opts.taskWidget && opts.taskWidget.trim().length > 0 ? [opts.taskWidget] : [];
218
+ const widgetRows = widgetLines.reduce((n, l) => n + physicalRows(l, cols), 0);
219
+ const lines = ["", "", ...widgetLines, bar, inputLine, ...dropdownLines, bar, footerLine];
201
220
  // 4. Donde queda el cursor, en filas fisicas. Antes se hacia cursorCol =
202
221
  // total % cols: aplicaba el modulo pero nunca sumaba la fila, asi que en
203
222
  // cuanto la entrada se partia el acento se iba a escribir a otra linea.
@@ -205,7 +224,7 @@ export function buildPromptFrame(opts) {
205
224
  const segments = typed.split("\n");
206
225
  // La fila de aire de arriba cuenta: sin sumarla, el cursor se dibuja una fila
207
226
  // por encima de donde se escribe.
208
- let cursorRow = 2 + physicalRows(bar, cols);
227
+ let cursorRow = 2 + widgetRows + physicalRows(bar, cols);
209
228
  for (let i = 0; i < segments.length - 1; i++) {
210
229
  cursorRow += Math.max(1, Math.ceil(((i === 0 ? symbolWidth : 0) + segments[i].length) / cols));
211
230
  }
@@ -1,30 +1,58 @@
1
1
  /**
2
- * Fija SOLO SI SE PIDE. Van dos veces que la pongo de serie y se rompe.
2
+ * De serie SÍ, desde la 1.6.7, y con salida de emergencia.
3
3
  *
4
- * La segunda: "ahora sale una barra y lo demas negro, escribo y se cierra".
4
+ * DOS VECES ESTUVO AQUÍ Y DOS VECES SALIÓ ROTO
5
5
  *
6
- * La regla que saco de esto, y que no pienso volver a saltarme: esto no vuelve
7
- * a ser lo normal hasta que el dueño confirme que lo ha visto funcionar en SU
8
- * consola con la variable puesta. Un emulador -por bueno que sea, y el de
9
- * tests/terminal.test.mjs lo es- prueba lo que sabe emular. Ha hecho falta que
10
- * falle dos veces para aprenderlo.
6
+ * La 1.6.0 salió en negro ("no sale nada, se bugea") y la 1.6.5 con "una barra y
7
+ * lo demás negro, escribo y se cierra". Las dos veces pasaban las 820 pruebas:
8
+ * un emulador prueba lo que sabe emular, y una consola de verdad hace cosas que
9
+ * no sabe.
10
+ *
11
+ * Esta vez el orden fue el otro: se entregó detrás de la variable, el dueño lo
12
+ * corrió en SU consola, y solo después pasó a ser lo normal. Lo hizo, y lo
13
+ * aprobó sabiendo lo que no le iba a gustar: que la caja no se queda clavada al
14
+ * hacer scroll. No se queda porque es texto del terminal, y en Claude Code
15
+ * tampoco se queda. Es el precio de recuperar la rueda del ratón y el historial.
16
+ *
17
+ * CHOCOLATITO_PANTALLA=normal devuelve la interfaz clásica. Existe porque una
18
+ * consola rara —una que no sea la suya ni la mía— puede seguir haciendo algo que
19
+ * no habíamos visto, y entonces el usuario necesita poder trabajar hoy, no
20
+ * esperar al parche.
11
21
  */
12
22
  export declare function pantallaFijaPedida(): boolean;
23
+ export declare function forzarPantallaFija(valor: boolean | null): void;
24
+ export declare function enPantallaFija(): boolean;
13
25
  /**
14
- * Enciende o apaga el modo a mano, SIN tocar el terminal.
26
+ * Enciende el modo de árbol único. Devuelve si de verdad se encendió.
27
+ *
28
+ * EL BOOLEANO NO SOBRA, Y SE VOLVIÓ IMPRESCINDIBLE AL PONERLO POR DEFECTO
29
+ *
30
+ * Sin terminal —una salida redirigida a un archivo, un `chocolatito "tarea"` en
31
+ * un script, CI— aquí no se entra. Pero quien llama montaba el árbol de todas
32
+ * formas, y Ink sin terminal escribe su marco como texto suelto: la salida del
33
+ * programa sale con la caja de escribir dentro.
15
34
  *
16
- * Las pruebas lo necesitan: entrar de verdad escribiría la secuencia de la
17
- * pantalla alternativa en la consola de quien corre las pruebas y le dejaría el
18
- * informe en una pantalla que desaparece al acabar.
35
+ * Mientras esto iba detrás de una variable no pasaba nunca, porque nadie la pone
36
+ * en un script. De serie, es el caso normal.
19
37
  */
20
- export declare function forzarPantallaFija(valor: boolean | null): void;
21
- export declare function enPantallaFija(): boolean;
22
- export declare function entrarEnPantallaFija(): void;
38
+ export declare function entrarEnPantallaFija(): boolean;
39
+ /**
40
+ * Manda `console` a la transcripción.
41
+ *
42
+ * Se exporta para poder probarlo: `entrarEnPantallaFija` no se puede llamar en
43
+ * las pruebas porque exige un terminal de verdad, y un parche de consola sin
44
+ * probar es de las cosas que fallan en silencio —lo que se pierde no se ve, que
45
+ * es justo el problema—.
46
+ */
47
+ export declare function interceptarConsola(): void;
48
+ export declare function devolverConsola(): void;
23
49
  /**
24
50
  * Devuelve el terminal como estaba.
25
51
  *
26
- * Se llama al salir del programa, y también si algo revienta: quedarse en la
27
- * pantalla alternativa deja al usuario en una consola en blanco sin su prompt,
28
- * y la única salida es cerrar la ventana.
52
+ * Aquí ya no hay ninguna pantalla que abandonar —esa era la versión de antes—,
53
+ * pero hay que devolver el conducto de dibujo y el pie: si el proceso sigue
54
+ * vivo después de esto (una prueba, una sesión que cambia de modo) y el dibujo
55
+ * se queda desviado, todo lo que se escriba va a una transcripción que ya no
56
+ * pinta nadie.
29
57
  */
30
58
  export declare function salirDePantallaFija(): void;