feat: Agent CLI 与终端审计回放全面优化

- Agent CLI: 多轮对话、SSH 长连接、流式推理、Evolver 按用户隔离、历史侧栏
- 终端审计: 回放播放器、命令书签、筛选分页导出、命令输出统计、录制落盘修复
- 修复 session_commands 表迁移、Kill 竞态导致录制丢失、无录制会话回放提示
- 审计历史页只读(移除删除),移除回放弹框录制搜索
This commit is contained in:
Logan committed 2026-07-01 12:13:53 +08:00
1 parent 9a3dd304f7
commit 1acb0c49af
81 files changed
+3916 -1655

No files matched your search

+36
View File
@@ -42,6 +42,7 @@ type EvolveResult struct {
LearnedHint string `json:"learned_hint"`
ToolSequence []string `json:"tool_sequence"`
ExperienceAdded bool `json:"experience_added"`
SkillAdded bool `json:"skill_added"`
Consolidated bool `json:"consolidated"`
}
@@ -107,6 +108,21 @@ func (e *EvolverEngine) Evolve(ctx context.Context, exec *TaskExecution) *Evolve
go e.memorizeFact(ctx, exec) // 异步,不阻塞进化主流程
}
// Step 6: PROCEDURAL —— 成功任务沉淀程序记忆(工具命令序列) // Logan.Li
if exec.Success {
if steps := extractSSHSteps(exec.ToolCalls); len(steps) >= 2 {
skill := SkillEntry{
Name: result.TaskType + "标准流程",
When: result.TaskType,
Steps: steps,
Timestamp: time.Now().Unix(),
}
if err := e.mem.AddSkill(skill); err == nil {
result.SkillAdded = true
}
}
}
return result
}
@@ -194,6 +210,12 @@ func (e *EvolverEngine) GetContextForPrompt(query string) string {
if hosts := e.mem.Hosts(); len(hosts) > 0 {
sb.WriteString(fmt.Sprintf(" 【已知主机】%s\n", strings.Join(hosts, ", ")))
}
if skills := e.mem.FindSkills(taskType, 2); len(skills) > 0 {
sb.WriteString(" 【推荐流程】\n")
for _, sk := range skills {
sb.WriteString(fmt.Sprintf(" - %s: %s\n", sk.Name, strings.Join(sk.Steps, " → ")))
}
}
return sb.String()
}
@@ -258,6 +280,20 @@ func resultToolNames(calls []ToolCallRecord) []string {
return out
}
// extractSSHSteps 从工具调用记录提取 ssh_execute 命令序列 // Logan.Li
func extractSSHSteps(calls []ToolCallRecord) []string {
out := make([]string, 0, len(calls))
for _, c := range calls {
if c.ToolName != "ssh_execute" {
continue
}
if cmd, ok := c.Args["command"].(string); ok && strings.TrimSpace(cmd) != "" {
out = append(out, strings.TrimSpace(cmd))
}
}
return out
}
func uniqueStrings(in []string) []string {
seen := make(map[string]bool)
out := make([]string, 0, len(in))