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:
Sakurasan committed 2026-10-26 00:54:46 +08:00
commit d5dac5a6fc
140 files changed
+26497

No files matched your search

+89
View File
@@ -0,0 +1,89 @@
package session
// 会话标题:sidecar 文件 <id>.title(与会话 jsonl 同目录)。
// 标题本地派生自用户首条消息,零请求、零延迟;TUI 与 WebUI 共用本文件。
import (
"os"
"path/filepath"
"strings"
)
// SafeID 拒绝路径穿越,标题文件只允许落在会话目录内。
func SafeID(id string) (string, bool) {
if id == "" || strings.ContainsAny(id, `/\`) || strings.Contains(id, "..") {
return "", false
}
return id, true
}
// TitlePath 标题 sidecar 文件路径。
func TitlePath(id string) string {
return filepath.Join(Dir(), id+".title")
}
// LoadTitle 读取标题;无标题返回 ""。
func LoadTitle(id string) string {
safe, ok := SafeID(id)
if !ok {
return ""
}
b, err := os.ReadFile(TitlePath(safe))
if err != nil {
return ""
}
return strings.TrimSpace(string(b))
}
// SaveTitle 写入标题(去首尾空白,上限 60 字)。
func SaveTitle(id, title string) error {
safe, ok := SafeID(id)
if !ok {
return os.ErrInvalid
}
title = TruncateRunes(strings.TrimSpace(title), 60)
if title == "" {
return os.ErrInvalid
}
if err := os.MkdirAll(Dir(), 0o755); err != nil {
return err
}
return os.WriteFile(TitlePath(safe), []byte(title), 0o644)
}
// TruncateRunes 按 rune 截断。
func TruncateRunes(s string, n int) string {
r := []rune(s)
if len(r) <= n {
return s
}
return string(r[:n])
}
// SanitizeTitle 清洗标题:去空白、去包围引号,折叠空白,截断 24 字。
func SanitizeTitle(s string) string {
s = strings.TrimSpace(s)
s = strings.Trim(s, `"'「」『』【】<>`)
s = strings.TrimSpace(s)
s = strings.Join(strings.Fields(s), " ")
return TruncateRunes(s, 24)
}
// DeriveTitle 从用户首条消息本地派生会话标题:不发请求、零延迟、无失败路径。
//
// 此前为标题单独发一次模型调用,代价远大于收益:该模型上常达 ~27s,与主回合并发时
// 极易超时(30s 上限),导致长回合的会话静默丢标题。而标题只是会话列表里的速记,
// 用「用户诉求的首行」就足够辨认,没必要为一个标签花掉一次完整往返。
func DeriveTitle(userMsg string) string {
s := strings.TrimSpace(userMsg)
if s == "" {
return ""
}
// 多行输入取首行——那通常是主诉求,后续多为补充细节或粘贴内容。
if i := strings.IndexByte(s, '\n'); i >= 0 {
s = s[:i]
}
// 去掉 markdown 装饰:标题符号、引用、列表符、代码块围栏。
s = strings.TrimLeft(s, "#>*-`~ ")
return SanitizeTitle(s)
}