import { buildApiUrl, isSystemProxyBaseUrl, resolveBackendApiUrl, type AiConfig } from "@/stores/use-config-store"; import { createClientId } from "@/lib/client-id"; import { createChannelTransport } from "@/services/api/channel-transport"; import type { GeminiPayload, ImageApiResponse, RequestOptions } from "@/services/api/image-contracts"; export function aiApiUrl(config: Pick, path: string) { return buildApiUrl(config.baseUrl, path); } export function aiHeaders(config: Pick, contentType?: string) { return { Authorization: `Bearer ${config.apiKey}`, ...(contentType ? { "Content-Type": contentType } : {}), ...(isSystemProxyBaseUrl(config.baseUrl) ? { "X-Canvas-Scene": "image", "X-Idempotency-Key": createClientId() } : {}), }; } export async function postVolcengineArkImage(config: Parameters[0], payload: Record, options?: RequestOptions) { return createChannelTransport(config, "image").postJson(aiApiUrl(config, "/images/generations"), payload, options); } export function geminiBaseUrl(config: Pick) { const normalizedBaseUrl = resolveBackendApiUrl(config.baseUrl).replace(/\/+$/, ""); const lowerBaseUrl = normalizedBaseUrl.toLowerCase(); return isSystemProxyBaseUrl(normalizedBaseUrl) || lowerBaseUrl.endsWith("/v1") || lowerBaseUrl.endsWith("/v1beta") ? normalizedBaseUrl : `${normalizedBaseUrl}/v1beta`; } export function geminiModelName(model: string) { return model.trim().replace(/^models\//, ""); } export function geminiApiUrl(config: Pick, action?: "generateContent" | "streamGenerateContent") { const baseUrl = geminiBaseUrl(config); if (!action) return `${baseUrl}/models`; return `${baseUrl}/models/${encodeURIComponent(geminiModelName(config.model))}:${action}`; } export function geminiHeaders(config: Pick) { return { "x-goog-api-key": config.apiKey, "Content-Type": "application/json", }; } export async function postChannelJSON(config: Parameters[0], upstreamUrl: string, body: unknown, options?: RequestOptions) { return createChannelTransport(config, "image").postJson(upstreamUrl, body, options); } export async function postGeminiJSON(config: Parameters[0] & Pick, body: unknown, options?: RequestOptions) { return createChannelTransport(config, "image").postJson(geminiApiUrl(config, "generateContent"), body, { ...options, headers: geminiHeaders(config), }); } export function imageChannelTransport(config: Parameters[0]) { return createChannelTransport(config, "image"); }