Add OpenRouter dedicated images API support
Fetches /api/v1/images/models in parallel with /models and merges results
into the model picker. Image-only models (e.g. Sourceful, Seedream, Flux
via this endpoint) were previously invisible since they don't appear in the
standard /models endpoint.
Models from the images API get usesImagesAPI=true and route through a new
generateImageAPIResponse() path in ChatViewModel that POSTs to /api/v1/images
with {model, prompt} instead of the chat completions endpoint. The response's
b64_json data is decoded and displayed via the existing GeneratedImagesView.
Cost is taken directly from the usage.cost field in the images API response
(USD per image) via a new rawCostUSD field on ChatResponse.Usage, bypassing
the token-based calculateCost() path used for chat models.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -420,6 +420,67 @@ struct ToolResultMessage: Encodable {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Images API — Model Discovery
|
||||
|
||||
struct OpenRouterImageModelsResponse: Codable {
|
||||
let data: [ImageModelData]
|
||||
|
||||
struct ImageModelData: Codable {
|
||||
let id: String
|
||||
let name: String
|
||||
let description: String?
|
||||
let architecture: Architecture?
|
||||
let supportsStreaming: Bool?
|
||||
|
||||
struct Architecture: Codable {
|
||||
let inputModalities: [String]?
|
||||
let outputModalities: [String]?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case inputModalities = "input_modalities"
|
||||
case outputModalities = "output_modalities"
|
||||
}
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, name, description, architecture
|
||||
case supportsStreaming = "supports_streaming"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Images API — Generation Response
|
||||
|
||||
struct OpenRouterImageGenerationResponse: Codable {
|
||||
let created: Int?
|
||||
let data: [ImageData]
|
||||
let usage: Usage?
|
||||
|
||||
struct ImageData: Codable {
|
||||
let b64Json: String
|
||||
let mediaType: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case b64Json = "b64_json"
|
||||
case mediaType = "media_type"
|
||||
}
|
||||
}
|
||||
|
||||
struct Usage: Codable {
|
||||
let promptTokens: Int
|
||||
let completionTokens: Int
|
||||
let totalTokens: Int
|
||||
let cost: Double?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case promptTokens = "prompt_tokens"
|
||||
case completionTokens = "completion_tokens"
|
||||
case totalTokens = "total_tokens"
|
||||
case cost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Error Response
|
||||
|
||||
struct OpenRouterErrorResponse: Codable {
|
||||
|
||||
Reference in New Issue
Block a user