diff --git a/core/state/config.go b/core/state/config.go
index 2a9084d..2b2afb1 100644
--- a/core/state/config.go
+++ b/core/state/config.go
@@ -5,6 +5,7 @@ import (
"github.com/mudler/LocalAgent/core/agent"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
)
type ConnectorConfig struct {
@@ -35,7 +36,7 @@ type AgentConfig struct {
MCPServers []agent.MCPServer `json:"mcp_servers" form:"mcp_servers"`
Description string `json:"description" form:"description"`
- // This is what needs to be part of ActionsConfig
+
Model string `json:"model" form:"model"`
MultimodalModel string `json:"multimodal_model" form:"multimodal_model"`
APIURL string `json:"api_url" form:"api_url"`
@@ -61,6 +62,211 @@ type AgentConfig struct {
SummaryLongTermMemory bool `json:"summary_long_term_memory" form:"summary_long_term_memory"`
}
+type AgentConfigMeta struct {
+ Fields []config.Field
+ Connectors []config.FieldGroup
+ Actions []config.FieldGroup
+ PromptBlocks []config.Field
+ MCPServers []config.Field
+}
+
+func NewAgentConfigMeta(actionsConfig []config.FieldGroup, connectorsConfig []config.FieldGroup) AgentConfigMeta {
+ return AgentConfigMeta{
+ Fields: []config.Field{
+ {
+ Name: "name",
+ Label: "Name",
+ Type: "text",
+ DefaultValue: "",
+ Required: true,
+ Tags: config.Tags{Section: "BasicInfo"},
+ },
+ {
+ Name: "description",
+ Label: "Description",
+ Type: "textarea",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "BasicInfo"},
+ },
+ {
+ Name: "identity_guidance",
+ Label: "Identity Guidance",
+ Type: "textarea",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "BasicInfo"},
+ },
+ {
+ Name: "random_identity",
+ Label: "Random Identity",
+ Type: "checkbox",
+ DefaultValue: false,
+ Tags: config.Tags{Section: "BasicInfo"},
+ },
+ {
+ Name: "hud",
+ Label: "HUD",
+ Type: "checkbox",
+ DefaultValue: false,
+ Tags: config.Tags{Section: "BasicInfo"},
+ },
+ {
+ Name: "model",
+ Label: "Model",
+ Type: "text",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "ModelSettings"},
+ },
+ {
+ Name: "multimodal_model",
+ Label: "Multimodal Model",
+ Type: "text",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "ModelSettings"},
+ },
+ {
+ Name: "api_url",
+ Label: "API URL",
+ Type: "text",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "ModelSettings"},
+ },
+ {
+ Name: "api_key",
+ Label: "API Key",
+ Type: "password",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "ModelSettings"},
+ },
+ {
+ Name: "local_rag_url",
+ Label: "Local RAG URL",
+ Type: "text",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "ModelSettings"},
+ },
+ {
+ Name: "local_rag_api_key",
+ Label: "Local RAG API Key",
+ Type: "password",
+ DefaultValue: "",
+ Tags: config.Tags{Section: "ModelSettings"},
+ },
+ {
+ Name: "enable_kb",
+ Label: "Enable Knowledge Base",
+ Type: "checkbox",
+ DefaultValue: false,
+ Tags: config.Tags{Section: "MemorySettings"},
+ },
+ {
+ Name: "kb_results",
+ Label: "Knowledge Base Results",
+ Type: "number",
+ DefaultValue: 5,
+ Min: 1,
+ Step: 1,
+ Tags: config.Tags{Section: "MemorySettings"},
+ },
+ {
+ Name: "long_term_memory",
+ Label: "Long Term Memory",
+ Type: "checkbox",
+ DefaultValue: false,
+ Tags: config.Tags{Section: "MemorySettings"},
+ },
+ {
+ Name: "summary_long_term_memory",
+ Label: "Summary Long Term Memory",
+ Type: "checkbox",
+ DefaultValue: false,
+ Tags: config.Tags{Section: "MemorySettings"},
+ },
+ {
+ Name: "system_prompt",
+ Label: "System Prompt",
+ Type: "textarea",
+ DefaultValue: "",
+ HelpText: "Instructions that define the agent's behavior and capabilities",
+ Tags: config.Tags{Section: "PromptsGoals"},
+ },
+ {
+ Name: "permanent_goal",
+ Label: "Permanent Goal",
+ Type: "textarea",
+ DefaultValue: "",
+ HelpText: "Long-term objective for the agent to pursue",
+ Tags: config.Tags{Section: "PromptsGoals"},
+ },
+ {
+ Name: "standalone_job",
+ Label: "Standalone Job",
+ Type: "checkbox",
+ DefaultValue: false,
+ HelpText: "Run as a standalone job without user interaction",
+ Tags: config.Tags{Section: "AdvancedSettings"},
+ },
+ {
+ Name: "initiate_conversations",
+ Label: "Initiate Conversations",
+ Type: "checkbox",
+ DefaultValue: false,
+ HelpText: "Allow agent to start conversations on its own",
+ Tags: config.Tags{Section: "AdvancedSettings"},
+ },
+ {
+ Name: "enable_planning",
+ Label: "Enable Planning",
+ Type: "checkbox",
+ DefaultValue: false,
+ HelpText: "Enable agent to create and execute plans",
+ Tags: config.Tags{Section: "AdvancedSettings"},
+ },
+ {
+ Name: "can_stop_itself",
+ Label: "Can Stop Itself",
+ Type: "checkbox",
+ DefaultValue: false,
+ HelpText: "Allow agent to terminate its own execution",
+ Tags: config.Tags{Section: "AdvancedSettings"},
+ },
+ {
+ Name: "periodic_runs",
+ Label: "Periodic Runs",
+ Type: "text",
+ DefaultValue: "",
+ Placeholder: "10m",
+ HelpText: "Duration for scheduling periodic agent runs",
+ Tags: config.Tags{Section: "AdvancedSettings"},
+ },
+ {
+ Name: "enable_reasoning",
+ Label: "Enable Reasoning",
+ Type: "checkbox",
+ DefaultValue: false,
+ HelpText: "Enable agent to explain its reasoning process",
+ Tags: config.Tags{Section: "AdvancedSettings"},
+ },
+ },
+ MCPServers: []config.Field{
+ {
+ Name: "url",
+ Label: "URL",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "token",
+ Label: "API Key",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ },
+ PromptBlocks: []config.Field{},
+ Connectors: connectorsConfig,
+ Actions: actionsConfig,
+ }
+}
+
type Connector interface {
AgentResultCallback() func(state types.ActionState)
AgentReasoningCallback() func(state types.ActionCurrentState) bool
diff --git a/pkg/config/meta.go b/pkg/config/meta.go
new file mode 100644
index 0000000..a427222
--- /dev/null
+++ b/pkg/config/meta.go
@@ -0,0 +1,42 @@
+package config
+
+type FieldType string
+
+const (
+ FieldTypeNumber FieldType = "number"
+ FieldTypeText FieldType = "text"
+ FieldTypeTextarea FieldType = "textarea"
+ FieldTypeCheckbox FieldType = "checkbox"
+ FieldTypeSelect FieldType = "select"
+)
+
+type Tags struct {
+ Section string `json:"section,omitempty"`
+}
+
+type FieldOption struct {
+ Value string `json:"value"`
+ Label string `json:"label"`
+}
+
+type Field struct {
+ Name string `json:"name"`
+ Type FieldType `json:"type"`
+ Label string `json:"label"`
+ DefaultValue any `json:"defaultValue"`
+ Placeholder string `json:"placeholder,omitempty"`
+ HelpText string `json:"helpText,omitempty"`
+ Required bool `json:"required,omitempty"`
+ Disabled bool `json:"disabled,omitempty"`
+ Options []FieldOption `json:"options,omitempty"`
+ Min float32 `json:"min,omitempty"`
+ Max float32 `json:"max,omitempty"`
+ Step float32 `json:"step,omitempty"`
+ Tags Tags `json:"tags,omitempty"`
+}
+
+type FieldGroup struct {
+ Name string `json:"name"`
+ Label string `json:"label"`
+ Fields []Field `json:"fields"`
+}
diff --git a/services/actions.go b/services/actions.go
index 173cff5..29a9690 100644
--- a/services/actions.go
+++ b/services/actions.go
@@ -8,6 +8,7 @@ import (
"github.com/mudler/LocalAgent/core/action"
"github.com/mudler/LocalAgent/core/state"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/services/actions"
@@ -30,7 +31,7 @@ const (
ActionWikipedia = "wikipedia"
ActionBrowse = "browse"
ActionTwitterPost = "twitter-post"
- ActionSendMail = "send_mail"
+ ActionSendMail = "send-mail"
ActionGenerateImage = "generate_image"
ActionCounter = "counter"
ActionCallAgents = "call_agents"
@@ -138,3 +139,108 @@ func Action(name string, config map[string]string, pool *state.AgentPool) (types
return a, nil
}
+
+func ActionsConfigMeta() []config.FieldGroup {
+ return []config.FieldGroup{
+ {
+ Name: "search",
+ Label: "Search",
+ Fields: actions.SearchConfigMeta(),
+ },
+ {
+ Name: "generate_image",
+ Label: "Generate Image",
+ Fields: actions.GenImageConfigMeta(),
+ },
+ {
+ Name: "github-issue-labeler",
+ Label: "GitHub Issue Labeler",
+ Fields: actions.GithubIssueLabelerConfigMeta(),
+ },
+ {
+ Name: "github-issue-opener",
+ Label: "GitHub Issue Opener",
+ Fields: actions.GithubIssueOpenerConfigMeta(),
+ },
+ {
+ Name: "github-issue-closer",
+ Label: "GitHub Issue Closer",
+ Fields: actions.GithubIssueCloserConfigMeta(),
+ },
+ {
+ Name: "github-issue-commenter",
+ Label: "GitHub Issue Commenter",
+ Fields: actions.GithubIssueCommenterConfigMeta(),
+ },
+ {
+ Name: "github-issue-reader",
+ Label: "GitHub Issue Reader",
+ Fields: actions.GithubIssueReaderConfigMeta(),
+ },
+ {
+ Name: "github-issue-searcher",
+ Label: "GitHub Issue Search",
+ Fields: actions.GithubIssueSearchConfigMeta(),
+ },
+ {
+ Name: "github-repository-get-content",
+ Label: "GitHub Repository Get Content",
+ Fields: actions.GithubRepositoryGetContentConfigMeta(),
+ },
+ {
+ Name: "github-repository-create-or-update-content",
+ Label: "GitHub Repository Create/Update Content",
+ Fields: actions.GithubRepositoryCreateOrUpdateContentConfigMeta(),
+ },
+ {
+ Name: "github-readme",
+ Label: "GitHub Repository README",
+ Fields: actions.GithubRepositoryREADMEConfigMeta(),
+ },
+ {
+ Name: "twitter-post",
+ Label: "Twitter Post",
+ Fields: actions.TwitterPostConfigMeta(),
+ },
+ {
+ Name: "send-mail",
+ Label: "Send Mail",
+ Fields: actions.SendMailConfigMeta(),
+ },
+ {
+ Name: "shell-command",
+ Label: "Shell Command",
+ Fields: actions.ShellConfigMeta(),
+ },
+ {
+ Name: "custom",
+ Label: "Custom",
+ Fields: []config.Field{},
+ },
+ {
+ Name: "scraper",
+ Label: "Scraper",
+ Fields: []config.Field{},
+ },
+ {
+ Name: "wikipedia",
+ Label: "Wikipedia",
+ Fields: []config.Field{},
+ },
+ {
+ Name: "browse",
+ Label: "Browse",
+ Fields: []config.Field{},
+ },
+ {
+ Name: "counter",
+ Label: "Counter",
+ Fields: []config.Field{},
+ },
+ {
+ Name: "call_agents",
+ Label: "Call Agents",
+ Fields: []config.Field{},
+ },
+ }
+}
diff --git a/services/actions/genimage.go b/services/actions/genimage.go
index bd4c609..fe296f3 100644
--- a/services/actions/genimage.go
+++ b/services/actions/genimage.go
@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -96,3 +97,32 @@ func (a *GenImageAction) Definition() types.ActionDefinition {
func (a *GenImageAction) Plannable() bool {
return true
}
+
+// GenImageConfigMeta returns the metadata for GenImage action configuration fields
+func GenImageConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "apiKey",
+ Label: "API Key",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "OpenAI API key for image generation",
+ },
+ {
+ Name: "apiURL",
+ Label: "API URL",
+ Type: config.FieldTypeText,
+ Required: true,
+ DefaultValue: "https://api.openai.com/v1",
+ HelpText: "OpenAI API URL",
+ },
+ {
+ Name: "model",
+ Label: "Model",
+ Type: config.FieldTypeText,
+ Required: true,
+ DefaultValue: "dall-e-3",
+ HelpText: "Image generation model to use (e.g., dall-e-3)",
+ },
+ }
+}
diff --git a/services/actions/githubissuecloser.go b/services/actions/githubissuecloser.go
index ba94a71..c3e1935 100644
--- a/services/actions/githubissuecloser.go
+++ b/services/actions/githubissuecloser.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -118,3 +119,36 @@ func (g *GithubIssuesCloser) Definition() types.ActionDefinition {
func (a *GithubIssuesCloser) Plannable() bool {
return true
}
+
+// GithubIssueCloserConfigMeta returns the metadata for GitHub Issue Closer action configuration fields
+func GithubIssueCloserConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubissuecomment.go b/services/actions/githubissuecomment.go
index 42497e8..7296c73 100644
--- a/services/actions/githubissuecomment.go
+++ b/services/actions/githubissuecomment.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -105,3 +106,36 @@ func (g *GithubIssuesCommenter) Definition() types.ActionDefinition {
func (a *GithubIssuesCommenter) Plannable() bool {
return true
}
+
+// GithubIssueCommenterConfigMeta returns the metadata for GitHub Issue Commenter action configuration fields
+func GithubIssueCommenterConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubissuelabeler.go b/services/actions/githubissuelabeler.go
index 055ae51..cf73914 100644
--- a/services/actions/githubissuelabeler.go
+++ b/services/actions/githubissuelabeler.go
@@ -7,6 +7,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -120,3 +121,43 @@ func (g *GithubIssuesLabeler) Definition() types.ActionDefinition {
func (a *GithubIssuesLabeler) Plannable() bool {
return true
}
+
+// GithubIssueLabelerConfigMeta returns the metadata for GitHub Issue Labeler action configuration fields
+func GithubIssueLabelerConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "availableLabels",
+ Label: "Available Labels",
+ Type: config.FieldTypeText,
+ HelpText: "Comma-separated list of available labels",
+ DefaultValue: "bug,enhancement",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubissueopener.go b/services/actions/githubissueopener.go
index bbff91d..dbbc061 100644
--- a/services/actions/githubissueopener.go
+++ b/services/actions/githubissueopener.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -111,3 +112,36 @@ func (g *GithubIssuesOpener) Definition() types.ActionDefinition {
func (a *GithubIssuesOpener) Plannable() bool {
return true
}
+
+// GithubIssueOpenerConfigMeta returns the metadata for GitHub Issue Opener action configuration fields
+func GithubIssueOpenerConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubissuereader.go b/services/actions/githubissuereader.go
index 2f6168c..df5cfac 100644
--- a/services/actions/githubissuereader.go
+++ b/services/actions/githubissuereader.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -99,3 +100,36 @@ func (g *GithubIssuesReader) Definition() types.ActionDefinition {
func (a *GithubIssuesReader) Plannable() bool {
return true
}
+
+// GithubIssueReaderConfigMeta returns the metadata for GitHub Issue Reader action configuration fields
+func GithubIssueReaderConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubissuesearch.go b/services/actions/githubissuesearch.go
index daa5358..bcf7bc4 100644
--- a/services/actions/githubissuesearch.go
+++ b/services/actions/githubissuesearch.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -108,3 +109,36 @@ func (g *GithubIssueSearch) Definition() types.ActionDefinition {
func (a *GithubIssueSearch) Plannable() bool {
return true
}
+
+// GithubIssueSearchConfigMeta returns the metadata for GitHub Issue Search action configuration fields
+func GithubIssueSearchConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubrepositorycreateupdatecontent.go b/services/actions/githubrepositorycreateupdatecontent.go
index 2a8398d..67befa3 100644
--- a/services/actions/githubrepositorycreateupdatecontent.go
+++ b/services/actions/githubrepositorycreateupdatecontent.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -144,3 +145,36 @@ func (g *GithubRepositoryCreateOrUpdateContent) Definition() types.ActionDefinit
func (a *GithubRepositoryCreateOrUpdateContent) Plannable() bool {
return true
}
+
+// GithubRepositoryCreateOrUpdateContentConfigMeta returns the metadata for GitHub Repository Create/Update Content action configuration fields
+func GithubRepositoryCreateOrUpdateContentConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubrepositorygetcontent.go b/services/actions/githubrepositorygetcontent.go
index 61c39d5..dd6e7c0 100644
--- a/services/actions/githubrepositorygetcontent.go
+++ b/services/actions/githubrepositorygetcontent.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -109,3 +110,36 @@ func (g *GithubRepositoryGetContent) Definition() types.ActionDefinition {
func (a *GithubRepositoryGetContent) Plannable() bool {
return true
}
+
+// GithubRepositoryGetContentConfigMeta returns the metadata for GitHub Repository Get Content action configuration fields
+func GithubRepositoryGetContentConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository name",
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub repository owner",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/githubrepositoryreadme.go b/services/actions/githubrepositoryreadme.go
index 03f0be8..5d0f349 100644
--- a/services/actions/githubrepositoryreadme.go
+++ b/services/actions/githubrepositoryreadme.go
@@ -6,6 +6,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -75,3 +76,22 @@ func (g *GithubRepositoryREADME) Definition() types.ActionDefinition {
func (a *GithubRepositoryREADME) Plannable() bool {
return true
}
+
+// GithubRepositoryREADMEConfigMeta returns the metadata for GitHub Repository README action configuration fields
+func GithubRepositoryREADMEConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "GitHub API token with repository access",
+ },
+ {
+ Name: "customActionName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ }
+}
diff --git a/services/actions/search.go b/services/actions/search.go
index 27130f6..ed09ac1 100644
--- a/services/actions/search.go
+++ b/services/actions/search.go
@@ -7,6 +7,7 @@ import (
"strings"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
"github.com/tmc/langchaingo/tools/duckduckgo"
"mvdan.cc/xurls/v2"
@@ -89,3 +90,19 @@ func (a *SearchAction) Definition() types.ActionDefinition {
func (a *SearchAction) Plannable() bool {
return true
}
+
+// SearchConfigMeta returns the metadata for Search action configuration fields
+func SearchConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "results",
+ Label: "Number of Results",
+ Type: config.FieldTypeNumber,
+ DefaultValue: 1,
+ Min: 1,
+ Max: 10,
+ Step: 1,
+ HelpText: "Number of search results to return",
+ },
+ }
+}
diff --git a/services/actions/sendmail.go b/services/actions/sendmail.go
index bc46a13..c6a4785 100644
--- a/services/actions/sendmail.go
+++ b/services/actions/sendmail.go
@@ -6,6 +6,7 @@ import (
"net/smtp"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -80,3 +81,45 @@ func (a *SendMailAction) Definition() types.ActionDefinition {
func (a *SendMailAction) Plannable() bool {
return true
}
+
+// SendMailConfigMeta returns the metadata for SendMail action configuration fields
+func SendMailConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "smtpHost",
+ Label: "SMTP Host",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "SMTP server host (e.g., smtp.gmail.com)",
+ },
+ {
+ Name: "smtpPort",
+ Label: "SMTP Port",
+ Type: config.FieldTypeText,
+ Required: true,
+ DefaultValue: "587",
+ HelpText: "SMTP server port (e.g., 587)",
+ },
+ {
+ Name: "username",
+ Label: "SMTP Username",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "SMTP username/email address",
+ },
+ {
+ Name: "password",
+ Label: "SMTP Password",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "SMTP password or app password",
+ },
+ {
+ Name: "email",
+ Label: "From Email",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "Sender email address",
+ },
+ }
+}
diff --git a/services/actions/shell.go b/services/actions/shell.go
index 9f95c27..a21636a 100644
--- a/services/actions/shell.go
+++ b/services/actions/shell.go
@@ -6,6 +6,7 @@ import (
"log"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/sashabaranov/go-openai/jsonschema"
"golang.org/x/crypto/ssh"
)
@@ -96,6 +97,43 @@ func (a *ShellAction) Definition() types.ActionDefinition {
}
}
+// ShellConfigMeta returns the metadata for Shell action configuration fields
+func ShellConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "privateKey",
+ Label: "Private Key",
+ Type: config.FieldTypeTextarea,
+ Required: true,
+ HelpText: "SSH private key for connecting to remote servers",
+ },
+ {
+ Name: "user",
+ Label: "Default User",
+ Type: config.FieldTypeText,
+ HelpText: "Default SSH user for connecting to remote servers",
+ },
+ {
+ Name: "host",
+ Label: "Default Host",
+ Type: config.FieldTypeText,
+ HelpText: "Default host for SSH connections (e.g., hostname:port)",
+ },
+ {
+ Name: "customName",
+ Label: "Custom Action Name",
+ Type: config.FieldTypeText,
+ HelpText: "Custom name for this action",
+ },
+ {
+ Name: "customDescription",
+ Label: "Custom Description",
+ Type: config.FieldTypeTextarea,
+ HelpText: "Custom description for this action",
+ },
+ }
+}
+
func sshCommand(privateKey, command, user, host string) (string, error) {
// Create signer from private key string
key, err := ssh.ParsePrivateKey([]byte(privateKey))
diff --git a/services/actions/twitter_post.go b/services/actions/twitter_post.go
index d0bd417..1921ad0 100644
--- a/services/actions/twitter_post.go
+++ b/services/actions/twitter_post.go
@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/services/connectors/twitter"
"github.com/sashabaranov/go-openai/jsonschema"
)
@@ -62,3 +63,22 @@ func (a *PostTweetAction) Definition() types.ActionDefinition {
func (a *PostTweetAction) Plannable() bool {
return true
}
+
+// TwitterPostConfigMeta returns the metadata for Twitter Post action configuration fields
+func TwitterPostConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "Twitter API Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ HelpText: "Twitter API token for posting tweets",
+ },
+ {
+ Name: "noCharacterLimit",
+ Label: "No Character Limit",
+ Type: config.FieldTypeCheckbox,
+ HelpText: "If checked, tweets longer than the character limit will be split into multiple tweets",
+ },
+ }
+}
diff --git a/services/connectors.go b/services/connectors.go
index 50317b0..7ad9ed5 100644
--- a/services/connectors.go
+++ b/services/connectors.go
@@ -3,6 +3,7 @@ package services
import (
"encoding/json"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/services/connectors"
@@ -69,3 +70,43 @@ func Connectors(a *state.AgentConfig) []state.Connector {
}
return conns
}
+
+func ConnectorsConfigMeta() []config.FieldGroup {
+ return []config.FieldGroup{
+ {
+ Name: "discord",
+ Label: "Discord",
+ Fields: connectors.DiscordConfigMeta(),
+ },
+ {
+ Name: "slack",
+ Label: "Slack",
+ Fields: connectors.SlackConfigMeta(),
+ },
+ {
+ Name: "telegram",
+ Label: "Telegram",
+ Fields: connectors.TelegramConfigMeta(),
+ },
+ {
+ Name: "github-issues",
+ Label: "GitHub Issues",
+ Fields: connectors.GithubIssueConfigMeta(),
+ },
+ {
+ Name: "github-prs",
+ Label: "GitHub PRs",
+ Fields: connectors.GithubPRConfigMeta(),
+ },
+ {
+ Name: "irc",
+ Label: "IRC",
+ Fields: connectors.IRCConfigMeta(),
+ },
+ {
+ Name: "twitter",
+ Label: "Twitter",
+ Fields: connectors.TwitterConfigMeta(),
+ },
+ }
+}
diff --git a/services/connectors/discord.go b/services/connectors/discord.go
index 15b5e08..1d95ada 100644
--- a/services/connectors/discord.go
+++ b/services/connectors/discord.go
@@ -6,6 +6,7 @@ import (
"github.com/bwmarrin/discordgo"
"github.com/mudler/LocalAgent/core/agent"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/sashabaranov/go-openai"
)
@@ -34,6 +35,28 @@ func NewDiscord(config map[string]string) *Discord {
}
}
+func DiscordConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "Discord Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "defaultChannel",
+ Label: "Default Channel",
+ Type: config.FieldTypeText,
+ },
+ {
+ Name: "lastMessageDuration",
+ Label: "Last Message Duration",
+ Type: config.FieldTypeText,
+ DefaultValue: "5m",
+ },
+ }
+}
+
func (d *Discord) AgentResultCallback() func(state types.ActionState) {
return func(state types.ActionState) {
// Send the result to the bot
diff --git a/services/connectors/githubissue.go b/services/connectors/githubissue.go
index 67c1b75..0b87854 100644
--- a/services/connectors/githubissue.go
+++ b/services/connectors/githubissue.go
@@ -8,6 +8,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/agent"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/sashabaranov/go-openai"
@@ -195,3 +196,39 @@ func (g *GithubIssues) issuesService() {
}
}
}
+
+// GithubIssueConfigMeta returns the metadata for GitHub Issues connector configuration fields
+func GithubIssueConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "replyIfNoReplies",
+ Label: "Reply If No Replies",
+ Type: config.FieldTypeCheckbox,
+ },
+ {
+ Name: "pollInterval",
+ Label: "Poll Interval",
+ Type: config.FieldTypeText,
+ DefaultValue: "10m",
+ HelpText: "How often to check for new issues (e.g., 10m, 1h)",
+ },
+ }
+}
diff --git a/services/connectors/githubpr.go b/services/connectors/githubpr.go
index 3041f73..70ef408 100644
--- a/services/connectors/githubpr.go
+++ b/services/connectors/githubpr.go
@@ -8,6 +8,7 @@ import (
"github.com/google/go-github/v69/github"
"github.com/mudler/LocalAgent/core/agent"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/sashabaranov/go-openai"
@@ -195,3 +196,39 @@ func (g *GithubPRs) prService() {
}
}
}
+
+// GithubPRConfigMeta returns the metadata for GitHub PR connector configuration fields
+func GithubPRConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "GitHub Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "repository",
+ Label: "Repository",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "owner",
+ Label: "Owner",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "replyIfNoReplies",
+ Label: "Reply If No Replies",
+ Type: config.FieldTypeCheckbox,
+ },
+ {
+ Name: "pollInterval",
+ Label: "Poll Interval",
+ Type: config.FieldTypeText,
+ DefaultValue: "10m",
+ HelpText: "How often to check for new PRs (e.g., 10m, 1h)",
+ },
+ }
+}
diff --git a/services/connectors/irc.go b/services/connectors/irc.go
index 58bc54e..6221d39 100644
--- a/services/connectors/irc.go
+++ b/services/connectors/irc.go
@@ -7,6 +7,7 @@ import (
"github.com/mudler/LocalAgent/core/agent"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/services/actions"
"github.com/sashabaranov/go-openai"
@@ -207,3 +208,44 @@ func (i *IRC) Start(a *agent.Agent) {
// Start the IRC client in a goroutine
go i.conn.Loop()
}
+
+// IRCConfigMeta returns the metadata for IRC connector configuration fields
+func IRCConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "server",
+ Label: "IRC Server",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "port",
+ Label: "Port",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "nickname",
+ Label: "Nickname",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "channel",
+ Label: "Channel",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "alwaysReply",
+ Label: "Always Reply",
+ Type: config.FieldTypeCheckbox,
+ },
+ {
+ Name: "lastMessageDuration",
+ Label: "Last Message Duration",
+ Type: config.FieldTypeText,
+ DefaultValue: "5m",
+ },
+ }
+}
diff --git a/services/connectors/slack.go b/services/connectors/slack.go
index 557d0ee..36814ed 100644
--- a/services/connectors/slack.go
+++ b/services/connectors/slack.go
@@ -10,6 +10,7 @@ import (
"sync"
"time"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/pkg/xstrings"
"github.com/mudler/LocalAgent/services/actions"
@@ -784,3 +785,37 @@ func (t *Slack) Start(a *agent.Agent) {
client.RunContext(a.Context())
}
+
+// SlackConfigMeta returns the metadata for Slack connector configuration fields
+func SlackConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "appToken",
+ Label: "App Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "botToken",
+ Label: "Bot Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "channelID",
+ Label: "Channel ID",
+ Type: config.FieldTypeText,
+ },
+ {
+ Name: "alwaysReply",
+ Label: "Always Reply",
+ Type: config.FieldTypeCheckbox,
+ },
+ {
+ Name: "lastMessageDuration",
+ Label: "Last Message Duration",
+ Type: config.FieldTypeText,
+ DefaultValue: "5m",
+ },
+ }
+}
diff --git a/services/connectors/telegram.go b/services/connectors/telegram.go
index 65e378b..2ff9806 100644
--- a/services/connectors/telegram.go
+++ b/services/connectors/telegram.go
@@ -14,6 +14,7 @@ import (
"github.com/go-telegram/bot/models"
"github.com/mudler/LocalAgent/core/agent"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/pkg/xstrings"
"github.com/mudler/LocalAgent/services/actions"
@@ -203,3 +204,27 @@ func NewTelegramConnector(config map[string]string) (*Telegram, error) {
conversationTracker: NewConversationTracker[int64](duration),
}, nil
}
+
+// TelegramConfigMeta returns the metadata for Telegram connector configuration fields
+func TelegramConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "Telegram Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "admins",
+ Label: "Admins",
+ Type: config.FieldTypeText,
+ HelpText: "Comma-separated list of Telegram usernames that are allowed to interact with the bot",
+ },
+ {
+ Name: "lastMessageDuration",
+ Label: "Last Message Duration",
+ Type: config.FieldTypeText,
+ DefaultValue: "5m",
+ },
+ }
+}
diff --git a/services/connectors/twitter.go b/services/connectors/twitter.go
index adab389..6f3c595 100644
--- a/services/connectors/twitter.go
+++ b/services/connectors/twitter.go
@@ -8,6 +8,7 @@ import (
"github.com/mudler/LocalAgent/core/agent"
"github.com/mudler/LocalAgent/core/types"
+ "github.com/mudler/LocalAgent/pkg/config"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/services/connectors/twitter"
"github.com/sashabaranov/go-openai"
@@ -134,3 +135,26 @@ func (t *Twitter) run(a *agent.Agent) error {
return nil
}
+
+// TwitterConfigMeta returns the metadata for Twitter connector configuration fields
+func TwitterConfigMeta() []config.Field {
+ return []config.Field{
+ {
+ Name: "token",
+ Label: "Twitter API Token",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "botUsername",
+ Label: "Bot Username",
+ Type: config.FieldTypeText,
+ Required: true,
+ },
+ {
+ Name: "noCharacterLimit",
+ Label: "No Character Limit",
+ Type: config.FieldTypeCheckbox,
+ },
+ }
+}
diff --git a/webui/app.go b/webui/app.go
index 53a593d..a4d4a25 100644
--- a/webui/app.go
+++ b/webui/app.go
@@ -477,3 +477,15 @@ func (a *App) CreateGroup(pool *state.AgentPool) func(c *fiber.Ctx) error {
return statusJSONMessage(c, "ok")
}
}
+
+// GetAgentConfigMeta returns the metadata for agent configuration fields
+func (a *App) GetAgentConfigMeta() func(c *fiber.Ctx) error {
+ return func(c *fiber.Ctx) error {
+ // Create a new instance of AgentConfigMeta
+ configMeta := state.NewAgentConfigMeta(
+ services.ActionsConfigMeta(),
+ services.ConnectorsConfigMeta(),
+ )
+ return c.JSON(configMeta)
+ }
+}
diff --git a/webui/react-ui/src/components/ActionForm.jsx b/webui/react-ui/src/components/ActionForm.jsx
index 721d12f..1976bb0 100644
--- a/webui/react-ui/src/components/ActionForm.jsx
+++ b/webui/react-ui/src/components/ActionForm.jsx
@@ -1,169 +1,31 @@
import React from 'react';
-import FallbackAction from './actions/FallbackAction';
-import GithubIssueLabelerAction from './actions/GithubIssueLabelerAction';
-import GithubIssueOpenerAction from './actions/GithubIssueOpenerAction';
-import GithubIssueCloserAction from './actions/GithubIssueCloserAction';
-import GithubIssueCommenterAction from './actions/GithubIssueCommenterAction';
-import GithubRepositoryAction from './actions/GithubRepositoryAction';
-import TwitterPostAction from './actions/TwitterPostAction';
-import SendMailAction from './actions/SendMailAction';
-import GenerateImageAction from './actions/GenerateImageAction';
+import ConfigForm from './ConfigForm';
/**
* ActionForm component for configuring an action
+ * Renders action configuration forms based on field group metadata
*/
-const ActionForm = ({ actions = [], onChange, onRemove, onAdd }) => {
- // Available action types
- const actionTypes = [
- { value: '', label: 'Select an action type' },
- { value: 'github-issue-labeler', label: 'GitHub Issue Labeler' },
- { value: 'github-issue-opener', label: 'GitHub Issue Opener' },
- { value: 'github-issue-closer', label: 'GitHub Issue Closer' },
- { value: 'github-issue-commenter', label: 'GitHub Issue Commenter' },
- { value: 'github-repository-get-content', label: 'GitHub Repository Get Content' },
- { value: 'github-repository-create-or-update-content', label: 'GitHub Repository Create/Update Content' },
- { value: 'github-readme', label: 'GitHub Readme' },
- { value: 'twitter-post', label: 'Twitter Post' },
- { value: 'send-mail', label: 'Send Email' },
- { value: 'search', label: 'Search' },
- { value: 'github-issue-searcher', label: 'GitHub Issue Searcher' },
- { value: 'github-issue-reader', label: 'GitHub Issue Reader' },
- { value: 'scraper', label: 'Web Scraper' },
- { value: 'wikipedia', label: 'Wikipedia' },
- { value: 'browse', label: 'Browse' },
- { value: 'generate_image', label: 'Generate Image' },
- { value: 'counter', label: 'Counter' },
- { value: 'call_agents', label: 'Call Agents' },
- { value: 'shell-command', label: 'Shell Command' },
- { value: 'custom', label: 'Custom' }
- ];
-
- // Parse the config JSON string to an object
- const parseConfig = (action) => {
- if (!action || !action.config) return {};
-
- try {
- return JSON.parse(action.config || '{}');
- } catch (error) {
- console.error('Error parsing action config:', error);
- return {};
- }
+const ActionForm = ({ actions = [], onChange, onRemove, onAdd, fieldGroups = [] }) => {
+ // Debug logging
+ console.log('ActionForm:', { actions, fieldGroups });
+
+ // Handle action change
+ const handleActionChange = (index, updatedAction) => {
+ console.log('Action change:', { index, updatedAction });
+ onChange(index, updatedAction);
};
-
- // Get a value from the config object
- const getConfigValue = (action, key, defaultValue = '') => {
- const config = parseConfig(action);
- return config[key] !== undefined ? config[key] : defaultValue;
- };
-
- // Update a value in the config object
- const onActionConfigChange = (index, key, value) => {
- const action = actions[index];
- const config = parseConfig(action);
- config[key] = value;
-
- onChange(index, {
- ...action,
- config: JSON.stringify(config)
- });
- };
-
- // Handle action type change
- const handleActionTypeChange = (index, value) => {
- const action = actions[index];
- onChange(index, {
- ...action,
- name: value
- });
- };
-
- // Render the appropriate action component based on the action type
- const renderActionComponent = (action, index) => {
- // Common props for all action components
- const actionProps = {
- index,
- onActionConfigChange: (key, value) => onActionConfigChange(index, key, value),
- getConfigValue: (key, defaultValue) => getConfigValue(action, key, defaultValue)
- };
-
- switch (action.name) {
- case 'github-issue-labeler':
- return