Class: Phronomy::Graph::StateGraph

Inherits:
Object
  • Object
show all
Defined in:
lib/phronomy/graph/state_graph.rb

Overview

Declarative agent workflow definition class. Assembles nodes and edges, then returns an executable CompiledGraph via compile.

Constant Summary collapse

START =
:__start__
FINISH =
:__end__

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(state_class) ⇒ StateGraph

Returns a new instance of StateGraph.

Parameters:

  • state_class (Class)

    class that includes Phronomy::Graph::State



14
15
16
17
18
19
20
21
22
# File 'lib/phronomy/graph/state_graph.rb', line 14

def initialize(state_class)
  @state_class = state_class
  @nodes = {}
  @edges = {}
  @conditional_edges = {}
  @entry_point = nil
  @before_callbacks = {}
  @after_callbacks = {}
end

Instance Attribute Details

#conditional_edgesObject (readonly)

Returns the value of attribute conditional_edges.



140
141
142
# File 'lib/phronomy/graph/state_graph.rb', line 140

def conditional_edges
  @conditional_edges
end

#edgesObject (readonly)

Returns the value of attribute edges.



11
12
13
# File 'lib/phronomy/graph/state_graph.rb', line 11

def edges
  @edges
end

#entry_pointObject (readonly)

Returns the value of attribute entry_point.



11
12
13
# File 'lib/phronomy/graph/state_graph.rb', line 11

def entry_point
  @entry_point
end

#nodesObject (readonly)

Returns the value of attribute nodes.



11
12
13
# File 'lib/phronomy/graph/state_graph.rb', line 11

def nodes
  @nodes
end

Instance Method Details

#add_conditional_edges(from, condition, mapping = nil) ⇒ self

Adds a conditional edge.

Parameters:

  • from (Symbol)
  • condition (Proc)

    receives state and returns the next node name

  • mapping (Hash, nil) (defaults to: nil)

    maps condition return value to a node name (optional)

Returns:

  • (self)


51
52
53
54
# File 'lib/phronomy/graph/state_graph.rb', line 51

def add_conditional_edges(from, condition, mapping = nil)
  @conditional_edges[from] = {condition: condition, mapping: mapping}
  self
end

#add_edge(from, to, condition = nil) ⇒ self

Adds a directed edge.

Parameters:

  • from (Symbol)
  • to (Symbol)
  • condition (Proc, nil) (defaults to: nil)

    guard condition — receives state and returns truthy/falsy. When nil, the edge is unconditional. When multiple edges exist from the same node, they are evaluated in registration order and the first matching edge is taken.

Returns:

  • (self)


40
41
42
43
44
# File 'lib/phronomy/graph/state_graph.rb', line 40

def add_edge(from, to, condition = nil)
  @edges[from] ||= []
  @edges[from] << {to: to, condition: condition}
  self
end

#add_node(name, callable = nil, &block) ⇒ self

Adds a node.

Parameters:

  • name (Symbol)
  • callable (#call, nil) (defaults to: nil)

    node execution logic (block accepted)

Returns:

  • (self)


28
29
30
31
# File 'lib/phronomy/graph/state_graph.rb', line 28

def add_node(name, callable = nil, &block)
  @nodes[name] = callable || block
  self
end

#add_parallel_node(name, *branches, timeout: nil, on_error: :raise) ⇒ self

Adds a parallel node that executes multiple branches concurrently. Each branch callable receives the current state and must return a Hash or nil. Results are merged in registration order (see ParallelNode for merge policy).

Parameters:

  • name (Symbol)
  • branches (Array<#call>)

    at least one callable required

  • timeout (Numeric, nil) (defaults to: nil)

    wall-clock limit in seconds (nil = unlimited)

  • on_error (Symbol) (defaults to: :raise)

    :raise (default) or :best_effort

Returns:

  • (self)

Raises:

  • (ArgumentError)


95
96
97
98
99
100
# File 'lib/phronomy/graph/state_graph.rb', line 95

def add_parallel_node(name, *branches, timeout: nil, on_error: :raise)
  raise ArgumentError, "add_parallel_node requires at least one branch" if branches.empty?

  @nodes[name] = ParallelNode.new(branches, timeout: timeout, on_error: on_error)
  self
end

#add_subgraph(name, subgraph, input_mapper: nil, output_mapper: nil) ⇒ self

Embeds a compiled subgraph as a single node in this graph. The subgraph is invoked with a Hash derived from the parent state; its final state Hash is returned and merged into the parent state.

Parameters:

  • name (Symbol)
  • subgraph (CompiledGraph)

    the compiled subgraph to embed

  • input_mapper (Proc, nil) (defaults to: nil)

    maps parent state → input Hash for the subgraph; defaults to state.to_h (passes all parent fields)

  • output_mapper (Proc, nil) (defaults to: nil)

    maps subgraph final state → Hash to merge back; defaults to sub_state.to_h (passes all subgraph fields)

Returns:

  • (self)


113
114
115
116
117
118
119
# File 'lib/phronomy/graph/state_graph.rb', line 113

def add_subgraph(name, subgraph, input_mapper: nil, output_mapper: nil)
  add_node(name) do |state|
    input = input_mapper ? input_mapper.call(state) : state.to_h
    sub_state = subgraph.invoke(input, config: {thread_id: state.thread_id})
    output_mapper ? output_mapper.call(sub_state) : sub_state.to_h
  end
end

#compile(state_store: nil) ⇒ CompiledGraph

Compiles the graph and returns a CompiledGraph. Callbacks registered on StateGraph are inherited; additional callbacks can be registered on the returned CompiledGraph to override or extend them.

Parameters:

  • state_store (Phronomy::StateStore::Base, nil) (defaults to: nil)

    optional state store to use for this compiled graph, overriding the global default.

Returns:



127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/phronomy/graph/state_graph.rb', line 127

def compile(state_store: nil)
  CompiledGraph.new(
    state_class: @state_class,
    nodes: @nodes,
    edges: @edges,
    conditional_edges: @conditional_edges,
    entry_point: @entry_point || @nodes.keys.first,
    before_callbacks: @before_callbacks.dup,
    after_callbacks: @after_callbacks.dup,
    state_store: state_store
  )
end

#interrupt_after(node) {|state| ... } ⇒ self

Registers a callback to run after the given node completes. Return :halt from the block to pause execution; any other value continues. Callbacks registered here become defaults for every CompiledGraph produced by compile.

Parameters:

  • node (Symbol)

Yields:

  • (state)

    the state after the node ran

Returns:

  • (self)


81
82
83
84
# File 'lib/phronomy/graph/state_graph.rb', line 81

def interrupt_after(node, &block)
  @after_callbacks[node] = block
  self
end

#interrupt_before(node) {|state| ... } ⇒ self

Registers a callback to run before the given node executes. Return :halt from the block to pause execution; any other value continues. Callbacks registered here become defaults for every CompiledGraph produced by compile.

Parameters:

  • node (Symbol)

Yields:

  • (state)

    the current state

Returns:

  • (self)


70
71
72
73
# File 'lib/phronomy/graph/state_graph.rb', line 70

def interrupt_before(node, &block)
  @before_callbacks[node] = block
  self
end

#set_entry_point(node_name) ⇒ self

Sets the entry point node.

Parameters:

  • node_name (Symbol)

Returns:

  • (self)


59
60
61
62
# File 'lib/phronomy/graph/state_graph.rb', line 59

def set_entry_point(node_name)
  @entry_point = node_name
  self
end