foobara-agent 0.0.10 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/lib/foobara/agent.rb +1 -1
- data/src/foobara/agent/accomplish_goal.rb +74 -45
- data/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb +97 -26
- data/src/foobara/agent/types/command_log_entry.rb +11 -0
- data/src/foobara/agent.rb +56 -39
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc4b3804b5930b121fdc679ecf203b9e8b4d11122d24da967cfbfd10a1e6562d
|
4
|
+
data.tar.gz: '0739391b9b59d453783756a8efed38ec3d559ce7636873776ee71a14027059b5'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ff04dba39a3edae5a80a98234cd7708c2f90d30bded9f12a0e2b665ea640c302e1ed14c607d61533daa5a0b3d7712684d92de740a3f3e085a1704286f95b837
|
7
|
+
data.tar.gz: 252b0f1a1c298bd984a856f4e63e57808b63cace046d58cf82f8c55f391c6d21fb3d98b8dda869582aa995eb6438a2fe998bae3952c5f6791eca00d25c5d181c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
## [0.0.13] - 2025-07-06
|
2
|
+
|
3
|
+
- Eliminate NotifyUser... result_type to save tokens/improve accuracy
|
4
|
+
- Choose DescribeCommand for commands with inputs that haven't been described
|
5
|
+
- Log failure output when trying to determine commands/inputs
|
6
|
+
|
7
|
+
## [0.0.12] - 2025-07-05
|
8
|
+
|
9
|
+
- Choose DescribeCommand for commands that have inputs and haven't been described
|
10
|
+
- Log determine command/input failures when verbose
|
11
|
+
|
12
|
+
## [0.0.11] - 2025-07-01
|
13
|
+
|
14
|
+
- Fix some bugs with result type/value mismatches
|
15
|
+
- Eliminate ability to select command and inputs separately
|
16
|
+
|
1
17
|
## [0.0.10] - 2025-06-30
|
2
18
|
|
3
19
|
- Allow more retries
|
data/lib/foobara/agent.rb
CHANGED
@@ -30,6 +30,7 @@ module Foobara
|
|
30
30
|
default: "claude-3-7-sonnet-20250219",
|
31
31
|
description: "The model to use for the LLM"
|
32
32
|
max_llm_calls_per_minute :integer, :allow_nil
|
33
|
+
result_entity_depth :symbol, :allow_nil, one_of: [:atom, :aggregate]
|
33
34
|
end
|
34
35
|
|
35
36
|
result do
|
@@ -51,9 +52,8 @@ module Foobara
|
|
51
52
|
throttle_llm_calls_if_necessary
|
52
53
|
|
53
54
|
determine_next_command_and_inputs
|
54
|
-
run_next_command
|
55
55
|
|
56
|
-
|
56
|
+
run_next_command
|
57
57
|
end
|
58
58
|
|
59
59
|
if given_up
|
@@ -75,7 +75,6 @@ module Foobara
|
|
75
75
|
fetch_next_command_class
|
76
76
|
|
77
77
|
run_next_command
|
78
|
-
log_last_command_outcome
|
79
78
|
end
|
80
79
|
|
81
80
|
def simulate_describe_list_commands_command
|
@@ -85,7 +84,6 @@ module Foobara
|
|
85
84
|
fetch_next_command_class
|
86
85
|
|
87
86
|
run_next_command
|
88
|
-
log_last_command_outcome
|
89
87
|
end
|
90
88
|
|
91
89
|
def simulate_describe_command(command_name = next_command_name)
|
@@ -100,7 +98,6 @@ module Foobara
|
|
100
98
|
fetch_next_command_class
|
101
99
|
|
102
100
|
run_next_command
|
103
|
-
log_last_command_outcome
|
104
101
|
|
105
102
|
self.next_command_name = old_next_command_name
|
106
103
|
self.next_command_inputs = old_next_command_inputs
|
@@ -114,7 +111,7 @@ module Foobara
|
|
114
111
|
return if context.command_log.size > 1
|
115
112
|
|
116
113
|
ListCommands.run!(command_connector: agent)[:user_provided_commands].each do |full_command_name|
|
117
|
-
next if
|
114
|
+
next if command_described?(full_command_name)
|
118
115
|
|
119
116
|
self.next_command_name = DescribeCommand.full_command_name
|
120
117
|
self.next_command_inputs = { command_name: full_command_name }
|
@@ -122,7 +119,6 @@ module Foobara
|
|
122
119
|
fetch_next_command_class
|
123
120
|
|
124
121
|
run_next_command
|
125
|
-
log_last_command_outcome
|
126
122
|
end
|
127
123
|
# :nocov:
|
128
124
|
end
|
@@ -145,11 +141,7 @@ module Foobara
|
|
145
141
|
|
146
142
|
compact_command_log
|
147
143
|
|
148
|
-
inputs_for_determine = {
|
149
|
-
context:,
|
150
|
-
llm_model:
|
151
|
-
}
|
152
|
-
|
144
|
+
inputs_for_determine = { context:, llm_model: }
|
153
145
|
determine_command = DetermineNextCommandNameAndInputs.new(inputs_for_determine)
|
154
146
|
|
155
147
|
outcome = begin
|
@@ -171,10 +163,17 @@ module Foobara
|
|
171
163
|
if outcome.success?
|
172
164
|
fetch_next_command_class
|
173
165
|
|
166
|
+
if need_to_describe_next_command?
|
167
|
+
simulate_describe_command
|
168
|
+
return determine_next_command_and_inputs(retries, outcome)
|
169
|
+
end
|
170
|
+
|
174
171
|
if next_command_has_inputs?
|
175
172
|
outcome = validate_next_command_inputs
|
176
173
|
|
177
174
|
unless outcome.success?
|
175
|
+
# TODO: test this path
|
176
|
+
# :nocov:
|
178
177
|
log_command_outcome(
|
179
178
|
command_name: next_command_name,
|
180
179
|
inputs: next_command_inputs,
|
@@ -184,6 +183,7 @@ module Foobara
|
|
184
183
|
simulate_describe_command
|
185
184
|
|
186
185
|
determine_next_command_and_inputs(retries - 1, outcome)
|
186
|
+
# :nocov:
|
187
187
|
end
|
188
188
|
else
|
189
189
|
self.next_command_inputs = {}
|
@@ -260,23 +260,7 @@ module Foobara
|
|
260
260
|
end
|
261
261
|
|
262
262
|
def run_next_command
|
263
|
-
|
264
|
-
args = if next_command_inputs.nil? || next_command_inputs.empty?
|
265
|
-
""
|
266
|
-
else
|
267
|
-
s = next_command_inputs.to_s
|
268
|
-
|
269
|
-
if s =~ /\A\{(.*)}\z/
|
270
|
-
"(#{::Regexp.last_match(1)})"
|
271
|
-
else
|
272
|
-
# :nocov:
|
273
|
-
raise "Unexpected next_command_inputs: #{next_command_inputs}"
|
274
|
-
# :nocov:
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
(io_out || $stdout).puts "#{next_command_name}.run#{args}"
|
279
|
-
end
|
263
|
+
log_command_code(command_name: next_command_name, inputs: next_command_inputs)
|
280
264
|
|
281
265
|
self.command_response = agent.run(
|
282
266
|
full_command_name: next_command_name,
|
@@ -286,19 +270,7 @@ module Foobara
|
|
286
270
|
|
287
271
|
self.command_outcome = command_response.outcome
|
288
272
|
|
289
|
-
|
290
|
-
unless command_outcome.success?
|
291
|
-
# :nocov:
|
292
|
-
(io_err || $stderr).puts(
|
293
|
-
"Command #{command_response.command.class.full_command_name} failed #{command_outcome.errors_hash}"
|
294
|
-
)
|
295
|
-
# :nocov:
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
def log_last_command_outcome
|
301
|
-
log_command_outcome(command: command_response.command)
|
273
|
+
log_command_outcome(command: command_response.command, log_command_code: false)
|
302
274
|
end
|
303
275
|
|
304
276
|
def compact_command_log
|
@@ -337,13 +309,14 @@ module Foobara
|
|
337
309
|
next unless last_success
|
338
310
|
|
339
311
|
failure_indexes.each do |failure_index|
|
312
|
+
# TODO: test this path
|
313
|
+
# :nocov:
|
340
314
|
if failure_index < last_success
|
341
315
|
indexes_to_delete << failure_index
|
342
316
|
else
|
343
|
-
# :nocov:
|
344
317
|
break
|
345
|
-
# :nocov:
|
346
318
|
end
|
319
|
+
# :nocov:
|
347
320
|
end
|
348
321
|
end
|
349
322
|
|
@@ -377,7 +350,12 @@ module Foobara
|
|
377
350
|
end
|
378
351
|
end
|
379
352
|
|
380
|
-
def log_command_outcome(command: nil,
|
353
|
+
def log_command_outcome(command: nil,
|
354
|
+
command_name: nil,
|
355
|
+
inputs: nil,
|
356
|
+
outcome: nil,
|
357
|
+
result: nil,
|
358
|
+
log_command_code: true)
|
381
359
|
if command
|
382
360
|
command_name ||= command.class.full_command_name
|
383
361
|
inputs ||= command.raw_inputs
|
@@ -405,6 +383,43 @@ module Foobara
|
|
405
383
|
)
|
406
384
|
|
407
385
|
context.command_log << log_entry
|
386
|
+
|
387
|
+
if verbose?
|
388
|
+
if log_command_code
|
389
|
+
# TODO: test this code path hmmm
|
390
|
+
# :nocov:
|
391
|
+
self.log_command_code(command_name:, inputs:)
|
392
|
+
# :nocov:
|
393
|
+
end
|
394
|
+
|
395
|
+
unless log_entry.success?
|
396
|
+
# :nocov:
|
397
|
+
(io_err || $stderr).puts(
|
398
|
+
"Command #{log_entry.command_name} failed:\n#{log_entry.errors_hash}"
|
399
|
+
)
|
400
|
+
# :nocov:
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def log_command_code(command_name:, inputs:)
|
406
|
+
if verbose?
|
407
|
+
args = if next_command_inputs.nil? || next_command_inputs.empty?
|
408
|
+
""
|
409
|
+
else
|
410
|
+
s = next_command_inputs.to_s
|
411
|
+
|
412
|
+
if s =~ /\A\{(.*)}\z/
|
413
|
+
"(#{::Regexp.last_match(1)})"
|
414
|
+
else
|
415
|
+
# :nocov:
|
416
|
+
raise "Unexpected next_command_inputs: #{next_command_inputs}"
|
417
|
+
# :nocov:
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
(io_out || $stdout).puts "#{next_command_name}.run#{args}"
|
422
|
+
end
|
408
423
|
end
|
409
424
|
|
410
425
|
# TODO: these are awkwardly called from outside. Come up with a better solution.
|
@@ -442,6 +457,20 @@ module Foobara
|
|
442
457
|
verbose
|
443
458
|
end
|
444
459
|
|
460
|
+
def need_to_describe_next_command?
|
461
|
+
return false if command_described?(next_command_name)
|
462
|
+
return false if next_command_name == DescribeCommand.full_command_name
|
463
|
+
return true if next_command_has_inputs?
|
464
|
+
|
465
|
+
# check if inputs were unexpectedly given for a command that doesn't need them,
|
466
|
+
# in which case we should describe it
|
467
|
+
next_command_inputs && !next_command_inputs.empty?
|
468
|
+
end
|
469
|
+
|
470
|
+
def command_described?(command_name)
|
471
|
+
described_commands.include?(command_name)
|
472
|
+
end
|
473
|
+
|
445
474
|
def llm_call_timestamps
|
446
475
|
@llm_call_timestamps ||= []
|
447
476
|
end
|
@@ -1,15 +1,18 @@
|
|
1
1
|
module Foobara
|
2
2
|
class Agent < CommandConnector
|
3
|
+
# NOTE: we intentionally don't use a result type here
|
4
|
+
# to reduce tokens the LLM has to deal with when this command is described
|
3
5
|
class NotifyUserThatCurrentGoalHasBeenAccomplished < Foobara::Command
|
4
6
|
extend Concerns::SubclassCacheable
|
5
7
|
|
6
8
|
class << self
|
7
|
-
attr_accessor :command_class
|
9
|
+
attr_accessor :command_class, :returns_message_to_user, :returns_result_data, :result_is_attributes,
|
10
|
+
:built_result_type
|
8
11
|
|
9
|
-
def for(agent_id: nil, result_type: nil, include_message_to_user_in_result: true)
|
12
|
+
def for(agent_id: nil, result_type: nil, include_message_to_user_in_result: true, result_entity_depth: nil)
|
10
13
|
agent_id ||= "Anon#{SecureRandom.hex(2)}"
|
11
14
|
|
12
|
-
cached_subclass([
|
15
|
+
cached_subclass([agent_id]) do
|
13
16
|
command_name = "Foobara::Agent::#{agent_id}::NotifyUserThatCurrentGoalHasBeenAccomplished"
|
14
17
|
klass = Util.make_class_p(command_name, self)
|
15
18
|
|
@@ -19,41 +22,50 @@ module Foobara
|
|
19
22
|
"The user might issue a new goal."
|
20
23
|
|
21
24
|
if result_type
|
25
|
+
klass.returns_result_data = true
|
26
|
+
unless result_type.is_a?(Types::Type)
|
27
|
+
result_type = Domain.current.foobara_type_from_declaration(result_type)
|
28
|
+
end
|
29
|
+
|
30
|
+
domain = result_type.created_in_namespace.foobara_domain
|
31
|
+
|
22
32
|
# TODO: fix this... agent backed command sets these via its own result type.
|
23
33
|
# check if message_to_user is already here and also search/fix result_data to be result for consistency.
|
24
34
|
if include_message_to_user_in_result
|
25
|
-
klass.
|
26
|
-
result result_type, :required
|
27
|
-
message_to_user :string, :required, "Message to the user about what was done"
|
28
|
-
end
|
35
|
+
klass.returns_message_to_user = true
|
29
36
|
|
30
|
-
klass.
|
37
|
+
klass.built_result_type = domain.foobara_type_from_declaration do
|
31
38
|
result result_type, :required
|
32
39
|
message_to_user :string, :required, "Message to the user about what was done"
|
33
40
|
end
|
34
41
|
|
42
|
+
klass.add_inputs klass.built_result_type
|
43
|
+
|
35
44
|
klass.description "Notifies the user that the current goal has been accomplished and returns a final " \
|
36
45
|
"result formatted according to the " \
|
37
46
|
"result schema and a message to the user. " \
|
38
47
|
"The user might issue a new goal."
|
39
48
|
else
|
40
|
-
|
41
|
-
|
49
|
+
if result_type.extends?(BuiltinTypes[:attributes])
|
50
|
+
klass.built_result_type = result_type
|
51
|
+
klass.result_is_attributes = true
|
52
|
+
klass.add_inputs result_type
|
53
|
+
else
|
54
|
+
klass.built_result_type = domain.foobara_type_from_declaration do
|
55
|
+
result result_type, :required
|
56
|
+
end
|
57
|
+
klass.add_inputs klass.built_result_type
|
42
58
|
end
|
43
59
|
|
44
|
-
klass.result result_type
|
45
|
-
|
46
60
|
klass.description "Notifies the user that the current goal has been accomplished and returns a final " \
|
47
61
|
"result formatted according to the " \
|
48
62
|
"result schema. " \
|
49
63
|
"The user might issue a new goal."
|
50
64
|
end
|
51
65
|
elsif include_message_to_user_in_result
|
52
|
-
klass.
|
53
|
-
message_to_user :string, :required, "Message to the user about what was done"
|
54
|
-
end
|
66
|
+
klass.returns_message_to_user = true
|
55
67
|
|
56
|
-
klass.
|
68
|
+
klass.add_inputs do
|
57
69
|
message_to_user :string, :required, "Message to the user about what was done"
|
58
70
|
end
|
59
71
|
|
@@ -68,9 +80,46 @@ module Foobara
|
|
68
80
|
# :nocov:
|
69
81
|
end
|
70
82
|
|
83
|
+
apply_result_data_transformer(klass, result_entity_depth)
|
84
|
+
|
71
85
|
klass
|
72
86
|
end
|
73
87
|
end
|
88
|
+
|
89
|
+
def result_data_transformer(result_entity_depth)
|
90
|
+
if result_entity_depth
|
91
|
+
case result_entity_depth
|
92
|
+
when AssociationDepth::AGGREGATE
|
93
|
+
CommandConnectors::Transformers::LoadAggregatesTransformer
|
94
|
+
when AssociationDepth::ATOM
|
95
|
+
CommandConnectors::Transformers::LoadAtomsTransformer
|
96
|
+
else
|
97
|
+
# :nocov:
|
98
|
+
raise "Unsupported result entity depth: #{result_entity_depth}"
|
99
|
+
# :nocov:
|
100
|
+
end&.instance
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def apply_result_data_transformer(command_klass, result_entity_depth)
|
105
|
+
transformer = result_data_transformer(result_entity_depth)
|
106
|
+
return unless transformer
|
107
|
+
|
108
|
+
inputs_type = command_klass.inputs_type
|
109
|
+
return unless inputs_type
|
110
|
+
|
111
|
+
if inputs_type.extends?(BuiltinTypes[:detached_entity]) ||
|
112
|
+
DetachedEntity.contains_associations?(inputs_type)
|
113
|
+
command_klass.before_commit_transaction do |command:, **|
|
114
|
+
# TODO: why can't we just pass in the command??
|
115
|
+
built_result = command.built_result
|
116
|
+
|
117
|
+
if built_result
|
118
|
+
transformer.process_value!(built_result)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
74
123
|
end
|
75
124
|
|
76
125
|
description "Ends the session giving a final result formatted according to the " \
|
@@ -81,24 +130,46 @@ module Foobara
|
|
81
130
|
end
|
82
131
|
|
83
132
|
def execute
|
133
|
+
build_result
|
84
134
|
mark_mission_accomplished
|
85
135
|
|
86
|
-
|
136
|
+
nil
|
87
137
|
end
|
88
138
|
|
139
|
+
attr_accessor :built_result
|
140
|
+
|
89
141
|
def mark_mission_accomplished
|
90
|
-
|
142
|
+
result, message_to_user = if returns_message_to_user?
|
143
|
+
[built_result[:result], built_result[:message_to_user]]
|
144
|
+
elsif returns_result_data?
|
145
|
+
[built_result, nil]
|
146
|
+
end
|
147
|
+
|
148
|
+
command_connector.mark_mission_accomplished(result, message_to_user)
|
91
149
|
end
|
92
150
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
151
|
+
def build_result
|
152
|
+
self.built_result = if returns_message_to_user?
|
153
|
+
inputs.slice(:result, :message_to_user)
|
154
|
+
elsif returns_result_data?
|
155
|
+
if result_is_attributes?
|
156
|
+
inputs.slice(*self.class.built_result_type.element_types.keys)
|
157
|
+
else
|
158
|
+
inputs[:result]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
96
162
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
163
|
+
def returns_message_to_user?
|
164
|
+
self.class.returns_message_to_user
|
165
|
+
end
|
166
|
+
|
167
|
+
def returns_result_data?
|
168
|
+
self.class.returns_result_data
|
169
|
+
end
|
170
|
+
|
171
|
+
def result_is_attributes?
|
172
|
+
self.class.result_is_attributes
|
102
173
|
end
|
103
174
|
end
|
104
175
|
end
|
@@ -11,6 +11,17 @@ module Foobara
|
|
11
11
|
errors_hash :duck, "Errors that occurred during the command"
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
def success?
|
16
|
+
outcome[:success]
|
17
|
+
end
|
18
|
+
|
19
|
+
def errors_hash
|
20
|
+
# TODO: test this path
|
21
|
+
# :nocov:
|
22
|
+
outcome[:errors_hash]
|
23
|
+
# :nocov:
|
24
|
+
end
|
14
25
|
end
|
15
26
|
end
|
16
27
|
end
|
data/src/foobara/agent.rb
CHANGED
@@ -23,7 +23,8 @@ module Foobara
|
|
23
23
|
:verbose,
|
24
24
|
:io_out,
|
25
25
|
:io_err,
|
26
|
-
:max_llm_calls_per_minute
|
26
|
+
:max_llm_calls_per_minute,
|
27
|
+
:result_entity_depth
|
27
28
|
|
28
29
|
def initialize(
|
29
30
|
context: nil,
|
@@ -36,18 +37,20 @@ module Foobara
|
|
36
37
|
io_out: nil,
|
37
38
|
io_err: nil,
|
38
39
|
max_llm_calls_per_minute: nil,
|
40
|
+
result_entity_depth: AssociationDepth::AGGREGATE,
|
39
41
|
**opts
|
40
42
|
)
|
41
43
|
# TODO: shouldn't have to pass command_log here since it has a default, debug that
|
42
44
|
self.context = context
|
43
45
|
self.agent_name = agent_name || "Anon#{SecureRandom.hex(2)}"
|
44
|
-
self.llm_model = llm_model
|
46
|
+
self.llm_model = llm_model || "claude-opus-4-20250514"
|
45
47
|
self.result_type = result_type
|
46
48
|
self.include_message_to_user_in_result = include_message_to_user_in_result
|
47
49
|
self.verbose = verbose
|
48
50
|
self.io_out = io_out
|
49
51
|
self.io_err = io_err
|
50
52
|
self.max_llm_calls_per_minute = max_llm_calls_per_minute
|
53
|
+
self.result_entity_depth = result_entity_depth
|
51
54
|
|
52
55
|
# unless opts.key?(:default_serializers)
|
53
56
|
# opts = opts.merge(default_serializers: [
|
@@ -140,42 +143,7 @@ module Foobara
|
|
140
143
|
state_machine.perform_transition!(:accomplish_goal)
|
141
144
|
|
142
145
|
begin
|
143
|
-
inputs =
|
144
|
-
goal:,
|
145
|
-
final_result_type: self.result_type,
|
146
|
-
context:,
|
147
|
-
agent: self
|
148
|
-
}
|
149
|
-
|
150
|
-
llm_model ||= self.llm_model
|
151
|
-
|
152
|
-
if llm_model
|
153
|
-
inputs[:llm_model] = llm_model
|
154
|
-
end
|
155
|
-
|
156
|
-
unless maximum_call_count.nil?
|
157
|
-
inputs[:maximum_command_calls] = maximum_call_count
|
158
|
-
end
|
159
|
-
|
160
|
-
if verbose
|
161
|
-
inputs[:verbose] = verbose
|
162
|
-
end
|
163
|
-
|
164
|
-
if io_out
|
165
|
-
inputs[:io_out] = io_out
|
166
|
-
end
|
167
|
-
|
168
|
-
if io_err
|
169
|
-
inputs[:io_err] = io_err
|
170
|
-
end
|
171
|
-
|
172
|
-
if include_message_to_user_in_result || include_message_to_user_in_result == false
|
173
|
-
inputs[:include_message_to_user_in_result] = include_message_to_user_in_result
|
174
|
-
end
|
175
|
-
|
176
|
-
if max_llm_calls_per_minute && max_llm_calls_per_minute > 0
|
177
|
-
inputs[:max_llm_calls_per_minute] = max_llm_calls_per_minute
|
178
|
-
end
|
146
|
+
inputs = accomplish_goal_inputs(goal, result_type:, maximum_call_count:, llm_model:)
|
179
147
|
|
180
148
|
self.current_accomplish_goal_command = AccomplishGoal.new(inputs)
|
181
149
|
|
@@ -196,6 +164,54 @@ module Foobara
|
|
196
164
|
end
|
197
165
|
end
|
198
166
|
|
167
|
+
def accomplish_goal_inputs(goal,
|
168
|
+
result_type: nil,
|
169
|
+
maximum_call_count: nil,
|
170
|
+
llm_model: nil)
|
171
|
+
inputs = {
|
172
|
+
goal:,
|
173
|
+
final_result_type: self.result_type,
|
174
|
+
context:,
|
175
|
+
agent: self
|
176
|
+
}
|
177
|
+
|
178
|
+
llm_model ||= self.llm_model
|
179
|
+
|
180
|
+
if llm_model
|
181
|
+
inputs[:llm_model] = llm_model
|
182
|
+
end
|
183
|
+
|
184
|
+
unless maximum_call_count.nil?
|
185
|
+
inputs[:maximum_command_calls] = maximum_call_count
|
186
|
+
end
|
187
|
+
|
188
|
+
if verbose
|
189
|
+
inputs[:verbose] = verbose
|
190
|
+
end
|
191
|
+
|
192
|
+
if io_out
|
193
|
+
inputs[:io_out] = io_out
|
194
|
+
end
|
195
|
+
|
196
|
+
if io_err
|
197
|
+
inputs[:io_err] = io_err
|
198
|
+
end
|
199
|
+
|
200
|
+
if include_message_to_user_in_result || include_message_to_user_in_result == false
|
201
|
+
inputs[:include_message_to_user_in_result] = include_message_to_user_in_result
|
202
|
+
end
|
203
|
+
|
204
|
+
if max_llm_calls_per_minute && max_llm_calls_per_minute > 0
|
205
|
+
inputs[:max_llm_calls_per_minute] = max_llm_calls_per_minute
|
206
|
+
end
|
207
|
+
|
208
|
+
if result_entity_depth
|
209
|
+
inputs[:result_entity_depth] = result_entity_depth
|
210
|
+
end
|
211
|
+
|
212
|
+
inputs
|
213
|
+
end
|
214
|
+
|
199
215
|
def set_context_goal(goal)
|
200
216
|
if context
|
201
217
|
context.set_new_goal(goal)
|
@@ -232,7 +248,8 @@ module Foobara
|
|
232
248
|
result_type:,
|
233
249
|
agent_id: agent_name,
|
234
250
|
# TODO: Support changing this flag when the goal changes
|
235
|
-
include_message_to_user_in_result
|
251
|
+
include_message_to_user_in_result:,
|
252
|
+
result_entity_depth:
|
236
253
|
)
|
237
254
|
else
|
238
255
|
NotifyUserThatCurrentGoalHasBeenAccomplished
|