55 lines
No EOL
1.9 KiB
TypeScript
55 lines
No EOL
1.9 KiB
TypeScript
import { tool } from "@opencode-ai/plugin/tool"
|
|
|
|
async function parseImageInput(input: string) {
|
|
// Accepts file path ("./img.png") or data URL ("data:image/png;base64,...")
|
|
if (input.startsWith("data:")) {
|
|
const base64 = input.split(",")[1]
|
|
const mime = input.substring(5, input.indexOf(";"))
|
|
return { mime, base64 }
|
|
}
|
|
// Treat as file path
|
|
const file = Bun.file(input)
|
|
const arr = await file.arrayBuffer()
|
|
const base64 = Buffer.from(arr).toString("base64")
|
|
// Best-effort mime
|
|
const mime = file.type || "image/png"
|
|
return { mime, base64 }
|
|
}
|
|
|
|
export default tool({
|
|
description: "Edit an image using Gemini. Pass file path or data URL.",
|
|
args: {
|
|
image: tool.schema.string().describe("File path or data URL"),
|
|
prompt: tool.schema.string().describe("Edit instruction"),
|
|
output: tool.schema.string().optional().describe("Output filename (default edited.png)"),
|
|
},
|
|
async execute(args, context) {
|
|
const apiKey = process.env.GEMINI_API_KEY
|
|
if (!apiKey) return "Set GEMINI_API_KEY in your environment"
|
|
|
|
const { mime, base64 } = await parseImageInput(args.image)
|
|
const res = await fetch(
|
|
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image-preview:generateContent",
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"x-goog-api-key": apiKey,
|
|
},
|
|
body: JSON.stringify({
|
|
inputs: [{ mimeType: mime, data: base64 }],
|
|
contents: [{ parts: [{ text: args.prompt }]}],
|
|
}),
|
|
}
|
|
)
|
|
|
|
if (!res.ok) return `API error: ${await res.text()}`
|
|
const json = await res.json()
|
|
const b64 = json?.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data
|
|
if (!b64) return "No image data returned"
|
|
|
|
const out = args.output || "edited.png"
|
|
await Bun.write(out, Buffer.from(b64, "base64"))
|
|
return `Saved ${out}`
|
|
},
|
|
}) |