192 lines
5.2 KiB
Go
192 lines
5.2 KiB
Go
package agentpool
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/mudler/LocalAGI/core/agent"
|
|
"github.com/mudler/LocalAGI/core/sse"
|
|
"github.com/mudler/LocalAGI/core/state"
|
|
agiServices "github.com/mudler/LocalAGI/services"
|
|
"github.com/mudler/LocalAI/core/services/agents"
|
|
)
|
|
|
|
// localAgentConfigBackend wraps the in-memory LocalAGI AgentPool for standalone mode.
|
|
type localAgentConfigBackend struct {
|
|
svc *AgentPoolService // back-reference for shared fields (pool, configMeta, outputsDir, etc.)
|
|
}
|
|
|
|
func newLocalAgentConfigBackend(svc *AgentPoolService) *localAgentConfigBackend {
|
|
return &localAgentConfigBackend{svc: svc}
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) ListAgents(userID string) map[string]bool {
|
|
statuses := map[string]bool{}
|
|
agents := b.svc.localAGI.pool.List()
|
|
prefix := ""
|
|
if userID != "" {
|
|
prefix = userID + ":"
|
|
}
|
|
for _, a := range agents {
|
|
if userID != "" && !strings.HasPrefix(a, prefix) {
|
|
continue
|
|
}
|
|
ag := b.svc.localAGI.pool.GetAgent(a)
|
|
if ag == nil {
|
|
continue
|
|
}
|
|
displayName := a
|
|
if prefix != "" {
|
|
displayName = strings.TrimPrefix(a, prefix)
|
|
}
|
|
statuses[displayName] = !ag.Paused()
|
|
}
|
|
return statuses
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) GetConfig(userID, name string) *state.AgentConfig {
|
|
cfg := b.svc.localAGI.pool.GetConfig(agents.AgentKey(userID, name))
|
|
if cfg == nil {
|
|
return nil
|
|
}
|
|
// Return a copy with the original name (strip userID: prefix)
|
|
result := *cfg
|
|
result.Name = name
|
|
return &result
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) SaveConfig(userID string, cfg *state.AgentConfig) error {
|
|
key := agents.AgentKey(userID, cfg.Name)
|
|
cfg.Name = key
|
|
return b.svc.localAGI.pool.CreateAgent(key, cfg)
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) UpdateConfig(userID, name string, cfg *state.AgentConfig) error {
|
|
key := agents.AgentKey(userID, name)
|
|
if old := b.svc.localAGI.pool.GetConfig(key); old == nil {
|
|
return fmt.Errorf("%w: %s", ErrAgentNotFound, name)
|
|
}
|
|
cfg.Name = key
|
|
return b.svc.localAGI.pool.RecreateAgent(key, cfg)
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) DeleteConfig(userID, name string) error {
|
|
return b.svc.localAGI.pool.Remove(agents.AgentKey(userID, name))
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) ImportConfig(userID string, cfg *state.AgentConfig) error {
|
|
key := agents.AgentKey(userID, cfg.Name)
|
|
cfg.Name = key
|
|
return b.svc.localAGI.pool.CreateAgent(key, cfg)
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) ExportConfig(userID, name string) ([]byte, error) {
|
|
cfg := b.svc.localAGI.pool.GetConfig(agents.AgentKey(userID, name))
|
|
if cfg == nil {
|
|
return nil, fmt.Errorf("%w: %s", ErrAgentNotFound, name)
|
|
}
|
|
return json.MarshalIndent(cfg, "", " ")
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) SetStatus(userID, name, status string) error {
|
|
ag := b.svc.localAGI.pool.GetAgent(agents.AgentKey(userID, name))
|
|
if ag == nil {
|
|
return fmt.Errorf("%w: %s", ErrAgentNotFound, name)
|
|
}
|
|
switch status {
|
|
case "paused":
|
|
ag.Pause()
|
|
case "active":
|
|
ag.Resume()
|
|
default:
|
|
return fmt.Errorf("unknown status: %s", status)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) GetAgent(userID, name string) *agent.Agent {
|
|
return b.svc.localAGI.pool.GetAgent(agents.AgentKey(userID, name))
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) GetSSEManager(userID, name string) sse.Manager {
|
|
return b.svc.localAGI.pool.GetManager(agents.AgentKey(userID, name))
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) GetStatus(userID, name string) *state.Status {
|
|
return b.svc.localAGI.pool.GetStatusHistory(agents.AgentKey(userID, name))
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) GetObservables(userID, name string) ([]json.RawMessage, error) {
|
|
ag := b.svc.localAGI.pool.GetAgent(agents.AgentKey(userID, name))
|
|
if ag == nil {
|
|
return nil, fmt.Errorf("%w: %s", ErrAgentNotFound, name)
|
|
}
|
|
history := ag.Observer().History()
|
|
result := make([]json.RawMessage, 0, len(history))
|
|
for _, obs := range history {
|
|
data, err := json.Marshal(obs)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
result = append(result, data)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) ClearObservables(userID, name string) error {
|
|
ag := b.svc.localAGI.pool.GetAgent(agents.AgentKey(userID, name))
|
|
if ag == nil {
|
|
return fmt.Errorf("%w: %s", ErrAgentNotFound, name)
|
|
}
|
|
ag.Observer().ClearHistory()
|
|
return nil
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) ListAllGrouped() map[string][]UserAgentInfo {
|
|
result := map[string][]UserAgentInfo{}
|
|
agents := b.svc.localAGI.pool.List()
|
|
for _, a := range agents {
|
|
ag := b.svc.localAGI.pool.GetAgent(a)
|
|
if ag == nil {
|
|
continue
|
|
}
|
|
userID := ""
|
|
name := a
|
|
if u, n, ok := strings.Cut(a, ":"); ok {
|
|
userID = u
|
|
name = n
|
|
}
|
|
result[userID] = append(result[userID], UserAgentInfo{
|
|
Name: name,
|
|
Active: !ag.Paused(),
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) GetConfigMeta() AgentConfigMetaResult {
|
|
meta := b.svc.localAGI.configMeta
|
|
return AgentConfigMetaResult{
|
|
Fields: meta.Fields,
|
|
Actions: meta.Actions,
|
|
Connectors: meta.Connectors,
|
|
Filters: meta.Filters,
|
|
OutputsDir: b.svc.outputsDir,
|
|
}
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) ListAvailableActions() []string {
|
|
return agiServices.AvailableActions
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) Chat(userID, name, message string) (string, error) {
|
|
return b.svc.Chat(agents.AgentKey(userID, name), message)
|
|
}
|
|
|
|
func (b *localAgentConfigBackend) Stop() {
|
|
if b.svc.localAGI.pool != nil {
|
|
b.svc.localAGI.pool.StopAll()
|
|
}
|
|
}
|