pi-banana 2.0.0 → 2.0.2

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.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # pi-banana
2
2
 
3
+ ![pi-banana banner](https://fcskjxapefiqdclrvbtw.supabase.co/storage/v1/object/public/assets/pi-packages/pi-banana-banner.jpg)
4
+
3
5
  Generate and edit images directly inside [pi](https://github.com/badlogic/pi-mono) using Google's **Nano Banana 2** (`gemini-3.1-flash-image-preview`) and **Nano Banana Pro** (`gemini-3-pro-image-preview`).
4
6
 
5
7
  - **Inline preview** in Kitty / iTerm2 / WezTerm — image shows up right under the tool call, no copy-pasting paths.
@@ -41,7 +43,9 @@ Just ask pi for what you want:
41
43
 
42
44
  The model calls `generate_image` automatically. The PNG is shown inline and written to disk.
43
45
 
44
- ## Tool: `generate_image`
46
+ ## Tool: `banana_image`
47
+
48
+ > Renamed from `generate_image` in v2.0.1 to avoid colliding with `@benvargas/pi-antigravity-image-gen`. Both extensions can now coexist in the same pi install.
45
49
 
46
50
  | Param | Type | Default | Description |
47
51
  |---|---|---|---|
@@ -16,6 +16,13 @@
16
16
 
17
17
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
18
18
  import { StringEnum } from "@earendil-works/pi-ai";
19
+ import {
20
+ Box,
21
+ Container,
22
+ Image,
23
+ Spacer,
24
+ Text,
25
+ } from "@earendil-works/pi-tui";
19
26
  import { GoogleGenAI } from "@google/genai";
20
27
  import { existsSync } from "node:fs";
21
28
  import { mkdir, readFile, writeFile } from "node:fs/promises";
@@ -178,8 +185,8 @@ async function resolveOutputPath(
178
185
 
179
186
  export default function (pi: ExtensionAPI) {
180
187
  pi.registerTool({
181
- name: "generate_image",
182
- label: "Image Gen",
188
+ name: "banana_image",
189
+ label: "Banana Image",
183
190
  description:
184
191
  "Generate or edit a PNG/JPEG image with Google's Nano Banana 2 " +
185
192
  "(Gemini 3.1 Flash Image) or Nano Banana Pro. The image is shown " +
@@ -188,8 +195,8 @@ export default function (pi: ExtensionAPI) {
188
195
  promptSnippet:
189
196
  "Generate or edit images with Google Nano Banana via the GOOGLE_API_KEY env var.",
190
197
  promptGuidelines: [
191
- "Call generate_image when the user asks to create, draw, illustrate, or edit a picture.",
192
- "For tweaks like 'make the sky purple', pass the previous file path as referenceImage to generate_image.",
198
+ "Call banana_image when the user asks to create, draw, illustrate, or edit a picture.",
199
+ "For tweaks like 'make the sky purple', pass the previous file path as referenceImage to banana_image.",
193
200
  "Default quality 'fast' is right for most asks; switch to 'high' only when the user explicitly wants top quality.",
194
201
  ],
195
202
  parameters: Type.Object({
@@ -370,6 +377,7 @@ export default function (pi: ExtensionAPI) {
370
377
  { type: "image", data: base64, mimeType },
371
378
  ],
372
379
  details: {
380
+ prompt: params.prompt,
373
381
  model,
374
382
  quality,
375
383
  aspectRatio,
@@ -381,5 +389,73 @@ export default function (pi: ExtensionAPI) {
381
389
  },
382
390
  };
383
391
  },
392
+
393
+ renderResult(result, _options, theme) {
394
+ const { details, content } = result;
395
+ const container = new Container();
396
+
397
+ // 1. Summary
398
+ const summaryPart = content.find((c: any) => c.type === "text");
399
+ const summaryText = (summaryPart && summaryPart.type === "text") ? summaryPart.text : "";
400
+ container.addChild(new Text(theme.fg("success", "✔ " + summaryText), 1, 0));
401
+
402
+ // 2. Image
403
+ const imagePart = content.find((c: any) => c.type === "image");
404
+ if (imagePart && imagePart.type === "image") {
405
+ container.addChild(
406
+ new Image(imagePart.data, imagePart.mimeType, {
407
+ ...theme,
408
+ fallbackColor: (s: string) => theme.fg("muted", s),
409
+ }, {
410
+ maxWidthCells: 80,
411
+ maxHeightCells: 24,
412
+ })
413
+ );
414
+ }
415
+
416
+ if (!details) return container;
417
+
418
+ const {
419
+ prompt,
420
+ model,
421
+ quality,
422
+ aspectRatio,
423
+ imageSize,
424
+ outputPath,
425
+ } = details as any;
426
+
427
+ container.addChild(new Spacer(1));
428
+
429
+ // 3. Settings Card
430
+ const settingsBox = new Box(1, 1, (s) => theme.bg("customMessageBg", s));
431
+ const settingsContainer = new Container();
432
+
433
+ settingsContainer.addChild(
434
+ new Text(theme.fg("accent", theme.bold("🛠️ GENERATION SETTINGS")), 0, 0)
435
+ );
436
+ settingsContainer.addChild(new Spacer(1));
437
+
438
+ const addSetting = (label: string, value: string) => {
439
+ settingsContainer.addChild(
440
+ new Text(
441
+ theme.fg("muted", label.padEnd(10)) + theme.fg("text", String(value)),
442
+ 0,
443
+ 0
444
+ )
445
+ );
446
+ };
447
+
448
+ if (prompt) addSetting("Prompt", prompt);
449
+ if (model) addSetting("Model", model);
450
+ if (quality) addSetting("Quality", quality);
451
+ if (aspectRatio) addSetting("Aspect", aspectRatio);
452
+ if (imageSize) addSetting("Size", imageSize);
453
+ if (outputPath) addSetting("Path", outputPath);
454
+
455
+ settingsBox.addChild(settingsContainer);
456
+ container.addChild(settingsBox);
457
+
458
+ return container;
459
+ },
384
460
  });
385
461
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-banana",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Generate and edit images in pi using Google Nano Banana 2 (gemini-3.1-flash-image) and Nano Banana Pro. Inline terminal preview, reference-image editing, auto-save.",
5
5
  "author": "Francesco Frapporti <effedue@gmail.com>",
6
6
  "license": "MIT",
@@ -20,12 +20,15 @@
20
20
  "pi-coding-agent",
21
21
  "google",
22
22
  "gemini",
23
+ "gemini-api",
23
24
  "nano-banana",
24
25
  "nano-banana-2",
25
26
  "nano-banana-pro",
27
+ "imagen",
26
28
  "image-generation",
27
- "image-edit",
28
- "imagen"
29
+ "image-editing",
30
+ "ai-image",
31
+ "terminal"
29
32
  ],
30
33
  "files": [
31
34
  "extensions",
@@ -47,11 +50,13 @@
47
50
  "peerDependencies": {
48
51
  "@earendil-works/pi-ai": "*",
49
52
  "@earendil-works/pi-coding-agent": "*",
53
+ "@earendil-works/pi-tui": "*",
50
54
  "typebox": "^1.1.24"
51
55
  },
52
56
  "devDependencies": {
53
57
  "@earendil-works/pi-ai": "*",
54
58
  "@earendil-works/pi-coding-agent": "*",
59
+ "@earendil-works/pi-tui": "*",
55
60
  "@types/node": "^22.0.0",
56
61
  "jiti": "^2.7.0",
57
62
  "typebox": "^1.1.24",