bd0c8c0dd3
agents/ ahora solo contiene carpetas de agentes (config, reglas, prompts). El runtime (Agent, Robot, Runner, registry, handler, commands, llm, memory) vive en devagents/ como package devagents. Cambios: - git mv agents/*.go → devagents/*.go - package agents → package devagents en todos los archivos movidos - Actualizar imports en agents/*/agent.go, cmd/launcher/, dev-scripts/ - Actualizar docs: CLAUDE.md, rules/, docs/e2ee.md, issues pendientes Build y tests pasan sin errores. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
120 lines
3.4 KiB
Go
120 lines
3.4 KiB
Go
package devagents
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"path/filepath"
|
|
|
|
coretypes "github.com/enmanuel/agents/pkg/llm"
|
|
"github.com/enmanuel/agents/pkg/memory"
|
|
shellmem "github.com/enmanuel/agents/shell/memory"
|
|
)
|
|
|
|
// ClearWindow resets the conversation window for a room and deletes persisted
|
|
// messages from SQLite so the agent starts fresh. Implements toolmemory.WindowClearer.
|
|
func (a *Agent) ClearWindow(roomID string) {
|
|
a.windowsMu.Lock()
|
|
a.windows[roomID] = memory.NewWindow(a.windowSize)
|
|
a.windowsMu.Unlock()
|
|
|
|
if a.memStore != nil {
|
|
if err := a.memStore.DeleteMessages(
|
|
context.Background(), a.cfg.Agent.ID, &roomID,
|
|
); err != nil {
|
|
a.logger.Warn("failed to delete persisted messages on clear", "room", roomID, "err", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// ensureWindowLoaded loads the conversation window from SQLite on first access for a room.
|
|
func (a *Agent) ensureWindowLoaded(ctx context.Context, roomID string) {
|
|
a.windowsMu.Lock()
|
|
defer a.windowsMu.Unlock()
|
|
if _, ok := a.windows[roomID]; ok {
|
|
return
|
|
}
|
|
w := memory.NewWindow(a.windowSize)
|
|
if a.memStore != nil {
|
|
msgs, err := a.memStore.LoadMessages(ctx, a.cfg.Agent.ID, roomID, a.windowSize)
|
|
if err != nil {
|
|
a.logger.Warn("failed to load message history", "room", roomID, "err", err)
|
|
} else {
|
|
for _, m := range msgs {
|
|
w = w.Append(coretypes.Message{Role: m.Role, Content: m.Content})
|
|
}
|
|
if len(msgs) > 0 {
|
|
a.logger.Debug("loaded message history", "room", roomID, "count", len(msgs))
|
|
}
|
|
}
|
|
}
|
|
a.windows[roomID] = w
|
|
}
|
|
|
|
// appendToWindow adds a message to the in-memory conversation window.
|
|
func (a *Agent) appendToWindow(roomID string, msg coretypes.Message) {
|
|
a.windowsMu.Lock()
|
|
defer a.windowsMu.Unlock()
|
|
w, ok := a.windows[roomID]
|
|
if !ok {
|
|
w = memory.NewWindow(a.windowSize)
|
|
}
|
|
a.windows[roomID] = w.Append(msg)
|
|
}
|
|
|
|
// getWindowMessages returns a copy of the conversation window for a room.
|
|
func (a *Agent) getWindowMessages(roomID string) []coretypes.Message {
|
|
a.windowsMu.RLock()
|
|
defer a.windowsMu.RUnlock()
|
|
w, ok := a.windows[roomID]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return w.ToLLMMessages()
|
|
}
|
|
|
|
// persistMessage saves a message to the SQLite store (no-op if store is nil).
|
|
func (a *Agent) persistMessage(ctx context.Context, roomID string, role coretypes.Role, content string) {
|
|
if a.memStore == nil {
|
|
return
|
|
}
|
|
if err := a.memStore.SaveMessage(ctx, memory.HistoryMessage{
|
|
AgentID: a.cfg.Agent.ID,
|
|
RoomID: roomID,
|
|
Role: role,
|
|
Content: content,
|
|
}); err != nil {
|
|
a.logger.Warn("failed to persist message", "room", roomID, "err", err)
|
|
}
|
|
}
|
|
|
|
// memoryInit holds the results of memory subsystem initialization.
|
|
type memoryInit struct {
|
|
store memory.Store
|
|
windowSize int
|
|
}
|
|
|
|
// initMemoryStore creates the memory store and resolves window size from config.
|
|
// Returns a zero-value memoryInit if memory is disabled.
|
|
func initMemoryStore(enabled bool, windowSizeCfg int, dbPathCfg string, dataBase string, logger *slog.Logger) (memoryInit, error) {
|
|
if !enabled {
|
|
return memoryInit{windowSize: defaultWindowSize}, nil
|
|
}
|
|
|
|
windowSize := windowSizeCfg
|
|
if windowSize <= 0 {
|
|
windowSize = defaultWindowSize
|
|
}
|
|
|
|
dbPath := dbPathCfg
|
|
if dbPath == "" {
|
|
dbPath = filepath.Join(dataBase, "memory.db")
|
|
}
|
|
store, err := shellmem.New(dbPath, logger)
|
|
if err != nil {
|
|
return memoryInit{}, fmt.Errorf("memory store: %w", err)
|
|
}
|
|
logger.Info("memory enabled", "window_size", windowSize, "db", dbPath)
|
|
return memoryInit{store: store, windowSize: windowSize}, nil
|
|
}
|