feat(server): place generated images beside the reference anchor node
Read a "reference anchor node:" agent directive and lay newly generated image nodes immediately to the right of that node, inheriting its row and falling back to its size, for planned, follow-up, and incremental flows. Generalize the directive parser shared with the image-generator target. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -196,6 +196,52 @@ func TestImageGeneratorTargetNodeIDParsesDirectiveCaseInsensitively(t *testing.T
|
||||
}
|
||||
}
|
||||
|
||||
func TestReferenceAnchorNodeIDParsesDirectiveCaseInsensitively(t *testing.T) {
|
||||
anchorID := referenceAnchorNodeID([]design.AgentChatMessage{
|
||||
{
|
||||
Role: "user",
|
||||
Contents: []design.AgentContent{
|
||||
{Type: "text", Text: "REFERENCE ANCHOR NODE: image-2", TextSource: "settings"},
|
||||
},
|
||||
},
|
||||
})
|
||||
if anchorID != "image-2" {
|
||||
t.Fatalf("expected reference anchor id, got %q", anchorID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionGeneratedNodesBesideReferenceKeepsAnchorAndOrdersResults(t *testing.T) {
|
||||
nodes := []design.Node{
|
||||
{ID: "reference-1", Type: design.NodeTypeImage, X: 100, Y: 80, Width: 500, Height: 360, Content: "https://example.com/reference.webp", Status: "success"},
|
||||
}
|
||||
generated := []design.Node{
|
||||
{ID: "generated-1", Type: design.NodeTypeImage, Width: 400, Height: 300},
|
||||
{ID: "generated-2", Type: design.NodeTypeImage, Width: 320, Height: 240},
|
||||
}
|
||||
|
||||
positioned := positionGeneratedNodesBesideReference(nodes, "reference-1", generated)
|
||||
if nodes[0].X != 100 || nodes[0].Content != "https://example.com/reference.webp" {
|
||||
t.Fatalf("expected reference node to remain unchanged, got %#v", nodes[0])
|
||||
}
|
||||
if positioned[0].X <= nodes[0].X+nodes[0].Width || positioned[0].Y != nodes[0].Y {
|
||||
t.Fatalf("expected first result beside reference, got %#v", positioned[0])
|
||||
}
|
||||
if positioned[1].X <= positioned[0].X+positioned[0].Width || positioned[1].Y != nodes[0].Y {
|
||||
t.Fatalf("expected second result after first result, got %#v", positioned[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionGeneratedNodesBesideReferenceKeepsDefaultPlacementWithoutAnchor(t *testing.T) {
|
||||
generated := []design.Node{
|
||||
{ID: "generated-1", Type: design.NodeTypeImage, X: 720, Y: 360, Width: 400, Height: 300},
|
||||
}
|
||||
|
||||
positioned := positionGeneratedNodesBesideReference(nil, "missing-reference", generated)
|
||||
if positioned[0].X != generated[0].X || positioned[0].Y != generated[0].Y {
|
||||
t.Fatalf("expected default placement without a matching anchor, got %#v", positioned[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarkImageGeneratorTargetGeneratingCopiesPlaceholdersForRequestedCount(t *testing.T) {
|
||||
nodes := []design.Node{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user