Files
AutoZero/session/naming_test.go
T
Sakurasan d5dac5a6fc feat: AutoZero 通用 Agent 框架(从 AutoGo 五阶段拆分完成)
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。
2026-10-26 00:54:46 +08:00

106 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package session
import (
"os"
"path/filepath"
"strings"
"testing"
"git.gopher.ink/mirrors2/AutoZero/llm"
)
// TestNewNameSkipsExisting:时间戳撞上已有文件时依次加 -2/-3,绝不指向别人的会话。
// 不依赖时钟(直接喂固定 ts),所以不会因跨过一秒而变哑。
func TestNewNameSkipsExisting(t *testing.T) {
dir := t.TempDir()
ts := "20260101-000000"
if got := newName(dir, ts); got != filepath.Join(dir, ts+".jsonl") {
t.Fatalf("干净目录里应直接用基础名,得到 %q", got)
}
writeFile(t, filepath.Join(dir, ts+".jsonl"))
if got := newName(dir, ts); got != filepath.Join(dir, ts+"-2.jsonl") {
t.Fatalf("基础名被占时应给 -2,得到 %q", got)
}
writeFile(t, filepath.Join(dir, ts+"-2.jsonl"))
if got := newName(dir, ts); got != filepath.Join(dir, ts+"-3.jsonl") {
t.Fatalf("前两个都被占时应给 -3,得到 %q", got)
}
}
// TestNewDoesNotRecoverOldSession:连续两次新建必须拿到不同名字,第二份还是空的。
// 撞名的真实后果:/session new 后立刻发消息(文件写下内容),同一秒内再新建,
// 前端拿 LoadOrCreate 打开同名文件,"新建"就变成了把旧会话整份恢复回来。
func TestNewDoesNotRecoverOldSession(t *testing.T) {
t.Setenv("HOME", t.TempDir())
first, err := New()
if err != nil {
t.Fatalf("New: %v", err)
}
if err := first.Append(llm.Message{Role: llm.RoleUser, Content: "history"}); err != nil {
t.Fatalf("append: %v", err)
}
second, err := New()
if err != nil {
t.Fatalf("New: %v", err)
}
if second.Path == first.Path {
t.Fatalf("两次新建拿到同一个名字 %s", second.Path)
}
if len(second.Messages) != 0 {
t.Fatalf("新会话应为空,得到 %d 条", len(second.Messages))
}
if _, err := os.Stat(second.Path); !os.IsNotExist(err) {
t.Fatalf("新会话文件不该在这一步出现(err=%v)", err)
}
// 经渠道/前端实际会走的路径再打开一次,仍然是空的
byName := strings.TrimSuffix(filepath.Base(second.Path), ".jsonl")
again, err := LoadOrCreate(byName)
if err != nil {
t.Fatalf("LoadOrCreate: %v", err)
}
if len(again.Messages) != 0 {
t.Fatalf("按名字打开新会话却拿到 %d 条消息", len(again.Messages))
}
// 第一份的历史不受影响
reloaded, err := Load(first.Path)
if err != nil {
t.Fatalf("load: %v", err)
}
if len(reloaded.Messages) != 1 || reloaded.Messages[0].Content != "history" {
t.Fatalf("旧会话被改动: %+v", reloaded.Messages)
}
}
// TestNewNameSkipsUnwrittenIssued:两份新会话都还没落盘时也不能同名。
// 会话文件要到第一条消息才写出来,所以"盘上没有"不等于"没人用"。
func TestNewNameSkipsUnwrittenIssued(t *testing.T) {
dir := t.TempDir()
ts := "20260202-120000"
first := newName(dir, ts)
second := newName(dir, ts)
if first == second {
t.Fatalf("两次取名拿到同一个名字 %s(第一份还没落盘,Stat 看不见)", first)
}
if strings.TrimSuffix(filepath.Base(second), ".jsonl") != ts+"-2" {
t.Fatalf("第二个名字 = %q,want %s-2.jsonl", second, ts)
}
// 已发出的名字不许被复用
if got := newName(dir, ts); got == first || got == second {
t.Fatalf("复用了已发出的名字: %q", got)
}
}
func writeFile(t *testing.T, path string) {
t.Helper()
if err := os.WriteFile(path, []byte("{}\n"), 0o644); err != nil {
t.Fatalf("write %s: %v", path, err)
}
}