feat: LLM 录制开关、模型列表第三方回退、命令页改为工具执行

在 review PR5 基础上的三处改进:

1. LLM 录制开关(默认关,settings.llm_record)
   - 录制页数据大小下拉框旁加开关;关闭时 Recorder.Stream 直接透传,
     不序列化、不累积、不写库,零开销。切换即时生效,无需重建 agent。

2. 模型列表拉取支持 Anthropic 兼容第三方
   - pgListModels 改为按序尝试多个候选端点:anthropic 的 /v1/models 拿不到时,
     剥掉 /anthropic 回退到 OpenAI 式 /models(自动切 Bearer 头)。
     修复 DeepSeek(anthropic) 加载模型 404。

3. 命令页改为「工具执行」列表
   - ListCommands 去掉 tool='Bash' 过滤,覆盖所有 tool_use;返回工具名列,
     搜索匹配工具名或参数。前端加「工具」列、标题/侧边栏改为「工具执行」。

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Autumn-27andClaude Opus 4.8 committed 2026-08-07 09:32:01 -04:00
1 parent 10f891a21d
commit ad9f14f140
12 files changed
+225 -83

No files matched your search

+10 -7
View File
@@ -6,19 +6,22 @@ import (
"time"
)
// CommandRecord is a paired Bash tool_use + tool_result from the activity table.
// CommandRecord is a paired tool_use + tool_result from the activity table
// (any tool, not just Bash). Command holds the raw tool input (JSON).
type CommandRecord struct {
ID int64 `json:"id"`
ExpID int64 `json:"exploration_id"`
Worker string `json:"worker"`
Tool string `json:"tool"`
Command string `json:"command"`
Output string `json:"output"`
IsError bool `json:"is_error"`
CreatedAt time.Time `json:"created_at"`
}
// ListCommands returns Bash command executions (tool_use + paired tool_result)
// across all explorations, with optional filtering and pagination.
// ListCommands returns tool executions (tool_use + paired tool_result) across all
// explorations, with optional filtering and pagination. Covers every tool, not
// just Bash; q matches the tool name or its input.
func (d *DB) ListCommands(expID *int64, q string, page, size int) ([]CommandRecord, int, error) {
if size <= 0 {
size = 50
@@ -28,7 +31,7 @@ func (d *DB) ListCommands(expID *int64, q string, page, size int) ([]CommandReco
}
offset := page * size
where := `WHERE u.tool = 'Bash' AND u.kind = 'tool_use'`
where := `WHERE u.kind = 'tool_use'`
args := []any{}
argN := 1
@@ -38,7 +41,7 @@ func (d *DB) ListCommands(expID *int64, q string, page, size int) ([]CommandReco
argN++
}
if q != "" {
where += fmt.Sprintf(` AND u.detail ILIKE $%d`, argN)
where += fmt.Sprintf(` AND (u.tool ILIKE $%d OR u.detail ILIKE $%d)`, argN, argN)
args = append(args, "%"+q+"%")
argN++
}
@@ -52,7 +55,7 @@ func (d *DB) ListCommands(expID *int64, q string, page, size int) ([]CommandReco
// data query: join tool_use with its tool_result
dataQ := `
SELECT u.id, u.exploration_id, COALESCE(u.worker,''), COALESCE(u.detail,''),
SELECT u.id, u.exploration_id, COALESCE(u.worker,''), COALESCE(u.tool,''), COALESCE(u.detail,''),
COALESCE(r.detail,''), COALESCE(r.is_error, false), u.created_at
FROM activity u
LEFT JOIN activity r ON r.tool_use_id = u.tool_use_id AND r.kind = 'tool_result'
@@ -70,7 +73,7 @@ LIMIT $` + fmt.Sprintf("%d", argN) + ` OFFSET $` + fmt.Sprintf("%d", argN+1)
out := []CommandRecord{}
for rows.Next() {
var c CommandRecord
if err := rows.Scan(&c.ID, &c.ExpID, &c.Worker, &c.Command, &c.Output, &c.IsError, &c.CreatedAt); err != nil {
if err := rows.Scan(&c.ID, &c.ExpID, &c.Worker, &c.Tool, &c.Command, &c.Output, &c.IsError, &c.CreatedAt); err != nil {
return nil, 0, err
}
out = append(out, c)