Skip to content

Commit d3c46c5

Browse files
authored
feat: add OpenRouter image generation and editing endpoints (#717)
will refine after.
1 parent 70bd261 commit d3c46c5

File tree

6 files changed

+684
-13
lines changed

6 files changed

+684
-13
lines changed

call-ai/pkg/image.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
/**
22
* Image generation API implementation for call-ai
3-
* Integration with custom image generation API
3+
* Integration with OpenRouter image generation API
44
*/
55
import { ImageGenOptions, ImageResponse } from "./types.js";
66
import { callAiFetch, joinUrlParts } from "./utils.js";
77
import { callAiEnv } from "./env.js";
88

99
/**
10-
* Generate images using a custom API that mimics OpenAI's image generation capabilities
10+
* Generate images using OpenRouter API with Gemini image generation
1111
* @param prompt Text prompt describing the image to generate
1212
* @param options Configuration options for the image generation request
1313
* @returns A Promise that resolves to the image response containing base64 encoded image data
1414
*/
1515
export async function imageGen(prompt: string, options: ImageGenOptions = {}): Promise<ImageResponse> {
16-
const { model = "gpt-image-1", apiKey = callAiEnv.CALLAI_API_KEY, size = "1024x1024" } = options;
16+
const { model = "google/gemini-2.5-flash-image", apiKey = callAiEnv.CALLAI_API_KEY, size = "1024x1024" } = options;
1717

1818
if (!apiKey) {
1919
throw new Error("API key is required for image generation. Provide via options.apiKey or set window.CALLAI_API_KEY");
@@ -27,7 +27,7 @@ export async function imageGen(prompt: string, options: ImageGenOptions = {}): P
2727
// Simple image generation with text prompt
2828
// Use explicit endpoint if provided (highest priority), otherwise construct from origin
2929
const generateEndpoint =
30-
options.endpoint || joinUrlParts(customOrigin || callAiEnv.def.CALLAI_CHAT_URL, "/api/openai-image/generate");
30+
options.endpoint || joinUrlParts(customOrigin || callAiEnv.def.CALLAI_CHAT_URL, "/api/openrouter-image/generate");
3131

3232
if (!apiKey) {
3333
throw new Error("API key is required for image generation (simple)");
@@ -81,7 +81,8 @@ export async function imageGen(prompt: string, options: ImageGenOptions = {}): P
8181
if (options.style) formData.append("style", options.style);
8282

8383
// Use explicit endpoint if provided (highest priority), otherwise construct from origin
84-
const editEndpoint = options.endpoint || joinUrlParts(customOrigin || callAiEnv.def.CALLAI_CHAT_URL, "/api/openai-image/edit");
84+
const editEndpoint =
85+
options.endpoint || joinUrlParts(customOrigin || callAiEnv.def.CALLAI_CHAT_URL, "/api/openrouter-image/edit");
8586

8687
if (!apiKey) {
8788
throw new Error("API key is required for image generation (edit)");

call-ai/tests/integration/imagegen.integration.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ describe("Image Generation Integration Tests", () => {
6060
expect(mock.fetch).toHaveBeenCalledTimes(1);
6161
const [url, optionsArg] = mock.fetch.mock.calls[0];
6262

63-
expect(url).toMatch(/.*\/api\/openai-image\/generate$/);
63+
expect(url).toMatch(/.*\/api\/openrouter-image\/generate$/);
6464
expect(optionsArg.method).toBe("POST");
6565

6666
// Check headers
@@ -77,7 +77,7 @@ describe("Image Generation Integration Tests", () => {
7777
// Verify request body content
7878
const requestBody = JSON.parse(optionsArg.body);
7979
expect(requestBody.prompt).toBe(testPrompt);
80-
expect(requestBody.model).toBe("gpt-image-1");
80+
expect(requestBody.model).toBe("google/gemini-2.5-flash-image");
8181
});
8282

8383
it("should handle image editing with multiple input images", async () => {
@@ -118,7 +118,7 @@ describe("Image Generation Integration Tests", () => {
118118
expect(mock.fetch).toHaveBeenCalledTimes(1);
119119
const [url, optionsArg] = mock.fetch.mock.calls[0];
120120

121-
expect(url).toMatch(/.*\/api\/openai-image\/edit$/);
121+
expect(url).toMatch(/.*\/api\/openrouter-image\/edit$/);
122122
expect(optionsArg.method).toBe("POST");
123123

124124
// Check headers

call-ai/tests/unit/imagegen.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ describe("imageGen", () => {
9595
expect(mock.fetch).toHaveBeenCalledTimes(1);
9696
const [url, optionsArg] = mock.fetch.mock.calls[0];
9797

98-
expect(url).toContain("/api/openai-image/generate");
98+
expect(url).toContain("/api/openrouter-image/generate");
9999
expect(optionsArg.method).toBe("POST");
100100

101101
// Check headers
@@ -148,7 +148,7 @@ describe("imageGen", () => {
148148
expect(mock.fetch).toHaveBeenCalledTimes(1);
149149
const [url, optionsArg] = mock.fetch.mock.calls[0];
150150

151-
expect(url).toContain("/api/openai-image/edit");
151+
expect(url).toContain("/api/openrouter-image/edit");
152152
expect(optionsArg.method).toBe("POST");
153153

154154
// Check headers
@@ -236,7 +236,7 @@ describe("imageGen", () => {
236236
// Verify the custom endpoint was used directly, not the default vibes.diy endpoint
237237
expect(url).toBe(customEndpoint);
238238
expect(url).not.toContain("vibes-diy-api.com");
239-
expect(url).not.toContain("/api/openai-image/generate");
239+
expect(url).not.toContain("/api/openrouter-image/generate");
240240

241241
// Verify the request was made with correct headers
242242
const headers = optionsArg.headers;
@@ -283,7 +283,7 @@ describe("imageGen", () => {
283283
// Verify the custom endpoint was used directly
284284
expect(url).toBe(customEndpoint);
285285
expect(url).not.toContain("vibes-diy-api.com");
286-
expect(url).not.toContain("/api/openai-image/edit");
286+
expect(url).not.toContain("/api/openrouter-image/edit");
287287

288288
// Verify the request was made with FormData
289289
expect(optionsArg.body).toBeInstanceOf(FormData);
@@ -308,6 +308,6 @@ describe("imageGen", () => {
308308
const [url] = mock.fetch.mock.calls[0];
309309

310310
// Should use the default vibes.diy endpoint
311-
expect(url).toContain("/api/openai-image/generate");
311+
expect(url).toContain("/api/openrouter-image/generate");
312312
});
313313
});

0 commit comments

Comments
 (0)