first commit

This commit is contained in:
2026-08-14 23:41:57 +08:00
commit 086803a8dd
471 changed files with 91938 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
// Tests for the /rewind command wiring: listing restore points and restoring
// files + conversation. The file-snapshot journal itself is tested in
// agenttool; here we exercise runRewind's REPL-level behavior over a replDeps.
package repl
import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"
"github.com/smallnest/pigo/internal/agentcore"
"github.com/smallnest/pigo/internal/agenttool"
)
// /rewind with no argument lists the committed restore points.
func TestREPLRewindListsPoints(t *testing.T) {
p := &replProvider{reply: "hi"}
deps, _ := newTestDeps(t, p)
deps.snap = agenttool.NewFileSnapshotRecorder()
dir := t.TempDir()
f := filepath.Join(dir, "a.txt")
if err := os.WriteFile(f, []byte("v0"), 0o644); err != nil {
t.Fatal(err)
}
deps.snap.Record(f)
deps.snap.Commit("", "add feature X")
var out bytes.Buffer
runRewind(&out, &deps, "/rewind")
got := out.String()
if !strings.Contains(got, "restore points") || !strings.Contains(got, "add feature X") {
t.Errorf("listing missing expected content:\n%s", got)
}
}
// /rewind N restores the file to its baseline and resets the conversation when
// the point's leaf is empty (it was the session's first turn).
func TestREPLRewindRestoresFiles(t *testing.T) {
p := &replProvider{reply: "hi"}
deps, _ := newTestDeps(t, p)
deps.snap = agenttool.NewFileSnapshotRecorder()
deps.agentCtx.Messages = agentcore.MessageList{
agentcore.UserMessage{RoleField: agentcore.RoleUser},
}
deps.persisted = 1
dir := t.TempDir()
f := filepath.Join(dir, "a.txt")
if err := os.WriteFile(f, []byte("original"), 0o644); err != nil {
t.Fatal(err)
}
deps.snap.Record(f) // baseline "original"
if err := os.WriteFile(f, []byte("changed"), 0o644); err != nil {
t.Fatal(err)
}
deps.snap.Commit("", "edit a.txt")
var out bytes.Buffer
runRewind(&out, &deps, "/rewind 1")
if data, _ := os.ReadFile(f); string(data) != "original" {
t.Errorf("file not restored: got %q, want original", string(data))
}
if len(deps.agentCtx.Messages) != 0 {
t.Errorf("conversation not reset: %d messages remain", len(deps.agentCtx.Messages))
}
if len(deps.snap.Points()) != 0 {
t.Errorf("journal not truncated after rewind")
}
if !strings.Contains(out.String(), "rewound to before point 1") {
t.Errorf("missing confirmation:\n%s", out.String())
}
}
// /rewind is unavailable when file tools are disabled (nil recorder).
func TestREPLRewindDisabled(t *testing.T) {
p := &replProvider{reply: "hi"}
deps, _ := newTestDeps(t, p)
deps.snap = nil
var out bytes.Buffer
runRewind(&out, &deps, "/rewind")
if !strings.Contains(out.String(), "unavailable") {
t.Errorf("want unavailable message, got:\n%s", out.String())
}
}