chocolatito-code 1.6.7 → 1.6.9

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 (55) hide show
  1. package/README.md +447 -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 +99 -6
  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 +68 -0
  35. package/dist/tools/gitAudit.js +374 -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/marco.d.ts +1 -0
  46. package/dist/ui/marco.js +4 -2
  47. package/dist/ui/permissionPrompt.d.ts +9 -0
  48. package/dist/ui/permissionPrompt.js +30 -0
  49. package/dist/ui/pieFijo.d.ts +1 -1
  50. package/dist/ui/pieFijo.js +1 -1
  51. package/dist/ui/renderer.js +8 -0
  52. package/extension/background.js +80 -0
  53. package/extension/content.js +106 -0
  54. package/extension/manifest.json +61 -60
  55. package/package.json +3 -2
@@ -799,6 +799,54 @@ export async function chromeExtension(params, cwd = process.cwd(), apiKey) {
799
799
  ? "Trabajo cerrado: pestana desagrupada y aviso retirado."
800
800
  : fail(action, res.error);
801
801
  }
802
+ case "console_logs": {
803
+ const res = await extensionBridge.send("getConsoleLogs", {
804
+ tabId: params.tabId,
805
+ clear: params.clear === true,
806
+ });
807
+ if (!res.ok)
808
+ return fail(action, res.error);
809
+ const logs = res.data?.logs || [];
810
+ if (logs.length === 0) {
811
+ return "Sin errores de consola registrados en la página.";
812
+ }
813
+ const formateados = logs
814
+ .map((log) => {
815
+ const hora = log.timestamp ? new Date(log.timestamp).toLocaleTimeString() : "";
816
+ const nivel = (log.level || "error").toUpperCase();
817
+ const prefijo = hora ? `[${hora}] [${nivel}]` : `[${nivel}]`;
818
+ let linea = `${prefijo} ${log.message || ""}`;
819
+ if (log.url)
820
+ linea += ` (${log.url})`;
821
+ if (log.stack)
822
+ linea += `\n Stack: ${log.stack.split("\n").slice(0, 3).join("\n ")}`;
823
+ return linea;
824
+ })
825
+ .join("\n");
826
+ return `LOGS DE CONSOLA (${logs.length} registro${logs.length === 1 ? "" : "s"}):\n${formateados}${params.clear ? "\n(Buffer limpiado)" : ""}`;
827
+ }
828
+ case "network_errors": {
829
+ const res = await extensionBridge.send("getNetworkErrors", {
830
+ tabId: params.tabId,
831
+ clear: params.clear === true,
832
+ });
833
+ if (!res.ok)
834
+ return fail(action, res.error);
835
+ const errors = res.data?.errors || [];
836
+ if (errors.length === 0) {
837
+ return "Sin errores de red registrados en la página.";
838
+ }
839
+ const formateados = errors
840
+ .map((err) => {
841
+ const hora = err.timestamp ? new Date(err.timestamp).toLocaleTimeString() : "";
842
+ const status = err.status ? ` HTTP ${err.status}` : "";
843
+ const detalle = err.error && err.error !== `HTTP ${err.status}` ? ` - ${err.error}` : "";
844
+ const horaStr = hora ? `[${hora}] ` : "";
845
+ return `${horaStr}${err.method || "GET"}${status} -> ${err.url}${detalle}`;
846
+ })
847
+ .join("\n");
848
+ return `ERRORES DE RED (${errors.length} peticion${errors.length === 1 ? "" : "es"} fallida${errors.length === 1 ? "" : "s"}):\n${formateados}${params.clear ? "\n(Buffer limpiado)" : ""}`;
849
+ }
802
850
  default:
803
851
  return fail(String(action), "accion no reconocida.");
804
852
  }
@@ -220,10 +220,31 @@ async function estadoTrasActuar(args) {
220
220
  export async function computerUse(params, cwd = process.cwd(), apiKey) {
221
221
  const { action } = params;
222
222
  const mode = params.mode || "background";
223
- const targetX = params.coordinate ? params.coordinate[0] : params.x;
224
- const targetY = params.coordinate ? params.coordinate[1] : params.y;
225
- const startX = params.start_coordinate ? params.start_coordinate[0] : params.x;
226
- const startY = params.start_coordinate ? params.start_coordinate[1] : params.y;
223
+ let targetX = params.coordinate ? params.coordinate[0] : params.x;
224
+ let targetY = params.coordinate ? params.coordinate[1] : params.y;
225
+ let startX = params.start_coordinate ? params.start_coordinate[0] : params.x;
226
+ let startY = params.start_coordinate ? params.start_coordinate[1] : params.y;
227
+ // Soporte de coordenadas normalizadas (0.0 a 1.0) estilo Astra / OpenAI Operator
228
+ if (targetX !== undefined && targetY !== undefined && targetX > 0 && targetX <= 1.0 && targetY > 0 && targetY <= 1.0) {
229
+ try {
230
+ const sInfo = await winHost.send("screen_info");
231
+ const sw = sInfo.virtualWidth || sInfo.primaryWidth || 1920;
232
+ const sh = sInfo.virtualHeight || sInfo.primaryHeight || 1080;
233
+ targetX = Math.round(targetX * sw);
234
+ targetY = Math.round(targetY * sh);
235
+ }
236
+ catch { }
237
+ }
238
+ if (startX !== undefined && startY !== undefined && startX > 0 && startX <= 1.0 && startY > 0 && startY <= 1.0) {
239
+ try {
240
+ const sInfo = await winHost.send("screen_info");
241
+ const sw = sInfo.virtualWidth || sInfo.primaryWidth || 1920;
242
+ const sh = sInfo.virtualHeight || sInfo.primaryHeight || 1080;
243
+ startX = Math.round(startX * sw);
244
+ startY = Math.round(startY * sh);
245
+ }
246
+ catch { }
247
+ }
227
248
  try {
228
249
  switch (action) {
229
250
  // ---------------------------------------------------------------- espera
@@ -459,7 +480,7 @@ export async function computerUse(params, cwd = process.cwd(), apiKey) {
459
480
  if (!apiKey) {
460
481
  return `Sin coincidencias en el arbol de accesibilidad para "${query}", y no hay API key para recurrir a la vision.`;
461
482
  }
462
- const shotPath = path.join(ensureCache(), "find_target.png");
483
+ const shotPath = path.join(ensureCache(), "find_target.jpg");
463
484
  const shot = await captureFor(params, shotPath);
464
485
  if (!shot.ok)
465
486
  return fail(action, shot.error || "no se pudo capturar");
@@ -475,7 +496,7 @@ export async function computerUse(params, cwd = process.cwd(), apiKey) {
475
496
  }
476
497
  // ---------------------------------------------------------------- captura
477
498
  case "screenshot": {
478
- const out = resolveOut(params.outputPath, "screen_latest.png", cwd);
499
+ const out = resolveOut(params.outputPath, "screen_latest.jpg", cwd);
479
500
  const choice = await resolveWindow(params);
480
501
  if (!choice.ok)
481
502
  return fail(action, choice.error);
@@ -502,6 +523,7 @@ export async function computerUse(params, cwd = process.cwd(), apiKey) {
502
523
  // ------------------------------------------------------------ raton/teclado
503
524
  case "left_click":
504
525
  case "click":
526
+ case "mouse_click":
505
527
  case "double_click":
506
528
  case "triple_click":
507
529
  case "right_click":
@@ -547,7 +569,8 @@ export async function computerUse(params, cwd = process.cwd(), apiKey) {
547
569
  return fail(action, res.error || "fallo desconocido");
548
570
  return `Cursor movido a (${targetX}, ${targetY}).`;
549
571
  }
550
- case "left_click_drag": {
572
+ case "left_click_drag":
573
+ case "drag": {
551
574
  if (targetX === undefined || targetY === undefined || startX === undefined || startY === undefined) {
552
575
  return fail(action, "faltan start_coordinate y coordinate.");
553
576
  }
@@ -589,7 +612,9 @@ export async function computerUse(params, cwd = process.cwd(), apiKey) {
589
612
  return `Escrito en la ventana enfocada (${res.chars} caracteres): "${preview(params.text)}"`;
590
613
  }
591
614
  case "key":
592
- case "hotkey": {
615
+ case "hotkey":
616
+ case "press":
617
+ case "key_press": {
593
618
  const combo = normalizeKeys(params.keys || params.key || params.text || "");
594
619
  if (!combo)
595
620
  return fail(action, 'indica la tecla en "keys" (ej. "Return", "ctrl+t", "alt+Tab").');
@@ -725,7 +750,7 @@ function normalizeKeys(raw) {
725
750
  let k = raw.trim();
726
751
  if (!k)
727
752
  return "";
728
- // Restos del formato SendKeys que usaba la version anterior.
753
+ // Restos del formato SendKeys y alias comunes de Astra/Operator/Playwright
729
754
  const sendKeysMap = {
730
755
  "{ENTER}": "Return",
731
756
  "{ESC}": "Escape",
@@ -740,7 +765,23 @@ function normalizeKeys(raw) {
740
765
  "^{TAB}": "ctrl+Tab",
741
766
  "%{TAB}": "alt+Tab",
742
767
  "%{F4}": "alt+F4",
768
+ enter: "Return",
769
+ return: "Return",
770
+ esc: "Escape",
771
+ escape: "Escape",
772
+ tab: "Tab",
773
+ space: "Space",
774
+ spacebar: "Space",
775
+ backspace: "BackSpace",
776
+ delete: "Delete",
777
+ del: "Delete",
778
+ up: "Up",
779
+ down: "Down",
780
+ left: "Left",
781
+ right: "Right",
743
782
  };
783
+ if (sendKeysMap[k.toLowerCase()])
784
+ return sendKeysMap[k.toLowerCase()];
744
785
  if (sendKeysMap[k])
745
786
  return sendKeysMap[k];
746
787
  if (/^\^\{?[A-Za-z0-9]+\}?$/.test(k))
@@ -749,6 +790,7 @@ function normalizeKeys(raw) {
749
790
  k = "alt+" + k.replace(/[%{}]/g, "");
750
791
  else if (/^\{[A-Za-z0-9]+\}$/.test(k))
751
792
  k = k.slice(1, -1);
793
+ k = k.replace(/control\+/gi, "ctrl+").replace(/super\+/gi, "win+").replace(/cmd\+/gi, "win+").replace(/meta\+/gi, "win+");
752
794
  return k.replace(/\s+/g, "");
753
795
  }
754
796
  function preview(text) {
@@ -54,7 +54,7 @@ export const TOOLS = [
54
54
  type: "function",
55
55
  function: {
56
56
  name: "save_memory",
57
- description: "Guarda un hecho importante, preferencia del usuario o aprendizaje en la memoria persistente (~/.chocolatito/memory/).",
57
+ description: "Guarda un hecho importante, preferencia del usuario o aprendizaje en la memoria persistente (~/.chocolatito/memory/ o local del proyecto).",
58
58
  parameters: {
59
59
  type: "object",
60
60
  properties: {
@@ -66,6 +66,11 @@ export const TOOLS = [
66
66
  type: "string",
67
67
  description: "El hecho o conocimiento a recordar en futuras sesiones.",
68
68
  },
69
+ scope: {
70
+ type: "string",
71
+ enum: ["project", "global"],
72
+ description: "Ámbito donde guardar: 'project' (local del proyecto en .chocolatito/memory/) o 'global' (en ~/.chocolatito/memory/). Por defecto 'project' si se está en un proyecto válido.",
73
+ },
69
74
  },
70
75
  required: ["topic", "fact"],
71
76
  },
@@ -83,6 +88,11 @@ export const TOOLS = [
83
88
  type: "string",
84
89
  description: "El tema o nombre del archivo de memoria a consultar.",
85
90
  },
91
+ scope: {
92
+ type: "string",
93
+ enum: ["project", "global"],
94
+ description: "Ámbito de consulta: 'project' (local del proyecto) o 'global' (en ~/.chocolatito/memory/). Si no se especifica, busca en proyecto primero y luego en global.",
95
+ },
86
96
  },
87
97
  required: ["topic"],
88
98
  },
@@ -299,6 +309,88 @@ export const TOOLS = [
299
309
  },
300
310
  },
301
311
  },
312
+ {
313
+ type: "function",
314
+ function: {
315
+ name: "start_background_task",
316
+ description: "Inicia un comando en segundo plano sin bloquear el bucle de interacción (útil para servidores dev, watchers, compilaciones continuas).",
317
+ parameters: {
318
+ type: "object",
319
+ properties: {
320
+ command: {
321
+ type: "string",
322
+ description: "El comando a ejecutar en segundo plano.",
323
+ },
324
+ description: {
325
+ type: "string",
326
+ description: "Descripción opcional de la tarea.",
327
+ },
328
+ cwd: {
329
+ type: "string",
330
+ description: "Directorio de trabajo desde donde ejecutar la tarea (opcional).",
331
+ },
332
+ },
333
+ required: ["command"],
334
+ },
335
+ },
336
+ },
337
+ {
338
+ type: "function",
339
+ function: {
340
+ name: "read_task_output",
341
+ description: "Lee la salida acumulada (logs) de una tarea en segundo plano sin bloquear.",
342
+ parameters: {
343
+ type: "object",
344
+ properties: {
345
+ taskId: {
346
+ type: "string",
347
+ description: "El ID de la tarea a consultar.",
348
+ },
349
+ lines: {
350
+ type: "integer",
351
+ description: "Número de líneas a devolver (por defecto 100).",
352
+ },
353
+ offset: {
354
+ type: "integer",
355
+ description: "Línea inicial desde donde comenzar a leer (opcional).",
356
+ },
357
+ },
358
+ required: ["taskId"],
359
+ },
360
+ },
361
+ },
362
+ {
363
+ type: "function",
364
+ function: {
365
+ name: "list_background_tasks",
366
+ description: "Lista todas las tareas en segundo plano registradas con su estado, PID y tiempo transcurrido.",
367
+ parameters: {
368
+ type: "object",
369
+ properties: {},
370
+ },
371
+ },
372
+ },
373
+ {
374
+ type: "function",
375
+ function: {
376
+ name: "stop_background_task",
377
+ description: "Detiene una tarea en segundo plano activa y termina todo su árbol de procesos.",
378
+ parameters: {
379
+ type: "object",
380
+ properties: {
381
+ taskId: {
382
+ type: "string",
383
+ description: "El ID de la tarea a detener.",
384
+ },
385
+ force: {
386
+ type: "boolean",
387
+ description: "Si es true, fuerza la terminación inmediata del proceso (por defecto true).",
388
+ },
389
+ },
390
+ required: ["taskId"],
391
+ },
392
+ },
393
+ },
302
394
  {
303
395
  type: "function",
304
396
  function: {
@@ -0,0 +1,68 @@
1
+ export interface AuditFinding {
2
+ type: "secret" | "debug" | "sensitive_file";
3
+ file: string;
4
+ line?: number;
5
+ message: string;
6
+ snippet?: string;
7
+ }
8
+ export interface AuditStats {
9
+ filesChanged: number;
10
+ insertions: number;
11
+ additions: number;
12
+ deletions: number;
13
+ files: string[];
14
+ }
15
+ export interface AuditReport {
16
+ ok: boolean;
17
+ clean: boolean;
18
+ stats: AuditStats;
19
+ secrets: AuditFinding[];
20
+ debugLogs: AuditFinding[];
21
+ residualLogs: AuditFinding[];
22
+ /** Cuantas sentencias se callaron por `.chocolatitoauditignore`. Se dice siempre. */
23
+ debugSilenciados: number;
24
+ sensitiveFiles: string[];
25
+ suggestedCommit: string;
26
+ rawDiff: string;
27
+ }
28
+ export declare const SECRET_PATTERNS: Array<{
29
+ name: string;
30
+ pattern: RegExp;
31
+ }>;
32
+ export declare const SENSITIVE_FILE_PATTERN: RegExp;
33
+ export declare const DEBUG_PATTERNS: Array<{
34
+ name: string;
35
+ pattern: RegExp;
36
+ }>;
37
+ export declare function esDocumentacion(archivo: string): boolean;
38
+ /** Quita los trozos entre comillas invertidas: `asi` y ``asi``. */
39
+ export declare function sinCitasEnLinea(texto: string): string;
40
+ /**
41
+ * SE PUEDE CALLAR EL RUIDO, NUNCA UN SECRETO
42
+ *
43
+ * En un programa de terminal, `console.log` NO es un resto de depuracion: es la
44
+ * interfaz. Este repositorio tiene ocho en `src/index.ts` que son justo eso -el
45
+ * enlace de `--servir`, el aviso de que solo escucha en esta maquina- y salian
46
+ * los ocho en cada auditoria. Ocho avisos que hay que ignorar a mano cada vez
47
+ * son ocho razones para dejar de leer la seccion entera.
48
+ *
49
+ * Adivinar cual es interfaz y cual es un olvido no se puede hacer desde fuera:
50
+ * es la misma llamada. Asi que lo dice el proyecto, en un `.chocolatitoauditignore`
51
+ * al lado del `.gitignore`, una ruta o un patron por linea, y `#` para comentar.
52
+ *
53
+ * Con un limite que no se negocia: **esto solo calla la seccion de calidad**. Un
54
+ * secreto, un archivo sensible o una clave privada se avisan siempre, este la
55
+ * ruta ignorada o no. Una herramienta que se puede configurar para callarse una
56
+ * credencial es peor que no tenerla, porque da la tranquilidad sin el aviso.
57
+ *
58
+ * Y lo que se calla se cuenta: el informe dice cuantos silencio, para que nadie
59
+ * descubra el fichero un año despues sin saber que estaba puesto.
60
+ */
61
+ export declare const ARCHIVO_DE_IGNORADOS = ".chocolatitoauditignore";
62
+ export declare function leerPatronesIgnorados(cwd: string): string[];
63
+ /** Un patron de `.chocolatitoauditignore` contra una ruta del diff. */
64
+ export declare function rutaIgnorada(archivo: string, patrones: string[]): boolean;
65
+ export declare function auditDiffText(rawDiff: string, changedFiles?: string[], patronesIgnorados?: string[]): AuditReport;
66
+ export declare function auditGitDiff(cwd?: string, mockDiff?: string): Promise<AuditReport>;
67
+ export declare function suggestConventionalCommit(files: string[], _insertions: number, _deletions: number): string;
68
+ export declare function formatAuditReport(report: AuditReport): string;