Class: Phronomy::Agent::AgentExecution

Inherits:
Object
  • Object
show all
Defined in:
lib/phronomy/agent/agent_execution.rb

Constant Summary collapse

ACTIVE_STATUSES =
%i[preparing active suspended].freeze
TERMINAL_STATUSES =
%i[completed failed cancelled rejected blocked].freeze
TRANSITIONS =
{
  preparing: %i[preparing active failed cancelled blocked],
  active: %i[active suspended completed failed cancelled rejected blocked],
  suspended: %i[suspended active failed cancelled],
  completed: %i[completed],
  failed: %i[failed],
  cancelled: %i[cancelled],
  rejected: %i[rejected],
  blocked: %i[blocked]
}.freeze
ATTRIBUTES =
%i[
  execution_id agent_id execution_revision status phase
  base_agent_revision base_context_revision base_journal_position
  working_records llm_calls approval_request result_ref error_ref
  created_at updated_at terminal_reason metadata
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**attributes) ⇒ AgentExecution

Returns a new instance of AgentExecution.

Raises:

  • (ArgumentError)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/phronomy/agent/agent_execution.rb', line 53

def initialize(**attributes)
  ATTRIBUTES.each do |name|
    value = attributes.fetch(name)
    value = value.to_sym if %i[status phase].include?(name)
    instance_variable_set("@#{name}", Immutable.copy(value))
  end
  raise ArgumentError, "unknown execution status: #{status.inspect}" unless TRANSITIONS.key?(status)
  raise ArgumentError, "execution_revision must be non-negative" if execution_revision.negative?
  Immutable.validate_canonical_json!(, label: "Execution metadata")
  if approval_request
    Immutable.validate_canonical_json!(approval_request, label: "Approval request")
  end
  freeze
end

Class Method Details

.start(agent_root:, input_record:, metadata: {}) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/phronomy/agent/agent_execution.rb', line 30

def self.start(agent_root:, input_record:, metadata: {})
  now = Time.now.utc.iso8601(6)
  new(
    execution_id: SecureRandom.uuid,
    agent_id: agent_root.agent_id,
    execution_revision: 0,
    status: :preparing,
    phase: :preparing,
    base_agent_revision: agent_root.agent_revision,
    base_context_revision: agent_root.context_revision,
    base_journal_position: agent_root.journal_position,
    working_records: [input_record],
    llm_calls: [],
    approval_request: nil,
    result_ref: nil,
    error_ref: nil,
    created_at: now,
    updated_at: now,
    terminal_reason: nil,
    metadata: 
  )
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/phronomy/agent/agent_execution.rb', line 68

def active?
  ACTIVE_STATUSES.include?(status)
end

#terminal?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/phronomy/agent/agent_execution.rb', line 72

def terminal?
  TERMINAL_STATUSES.include?(status)
end

#to_hObject



87
88
89
90
91
92
93
94
# File 'lib/phronomy/agent/agent_execution.rb', line 87

def to_h
  ATTRIBUTES.to_h do |name|
    value = public_send(name)
    value = value.map(&:to_h) if name == :working_records
    value = value.map(&:to_h) if name == :llm_calls
    [name.to_s, value]
  end
end

#with(**changes) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/phronomy/agent/agent_execution.rb', line 76

def with(**changes)
  next_status = changes.fetch(:status, status).to_sym
  unless TRANSITIONS.fetch(status).include?(next_status)
    raise ArgumentError, "illegal AgentExecution transition: #{status} -> #{next_status}"
  end
  values = ATTRIBUTES.to_h { |name| [name, public_send(name)] }.merge(changes)
  values[:execution_revision] = execution_revision + 1 unless changes.key?(:execution_revision)
  values[:updated_at] = Time.now.utc.iso8601(6) unless changes.key?(:updated_at)
  self.class.new(**values)
end