Module: Legate::GlobalToolManager

Defined in:
lib/legate/global_tool_manager.rb

Overview

Manages the central registration and discovery of all defined Legate::Tool subclasses. This provides a way to list all available tools without needing a specific ToolRegistry instance (which is tied to an Agent).

Class Method Summary collapse

Class Method Details

.create_instance(name_symbol) ⇒ Legate::Tool?

Create an instance of a tool by its name symbol using the globally registered class.

Parameters:

  • name_symbol (Symbol)

    The symbolic name of the tool.

Returns:

  • (Legate::Tool, nil)

    An instance of the tool or nil if instantiation fails or class not found.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/legate/global_tool_manager.rb', line 111

def self.create_instance(name_symbol)
  klass = find_class(name_symbol.to_sym)

  if klass
    begin
      instance = klass.new
      Legate.logger.debug("GlobalToolManager: Successfully instantiated tool '#{name_symbol}'.")
      instance
    rescue StandardError => e
      Legate.logger.error("GlobalToolManager: Failed to instantiate tool '#{name_symbol}' (Class: #{klass}): #{e.class} - #{e.message}")
      Legate.logger.error(e.backtrace.first(5).join("\n"))
      nil
    end
  else
    Legate.logger.warn("GlobalToolManager: Attempted to create instance of tool '#{name_symbol}' which is not globally registered.")
    nil
  end
end

.find_class(name_symbol) ⇒ Class?

Find a registered tool class by its name symbol.

Parameters:

  • name_symbol (Symbol)

    The symbolic name of the tool.

Returns:

  • (Class, nil)

    The tool class or nil if not found.



98
99
100
# File 'lib/legate/global_tool_manager.rb', line 98

def self.find_class(name_symbol)
  @mutex.synchronize { @defined_tools[name_symbol.to_sym] }
end

.list_all_toolsArray<Hash>

Get a list of all globally registered tools with basic info.

Returns:

  • (Array<Hash>)

    An array of hashes, each with :name and :description.



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/legate/global_tool_manager.rb', line 83

def self.list_all_tools
  snapshot = @mutex.synchronize { @defined_tools.dup }
  snapshot.map do |name_sym, klass|
     = klass.
    {
      name: [:name] || name_sym, # Fallback, though name should always be present if registered
      description: [:description] || '[No description provided]',
      parameters: [:parameters] || []
    }
  end.sort_by { |t| t[:name].to_s }
end

.register_tool(tool_class) ⇒ Object

Register a tool class globally. Called automatically via Legate::Tool.inherited

Parameters:

  • tool_class (Class)

    The tool class to register.



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
# File 'lib/legate/global_tool_manager.rb', line 21

def self.register_tool(tool_class)
  unless tool_class < Legate::Tool
    Legate.logger.warn("GlobalToolManager: Attempted to register non-tool class: #{tool_class.inspect}")
    return
  end

   = tool_class.
  tool_name = [:name]&.to_sym

  # --- Attempt name inference if not found in metadata ---
  # This handles cases where the new DSL isn't used (e.g., old define_metadata)
  # or if the DSL itself couldn't determine a name (e.g., anonymous class)
  if tool_name.nil? || tool_name == :''
    # First, check for the instance variable set by the DEPRECATED define_metadata
    if tool_class.instance_variable_defined?(:@tool_name)
      tool_name = tool_class.instance_variable_get(:@tool_name)
      Legate.logger.debug("GlobalToolManager: Tool class #{tool_class} using name from deprecated @tool_name: #{tool_name.inspect}")
    else
      # If not found via deprecated method, try inference via DSL
      begin
        # Check if the class responds to inferred_name (from MetadataDsl)
        if tool_class.respond_to?(:inferred_name)
          inferred = tool_class.inferred_name
          if inferred
            Legate.logger.debug("GlobalToolManager: Tool class #{tool_class} had no explicit name, using inferred name: #{inferred.inspect}")
            tool_name = inferred
          else
            Legate.logger.warn("GlobalToolManager: Tool class #{tool_class} has no explicit name and inference failed (maybe anonymous?). Skipping registration.")
            return
          end
        else
          # Fallback if MetadataDsl isn't included or something is wrong
          Legate.logger.warn("GlobalToolManager: Tool class #{tool_class} has no name defined via tool_metadata or @tool_name, and does not support inferred_name. Skipping registration.")
          return
        end
      rescue StandardError => e
        Legate.logger.error("GlobalToolManager: Error during name inference for #{tool_class}: #{e.message}")
        return # Don't register if inference itself fails
      end
    end
  end
  # --- End Name Inference Attempt ---

  # Ensure tool_name is a symbol before proceeding
  tool_name = tool_name&.to_sym
  if tool_name.nil? || tool_name == :''
    Legate.logger.error("GlobalToolManager: Could not determine a valid tool name for #{tool_class}. Skipping registration.")
    return
  end

  @mutex.synchronize do
    if @defined_tools.key?(tool_name) && @defined_tools[tool_name] != tool_class
      Legate.logger.warn("GlobalToolManager: Tool name '#{tool_name}' is already registered with class #{@defined_tools[tool_name]}. Overwriting with #{tool_class}.")
    elsif !@defined_tools.key?(tool_name)
      Legate.logger.debug("GlobalToolManager: Registered tool '#{tool_name}' with class #{tool_class}.")
    end
    @defined_tools[tool_name] = tool_class
  end
end

.registered_tool_namesArray<Symbol>

Get the names (symbols) of all registered tools.

Returns:

  • (Array<Symbol>)

    An array of tool name symbols.



104
105
106
# File 'lib/legate/global_tool_manager.rb', line 104

def self.registered_tool_names
  @mutex.synchronize { @defined_tools.keys }
end

.reset!Object

Clears all registered tools. Primarily for testing.



131
132
133
# File 'lib/legate/global_tool_manager.rb', line 131

def self.reset!
  @mutex.synchronize { @defined_tools = {} }
end