Skip to main content

tena

tena provides a small async wrapper for text-to-image model calls.

Install

Prerequisites:

  • Python 3.10+
  • uv

Dependencies are declared in pyproject.toml:

  • openai
  • google-genai
  • httpx
  • pytest
  • python-dotenv

Image generation

Python API

Use draw with a registered model_path. The function returns a list of GeneratedImage objects. Each object contains image bytes and a MIME type.

import asyncio
from pathlib import Path

from tena import draw, suffix_for_mime_type


async def main() -> None:
    images = await draw(
        model_path="openrouter/gpt-image-2",
        prompt="A clean product photo of a ceramic cup",
        size="1024x1024",
        number=1,
        input_images=[
            "./reference-1.png",
            "https://example.com/reference-2.png",
        ],
    )

    image = images[0]
    suffix = suffix_for_mime_type(image.mime_type)
    Path(f"result{suffix}").write_bytes(image.data)


asyncio.run(main())

The package exports the reusable API from tena/__init__.py. tena/main.py is only the CLI entrypoint; core image generation logic lives in tena/image.py.

CLI

The tena command is a thin wrapper around the Python API.

Generate one image and write it to a required output path:

uv run tena --model-path openrouter/gpt-image-2 --prompt "A clean product photo of a ceramic cup" --output ./result.png --size 1024x1024

The output path supports ~, including --output ~/Downloads/result.png and --output=~/Downloads/result.png.

Use - as the prompt to read from stdin:

echo "A simple red cube on a clean white background" | uv run tena --model-path openrouter/gpt-image-2 --prompt - --output ./result.png --size 1024x1024

Generate multiple images with --number. The first image uses the exact output path, and later images are numbered:

uv run tena --model-path zenmux/gpt-image-2 --prompt "A blue sphere" --output ./result.png --number 2 --size 1024x1024

This writes result.png and result-2.png.

Provide reference images with repeated --input-image arguments. Each value can be a local file path or an http/https URL:

uv run tena \
  --model-path openrouter/gpt-image-2 \
  --prompt "Create a studio product photo using the reference objects" \
  --input-image ./reference-1.png \
  --input-image https://example.com/reference-2.png \
  --output ./result.png \
  --size 1024x1024

URL images are downloaded to /tmp/tena/input_images and cached by URL, so the same URL is reused on later runs instead of downloaded again.

CLI logs are written to stderr and default to INFO. The generated output paths are still written to stdout. Use --log-level WARNING to hide normal progress logs, or --log-level DEBUG for diagnostic details:

uv run tena --model-path openrouter/gpt-image-2 --prompt "A blue sphere" --output ./result.png --log-level WARNING

INFO logs include concise request metadata, URL cache/download status, byte counts, and elapsed times. DEBUG logs include more detailed SDK and input image diagnostics. Logs do not include API keys, full prompts, full input URLs, or image data.

Return object

@dataclass(frozen=True)
class GeneratedImage:
    data: bytes
    mime_type: str

Registered models

Models are currently registered in code. model_path is the lookup key, and model_realname is the model id sent to the upstream API.

@dataclass(frozen=True)
class ImageModel:
    model_displayname: str
    model_realname: str
    client: Literal[
        "openai",
        "openrouter",
        "gemini-interactions",
        "gemini-generate-content",
    ]
    api_key_env: str
    base_url: str | None = None
    default_mime_type: str = "image/png"

Current model paths:

  • 302ai/gpt-image-2
  • 302ai/gemini-3.1-flash-image-preview
  • google/gemini-3.1-flash-image
  • openrouter/gpt-image-2
  • zenmux/gpt-image-2
  • zenmux/gemini-3.1-flash-image

client means which upstream API contract is used. OpenAI-compatible gateways can use client="openai" with a custom base_url. OpenRouter uses client="openrouter" and calls its /images unified image generation endpoint directly.

Gemini image models use two different API contracts:

  • gemini-interactions uses Google's Interactions API and is used for direct Google Gemini access.
  • gemini-generate-content uses the Generate Content API and is used for Gemini-compatible gateways such as Zenmux and 302AI.

Environment variables

Set the API key required by the selected model entry. Values can be provided by the process environment, a project-root .env file, or ~/.tena/config/.env:

  • OPENROUTER_API_KEY
  • ZENMUX_API_KEY
  • AI302_API_KEY
  • GEMINI_API_KEY

Dotenv files are loaded in this order: project-root .env, then ~/.tena/config/.env. Later values override earlier values.

Gemini size format

Gemini image models use a single size string that is parsed into the Gemini image response configuration. Interactions requests use response_format; Generate Content requests use image_config.

  • 16:9 -> aspect_ratio
  • 2K or 4K -> image_size
  • 16:9@2K -> both aspect_ratio and image_size
  • auto -> no explicit Gemini response_format

OpenAI-compatible and OpenRouter clients pass size through as the API size parameter.

Not implemented yet

The following parameters are part of the public function signature but are not implemented yet:

  • web_search

Passing web_search raises NotImplementedError.

Integration tests

Live image generation tests are grouped under tests/integration. Set the API key for the model you want to test in the environment or in the project .env file:

  • OPENROUTER_API_KEY for openrouter/gpt-image-2
  • ZENMUX_API_KEY for zenmux/gpt-image-2

Then run:

pytest tests/integration

Tests with missing API keys are skipped. When a test succeeds, it writes the generated image to ~/Downloads with a tena-<provider>-gpt-image-2 filename prefix.

Metadata

Release files for tena 0.1.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tena 0.1.8
File Size Uploaded Provenance Actions
tena-0.1.8.tar.gz 72.4 kB Without provenance Details for tena-0.1.8.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tena 0.1.8
File Interpreter ABI Platform Actions
tena-0.1.8-py3-none-any.whl Python 3 none any Details for tena-0.1.8-py3-none-any.whl

Total release size: 84.8 kB

Release files / tena-0.1.8.tar.gz

Download URL tena-0.1.8.tar.gz
Size 72.4 kB
Tags Source
SHA-256 checksum
How to use checksums
22ce22d9f412632e63b1ba5e2aa8adf57430a727f476110d6c299c5bef0b3160
BLAKE2b-256 checksum
How to use checksums
a2abcfc783cf7559ed87d3d8fe75ae20f89506c7ae376be164dfc1bacc6ec95b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.13

Release files / tena-0.1.8-py3-none-any.whl

Download URL tena-0.1.8-py3-none-any.whl
Size 12.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b30297d1530c6a224d101e1921dc8e80e33d637949c91f1cf8a5630607b86b47
BLAKE2b-256 checksum
How to use checksums
e3a1bff8974cfe21a5915d3271f9d964d9d08189fbecbac5007fa0c5b0479e66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.13

Security for tena 0.1.8

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page