open-agents-ai 0.184.79 → 0.184.81

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 (2) hide show
  1. package/dist/index.js +76 -27
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16206,7 +16206,7 @@ var init_desktop_click = __esm({
16206
16206
  DesktopClickTool = class {
16207
16207
  workingDir;
16208
16208
  name = "desktop_click";
16209
- description = "Click on a UI element identified by natural language description. Takes a screenshot, uses vision to find the described element, then clicks at that location using xdotool (Linux) or cliclick (macOS). Example: desktop_click({ target: 'the Save button' })";
16209
+ description = "Click on a UI element identified by natural language description. Takes a screenshot, uses Moondream vision to find the element's coordinates, then clicks at that location. Supports single click, double click, and right click.\n Single click: desktop_click({ target: 'the Save button' })\n Double click: desktop_click({ target: 'document.pdf', click_type: 'double' })\n Right click: desktop_click({ target: 'file icon', button: 'right' })\nChain multiple calls for complex interactions (e.g. right-click \u2192 select menu item).";
16210
16210
  /** Active Ollama model name — used as vision fallback if it has vision capability */
16211
16211
  _activeModel = "";
16212
16212
  /** Whether the active model has vision capability */
@@ -16303,20 +16303,51 @@ var init_desktop_click = __esm({
16303
16303
  const envModel = process.env["OLLAMA_VISION_MODEL"];
16304
16304
  const ollamaModel = envModel || (this._activeModelHasVision && this._activeModel ? this._activeModel : "moondream");
16305
16305
  const imageBase64 = readFileSync15(screenshotPath).toString("base64");
16306
- const res = await fetch(`${ollamaHost}/api/generate`, {
16306
+ let res = await fetch(`${ollamaHost}/api/generate`, {
16307
16307
  method: "POST",
16308
16308
  headers: { "Content-Type": "application/json" },
16309
- body: JSON.stringify({ model: ollamaModel, prompt: `Point to ${target}`, images: [imageBase64], stream: false }),
16309
+ body: JSON.stringify({ model: ollamaModel, prompt: `Locate the "${target}" in this image and give its x,y position as normalized coordinates.`, images: [imageBase64], stream: false }),
16310
16310
  signal: AbortSignal.timeout(6e4)
16311
16311
  });
16312
+ if (!res.ok && ollamaModel === "moondream") {
16313
+ const errText = await res.text().catch(() => "");
16314
+ if (res.status === 404 || /not found|does not exist/i.test(errText)) {
16315
+ try {
16316
+ const { execSync: es } = await import("node:child_process");
16317
+ es("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
16318
+ res = await fetch(`${ollamaHost}/api/generate`, {
16319
+ method: "POST",
16320
+ headers: { "Content-Type": "application/json" },
16321
+ body: JSON.stringify({ model: ollamaModel, prompt: `Locate the "${target}" in this image and give its x,y position as normalized coordinates.`, images: [imageBase64], stream: false }),
16322
+ signal: AbortSignal.timeout(6e4)
16323
+ });
16324
+ } catch {
16325
+ }
16326
+ }
16327
+ }
16312
16328
  if (res.ok) {
16313
16329
  const data = await res.json();
16314
16330
  const response = data.response || "";
16315
- const pointMatches = [...response.matchAll(/<point\s+x="([\d.]+)"\s+y="([\d.]+)"\s*\/?>/g)];
16316
- if (pointMatches.length > 0) {
16317
- points = pointMatches.map((m) => ({ x: parseFloat(m[1]), y: parseFloat(m[2]) }));
16331
+ const xmlMatches = [...response.matchAll(/<point\s+x="([\d.]+)"\s+y="([\d.]+)"\s*\/?>/g)];
16332
+ if (xmlMatches.length > 0) {
16333
+ points = xmlMatches.map((m) => ({ x: parseFloat(m[1]), y: parseFloat(m[2]) }));
16318
16334
  visionWorked = true;
16319
16335
  }
16336
+ if (!visionWorked) {
16337
+ const arrayMatch = response.match(/\[\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+)\s*,\s*([\d.]+))?\s*\]/);
16338
+ if (arrayMatch) {
16339
+ const x1 = parseFloat(arrayMatch[1]);
16340
+ const y1 = parseFloat(arrayMatch[2]);
16341
+ if (arrayMatch[3] && arrayMatch[4]) {
16342
+ const x2 = parseFloat(arrayMatch[3]);
16343
+ const y2 = parseFloat(arrayMatch[4]);
16344
+ points = [{ x: (x1 + x2) / 2, y: (y1 + y2) / 2 }];
16345
+ } else {
16346
+ points = [{ x: x1, y: y1 }];
16347
+ }
16348
+ visionWorked = true;
16349
+ }
16350
+ }
16320
16351
  }
16321
16352
  } catch {
16322
16353
  }
@@ -16480,12 +16511,28 @@ ${caption}`);
16480
16511
  const ollamaModel = envModel || (this._activeModelHasVision && this._activeModel ? this._activeModel : "moondream");
16481
16512
  const imageBase64 = imageBuffer.toString("base64");
16482
16513
  const ollamaPrompt = question || "Describe what you see on this desktop screenshot in detail. Include visible applications, windows, text, and UI elements.";
16483
- const res = await fetch(`${ollamaHost}/api/generate`, {
16514
+ let res = await fetch(`${ollamaHost}/api/generate`, {
16484
16515
  method: "POST",
16485
16516
  headers: { "Content-Type": "application/json" },
16486
16517
  body: JSON.stringify({ model: ollamaModel, prompt: ollamaPrompt, images: [imageBase64], stream: false }),
16487
16518
  signal: AbortSignal.timeout(6e4)
16488
16519
  });
16520
+ if (!res.ok && ollamaModel === "moondream") {
16521
+ const errText = await res.text().catch(() => "");
16522
+ if (res.status === 404 || /not found|does not exist/i.test(errText)) {
16523
+ try {
16524
+ const { execSync: es } = await import("node:child_process");
16525
+ es("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
16526
+ res = await fetch(`${ollamaHost}/api/generate`, {
16527
+ method: "POST",
16528
+ headers: { "Content-Type": "application/json" },
16529
+ body: JSON.stringify({ model: ollamaModel, prompt: ollamaPrompt, images: [imageBase64], stream: false }),
16530
+ signal: AbortSignal.timeout(6e4)
16531
+ });
16532
+ } catch {
16533
+ }
16534
+ }
16535
+ }
16489
16536
  if (res.ok) {
16490
16537
  const data = await res.json();
16491
16538
  if (data.response) {
@@ -64433,26 +64480,28 @@ ${lines.join("\n")}
64433
64480
  dynamicContext += `
64434
64481
 
64435
64482
  <vision-capabilities>
64436
- You have vision capabilities available. You can analyze images using these tools:
64437
-
64438
- 1. **image_read** \u2014 Read/view an image file directly. Use this for screenshots, photos,
64439
- diagrams, or any image the user provides. Pass the file path.
64440
- Example: image_read(image="/path/to/image.png")
64441
-
64442
- 2. **vision** \u2014 Analyze images with Moondream vision model. Supports:
64443
- - caption: Describe what's in an image
64444
- - query: Ask a question about an image (visual QA)
64445
- - detect: Find all instances of an object (bounding boxes)
64446
- - point: Find the center location of an object (for click targeting)
64447
- Example: vision(image="/tmp/screenshot.png", action="caption")
64448
- Example: vision(image="photo.jpg", action="query", prompt="What color is the car?")
64449
-
64450
- 3. **screenshot** \u2014 Capture the current screen (desktop automation).
64451
- Returns a screenshot path you can then analyze with vision or image_read.
64452
-
64453
- When the user asks you to look at, describe, or analyze an image or camera feed,
64454
- use these tools proactively. Do not say you cannot see images \u2014 you can.
64455
- For video streams or camera feeds, capture frames and analyze them sequentially.
64483
+ You have vision capabilities available.
64484
+
64485
+ IMAGE ANALYSIS:
64486
+ image_read(image="path") \u2014 View/read an image file directly
64487
+ vision(image="path", action="caption") \u2014 Describe image contents
64488
+ vision(image="path", action="query", prompt="question") \u2014 Visual QA
64489
+ vision(image="path", action="detect", prompt="object") \u2014 Find objects (bounding boxes)
64490
+ vision(image="path", action="point", prompt="element") \u2014 Find element center (for clicking)
64491
+
64492
+ DESKTOP INTERACTION PIPELINE:
64493
+ 1. desktop_describe() \u2014 Screenshot + describe what's on screen
64494
+ 2. desktop_click({ target: "element" }) \u2014 Find + click an element
64495
+ 3. desktop_click({ target: "file.pdf", click_type: "double" }) \u2014 Double click to open
64496
+ 4. desktop_click({ target: "icon", button: "right" }) \u2014 Right click for context menu
64497
+ Chain calls iteratively: describe \u2192 click \u2192 wait \u2192 describe \u2192 click next item
64498
+
64499
+ RULES:
64500
+ - Do NOT say you cannot see images \u2014 you can.
64501
+ - Use desktop_describe first to survey the screen, then desktop_click to interact.
64502
+ - After clicking, call desktop_describe again to verify the result.
64503
+ - For file operations: double-click to open, right-click for context menus.
64504
+ - Use delay_ms parameter if UI needs time to transition between clicks.
64456
64505
  </vision-capabilities>`;
64457
64506
  }
64458
64507
  let localFirstOverride = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.184.79",
3
+ "version": "0.184.81",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",