mirror of
https://github.com/j3ssie/osmedeus.git
synced 2026-08-21 23:22:30 +02:00
- Add LLM executor supporting OpenAI vision, tool calling, embeddings, and structured outputs - Introduce event emitter/receiver workflows with deduplication and filtering (generate_event functions) - Add workflow extends/override system enabling inheritance chains and step merge modes - Update function naming to snake_case across all testdata (fileExists→file_exists, etc.) - Add comprehensive test fixtures for linter, events, CDN, step dependencies, and extends workflows
142 lines
3.7 KiB
Go
142 lines
3.7 KiB
Go
package parser
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/j3ssie/osmedeus/v5/internal/core"
|
|
"github.com/j3ssie/osmedeus/v5/internal/utils"
|
|
)
|
|
|
|
// DependencyChecker validates workflow dependencies
|
|
type DependencyChecker struct{}
|
|
|
|
// NewDependencyChecker creates a new dependency checker
|
|
func NewDependencyChecker() *DependencyChecker {
|
|
return &DependencyChecker{}
|
|
}
|
|
|
|
// CheckCommands checks if required commands are available in binariesPath or system PATH
|
|
func (c *DependencyChecker) CheckCommands(commands []string, binariesPath string) error {
|
|
var missing []string
|
|
for _, cmd := range commands {
|
|
if _, err := utils.LookPathWithBinaries(cmd, binariesPath); err != nil {
|
|
missing = append(missing, cmd)
|
|
}
|
|
}
|
|
|
|
if len(missing) > 0 {
|
|
return &DependencyError{
|
|
Type: "commands",
|
|
Missing: missing,
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CheckFiles checks if required files exist
|
|
func (c *DependencyChecker) CheckFiles(files []string, ctx map[string]interface{}) error {
|
|
// Files would need template rendering first
|
|
// This is a placeholder for the actual implementation
|
|
return nil
|
|
}
|
|
|
|
// CheckVariables validates required variables are present and valid
|
|
func (c *DependencyChecker) CheckVariables(deps []core.VariableDep, ctx map[string]interface{}) error {
|
|
var errors []string
|
|
|
|
for _, dep := range deps {
|
|
if !dep.Required {
|
|
continue
|
|
}
|
|
|
|
value, ok := ctx[dep.Name]
|
|
if !ok || value == nil || value == "" {
|
|
errors = append(errors, fmt.Sprintf("required variable '%s' is missing", dep.Name))
|
|
continue
|
|
}
|
|
|
|
// Validate type
|
|
if err := c.validateType(dep.Name, value, dep.Type); err != nil {
|
|
errors = append(errors, err.Error())
|
|
}
|
|
}
|
|
|
|
if len(errors) > 0 {
|
|
return &DependencyError{
|
|
Type: "variables",
|
|
Errors: errors,
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateType validates a value against a variable type.
|
|
// Supports comma-separated types (e.g., "domain,url") where matching any type is sufficient.
|
|
func (c *DependencyChecker) validateType(name string, value interface{}, varType core.VariableType) error {
|
|
str, ok := value.(string)
|
|
if !ok {
|
|
return fmt.Errorf("variable '%s' must be a string", name)
|
|
}
|
|
|
|
// Use MatchesAnyVariableType to support comma-separated types
|
|
ok, err := core.MatchesAnyVariableType(str, varType)
|
|
if err != nil {
|
|
return fmt.Errorf("variable '%s' has invalid type: %w", name, err)
|
|
}
|
|
if !ok {
|
|
return fmt.Errorf("variable '%s' does not match type '%s'", name, varType)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CheckAll performs all dependency checks
|
|
// Note: FunctionsConditions are checked at runtime by the executor, not here
|
|
func (c *DependencyChecker) CheckAll(deps *core.Dependencies, ctx map[string]interface{}, binariesPath string) error {
|
|
if deps == nil {
|
|
return nil
|
|
}
|
|
|
|
if len(deps.Commands) > 0 {
|
|
if err := c.CheckCommands(deps.Commands, binariesPath); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if len(deps.Files) > 0 {
|
|
if err := c.CheckFiles(deps.Files, ctx); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if len(deps.Variables) > 0 {
|
|
if err := c.CheckVariables(deps.Variables, ctx); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DependencyError represents a dependency check failure
|
|
type DependencyError struct {
|
|
Type string
|
|
Missing []string
|
|
Errors []string
|
|
}
|
|
|
|
func (e *DependencyError) Error() string {
|
|
if len(e.Missing) > 0 {
|
|
return fmt.Sprintf("missing %s: %v", e.Type, e.Missing)
|
|
}
|
|
return fmt.Sprintf("%s validation errors: %v", e.Type, e.Errors)
|
|
}
|
|
|
|
// isValidDomain checks if a string is a valid domain
|
|
// DefaultDependencyChecker is the global dependency checker
|
|
var DefaultDependencyChecker = NewDependencyChecker()
|
|
|
|
// CheckDependencies checks all dependencies using the default checker
|
|
func CheckDependencies(deps *core.Dependencies, ctx map[string]interface{}, binariesPath string) error {
|
|
return DefaultDependencyChecker.CheckAll(deps, ctx, binariesPath)
|
|
}
|