Restore MiniMax media routing parity across image and video flows
The server now keeps portable image ratio normalization, enforces documented Seedream size presets, routes MiniMax img2img through generations-style payloads, and submits Hailuo video variants through the video generations API with proper reference-image handling. Constraint: The deployed test chain relies on popiartServer as the lowest-risk place to adapt provider-specific routing without broad newapi changes Rejected: Expand newapi relay modes for every MiniMax image/video branch | larger blast radius than needed for the verified server-managed flows Confidence: high Scope-risk: moderate Reversibility: clean Directive: Keep MiniMax-specific media routing in popiartServer unless upstream newapi adapters are upgraded to the same contract Tested: go test ./internal/server -run TestInferRouteKeyForModelRecognizesViduAsVideo|TestGenerate|TestResolve|TestSubmitMiniMaxVideoTask|TestExecuteImageToImageJobUsesGenerationsPathForMiniMax|TestExecuteImageToVideoJob|TestResolveVideoReferencesSupportsImagesArray Not-tested: Full PopiNewAPI unit suite (blocked earlier by external module checksum drift in local checkout)
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExecuteImageToImageJobUsesGenerationsPathForMiniMax(t *testing.T) {
|
||||
var gotPath string
|
||||
var gotBody map[string]any
|
||||
|
||||
var apiSrv *httptest.Server
|
||||
apiSrv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/reference.png":
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
_, _ = w.Write(tinyPNG(t))
|
||||
case "/v1/images/generations":
|
||||
gotPath = r.URL.Path
|
||||
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
|
||||
t.Fatalf("decode request body: %v", err)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{
|
||||
"created": 1711234567,
|
||||
"data": [{"url":"` + strings.TrimRight(apiSrv.URL, "/") + `/generated.png"}]
|
||||
}`))
|
||||
case "/generated.png":
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
_, _ = w.Write(tinyPNG(t))
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}))
|
||||
defer apiSrv.Close()
|
||||
|
||||
cfg := Config{
|
||||
NewAPIBaseURL: apiSrv.URL,
|
||||
SQLitePath: filepath.Join(t.TempDir(), "popiart.db"),
|
||||
SkillhubDir: makeEmptySkillhub(t),
|
||||
SessionSecret: "test-secret",
|
||||
PublicBaseURL: "http://127.0.0.1:8080",
|
||||
}
|
||||
server, err := NewWithConfig(cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("NewWithConfig: %v", err)
|
||||
}
|
||||
server.newapi.httpClient = apiSrv.Client()
|
||||
|
||||
sessionToken, _, ok, err := server.store.createSession("sk-test-upstream")
|
||||
if err != nil {
|
||||
t.Fatalf("createSession: %v", err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("expected session creation to succeed")
|
||||
}
|
||||
current, exists, err := server.store.session(sessionToken)
|
||||
if err != nil {
|
||||
t.Fatalf("load session: %v", err)
|
||||
}
|
||||
if !exists {
|
||||
t.Fatal("expected stored session")
|
||||
}
|
||||
|
||||
record, _, err := server.store.createJob(
|
||||
"",
|
||||
"image.img2img",
|
||||
"image-01",
|
||||
"sync_result",
|
||||
map[string]any{
|
||||
"prompt": "turn this into a poster",
|
||||
"image": apiSrv.URL + "/reference.png",
|
||||
"aspect_ratio": "3:4",
|
||||
"response_format": "url",
|
||||
},
|
||||
"",
|
||||
"normal",
|
||||
"",
|
||||
current,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("createJob: %v", err)
|
||||
}
|
||||
|
||||
server.executeImageToImageJob(record)
|
||||
|
||||
if gotPath != "/v1/images/generations" {
|
||||
t.Fatalf("expected minimax img2img to use /v1/images/generations, got %q", gotPath)
|
||||
}
|
||||
if gotBody["model"] != "image-01" {
|
||||
t.Fatalf("unexpected model payload: %#v", gotBody["model"])
|
||||
}
|
||||
if gotBody["image"] != apiSrv.URL+"/reference.png" {
|
||||
t.Fatalf("expected generations payload image field, got %#v", gotBody["image"])
|
||||
}
|
||||
|
||||
done, exists, err := server.store.getJob(current.User.ID, record.JobID)
|
||||
if err != nil {
|
||||
t.Fatalf("getJob: %v", err)
|
||||
}
|
||||
if !exists {
|
||||
t.Fatal("expected stored job")
|
||||
}
|
||||
if done.Status != "done" {
|
||||
t.Fatalf("expected job done, got %#v", done.Status)
|
||||
}
|
||||
if len(done.ArtifactIDs) != 1 {
|
||||
t.Fatalf("expected one artifact id, got %#v", done.ArtifactIDs)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user