Add more actions, small fixups in the UI, add stop action

This commit is contained in:
mudler
2024-04-15 17:50:51 +02:00
parent 7db2b10bd2
commit 55b7b4a41e
28 changed files with 469 additions and 190 deletions

65
example/webui/actions.go Normal file
View File

@@ -0,0 +1,65 @@
package main
import (
"context"
"encoding/json"
"log/slog"
. "github.com/mudler/local-agent-framework/agent"
"github.com/mudler/local-agent-framework/external"
)
const (
// Actions
ActionSearch = "search"
ActionGithubIssueLabeler = "github-issue-labeler"
ActionGithubIssueOpener = "github-issue-opener"
ActionGithubIssueCloser = "github-issue-closer"
ActionGithubIssueSearcher = "github-issue-searcher"
ActionScraper = "scraper"
ActionWikipedia = "wikipedia"
)
var AvailableActions = []string{
ActionSearch,
ActionGithubIssueLabeler,
ActionGithubIssueOpener,
ActionGithubIssueCloser,
ActionGithubIssueSearcher,
ActionScraper,
ActionWikipedia,
}
func (a *AgentConfig) availableActions(ctx context.Context) []Action {
actions := []Action{}
for _, action := range a.Actions {
slog.Info("Set Action", action)
var config map[string]string
if err := json.Unmarshal([]byte(action.Config), &config); err != nil {
slog.Info("Error unmarshalling action config", err)
continue
}
slog.Info("Config", config)
switch action.Name {
case ActionSearch:
actions = append(actions, external.NewSearch(config))
case ActionGithubIssueLabeler:
actions = append(actions, external.NewGithubIssueLabeler(ctx, config))
case ActionGithubIssueOpener:
actions = append(actions, external.NewGithubIssueOpener(ctx, config))
case ActionGithubIssueCloser:
actions = append(actions, external.NewGithubIssueCloser(ctx, config))
case ActionGithubIssueSearcher:
actions = append(actions, external.NewGithubIssueSearch(ctx, config))
case ActionScraper:
actions = append(actions, external.NewScraper(config))
case ActionWikipedia:
actions = append(actions, external.NewWikipedia(config))
}
}
return actions
}

View File

@@ -0,0 +1,30 @@
package main
type ConnectorConfig struct {
Type string `json:"type"` // e.g. Slack
Config string `json:"config"`
}
type ActionsConfig struct {
Name string `json:"name"` // e.g. search
Config string `json:"config"`
}
type AgentConfig struct {
Connector []ConnectorConfig `json:"connectors" form:"connectors" `
Actions []ActionsConfig `json:"actions" form:"actions"`
// This is what needs to be part of ActionsConfig
Model string `json:"model" form:"model"`
Name string `json:"name" form:"name"`
HUD bool `json:"hud" form:"hud"`
StandaloneJob bool `json:"standalone_job" form:"standalone_job"`
RandomIdentity bool `json:"random_identity" form:"random_identity"`
InitiateConversations bool `json:"initiate_conversations" form:"initiate_conversations"`
IdentityGuidance string `json:"identity_guidance" form:"identity_guidance"`
PeriodicRuns string `json:"periodic_runs" form:"periodic_runs"`
PermanentGoal string `json:"permanent_goal" form:"permanent_goal"`
EnableKnowledgeBase bool `json:"enable_kb" form:"enable_kb"`
KnowledgeBaseResults int `json:"kb_results" form:"kb_results"`
CanStopItself bool `json:"can_stop_itself" form:"can_stop_itself"`
SystemPrompt string `json:"system_prompt" form:"system_prompt"`
}

View File

@@ -10,41 +10,9 @@ import (
"sync"
"time"
"github.com/mudler/local-agent-framework/example/webui/connector"
. "github.com/mudler/local-agent-framework/agent"
"github.com/mudler/local-agent-framework/external"
)
type ConnectorConfig struct {
Type string `json:"type"` // e.g. Slack
Config string `json:"config"`
}
type ActionsConfig struct {
Name string `json:"name"` // e.g. search
Config string `json:"config"`
}
type AgentConfig struct {
Connector []ConnectorConfig `json:"connectors" form:"connectors" `
Actions []ActionsConfig `json:"actions" form:"actions"`
// This is what needs to be part of ActionsConfig
Model string `json:"model" form:"model"`
Name string `json:"name" form:"name"`
HUD bool `json:"hud" form:"hud"`
StandaloneJob bool `json:"standalone_job" form:"standalone_job"`
RandomIdentity bool `json:"random_identity" form:"random_identity"`
InitiateConversations bool `json:"initiate_conversations" form:"initiate_conversations"`
IdentityGuidance string `json:"identity_guidance" form:"identity_guidance"`
PeriodicRuns string `json:"periodic_runs" form:"periodic_runs"`
PermanentGoal string `json:"permanent_goal" form:"permanent_goal"`
EnableKnowledgeBase bool `json:"enable_kb" form:"enable_kb"`
KnowledgeBaseResults int `json:"kb_results" form:"kb_results"`
CanStopItself bool `json:"can_stop_itself" form:"can_stop_itself"`
SystemPrompt string `json:"system_prompt" form:"system_prompt"`
}
type AgentPool struct {
sync.Mutex
file string
@@ -148,105 +116,6 @@ func (a *AgentPool) List() []string {
return agents
}
const (
// Connectors
ConnectorTelegram = "telegram"
ConnectorSlack = "slack"
ConnectorDiscord = "discord"
ConnectorGithubIssues = "github-issues"
// Actions
ActionSearch = "search"
ActionGithubIssueLabeler = "github-issue-labeler"
ActionGithubIssueOpener = "github-issue-opener"
ActionGithubIssueCloser = "github-issue-closer"
ActionGithubIssueSearcher = "github-issue-searcher"
)
var AvailableActions = []string{
ActionSearch,
ActionGithubIssueLabeler,
ActionGithubIssueOpener,
ActionGithubIssueCloser,
ActionGithubIssueSearcher,
}
func (a *AgentConfig) availableActions(ctx context.Context) []Action {
actions := []Action{}
for _, action := range a.Actions {
slog.Info("Set Action", action)
var config map[string]string
if err := json.Unmarshal([]byte(action.Config), &config); err != nil {
slog.Info("Error unmarshalling action config", err)
continue
}
slog.Info("Config", config)
switch action.Name {
case ActionSearch:
actions = append(actions, external.NewSearch(config))
case ActionGithubIssueLabeler:
actions = append(actions, external.NewGithubIssueLabeler(ctx, config))
case ActionGithubIssueOpener:
actions = append(actions, external.NewGithubIssueOpener(ctx, config))
case ActionGithubIssueCloser:
actions = append(actions, external.NewGithubIssueCloser(ctx, config))
case ActionGithubIssueSearcher:
actions = append(actions, external.NewGithubIssueSearch(ctx, config))
}
}
return actions
}
type Connector interface {
AgentResultCallback() func(state ActionState)
AgentReasoningCallback() func(state ActionCurrentState) bool
Start(a *Agent)
}
var AvailableConnectors = []string{
ConnectorTelegram,
ConnectorSlack,
ConnectorDiscord,
ConnectorGithubIssues,
}
func (a *AgentConfig) availableConnectors() []Connector {
connectors := []Connector{}
for _, c := range a.Connector {
slog.Info("Set Connector", c)
var config map[string]string
if err := json.Unmarshal([]byte(c.Config), &config); err != nil {
slog.Info("Error unmarshalling connector config", err)
continue
}
slog.Info("Config", config)
switch c.Type {
case ConnectorTelegram:
cc, err := connector.NewTelegramConnector(config)
if err != nil {
slog.Info("Error creating telegram connector", err)
continue
}
connectors = append(connectors, cc)
case ConnectorSlack:
connectors = append(connectors, connector.NewSlack(config))
case ConnectorDiscord:
connectors = append(connectors, connector.NewDiscord(config))
case ConnectorGithubIssues:
connectors = append(connectors, connector.NewGithubIssueWatcher(config))
}
}
return connectors
}
func (a *AgentPool) GetStatusHistory(name string) *Status {
a.Lock()
defer a.Unlock()

View File

@@ -264,7 +264,11 @@ func (a *App) Chat(pool *AgentPool) func(c *fiber.Ctx) error {
res := agent.Ask(
WithText(query),
)
slog.Info("response is", res.Response)
if res.Error != nil {
slog.Error("Error asking agent", "agent", agentName, "error", res.Error)
} else {
slog.Info("we got a response from the agent", "agent", agentName, "response", res.Response)
}
manager.Send(
NewMessage(
chatDiv(res.Response, "blue"),

View File

@@ -0,0 +1,64 @@
package main
import (
"encoding/json"
"log/slog"
. "github.com/mudler/local-agent-framework/agent"
"github.com/mudler/local-agent-framework/example/webui/connector"
)
const (
// Connectors
ConnectorTelegram = "telegram"
ConnectorSlack = "slack"
ConnectorDiscord = "discord"
ConnectorGithubIssues = "github-issues"
)
type Connector interface {
AgentResultCallback() func(state ActionState)
AgentReasoningCallback() func(state ActionCurrentState) bool
Start(a *Agent)
}
var AvailableConnectors = []string{
ConnectorTelegram,
ConnectorSlack,
ConnectorDiscord,
ConnectorGithubIssues,
}
func (a *AgentConfig) availableConnectors() []Connector {
connectors := []Connector{}
for _, c := range a.Connector {
slog.Info("Set Connector", c)
var config map[string]string
if err := json.Unmarshal([]byte(c.Config), &config); err != nil {
slog.Info("Error unmarshalling connector config", err)
continue
}
slog.Info("Config", config)
switch c.Type {
case ConnectorTelegram:
cc, err := connector.NewTelegramConnector(config)
if err != nil {
slog.Info("Error creating telegram connector", err)
continue
}
connectors = append(connectors, cc)
case ConnectorSlack:
connectors = append(connectors, connector.NewSlack(config))
case ConnectorDiscord:
connectors = append(connectors, connector.NewDiscord(config))
case ConnectorGithubIssues:
connectors = append(connectors, connector.NewGithubIssueWatcher(config))
}
}
return connectors
}

View File

@@ -105,7 +105,7 @@
</div>
<div class="mb-4">
<label for="identity_guidance" class="block text-lg font-medium text-gray-400">Identity Guidance</label>
<input type="text" name="identity_guidance" id="identity_guidance" class="mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md bg-gray-700 text-white" placeholder="Identity Guidance">
<textarea name="identity_guidance" id="identity_guidance" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md bg-gray-700 text-white" placeholder="Identity Guidance"></textarea>
</div>
<div class="mb-4">
<label for="periodic_runs" class="block text-lg font-medium text-gray-400">Periodic Runs</label>
@@ -113,13 +113,13 @@
</div>
<div class="mb-4">
<label for="permanent_goal" class="block text-lg font-medium text-gray-400">Permanent goal</label>
<input type="text" name="permanent_goal" id="permanent_goal" class="mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md bg-gray-700 text-white" placeholder="Permanent goal">
<textarea name="permanent_goal" id="permanent_goal" class="mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md bg-gray-700 text-white" placeholder="Permanent goal"></textarea>
</div>
<div class="mb-4">
<label for="system_prompt" class="block text-lg font-medium text-gray-400">System prompt</label>
<input type="text" name="system_prompt" id="system_prompt" class="mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md bg-gray-700 text-white" placeholder="System prompt">
<textarea name="system_prompt" id="system_prompt" class="mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md bg-gray-700 text-white" placeholder="System prompt"></textarea>
</div>
<div class="flex items-center justify-between">
<button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-500 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
Create Agent

View File

@@ -66,7 +66,7 @@
<div class="section-box">
<h2>Danger section</h2>
<a href="/delete/{{.}}" class="text-red-500 hover:text-red-400">
<a href="/delete/{{.Name}}" class="text-red-500 hover:text-red-400">
<i class="fas fa-trash-alt"></i> Delete
</a>
</div>