mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-12 14:15:00 +00:00
OpenAI shipped GPT Image 2.5 on 2026-09-08 as two model IDs rather than one: flare is tuned for speed, sunburst for editing precision. Both accept text and image input and run on /images/generations, /images/edits and the Responses API, which is the path the native image_generation tool already uses. Flare replaces gpt-image-2 as the default because OpenAI reports higher quality at roughly half the latency, which suits create_image's one-shot call. Both gpt-image-2 and gpt-image-1.5 stay on the whitelist, so a saved image_model keeps working untouched. Also in this change: - The rejection message is now built from the whitelist itself instead of a hand-written string that drifts whenever a model is added. - codex_build.go uses the DefaultImageModel constant instead of hardcoding "gpt-image-2", so the inline chat path cannot drift from the shared default. - Both new models join the isEditModel branch so reference images route to /images/edits. - ParamField gains an optional labelKey, letting the dropdown read its label from i18n instead of showing English inside a translated UI. It passes a defaultValue, so a missing key degrades to the literal rather than breaking. - Locale keys added to all five catalogs; ko was missing the whole mediaChain.imageModel* group. Surface parity: the desktop UI is unchanged because sortable-provider-card renders no param form and passes params through as Record<string, unknown>. The CLI is unchanged because cmd/ exposes no image-model flag. The API contract is unchanged because image_model lives in the free-form params map; only the backend whitelist widened. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
package providers
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestValidateImageModel(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{name: "empty falls back to default", input: "", want: DefaultImageModel},
|
|
{name: "flare", input: "gpt-image-2.5-flare", want: "gpt-image-2.5-flare"},
|
|
{name: "sunburst", input: "gpt-image-2.5-sunburst", want: "gpt-image-2.5-sunburst"},
|
|
{name: "previous generation", input: "gpt-image-2", want: "gpt-image-2"},
|
|
{name: "legacy", input: "gpt-image-1.5", want: "gpt-image-1.5"},
|
|
{name: "unversioned 2.5 is not a real model id", input: "gpt-image-2.5", wantErr: true},
|
|
{name: "unrelated model", input: "dall-e-3", wantErr: true},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got, err := ValidateImageModel(tc.input)
|
|
if tc.wantErr {
|
|
if err == nil {
|
|
t.Fatalf("ValidateImageModel(%q) = %q, want error", tc.input, got)
|
|
}
|
|
// The error must list the allowed models so the caller can self-correct.
|
|
if !strings.Contains(err.Error(), DefaultImageModel) {
|
|
t.Errorf("error %q does not mention the default model %q", err, DefaultImageModel)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("ValidateImageModel(%q) returned error: %v", tc.input, err)
|
|
}
|
|
if got != tc.want {
|
|
t.Errorf("ValidateImageModel(%q) = %q, want %q", tc.input, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestDefaultImageModelIsAllowed guards against the default drifting out of the
|
|
// whitelist, which would make every create_image call with no explicit model fail.
|
|
func TestDefaultImageModelIsAllowed(t *testing.T) {
|
|
if !allowedImageModels[DefaultImageModel] {
|
|
t.Fatalf("DefaultImageModel %q is missing from allowedImageModels", DefaultImageModel)
|
|
}
|
|
}
|