Allow to configure connectors

This commit is contained in:
mudler
2024-04-08 20:15:32 +02:00
parent 533caeee96
commit 66b1847644
6 changed files with 105 additions and 12 deletions

View File

@@ -87,6 +87,10 @@ func (a *Agent) StopAction() {
} }
} }
func (a *Agent) Context() context.Context {
return a.context.Context
}
// Ask is a pre-emptive, blocking call that returns the response as soon as it's ready. // Ask is a pre-emptive, blocking call that returns the response as soon as it's ready.
// It discards any other computation. // It discards any other computation.
func (a *Agent) Ask(opts ...JobOption) *JobResult { func (a *Agent) Ask(opts ...JobOption) *JobResult {

View File

@@ -7,19 +7,21 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"github.com/mudler/local-agent-framework/example/webui/connector"
. "github.com/mudler/local-agent-framework/agent" . "github.com/mudler/local-agent-framework/agent"
"github.com/mudler/local-agent-framework/external" "github.com/mudler/local-agent-framework/external"
) )
type ConnectorConfig struct { type ConnectorConfig struct {
Type string `json:"type"` // e.g. Slack Type string `json:"type"` // e.g. Slack
Config map[string]interface{} `json:"config"` Config string `json:"config"`
} }
type ActionsConfig string type ActionsConfig string
type AgentConfig struct { type AgentConfig struct {
Connector []ConnectorConfig `json:"connector" form:"connector" ` Connector []ConnectorConfig `json:"connectors" form:"connectors" `
Actions []ActionsConfig `json:"actions" form:"actions"` Actions []ActionsConfig `json:"actions" form:"actions"`
// This is what needs to be part of ActionsConfig // This is what needs to be part of ActionsConfig
Model string `json:"model" form:"model"` Model string `json:"model" form:"model"`
@@ -111,7 +113,12 @@ func (a *AgentPool) List() []string {
return agents return agents
} }
var AvailableActions = []string{"search"} const (
ConnectorTelegram = "telegram"
ActionSearch = "search"
)
var AvailableActions = []string{ActionSearch}
func (a *AgentConfig) availableActions() []Action { func (a *AgentConfig) availableActions() []Action {
actions := []Action{} actions := []Action{}
@@ -123,7 +130,7 @@ func (a *AgentConfig) availableActions() []Action {
for _, action := range a.Actions { for _, action := range a.Actions {
fmt.Println("Set Action", action) fmt.Println("Set Action", action)
switch action { switch action {
case "search": case ActionSearch:
actions = append(actions, external.NewSearch(3)) actions = append(actions, external.NewSearch(3))
} }
} }
@@ -131,6 +138,39 @@ func (a *AgentConfig) availableActions() []Action {
return actions return actions
} }
type Connector interface {
AgentResultCallback() func(state ActionState)
AgentReasoningCallback() func(state ActionCurrentState) bool
Start(a *Agent)
}
var AvailableConnectors = []string{ConnectorTelegram}
func (a *AgentConfig) availableConnectors() []Connector {
connectors := []Connector{}
for _, c := range a.Connector {
fmt.Println("Set Connector", c)
switch c.Type {
case ConnectorTelegram:
var config map[string]string
if err := json.Unmarshal([]byte(c.Config), &config); err != nil {
fmt.Println("Error unmarshalling connector config", err)
continue
}
fmt.Println("Config", config)
cc, err := connector.NewTelegramConnector(config)
if err != nil {
fmt.Println("Error creating telegram connector", err)
continue
}
connectors = append(connectors, cc)
}
}
return connectors
}
func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error { func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error {
manager := NewManager(5) manager := NewManager(5)
model := a.model model := a.model
@@ -140,6 +180,9 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
if config.PeriodicRuns == "" { if config.PeriodicRuns == "" {
config.PeriodicRuns = "10m" config.PeriodicRuns = "10m"
} }
connectors := config.availableConnectors()
fmt.Println("Creating agent", name) fmt.Println("Creating agent", name)
fmt.Println("Model", model) fmt.Println("Model", model)
fmt.Println("API URL", a.apiURL) fmt.Println("API URL", a.apiURL)
@@ -165,6 +208,12 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
fmt.Sprintf(`Thinking: %s`, htmlIfy(state.Reasoning)), fmt.Sprintf(`Thinking: %s`, htmlIfy(state.Reasoning)),
).WithEvent("status"), ).WithEvent("status"),
) )
for _, c := range connectors {
if !c.AgentReasoningCallback()(state) {
return false
}
}
return true return true
}), }),
WithAgentResultCallback(func(state ActionState) { WithAgentResultCallback(func(state ActionState) {
@@ -185,6 +234,10 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
), ),
).WithEvent("status"), ).WithEvent("status"),
) )
for _, c := range connectors {
c.AgentResultCallback()(state)
}
}), }),
} }
if config.HUD { if config.HUD {
@@ -220,6 +273,10 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
} }
}() }()
for _, c := range connectors {
go c.Start(agent)
}
go func() { go func() {
for { for {
time.Sleep(1 * time.Second) // Send a message every seconds time.Sleep(1 * time.Second) // Send a message every seconds

View File

@@ -18,12 +18,40 @@
<input type="text" name="name" id="name" 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="Name"> <input type="text" name="name" id="name" 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="Name">
</div> </div>
<!--
<div class="mb-4"> <div id="connectorsSection">
<label for="connector" class="block text-sm font-medium text-gray-400">Connector Config (JSON)</label> <div class="connector mb-4">
<textarea id="connector" name="connector" 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='[{"...":"..."}]'></textarea> </div>
</div> </div>
--> <button type="button" id="addConnectorButton" 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">
Add Connector
</button>
<script>
document.getElementById('addConnectorButton').addEventListener('click', function() {
const connectorsSection = document.getElementById('connectorsSection');
const newConnectorIndex = connectorsSection.getElementsByClassName('connector').length;
const newConnectorHTML = `
<div class="connector mb-4">
<div class="mb-4">
<label for="connectorType${newConnectorIndex}" class="block text-sm font-medium text-gray-400">Connector Type</label>
<select name="connectors[${newConnectorIndex}].type" id="connectorType${newConnectorIndex}" 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">
{{ range .Connectors }}
<option value="{{.}}">{{.}}</option>
{{ end }}
</select>
</div>
<div class="mb-4">
<label for="connectorConfig${newConnectorIndex}" class="block text-sm font-medium text-gray-400">Connector Config (JSON)</label>
<textarea id="connectorConfig${newConnectorIndex}" name="connectors[${newConnectorIndex}].config" 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='{"token":"..."}'></textarea>
</div>
</div>
`;
connectorsSection.insertAdjacentHTML('beforeend', newConnectorHTML);
});
</script>
<div class="mb-4" id="action_box"> <div class="mb-4" id="action_box">
<label for="actions" class="block text-sm font-medium text-gray-400">Agent Actions</label> <label for="actions" class="block text-sm font-medium text-gray-400">Agent Actions</label>
<select style="display: none" name="actions" id="actions" 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"> <select style="display: none" name="actions" id="actions" 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">

View File

@@ -88,8 +88,9 @@ func main() {
webapp.Get("/create", func(c *fiber.Ctx) error { webapp.Get("/create", func(c *fiber.Ctx) error {
return c.Render("create.html", fiber.Map{ return c.Render("create.html", fiber.Map{
"Title": "Hello, World!", "Title": "Hello, World!",
"Actions": AvailableActions, "Actions": AvailableActions,
"Connectors": AvailableConnectors,
}) })
}) })

1
go.mod
View File

@@ -20,6 +20,7 @@ require (
github.com/andybalholm/cascadia v1.1.0 // indirect github.com/andybalholm/cascadia v1.1.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/logr v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/go-telegram/bot v1.2.1 // indirect
github.com/gofiber/fiber/v2 v2.52.4 // indirect github.com/gofiber/fiber/v2 v2.52.4 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect

2
go.sum
View File

@@ -16,6 +16,8 @@ github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-telegram/bot v1.2.1 h1:FkrixLCtMtPUQAN4plXdNElbhkdXkx2p68YPXKBruDg=
github.com/go-telegram/bot v1.2.1/go.mod h1:i2TRs7fXWIeaceF3z7KzsMt/he0TwkVC680mvdTFYeM=
github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM=
github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
github.com/gofiber/fiber/v3 v3.0.0-20240405062939-c8c51ee78331 h1:kDxTNPKMIRz8q28+tJHL2p87Cjtmkfn/OsLfastmpaY= github.com/gofiber/fiber/v3 v3.0.0-20240405062939-c8c51ee78331 h1:kDxTNPKMIRz8q28+tJHL2p87Cjtmkfn/OsLfastmpaY=