Add gpt-image-2.5-flare (new default) and gpt-image-2.5-sunburst, released 2026-09-08. Both support custom WxH sizes, transparent backgrounds and the new xhigh/max quality tiers; gpt-image-2 falls back to high when an extended tier is selected. Retire gpt-image-1 and gpt-image-1.5 ahead of their 2026-10-23 and 2026-12-01 shutdown dates. That drops the input_fidelity parameter with them: gpt-image-2 and 2.5 always use high input fidelity and error if it is sent, so no shipped model can use it. With every remaining model accepting custom sizes, the custom_size capability flag became constant-true; removing it collapses resolve_size to a validation call and drops its unused model argument. BREAKING CHANGE: saved workflows selecting gpt-image-1 or gpt-image-1.5 must have their model widget re-picked.
78 lines
3.0 KiB
Python
78 lines
3.0 KiB
Python
import json
|
|
import imagent.client as client
|
|
|
|
|
|
def test_env_var_takes_precedence(monkeypatch, tmp_path):
|
|
monkeypatch.setenv("OPENAI_API_KEY", "sk-from-env")
|
|
monkeypatch.setattr(client, "_CONFIG_PATH", tmp_path / "config.json")
|
|
(tmp_path / "config.json").write_text(json.dumps({"OPENAI_API_KEY": "sk-from-file"}))
|
|
assert client.resolve_api_key() == "sk-from-env"
|
|
|
|
|
|
def test_config_file_fallback(monkeypatch, tmp_path):
|
|
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
|
cfg = tmp_path / "config.json"
|
|
cfg.write_text(json.dumps({"OPENAI_API_KEY": "sk-from-file"}))
|
|
monkeypatch.setattr(client, "_CONFIG_PATH", cfg)
|
|
assert client.resolve_api_key() == "sk-from-file"
|
|
|
|
|
|
def test_missing_key_returns_none(monkeypatch, tmp_path):
|
|
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
|
monkeypatch.setattr(client, "_CONFIG_PATH", tmp_path / "nope.json")
|
|
assert client.resolve_api_key() is None
|
|
|
|
|
|
def test_placeholder_key_is_ignored(monkeypatch, tmp_path):
|
|
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
|
cfg = tmp_path / "config.json"
|
|
cfg.write_text(json.dumps({"OPENAI_API_KEY": "sk-..."}))
|
|
monkeypatch.setattr(client, "_CONFIG_PATH", cfg)
|
|
assert client.resolve_api_key() is None
|
|
|
|
|
|
def test_model_catalog_defaults():
|
|
assert client.DEFAULT_MODEL == "gpt-image-2.5-flare"
|
|
assert set(client.MODELS) == {"gpt-image-2", "gpt-image-2.5-flare",
|
|
"gpt-image-2.5-sunburst"}
|
|
assert "gpt-image-1-mini" not in client.MODELS
|
|
assert "gpt-image-2-2026-04-21" not in client.MODELS
|
|
assert "gpt-image-2.5-flare-2026-09-08" not in client.MODELS
|
|
# Retired: both shut down before this release's models do.
|
|
assert "gpt-image-1" not in client.MODELS
|
|
assert "gpt-image-1.5" not in client.MODELS
|
|
assert all("dall-e" not in m for m in client.MODELS)
|
|
|
|
|
|
def test_friendly_error_maps_403_and_429():
|
|
assert "verif" in client.friendly_error(Exception("Error code: 403 - org not verified")).lower()
|
|
assert "rate" in client.friendly_error(Exception("Error code: 429 - too many requests")).lower()
|
|
|
|
|
|
def test_malformed_config_returns_none(monkeypatch, tmp_path, caplog):
|
|
import logging
|
|
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
|
cfg = tmp_path / "config.json"
|
|
cfg.write_text("{bad json")
|
|
monkeypatch.setattr(client, "_CONFIG_PATH", cfg)
|
|
with caplog.at_level(logging.WARNING, logger="imagent"):
|
|
assert client.resolve_api_key() is None
|
|
assert "could not read" in caplog.text
|
|
|
|
|
|
def test_env_placeholder_is_ignored(monkeypatch, tmp_path):
|
|
monkeypatch.setenv("OPENAI_API_KEY", "your_openai_api_key_here")
|
|
monkeypatch.setattr(client, "_CONFIG_PATH", tmp_path / "nope.json")
|
|
assert client.resolve_api_key() is None
|
|
|
|
|
|
def test_friendly_error_uses_status_code():
|
|
class FakeAPIError(Exception):
|
|
status_code = 403
|
|
|
|
class FakeRateError(Exception):
|
|
status_code = 429
|
|
|
|
assert "verif" in client.friendly_error(FakeAPIError("denied")).lower()
|
|
assert "rate" in client.friendly_error(FakeRateError("slow down")).lower()
|