Class: Foobara::Agent::NotifyUserThatCurrentGoalHasBeenAccomplished

Inherits:
Command
  • Object
show all
Extended by:
Concerns::SubclassCacheable
Defined in:
foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb

Overview

NOTE: we intentionally don’t use a result type here to reduce tokens the LLM has to deal with when this command is described

Constant Summary

Constants included from TruncatedInspect

TruncatedInspect::MAX_LENGTH

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes included from CommandPatternImplementation::Concerns::Subcommands

#is_subcommand

Attributes included from CommandPatternImplementation::Concerns::Runtime

#exception, #outcome, #raw_result

Attributes included from CommandPatternImplementation::Concerns::Errors

#error_collection

Attributes included from CommandPatternImplementation::Concerns::Inputs

#inputs, #raw_inputs

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Concerns::SubclassCacheable

cached_subclass, clear_subclass_cache, subclass_cache

Methods inherited from Command

install!, reset_all

Methods included from Concern

foobara_class_methods_module_for, foobara_concern?, included

Methods included from CommandPatternImplementation::Concerns::Reflection

#initialize

Methods included from CommandPatternImplementation::Concerns::DomainMappers

#domain_map, #domain_map!, #run_mapped_subcommand!

Methods included from CommandPatternImplementation::Concerns::Subcommands

#run_subcommand!, #subcommand?

Methods included from CommandPatternImplementation::Concerns::Entities

#load_entities, #load_records

Methods included from CommandPatternImplementation::Concerns::Transactions

#relevant_entity_classes

Methods included from NestedTransactionable

#auto_detect_current_transactions, #commit_transaction, #commit_transaction_if_open, #open_transaction, #opened_transactions, #relevant_entity_classes, relevant_entity_classes_for_type, #relevant_entity_classes_for_type, #rollback_transaction, #transactions, #use_transaction, with_needed_transactions_for_type

Methods included from CommandPatternImplementation::Concerns::StateMachine

#state_machine

Methods included from CommandPatternImplementation::Concerns::Callbacks

#state_machine_callback_registry

Methods included from CommandPatternImplementation::Concerns::Runtime

#halt!, #run, #run!, #run_execute, #succeed, #success?, #validate, #validate_records

Methods included from CommandPatternImplementation::Concerns::Errors

#initialize

Methods included from CommandPatternImplementation::Concerns::Inputs

#cast_and_validate_inputs, #initialize, #method_missing, #respond_to_missing?, #respond_to_missing_for_inputs?

Methods included from TruncatedInspect

#inspect, truncating

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Foobara::CommandPatternImplementation::Concerns::Inputs

Class Attribute Details

.built_result_typeObject

Returns the value of attribute built_result_type.



9
10
11
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 9

def built_result_type
  @built_result_type
end

.command_classObject

Returns the value of attribute command_class.



9
10
11
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 9

def command_class
  @command_class
end

.result_is_attributesObject

Returns the value of attribute result_is_attributes.



9
10
11
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 9

def result_is_attributes
  @result_is_attributes
end

.result_is_modelObject

Returns the value of attribute result_is_model.



9
10
11
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 9

def result_is_model
  @result_is_model
end

.returns_message_to_userObject

Returns the value of attribute returns_message_to_user.



9
10
11
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 9

def returns_message_to_user
  @returns_message_to_user
end

.returns_result_dataObject

Returns the value of attribute returns_result_data.



9
10
11
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 9

def returns_result_data
  @returns_result_data
end

Instance Attribute Details

#final_message_to_userObject

Returns the value of attribute final_message_to_user.



157
158
159
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 157

def final_message_to_user
  @final_message_to_user
end

#final_result_dataObject

Returns the value of attribute final_result_data.



157
158
159
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 157

def final_result_data
  @final_result_data
end

Class Method Details

.apply_result_data_transformer(command_klass, result_entity_depth) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 122

def apply_result_data_transformer(command_klass, result_entity_depth)
  transformer = result_data_transformer(result_entity_depth)
  return unless transformer

  inputs_type = command_klass.inputs_type
  return unless inputs_type

  if inputs_type.extends?(BuiltinTypes[:detached_entity]) ||
     DetachedEntity.contains_associations?(inputs_type)
    command_klass.before_commit_transaction do |command:, **|
      # TODO: why can't we just pass in the command??
      built_result = command.final_result_data

      if built_result
        transformer.process_value!(built_result)
      end
    end
  end
end

.for(agent_id: nil, result_type: nil, include_message_to_user_in_result: true, result_entity_depth: nil) ⇒ Object



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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 12

def for(agent_id: nil, result_type: nil, include_message_to_user_in_result: true, result_entity_depth: nil)
  agent_id ||= "Anon#{SecureRandom.hex(2)}"

  cached_subclass([agent_id]) do
    command_name = "Foobara::Agent::#{agent_id}::NotifyUserThatCurrentGoalHasBeenAccomplished"
    klass = Util.make_class_p(command_name, self)

    klass.description "Notifies the user that the current goal has been accomplished and returns a final " \
                      "result formatted according to the " \
                      "result schema and an optional message to the user. " \
                      "The user might issue a new goal."

    if result_type
      klass.returns_result_data = true
      unless result_type.is_a?(Types::Type)
        result_type = Domain.current.foobara_type_from_declaration(result_type)
      end

      domain = result_type.created_in_namespace.foobara_domain

      # TODO: fix this... agent backed command sets these via its own result type.
      # check if message_to_user is already here and also search/fix result_data to be result for consistency.
      if include_message_to_user_in_result
        klass.returns_message_to_user = true

        klass.built_result_type = domain.foobara_type_from_declaration do
          result result_type, :required
          message_to_user :string, :required, "Message to the user about what was done"
        end

        klass.add_inputs klass.built_result_type

        klass.description "Notifies the user that the current goal has been accomplished and returns a final " \
                          "result formatted according to the " \
                          "result schema and a message to the user. " \
                          "The user might issue a new goal."
      else
        if result_type.extends?(BuiltinTypes[:model]) &&
           !result_type.extends?(BuiltinTypes[:detached_entity]) && result_type != BuiltinTypes[:model]
          # TODO: Create a ModelToAttributesInputsTransformer in foobara gem and move this logic there
          model_declaration = result_type.declaration_data

          # Distinguishing between nil and no inputs might be tricky so if :allow_nil then
          # we will prefer `result: nil` over `nil`
          # if there's a description we'll also prefer result: so that the description will
          # make it through to the LLM on that input.
          # TODO: handle the model's description via the command's description instead.
          if !model_declaration.key?(:allow_nil) && !model_declaration.key?(:description)
            klass.built_result_type = result_type
            klass.result_is_model = true
            klass.add_inputs result_type.target_class.attributes_type
          end
        end

        unless klass.result_is_model
          if result_type.extends?(BuiltinTypes[:attributes])
            klass.built_result_type = result_type
            klass.result_is_attributes = true
            klass.add_inputs result_type
          else
            klass.built_result_type = domain.foobara_type_from_declaration do
              result result_type, :required
            end
            klass.add_inputs klass.built_result_type
          end
        end

        klass.description "Notifies the user that the current goal has been accomplished and accepts a final " \
                          "result value as inputs. " \
                          "The user might issue a new goal."
      end
    elsif include_message_to_user_in_result
      klass.returns_message_to_user = true

      klass.add_inputs do
        message_to_user :string, :required, "Message to the user about what was done"
      end

      klass.description "Notifies the user that the current goal has been accomplished and results in a " \
                        "message to the user. " \
                        "The user might issue a new goal."
    else
      # This should be unreachable actually
      # :nocov:
      klass.description "Notifies the user that the current goal has been accomplished. " \
                        "The user might issue a new goal."
      # :nocov:
    end

    apply_result_data_transformer(klass, result_entity_depth)

    klass
  end
end

.result_data_transformer(result_entity_depth) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 107

def result_data_transformer(result_entity_depth)
  if result_entity_depth
    case result_entity_depth
    when AssociationDepth::AGGREGATE
      CommandConnectors::Transformers::LoadAggregatesTransformer
    when AssociationDepth::ATOM
      CommandConnectors::Transformers::LoadAtomsTransformer
    else
      # :nocov:
      raise "Unsupported result entity depth: #{result_entity_depth}"
      # :nocov:
    end&.instance
  end
end

Instance Method Details

#executeObject



150
151
152
153
154
155
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 150

def execute
  extract_result_data_and_message_to_user
  mark_mission_accomplished

  nil
end

#extract_result_data_and_message_to_userObject



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 159

def extract_result_data_and_message_to_user
  result, message = if returns_message_to_user?
                      inputs.values_at(:result, :message_to_user)
                    elsif returns_result_data?
                      if result_is_attributes?
                        inputs.slice(*self.class.built_result_type.element_types.keys)
                      elsif result_is_model?
                        inputs.slice(
                          *self.class.built_result_type.target_class.attributes_type.element_types.keys
                        )
                      else
                        [inputs[:result], nil]
                      end
                    end

  self.final_result_data = result
  self.final_message_to_user = message
end

#mark_mission_accomplishedObject



178
179
180
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 178

def mark_mission_accomplished
  command_connector.mark_mission_accomplished(final_result_data, final_message_to_user)
end

#result_is_attributes?Boolean

Returns:

  • (Boolean)


190
191
192
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 190

def result_is_attributes?
  self.class.result_is_attributes
end

#result_is_model?Boolean

Returns:

  • (Boolean)


194
195
196
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 194

def result_is_model?
  self.class.result_is_model
end

#returns_message_to_user?Boolean

Returns:

  • (Boolean)


182
183
184
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 182

def returns_message_to_user?
  self.class.returns_message_to_user
end

#returns_result_data?Boolean

Returns:

  • (Boolean)


186
187
188
# File 'foobara-agent-0.0.21/src/foobara/agent/notify_user_that_current_goal_has_been_accomplished.rb', line 186

def returns_result_data?
  self.class.returns_result_data
end