package routing import ( "context" "fmt" ) // ActivityExecutor defines how to execute an activity type ActivityExecutor interface { // Execute runs the activity with given parameters Execute(ctx context.Context, activityName string, params map[string]interface{}) (interface{}, error) } // TemporalActivityExecutor executes activities via Temporal type TemporalActivityExecutor struct { // This would be implemented by workflow context executor func(context.Context, string, interface{}) error } // StateTransitioner defines state machine transitions type StateTransitioner interface { // CanTransition checks if transition is allowed CanTransition(from, to *State) bool // Transit performs the transition Transit(from, to *State) error } // DefaultStateTransitioner implements basic transitions type DefaultStateTransitioner struct { validators []TransitionValidator } // TransitionValidator validates a specific transition type TransitionValidator interface { Validate(from, to *State) error } // NewDefaultStateTransitioner creates a new transitioner func NewDefaultStateTransitioner() *DefaultStateTransitioner { return &DefaultStateTransitioner{ validators: []TransitionValidator{ &StateTypeValidator{}, &OutputMatchValidator{}, }, } } // CanTransition checks if transition is valid func (dst *DefaultStateTransitioner) CanTransition(from, to *State) bool { return dst.Transit(from, to) == nil } // Transit validates and performs transition func (dst *DefaultStateTransitioner) Transit(from, to *State) error { for _, v := range dst.validators { if err := v.Validate(from, to); err != nil { return err } } return nil } // StateTypeValidator checks state type compatibility type StateTypeValidator struct{} func (stv *StateTypeValidator) Validate(from, to *State) error { if from == nil { return nil // Initial transition } // Can't transition from terminal states if from.Type == StateTypeFail { return fmt.Errorf("cannot transition from Fail state") } if from.End && from.Type != StateTypePass { return fmt.Errorf("cannot transition from end state") } return nil } // OutputMatchValidator checks output-input binding type OutputMatchValidator struct{} func (omv *OutputMatchValidator) Validate(from, to *State) error { // Could validate that outputs from previous state match inputs needed return nil } // ParameterBinder resolves parameters from context type ParameterBinder interface { // Bind resolves all parameters for a state Bind(state *State, context *ExecutionContext) (map[string]interface{}, error) } // DefaultParameterBinder implements parameter resolution type DefaultParameterBinder struct { resolver *JSONPathResolver } // NewDefaultParameterBinder creates a new binder func NewDefaultParameterBinder() *DefaultParameterBinder { return &DefaultParameterBinder{ resolver: NewJSONPathResolver(nil, nil), } } // Bind resolves all parameters func (dpb *DefaultParameterBinder) Bind(state *State, context *ExecutionContext) (map[string]interface{}, error) { dpb.resolver.input = context.Input dpb.resolver.stepResults = context.StepResults resolved, err := dpb.resolver.ResolvePaths(state.Parameters) if err != nil { return nil, fmt.Errorf("parameter binding failed: %w", err) } return resolved, nil } // WorkflowValidator validates workflow specs type WorkflowValidator interface { // Validate checks if workflow is valid Validate(spec *WorkflowSpec) error } // CompositeValidator combines multiple validators type CompositeValidator struct { validators []WorkflowValidator } // NewCompositeValidator creates a composite validator func NewCompositeValidator(validators ...WorkflowValidator) *CompositeValidator { return &CompositeValidator{validators: validators} } // Validate runs all validators func (cv *CompositeValidator) Validate(spec *WorkflowSpec) error { for _, v := range cv.validators { if err := v.Validate(spec); err != nil { return err } } return nil } // StateGraphValidator validates state graph structure type StateGraphValidator struct{} func (sgv *StateGraphValidator) Validate(spec *WorkflowSpec) error { if spec == nil { return fmt.Errorf("workflow spec is nil") } if len(spec.States) == 0 { return fmt.Errorf("workflow has no states") } stateMap := make(map[string]*State) for i := range spec.States { stateMap[spec.States[i].Name] = &spec.States[i] } // Check all transitions point to valid states for _, state := range spec.States { if state.Type == StateTypeTask && !state.End { if state.Next == "" { return fmt.Errorf("state %s has no next state and is not end", state.Name) } if _, exists := stateMap[state.Next]; !exists { return fmt.Errorf("state %s references non-existent next state %s", state.Name, state.Next) } } // Validate catch clauses for _, catch := range state.Catch { if _, exists := stateMap[catch.Next]; !exists { return fmt.Errorf("catch handler in %s references non-existent state %s", state.Name, catch.Next) } } } return nil } // ActivityAvailabilityValidator validates activities exist type ActivityAvailabilityValidator struct { kb *KnowledgeBase } // NewActivityAvailabilityValidator creates a new validator func NewActivityAvailabilityValidator(kb *KnowledgeBase) *ActivityAvailabilityValidator { return &ActivityAvailabilityValidator{kb: kb} } // Validate checks all activities are available func (aav *ActivityAvailabilityValidator) Validate(spec *WorkflowSpec) error { for _, state := range spec.States { if state.Type == StateTypeTask { if !aav.kb.HasActivity(state.Resource) { return fmt.Errorf("activity %s not found in knowledge base", state.Resource) } } } return nil } // TimeoutValidator validates timeouts type TimeoutValidator struct{} func (tv *TimeoutValidator) Validate(spec *WorkflowSpec) error { for _, state := range spec.States { if state.Timeout != "" { if _, err := parseDuration(state.Timeout); err != nil { return fmt.Errorf("invalid timeout in state %s: %w", state.Name, err) } } } return nil } func parseDuration(d string) (interface{}, error) { // Placeholder for duration parsing return nil, nil }