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。
This commit is contained in:
commit
d5dac5a6fc
140 files changed
+26497
No files matched your search
@@ -0,0 +1,71 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"git.gopher.ink/mirrors2/AutoZero/llm"
|
||||
)
|
||||
|
||||
// Checkpoint 是一次上下文压缩留下的交接文档,以及它覆盖到原 transcript 的哪个位置。
|
||||
//
|
||||
// 它值得落盘:压缩本身只改视图,但 WebUI 每个回合都会新建 Agent。没有 sidecar,
|
||||
// 新回合又要把整段历史重新摘要一遍;有了它,新回合直接从 checkpoint + 未覆盖的
|
||||
// 新消息开始。Covered/TailHash 是失效保护——历史被回退或改写后,指纹对不上就
|
||||
// 当作没有 checkpoint,绝不拿一份覆盖了不同消息的旧摘要继续跑。
|
||||
type Checkpoint struct {
|
||||
Text string `json:"text"`
|
||||
Covered int `json:"covered"` // 已纳入 checkpoint 的消息条数(transcript 前缀)
|
||||
TailHash string `json:"tail_hash"` // 第 Covered 条消息的指纹
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
|
||||
// CheckpointPath 是压缩交接文档的 sidecar 路径(与 .title / .run.json 同目录)。
|
||||
func CheckpointPath(id string) string {
|
||||
return filepath.Join(Dir(), id+".checkpoint.json")
|
||||
}
|
||||
|
||||
// LoadCheckpoint 读取 checkpoint;缺失或损坏返回 false。
|
||||
func LoadCheckpoint(id string) (Checkpoint, bool) {
|
||||
if _, ok := SafeID(id); !ok {
|
||||
return Checkpoint{}, false
|
||||
}
|
||||
var cp Checkpoint
|
||||
if err := LoadState(CheckpointPath(id), &cp); err != nil {
|
||||
return Checkpoint{}, false
|
||||
}
|
||||
return cp, cp.Text != ""
|
||||
}
|
||||
|
||||
// SaveCheckpoint 原子写 checkpoint。
|
||||
func SaveCheckpoint(id string, cp Checkpoint) error {
|
||||
if _, ok := SafeID(id); !ok {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
if cp.UpdatedAt == 0 {
|
||||
cp.UpdatedAt = time.Now().UnixMilli()
|
||||
}
|
||||
return SaveState(CheckpointPath(id), cp)
|
||||
}
|
||||
|
||||
// RemoveCheckpoint 删除 checkpoint sidecar(会话删除时用)。
|
||||
func RemoveCheckpoint(id string) {
|
||||
if _, ok := SafeID(id); ok {
|
||||
_ = os.Remove(CheckpointPath(id))
|
||||
}
|
||||
}
|
||||
|
||||
// MessageFingerprint 是一条消息的稳定指纹,用于识别 checkpoint 的覆盖边界。
|
||||
// 只取会进模型视野的字段(role/content/tool call),不含本地 trace。
|
||||
func MessageFingerprint(m llm.Message) string {
|
||||
h := sha256.New()
|
||||
fmt.Fprintf(h, "%s\x00%s\x00%s\x00", m.Role, m.Content, m.ToolCallID)
|
||||
for _, tc := range m.ToolCalls {
|
||||
fmt.Fprintf(h, "%s\x00%s\x00%s\x00", tc.ID, tc.Name, tc.Input)
|
||||
}
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
Reference in new issue
Block a user