Files
sanspie 5eb1832907
ci-platforms / darwin amd64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 15m28s
ci / release (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci / checks (push) Successful in 7m47s
Complete Stage 12 for v0.12.0
2026-11-05 11:46:53 +03:00

91 lines
2.5 KiB
Go

package agentbridge
import (
"bytes"
"fmt"
"slices"
"strings"
"aego/app/agent"
"aego/asset/pipeline"
"aego/editor/core/context"
"aego/editor/core/history"
)
type drawingCommand struct {
label string
editor *context.Editor
edits []pipeline.SourceEdit
}
func (c *drawingCommand) Label() string { return c.label }
func (*drawingCommand) Merge(history.Command) bool { return false }
func (c *drawingCommand) Do(history.Target) error { return c.apply(false) }
func (c *drawingCommand) Undo(history.Target) error { return c.apply(true) }
func (c *drawingCommand) check(back bool) error {
for _, e := range c.edits {
rel := strings.TrimSuffix(e.Path, pipeline.MetaSuffix)
if id, ok := c.editor.Pipeline.Lookup(rel); ok {
if d := c.editor.Docs.AssetDocument(id); d != nil && d.Dirty() {
return fmt.Errorf("%s has unsaved edits; save or discard them first", rel)
}
}
if d := c.editor.Docs.Script(e.Path); d != nil && (d.Conflict || d.Dirty()) {
return fmt.Errorf("%s has unsaved changes", e.Path)
}
if back {
got, err := c.editor.Pipeline.SourceBytes(e.Path)
if err != nil {
return err
}
if (got == nil) != (e.After == nil) || !bytes.Equal(got, e.After) {
return fmt.Errorf("%s changed after the drawing", e.Path)
}
}
}
return nil
}
func (c *drawingCommand) apply(back bool) error {
if err := c.check(back); err != nil {
return err
}
b, err := c.editor.Pipeline.ApplySources(c.edits, back)
if err != nil {
return err
}
c.editor.ApplyBatch(b)
c.editor.Docs.CheckExternalScripts()
return nil
}
func (b *Bridge) applyDrawing(p *Proposal) (*agent.Output, error) {
draw := p.Preview.Drawing
cmd := &drawingCommand{editor: b.ctx, edits: draw.Sources, label: b.stepName("Draw " + draw.Files[0])}
if d := b.ctx.Docs.Edit(); d != nil {
if err := d.History.Exec(cmd); err != nil {
return nil, err
}
b.note(d, cmd.Label())
} else {
if err := cmd.Do(nil); err != nil {
return nil, err
}
b.last = &undoRef{label: cmd.Label()}
}
// The reference PNG is an input to the approved render. Later changes
// to it must not prevent undoing or redoing this independent destination.
cmd.edits = slices.DeleteFunc(slices.Clone(cmd.edits), func(e pipeline.SourceEdit) bool {
return !slices.Contains(draw.Files, strings.TrimSuffix(e.Path, pipeline.MetaSuffix))
})
b.last.drawing = cmd
o := *p.Preview
o.DryRun = false
o.Files = draw.Files
o.Created = draw.Created
o.Drawing = nil
p.Preview.Drawing = nil
return &o, nil
}