openrouter

package
v0.1.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 14, 2025 License: MIT Imports: 27 Imported by: 0

README

OpenRouter Input Plugin

Internal plugin for generating images using OpenRouter.ai models via their REST API.

Features

  • Direct integration with OpenRouter.ai API
  • Support for multiple image generation models (Flux, DALL-E, Gemini, etc.)
  • Automatic model selection (cheapest/free models preferred)
  • Live pricing from API with --ai.list-models
  • Automatic image caching
  • Region/border colour sampling for ambient lighting
  • Wallpaper passthrough support
  • Multiple aspect ratios
  • Deterministic colour extraction with content-based seeding

Prerequisites

Set your OpenRouter API key:

export OPENROUTER_API_KEY="your-api-key-here"

Get an API key at: https://openrouter.ai/keys

Usage

Basic Usage

The default model is auto, which automatically selects the cheapest available image generation model (preferring free models).

tinct generate -i openrouter --ai.prompt "sunset over mountains" -o kitty
With Specific Model
tinct generate -i openrouter \
  --ai.prompt "cyberpunk city at night" \
  --ai.model "google/gemini-2.5-flash-image-preview" \
  --aspect-ratio "16:9" \
  -o kitty
With Ambient Lighting
tinct generate -i openrouter \
  --ai.prompt "forest landscape" \
  --extract-ambience \
  --regions 16 \
  -o wled-ambient
List Available Models
tinct generate -i openrouter --ai.list-models

This will show all available image generation models with their current pricing, sorted by cost (free first).

Available Flags

The plugin uses three categories of flags:

Shared AI Flags (ai.* prefix)

These flags are shared across all AI image generation plugins.

Flag Type Default Description
--ai.prompt string required Text description for AI image generation
--ai.model string auto AI model to use (auto selects cheapest)
--ai.list-models bool false List available AI models and exit
--ai.no-extended-prompt bool false Disable automatic wallpaper prompt enhancements
--ai.no-negative-prompt bool false Disable default negative prompt
--ai.negative-prompt string - Custom negative prompt to discourage certain elements
Common Flags (unprefixed)

These flags are shared across multiple input plugins.

Flag Type Default Description
--count int 32 Number of colours to extract
--aspect-ratio string 16:9 Image aspect ratio (1:1, 3:4, 4:3, 9:16, 16:9)
--cache bool true Enable image caching
--cache-dir string ~/.cache/tinct/generated Cache directory
--cache-filename string auto Custom cache filename
--cache-overwrite bool false Overwrite existing cache
--extract-ambience bool false Extract edge/corner colours
--regions int 8 Number of edge regions (4, 8, 12, 16)
--sample-percent int 10 Percentage of edge to sample (1-50)
--sample-method string average Sampling method (average or dominant)
--seed-mode string content Seed mode (content, manual, random)
--seed-value int64 0 Manual seed value
Plugin-Specific Flags (openrouter.* prefix)
Flag Type Default Description
--openrouter.prefer-free bool true Prefer free models when using auto selection

Auto Model Selection

When --ai.model is set to auto (the default), the plugin:

  1. Fetches the list of available models from OpenRouter API
  2. Filters to only models that support image output
  3. Sorts by cost (cheapest first)
  4. If --openrouter.prefer-free is enabled (default), selects a free model if available
  5. Otherwise selects the cheapest model

This ensures you always use the most cost-effective option without needing to track model availability.

Available Models

Use --ai.list-models to see current models and pricing. Common image-capable models include:

Model ID Description
google/gemini-2.5-flash-image Gemini Flash image generation
black-forest-labs/flux.2-pro Flux 2 Pro
black-forest-labs/flux.2-flex Flux 2 Flex
sourceful/riverflow-v2-standard-preview Riverflow V2 Standard
Various others See --ai.list-models for current list

Note: Not all OpenRouter models appear in the API response used by --ai.list-models. You can use any valid model ID with --ai.model, even if not listed. For the complete list of image generation models, visit: https://openrouter.ai/models?fmt=cards&input_modalities=image%2Ctext&output_modalities=image

Implementation Details

Interfaces Implemented
  • input.Plugin - Core plugin interface
  • input.WallpaperProvider - Provides wallpaper path for --set-wallpaper flag
API Integration

Uses the OpenRouter.ai REST API:

  • Endpoint: https://openrouter.ai/api/v1/chat/completions
  • Authentication: Bearer token via OPENROUTER_API_KEY
  • Image Generation: Uses modalities: ["image", "text"] parameter
  • Response: Base64-encoded PNG images in the response message
Dependencies
  • Uses tinct's internal utilities:
    • internal/colour - K-means colour extraction
    • internal/image - Smart image loading
    • internal/plugin/input/shared/regions - Region sampling
    • internal/plugin/input/shared/aiflags - Shared AI flags
    • internal/plugin/input/shared/commonflags - Shared common flags
Architecture
  1. Generate() - Main entry point

    • Auto-selects model if set to "auto"
    • Validates configuration
    • Determines cache path
    • Generates image via OpenRouter API
    • Extracts colours using k-means
    • Optionally extracts region colours for ambient lighting
  2. Image Generation - Calls chat/completions API

    • Enhances prompt for wallpaper suitability
    • Configures aspect ratio (model dependent)
    • Parses base64 image data from response
    • Writes image bytes to cache
  3. Model Selection - Automatic cheapest model selection

    • Fetches models from /api/v1/models
    • Filters for image output capability
    • Sorts by pricing
    • Prefers free models by default
  4. Colour Extraction - Uses tinct's k-means extractor

    • Supports content-based seeding for deterministic results
    • Combines main palette with region colours (if enabled)
    • Applies proper weights (90% main, 10% regions)

Testing

The plugin can be tested with dry-run mode:

# Test validation
tinct generate -i openrouter --dry-run -o kitty
# Error: input plugin validation failed: --ai.prompt is required

# Test with prompt (dry-run skips API call)
tinct generate -i openrouter --ai.prompt "test" --dry-run -o kitty

# List models (does not require prompt)
tinct generate -i openrouter --ai.list-models

Cost Considerations

  • Use auto model selection (default) to always use the cheapest available model
  • Enable --openrouter.prefer-free (enabled by default) to prioritize free models
  • Enable caching to minimize costs by reusing generated images
  • Use --ai.list-models to see current pricing before generating

Comparison with Google GenAI Plugin

Feature OpenRouter Google GenAI
Model Variety Many providers (Flux, DALL-E, etc.) Google models only
Pricing Variable, includes free options Per-model pricing
Auto Selection Cheapest model by default Manual selection
API Key OPENROUTER_API_KEY GOOGLE_API_KEY
Negative Prompts Via prompt enhancement Native API support

Documentation

Overview

Package openrouter provides an input plugin for generating images using OpenRouter.ai models.

Index

Constants

View Source
const (
	// RegionWeightFactor determines how much weight region colors receive
	// relative to main palette colors. Region colors get 10% of the total weight.
	RegionWeightFactor = 0.1

	// MainColorWeightRatio is the proportion of total weight allocated to
	// main palette colors when region extraction is enabled (90%).
	MainColorWeightRatio = 0.9
)

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	Message string      `json:"message"`
	Type    string      `json:"type"`
	Code    interface{} `json:"code"` // Can be string or number depending on provider
}

APIError represents an API error response.

func (*APIError) CodeString

func (e *APIError) CodeString() string

CodeString returns the error code as a string.

type Architecture

type Architecture struct {
	Modality         string   `json:"modality"`
	InputModalities  []string `json:"input_modalities"`
	OutputModalities []string `json:"output_modalities"`
	Tokenizer        string   `json:"tokenizer"`
}

Architecture contains model capability information.

type ChatCompletionRequest

type ChatCompletionRequest struct {
	Model       string       `json:"model"`
	Messages    []Message    `json:"messages"`
	Modalities  []string     `json:"modalities,omitempty"`
	ImageConfig *ImageConfig `json:"image_config,omitempty"`
	MaxTokens   int          `json:"max_tokens,omitempty"`
}

ChatCompletionRequest represents the request body for OpenRouter chat completions.

type ChatCompletionResponse

type ChatCompletionResponse struct {
	ID      string    `json:"id"`
	Model   string    `json:"model"`
	Choices []Choice  `json:"choices"`
	Error   *APIError `json:"error,omitempty"`
}

ChatCompletionResponse represents the response from OpenRouter.

type Choice

type Choice struct {
	Index        int             `json:"index"`
	Message      ResponseMessage `json:"message"`
	FinishReason string          `json:"finish_reason"`
}

Choice represents a completion choice.

type ImageConfig

type ImageConfig struct {
	AspectRatio string `json:"aspect_ratio,omitempty"`
}

ImageConfig contains image generation configuration.

type ImageData

type ImageData struct {
	Type     string   `json:"type"`
	ImageURL ImageURL `json:"image_url"`
}

ImageData represents an image in the response.

type ImageMetadata

type ImageMetadata struct {
	// Generation parameters
	Prompt         string `json:"prompt"`
	EnhancedPrompt string `json:"enhanced_prompt,omitempty"`
	NegativePrompt string `json:"negative_prompt,omitempty"`
	Model          string `json:"model"`
	AspectRatio    string `json:"aspect_ratio"`

	// Generation details
	CreatedAt  time.Time `json:"created_at"`
	ImagePath  string    `json:"image_path"`
	ImageSize_ int       `json:"image_bytes"`

	// API response data
	FinishReason string `json:"finish_reason,omitempty"`
}

ImageMetadata contains metadata about a generated image.

type ImageURL

type ImageURL struct {
	URL string `json:"url"`
}

ImageURL contains the image URL data.

type Message

type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

Message represents a chat message.

type Model

type Model struct {
	ID           string       `json:"id"`
	Name         string       `json:"name"`
	Description  string       `json:"description"`
	Created      int64        `json:"created"`
	Architecture Architecture `json:"architecture"`
	Pricing      Pricing      `json:"pricing"`
	TopProvider  *TopProvider `json:"top_provider,omitempty"`
}

Model represents a model in the API response.

type ModelsResponse

type ModelsResponse struct {
	Data []Model `json:"data"`
}

ModelsResponse represents the response from the models API.

type Plugin

type Plugin struct {
	// contains filtered or unexported fields
}

Plugin implements the input.Plugin interface for OpenRouter image generation.

func New

func New() *Plugin

New creates a new OpenRouter input plugin with default settings.

func (*Plugin) Description

func (p *Plugin) Description() string

Description returns a human-readable description.

func (*Plugin) Generate

func (p *Plugin) Generate(ctx context.Context, opts input.GenerateOptions) (*colour.Palette, error)

Generate creates an image using OpenRouter and extracts colors.

func (*Plugin) GetFlagHelp

func (p *Plugin) GetFlagHelp() []input.FlagHelp

GetFlagHelp returns help information for all plugin flags.

func (*Plugin) Name

func (p *Plugin) Name() string

Name returns the plugin name.

func (*Plugin) RegisterFlags

func (p *Plugin) RegisterFlags(cmd *cobra.Command)

RegisterFlags registers plugin-specific flags.

func (*Plugin) Validate

func (p *Plugin) Validate() error

Validate checks if required inputs are configured.

func (*Plugin) Version

func (p *Plugin) Version() string

Version returns the plugin version.

func (*Plugin) WallpaperPath

func (p *Plugin) WallpaperPath() string

WallpaperPath returns the path to the generated image for wallpaper use.

type Pricing

type Pricing struct {
	Prompt     string `json:"prompt"`
	Completion string `json:"completion"`
	Request    string `json:"request"`
	Image      string `json:"image"`
}

Pricing contains model pricing information.

type PricingInfo

type PricingInfo struct {
	Type           PricingType
	ImageCost      float64 // Cost per image
	RequestCost    float64 // Cost per request
	PromptCost     float64 // Cost per input token
	CompletionCost float64 // Cost per output token
}

PricingInfo contains parsed pricing information for a model.

type PricingType

type PricingType int

PricingType indicates the pricing model used by a model.

const (
	PricingFree PricingType = iota
	PricingPerImage
	PricingPerRequest
	PricingPerToken
)

type ResponseMessage

type ResponseMessage struct {
	Role    string      `json:"role"`
	Content string      `json:"content"`
	Images  []ImageData `json:"images,omitempty"`
}

ResponseMessage represents the assistant's response message.

type TopProvider

type TopProvider struct {
	ContextLength       int  `json:"context_length"`
	MaxCompletionTokens int  `json:"max_completion_tokens"`
	IsModerated         bool `json:"is_moderated"`
}

TopProvider contains provider-specific information.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL