fix(creation): 创作与模型配置 - 修复附件预览隐藏和 MiniMax 2K 能力校验 (#433)

This commit is contained in:
MasterChiefCN authored and GitHub committed 2026-09-07 17:05:47 +08:00
1 parent d4f3a7e7d3
commit 469627c792
5 files changed
+86 -6

No files matched your search

@@ -65,6 +65,41 @@ func TestMatchCapabilityTreatsVideoResolutionSuffixAsEquivalent(t *testing.T) {
}
}
func TestVideoResolutionAliasesAcrossProductAndPricedRoutes(t *testing.T) {
product := CapabilitySpec{
Version: 1, Capability: "video",
Options: map[string]OptionConstraint{"vquality": {Values: []any{"768P", "2K"}}},
}
route := capabilitySpecWithPriceTiers(product, model.ChannelModel{
PriceTiers: []model.ChannelModelPriceTier{
{Resolution: "768P", Enabled: true, PriceConfigured: true},
{Resolution: "2K", Enabled: true, PriceConfigured: true},
},
})
if err := validateProductSpecWithinRoutes(product, []CapabilitySpec{route}); err != nil {
t.Fatalf("2K product rejected against priced route: %v", err)
}
for _, resolution := range []string{"2K", "2k", "1440P", "1440"} {
intent := ModelRequestIntent{Capability: "video", Options: map[string]any{
"vquality": normalizeModelRequestOption("vquality", resolution),
}}
for name, spec := range map[string]CapabilitySpec{"product": product, "route": route} {
if match := MatchCapability(spec, intent); !match.Matched {
t.Errorf("%s rejected %s: %#v", name, resolution, match)
}
}
}
unsupported := CapabilitySpec{Version: 1, Capability: "video", Options: map[string]OptionConstraint{
"vquality": {Values: []any{"4K"}},
}}
if err := validateProductSpecWithinRoutes(unsupported, []CapabilitySpec{route}); err == nil {
t.Fatal("2K route accepted unsupported 4K product")
}
if capabilityOptionValuesEqual("quality", "2K", "1440p") {
t.Fatal("video aliases must not affect image quality")
}
}
func TestValidateProductSpecWithinRoutesRejectsUnsupportedCapabilityValue(t *testing.T) {
routes := []CapabilitySpec{
{
+3 -2
View File
@@ -358,8 +358,9 @@ func capabilityOptionValuesEqual(name string, candidate any, value any) bool {
left := normalizedScalar(candidate)
right := normalizedScalar(value)
if canonicalCapabilityOptionName(name) == "vquality" {
left = strings.TrimSuffix(left, "p")
right = strings.TrimSuffix(right, "p")
// Compare using the same aliases as request intents and price tiers.
left = strings.TrimSuffix(normalizedScalar(normalizeModelRequestOption(name, left)), "p")
right = strings.TrimSuffix(normalizedScalar(normalizeModelRequestOption(name, right)), "p")
}
return left == right
}
+33
View File
@@ -2706,6 +2706,39 @@ func TestRunMiniMaxVideoTaskCreatesPollsAndDownloads(t *testing.T) {
}
}
func TestRunMiniMaxVideoTaskSendsOfficial2KResolution(t *testing.T) {
t.Setenv("CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS", "127.0.0.1")
for _, quality := range []string{"2K", "1440p"} {
t.Run(quality, func(t *testing.T) {
requested := false
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost || r.URL.Path != "/v2/video_generation" {
t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
}
requested = true
var body miniMaxVideoRequest
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Errorf("decode request: %v", err)
}
if body.Resolution != "2K" {
t.Errorf("resolution = %q, want official API value 2K", body.Resolution)
}
// End at submission: this test inspects the wire payload without polling.
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{}`))
}))
defer server.Close()
_, err := runMiniMaxVideoTask(context.Background(), canvasGenerationInput{
Mode: "video", Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "MiniMax-H3", VQuality: quality},
})
if !requested || err == nil || !strings.Contains(err.Error(), "没有返回任务 ID") {
t.Fatalf("expected submission without task ID, requested=%v err=%v", requested, err)
}
})
}
}
func TestRunMiniMaxVideoTaskUsesExplicitReferenceRoles(t *testing.T) {
t.Setenv("CANVAS_ALLOW_PRIVATE_UPSTREAMS", "true")
var server *httptest.Server