mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-13 18:07:36 +08:00
120 lines
3.2 KiB
Go
120 lines
3.2 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"clawgo/pkg/providers"
|
|
)
|
|
|
|
type SessionInfo struct {
|
|
Key string
|
|
Kind string
|
|
Summary string
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
type SessionsTool struct {
|
|
listFn func(limit int) []SessionInfo
|
|
historyFn func(key string, limit int) []providers.Message
|
|
}
|
|
|
|
func NewSessionsTool(listFn func(limit int) []SessionInfo, historyFn func(key string, limit int) []providers.Message) *SessionsTool {
|
|
return &SessionsTool{listFn: listFn, historyFn: historyFn}
|
|
}
|
|
|
|
func (t *SessionsTool) Name() string { return "sessions" }
|
|
|
|
func (t *SessionsTool) Description() string {
|
|
return "Inspect sessions in current runtime: list or history"
|
|
}
|
|
|
|
func (t *SessionsTool) Parameters() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"type": "object",
|
|
"properties": map[string]interface{}{
|
|
"action": map[string]interface{}{"type": "string", "description": "list|history"},
|
|
"key": map[string]interface{}{"type": "string", "description": "session key for history"},
|
|
"limit": map[string]interface{}{"type": "integer", "description": "max items", "default": 20},
|
|
"include_tools": map[string]interface{}{"type": "boolean", "description": "include tool role messages in history", "default": false},
|
|
},
|
|
"required": []string{"action"},
|
|
}
|
|
}
|
|
|
|
func (t *SessionsTool) Execute(ctx context.Context, args map[string]interface{}) (string, error) {
|
|
_ = ctx
|
|
action, _ := args["action"].(string)
|
|
action = strings.ToLower(strings.TrimSpace(action))
|
|
limit := 20
|
|
if v, ok := args["limit"].(float64); ok && int(v) > 0 {
|
|
limit = int(v)
|
|
}
|
|
includeTools := false
|
|
if v, ok := args["include_tools"].(bool); ok {
|
|
includeTools = v
|
|
}
|
|
|
|
switch action {
|
|
case "list":
|
|
if t.listFn == nil {
|
|
return "sessions list unavailable", nil
|
|
}
|
|
items := t.listFn(limit)
|
|
if len(items) == 0 {
|
|
return "No sessions.", nil
|
|
}
|
|
sort.Slice(items, func(i, j int) bool { return items[i].UpdatedAt.After(items[j].UpdatedAt) })
|
|
var sb strings.Builder
|
|
sb.WriteString("Sessions:\n")
|
|
for _, s := range items {
|
|
sb.WriteString(fmt.Sprintf("- %s kind=%s updated=%s\n", s.Key, s.Kind, s.UpdatedAt.Format(time.RFC3339)))
|
|
}
|
|
return strings.TrimSpace(sb.String()), nil
|
|
case "history":
|
|
if t.historyFn == nil {
|
|
return "sessions history unavailable", nil
|
|
}
|
|
key, _ := args["key"].(string)
|
|
key = strings.TrimSpace(key)
|
|
if key == "" {
|
|
return "key is required for history", nil
|
|
}
|
|
h := t.historyFn(key, limit*3)
|
|
if len(h) == 0 {
|
|
return "No history.", nil
|
|
}
|
|
if !includeTools {
|
|
filtered := make([]providers.Message, 0, len(h))
|
|
for _, m := range h {
|
|
if strings.TrimSpace(strings.ToLower(m.Role)) == "tool" {
|
|
continue
|
|
}
|
|
filtered = append(filtered, m)
|
|
}
|
|
h = filtered
|
|
}
|
|
if len(h) == 0 {
|
|
return "No history (after filters).", nil
|
|
}
|
|
if len(h) > limit {
|
|
h = h[len(h)-limit:]
|
|
}
|
|
var sb strings.Builder
|
|
sb.WriteString(fmt.Sprintf("History for %s:\n", key))
|
|
for _, m := range h {
|
|
content := strings.TrimSpace(m.Content)
|
|
if len(content) > 180 {
|
|
content = content[:180] + "..."
|
|
}
|
|
sb.WriteString(fmt.Sprintf("- [%s] %s\n", m.Role, content))
|
|
}
|
|
return strings.TrimSpace(sb.String()), nil
|
|
default:
|
|
return "unsupported action", nil
|
|
}
|
|
}
|