diff --git a/example/webui/agentpool.go b/example/webui/agentpool.go index f5d42f0..a3cf60d 100644 --- a/example/webui/agentpool.go +++ b/example/webui/agentpool.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path/filepath" + "sync" "time" "github.com/mudler/local-agent-framework/example/webui/connector" @@ -44,15 +45,34 @@ type AgentConfig struct { } type AgentPool struct { + sync.Mutex file string pooldir string pool AgentPoolData agents map[string]*Agent managers map[string]Manager + agentStatus map[string]*Status apiURL, model string ragDB RAGDB } +type Status struct { + results []ActionState +} + +func (s *Status) addResult(result ActionState) { + // If we have more than 10 results, remove the oldest one + if len(s.results) > 10 { + s.results = s.results[1:] + } + + s.results = append(s.results, result) +} + +func (s *Status) Results() []ActionState { + return s.results +} + type AgentPoolData map[string]AgentConfig func loadPoolFromFile(path string) (*AgentPoolData, error) { @@ -75,14 +95,15 @@ func NewAgentPool(model, apiURL, directory string, RagDB RAGDB) (*AgentPool, err if _, err := os.Stat(poolfile); err != nil { // file does not exist, create a new pool return &AgentPool{ - file: poolfile, - pooldir: directory, - apiURL: apiURL, - model: model, - ragDB: RagDB, - agents: make(map[string]*Agent), - pool: make(map[string]AgentConfig), - managers: make(map[string]Manager), + file: poolfile, + pooldir: directory, + apiURL: apiURL, + model: model, + ragDB: RagDB, + agents: make(map[string]*Agent), + pool: make(map[string]AgentConfig), + agentStatus: make(map[string]*Status), + managers: make(map[string]Manager), }, nil } @@ -91,14 +112,15 @@ func NewAgentPool(model, apiURL, directory string, RagDB RAGDB) (*AgentPool, err return nil, err } return &AgentPool{ - file: poolfile, - apiURL: apiURL, - pooldir: directory, - ragDB: RagDB, - model: model, - agents: make(map[string]*Agent), - managers: make(map[string]Manager), - pool: *poolData, + file: poolfile, + apiURL: apiURL, + pooldir: directory, + ragDB: RagDB, + model: model, + agents: make(map[string]*Agent), + managers: make(map[string]Manager), + agentStatus: map[string]*Status{}, + pool: *poolData, }, nil } @@ -224,6 +246,12 @@ func (a *AgentConfig) availableConnectors() []Connector { return connectors } +func (a *AgentPool) GetStatusHistory(name string) *Status { + a.Lock() + defer a.Unlock() + return a.agentStatus[name] +} + func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error { manager := NewManager(5) ctx := context.Background() @@ -275,6 +303,13 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error }), WithSystemPrompt(config.SystemPrompt), WithAgentResultCallback(func(state ActionState) { + a.Lock() + if _, ok := a.agentStatus[name]; !ok { + a.agentStatus[name] = &Status{} + } + + a.agentStatus[name].addResult(state) + a.Unlock() fmt.Println("Reasoning", state.Reasoning) text := fmt.Sprintf(`Reasoning: %s diff --git a/example/webui/routes.go b/example/webui/routes.go index c57684b..22cb22e 100644 --- a/example/webui/routes.go +++ b/example/webui/routes.go @@ -6,6 +6,7 @@ import ( fiber "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/filesystem" + "github.com/mudler/local-agent-framework/agent" ) func RegisterRoutes(webapp *fiber.App, pool *AgentPool, db *InMemoryDatabase, app *App) { @@ -54,6 +55,19 @@ func RegisterRoutes(webapp *fiber.App, pool *AgentPool, db *InMemoryDatabase, ap return nil }) + webapp.Get("/status/:name", func(c *fiber.Ctx) error { + history := pool.GetStatusHistory(c.Params("name")) + if history == nil { + history = &Status{results: []agent.ActionState{}} + } + // reverse history + + return c.Render("views/status", fiber.Map{ + "Name": c.Params("name"), + "History": Reverse(history.Results()), + }) + }) + webapp.Get("/notify/:name", app.Notify(pool)) webapp.Post("/chat/:name", app.Chat(pool)) webapp.Post("/create", app.Create(pool)) @@ -81,3 +95,15 @@ func randStringRunes(n int) string { } return string(b) } + +func Reverse[T any](original []T) (reversed []T) { + reversed = make([]T, len(original)) + copy(reversed, original) + + for i := len(reversed)/2 - 1; i >= 0; i-- { + tmp := len(reversed) - 1 - i + reversed[i], reversed[tmp] = reversed[tmp], reversed[i] + } + + return +} diff --git a/example/webui/views/agents.html b/example/webui/views/agents.html index 067aeef..f2cdcb2 100644 --- a/example/webui/views/agents.html +++ b/example/webui/views/agents.html @@ -48,9 +48,13 @@ {{ range .Agents }} - + {{.}} -
+ + + Status + + Talk diff --git a/example/webui/views/status.html b/example/webui/views/status.html new file mode 100644 index 0000000..8339c3f --- /dev/null +++ b/example/webui/views/status.html @@ -0,0 +1,61 @@ + + + + Smart Agent status + {{template "views/partials/header"}} + + + + {{template "views/partials/menu"}} +
+ +
+

{{.Name}}

+
+ +
+
+ {{ range .History }} + +
+

Agent:

+
+ Result: {{.Result}} Action: {{.Action}} Params: {{.Params}} Reasoning: {{.Reasoning}} +
+
+ {{end}} +
+
+ +