feat(image): pass reference images to GPT image model for edits
Server: forward canvas/reference images to the image model so extract, continue, and edit requests stay faithful to the source product. - Add ImageRequestOptions.Images and route requests with inputs to the /v1/images/edits endpoint, via multipart upload (default) or JSON image_url payload, selectable through Agent.Image.InputImageTransport. - Extract reference URLs from prompt directives, inline @image tokens, and chat message image/mask contents; fold them into the idempotency key and prepend a reference-fidelity instruction to the prompt. Frontend: - Shrink CanvasToast to a compact top pill. - Paste an internal transparent clipboard node instead of re-uploading when it matches the clipboard image. - Keep agent-project polling alive on stream error while streaming.
This commit is contained in:
@@ -214,6 +214,52 @@ func TestDesignAgentGeneratesImageThroughPiAgent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDesignAgentPassesInlineReferenceImagesToImageGenerator(t *testing.T) {
|
||||
imageGenerator := &fakeImageGenerator{}
|
||||
agent := NewDesignAgent(fakeRunner{}, imageGenerator, fakeCreativeAgent{})
|
||||
|
||||
_, err := agent.Plan(context.Background(), design.AgentRequest{
|
||||
Prompt: "把参考图里的灰裤子拆成单件商品图",
|
||||
Mode: "image",
|
||||
ImageModel: "gpt-image-2",
|
||||
Messages: []design.AgentChatMessage{
|
||||
{
|
||||
Role: "user",
|
||||
Contents: []design.AgentContent{
|
||||
{Type: "image", ImageURL: "https://example.com/pants-rack.png", ImageWidth: 1200, ImageHeight: 900},
|
||||
{Type: "text", Text: "把参考图里的灰裤子拆成单件商品图", TextSource: "input"},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(imageGenerator.opts.Images) != 1 || imageGenerator.opts.Images[0] != "https://example.com/pants-rack.png" {
|
||||
t.Fatalf("expected reference image to be passed to GPT Image 2, got %#v", imageGenerator.opts.Images)
|
||||
}
|
||||
if !strings.Contains(imageGenerator.prompt, "参考图") {
|
||||
t.Fatalf("expected prompt to tell image model to use attached reference, got %s", imageGenerator.prompt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDesignAgentPassesPromptDirectiveReferenceImagesToImageGenerator(t *testing.T) {
|
||||
imageGenerator := &fakeImageGenerator{}
|
||||
agent := NewDesignAgent(fakeRunner{}, imageGenerator, fakeCreativeAgent{})
|
||||
|
||||
_, err := agent.Plan(context.Background(), design.AgentRequest{
|
||||
Prompt: "参考图 1(image):https://example.com/pants-rack.png\n灰裤子拆成单件衣服,为了后面电商配图。",
|
||||
Mode: "image",
|
||||
ImageModel: "gpt-image-2",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(imageGenerator.opts.Images) != 1 || imageGenerator.opts.Images[0] != "https://example.com/pants-rack.png" {
|
||||
t.Fatalf("expected directive reference image to be passed to GPT Image 2, got %#v", imageGenerator.opts.Images)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDesignAgentUsesDefaultImageSizeWithoutExplicitRequest(t *testing.T) {
|
||||
imageGenerator := &fakeImageGenerator{}
|
||||
agent := NewDesignAgent(fakeRunner{}, imageGenerator, fakeCreativeAgent{})
|
||||
|
||||
Reference in New Issue
Block a user