Files
renjue e761074fb9
CI / docker (push) Successful in 3m46s
Unify ComfyUI ingress model ID and fix seed validation errors.
Merge model_id/alias in the image provider UI, and ensure ComfyUI never receives seed -1 after cloneMap type coercion.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 14:17:49 +08:00

98 lines
2.1 KiB
Go

package prediction
import (
"crypto/rand"
"encoding/json"
"fmt"
"math/big"
)
func BuildPrompt(workflowJSON string, binding InputBinding, input map[string]any) (map[string]any, error) {
var workflow map[string]any
if err := json.Unmarshal([]byte(workflowJSON), &workflow); err != nil {
return nil, fmt.Errorf("invalid workflow: %w", err)
}
prompt := deepCopyMap(workflow)
for name, target := range binding {
if target == nil || target.Node == "" || target.Field == "" {
continue
}
val, ok := input[name]
if !ok {
continue
}
if name == "seed" {
val = resolveSeed(val)
}
node, ok := prompt[target.Node].(map[string]any)
if !ok {
return nil, fmt.Errorf("node %s not found", target.Node)
}
inputs, ok := node["inputs"].(map[string]any)
if !ok {
return nil, fmt.Errorf("node %s inputs missing", target.Node)
}
inputs[target.Field] = val
}
sanitizeSamplerSeeds(prompt)
return prompt, nil
}
// resolveSeed maps seed < 0 (random) to a non-negative value ComfyUI accepts.
func resolveSeed(val any) any {
n, ok := seedAsInt64(val)
if !ok || n >= 0 {
return val
}
r, err := rand.Int(rand.Reader, big.NewInt(1<<31-1))
if err != nil {
return int(0)
}
return int(r.Int64())
}
func seedAsInt64(v any) (int64, bool) {
switch n := v.(type) {
case int:
return int64(n), true
case int64:
return n, true
case float64:
return int64(n), true
case json.Number:
i, err := n.Int64()
return i, err == nil
default:
return 0, false
}
}
func sanitizeSamplerSeeds(prompt map[string]any) {
seedFields := []string{"seed", "noise_seed"}
for _, raw := range prompt {
node, ok := raw.(map[string]any)
if !ok {
continue
}
if class, _ := node["class_type"].(string); class != "KSampler" {
continue
}
inputs, ok := node["inputs"].(map[string]any)
if !ok {
continue
}
for _, field := range seedFields {
if v, ok := inputs[field]; ok {
inputs[field] = resolveSeed(v)
}
}
}
}
func deepCopyMap(src map[string]any) map[string]any {
b, _ := json.Marshal(src)
var dst map[string]any
_ = json.Unmarshal(b, &dst)
return dst
}