{"version":3,"file":"adapter.cjs","names":["#options","#resolveResponseFormat","#url","#headers","#sendRequest","#mapResponse"],"sources":["../../../../src/batteries/generation/openai/adapter.ts"],"sourcesContent":["/**\n * Cross-environment OpenAI media generation adapter battery.\n *\n * @module @nhtio/adk/batteries/generation/openai/adapter\n *\n * @remarks\n * Opinionated media-generation battery for the OpenAI `/v1/images/generations` and\n * `/v1/images/edits` wire shapes. Ships an {@link OpenAIGenerationAdapter} that targets any\n * OpenAI-`/v1/images`-compatible endpoint (OpenAI proper, Azure-behind-proxy, a local gateway,\n * etc.) over raw `fetch` — no SDK dependency, so it runs unchanged in Node, the browser, edge\n * runtimes, and workers.\n *\n * Construction validates options eagerly via\n * {@link @nhtio/adk/batteries/generation/openai/validation!validateOptions} and throws\n * {@link @nhtio/adk/batteries/generation/openai/exceptions!E_INVALID_OPENAI_GENERATION_OPTIONS} on\n * failure — config bugs fail loud, not at generate/edit time.\n */\n\nimport { toBytes } from '../_shared'\nimport { isError } from '@nhtio/adk/guards'\nimport { validateOptions } from './validation'\nimport { decodeBase64 } from '../../../lib/helpers/base64'\nimport { computeBackoff, sleepWithJitter, parseRetryAfter } from '../../../lib/utils/retry'\nimport {\n  E_OPENAI_GENERATION_HTTP_ERROR,\n  E_OPENAI_GENERATION_REQUEST_TIMEOUT,\n  E_OPENAI_GENERATION_MALFORMED_RESPONSE,\n} from './exceptions'\nimport type { GenerationImageInput } from '../_shared'\nimport type {\n  GenerationRetryConfig,\n  GeneratedMediaOutput,\n  OpenAIGenerationAdapterOptions,\n  OpenAIGenerateOptions,\n  OpenAIEditOptions,\n  OpenAIImagesGenerationRequestBody,\n  OpenAIImagesResponse,\n} from './types'\n\n// ─── Wire constants ────────────────────────────────────────────────────────────\n\n/**\n * The multipart field name used for each image appended to an `/v1/images/edits` request.\n *\n * @remarks\n * Defined once, in this one place, so the WP-0 upstream-probe finding (whether the live API\n * expects the array-suffixed `'image[]'` form or the bare `'image'` form for multi-image edit\n * requests) can flip the wire behavior by changing a single constant, with every call site and\n * test following automatically.\n */\nexport const EDIT_IMAGE_FIELD_NAME = 'image[]'\n\n// ─── Adapter class ────────────────────────────────────────────────────────────\n\n/**\n * Media generation adapter for the OpenAI `/v1/images/generations` and `/v1/images/edits` wire\n * shapes.\n *\n * @remarks\n * Reusable: construct once, call {@link OpenAIGenerationAdapter.generate} /\n * {@link OpenAIGenerationAdapter.edit} as many times as needed.\n */\nexport class OpenAIGenerationAdapter {\n  readonly #options: OpenAIGenerationAdapterOptions\n\n  /**\n   * Whether this battery can run in the current environment. For the HTTP-backed OpenAI battery\n   * this is always `true` (a `fetch` is always resolvable); present for surface-parity with\n   * WebGPU-gated batteries.\n   */\n  public static isAvailable(): boolean {\n    return true\n  }\n\n  /**\n   * @param options - Constructor options. Validated eagerly.\n   * @throws {@link @nhtio/adk/batteries/generation/openai/exceptions!E_INVALID_OPENAI_GENERATION_OPTIONS} when `options` does not satisfy\n   *   {@link @nhtio/adk/batteries/generation/openai/validation!openAIGenerationOptionsSchema} (e.g. missing `model`).\n   */\n  constructor(options: unknown) {\n    this.#options = validateOptions(options)\n  }\n\n  /** See {@link OpenAIGenerationAdapter.isAvailable}. Instance alias for surface-parity. */\n  isAvailable(): boolean {\n    return OpenAIGenerationAdapter.isAvailable()\n  }\n\n  /**\n   * No-op warm-up. The OpenAI battery has no engine to preload; present for surface-parity with\n   * on-device generation batteries so callers can treat them interchangeably.\n   */\n  async preload(): Promise<void> {\n    // intentionally empty — nothing to warm for an HTTP-backed battery\n  }\n\n  /**\n   * No-op state reset. Present for surface-parity with on-device generation batteries.\n   */\n  reset(): void {\n    // intentionally empty — the OpenAI battery holds no engine state\n  }\n\n  /**\n   * Generates one or more images from a text prompt.\n   *\n   * @param prompt - The text prompt describing the desired image(s).\n   * @param opts - Per-call options (`n`, `size`, `quality`, `outputFormat`, `background`), each\n   *   falling back to the adapter's configured default when omitted.\n   * @returns One {@link GeneratedMediaOutput} per generated image.\n   * @throws {@link @nhtio/adk/batteries/generation/openai/exceptions!E_OPENAI_GENERATION_HTTP_ERROR} on a non-2xx response or transport failure.\n   * @throws {@link @nhtio/adk/batteries/generation/openai/exceptions!E_OPENAI_GENERATION_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.\n   * @throws {@link @nhtio/adk/batteries/generation/openai/exceptions!E_OPENAI_GENERATION_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.\n   */\n  async generate(prompt: string, opts?: OpenAIGenerateOptions): Promise<GeneratedMediaOutput[]> {\n    const model = this.#options.model\n    const size = opts?.size ?? this.#options.size\n    const quality = opts?.quality ?? this.#options.quality\n    const outputFormat = opts?.outputFormat ?? this.#options.outputFormat ?? 'png'\n    const background = opts?.background ?? this.#options.background\n\n    const body: OpenAIImagesGenerationRequestBody = {\n      model,\n      prompt,\n      ...(opts?.n !== undefined ? { n: opts.n } : {}),\n      ...(size !== undefined ? { size } : {}),\n      ...(quality !== undefined ? { quality } : {}),\n      ...(outputFormat !== undefined ? { output_format: outputFormat } : {}),\n      ...(background !== undefined ? { background } : {}),\n    }\n\n    const responseFormat = this.#resolveResponseFormat(model)\n    if (responseFormat !== undefined) {\n      body.response_format = responseFormat\n    }\n\n    const url = this.#url('/images/generations')\n    const headers = this.#headers(true)\n    const response = await this.#sendRequest(url, headers, JSON.stringify(body))\n    return this.#mapResponse(response, outputFormat)\n  }\n\n  /**\n   * Edits one or more source images from a text prompt, optionally constrained to a masked\n   * region.\n   *\n   * @param inputs - One image, or several images, in any {@link GenerationImageInput} form.\n   * @param prompt - The text prompt describing the desired edit.\n   * @param opts - Per-call options (`n`, `size`, `quality`, `mask`), each falling back to the\n   *   adapter's configured default when omitted (`mask` has no adapter-level default).\n   * @returns One {@link GeneratedMediaOutput} per edited image.\n   * @throws {@link @nhtio/adk/batteries/generation/openai/exceptions!E_OPENAI_GENERATION_HTTP_ERROR} on a non-2xx response or transport failure.\n   * @throws {@link @nhtio/adk/batteries/generation/openai/exceptions!E_OPENAI_GENERATION_REQUEST_TIMEOUT} when the handshake exceeds `requestTimeoutMs`.\n   * @throws {@link @nhtio/adk/batteries/generation/openai/exceptions!E_OPENAI_GENERATION_MALFORMED_RESPONSE} when the 2xx body is not the expected shape.\n   */\n  async edit(\n    inputs: GenerationImageInput | GenerationImageInput[],\n    prompt: string,\n    opts?: OpenAIEditOptions\n  ): Promise<GeneratedMediaOutput[]> {\n    const model = this.#options.model\n    const size = opts?.size ?? this.#options.size\n    const quality = opts?.quality ?? this.#options.quality\n    const outputFormat = this.#options.outputFormat ?? 'png'\n\n    const normalizedInputs = await Promise.all(\n      (Array.isArray(inputs) ? inputs : [inputs]).map((input) => toBytes(input))\n    )\n\n    const form = new FormData()\n    normalizedInputs.forEach(({ bytes, mimeType }, i) => {\n      form.append(\n        EDIT_IMAGE_FIELD_NAME,\n        new Blob([bytes as Uint8Array<ArrayBuffer>], { type: mimeType ?? 'image/png' }),\n        `input-${i + 1}.png`\n      )\n    })\n    form.append('prompt', prompt)\n    form.append('model', model)\n    if (opts?.n !== undefined) form.append('n', String(opts.n))\n    if (size !== undefined) form.append('size', size)\n    if (quality !== undefined) form.append('quality', quality)\n    if (opts?.mask !== undefined) {\n      const mask = await toBytes(opts.mask)\n      form.append(\n        'mask',\n        new Blob([mask.bytes as Uint8Array<ArrayBuffer>], { type: mask.mimeType ?? 'image/png' }),\n        'mask.png'\n      )\n    }\n\n    const url = this.#url('/images/edits')\n    // CRITICAL: no Content-Type here — fetch supplies the multipart boundary itself.\n    const headers = this.#headers(false)\n    const response = await this.#sendRequest(url, headers, form)\n    return this.#mapResponse(response, outputFormat)\n  }\n\n  // ─── internals ──────────────────────────────────────────────────────────────\n\n  #resolveResponseFormat(model: string): string | undefined {\n    const mode = this.#options.responseFormatMode ?? 'auto'\n    if (mode === 'omit') return undefined\n    if (mode === 'send') return 'b64_json'\n    // 'auto' — dall-e-* defaults to a hosted URL unless told otherwise; gpt-image-* always\n    // returns base64 and rejects the parameter entirely.\n    return model.startsWith('dall-e') ? 'b64_json' : undefined\n  }\n\n  #url(path: string): string {\n    const rawBase = this.#options.baseURL ?? 'https://api.openai.com/v1'\n    const baseURL = rawBase.endsWith('/') ? rawBase.slice(0, -1) : rawBase\n    return `${baseURL}${path}`\n  }\n\n  #headers(isJson: boolean): Record<string, string> {\n    const headers: Record<string, string> = {}\n    if (isJson) headers['Content-Type'] = 'application/json'\n    if (this.#options.apiKey) {\n      headers['Authorization'] = `Bearer ${this.#options.apiKey}`\n    }\n    if (this.#options.headers) {\n      Object.assign(headers, this.#options.headers)\n    }\n    return headers\n  }\n\n  #mapResponse(response: OpenAIImagesResponse, outputFormat: string): GeneratedMediaOutput[] {\n    if (!response || !Array.isArray(response.data) || response.data.length === 0) {\n      throw new E_OPENAI_GENERATION_MALFORMED_RESPONSE(['response contained no image data'])\n    }\n    return response.data.map((entry, i) => {\n      if (!entry.b64_json) {\n        throw new E_OPENAI_GENERATION_MALFORMED_RESPONSE([`entry ${i} is missing \"b64_json\"`])\n      }\n      return {\n        kind: 'image',\n        mimeType: `image/${outputFormat}`,\n        bytes: decodeBase64(entry.b64_json),\n        filename: `generated-${i + 1}.${outputFormat}`,\n      }\n    })\n  }\n\n  // Shared HTTP request core — clones the OpenAI Embeddings adapter's retry loop exactly\n  // (AbortController + requestTimeoutMs (0=disabled), retriable statuses, Retry-After honor,\n  // transport-error status 0, exhaustion throws last HTTP error) so retry/timeout/error semantics\n  // stay identical across every bundled OpenAI-style HTTP battery.\n  async #sendRequest(\n    url: string,\n    headers: Record<string, string>,\n    body: BodyInit\n  ): Promise<OpenAIImagesResponse> {\n    const retryCfg: Required<GenerationRetryConfig> = {\n      maxAttempts: this.#options.retry?.maxAttempts ?? 1,\n      baseDelayMs: this.#options.retry?.baseDelayMs ?? 500,\n      maxDelayMs: this.#options.retry?.maxDelayMs ?? 30_000,\n      retriableStatuses: this.#options.retry?.retriableStatuses ?? [429, 500, 502, 503, 504],\n      honorRetryAfter: this.#options.retry?.honorRetryAfter ?? true,\n    }\n\n    const fetchFn = this.#options.fetch ?? globalThis.fetch\n    const requestTimeoutMs = this.#options.requestTimeoutMs ?? 0\n    const maxAttempts = retryCfg.maxAttempts\n\n    let attempt = 1\n    while (attempt <= maxAttempts) {\n      const controller = new AbortController()\n      let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n      if (requestTimeoutMs > 0) {\n        timeoutHandle = setTimeout(() => controller.abort(), requestTimeoutMs)\n      }\n\n      let response: Response\n      try {\n        response = await fetchFn(url, {\n          method: 'POST',\n          headers,\n          body,\n          signal: controller.signal,\n        })\n      } catch (err) {\n        if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n        if (controller.signal.aborted) {\n          // Timed out before headers — retry if attempts remain.\n          if (attempt < maxAttempts) {\n            await sleepWithJitter(computeBackoff(attempt, retryCfg))\n            attempt += 1\n            continue\n          }\n          throw new E_OPENAI_GENERATION_REQUEST_TIMEOUT([requestTimeoutMs])\n        }\n        // Generic transport failure — retry if attempts remain, else surface as status 0.\n        if (attempt < maxAttempts) {\n          await sleepWithJitter(computeBackoff(attempt, retryCfg))\n          attempt += 1\n          continue\n        }\n        throw new E_OPENAI_GENERATION_HTTP_ERROR([0, isError(err) ? err.message : String(err)])\n      }\n      if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n\n      if (!response.ok) {\n        const status = response.status\n        const retriable = retryCfg.retriableStatuses.includes(status)\n        if (retriable && attempt < maxAttempts) {\n          let delay = computeBackoff(attempt, retryCfg)\n          if (retryCfg.honorRetryAfter) {\n            const ra = response.headers.get('Retry-After')\n            if (ra) {\n              const raMs = parseRetryAfter(ra)\n              if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs)\n            }\n          }\n          await sleepWithJitter(delay)\n          attempt += 1\n          continue\n        }\n        const detail = await response.text().catch(() => '')\n        throw new E_OPENAI_GENERATION_HTTP_ERROR([status, detail])\n      }\n\n      try {\n        return (await response.json()) as OpenAIImagesResponse\n      } catch (err) {\n        throw new E_OPENAI_GENERATION_MALFORMED_RESPONSE([isError(err) ? err.message : String(err)])\n      }\n    }\n\n    // Unreachable: the loop either returns or throws. Satisfies the type checker.\n    throw new E_OPENAI_GENERATION_HTTP_ERROR([0, 'retry loop exhausted without a response'])\n  }\n}\n"],"mappings":"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"}