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,265 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ import puppeteer from "puppeteer";
5
+ import { execa } from "execa";
6
+ let globalBrowser = null;
7
+ let globalPage = null;
8
+ let consoleLogs = [];
9
+ let networkErrors = [];
10
+ export async function browserLive(params, cwd = process.cwd()) {
11
+ const { action, url, selector, text, script, outputPath, headless = false, profileDirectory } = params;
12
+ try {
13
+ // 0. Handle open_system: Opens the URL directly in the user's real Chrome profile without guest isolation
14
+ if (action === "open_system") {
15
+ const targetUrl = url || "https://labs.google/fx/tools/flow";
16
+ const profile = profileDirectory || "Profile 1"; // Profile 1 is the main user profile with active Google session
17
+ try {
18
+ if (process.platform === "win32") {
19
+ execa("cmd.exe", ["/c", "start", "", "chrome.exe", `--profile-directory=${profile}`, targetUrl], {
20
+ detached: true,
21
+ stdio: "ignore",
22
+ }).unref();
23
+ }
24
+ else if (process.platform === "darwin") {
25
+ execa("open", ["-a", "Google Chrome", "--args", `--profile-directory=${profile}`, targetUrl], {
26
+ detached: true,
27
+ stdio: "ignore",
28
+ }).unref();
29
+ }
30
+ else {
31
+ execa("google-chrome", [`--profile-directory=${profile}`, targetUrl], {
32
+ detached: true,
33
+ stdio: "ignore",
34
+ }).unref();
35
+ }
36
+ return `✔ URL "${targetUrl}" abierta de forma segura en Chrome con el perfil "${profile}".`;
37
+ }
38
+ catch (err) {
39
+ return `Fallo al abrir Chrome del sistema: ${err?.message || String(err)}`;
40
+ }
41
+ }
42
+ // 1. Ensure persistent browser profile directory exists
43
+ const persistentDataDir = params.userDataDir || path.join(os.homedir(), ".chocolatito", "browser-data");
44
+ if (!fs.existsSync(persistentDataDir)) {
45
+ fs.mkdirSync(persistentDataDir, { recursive: true });
46
+ }
47
+ // 2. Ensure browser is open if needed
48
+ if (action !== "close" && (!globalBrowser || !globalBrowser.connected)) {
49
+ consoleLogs = [];
50
+ networkErrors = [];
51
+ const launchArgs = [
52
+ "--no-sandbox",
53
+ "--disable-setuid-sandbox",
54
+ "--start-maximized",
55
+ ];
56
+ if (profileDirectory) {
57
+ launchArgs.push(`--profile-directory=${profileDirectory}`);
58
+ }
59
+ try {
60
+ globalBrowser = await puppeteer.launch({
61
+ headless: headless ? "shell" : false,
62
+ userDataDir: persistentDataDir,
63
+ defaultViewport: null,
64
+ args: launchArgs,
65
+ });
66
+ }
67
+ catch {
68
+ globalBrowser = await puppeteer.launch({
69
+ channel: "chrome",
70
+ headless: headless ? "shell" : false,
71
+ userDataDir: persistentDataDir,
72
+ defaultViewport: null,
73
+ args: launchArgs,
74
+ });
75
+ }
76
+ const pages = await globalBrowser.pages();
77
+ globalPage = pages.length > 0 ? pages[0] : await globalBrowser.newPage();
78
+ globalPage.on("console", (msg) => {
79
+ consoleLogs.push({
80
+ type: msg.type(),
81
+ text: msg.text(),
82
+ time: new Date().toLocaleTimeString(),
83
+ });
84
+ });
85
+ globalPage.on("pageerror", (err) => {
86
+ consoleLogs.push({
87
+ type: "error",
88
+ text: `[Page Error]: ${err?.message || String(err)}`,
89
+ time: new Date().toLocaleTimeString(),
90
+ });
91
+ });
92
+ globalPage.on("requestfailed", (req) => {
93
+ networkErrors.push(`[${req.method()}] ${req.url()} - ${req.failure()?.errorText || "FAILED"}`);
94
+ });
95
+ }
96
+ // 3. Dispatch specific browser actions
97
+ switch (action) {
98
+ case "launch": {
99
+ const target = url || "http://localhost:3000";
100
+ await globalPage.goto(target, { waitUntil: "domcontentloaded", timeout: 20_000 });
101
+ const title = await globalPage.title();
102
+ return `✔ Navegador en vivo iniciado en "${target}" (Título: "${title}").`;
103
+ }
104
+ case "navigate": {
105
+ if (!url)
106
+ return "Error: Se requiere 'url' para navegar.";
107
+ await globalPage.goto(url, { waitUntil: "domcontentloaded", timeout: 25_000 });
108
+ const title = await globalPage.title();
109
+ return `✔ Navegador en tiempo real abierto en "${url}" (Título: "${title}").`;
110
+ }
111
+ case "click": {
112
+ if (!selector)
113
+ return "Error: Se requiere un 'selector' CSS o texto para hacer clic.";
114
+ await globalPage.waitForSelector(selector, { timeout: 8_000 });
115
+ // Inject visual click ripple in the DOM
116
+ await globalPage.evaluate((sel) => {
117
+ // @ts-ignore
118
+ const el = document.querySelector(sel);
119
+ if (el) {
120
+ const rect = el.getBoundingClientRect();
121
+ // @ts-ignore
122
+ const dot = document.createElement("div");
123
+ dot.style.position = "fixed";
124
+ dot.style.left = `${rect.left + rect.width / 2 - 16}px`;
125
+ dot.style.top = `${rect.top + rect.height / 2 - 16}px`;
126
+ dot.style.width = "32px";
127
+ dot.style.height = "32px";
128
+ dot.style.borderRadius = "50%";
129
+ dot.style.background = "rgba(235, 87, 87, 0.5)";
130
+ dot.style.border = "3px solid #EB5757";
131
+ dot.style.boxShadow = "0 0 16px #A855F7";
132
+ dot.style.zIndex = "2147483647";
133
+ dot.style.pointerEvents = "none";
134
+ dot.style.transition = "transform 0.4s ease-out, opacity 0.4s ease-out";
135
+ // @ts-ignore
136
+ document.body.appendChild(dot);
137
+ setTimeout(() => {
138
+ dot.style.transform = "scale(2.2)";
139
+ dot.style.opacity = "0";
140
+ }, 30);
141
+ setTimeout(() => dot.remove(), 450);
142
+ }
143
+ }, selector);
144
+ await globalPage.click(selector);
145
+ return `✔ Clic ejecutado sobre "${selector}" con efecto visual de cursor activo.`;
146
+ }
147
+ case "type": {
148
+ if (!selector || text === undefined)
149
+ return "Error: Se requiere 'selector' y 'text'.";
150
+ await globalPage.waitForSelector(selector, { timeout: 8_000 });
151
+ // Highlight input field
152
+ await globalPage.evaluate((sel) => {
153
+ const el = document.querySelector(sel);
154
+ if (el) {
155
+ el.style.outline = "3px solid #EB5757";
156
+ el.style.boxShadow = "0 0 12px rgba(235, 87, 87, 0.6)";
157
+ }
158
+ }, selector);
159
+ await globalPage.type(selector, text);
160
+ return `✔ Texto "${text}" escrito en "${selector}".`;
161
+ }
162
+ case "screenshot": {
163
+ const cacheDir = path.join(os.homedir(), ".chocolatito", "cache");
164
+ if (!fs.existsSync(cacheDir))
165
+ fs.mkdirSync(cacheDir, { recursive: true });
166
+ const out = outputPath
167
+ ? (path.isAbsolute(outputPath) ? outputPath : path.resolve(cwd, outputPath))
168
+ : path.join(cacheDir, "browser_latest.png");
169
+ const outDir = path.dirname(out);
170
+ if (!fs.existsSync(outDir))
171
+ fs.mkdirSync(outDir, { recursive: true });
172
+ // Inject visible glowing mouse cursor indicator in DOM
173
+ await globalPage.evaluate(() => {
174
+ let cursor = document.getElementById("__chocolatito_cursor__");
175
+ if (!cursor) {
176
+ cursor = document.createElement("div");
177
+ cursor.id = "__chocolatito_cursor__";
178
+ cursor.style.position = "fixed";
179
+ cursor.style.width = "30px";
180
+ cursor.style.height = "30px";
181
+ cursor.style.borderRadius = "50%";
182
+ cursor.style.border = "3px solid #EB5757";
183
+ cursor.style.backgroundColor = "rgba(255, 120, 80, 0.45)";
184
+ cursor.style.boxShadow = "0 0 12px #EB5757";
185
+ cursor.style.pointerEvents = "none";
186
+ cursor.style.zIndex = "2147483647";
187
+ cursor.style.transform = "translate(-50%, -50%)";
188
+ cursor.style.top = "50%";
189
+ cursor.style.left = "50%";
190
+ document.body.appendChild(cursor);
191
+ }
192
+ });
193
+ await globalPage.screenshot({ path: out, fullPage: false });
194
+ const displayPath = outputPath ? path.relative(cwd, out) || out : out;
195
+ return `✔ Captura en vivo del navegador guardada con cursor visible en "${displayPath}" (${(fs.statSync(out).size / 1024).toFixed(1)} KB).`;
196
+ }
197
+ case "evaluate": {
198
+ if (!script)
199
+ return "Error: Se requiere un 'script' JavaScript para evaluar en la consola.";
200
+ const result = await globalPage.evaluate((code) => {
201
+ try {
202
+ // @ts-ignore
203
+ return window.eval(code);
204
+ }
205
+ catch (e) {
206
+ return `Error JS: ${e?.message || String(e)}`;
207
+ }
208
+ }, script);
209
+ return `✔ Salida de consola JS:\n${typeof result === "object" ? JSON.stringify(result, null, 2) : String(result)}`;
210
+ }
211
+ case "get_interactive_elements": {
212
+ const elements = await globalPage.evaluate(() => {
213
+ const res = [];
214
+ const candidates = document.querySelectorAll("button, a, input, textarea, [role='button']");
215
+ candidates.forEach((el) => {
216
+ const rect = el.getBoundingClientRect();
217
+ if (rect.width > 0 && rect.height > 0 && rect.top >= 0) {
218
+ const text = (el.textContent || el.value || el.placeholder || "").trim().slice(0, 40);
219
+ const tag = el.tagName.toLowerCase();
220
+ const id = el.id ? `#${el.id}` : "";
221
+ const cls = el.className && typeof el.className === "string" ? `.${el.className.trim().split(/\s+/)[0]}` : "";
222
+ const selector = id || `${tag}${cls}` || tag;
223
+ res.push({ tag, text, selector, rect: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) } });
224
+ }
225
+ });
226
+ return res.slice(0, 25);
227
+ });
228
+ const list = elements.map((e) => `- [${e.tag}] "${e.text}" -> Selector: \`${e.selector}\` en (X: ${e.rect.x + Math.round(e.rect.width / 2)}, Y: ${e.rect.y + Math.round(e.rect.height / 2)})`).join("\n");
229
+ return `--- ELEMENTOS INTERACTIVOS DETECTADOS ---\n${list || "No se encontraron elementos interactivos visibles."}`;
230
+ }
231
+ case "get_console_logs": {
232
+ const recentLogs = consoleLogs.slice(-20);
233
+ const recentErrors = networkErrors.slice(-10);
234
+ if (recentLogs.length === 0 && recentErrors.length === 0) {
235
+ return "Consola del navegador limpia: Sin errores ni logs registrados.";
236
+ }
237
+ const logLines = recentLogs.map((l) => `[${l.time}] [${l.type.toUpperCase()}] ${l.text}`).join("\n");
238
+ const errLines = recentErrors.length > 0 ? `\n\nErrores de Red:\n${recentErrors.join("\n")}` : "";
239
+ return `--- REGISTRO DE CONSOLA Y DEPURACIÓN EN VIVO ---\n${logLines}${errLines}`;
240
+ }
241
+ case "get_content": {
242
+ const textContent = await globalPage.evaluate(() => {
243
+ // @ts-ignore
244
+ return document.body.innerText;
245
+ });
246
+ const title = await globalPage.title();
247
+ const url = globalPage.url();
248
+ return `Página: "${title}" (${url})\n\nContenido visible:\n${textContent.slice(0, 5_000)}`;
249
+ }
250
+ case "close": {
251
+ if (globalBrowser) {
252
+ await globalBrowser.close();
253
+ globalBrowser = null;
254
+ globalPage = null;
255
+ }
256
+ return "✔ Navegador cerrado exitosamente.";
257
+ }
258
+ default:
259
+ return `Acción no reconocida: ${action}`;
260
+ }
261
+ }
262
+ catch (err) {
263
+ return `Error en control de navegador (${action}): ${err?.message || String(err)}`;
264
+ }
265
+ }
@@ -0,0 +1,5 @@
1
+ export declare function changeDir(targetPath: string, currentCwd?: string): Promise<{
2
+ success: boolean;
3
+ newCwd: string;
4
+ message: string;
5
+ }>;
@@ -0,0 +1,63 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ import fg from "fast-glob";
5
+ export async function changeDir(targetPath, currentCwd = process.cwd()) {
6
+ const home = os.homedir();
7
+ const cleanedTarget = targetPath.trim().replace(/^['"]|['"]$/g, "");
8
+ // 1. Direct candidates
9
+ const candidates = [
10
+ path.isAbsolute(cleanedTarget) ? cleanedTarget : path.resolve(currentCwd, cleanedTarget),
11
+ path.join(home, "Documents", cleanedTarget),
12
+ path.join(home, "Desktop", cleanedTarget),
13
+ path.join(home, "Downloads", cleanedTarget),
14
+ path.join(home, cleanedTarget),
15
+ path.resolve(currentCwd, "..", cleanedTarget),
16
+ ];
17
+ for (const cand of candidates) {
18
+ if (fs.existsSync(cand)) {
19
+ try {
20
+ const stat = fs.statSync(cand);
21
+ if (stat.isDirectory()) {
22
+ process.chdir(cand);
23
+ return {
24
+ success: true,
25
+ newCwd: cand,
26
+ message: `Directorio de trabajo cambiado a: "${cand}"`,
27
+ };
28
+ }
29
+ }
30
+ catch { }
31
+ }
32
+ }
33
+ // 2. Deep search in user profile if not found directly
34
+ try {
35
+ const baseName = path.basename(cleanedTarget);
36
+ const searchRoots = [home, "C:\\", currentCwd];
37
+ for (const root of searchRoots) {
38
+ if (!fs.existsSync(root))
39
+ continue;
40
+ const matches = await fg([`**/${baseName}`], {
41
+ cwd: root,
42
+ onlyDirectories: true,
43
+ deep: 4,
44
+ ignore: ["**/node_modules/**", "**/.git/**", "**/AppData/**", "**/Windows/**"],
45
+ });
46
+ if (matches.length > 0) {
47
+ const bestMatch = path.resolve(root, matches[0]);
48
+ process.chdir(bestMatch);
49
+ return {
50
+ success: true,
51
+ newCwd: bestMatch,
52
+ message: `Directorio localizado y cambiado a: "${bestMatch}"`,
53
+ };
54
+ }
55
+ }
56
+ }
57
+ catch { }
58
+ return {
59
+ success: false,
60
+ newCwd: currentCwd,
61
+ message: `Error: No se pudo localizar el directorio "${targetPath}".`,
62
+ };
63
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * COMPUTER USE
3
+ *
4
+ * Rediseno completo. Los cuatro fallos de la version anterior eran:
5
+ *
6
+ * 1. Coordenadas desviadas por DPI. Windows reportaba la pantalla escalada
7
+ * (2048x1152 en un monitor de 2560x1440 al 125%) mientras el raton se movia
8
+ * en pixeles fisicos. Todo clic caia ~25% arriba-izquierda. El host nuevo se
9
+ * declara DPI-aware antes de medir nada, asi que hay un unico sistema de
10
+ * coordenadas.
11
+ *
12
+ * 2. Ceguera. Se tomaba una captura y el modelo solo recibia "captura guardada,
13
+ * 340 KB". Sin ver nada, tiraba de coordenadas fijas escritas a mano en el
14
+ * prompt. Ahora hay dos formas de saber que hay en pantalla de verdad:
15
+ * ui_snapshot (arbol de accesibilidad, texto exacto) y screenshot (que pasa
16
+ * por el modelo de vision y vuelve como descripcion).
17
+ *
18
+ * 3. Lentitud. Un powershell.exe nuevo con Add-Type por accion, ~1s cada uno.
19
+ * Ahora hay un host persistente y cada accion cuesta milisegundos.
20
+ *
21
+ * 4. Robo de pantalla. Todo pasaba por el primer plano, con un overlay que se
22
+ * dibujaba encima y a veces se quedaba pegado. Ahora el modo por defecto es
23
+ * "background": se actua sobre una ventana concreta sin traerla al frente y
24
+ * sin mover el raton del usuario.
25
+ */
26
+ export type ComputerAction = "screenshot" | "ui_snapshot" | "ui_click" | "ui_type" | "ui_focus" | "find_element" | "left_click" | "click" | "double_click" | "triple_click" | "right_click" | "middle_click" | "mouse_move" | "move" | "left_click_drag" | "scroll" | "type" | "key" | "hotkey" | "wait" | "sleep" | "cursor_position" | "list_windows" | "focus_window" | "get_active_window" | "open_app";
27
+ export interface ComputerUseParams {
28
+ action: ComputerAction;
29
+ /** Ventana objetivo por titulo o proceso (ej. "chrome", "Flow"). */
30
+ window?: string;
31
+ /** "background" (por defecto): no roba el foco. "foreground": raton real. */
32
+ mode?: "background" | "foreground";
33
+ ref?: number;
34
+ /** Solo ui_type: true sustituye todo el contenido del control. Por defecto inserta. */
35
+ replace?: boolean;
36
+ coordinate?: [number, number];
37
+ start_coordinate?: [number, number];
38
+ x?: number;
39
+ y?: number;
40
+ text?: string;
41
+ keys?: string;
42
+ key?: string;
43
+ query?: string;
44
+ filter?: string;
45
+ direction?: "up" | "down" | "left" | "right";
46
+ amount?: number;
47
+ repeat?: number;
48
+ ms?: number;
49
+ seconds?: number;
50
+ max?: number;
51
+ outputPath?: string;
52
+ appName?: string;
53
+ /** Solo para screenshot: pregunta concreta para el modelo de vision. */
54
+ question?: string;
55
+ /** Solo para screenshot: pone false para saltarse la vision y ahorrar tokens. */
56
+ analyze?: boolean;
57
+ }
58
+ export declare function computerUse(params: ComputerUseParams, cwd?: string, apiKey?: string): Promise<string>;