Class: LLM::Tool::Exec

Inherits:
LLM::Tool show all
Includes:
Utils, Utils::Process
Defined in:
lib/llm/tools/exec.rb

Overview

The LLM::Tool::Exec tool spawns a command without a shell. It can be used both directly and indirectly, and multiple other llm.rb tools are built on top of this one.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

#name_of, #normalize_base_path, #object_id, #record?, #resolve_option, #timestamp, #uuidv7?

Methods inherited from LLM::Tool

NotFound, a2a, a2a?, #a2a?, abstract!, abstract?, clear_registry!, description, find_by_name!, #function, function, inherited, mcp, #mcp?, mcp?, name, #on_cancel, #on_interrupt, params, register, registry, set, subclasses, unregister

Methods included from Param

#defaults, #param, #required

Methods included from Function::Registry

#clear_registry!, #find_by_name, #lock, #register, #registry, #registry_key, #tool_name, #unregister

Constructor Details

#initialize(env: {}) ⇒ LLM::Tool::Exec

Parameters:

  • env (Hash) (defaults to: {}) —

    Extra environment variables to set for the command. This is configuration for the tool instance, not a model-provided parameter.



44
45
46
# File 'lib/llm/tools/exec.rb', line 44

def initialize(env: {})
  @env = env
end

Class Method Details

.max_bytes(bytes = UNDEFINED) ⇒ Integer

Returns (or sets) the advisory maximum number of bytes this tool returns to the model.

Parameters:

  • bytes (Integer, nil) (defaults to: UNDEFINED) —

    When given, sets the maximum

Returns:

  • (Integer)


30
31
32
33
34
35
36
# File 'lib/llm/tools/exec.rb', line 30

def self.max_bytes(bytes = UNDEFINED)
  if bytes.equal?(UNDEFINED)
    @max_bytes || 75_000
  else
    @max_bytes = bytes
  end
end

Instance Method Details

#call(command:, arguments: [], timeout: 60, max_bytes: self.class.max_bytes) ⇒ Hash

Parameters:

  • command (String) —

    The command to run

  • arguments (Array<String>) (defaults to: []) —

    One or more arguments for the command

  • timeout (Integer) (defaults to: 60) —

    The maximum allowed time for the command to run (in seconds)

  • max_bytes (Integer) (defaults to: self.class.max_bytes) —

    the max number of bytes to emit

Returns:

  • (Hash)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/llm/tools/exec.rb', line 58

def call(command:, arguments: [], timeout: 60, max_bytes: self.class.max_bytes)
  startat = now
  spawned = spawn(command:, arguments:, env:, max_bytes:)
  killed = catch(:kill) { [wait(command: spawned, timeout:), nil].last }
  if spawned.not_found?
    {ok: false, error: "command '#{command}' was not found on this system"}
  else
    {ok: spawned.success?,
    stdout: truncate(spawned.stdout, max_bytes:),
    stderr: truncate(spawned.stderr, max_bytes:),
    duration: "#{(now - startat).round(1)} seconds",
    note: killed ? "The command was killed after "            \
                   "exceeding the #{timeout}s timeout. "      \
                   "stdout and stderr are what it produced "  \
                   "before it was killed and both streams "   \
                   "are probably incomplete." : nil
    }.compact
  end
rescue LLM::Interrupt
  spawned.kill! if spawned&.running?
  raise
end