This reverts commit d7cfa7f0b2.
This commit is contained in:
committed by
GitHub
parent
1e5b3f501f
commit
d54abc3ed0
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,7 +2,5 @@ models/
|
|||||||
data/
|
data/
|
||||||
pool
|
pool
|
||||||
uploads/
|
uploads/
|
||||||
volumes/
|
|
||||||
local-agent-framework
|
local-agent-framework
|
||||||
localagent
|
localagent
|
||||||
LocalAgent
|
|
||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnectorConfig struct {
|
type ConnectorConfig struct {
|
||||||
@@ -63,6 +62,5 @@ type AgentConfig struct {
|
|||||||
type Connector interface {
|
type Connector interface {
|
||||||
AgentResultCallback() func(state agent.ActionState)
|
AgentResultCallback() func(state agent.ActionState)
|
||||||
AgentReasoningCallback() func(state agent.ActionCurrentState) bool
|
AgentReasoningCallback() func(state agent.ActionCurrentState) bool
|
||||||
ConfigForm() metaform.Form
|
|
||||||
Start(a *agent.Agent)
|
Start(a *agent.Agent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
package metaform
|
|
||||||
|
|
||||||
// Option represents a selectable option for FieldOption type
|
|
||||||
type Option struct {
|
|
||||||
Value string `json:"value"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FieldKind string
|
|
||||||
|
|
||||||
const (
|
|
||||||
FieldString FieldKind = "string"
|
|
||||||
FieldNumber FieldKind = "number"
|
|
||||||
FieldOptions FieldKind = "options"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Field struct {
|
|
||||||
Kind FieldKind `json:"kind"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
Required bool `json:"required"`
|
|
||||||
Placeholder string `json:"placeholder,omitempty"`
|
|
||||||
Options []Option `json:"options,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Form struct {
|
|
||||||
Fields []Field
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -38,27 +37,6 @@ func (d *Discord) AgentReasoningCallback() func(state agent.ActionCurrentState)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discord) ConfigForm() metaform.Form {
|
|
||||||
return metaform.Form{
|
|
||||||
Fields: []metaform.Field{
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "token",
|
|
||||||
Label: "Bot Token",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "Your Discord bot token",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "defaultChannel",
|
|
||||||
Label: "Default Channel",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "The default channel for the bot to join",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Discord) Start(a *agent.Agent) {
|
func (d *Discord) Start(a *agent.Agent) {
|
||||||
|
|
||||||
Token := d.token
|
Token := d.token
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
|
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
@@ -64,51 +63,6 @@ func (g *GithubIssues) AgentReasoningCallback() func(state agent.ActionCurrentSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssues) ConfigForm() metaform.Form {
|
|
||||||
return metaform.Form{
|
|
||||||
Fields: []metaform.Field{
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "token",
|
|
||||||
Label: "GitHub Token",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "Your GitHub personal access token",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "owner",
|
|
||||||
Label: "Repository Owner",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "username or organization",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "repository",
|
|
||||||
Label: "Repository Name",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "repo-name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldOptions,
|
|
||||||
Name: "replyIfNoReplies",
|
|
||||||
Label: "Reply Behavior",
|
|
||||||
Required: true,
|
|
||||||
Options: []metaform.Option{
|
|
||||||
{Value: "true", Label: "Reply only to issues with no comments"},
|
|
||||||
{Value: "false", Label: "Reply to all issues"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "pollInterval",
|
|
||||||
Label: "Poll Interval",
|
|
||||||
Required: false,
|
|
||||||
Placeholder: "10m",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GithubIssues) Start(a *agent.Agent) {
|
func (g *GithubIssues) Start(a *agent.Agent) {
|
||||||
// Start the connector
|
// Start the connector
|
||||||
g.agent = a
|
g.agent = a
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
|
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
@@ -64,51 +63,6 @@ func (g *GithubPRs) AgentReasoningCallback() func(state agent.ActionCurrentState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubPRs) ConfigForm() metaform.Form {
|
|
||||||
return metaform.Form{
|
|
||||||
Fields: []metaform.Field{
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "token",
|
|
||||||
Label: "GitHub Token",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "Your GitHub personal access token",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "owner",
|
|
||||||
Label: "Repository Owner",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "username or organization",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "repository",
|
|
||||||
Label: "Repository Name",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "repo-name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldOptions,
|
|
||||||
Name: "replyIfNoReplies",
|
|
||||||
Label: "Reply Behavior",
|
|
||||||
Required: true,
|
|
||||||
Options: []metaform.Option{
|
|
||||||
{Value: "true", Label: "Reply only to PRs with no comments"},
|
|
||||||
{Value: "false", Label: "Reply to all PRs"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "pollInterval",
|
|
||||||
Label: "Poll Interval",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "10m",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GithubPRs) Start(a *agent.Agent) {
|
func (g *GithubPRs) Start(a *agent.Agent) {
|
||||||
// Start the connector
|
// Start the connector
|
||||||
g.agent = a
|
g.agent = a
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services/actions"
|
"github.com/mudler/LocalAgent/services/actions"
|
||||||
irc "github.com/thoj/go-ircevent"
|
irc "github.com/thoj/go-ircevent"
|
||||||
@@ -44,51 +43,6 @@ func (i *IRC) AgentReasoningCallback() func(state agent.ActionCurrentState) bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IRC) ConfigForm() metaform.Form {
|
|
||||||
return metaform.Form{
|
|
||||||
Fields: []metaform.Field{
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "server",
|
|
||||||
Label: "Server",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "chat.freenode.net",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "port",
|
|
||||||
Label: "Port",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "6667",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "nickname",
|
|
||||||
Label: "Nickname",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "LocalAgentBot",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "channel",
|
|
||||||
Label: "Channel",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "#general",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldOptions,
|
|
||||||
Name: "alwaysReply",
|
|
||||||
Label: "Always Reply",
|
|
||||||
Required: true,
|
|
||||||
Options: []metaform.Option{
|
|
||||||
{Value: "false", Label: "Only when mentioned"},
|
|
||||||
{Value: "true", Label: "Reply to all messages"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanUpUsernameFromMessage removes the bot's nickname from the message
|
// cleanUpUsernameFromMessage removes the bot's nickname from the message
|
||||||
func cleanUpMessage(message string, nickname string) string {
|
func cleanUpMessage(message string, nickname string) string {
|
||||||
cleaned := strings.ReplaceAll(message, nickname+":", "")
|
cleaned := strings.ReplaceAll(message, nickname+":", "")
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services/actions"
|
"github.com/mudler/LocalAgent/services/actions"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
@@ -53,44 +52,6 @@ func (t *Slack) AgentReasoningCallback() func(state agent.ActionCurrentState) bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Slack) ConfigForm() metaform.Form {
|
|
||||||
return metaform.Form{
|
|
||||||
Fields: []metaform.Field{
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "appToken",
|
|
||||||
Label: "App Token",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "xapp-...",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "botToken",
|
|
||||||
Label: "Bot Token",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "xoxb-...",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "channelID",
|
|
||||||
Label: "Channel ID",
|
|
||||||
Required: false,
|
|
||||||
Placeholder: "C12345678",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldOptions,
|
|
||||||
Name: "alwaysReply",
|
|
||||||
Label: "Always Reply",
|
|
||||||
Required: false,
|
|
||||||
Options: []metaform.Option{
|
|
||||||
{Value: "false", Label: "Only when mentioned"},
|
|
||||||
{Value: "true", Label: "Reply to all messages"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanUpUsernameFromMessage(message string, b *slack.AuthTestResponse) string {
|
func cleanUpUsernameFromMessage(message string, b *slack.AuthTestResponse) string {
|
||||||
cleaned := strings.ReplaceAll(message, "<@"+b.UserID+">", "")
|
cleaned := strings.ReplaceAll(message, "<@"+b.UserID+">", "")
|
||||||
cleaned = strings.ReplaceAll(cleaned, "<@"+b.BotID+">", "")
|
cleaned = strings.ReplaceAll(cleaned, "<@"+b.BotID+">", "")
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/go-telegram/bot"
|
"github.com/go-telegram/bot"
|
||||||
"github.com/go-telegram/bot/models"
|
"github.com/go-telegram/bot/models"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Telegram struct {
|
type Telegram struct {
|
||||||
@@ -38,20 +37,6 @@ func (t *Telegram) AgentReasoningCallback() func(state agent.ActionCurrentState)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Telegram) ConfigForm() metaform.Form {
|
|
||||||
return metaform.Form{
|
|
||||||
Fields: []metaform.Field{
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "token",
|
|
||||||
Label: "Bot Token",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "Your Telegram bot token from @BotFather",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Telegram) Start(a *agent.Agent) {
|
func (t *Telegram) Start(a *agent.Agent) {
|
||||||
ctx, cancel := signal.NotifyContext(a.Context(), os.Interrupt)
|
ctx, cancel := signal.NotifyContext(a.Context(), os.Interrupt)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services/connectors/twitter"
|
"github.com/mudler/LocalAgent/services/connectors/twitter"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
@@ -33,37 +32,6 @@ func (t *Twitter) AgentReasoningCallback() func(state agent.ActionCurrentState)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Twitter) ConfigForm() metaform.Form {
|
|
||||||
return metaform.Form{
|
|
||||||
Fields: []metaform.Field{
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "token",
|
|
||||||
Label: "Token",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "elmo-...",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldString,
|
|
||||||
Name: "botUsername",
|
|
||||||
Label: "Bot Username",
|
|
||||||
Required: true,
|
|
||||||
Placeholder: "Chocolate Pineapple",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: metaform.FieldOptions,
|
|
||||||
Name: "noCharacterLimit",
|
|
||||||
Label: "No Character Limit",
|
|
||||||
Required: false,
|
|
||||||
Options: []metaform.Option{
|
|
||||||
{Value: "false", Label: ""},
|
|
||||||
{Value: "true", Label: ""},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTwitterConnector(config map[string]string) (*Twitter, error) {
|
func NewTwitterConnector(config map[string]string) (*Twitter, error) {
|
||||||
return &Twitter{
|
return &Twitter{
|
||||||
token: config["token"],
|
token: config["token"],
|
||||||
|
|||||||
41
webui/app.go
41
webui/app.go
@@ -10,13 +10,10 @@ import (
|
|||||||
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/webui/types"
|
"github.com/mudler/LocalAgent/webui/types"
|
||||||
"github.com/mudler/LocalAgent/services"
|
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/core/sse"
|
"github.com/mudler/LocalAgent/core/sse"
|
||||||
"github.com/mudler/LocalAgent/core/state"
|
"github.com/mudler/LocalAgent/core/state"
|
||||||
"github.com/mudler/LocalAgent/pkg/metaform"
|
|
||||||
"github.com/mudler/LocalAgent/services/connectors"
|
|
||||||
|
|
||||||
"github.com/donseba/go-htmx"
|
"github.com/donseba/go-htmx"
|
||||||
fiber "github.com/gofiber/fiber/v2"
|
fiber "github.com/gofiber/fiber/v2"
|
||||||
@@ -353,41 +350,3 @@ func (a *App) Responses(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
|||||||
return c.JSON(response)
|
return c.JSON(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) GetConnectorForm(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
|
||||||
return func(c *fiber.Ctx) error {
|
|
||||||
connectorType := c.Params("type")
|
|
||||||
|
|
||||||
// Create a temporary connector to get its form metadata
|
|
||||||
var form metaform.Form
|
|
||||||
|
|
||||||
switch connectorType {
|
|
||||||
case services.ConnectorTelegram:
|
|
||||||
form = (&connectors.Telegram{}).ConfigForm()
|
|
||||||
case services.ConnectorSlack:
|
|
||||||
form = (&connectors.Slack{}).ConfigForm()
|
|
||||||
case services.ConnectorDiscord:
|
|
||||||
form = (&connectors.Discord{}).ConfigForm()
|
|
||||||
case services.ConnectorGithubIssues:
|
|
||||||
form = (&connectors.GithubIssues{}).ConfigForm()
|
|
||||||
case services.ConnectorGithubPRs:
|
|
||||||
form = (&connectors.GithubPRs{}).ConfigForm()
|
|
||||||
case services.ConnectorIRC:
|
|
||||||
form = (&connectors.IRC{}).ConfigForm()
|
|
||||||
case services.ConnectorTwitter:
|
|
||||||
form = (&connectors.Twitter{}).ConfigForm()
|
|
||||||
default:
|
|
||||||
return c.Status(404).JSON(fiber.Map{
|
|
||||||
"error": "Connector type not found",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a data structure to pass both the form and the connector type
|
|
||||||
data := fiber.Map{
|
|
||||||
"Form": form,
|
|
||||||
"Type": connectorType,
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Render("views/partials/metaform", data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,39 +1,15 @@
|
|||||||
// Common utility functions for agent forms
|
// Common utility functions for agent forms
|
||||||
const AgentFormUtils = {
|
const AgentFormUtils = {
|
||||||
// Add dynamic component based on template
|
// Add dynamic component based on template
|
||||||
addDynamicComponent: function(sectionId, templateFunction, options = {}) {
|
addDynamicComponent: function(sectionId, templateFunction, dataItems) {
|
||||||
const section = document.getElementById(sectionId);
|
const section = document.getElementById(sectionId);
|
||||||
if (!section) return;
|
const newIndex = section.getElementsByClassName(dataItems.className).length;
|
||||||
|
|
||||||
const index = section.getElementsByClassName(options.className || 'dynamic-component').length;
|
// Generate HTML from template function
|
||||||
const templateData = { index, ...options };
|
const newHtml = templateFunction(newIndex, dataItems);
|
||||||
|
|
||||||
// Create a new element from the template
|
// Add to DOM
|
||||||
const tempDiv = document.createElement('div');
|
section.insertAdjacentHTML('beforeend', newHtml);
|
||||||
tempDiv.innerHTML = templateFunction(index, templateData);
|
|
||||||
const newElement = tempDiv.firstElementChild;
|
|
||||||
|
|
||||||
// Add the new element to the section
|
|
||||||
section.appendChild(newElement);
|
|
||||||
|
|
||||||
// If it's a connector, add event listener for type change
|
|
||||||
if (options.className === 'connector') {
|
|
||||||
const newIndex = index;
|
|
||||||
const connectorType = document.getElementById(`connectorType${newIndex}`);
|
|
||||||
if (connectorType) {
|
|
||||||
// Add event listener for future changes
|
|
||||||
connectorType.addEventListener('change', function() {
|
|
||||||
loadConnectorForm(newIndex, this.value, null);
|
|
||||||
});
|
|
||||||
|
|
||||||
// If a connector type is already selected (default value), load its form immediately
|
|
||||||
if (connectorType.value) {
|
|
||||||
loadConnectorForm(newIndex, connectorType.value, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newElement;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Process form data into JSON structure
|
// Process form data into JSON structure
|
||||||
@@ -84,57 +60,32 @@ const AgentFormUtils = {
|
|||||||
const connectorsElements = document.getElementsByClassName('connector');
|
const connectorsElements = document.getElementsByClassName('connector');
|
||||||
|
|
||||||
for (let i = 0; i < connectorsElements.length; i++) {
|
for (let i = 0; i < connectorsElements.length; i++) {
|
||||||
const typeSelect = document.getElementById(`connectorType${i}`);
|
const typeField = document.getElementById(`connectorType${i}`);
|
||||||
|
const configField = document.getElementById(`connectorConfig${i}`);
|
||||||
|
|
||||||
if (typeSelect) {
|
if (typeField && configField) {
|
||||||
const connectorType = typeSelect.value;
|
try {
|
||||||
const configContainer = document.getElementById(`connectorConfigContainer${i}`);
|
// Validate JSON but send as string
|
||||||
|
const configValue = configField.value.trim() || '{}';
|
||||||
// Only process if we have a metaform
|
// Parse to validate but don't use the parsed object
|
||||||
if (configContainer && configContainer.querySelector('.metaform')) {
|
JSON.parse(configValue);
|
||||||
try {
|
|
||||||
// Get all form fields
|
|
||||||
const fields = configContainer.querySelectorAll('.connector-field');
|
|
||||||
let configObj = {};
|
|
||||||
|
|
||||||
// Process each field based on its type
|
|
||||||
fields.forEach(field => {
|
|
||||||
const fieldName = field.dataset.fieldName;
|
|
||||||
const fieldType = field.dataset.fieldType;
|
|
||||||
|
|
||||||
// Convert value based on field type
|
|
||||||
let value = field.value;
|
|
||||||
if (fieldType === 'number' && value !== '') {
|
|
||||||
value = parseFloat(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
configObj[fieldName] = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add the connector to the list
|
|
||||||
connectors.push({
|
|
||||||
type: connectorType,
|
|
||||||
config: JSON.stringify(configObj)
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`Error processing connector ${i} form:`, err);
|
|
||||||
showToast(`Error in connector ${i+1} configuration`, 'error');
|
|
||||||
|
|
||||||
// If button is provided, restore its state
|
|
||||||
if (button) {
|
|
||||||
const originalButtonText = button.getAttribute('data-original-text');
|
|
||||||
button.innerHTML = originalButtonText;
|
|
||||||
button.disabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null; // Indicate validation error
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If no form is loaded, create an empty config
|
|
||||||
connectors.push({
|
connectors.push({
|
||||||
type: connectorType,
|
type: typeField.value,
|
||||||
config: '{}'
|
config: configValue // Send the raw string, not parsed JSON
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error parsing connector ${i} config:`, err);
|
||||||
|
showToast(`Error in connector ${i+1} configuration: Invalid JSON`, 'error');
|
||||||
|
|
||||||
|
// If button is provided, restore its state
|
||||||
|
if (button) {
|
||||||
|
const originalButtonText = button.getAttribute('data-original-text');
|
||||||
|
button.innerHTML = originalButtonText;
|
||||||
|
button.disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // Indicate validation error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,16 +199,14 @@ const AgentFormUtils = {
|
|||||||
const parsed = JSON.parse(configValue);
|
const parsed = JSON.parse(configValue);
|
||||||
configElement.value = JSON.stringify(parsed, null, 2);
|
configElement.value = JSON.stringify(parsed, null, 2);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If parsing fails, use the raw string
|
console.warn("Failed to parse config JSON string:", e);
|
||||||
configElement.value = configValue;
|
configElement.value = configValue; // Keep as is if parsing fails
|
||||||
}
|
}
|
||||||
}
|
} else if (configValue !== undefined && configValue !== null) {
|
||||||
// If it's already an object, stringify it
|
// Direct object, just stringify with formatting
|
||||||
else if (typeof configValue === 'object' && configValue !== null) {
|
|
||||||
configElement.value = JSON.stringify(configValue, null, 2);
|
configElement.value = JSON.stringify(configValue, null, 2);
|
||||||
}
|
} else {
|
||||||
// Default to empty object
|
// Default to empty object
|
||||||
else {
|
|
||||||
configElement.value = '{}';
|
configElement.value = '{}';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -265,90 +214,21 @@ const AgentFormUtils = {
|
|||||||
// Helper function to set select value (with fallback if option doesn't exist)
|
// Helper function to set select value (with fallback if option doesn't exist)
|
||||||
setSelectValue: function(selectElement, value) {
|
setSelectValue: function(selectElement, value) {
|
||||||
// Check if the option exists
|
// Check if the option exists
|
||||||
let optionExists = false;
|
const optionExists = Array.from(selectElement.options).some(option => option.value === value);
|
||||||
for (let i = 0; i < selectElement.options.length; i++) {
|
|
||||||
if (selectElement.options[i].value === value) {
|
|
||||||
optionExists = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the value if the option exists
|
|
||||||
if (optionExists) {
|
if (optionExists) {
|
||||||
selectElement.value = value;
|
selectElement.value = value;
|
||||||
} else if (selectElement.options.length > 0) {
|
} else if (value) {
|
||||||
// Otherwise select the first option
|
// If value is provided but option doesn't exist, create a new option
|
||||||
selectElement.selectedIndex = 0;
|
const newOption = document.createElement('option');
|
||||||
|
newOption.value = value;
|
||||||
|
newOption.text = value + ' (custom)';
|
||||||
|
selectElement.add(newOption);
|
||||||
|
selectElement.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to load connector form based on type
|
|
||||||
function loadConnectorForm(index, connectorType, configData) {
|
|
||||||
if (!connectorType) return;
|
|
||||||
|
|
||||||
const configContainer = document.getElementById(`connectorConfigContainer${index}`);
|
|
||||||
if (!configContainer) return;
|
|
||||||
|
|
||||||
// Show loading indicator
|
|
||||||
configContainer.innerHTML = '<div class="loading-spinner">Loading form...</div>';
|
|
||||||
|
|
||||||
// Fetch the form for the selected connector type
|
|
||||||
fetch(`/settings/connector/form/${connectorType}`)
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Failed to load connector form');
|
|
||||||
}
|
|
||||||
return response.text();
|
|
||||||
})
|
|
||||||
.then(html => {
|
|
||||||
// Replace the container content with the form
|
|
||||||
configContainer.innerHTML = html;
|
|
||||||
|
|
||||||
// Store the connector type as a data attribute on the form
|
|
||||||
const metaform = configContainer.querySelector('.metaform');
|
|
||||||
if (metaform) {
|
|
||||||
metaform.setAttribute('data-connector-type', connectorType);
|
|
||||||
|
|
||||||
// Add a hidden input to store the connector type
|
|
||||||
const hiddenInput = document.createElement('input');
|
|
||||||
hiddenInput.type = 'hidden';
|
|
||||||
hiddenInput.name = 'connector-type';
|
|
||||||
hiddenInput.value = connectorType;
|
|
||||||
metaform.appendChild(hiddenInput);
|
|
||||||
|
|
||||||
// If we have config data, populate the form fields
|
|
||||||
if (configData) {
|
|
||||||
try {
|
|
||||||
// Parse the config JSON
|
|
||||||
const parsedConfig = JSON.parse(configData);
|
|
||||||
|
|
||||||
// Find all form fields
|
|
||||||
const fields = metaform.querySelectorAll('.connector-field');
|
|
||||||
|
|
||||||
// Populate each field with the corresponding value from the config
|
|
||||||
fields.forEach(field => {
|
|
||||||
const fieldName = field.dataset.fieldName;
|
|
||||||
if (parsedConfig[fieldName] !== undefined) {
|
|
||||||
field.value = parsedConfig[fieldName];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`Failed to populate connector form for ${connectorType}:`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error loading connector form:', error);
|
|
||||||
configContainer.innerHTML = `
|
|
||||||
<div class="error-message">
|
|
||||||
<p>Failed to load connector form: ${error.message}</p>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTML Templates for dynamic elements
|
// HTML Templates for dynamic elements
|
||||||
const AgentFormTemplates = {
|
const AgentFormTemplates = {
|
||||||
// Connector template
|
// Connector template
|
||||||
@@ -362,10 +242,9 @@ const AgentFormTemplates = {
|
|||||||
${data.options}
|
${data.options}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="connectorConfigContainer${index}" class="mb-4">
|
<div class="mb-4">
|
||||||
<div class="text-center py-4">
|
<label for="connectorConfig${index}">Connector Config (JSON)</label>
|
||||||
<p>Select a connector type to load its configuration form.</p>
|
<textarea id="connectorConfig${index}" name="connectors[${index}].config" placeholder='{"token":"sk-mg3.."}'>{}</textarea>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -377,12 +256,12 @@ const AgentFormTemplates = {
|
|||||||
<div class="mcp_server mb-4 section-box" style="margin-top: 15px; padding: 15px;">
|
<div class="mcp_server mb-4 section-box" style="margin-top: 15px; padding: 15px;">
|
||||||
<h2>MCP Server ${index + 1}</h2>
|
<h2>MCP Server ${index + 1}</h2>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="mcpURL${index}">Server URL</label>
|
<label for="mcpURL${index}">MCP Server URL</label>
|
||||||
<input type="text" id="mcpURL${index}" name="mcp_servers[${index}].url" placeholder="https://example.com">
|
<input type="text" id="mcpURL${index}" name="mcp_servers[${index}].url" placeholder='https://...'>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="mcpToken${index}">API Token (Optional)</label>
|
<label for="mcpToken${index}">Bearer Token</label>
|
||||||
<input type="text" id="mcpToken${index}" name="mcp_servers[${index}].token" placeholder="API token">
|
<input type="text" id="mcpToken${index}" name="mcp_servers[${index}].token" placeholder='Bearer token'>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -394,14 +273,14 @@ const AgentFormTemplates = {
|
|||||||
<div class="action mb-4 section-box" style="margin-top: 15px; padding: 15px;">
|
<div class="action mb-4 section-box" style="margin-top: 15px; padding: 15px;">
|
||||||
<h2>Action ${index + 1}</h2>
|
<h2>Action ${index + 1}</h2>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="actionsName${index}">Action Type</label>
|
<label for="actionsName${index}">Action</label>
|
||||||
<select name="actions[${index}].name" id="actionsName${index}">
|
<select name="actions[${index}].name" id="actionsName${index}">
|
||||||
${data.options}
|
${data.options}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="actionsConfig${index}">Action Config (JSON)</label>
|
<label for="actionsConfig${index}">Action Config (JSON)</label>
|
||||||
<textarea id="actionsConfig${index}" name="actions[${index}].config" placeholder='{"param":"value"}'>{}</textarea>
|
<textarea id="actionsConfig${index}" name="actions[${index}].config" placeholder='{"results":"5"}'>{}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -413,14 +292,14 @@ const AgentFormTemplates = {
|
|||||||
<div class="promptBlock mb-4 section-box" style="margin-top: 15px; padding: 15px;">
|
<div class="promptBlock mb-4 section-box" style="margin-top: 15px; padding: 15px;">
|
||||||
<h2>Prompt Block ${index + 1}</h2>
|
<h2>Prompt Block ${index + 1}</h2>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="promptName${index}">Prompt Block Type</label>
|
<label for="promptName${index}">Block Prompt</label>
|
||||||
<select name="promptblocks[${index}].name" id="promptName${index}">
|
<select name="promptblocks[${index}].name" id="promptName${index}">
|
||||||
${data.options}
|
${data.options}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="promptConfig${index}">Prompt Block Config (JSON)</label>
|
<label for="promptConfig${index}">Prompt Config (JSON)</label>
|
||||||
<textarea id="promptConfig${index}" name="promptblocks[${index}].config" placeholder='{"param":"value"}'>{}</textarea>
|
<textarea id="promptConfig${index}" name="promptblocks[${index}].config" placeholder='{"results":"5"}'>{}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -465,39 +344,25 @@ function initAgentFormCommon(options = {}) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add additional CSS for loading spinner and error messages
|
// Add additional CSS for checkbox labels
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
.loading-spinner {
|
.checkbox-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100px;
|
cursor: pointer;
|
||||||
color: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-spinner::after {
|
|
||||||
content: '';
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border: 2px solid #f0f0f0;
|
|
||||||
border-top-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spinner 1s linear infinite;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spinner {
|
|
||||||
to { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-message {
|
|
||||||
color: #ff5555;
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid #ff5555;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checkbox-label .checkbox-custom {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% { transform: scale(1); }
|
||||||
|
50% { transform: scale(1.05); }
|
||||||
|
100% { transform: scale(1); }
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,6 @@ func (app *App) registerRoutes(pool *state.AgentPool, webapp *fiber.App) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
webapp.Get("/settings/connector/form/:type", app.GetConnectorForm(pool))
|
|
||||||
webapp.Get("/settings/:name", func(c *fiber.Ctx) error {
|
webapp.Get("/settings/:name", func(c *fiber.Ctx) error {
|
||||||
status := false
|
status := false
|
||||||
for _, a := range pool.List() {
|
for _, a := range pool.List() {
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Metaform Partial Template
|
|
||||||
This template renders a form based on a Form struct from the metaform package.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
{{template "partials/metaform.html" .}}
|
|
||||||
|
|
||||||
Where . contains Form and Type fields
|
|
||||||
*/}}
|
|
||||||
|
|
||||||
<div class="metaform" data-connector-type="{{.Type}}">
|
|
||||||
{{range .Form.Fields}}
|
|
||||||
<div class="mb-4">
|
|
||||||
<label for="connector_{{.Name}}">{{.Label}}{{if .Required}} <span class="required">*</span>{{end}}</label>
|
|
||||||
|
|
||||||
{{if eq .Kind "string"}}
|
|
||||||
<input type="text"
|
|
||||||
name="connector_field_{{.Name}}"
|
|
||||||
id="connector_{{.Name}}"
|
|
||||||
class="connector-field"
|
|
||||||
data-field-name="{{.Name}}"
|
|
||||||
data-field-type="string"
|
|
||||||
{{if .Placeholder}}placeholder="{{.Placeholder}}"{{end}}
|
|
||||||
{{if .Required}}required{{end}}>
|
|
||||||
|
|
||||||
{{else if eq .Kind "number"}}
|
|
||||||
<input type="number"
|
|
||||||
name="connector_field_{{.Name}}"
|
|
||||||
id="connector_{{.Name}}"
|
|
||||||
class="connector-field"
|
|
||||||
data-field-name="{{.Name}}"
|
|
||||||
data-field-type="number"
|
|
||||||
{{if .Placeholder}}placeholder="{{.Placeholder}}"{{end}}
|
|
||||||
{{if .Required}}required{{end}}>
|
|
||||||
|
|
||||||
{{else if eq .Kind "options"}}
|
|
||||||
<select name="connector_field_{{.Name}}"
|
|
||||||
id="connector_{{.Name}}"
|
|
||||||
class="connector-field"
|
|
||||||
data-field-name="{{.Name}}"
|
|
||||||
data-field-type="options"
|
|
||||||
{{if .Required}}required{{end}}>
|
|
||||||
<option value="">Select an option</option>
|
|
||||||
{{range .Options}}
|
|
||||||
<option value="{{.Value}}">{{.Label}}</option>
|
|
||||||
{{end}}
|
|
||||||
</select>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.metaform .required {
|
|
||||||
color: #ff5555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metaform input[type="text"],
|
|
||||||
.metaform input[type="number"],
|
|
||||||
.metaform select {
|
|
||||||
width: 100%;
|
|
||||||
padding: 10px;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
border: 1px solid #333;
|
|
||||||
color: #f0f0f0;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-top: 5px;
|
|
||||||
transition: border-color 0.3s, box-shadow 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metaform input[type="text"]:focus,
|
|
||||||
.metaform input[type="number"]:focus,
|
|
||||||
.metaform select:focus {
|
|
||||||
border-color: #00b3ff;
|
|
||||||
box-shadow: 0 0 5px rgba(0, 179, 255, 0.5);
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metaform select {
|
|
||||||
appearance: none;
|
|
||||||
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f0f0f0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: right 10px center;
|
|
||||||
background-size: 16px;
|
|
||||||
padding-right: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metaform label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
color: #f0f0f0;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -190,16 +190,10 @@
|
|||||||
updateButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Updating...';
|
updateButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Updating...';
|
||||||
updateButton.disabled = true;
|
updateButton.disabled = true;
|
||||||
|
|
||||||
// Get the agent name from the hidden input field
|
|
||||||
const agentName = document.getElementById('name').value;
|
|
||||||
|
|
||||||
// Build a structured data object
|
// Build a structured data object
|
||||||
const formData = new FormData(form);
|
const formData = new FormData(form);
|
||||||
const jsonData = AgentFormUtils.processFormData(formData);
|
const jsonData = AgentFormUtils.processFormData(formData);
|
||||||
|
|
||||||
// Ensure the name is set correctly
|
|
||||||
jsonData.name = agentName;
|
|
||||||
|
|
||||||
// Process special fields
|
// Process special fields
|
||||||
jsonData.connectors = AgentFormUtils.processConnectors(updateButton);
|
jsonData.connectors = AgentFormUtils.processConnectors(updateButton);
|
||||||
if (jsonData.connectors === null) return; // Validation failed
|
if (jsonData.connectors === null) return; // Validation failed
|
||||||
@@ -215,7 +209,7 @@
|
|||||||
console.log('Sending data:', jsonData);
|
console.log('Sending data:', jsonData);
|
||||||
|
|
||||||
// Send the structured data as JSON
|
// Send the structured data as JSON
|
||||||
fetch(`/api/agent/${agentName}/config`, {
|
fetch(`/api/agent/${jsonData.name}/config`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@@ -366,13 +360,16 @@
|
|||||||
|
|
||||||
// Find the added connector elements
|
// Find the added connector elements
|
||||||
const connectorType = document.getElementById(`connectorType${index}`);
|
const connectorType = document.getElementById(`connectorType${index}`);
|
||||||
|
const connectorConfig = document.getElementById(`connectorConfig${index}`);
|
||||||
|
|
||||||
// Set connector type value
|
// Set values
|
||||||
if (connectorType) {
|
if (connectorType) {
|
||||||
AgentFormUtils.setSelectValue(connectorType, connector.type);
|
AgentFormUtils.setSelectValue(connectorType, connector.type);
|
||||||
|
}
|
||||||
// Load the connector form with the existing config data
|
|
||||||
loadConnectorForm(index, connector.type, connector.config);
|
if (connectorConfig) {
|
||||||
|
// Format the config value
|
||||||
|
AgentFormUtils.formatConfigValue(connectorConfig, connector.config);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user