10
11
12
13
14
15
16
17
18
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
55
56
57
58
59
60
61
62
63
64
65
66
|
# File 'lib/phronomy/agent/context_parts/unit_builders/dependency_aware_unit_builder.rb', line 10
def build(candidates)
ordered = Array(candidates).sort_by { |candidate| [candidate.sequence || 0, candidate.candidate_id] }
by_id = ordered.to_h { |candidate| [candidate.candidate_id, candidate] }
canonical_assistants = ordered.select { |candidate| candidate.category == :assistant_message }
canonical_tool_messages = ordered.select { |candidate| candidate.category == :tool_message }
.group_by(&:tool_call_id)
assistant_by_tool_call_id = canonical_assistants.each_with_object({}) do |candidate, result|
canonical_tool_call_ids(candidate).each do |tool_call_id|
if result.key?(tool_call_id)
raise ArgumentError, "duplicate assistant Tool Call id in Context candidates: #{tool_call_id}"
end
result[tool_call_id] = candidate
end
end
legacy_tool_results = ordered.select { |candidate| candidate.category == :tool_result }
.group_by(&:tool_call_id)
legacy_calls_by_llm = ordered.select do |candidate|
candidate.category == :tool_call && candidate.llm_call_id
end.group_by(&:llm_call_id)
legacy_assistant_by_llm = ordered.select do |candidate|
candidate.llm_call_id && %i[llm_message tool_call].include?(candidate.category)
end.group_by(&:llm_call_id)
claimed = Set.new
units = []
ordered.each_with_index do |candidate, index|
next if claimed.include?(candidate.candidate_id)
group = canonical_tool_exchange(
candidate,
assistant_by_tool_call_id: assistant_by_tool_call_id,
tool_messages: canonical_tool_messages
)
group ||= if legacy_runtime_tool_exchange?(candidate, legacy_calls_by_llm)
legacy_runtime_tool_exchange(
candidate,
assistant_by_llm: legacy_assistant_by_llm,
calls_by_llm: legacy_calls_by_llm,
tool_results: legacy_tool_results
)
else
legacy_import_tool_exchange(ordered, index, legacy_tool_results)
end
if group && !group.empty?
group.each { |item| claimed << item.candidate_id }
units << build_unit(group, kind: :tool_exchange)
else
claimed << candidate.candidate_id
units << build_unit([by_id.fetch(candidate.candidate_id)], kind: :message)
end
end
units.sort_by { |unit| unit.sequence_range.first }.freeze
end
|