llm(三协议 Provider)/ session(JSONL 持久化)/ tools(Registry、围栏、 builtin、computer)/ cdp(browser)/ skills / mcp / agent(循环、两级压缩、 编排、审批门控)+ 底座 jsonl/textx/execx/diag/scratch/spill/imagecache。 产品装配代码(config 桥接、schedule 工具、memory/plan/retro/prompt) 留在 AutoGo,宿主接入方式见 MIGRATION.md。
70 lines
2.2 KiB
Go
70 lines
2.2 KiB
Go
package session
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"testing"
|
||
)
|
||
|
||
// TestRunStateRoundTrip:写读往返。
|
||
func TestRunStateRoundTrip(t *testing.T) {
|
||
t.Setenv("HOME", t.TempDir())
|
||
want := RunState{RunID: "run-1", Status: "running", StartedAt: 1234}
|
||
if err := SaveRunState("sess1", want); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
got, ok := LoadRunState("sess1")
|
||
if !ok {
|
||
t.Fatal("读不回刚写的状态")
|
||
}
|
||
if got.RunID != want.RunID || got.Status != want.Status || got.StartedAt != want.StartedAt {
|
||
t.Errorf("往返不一致: %+v vs %+v", got, want)
|
||
}
|
||
if _, ok := LoadRunState("nope"); ok {
|
||
t.Error("不存在的会话不该返回状态")
|
||
}
|
||
}
|
||
|
||
// TestReconcileRunStates:进程刚起来时把遗留的 running 认成 interrupted,
|
||
// 其它状态原样保留(不能把上次正常完成的 done 也改掉)。
|
||
func TestReconcileRunStates(t *testing.T) {
|
||
t.Setenv("HOME", t.TempDir())
|
||
if err := os.MkdirAll(Dir(), 0o755); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
cases := []RunState{
|
||
{RunID: "a", Status: "running", StartedAt: 1},
|
||
{RunID: "b", Status: "done", StartedAt: 1, EndedAt: 2},
|
||
{RunID: "c", Status: "interrupted", StartedAt: 1},
|
||
}
|
||
for i, st := range cases {
|
||
if err := SaveRunState(string(rune('a'+i)), st); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
// 损坏的文件不该让 reconcile 崩掉
|
||
if err := os.WriteFile(filepath.Join(Dir(), "broken.run.json"), []byte("{not json"), 0o644); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
// 非 run.json 的文件不该被动
|
||
if err := os.WriteFile(filepath.Join(Dir(), "keep.jsonl"), []byte("x"), 0o644); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if n := ReconcileRunStates(); n != 1 {
|
||
t.Errorf("改写条数 = %d, want 1(只有 running 那条)", n)
|
||
}
|
||
if st, _ := LoadRunState("a"); st.Status != "interrupted" {
|
||
t.Errorf("running 应被改成 interrupted,实际 %q", st.Status)
|
||
}
|
||
if st, _ := LoadRunState("b"); st.Status != "done" {
|
||
t.Errorf("done 不该被改,实际 %q", st.Status)
|
||
}
|
||
if st, _ := LoadRunState("c"); st.Status != "interrupted" {
|
||
t.Errorf("已经是 interrupted 的不该变,实际 %q", st.Status)
|
||
}
|
||
if _, err := os.Stat(filepath.Join(Dir(), "keep.jsonl")); err != nil {
|
||
t.Errorf("非 run.json 文件被动过了: %v", err)
|
||
}
|
||
}
|