87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package filters
|
|
|
|
import (
|
|
"encoding/json"
|
|
"regexp"
|
|
|
|
"github.com/mudler/LocalAGI/core/types"
|
|
"github.com/mudler/LocalAGI/pkg/config"
|
|
)
|
|
|
|
const FilterRegex = "regex"
|
|
|
|
type RegexFilter struct {
|
|
name string
|
|
pattern *regexp.Regexp
|
|
allowOnMatch bool
|
|
isTrigger bool
|
|
}
|
|
|
|
type RegexFilterConfig struct {
|
|
Name string `json:"name"`
|
|
Pattern string `json:"pattern"`
|
|
AllowOnMatch bool `json:"allow_on_match"`
|
|
IsTrigger bool `json:"is_trigger"`
|
|
}
|
|
|
|
func NewRegexFilter(configJSON string) (*RegexFilter, error) {
|
|
var cfg RegexFilterConfig
|
|
if err := json.Unmarshal([]byte(configJSON), &cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
re, err := regexp.Compile(cfg.Pattern)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &RegexFilter{
|
|
name: cfg.Name,
|
|
pattern: re,
|
|
allowOnMatch: cfg.AllowOnMatch,
|
|
isTrigger: cfg.IsTrigger,
|
|
}, nil
|
|
}
|
|
|
|
func (f *RegexFilter) Name() string { return f.name }
|
|
func (f *RegexFilter) Apply(job *types.Job) (bool, error) {
|
|
input := extractInputFromJob(job)
|
|
if f.pattern.MatchString(input) {
|
|
return f.allowOnMatch, nil
|
|
}
|
|
return !f.allowOnMatch, nil
|
|
}
|
|
|
|
func (f *RegexFilter) IsTrigger() bool {
|
|
return f.isTrigger
|
|
}
|
|
|
|
func RegexFilterConfigMeta() config.FieldGroup {
|
|
return config.FieldGroup{
|
|
Name: FilterRegex,
|
|
Label: "Regex Filter/Trigger",
|
|
Fields: []config.Field{
|
|
{Name: "name", Label: "Name", Type: "text", Required: true},
|
|
{Name: "pattern", Label: "Pattern", Type: "text", Required: true},
|
|
{Name: "allow_on_match", Label: "Allow on Match", Type: "checkbox", Required: true},
|
|
{Name: "is_trigger", Label: "Is Trigger", Type: "checkbox", Required: true},
|
|
},
|
|
}
|
|
}
|
|
|
|
// extractInputFromJob attempts to extract a string input for filtering.
|
|
func extractInputFromJob(job *types.Job) string {
|
|
if job.Metadata != nil {
|
|
if v, ok := job.Metadata["input"]; ok {
|
|
if s, ok := v.(string); ok {
|
|
return s
|
|
}
|
|
}
|
|
}
|
|
// fallback: try to use conversation history if available
|
|
if len(job.ConversationHistory) > 0 {
|
|
// Use the last message content
|
|
last := job.ConversationHistory[len(job.ConversationHistory)-1]
|
|
return last.Content
|
|
}
|
|
return ""
|
|
}
|