Class: Phronomy::Agent::ContextPlanValidator

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

Defined Under Namespace

Classes: ValidatedContextPlan

Instance Method Summary collapse

Instance Method Details

#validate!(request:, plan:) ⇒ Object

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/phronomy/agent/context_plan_validator.rb', line 19

def validate!(request:, plan:)
  unless plan.is_a?(ContextPlan)
    raise ArgumentError, "Context Policy returned #{plan.class}, expected #{ContextPlan}"
  end

  units = request.parts.fetch(:unit_builder).build(request.candidates)
  units = request.parts.fetch(:required_context_resolver).resolve(
    request: request,
    units: units
  )
  unit_index = units.to_h { |unit| [unit.unit_id, unit] }
  unknown = plan.selected_unit_ids.reject { |unit_id| unit_index.key?(unit_id) }
  raise ArgumentError, "ContextPlan contains unknown units: #{unknown.inspect}" unless unknown.empty?

  selected_units = plan.selected_unit_ids.map { |unit_id| unit_index.fetch(unit_id) }
  required = units.reject { |unit| unit.requirement == :optional }.map(&:unit_id)
  missing_required = required - plan.selected_unit_ids
  unless missing_required.empty?
    raise Phronomy::ContextBudgetExceededError,
      "ContextPlan omitted required units: #{missing_required.inspect}"
  end

  candidate_index = request.candidates.to_h { |candidate| [candidate.candidate_id, candidate] }
  selected_candidates = selected_units.flat_map(&:candidate_ids).uniq.map do |candidate_id|
    candidate_index.fetch(candidate_id)
  end
  validate_tool_dependencies!(request.candidates, selected_candidates)
  validate_derived_contents!(request, plan)

  ValidatedContextPlan.new(
    plan: plan,
    units: units,
    selected_units: selected_units,
    selected_candidates: selected_candidates
  )
end