chocolatito-code 1.0.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.
Files changed (140) hide show
  1. package/.mcp.json.ejemplo +19 -0
  2. package/COMPUTER-USE.md +484 -0
  3. package/LICENSE +21 -0
  4. package/README.md +186 -0
  5. package/dist/agent/context.d.ts +9 -0
  6. package/dist/agent/context.js +123 -0
  7. package/dist/agent/fileTracker.d.ts +16 -0
  8. package/dist/agent/fileTracker.js +53 -0
  9. package/dist/agent/loop.d.ts +25 -0
  10. package/dist/agent/loop.js +524 -0
  11. package/dist/agent/mentions.d.ts +11 -0
  12. package/dist/agent/mentions.js +43 -0
  13. package/dist/agent/retry.d.ts +17 -0
  14. package/dist/agent/retry.js +57 -0
  15. package/dist/agent/subagent.d.ts +2 -0
  16. package/dist/agent/subagent.js +116 -0
  17. package/dist/agent/syntaxValidator.d.ts +5 -0
  18. package/dist/agent/syntaxValidator.js +71 -0
  19. package/dist/agent/tracker.d.ts +19 -0
  20. package/dist/agent/tracker.js +38 -0
  21. package/dist/agent/undoManager.d.ts +37 -0
  22. package/dist/agent/undoManager.js +95 -0
  23. package/dist/config/constants.d.ts +77 -0
  24. package/dist/config/constants.js +146 -0
  25. package/dist/config/engine.d.ts +49 -0
  26. package/dist/config/engine.js +86 -0
  27. package/dist/config/env.d.ts +13 -0
  28. package/dist/config/env.js +103 -0
  29. package/dist/config/license.d.ts +39 -0
  30. package/dist/config/license.js +306 -0
  31. package/dist/config/permissions.d.ts +38 -0
  32. package/dist/config/permissions.js +239 -0
  33. package/dist/config/quota.d.ts +58 -0
  34. package/dist/config/quota.js +156 -0
  35. package/dist/hooks/manager.d.ts +60 -0
  36. package/dist/hooks/manager.js +193 -0
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.js +470 -0
  39. package/dist/mcp/client.d.ts +55 -0
  40. package/dist/mcp/client.js +282 -0
  41. package/dist/mcp/manager.d.ts +26 -0
  42. package/dist/mcp/manager.js +167 -0
  43. package/dist/memory/manager.d.ts +9 -0
  44. package/dist/memory/manager.js +59 -0
  45. package/dist/prompts/systemPrompt.d.ts +5 -0
  46. package/dist/prompts/systemPrompt.js +177 -0
  47. package/dist/sessions/manager.d.ts +21 -0
  48. package/dist/sessions/manager.js +54 -0
  49. package/dist/skills/manager.d.ts +14 -0
  50. package/dist/skills/manager.js +86 -0
  51. package/dist/tools/browserCdp.d.ts +26 -0
  52. package/dist/tools/browserCdp.js +610 -0
  53. package/dist/tools/browserExtension.d.ts +58 -0
  54. package/dist/tools/browserExtension.js +479 -0
  55. package/dist/tools/browserLive.d.ts +12 -0
  56. package/dist/tools/browserLive.js +265 -0
  57. package/dist/tools/changeDir.d.ts +5 -0
  58. package/dist/tools/changeDir.js +63 -0
  59. package/dist/tools/computerUse.d.ts +58 -0
  60. package/dist/tools/computerUse.js +567 -0
  61. package/dist/tools/createImage.d.ts +1 -0
  62. package/dist/tools/createImage.js +34 -0
  63. package/dist/tools/definitions.d.ts +8 -0
  64. package/dist/tools/definitions.js +401 -0
  65. package/dist/tools/deleteFile.d.ts +1 -0
  66. package/dist/tools/deleteFile.js +17 -0
  67. package/dist/tools/editFile.d.ts +5 -0
  68. package/dist/tools/editFile.js +88 -0
  69. package/dist/tools/findFiles.d.ts +1 -0
  70. package/dist/tools/findFiles.js +33 -0
  71. package/dist/tools/getSystemInfo.d.ts +1 -0
  72. package/dist/tools/getSystemInfo.js +23 -0
  73. package/dist/tools/gitTools.d.ts +3 -0
  74. package/dist/tools/gitTools.js +47 -0
  75. package/dist/tools/grepSearch.d.ts +1 -0
  76. package/dist/tools/grepSearch.js +37 -0
  77. package/dist/tools/listDir.d.ts +1 -0
  78. package/dist/tools/listDir.js +33 -0
  79. package/dist/tools/moveCopyFile.d.ts +1 -0
  80. package/dist/tools/moveCopyFile.js +21 -0
  81. package/dist/tools/runCommand.d.ts +1 -0
  82. package/dist/tools/runCommand.js +61 -0
  83. package/dist/tools/runner.d.ts +5 -0
  84. package/dist/tools/runner.js +177 -0
  85. package/dist/tools/safety.d.ts +17 -0
  86. package/dist/tools/safety.js +33 -0
  87. package/dist/tools/todoTool.d.ts +8 -0
  88. package/dist/tools/todoTool.js +27 -0
  89. package/dist/tools/toolDefsComputer.d.ts +13 -0
  90. package/dist/tools/toolDefsComputer.js +205 -0
  91. package/dist/tools/truncator.d.ts +11 -0
  92. package/dist/tools/truncator.js +24 -0
  93. package/dist/tools/viewFile.d.ts +1 -0
  94. package/dist/tools/viewFile.js +45 -0
  95. package/dist/tools/visionBridge.d.ts +37 -0
  96. package/dist/tools/visionBridge.js +107 -0
  97. package/dist/tools/webFetch.d.ts +1 -0
  98. package/dist/tools/webFetch.js +25 -0
  99. package/dist/tools/webSearch.d.ts +1 -0
  100. package/dist/tools/webSearch.js +35 -0
  101. package/dist/tools/win/hostClient.d.ts +31 -0
  102. package/dist/tools/win/hostClient.js +158 -0
  103. package/dist/tools/win/hostScript.d.ts +1 -0
  104. package/dist/tools/win/hostScript.js +925 -0
  105. package/dist/tools/writeFile.d.ts +1 -0
  106. package/dist/tools/writeFile.js +13 -0
  107. package/dist/ui/banner.d.ts +10 -0
  108. package/dist/ui/banner.js +165 -0
  109. package/dist/ui/diffViewer.d.ts +1 -0
  110. package/dist/ui/diffViewer.js +60 -0
  111. package/dist/ui/interrupt.d.ts +17 -0
  112. package/dist/ui/interrupt.js +156 -0
  113. package/dist/ui/markdownStream.d.ts +23 -0
  114. package/dist/ui/markdownStream.js +0 -0
  115. package/dist/ui/modes.d.ts +28 -0
  116. package/dist/ui/modes.js +57 -0
  117. package/dist/ui/permissionPrompt.d.ts +35 -0
  118. package/dist/ui/permissionPrompt.js +271 -0
  119. package/dist/ui/prompt.d.ts +7 -0
  120. package/dist/ui/prompt.js +466 -0
  121. package/dist/ui/reasoningStream.d.ts +6 -0
  122. package/dist/ui/reasoningStream.js +38 -0
  123. package/dist/ui/renderer.d.ts +10 -0
  124. package/dist/ui/renderer.js +142 -0
  125. package/dist/ui/spinner.d.ts +24 -0
  126. package/dist/ui/spinner.js +111 -0
  127. package/dist/ui/theme.d.ts +36 -0
  128. package/dist/ui/theme.js +37 -0
  129. package/dist/ui/typeAhead.d.ts +31 -0
  130. package/dist/ui/typeAhead.js +87 -0
  131. package/extension/README.md +74 -0
  132. package/extension/background.js +575 -0
  133. package/extension/content.js +446 -0
  134. package/extension/manifest.json +36 -0
  135. package/extension/popup.html +22 -0
  136. package/extension/popup.js +12 -0
  137. package/package.json +66 -0
  138. package/skills/complex-refactor/SKILL.md +13 -0
  139. package/skills/deep-debugger/SKILL.md +14 -0
  140. package/skills/software-architect/SKILL.md +20 -0
@@ -0,0 +1,401 @@
1
+ import { BROWSER_TOOL, COMPUTER_USE_TOOL, CHROME_TOOL } from "./toolDefsComputer.js";
2
+ import { mcpManager } from "../mcp/manager.js";
3
+ export const TOOLS = [
4
+ {
5
+ type: "function",
6
+ function: {
7
+ name: "todo_write",
8
+ description: "Crea o actualiza la lista de tareas del proyecto visible para el usuario (con estado 'pending', 'in_progress' o 'completed').",
9
+ parameters: {
10
+ type: "object",
11
+ properties: {
12
+ tasks: {
13
+ type: "array",
14
+ items: {
15
+ type: "object",
16
+ properties: {
17
+ text: {
18
+ type: "string",
19
+ description: "Descripción de la tarea.",
20
+ },
21
+ status: {
22
+ type: "string",
23
+ enum: ["pending", "in_progress", "completed"],
24
+ description: "Estado de la tarea.",
25
+ },
26
+ },
27
+ required: ["text", "status"],
28
+ },
29
+ description: "Lista de tareas estructuradas.",
30
+ },
31
+ },
32
+ required: ["tasks"],
33
+ },
34
+ },
35
+ },
36
+ {
37
+ type: "function",
38
+ function: {
39
+ name: "use_skill",
40
+ description: "Carga las instrucciones completas y recursos de un skill especializado por su nombre.",
41
+ parameters: {
42
+ type: "object",
43
+ properties: {
44
+ skillName: {
45
+ type: "string",
46
+ description: "El nombre del skill a cargar (ej. 'chocolatito-video', 'artifact-design').",
47
+ },
48
+ },
49
+ required: ["skillName"],
50
+ },
51
+ },
52
+ },
53
+ {
54
+ type: "function",
55
+ function: {
56
+ name: "save_memory",
57
+ description: "Guarda un hecho importante, preferencia del usuario o aprendizaje en la memoria persistente (~/.chocolatito/memory/).",
58
+ parameters: {
59
+ type: "object",
60
+ properties: {
61
+ topic: {
62
+ type: "string",
63
+ description: "Tema o categoría (ej. 'preferencias_usuario', 'arquitectura_proyecto').",
64
+ },
65
+ fact: {
66
+ type: "string",
67
+ description: "El hecho o conocimiento a recordar en futuras sesiones.",
68
+ },
69
+ },
70
+ required: ["topic", "fact"],
71
+ },
72
+ },
73
+ },
74
+ {
75
+ type: "function",
76
+ function: {
77
+ name: "read_memory",
78
+ description: "Lee un archivo de memoria persistente existente por su tema.",
79
+ parameters: {
80
+ type: "object",
81
+ properties: {
82
+ topic: {
83
+ type: "string",
84
+ description: "El tema o nombre del archivo de memoria a consultar.",
85
+ },
86
+ },
87
+ required: ["topic"],
88
+ },
89
+ },
90
+ },
91
+ {
92
+ type: "function",
93
+ function: {
94
+ name: "spawn_agent",
95
+ description: "Lanza un subagente autónomo en un contexto aislado para realizar una tarea de búsqueda o planificación sin saturar la memoria principal.",
96
+ parameters: {
97
+ type: "object",
98
+ properties: {
99
+ type: {
100
+ type: "string",
101
+ enum: ["explore", "plan", "general"],
102
+ description: "Tipo de subagente: 'explore' (búsqueda e investigación read-only), 'plan' (arquitectura), 'general' (tarea de trabajo).",
103
+ },
104
+ prompt: {
105
+ type: "string",
106
+ description: "La instrucción precisa para el subagente.",
107
+ },
108
+ },
109
+ required: ["type", "prompt"],
110
+ },
111
+ },
112
+ },
113
+ CHROME_TOOL,
114
+ BROWSER_TOOL,
115
+ COMPUTER_USE_TOOL,
116
+ {
117
+ type: "function",
118
+ function: {
119
+ name: "change_dir",
120
+ description: "Cambia el directorio de trabajo activo (equivalente a 'cd') con búsqueda profunda automática.",
121
+ parameters: {
122
+ type: "object",
123
+ properties: {
124
+ path: {
125
+ type: "string",
126
+ description: "Ruta del directorio al que se desea entrar.",
127
+ },
128
+ },
129
+ required: ["path"],
130
+ },
131
+ },
132
+ },
133
+ {
134
+ type: "function",
135
+ function: {
136
+ name: "find_files",
137
+ description: "Busca archivos y carpetas por nombre o patrón glob (ej. '*.tsx', 'claude', 'package.json') en cualquier directorio.",
138
+ parameters: {
139
+ type: "object",
140
+ properties: {
141
+ pattern: {
142
+ type: "string",
143
+ description: "Patrón o nombre del archivo o carpeta a buscar.",
144
+ },
145
+ searchDirectory: {
146
+ type: "string",
147
+ description: "Directorio base donde buscar.",
148
+ },
149
+ },
150
+ required: ["pattern"],
151
+ },
152
+ },
153
+ },
154
+ {
155
+ type: "function",
156
+ function: {
157
+ name: "view_file",
158
+ description: "Lee el contenido de un archivo en el disco con numeración de líneas.",
159
+ parameters: {
160
+ type: "object",
161
+ properties: {
162
+ path: {
163
+ type: "string",
164
+ description: "Ruta del archivo a leer.",
165
+ },
166
+ startLine: {
167
+ type: "integer",
168
+ description: "Línea inicial (opcional).",
169
+ },
170
+ endLine: {
171
+ type: "integer",
172
+ description: "Línea final (opcional).",
173
+ },
174
+ },
175
+ required: ["path"],
176
+ },
177
+ },
178
+ },
179
+ {
180
+ type: "function",
181
+ function: {
182
+ name: "edit_file",
183
+ description: "Reemplaza un bloque CONTIGUO exacto de texto en un archivo existente mostrando diffs.",
184
+ parameters: {
185
+ type: "object",
186
+ properties: {
187
+ path: {
188
+ type: "string",
189
+ description: "Ruta del archivo a modificar.",
190
+ },
191
+ oldText: {
192
+ type: "string",
193
+ description: "El bloque exacto actual a reemplazar.",
194
+ },
195
+ newText: {
196
+ type: "string",
197
+ description: "El nuevo texto que reemplazará a oldText.",
198
+ },
199
+ },
200
+ required: ["path", "oldText", "newText"],
201
+ },
202
+ },
203
+ },
204
+ {
205
+ type: "function",
206
+ function: {
207
+ name: "write_file",
208
+ description: "Crea un archivo nuevo o sobreescribe uno existente con el contenido provisto.",
209
+ parameters: {
210
+ type: "object",
211
+ properties: {
212
+ path: {
213
+ type: "string",
214
+ description: "Ruta del archivo a crear o sobreescribir.",
215
+ },
216
+ content: {
217
+ type: "string",
218
+ description: "El contenido completo del archivo.",
219
+ },
220
+ },
221
+ required: ["path", "content"],
222
+ },
223
+ },
224
+ },
225
+ {
226
+ type: "function",
227
+ function: {
228
+ name: "delete_file",
229
+ description: "Elimina un archivo o directorio de forma segura.",
230
+ parameters: {
231
+ type: "object",
232
+ properties: {
233
+ path: {
234
+ type: "string",
235
+ description: "Ruta del archivo o carpeta a eliminar.",
236
+ },
237
+ },
238
+ required: ["path"],
239
+ },
240
+ },
241
+ },
242
+ {
243
+ type: "function",
244
+ function: {
245
+ name: "move_copy_file",
246
+ description: "Mueve, renombra o copia archivos y directorios.",
247
+ parameters: {
248
+ type: "object",
249
+ properties: {
250
+ sourcePath: {
251
+ type: "string",
252
+ description: "Ruta de origen.",
253
+ },
254
+ destinationPath: {
255
+ type: "string",
256
+ description: "Ruta de destino.",
257
+ },
258
+ operation: {
259
+ type: "string",
260
+ enum: ["move", "copy"],
261
+ description: "Operación a realizar.",
262
+ },
263
+ },
264
+ required: ["sourcePath", "destinationPath"],
265
+ },
266
+ },
267
+ },
268
+ {
269
+ type: "function",
270
+ function: {
271
+ name: "run_command",
272
+ description: "Ejecuta un comando en la terminal del sistema (PowerShell en Windows, Bash en Unix).",
273
+ parameters: {
274
+ type: "object",
275
+ properties: {
276
+ command: {
277
+ type: "string",
278
+ description: "El comando exacto a ejecutar.",
279
+ },
280
+ timeout: {
281
+ type: "integer",
282
+ description: "Tiempo maximo en ms (por defecto 120000, maximo 600000). Subelo para instalaciones, compilaciones o suites de tests largas.",
283
+ },
284
+ },
285
+ required: ["command"],
286
+ },
287
+ },
288
+ },
289
+ {
290
+ type: "function",
291
+ function: {
292
+ name: "list_dir",
293
+ description: "Lista los archivos y subdirectorios de una carpeta con tamaños.",
294
+ parameters: {
295
+ type: "object",
296
+ properties: {
297
+ dirPath: {
298
+ type: "string",
299
+ description: "Ruta del directorio a listar.",
300
+ },
301
+ },
302
+ },
303
+ },
304
+ },
305
+ {
306
+ type: "function",
307
+ function: {
308
+ name: "grep_search",
309
+ description: "Busca un patrón de texto o regex dentro de los archivos del proyecto.",
310
+ parameters: {
311
+ type: "object",
312
+ properties: {
313
+ query: {
314
+ type: "string",
315
+ description: "El texto o expresión regular a buscar.",
316
+ },
317
+ searchPath: {
318
+ type: "string",
319
+ description: "Ruta donde buscar.",
320
+ },
321
+ },
322
+ required: ["query"],
323
+ },
324
+ },
325
+ },
326
+ {
327
+ type: "function",
328
+ function: {
329
+ name: "web_search",
330
+ description: "Busca información, documentación o librerías en la web.",
331
+ parameters: {
332
+ type: "object",
333
+ properties: {
334
+ query: {
335
+ type: "string",
336
+ description: "El término de búsqueda.",
337
+ },
338
+ },
339
+ required: ["query"],
340
+ },
341
+ },
342
+ },
343
+ {
344
+ type: "function",
345
+ function: {
346
+ name: "web_fetch",
347
+ description: "Descarga y lee contenido de texto de una URL.",
348
+ parameters: {
349
+ type: "object",
350
+ properties: {
351
+ url: {
352
+ type: "string",
353
+ description: "La URL a consultar.",
354
+ },
355
+ },
356
+ required: ["url"],
357
+ },
358
+ },
359
+ },
360
+ {
361
+ type: "function",
362
+ function: {
363
+ name: "create_image",
364
+ description: "Genera imágenes o ilustraciones (Python Pillow/Matplotlib o SVG).",
365
+ parameters: {
366
+ type: "object",
367
+ properties: {
368
+ outputPath: {
369
+ type: "string",
370
+ description: "Ruta de salida.",
371
+ },
372
+ generatorScript: {
373
+ type: "string",
374
+ description: "Código Python o SVG.",
375
+ },
376
+ },
377
+ required: ["outputPath", "generatorScript"],
378
+ },
379
+ },
380
+ },
381
+ {
382
+ type: "function",
383
+ function: {
384
+ name: "get_system_info",
385
+ description: "Obtiene diagnóstico del sistema y estado de Git.",
386
+ parameters: {
387
+ type: "object",
388
+ properties: {},
389
+ },
390
+ },
391
+ },
392
+ ];
393
+ /**
394
+ * Herramientas que ve el modelo: las nativas mas las que publiquen los
395
+ * servidores MCP conectados. Se calcula en cada turno porque un servidor puede
396
+ * conectarse o caerse a mitad de sesion.
397
+ */
398
+ export function getAllTools() {
399
+ const mcp = mcpManager.getToolDefinitions();
400
+ return mcp.length > 0 ? [...TOOLS, ...mcp] : TOOLS;
401
+ }
@@ -0,0 +1 @@
1
+ export declare function deleteFile(targetPath: string, cwd?: string): Promise<string>;
@@ -0,0 +1,17 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ export async function deleteFile(targetPath, cwd = process.cwd()) {
4
+ const resolved = path.isAbsolute(targetPath) ? targetPath : path.resolve(cwd, targetPath);
5
+ if (!fs.existsSync(resolved)) {
6
+ return `Error: La ruta "${targetPath}" no existe.`;
7
+ }
8
+ const stat = fs.statSync(resolved);
9
+ if (stat.isDirectory()) {
10
+ fs.rmSync(resolved, { recursive: true, force: true });
11
+ return `✔ Directorio "${targetPath}" y su contenido eliminados exitosamente.`;
12
+ }
13
+ else {
14
+ fs.unlinkSync(resolved);
15
+ return `✔ Archivo "${targetPath}" eliminado exitosamente.`;
16
+ }
17
+ }
@@ -0,0 +1,5 @@
1
+ export declare function editFile(filePath: string, oldText: string, newText: string, cwd?: string): Promise<{
2
+ success: boolean;
3
+ message: string;
4
+ diffText?: string;
5
+ }>;
@@ -0,0 +1,88 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { formatNumberedDiff } from "../ui/diffViewer.js";
4
+ export async function editFile(filePath, oldText, newText, cwd = process.cwd()) {
5
+ const resolved = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
6
+ if (!fs.existsSync(resolved)) {
7
+ return {
8
+ success: false,
9
+ message: `Error: El archivo "${filePath}" no existe.`,
10
+ };
11
+ }
12
+ const currentContent = fs.readFileSync(resolved, "utf-8");
13
+ // Normalize line endings for comparison
14
+ const normalizedCurrent = currentContent.replace(/\r\n/g, "\n");
15
+ const normalizedOld = oldText.replace(/\r\n/g, "\n");
16
+ const normalizedNew = newText.replace(/\r\n/g, "\n");
17
+ let matchIndex = normalizedCurrent.indexOf(normalizedOld);
18
+ let finalOldText = normalizedOld;
19
+ // Si el fragmento aparece varias veces, editar la primera ocurrencia es una
20
+ // apuesta: puede tocar la funcion equivocada y el usuario no se entera hasta
21
+ // mucho despues. Mejor negarse y pedir mas contexto.
22
+ if (matchIndex !== -1 && normalizedOld.length > 0) {
23
+ let count = 0;
24
+ let from = 0;
25
+ while (true) {
26
+ const at = normalizedCurrent.indexOf(normalizedOld, from);
27
+ if (at === -1)
28
+ break;
29
+ count++;
30
+ if (count > 1)
31
+ break;
32
+ from = at + normalizedOld.length;
33
+ }
34
+ if (count > 1) {
35
+ return {
36
+ success: false,
37
+ message: `Error: el fragmento aparece mas de una vez en "${filePath}". No voy a adivinar cual. ` +
38
+ `Incluye lineas de alrededor para que el fragmento sea unico.`,
39
+ };
40
+ }
41
+ }
42
+ // Fallback: If exact match fails, try line-by-line trimmed matching
43
+ if (matchIndex === -1) {
44
+ const fileLines = normalizedCurrent.split("\n");
45
+ const targetLines = normalizedOld.split("\n").map((l) => l.trimEnd());
46
+ let foundLineIdx = -1;
47
+ for (let i = 0; i <= fileLines.length - targetLines.length; i++) {
48
+ let isMatch = true;
49
+ for (let j = 0; j < targetLines.length; j++) {
50
+ if (fileLines[i + j].trimEnd() !== targetLines[j]) {
51
+ isMatch = false;
52
+ break;
53
+ }
54
+ }
55
+ if (isMatch) {
56
+ if (foundLineIdx === -1) {
57
+ foundLineIdx = i;
58
+ }
59
+ else {
60
+ // Multiple ambiguous matches found, don't guess
61
+ foundLineIdx = -2;
62
+ break;
63
+ }
64
+ }
65
+ }
66
+ if (foundLineIdx >= 0) {
67
+ const matchedBlock = fileLines.slice(foundLineIdx, foundLineIdx + targetLines.length).join("\n");
68
+ matchIndex = normalizedCurrent.indexOf(matchedBlock);
69
+ finalOldText = matchedBlock;
70
+ }
71
+ }
72
+ if (matchIndex === -1) {
73
+ return {
74
+ success: false,
75
+ message: `Error: No se encontró el fragmento de texto en "${filePath}". Asegúrate de copiar las líneas exactas a reemplazar.`,
76
+ };
77
+ }
78
+ // Calculate real starting line number in the original file
79
+ const startLine = normalizedCurrent.slice(0, matchIndex).split("\n").length;
80
+ const updatedContent = normalizedCurrent.slice(0, matchIndex) + normalizedNew + normalizedCurrent.slice(matchIndex + finalOldText.length);
81
+ fs.writeFileSync(resolved, updatedContent, "utf-8");
82
+ const diffText = formatNumberedDiff(path.relative(cwd, resolved) || filePath, finalOldText, normalizedNew, startLine);
83
+ return {
84
+ success: true,
85
+ message: `✔ Archivo "${filePath}" editado exitosamente (Línea ${startLine}+).`,
86
+ diffText,
87
+ };
88
+ }
@@ -0,0 +1 @@
1
+ export declare function findFiles(pattern: string, searchDirectory?: string, cwd?: string): Promise<string>;
@@ -0,0 +1,33 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import fg from "fast-glob";
4
+ export async function findFiles(pattern, searchDirectory = process.cwd(), cwd = process.cwd()) {
5
+ const resolvedDir = path.isAbsolute(searchDirectory)
6
+ ? searchDirectory
7
+ : path.resolve(cwd, searchDirectory);
8
+ if (!fs.existsSync(resolvedDir)) {
9
+ return `Error: La carpeta "${searchDirectory}" no existe.`;
10
+ }
11
+ const matches = await fg([pattern.includes("*") ? pattern : `**/*${pattern}*`], {
12
+ cwd: resolvedDir,
13
+ dot: true,
14
+ onlyFiles: false,
15
+ deep: 6,
16
+ ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/AppData/**", "**/__pycache__/**"],
17
+ });
18
+ if (matches.length === 0) {
19
+ return `No se encontraron archivos ni carpetas con el patrón "${pattern}" en "${resolvedDir}".`;
20
+ }
21
+ const formatted = matches.slice(0, 40).map((relPath) => {
22
+ const full = path.join(resolvedDir, relPath);
23
+ try {
24
+ const isDir = fs.statSync(full).isDirectory();
25
+ return `${isDir ? "[DIR] " : "[FILE]"} ${relPath}`;
26
+ }
27
+ catch {
28
+ return `[ITEM] ${relPath}`;
29
+ }
30
+ });
31
+ const totalStr = matches.length > 40 ? ` (mostrando primeros 40 de ${matches.length})` : "";
32
+ return `Resultados encontrados para "${pattern}" en "${resolvedDir}"${totalStr}:\n${formatted.join("\n")}`;
33
+ }
@@ -0,0 +1 @@
1
+ export declare function getSystemInfo(cwd?: string): Promise<string>;
@@ -0,0 +1,23 @@
1
+ import os from "node:os";
2
+ import { execa } from "execa";
3
+ export async function getSystemInfo(cwd = process.cwd()) {
4
+ const nodeVersion = process.version;
5
+ const platform = `${os.type()} ${os.release()} (${os.arch()})`;
6
+ const memoryFree = `${(os.freemem() / (1024 * 1024 * 1024)).toFixed(1)} GB`;
7
+ const memoryTotal = `${(os.totalmem() / (1024 * 1024 * 1024)).toFixed(1)} GB`;
8
+ let gitInfo = "Git no disponible o fuera de repositorio.";
9
+ try {
10
+ const { stdout: status } = await execa("git", ["status", "--short"], { cwd, reject: false });
11
+ const { stdout: branch } = await execa("git", ["branch", "--show-current"], { cwd, reject: false });
12
+ gitInfo = `Rama: ${branch.trim() || "HEAD"}\nCambios:\n${status.trim() || "Directorio limpio (sin cambios pendientes)."}`;
13
+ }
14
+ catch { }
15
+ return [
16
+ `--- INFORMACIÓN DEL SISTEMA ---`,
17
+ `Plataforma: ${platform}`,
18
+ `Node.js: ${nodeVersion}`,
19
+ `Memoria: ${memoryFree} libre de ${memoryTotal}`,
20
+ `Directorio actual: ${cwd}`,
21
+ `Estado Git:\n${gitInfo}`,
22
+ ].join("\n");
23
+ }
@@ -0,0 +1,3 @@
1
+ export declare function gitStatus(cwd?: string): Promise<string>;
2
+ export declare function gitDiff(staged?: boolean, cwd?: string): Promise<string>;
3
+ export declare function gitCommit(message: string, addAll?: boolean, cwd?: string): Promise<string>;
@@ -0,0 +1,47 @@
1
+ import { execa } from "execa";
2
+ export async function gitStatus(cwd = process.cwd()) {
3
+ try {
4
+ const { stdout: status } = await execa("git", ["status", "--short"], { cwd, reject: false });
5
+ const { stdout: branch } = await execa("git", ["branch", "--show-current"], { cwd, reject: false });
6
+ const { stdout: lastLog } = await execa("git", ["log", "-n", "3", "--oneline"], { cwd, reject: false });
7
+ return [
8
+ `--- ESTADO DE GIT ---`,
9
+ `Rama actual: ${branch.trim() || "HEAD (sin rama)"}`,
10
+ `Archivos modificados/nuevos:\n${status.trim() || "Repositorio limpio (sin cambios pendientes)."}\n`,
11
+ `Últimos commits:\n${lastLog.trim() || "Sin historial de commits."}`,
12
+ ].join("\n");
13
+ }
14
+ catch (err) {
15
+ return `Error consultando estado de Git: ${err?.message || String(err)}`;
16
+ }
17
+ }
18
+ export async function gitDiff(staged = false, cwd = process.cwd()) {
19
+ try {
20
+ const args = ["diff"];
21
+ if (staged)
22
+ args.push("--staged");
23
+ const { stdout } = await execa("git", args, { cwd, reject: false });
24
+ if (!stdout.trim()) {
25
+ return staged ? "No hay cambios preparados (staged)." : "No hay cambios sin preparar (unstaged).";
26
+ }
27
+ return stdout.slice(0, 12_000);
28
+ }
29
+ catch (err) {
30
+ return `Error obteniendo git diff: ${err?.message || String(err)}`;
31
+ }
32
+ }
33
+ export async function gitCommit(message, addAll = true, cwd = process.cwd()) {
34
+ try {
35
+ if (addAll) {
36
+ await execa("git", ["add", "-A"], { cwd, reject: false });
37
+ }
38
+ const { stdout, stderr, exitCode } = await execa("git", ["commit", "-m", message], { cwd, reject: false });
39
+ if (exitCode !== 0) {
40
+ return `Fallo al hacer commit:\n${stderr || stdout}`;
41
+ }
42
+ return `✔ Commit creado exitosamente: "${message}"\n${stdout}`;
43
+ }
44
+ catch (err) {
45
+ return `Error creando commit: ${err?.message || String(err)}`;
46
+ }
47
+ }
@@ -0,0 +1 @@
1
+ export declare function grepSearch(query: string, searchPath?: string, cwd?: string): Promise<string>;
@@ -0,0 +1,37 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import fg from "fast-glob";
4
+ export async function grepSearch(query, searchPath = ".", cwd = process.cwd()) {
5
+ const resolved = path.isAbsolute(searchPath) ? searchPath : path.resolve(cwd, searchPath);
6
+ if (!fs.existsSync(resolved)) {
7
+ return `Error: La ruta "${searchPath}" no existe.`;
8
+ }
9
+ const files = await fg(["**/*"], {
10
+ cwd: resolved,
11
+ onlyFiles: true,
12
+ ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/*.lock", "**/*.png", "**/*.jpg", "**/*.mp4", "**/*.webm", "**/*.zip", "**/*.bin"],
13
+ });
14
+ const matches = [];
15
+ const regex = new RegExp(query, "i");
16
+ for (const relFile of files) {
17
+ if (matches.length >= 30)
18
+ break; // Limit to 30 matches
19
+ const fullPath = path.join(resolved, relFile);
20
+ try {
21
+ const content = fs.readFileSync(fullPath, "utf-8");
22
+ const lines = content.split(/\r?\n/);
23
+ lines.forEach((line, idx) => {
24
+ if (regex.test(line) && matches.length < 30) {
25
+ matches.push(`${relFile}:${idx + 1} | ${line.trim()}`);
26
+ }
27
+ });
28
+ }
29
+ catch {
30
+ // Ignore binary files or read errors
31
+ }
32
+ }
33
+ if (matches.length === 0) {
34
+ return `No se encontraron coincidencias para "${query}" en "${searchPath}".`;
35
+ }
36
+ return `Coincidencias encontradas (${matches.length}):\n${matches.join("\n")}`;
37
+ }
@@ -0,0 +1 @@
1
+ export declare function listDir(dirPath?: string, cwd?: string): Promise<string>;