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。
77 lines
2.2 KiB
Go
77 lines
2.2 KiB
Go
package session
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// RunState 是一次回合的**落盘**状态,供 UI 在进程重启后说明"上次那次跑到哪了"。
|
|
//
|
|
// 注意它能表达的东西有边界:agent 在进程内,进程重启无法续跑。所以这个文件的
|
|
// 用途只有一个——把上次遗留的 running 认出来是 interrupted,而不是假装它还在跑。
|
|
// 会话消息本身是逐条落盘的(见 Session.Append),不会因为重启丢失。
|
|
type RunState struct {
|
|
RunID string `json:"run_id"`
|
|
Status string `json:"status"` // running | done | error | stopped | interrupted
|
|
StartedAt int64 `json:"started_at"`
|
|
EndedAt int64 `json:"ended_at,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// RunStatePath 运行状态 sidecar 路径(与 TitlePath 同一套命名与目录)。
|
|
func RunStatePath(id string) string {
|
|
return filepath.Join(Dir(), id+".run.json")
|
|
}
|
|
|
|
// LoadRunState 读取运行状态;文件不存在或损坏时返回 (zero, false)。
|
|
func LoadRunState(id string) (RunState, bool) {
|
|
b, err := os.ReadFile(RunStatePath(id))
|
|
if err != nil {
|
|
return RunState{}, false
|
|
}
|
|
var st RunState
|
|
if json.Unmarshal(b, &st) != nil {
|
|
return RunState{}, false
|
|
}
|
|
return st, true
|
|
}
|
|
|
|
// SaveRunState 原子写运行状态。
|
|
func SaveRunState(id string, st RunState) error {
|
|
return SaveState(RunStatePath(id), st)
|
|
}
|
|
|
|
// ReconcileRunStates 把所有遗留的 running 状态改写成 interrupted,返回改写条数。
|
|
//
|
|
// 进程刚起来时调用:此时不可能有任何回合在跑,文件里写着 running 的一定是上次
|
|
// 进程退出/被杀时留下的。不这么做的话,UI 会永远显示"正在回复…"。
|
|
func ReconcileRunStates() int {
|
|
entries, err := os.ReadDir(Dir())
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
n := 0
|
|
for _, e := range entries {
|
|
name := e.Name()
|
|
if e.IsDir() || !strings.HasSuffix(name, ".run.json") {
|
|
continue
|
|
}
|
|
path := filepath.Join(Dir(), name)
|
|
b, err := os.ReadFile(path)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
var st RunState
|
|
if json.Unmarshal(b, &st) != nil || st.Status != "running" {
|
|
continue
|
|
}
|
|
st.Status = "interrupted"
|
|
if err := SaveState(path, st); err == nil {
|
|
n++
|
|
}
|
|
}
|
|
return n
|
|
}
|