foobara-agent 0.0.2 → 0.0.4
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 +17 -0
- data/lib/foobara/agent.rb +1 -1
- data/src/foobara/agent/accomplish_goal.rb +51 -24
- data/src/foobara/agent/concerns/subclass_cacheable.rb +1 -1
- data/src/foobara/agent/connector/set_command_connector_inputs_transformer.rb +1 -1
- data/src/foobara/agent/describe_command.rb +2 -2
- data/src/foobara/agent/describe_type.rb +1 -1
- data/src/foobara/agent/determine_inputs_for_next_command.rb +2 -2
- data/src/foobara/agent/determine_next_command.rb +11 -2
- data/src/foobara/agent/determine_next_command_name_and_inputs.rb +8 -4
- data/src/foobara/agent/give_up.rb +1 -1
- data/src/foobara/agent/list_commands.rb +1 -1
- data/src/foobara/agent/list_types.rb +1 -1
- data/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb +2 -1
- data/src/foobara/agent/types/command_log_entry.rb +1 -1
- data/src/foobara/agent/types/context.rb +1 -1
- data/src/foobara/agent.rb +147 -33
- metadata +1 -2
- data/src/foobara/agent/connector/connector.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc0affa9f2a80a45d94dbcde1ad4ba5f173d0e3aa91076d91147058e5e1c6829
|
4
|
+
data.tar.gz: 40f0e2ed19b6e95a0b325e54eb624b15d3cde7eeda9cfe325626bee5a347f001
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 716dbb353942408388d6a8e28f87c54911f44d067f398d8c224bbed7e926adc63eae816cea9d40f5acd7ccab478421319c542d2d28e9451996775fcd6ec5f9e7
|
7
|
+
data.tar.gz: 0e80baab41484b2843ddbbe49a1a9412cce157ed43758af7f621f8dc7c99d94d02e0767b92cbe069d5396373e561ee03da4b510e94cb1ddcc86b738b413d203c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
## [0.0.4] - 2025-05-30
|
2
|
+
|
3
|
+
- Refactor agent to be a command connector
|
4
|
+
|
5
|
+
## [0.0.3] - 2025-05-30
|
6
|
+
|
7
|
+
- Increase the retries, attempt to improve command descriptions,
|
8
|
+
and attempt to improve the information stored in the context/command log
|
9
|
+
- Add some safeguards around changing the result type too late in the process
|
10
|
+
- Add an agent state machine and a kill! method
|
11
|
+
|
12
|
+
## [0.0.2] - 2025-05-27
|
13
|
+
|
14
|
+
- Add maximum_call_count option
|
15
|
+
- Try getting the command and inputs together to reduce calls
|
16
|
+
- Tweaks to algorithms and improvements to what is stored in context/command_log
|
17
|
+
|
1
18
|
## [0.0.1] - 2025-05-21
|
2
19
|
|
3
20
|
- Initial release
|
data/lib/foobara/agent.rb
CHANGED
@@ -2,7 +2,7 @@ require_relative "list_commands"
|
|
2
2
|
|
3
3
|
module Foobara
|
4
4
|
# TODO: should agent maybe be a command connector? It feels a bit more like a command connector.
|
5
|
-
class Agent
|
5
|
+
class Agent < CommandConnector
|
6
6
|
class AccomplishGoal < Foobara::Command
|
7
7
|
possible_error :gave_up, context: { reason: :string }, message: "Gave up."
|
8
8
|
possible_error :too_many_command_calls,
|
@@ -62,7 +62,8 @@ module Foobara
|
|
62
62
|
connect_agent_commands
|
63
63
|
end
|
64
64
|
|
65
|
-
until mission_accomplished or given_up
|
65
|
+
until mission_accomplished or given_up
|
66
|
+
check_if_too_many_calls
|
66
67
|
if choose_next_command_and_next_inputs_separately?
|
67
68
|
determine_next_command_then_inputs_separately
|
68
69
|
else
|
@@ -71,7 +72,6 @@ module Foobara
|
|
71
72
|
|
72
73
|
run_next_command
|
73
74
|
log_last_command_outcome
|
74
|
-
check_if_too_many_calls
|
75
75
|
end
|
76
76
|
|
77
77
|
if given_up
|
@@ -115,19 +115,17 @@ module Foobara
|
|
115
115
|
@command_connector ||= existing_command_connector
|
116
116
|
end
|
117
117
|
|
118
|
+
# Do we really want to support calling AccomplishGoal outside the context of an Agent?
|
119
|
+
# If not, just delete this awkward coupling
|
118
120
|
def build_command_connector
|
119
|
-
self.command_connector ||=
|
120
|
-
|
121
|
-
default_serializers: [
|
122
|
-
Foobara::CommandConnectors::Serializers::ErrorsSerializer,
|
123
|
-
Foobara::CommandConnectors::Serializers::AtomicSerializer
|
124
|
-
],
|
121
|
+
self.command_connector ||= Agent.new(
|
122
|
+
current_accomplish_goal_command: self,
|
125
123
|
llm_model:
|
126
124
|
)
|
127
125
|
end
|
128
126
|
|
129
127
|
def set_accomplished_goal_command
|
130
|
-
command_connector.
|
128
|
+
command_connector.current_accomplish_goal_command = self
|
131
129
|
end
|
132
130
|
|
133
131
|
def connect_agent_commands
|
@@ -140,7 +138,7 @@ module Foobara
|
|
140
138
|
end
|
141
139
|
end
|
142
140
|
|
143
|
-
def determine_next_command_and_inputs(retries =
|
141
|
+
def determine_next_command_and_inputs(retries = 2)
|
144
142
|
if context.command_log.empty?
|
145
143
|
self.next_command_name = ListCommands.full_command_name
|
146
144
|
self.next_command_inputs = nil
|
@@ -157,7 +155,13 @@ module Foobara
|
|
157
155
|
|
158
156
|
determine_command = DetermineNextCommandNameAndInputs.new(inputs_for_determine)
|
159
157
|
|
160
|
-
outcome =
|
158
|
+
outcome = begin
|
159
|
+
determine_command.run
|
160
|
+
rescue CommandPatternImplementation::Concerns::Result::CouldNotProcessResult => e
|
161
|
+
# :nocov:
|
162
|
+
Outcome.errors(e.errors)
|
163
|
+
# :nocov:
|
164
|
+
end
|
161
165
|
|
162
166
|
if outcome.success?
|
163
167
|
self.next_command_name = outcome.result[:command_name]
|
@@ -182,7 +186,8 @@ module Foobara
|
|
182
186
|
log_command_outcome(
|
183
187
|
command: determine_command,
|
184
188
|
inputs: determine_command.inputs.except(:context),
|
185
|
-
outcome
|
189
|
+
outcome:,
|
190
|
+
result: outcome.result || determine_command.raw_result
|
186
191
|
)
|
187
192
|
|
188
193
|
determine_next_command_inputs
|
@@ -194,7 +199,8 @@ module Foobara
|
|
194
199
|
log_command_outcome(
|
195
200
|
command: determine_command,
|
196
201
|
inputs: determine_command.inputs&.except(:context),
|
197
|
-
outcome
|
202
|
+
outcome:,
|
203
|
+
result: outcome.result || determine_command.raw_result
|
198
204
|
)
|
199
205
|
|
200
206
|
if retries > 0
|
@@ -207,7 +213,8 @@ module Foobara
|
|
207
213
|
log_command_outcome(
|
208
214
|
command_name: determine_command.class.full_command_name,
|
209
215
|
inputs: determine_command.inputs&.except(:context),
|
210
|
-
outcome
|
216
|
+
outcome:,
|
217
|
+
result: outcome.result || determine_command.raw_result
|
211
218
|
)
|
212
219
|
|
213
220
|
if retries > 0
|
@@ -258,7 +265,7 @@ module Foobara
|
|
258
265
|
@command_name_type ||= Agent.foobara_type_from_declaration(:string, one_of: all_command_classes)
|
259
266
|
end
|
260
267
|
|
261
|
-
def determine_next_command_name(retries =
|
268
|
+
def determine_next_command_name(retries = 2)
|
262
269
|
self.next_command_name = if context.command_log.empty?
|
263
270
|
ListCommands.full_command_name
|
264
271
|
elsif delayed_command_name
|
@@ -276,13 +283,20 @@ module Foobara
|
|
276
283
|
end
|
277
284
|
|
278
285
|
command = command_class.new(inputs)
|
279
|
-
outcome =
|
286
|
+
outcome = begin
|
287
|
+
command.run
|
288
|
+
rescue CommandPatternImplementation::Concerns::Result::CouldNotProcessResult => e
|
289
|
+
# :nocov:
|
290
|
+
Outcome.errors(e.errors)
|
291
|
+
# :nocov:
|
292
|
+
end
|
280
293
|
|
281
294
|
if outcome.success?
|
282
295
|
if log_successful_determine_command_and_inputs_outcomes?
|
283
296
|
log_command_outcome(
|
284
297
|
command:,
|
285
|
-
inputs: command.inputs.except(:context)
|
298
|
+
inputs: command.inputs.except(:context),
|
299
|
+
outcome:
|
286
300
|
)
|
287
301
|
end
|
288
302
|
else
|
@@ -290,7 +304,9 @@ module Foobara
|
|
290
304
|
# :nocov:
|
291
305
|
log_command_outcome(
|
292
306
|
command:,
|
293
|
-
inputs: command.inputs.except(:context)
|
307
|
+
inputs: command.inputs.except(:context),
|
308
|
+
outcome:,
|
309
|
+
result: outcome.result || command.raw_result
|
294
310
|
)
|
295
311
|
|
296
312
|
if retries > 0
|
@@ -318,7 +334,7 @@ module Foobara
|
|
318
334
|
self.next_command_class = command_connector.transformed_command_from_name(next_command_name)
|
319
335
|
end
|
320
336
|
|
321
|
-
def determine_next_command_inputs(retries =
|
337
|
+
def determine_next_command_inputs(retries = 2)
|
322
338
|
self.next_command_inputs = if next_command_has_inputs?
|
323
339
|
command_class = command_class_for_determine_inputs_for_next_command
|
324
340
|
|
@@ -328,13 +344,20 @@ module Foobara
|
|
328
344
|
end
|
329
345
|
|
330
346
|
command = command_class.new(inputs)
|
331
|
-
outcome =
|
347
|
+
outcome = begin
|
348
|
+
command.run
|
349
|
+
rescue CommandPatternImplementation::Concerns::Result::CouldNotProcessResult => e
|
350
|
+
# :nocov:
|
351
|
+
Outcome.errors(e.errors)
|
352
|
+
# :nocov:
|
353
|
+
end
|
332
354
|
|
333
355
|
if outcome.success?
|
334
356
|
if log_successful_determine_command_and_inputs_outcomes?
|
335
357
|
log_command_outcome(
|
336
358
|
command:,
|
337
|
-
inputs: command.inputs.except(:context)
|
359
|
+
inputs: command.inputs.except(:context),
|
360
|
+
outcome:
|
338
361
|
)
|
339
362
|
end
|
340
363
|
else
|
@@ -342,7 +365,9 @@ module Foobara
|
|
342
365
|
# :nocov:
|
343
366
|
log_command_outcome(
|
344
367
|
command:,
|
345
|
-
inputs: command.inputs.except(:context)
|
368
|
+
inputs: command.inputs.except(:context),
|
369
|
+
outcome:,
|
370
|
+
result: outcome.result || command.raw_result
|
346
371
|
)
|
347
372
|
if retries > 0
|
348
373
|
return determine_next_command_inputs(retries - 1)
|
@@ -409,11 +434,13 @@ module Foobara
|
|
409
434
|
outcome_hash[:errors_hash] = outcome.errors_hash
|
410
435
|
end
|
411
436
|
|
412
|
-
|
437
|
+
log_entry = CommandLogEntry.new(
|
413
438
|
command_name:,
|
414
439
|
inputs:,
|
415
440
|
outcome: outcome_hash
|
416
441
|
)
|
442
|
+
|
443
|
+
context.command_log << log_entry
|
417
444
|
end
|
418
445
|
|
419
446
|
# TODO: these are awkwardly called from outside. Come up with a better solution.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Foobara
|
2
|
-
class Agent
|
2
|
+
class Agent < CommandConnector
|
3
3
|
class DescribeCommand < Foobara::Command
|
4
4
|
inputs do
|
5
5
|
command_connector :duck, :required, "Connector to find relevant command in"
|
@@ -52,7 +52,7 @@ module Foobara
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def mark_command_as_described
|
55
|
-
command_connector.
|
55
|
+
command_connector.current_accomplish_goal_command.described_commands << command_class.full_command_name
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "foobara/llm_backed_command"
|
2
2
|
|
3
3
|
module Foobara
|
4
|
-
class Agent
|
4
|
+
class Agent < CommandConnector
|
5
5
|
class DetermineInputsForNextCommand < Foobara::LlmBackedCommand
|
6
6
|
extend Concerns::SubclassCacheable
|
7
7
|
|
@@ -17,7 +17,7 @@ module Foobara
|
|
17
17
|
"accomplishing the goal."
|
18
18
|
|
19
19
|
klass.inputs do
|
20
|
-
goal :string, :required, "
|
20
|
+
goal :string, :required, "The current (possibly already accomplished) goal"
|
21
21
|
context Context, :required, "Context of the progress towards the goal so far"
|
22
22
|
llm_model :string,
|
23
23
|
one_of: Foobara::Ai::AnswerBot::Types::ModelEnum,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "foobara/llm_backed_command"
|
2
2
|
|
3
3
|
module Foobara
|
4
|
-
class Agent
|
4
|
+
class Agent < CommandConnector
|
5
5
|
class DetermineNextCommand < Foobara::LlmBackedCommand
|
6
6
|
extend Concerns::SubclassCacheable
|
7
7
|
|
@@ -12,8 +12,17 @@ module Foobara
|
|
12
12
|
command_name = "Foobara::Agent::#{agent_id}::DetermineNextCommand"
|
13
13
|
klass = Util.make_class_p(command_name, self)
|
14
14
|
|
15
|
+
klass.description "Accepts the current goal, which might already be accomplished, " \
|
16
|
+
"and context of the work " \
|
17
|
+
"so far and returns the name of " \
|
18
|
+
"the next command to run to make progress towards " \
|
19
|
+
"accomplishing the goal. If the goal has already been accomplished then choose the " \
|
20
|
+
"NotifyUserThatCurrentGoalHasBeenAccomplished command."
|
21
|
+
|
15
22
|
klass.inputs do
|
16
|
-
goal :string, :required, "
|
23
|
+
goal :string, :required, "The current goal to accomplish. If the goal has already been accomplished " \
|
24
|
+
"by the previous command runs then choose " \
|
25
|
+
"NotifyUserThatCurrentGoalHasBeenAccomplished to stop the loop."
|
17
26
|
context Context, :required, "Context of progress so far"
|
18
27
|
llm_model :string,
|
19
28
|
one_of: Foobara::Ai::AnswerBot::Types::ModelEnum,
|
@@ -1,14 +1,18 @@
|
|
1
1
|
require "foobara/llm_backed_command"
|
2
2
|
|
3
3
|
module Foobara
|
4
|
-
class Agent
|
4
|
+
class Agent < CommandConnector
|
5
5
|
class DetermineNextCommandNameAndInputs < Foobara::LlmBackedCommand
|
6
|
-
description "Accepts
|
6
|
+
description "Accepts the current goal, which might already be accomplished, and context of the work " \
|
7
|
+
"so far and returns the inputs for " \
|
7
8
|
"the next command to run to make progress towards " \
|
8
|
-
"accomplishing the goal."
|
9
|
+
"accomplishing the goal. If the goal has already been accomplished then choose the " \
|
10
|
+
"NotifyUserThatCurrentGoalHasBeenAccomplished command."
|
9
11
|
|
10
12
|
inputs do
|
11
|
-
goal :string, :required, "
|
13
|
+
goal :string, :required, "The current goal to accomplish. If the goal has already been accomplished " \
|
14
|
+
"by the previous command runs then choose " \
|
15
|
+
"NotifyUserThatCurrentGoalHasBeenAccomplished to stop the loop."
|
12
16
|
context Context, :required, "Context of the progress towards the goal so far"
|
13
17
|
command_class_names [:string], :required
|
14
18
|
llm_model :string,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Foobara
|
2
|
-
class Agent
|
2
|
+
class Agent < CommandConnector
|
3
3
|
class NotifyUserThatCurrentGoalHasBeenAccomplished < Foobara::Command
|
4
4
|
extend Concerns::SubclassCacheable
|
5
5
|
|
@@ -71,6 +71,7 @@ module Foobara
|
|
71
71
|
data = if result_type
|
72
72
|
inputs[:result_data]
|
73
73
|
end
|
74
|
+
|
74
75
|
command_connector.mark_mission_accomplished(data, message_to_user)
|
75
76
|
end
|
76
77
|
|
data/src/foobara/agent.rb
CHANGED
@@ -1,56 +1,140 @@
|
|
1
1
|
module Foobara
|
2
|
-
class Agent
|
3
|
-
|
2
|
+
class Agent < CommandConnector
|
3
|
+
StateMachine = Foobara::StateMachine.for(
|
4
|
+
[:initialized, :idle, :error, :failure] => {
|
5
|
+
kill: :killed,
|
6
|
+
accomplish_goal: :accomplishing_goal
|
7
|
+
},
|
8
|
+
accomplishing_goal: {
|
9
|
+
goal_accomplished: :idle,
|
10
|
+
goal_errored: :error,
|
11
|
+
goal_failed: :failure,
|
12
|
+
kill: :killed
|
13
|
+
}
|
14
|
+
)
|
15
|
+
|
16
|
+
attr_accessor :context,
|
17
|
+
:agent_name,
|
18
|
+
:llm_model,
|
19
|
+
:current_accomplish_goal_command,
|
20
|
+
:result_type,
|
21
|
+
:agent_commands_connected
|
4
22
|
|
5
23
|
def initialize(
|
6
24
|
context: nil,
|
7
25
|
agent_name: nil,
|
8
26
|
command_classes: nil,
|
9
|
-
|
10
|
-
|
27
|
+
llm_model: nil,
|
28
|
+
result_type: nil,
|
29
|
+
current_accomplish_goal_command: nil,
|
30
|
+
**opts
|
11
31
|
)
|
12
32
|
# TODO: shouldn't have to pass command_log here since it has a default, debug that
|
13
33
|
self.context = context
|
14
|
-
self.agent_command_connector = agent_command_connector
|
15
34
|
self.agent_name = agent_name if agent_name
|
16
35
|
self.llm_model = llm_model
|
36
|
+
self.result_type = result_type
|
37
|
+
self.current_accomplish_goal_command = current_accomplish_goal_command
|
38
|
+
|
39
|
+
unless opts.key?(:default_serializers)
|
40
|
+
opts = opts.merge(default_serializers: [
|
41
|
+
Foobara::CommandConnectors::Serializers::ErrorsSerializer,
|
42
|
+
Foobara::CommandConnectors::Serializers::AtomicSerializer
|
43
|
+
])
|
44
|
+
end
|
45
|
+
|
46
|
+
super(**opts)
|
17
47
|
|
18
48
|
build_initial_context
|
19
|
-
build_agent_command_connector
|
20
49
|
|
50
|
+
# TODO: push this convenience method up into base class?
|
21
51
|
command_classes&.each do |command_class|
|
22
|
-
|
52
|
+
connect(command_class)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def run(*args, **)
|
57
|
+
if args.first.is_a?(::String)
|
58
|
+
accomplish_goal(*args, **)
|
59
|
+
else
|
60
|
+
unless agent_commands_connected?
|
61
|
+
connect_agent_commands
|
62
|
+
end
|
63
|
+
|
64
|
+
super
|
23
65
|
end
|
24
66
|
end
|
25
67
|
|
68
|
+
def state_machine
|
69
|
+
@state_machine ||= StateMachine.new
|
70
|
+
end
|
71
|
+
|
72
|
+
def kill!
|
73
|
+
state_machine.perform_transition!(:kill)
|
74
|
+
end
|
75
|
+
|
76
|
+
def killed?
|
77
|
+
state_machine.current_state == :killed
|
78
|
+
end
|
79
|
+
|
26
80
|
def accomplish_goal(
|
27
81
|
goal,
|
28
82
|
result_type: nil,
|
29
83
|
choose_next_command_and_next_inputs_separately: nil,
|
30
84
|
maximum_call_count: nil
|
31
85
|
)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
86
|
+
if result_type && self.result_type != result_type
|
87
|
+
if self.result_type
|
88
|
+
# :nocov:
|
89
|
+
raise ArgumentError, "You can only specify a result type once"
|
90
|
+
# :nocov:
|
91
|
+
elsif agent_commands_connected?
|
92
|
+
# :nocov:
|
93
|
+
raise ArgumentError, "You can't specify a result type this late in the process"
|
94
|
+
# :nocov:
|
95
|
+
else
|
96
|
+
self.result_type = result_type
|
97
|
+
end
|
98
|
+
end
|
38
99
|
|
39
|
-
|
100
|
+
state_machine.perform_transition!(:accomplish_goal)
|
40
101
|
|
41
|
-
|
42
|
-
inputs
|
43
|
-
|
102
|
+
begin
|
103
|
+
inputs = {
|
104
|
+
goal:,
|
105
|
+
final_result_type: self.result_type,
|
106
|
+
current_context: context,
|
107
|
+
existing_command_connector: self,
|
108
|
+
agent_name:
|
109
|
+
}
|
44
110
|
|
45
|
-
|
46
|
-
|
47
|
-
|
111
|
+
if llm_model
|
112
|
+
inputs[:llm_model] = llm_model
|
113
|
+
end
|
48
114
|
|
49
|
-
|
50
|
-
|
51
|
-
|
115
|
+
unless choose_next_command_and_next_inputs_separately.nil?
|
116
|
+
inputs[:choose_next_command_and_next_inputs_separately] = choose_next_command_and_next_inputs_separately
|
117
|
+
end
|
118
|
+
|
119
|
+
unless maximum_call_count.nil?
|
120
|
+
inputs[:maximum_command_calls] = maximum_call_count
|
121
|
+
end
|
52
122
|
|
53
|
-
|
123
|
+
self.current_accomplish_goal_command = AccomplishGoal.new(inputs)
|
124
|
+
|
125
|
+
current_accomplish_goal_command.run.tap do |outcome|
|
126
|
+
if outcome.success?
|
127
|
+
state_machine.perform_transition!(:goal_accomplished)
|
128
|
+
else
|
129
|
+
state_machine.perform_transition!(:goal_errored)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
rescue
|
133
|
+
# :nocov:
|
134
|
+
state_machine.perform_transition!(:goal_failed)
|
135
|
+
raise
|
136
|
+
# :nocov:
|
137
|
+
end
|
54
138
|
end
|
55
139
|
|
56
140
|
def build_initial_context
|
@@ -58,15 +142,45 @@ module Foobara
|
|
58
142
|
self.context ||= Context.new(command_log: [])
|
59
143
|
end
|
60
144
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
145
|
+
def mark_mission_accomplished(final_result, message_to_user)
|
146
|
+
# TODO: this is a pretty awkward way to communicate between commands hmmm...
|
147
|
+
# maybe see if there's a less hacky way to pull this off.
|
148
|
+
current_accomplish_goal_command.mission_accomplished!(final_result, message_to_user)
|
149
|
+
end
|
150
|
+
|
151
|
+
def give_up(reason)
|
152
|
+
current_accomplish_goal_command.give_up!(reason)
|
153
|
+
end
|
154
|
+
|
155
|
+
def agent_commands_connected?
|
156
|
+
agent_commands_connected
|
157
|
+
end
|
158
|
+
|
159
|
+
def connect_agent_commands(final_result_type: nil, agent_name: nil)
|
160
|
+
command_classes = [
|
161
|
+
DescribeCommand,
|
162
|
+
DescribeType,
|
163
|
+
GiveUp,
|
164
|
+
ListCommands,
|
165
|
+
ListTypes
|
166
|
+
]
|
167
|
+
|
168
|
+
command_classes << if final_result_type
|
169
|
+
NotifyUserThatCurrentGoalHasBeenAccomplished.for(
|
170
|
+
result_type: final_result_type,
|
171
|
+
agent_id: agent_name
|
172
|
+
)
|
173
|
+
else
|
174
|
+
NotifyUserThatCurrentGoalHasBeenAccomplished
|
175
|
+
end
|
176
|
+
|
177
|
+
set_command_connector_transformer = SetCommandConnectorInputsTransformer.for(self)
|
178
|
+
|
179
|
+
command_classes.each do |command_class|
|
180
|
+
connect(command_class, inputs: set_command_connector_transformer)
|
181
|
+
end
|
182
|
+
|
183
|
+
self.agent_commands_connected = true
|
70
184
|
end
|
71
185
|
end
|
72
186
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foobara-agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
@@ -51,7 +51,6 @@ files:
|
|
51
51
|
- src/foobara/agent.rb
|
52
52
|
- src/foobara/agent/accomplish_goal.rb
|
53
53
|
- src/foobara/agent/concerns/subclass_cacheable.rb
|
54
|
-
- src/foobara/agent/connector/connector.rb
|
55
54
|
- src/foobara/agent/connector/set_command_connector_inputs_transformer.rb
|
56
55
|
- src/foobara/agent/describe_command.rb
|
57
56
|
- src/foobara/agent/describe_type.rb
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require "foobara/command_connectors"
|
2
|
-
|
3
|
-
module Foobara
|
4
|
-
class Agent
|
5
|
-
class Connector < Foobara::CommandConnector
|
6
|
-
attr_accessor :accomplish_goal_command, :agent_commands_connected, :llm_model
|
7
|
-
|
8
|
-
def initialize(*, accomplish_goal_command:, llm_model: nil, **)
|
9
|
-
self.accomplish_goal_command = accomplish_goal_command
|
10
|
-
self.llm_model = llm_model
|
11
|
-
|
12
|
-
super(*, **)
|
13
|
-
end
|
14
|
-
|
15
|
-
def mark_mission_accomplished(final_result, message_to_user)
|
16
|
-
# TODO: this is a pretty awkward way to communicate between commands hmmm...
|
17
|
-
# maybe see if there's a less hacky way to pull this off.
|
18
|
-
accomplish_goal_command.mission_accomplished!(final_result, message_to_user)
|
19
|
-
end
|
20
|
-
|
21
|
-
def give_up(reason)
|
22
|
-
accomplish_goal_command.give_up!(reason)
|
23
|
-
end
|
24
|
-
|
25
|
-
def agent_commands_connected?
|
26
|
-
agent_commands_connected
|
27
|
-
end
|
28
|
-
|
29
|
-
def connect_agent_commands(final_result_type: nil, agent_name: nil)
|
30
|
-
command_classes = [
|
31
|
-
DescribeCommand,
|
32
|
-
DescribeType,
|
33
|
-
GiveUp,
|
34
|
-
ListCommands,
|
35
|
-
ListTypes
|
36
|
-
]
|
37
|
-
|
38
|
-
command_classes << if final_result_type
|
39
|
-
NotifyUserThatCurrentGoalHasBeenAccomplished.for(
|
40
|
-
result_type: final_result_type,
|
41
|
-
agent_id: agent_name
|
42
|
-
)
|
43
|
-
else
|
44
|
-
NotifyUserThatCurrentGoalHasBeenAccomplished
|
45
|
-
end
|
46
|
-
|
47
|
-
command_classes.each do |command_class|
|
48
|
-
connect(command_class, inputs: set_command_connector_transformer)
|
49
|
-
end
|
50
|
-
|
51
|
-
self.agent_commands_connected = true
|
52
|
-
end
|
53
|
-
|
54
|
-
def set_command_connector_transformer
|
55
|
-
@set_command_connector_transformer ||= SetCommandConnectorInputsTransformer.for(self)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|