mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-13 16:47:34 +08:00
enhance memory_write metadata and add /lang command
This commit is contained in:
@@ -206,6 +206,28 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
|
||||
return al.processSystemMessage(ctx, msg)
|
||||
}
|
||||
|
||||
// Explicit language command: /lang <code>
|
||||
if strings.HasPrefix(strings.TrimSpace(msg.Content), "/lang") {
|
||||
parts := strings.Fields(strings.TrimSpace(msg.Content))
|
||||
if len(parts) < 2 {
|
||||
preferred, last := al.sessions.GetLanguagePreferences(msg.SessionKey)
|
||||
if preferred == "" {
|
||||
preferred = "(auto)"
|
||||
}
|
||||
if last == "" {
|
||||
last = "(none)"
|
||||
}
|
||||
return fmt.Sprintf("Usage: /lang <code>\nCurrent preferred: %s\nLast detected: %s", preferred, last), nil
|
||||
}
|
||||
lang := normalizeLang(parts[1])
|
||||
if lang == "" {
|
||||
return "Invalid language code.", nil
|
||||
}
|
||||
al.sessions.SetPreferredLanguage(msg.SessionKey, lang)
|
||||
al.sessions.Save(al.sessions.GetOrCreate(msg.SessionKey))
|
||||
return fmt.Sprintf("Language preference updated to %s", lang), nil
|
||||
}
|
||||
|
||||
// Update tool contexts
|
||||
if tool, ok := al.tools.Get("message"); ok {
|
||||
if mt, ok := tool.(*tools.MessageTool); ok {
|
||||
|
||||
@@ -38,6 +38,21 @@ func (t *MemoryWriteTool) Parameters() map[string]interface{} {
|
||||
"description": "Target memory kind: longterm or daily",
|
||||
"default": "daily",
|
||||
},
|
||||
"importance": map[string]interface{}{
|
||||
"type": "string",
|
||||
"description": "low|medium|high. high is recommended for longterm",
|
||||
"default": "medium",
|
||||
},
|
||||
"source": map[string]interface{}{
|
||||
"type": "string",
|
||||
"description": "Source/context for this memory, e.g. user, system, tool",
|
||||
"default": "user",
|
||||
},
|
||||
"tags": map[string]interface{}{
|
||||
"type": "array",
|
||||
"items": map[string]interface{}{"type": "string"},
|
||||
"description": "Optional tags for filtering/search, e.g. preference,todo,decision",
|
||||
},
|
||||
"append": map[string]interface{}{
|
||||
"type": "boolean",
|
||||
"description": "Append mode (default true)",
|
||||
@@ -61,18 +76,31 @@ func (t *MemoryWriteTool) Execute(ctx context.Context, args map[string]interface
|
||||
kind = "daily"
|
||||
}
|
||||
|
||||
importance, _ := args["importance"].(string)
|
||||
importance = normalizeImportance(importance)
|
||||
|
||||
source, _ := args["source"].(string)
|
||||
source = strings.TrimSpace(source)
|
||||
if source == "" {
|
||||
source = "user"
|
||||
}
|
||||
|
||||
tags := parseTags(args["tags"])
|
||||
|
||||
appendMode := true
|
||||
if v, ok := args["append"].(bool); ok {
|
||||
appendMode = v
|
||||
}
|
||||
|
||||
formatted := formatMemoryLine(content, importance, source, tags)
|
||||
|
||||
switch kind {
|
||||
case "longterm", "memory", "permanent":
|
||||
path := filepath.Join(t.workspace, "MEMORY.md")
|
||||
if appendMode {
|
||||
return t.appendWithTimestamp(path, content)
|
||||
return t.appendWithTimestamp(path, formatted)
|
||||
}
|
||||
if err := os.WriteFile(path, []byte(content+"\n"), 0644); err != nil {
|
||||
if err := os.WriteFile(path, []byte(formatted+"\n"), 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("Wrote long-term memory: %s", path), nil
|
||||
@@ -83,9 +111,9 @@ func (t *MemoryWriteTool) Execute(ctx context.Context, args map[string]interface
|
||||
}
|
||||
path := filepath.Join(memDir, time.Now().Format("2006-01-02")+".md")
|
||||
if appendMode {
|
||||
return t.appendWithTimestamp(path, content)
|
||||
return t.appendWithTimestamp(path, formatted)
|
||||
}
|
||||
if err := os.WriteFile(path, []byte(content+"\n"), 0644); err != nil {
|
||||
if err := os.WriteFile(path, []byte(formatted+"\n"), 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("Wrote daily memory: %s", path), nil
|
||||
@@ -109,3 +137,45 @@ func (t *MemoryWriteTool) appendWithTimestamp(path, content string) (string, err
|
||||
}
|
||||
return fmt.Sprintf("Appended memory to %s", path), nil
|
||||
}
|
||||
|
||||
func normalizeImportance(v string) string {
|
||||
s := strings.ToLower(strings.TrimSpace(v))
|
||||
switch s {
|
||||
case "high", "medium", "low":
|
||||
return s
|
||||
default:
|
||||
return "medium"
|
||||
}
|
||||
}
|
||||
|
||||
func parseTags(raw interface{}) []string {
|
||||
items, ok := raw.([]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
out := make([]string, 0, len(items))
|
||||
seen := map[string]struct{}{}
|
||||
for _, it := range items {
|
||||
s, _ := it.(string)
|
||||
s = strings.ToLower(strings.TrimSpace(s))
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
if _, exists := seen[s]; exists {
|
||||
continue
|
||||
}
|
||||
seen[s] = struct{}{}
|
||||
out = append(out, s)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func formatMemoryLine(content, importance, source string, tags []string) string {
|
||||
var meta []string
|
||||
meta = append(meta, "importance="+importance)
|
||||
meta = append(meta, "source="+source)
|
||||
if len(tags) > 0 {
|
||||
meta = append(meta, "tags="+strings.Join(tags, ","))
|
||||
}
|
||||
return fmt.Sprintf("[%s] %s", strings.Join(meta, " | "), content)
|
||||
}
|
||||
|
||||
28
pkg/tools/memory_write_test.go
Normal file
28
pkg/tools/memory_write_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormatMemoryLine(t *testing.T) {
|
||||
got := formatMemoryLine("remember this", "high", "user", []string{"preference", "lang"})
|
||||
if got == "" {
|
||||
t.Fatal("empty formatted line")
|
||||
}
|
||||
if want := "importance=high"; !strings.Contains(got, want) {
|
||||
t.Fatalf("expected %q in %q", want, got)
|
||||
}
|
||||
if want := "source=user"; !strings.Contains(got, want) {
|
||||
t.Fatalf("expected %q in %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeImportance(t *testing.T) {
|
||||
if normalizeImportance("HIGH") != "high" {
|
||||
t.Fatal("expected high")
|
||||
}
|
||||
if normalizeImportance("unknown") != "medium" {
|
||||
t.Fatal("expected medium fallback")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user