All files / src/providers/openai Image.ts

85.71% Statements 12/14
75% Branches 9/12
100% Functions 2/2
85.71% Lines 12/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57                40x 40x       1x               1x 1x   1x                         1x       1x 1x 1x   1x       1x              
import { ImageRequest, ImageResponse } from "../Provider.js";
import { handleOpenAIError } from "./Errors.js";
import { buildUrl } from "./utils.js";
import { logger } from "../../utils/logger.js";
import { fetchWithTimeout } from "../../utils/fetch.js";
 
export class OpenAIImage {
  constructor(
    private readonly baseUrl: string,
    private readonly apiKey: string
  ) {}
 
  async execute(request: ImageRequest): Promise<ImageResponse> {
    const body: Record<string, unknown> = {
      model: request.model || "dall-e-3",
      prompt: request.prompt,
      size: request.size || "1024x1024",
      quality: request.quality || "standard",
      n: request.n || 1
    };
 
    const url = buildUrl(this.baseUrl, "/images/generations");
    logger.logRequest("OpenAI", "POST", url, body);
 
    const response = await fetchWithTimeout(
      url,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${this.apiKey}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify(body)
      },
      request.requestTimeout
    );
 
    Iif (!response.ok) {
      await handleOpenAIError(response, request.model);
    }
 
    const json = await response.json();
    logger.logResponse("OpenAI", response.status, response.statusText, json);
    const data = json.data?.[0];
 
    Iif (!data) {
      throw new Error("OpenAI returned empty image response");
    }
 
    return {
      url: data.url,
      revised_prompt: data.revised_prompt,
      mime_type: "image/png"
    };
  }
}