@bunny-agent/runner-cli 0.9.32 → 0.9.34

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/bundle.mjs +124 -29
  2. package/package.json +3 -3
package/dist/bundle.mjs CHANGED
@@ -1388,20 +1388,37 @@ var generateImageSchema = {
1388
1388
  size: {
1389
1389
  type: "string",
1390
1390
  enum: [
1391
+ "auto",
1392
+ "1024x1024",
1393
+ "1536x1024",
1394
+ "1024x1536",
1391
1395
  "256x256",
1392
1396
  "512x512",
1393
- "1024x1024",
1394
1397
  "1792x1024",
1395
- "1024x1792",
1396
- "1280x1280",
1397
- "1568x1056",
1398
- "1056x1568",
1399
- "1472x1088",
1400
- "1088x1472",
1401
- "1728x960",
1402
- "960x1728"
1398
+ "1024x1792"
1403
1399
  ],
1404
- description: "Image dimensions. Common: 1024x1024 (square), 1280x1280, 1568x1056 (landscape), 1056x1568 (portrait), 1728x960 (wide), 960x1728 (tall)."
1400
+ description: "Image dimensions. Supported values: auto, 1024x1024, 1536x1024, 1024x1536, 256x256, 512x512, 1792x1024, 1024x1792."
1401
+ },
1402
+ aspectRatio: {
1403
+ type: "string",
1404
+ enum: [
1405
+ "1:1",
1406
+ "3:2",
1407
+ "2:3",
1408
+ "3:4",
1409
+ "4:3",
1410
+ "4:5",
1411
+ "5:4",
1412
+ "9:16",
1413
+ "16:9",
1414
+ "21:9"
1415
+ ],
1416
+ description: "Image aspect ratio. Use this instead of size for models that support it when exact proportions matter. Supported values: 1:1, 3:2, 2:3, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9."
1417
+ },
1418
+ imageSize: {
1419
+ type: "string",
1420
+ enum: ["1K", "2K", "4K"],
1421
+ description: "Image resolution for models that support K-resolution output. Use this for requests like 2K or 4K."
1405
1422
  },
1406
1423
  quality: {
1407
1424
  type: "string",
@@ -1412,6 +1429,33 @@ var generateImageSchema = {
1412
1429
  required: ["prompt"],
1413
1430
  additionalProperties: false
1414
1431
  };
1432
+ var hasImagePayload = (item) => Boolean(item.b64_json ?? item.b64Json ?? item.image_base64 ?? item.imageBase64 ?? item.base64 ?? item.data ?? item.inlineData?.data ?? item.inline_data?.data ?? item.url ?? item.image_url ?? item.imageUrl ?? (typeof item.image === "string" ? item.image : item.image?.b64_json ?? item.image?.base64 ?? item.image?.data ?? item.image?.url));
1433
+ function readString(value) {
1434
+ return typeof value === "string" && value.length > 0 ? value : void 0;
1435
+ }
1436
+ function readInlineData(value) {
1437
+ if (!value || typeof value !== "object")
1438
+ return void 0;
1439
+ const obj = value;
1440
+ return {
1441
+ data: readString(obj.data),
1442
+ mimeType: readString(obj.mimeType),
1443
+ mime_type: readString(obj.mime_type)
1444
+ };
1445
+ }
1446
+ function readImage(value) {
1447
+ if (typeof value === "string" && value.length > 0)
1448
+ return value;
1449
+ if (!value || typeof value !== "object")
1450
+ return void 0;
1451
+ const obj = value;
1452
+ return {
1453
+ base64: readString(obj.base64),
1454
+ b64_json: readString(obj.b64_json),
1455
+ url: readString(obj.url),
1456
+ data: readString(obj.data)
1457
+ };
1458
+ }
1415
1459
  async function resolveB64(item, apiKey) {
1416
1460
  if (item.b64_json)
1417
1461
  return item.b64_json;
@@ -1423,12 +1467,20 @@ async function resolveB64(item, apiKey) {
1423
1467
  return item.imageBase64;
1424
1468
  if (item.base64)
1425
1469
  return item.base64;
1470
+ if (item.data)
1471
+ return item.data;
1472
+ if (item.inlineData?.data)
1473
+ return item.inlineData.data;
1474
+ if (item.inline_data?.data)
1475
+ return item.inline_data.data;
1426
1476
  if (typeof item.image === "string")
1427
1477
  return item.image;
1428
1478
  if (item.image?.b64_json)
1429
1479
  return item.image.b64_json;
1430
1480
  if (item.image?.base64)
1431
1481
  return item.image.base64;
1482
+ if (item.image?.data)
1483
+ return item.image.data;
1432
1484
  const url = item.url ?? item.image_url ?? item.imageUrl ?? item.image?.url;
1433
1485
  if (url) {
1434
1486
  const headers = {};
@@ -1446,16 +1498,24 @@ function pickImageItem(response) {
1446
1498
  if (!value || typeof value !== "object")
1447
1499
  return void 0;
1448
1500
  const obj = value;
1501
+ const image = readImage(obj.image);
1502
+ const inlineData = readInlineData(obj.inlineData);
1503
+ const inline_data = readInlineData(obj.inline_data);
1449
1504
  return {
1450
- b64_json: obj.b64_json ?? obj.b64Json,
1451
- b64Json: obj.b64Json,
1452
- url: obj.url ?? obj.imageUrl,
1453
- image_base64: obj.image_base64 ?? obj.imageBase64,
1454
- imageBase64: obj.imageBase64,
1455
- image_url: obj.image_url ?? obj.imageUrl,
1456
- imageUrl: obj.imageUrl,
1457
- base64: obj.base64,
1458
- image: obj.image
1505
+ b64_json: readString(obj.b64_json) ?? readString(obj.b64Json),
1506
+ b64Json: readString(obj.b64Json),
1507
+ url: readString(obj.url) ?? readString(obj.imageUrl),
1508
+ image_base64: readString(obj.image_base64) ?? readString(obj.imageBase64),
1509
+ imageBase64: readString(obj.imageBase64),
1510
+ image_url: readString(obj.image_url) ?? readString(obj.imageUrl),
1511
+ imageUrl: readString(obj.imageUrl),
1512
+ base64: readString(obj.base64),
1513
+ data: readString(obj.data),
1514
+ mimeType: readString(obj.mimeType),
1515
+ mime_type: readString(obj.mime_type),
1516
+ inlineData,
1517
+ inline_data,
1518
+ image
1459
1519
  };
1460
1520
  };
1461
1521
  const asItem = (value) => {
@@ -1466,7 +1526,7 @@ function pickImageItem(response) {
1466
1526
  }
1467
1527
  if (typeof value === "object") {
1468
1528
  const normalized = tryFromObject(value);
1469
- if (normalized)
1529
+ if (normalized && hasImagePayload(normalized))
1470
1530
  return normalized;
1471
1531
  }
1472
1532
  return void 0;
@@ -1509,8 +1569,7 @@ function pickImageItem(response) {
1509
1569
  continue;
1510
1570
  const normalized = tryFromObject(current);
1511
1571
  if (normalized) {
1512
- const hasUsefulField = Boolean(normalized.b64_json ?? normalized.b64Json ?? normalized.image_base64 ?? normalized.imageBase64 ?? normalized.base64 ?? normalized.url ?? normalized.image_url ?? normalized.imageUrl ?? (typeof normalized.image === "string" ? normalized.image : normalized.image?.b64_json ?? normalized.image?.base64 ?? normalized.image?.url));
1513
- if (hasUsefulField)
1572
+ if (hasImagePayload(normalized))
1514
1573
  return normalized;
1515
1574
  }
1516
1575
  if (Array.isArray(current)) {
@@ -1556,19 +1615,23 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
1556
1615
  name: "generate_image",
1557
1616
  label: "generate image",
1558
1617
  description: "Generate an image from a text prompt. Saves the image to disk and returns the file path.",
1559
- promptSnippet: "generate_image(prompt, filename?, size?, quality?) - generate an image from text",
1618
+ promptSnippet: "generate_image(prompt, filename?, size?, aspectRatio?, imageSize?, quality?) - generate an image from text",
1560
1619
  promptGuidelines: [
1561
1620
  "Use generate_image when the user asks to create, draw, or visualize something.",
1562
1621
  "Be descriptive in the prompt \u2014 more detail produces better results.",
1563
- "Provide a filename with extension, e.g. 'cat.png'."
1622
+ "Provide a filename with extension, e.g. 'cat.png'.",
1623
+ "Use aspectRatio (e.g. '3:4') when the requested output needs specific proportions.",
1624
+ "Use imageSize (e.g. '2K') when the user requests 1K, 2K, or 4K resolution."
1564
1625
  ],
1565
1626
  // biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
1566
1627
  parameters: generateImageSchema,
1567
1628
  async execute(_toolCallId, params, signal, _onUpdate) {
1568
1629
  const p = params;
1569
1630
  const prompt = p.prompt;
1570
- const size = p.size ?? "1024x1024";
1631
+ const size = p.size;
1571
1632
  const quality = p.quality ?? "auto";
1633
+ const aspectRatio = p.aspectRatio;
1634
+ const imageSize = p.imageSize;
1572
1635
  const rawFilename = p.filename;
1573
1636
  const filename = rawFilename ? extname(rawFilename) ? rawFilename : `${rawFilename}.png` : `image_${Date.now()}.png`;
1574
1637
  const filePath = join6(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
@@ -1584,10 +1647,12 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
1584
1647
  model: imageModelId,
1585
1648
  prompt,
1586
1649
  n: 1,
1587
- size,
1588
1650
  quality,
1589
1651
  response_format: "b64_json",
1590
- output_format: "png"
1652
+ output_format: "png",
1653
+ ...aspectRatio ? { aspect_ratio: aspectRatio } : {},
1654
+ ...imageSize ? { image_size: imageSize } : {},
1655
+ ...size ? { size } : !aspectRatio && !imageSize ? { size: "1024x1024" } : {}
1591
1656
  }),
1592
1657
  signal
1593
1658
  });
@@ -1649,6 +1714,27 @@ var editImageSchema = {
1649
1714
  type: "string",
1650
1715
  enum: ["low", "medium", "high", "auto"],
1651
1716
  description: "Image quality. Optional; omit or set auto to let model decide."
1717
+ },
1718
+ aspectRatio: {
1719
+ type: "string",
1720
+ enum: [
1721
+ "1:1",
1722
+ "3:2",
1723
+ "2:3",
1724
+ "3:4",
1725
+ "4:3",
1726
+ "4:5",
1727
+ "5:4",
1728
+ "9:16",
1729
+ "16:9",
1730
+ "21:9"
1731
+ ],
1732
+ description: "Gemini image aspect ratio. Use this instead of size for Gemini image edit models when exact proportions matter."
1733
+ },
1734
+ imageSize: {
1735
+ type: "string",
1736
+ enum: ["1K", "2K", "4K"],
1737
+ description: "Gemini output resolution for image edit models that support K-resolution output."
1652
1738
  }
1653
1739
  },
1654
1740
  required: ["image", "prompt"],
@@ -1685,12 +1771,13 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
1685
1771
  name: "edit_image",
1686
1772
  label: "edit image",
1687
1773
  description: "Edit an existing image based on a text prompt. Optionally use a mask to control which areas to modify. Saves the result to disk and returns the file path.",
1688
- promptSnippet: "edit_image(image, prompt, mask?, filename?, size?, quality?) - edit an existing image",
1774
+ promptSnippet: "edit_image(image, prompt, mask?, filename?, size?, quality?, aspectRatio?, imageSize?) - edit an existing image",
1689
1775
  promptGuidelines: [
1690
1776
  "Use edit_image when the user wants to modify, retouch, or transform an existing image.",
1691
1777
  "The prompt should describe the full desired final image, not just the change.",
1692
1778
  "Provide the source image path. Use a mask image (PNG with transparent areas) to control where edits happen.",
1693
- "Without a mask, the model decides what to change based on the prompt."
1779
+ "Without a mask, the model decides what to change based on the prompt.",
1780
+ "For Gemini image edit models, use aspectRatio and imageSize when the user asks for those controls."
1694
1781
  ],
1695
1782
  // biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
1696
1783
  parameters: editImageSchema,
@@ -1703,6 +1790,8 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
1703
1790
  const maskPath = p.mask;
1704
1791
  const size = p.size;
1705
1792
  const quality = p.quality;
1793
+ const aspectRatio = p.aspectRatio;
1794
+ const imageSize = p.imageSize;
1706
1795
  const rawFilename = p.filename;
1707
1796
  const safePrompt = buildPolicySafeEditPrompt(prompt);
1708
1797
  const resolvedImage = resolve4(cwd, imagePath);
@@ -1734,6 +1823,12 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
1734
1823
  if (quality && quality !== "auto") {
1735
1824
  fields.push({ name: "quality", value: quality });
1736
1825
  }
1826
+ if (aspectRatio) {
1827
+ fields.push({ name: "aspect_ratio", value: aspectRatio });
1828
+ }
1829
+ if (imageSize) {
1830
+ fields.push({ name: "image_size", value: imageSize });
1831
+ }
1737
1832
  const files = [
1738
1833
  {
1739
1834
  name: "image",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunny-agent/runner-cli",
3
- "version": "0.9.32",
3
+ "version": "0.9.34",
4
4
  "description": "BunnyAgent Runner CLI - Like gemini-cli or claude-code, runs in your local terminal with AI SDK UI streaming",
5
5
  "type": "module",
6
6
  "bin": {
@@ -55,10 +55,10 @@
55
55
  "vitest": "^1.6.1",
56
56
  "@bunny-agent/runner-harness": "0.1.1-beta.0",
57
57
  "@bunny-agent/runner-opencode": "0.6.2",
58
- "@bunny-agent/runner-gemini": "0.6.2",
58
+ "@bunny-agent/runner-pi": "0.6.4-beta.0",
59
59
  "@bunny-agent/runner-codex": "0.6.2",
60
60
  "@bunny-agent/runner-claude": "0.6.2",
61
- "@bunny-agent/runner-pi": "0.6.4-beta.0"
61
+ "@bunny-agent/runner-gemini": "0.6.2"
62
62
  },
63
63
  "scripts": {
64
64
  "build": "tsc && pnpm bundle",