Class: LLM::Function::Ractor::Task

Inherits:
Task
  • Object
show all
Defined in:
lib/llm/function/ractor/task.rb

Overview

Wraps a ractor-backed function call.

One ractor runs the tool and hands its result to a Port the task reads. A thread inside the ractor services interrupts, and the port is the only way a result leaves.

Instance Attribute Summary collapse

Attributes inherited from Task

#finished_at, #function, #started_at

Instance Method Summary collapse

Methods inherited from Task

#intercepted?

Constructor Details

#initialize(fn, options = {}) ⇒ LLM::Function::Ractor::Task

Parameters:

Options Hash (options):

  • :tracer (LLM::Tracer, nil)
  • :runner_class (Class)
  • :id (String, nil)
  • :name (String)
  • :arguments (Hash, Array, nil)
  • :model (String, nil)


51
52
53
54
55
56
57
58
59
60
# File 'lib/llm/function/ractor/task.rb', line 51

def initialize(fn, options = {})
  super
  @runner_class = options.fetch(:runner_class)
  @id = options.fetch(:id)
  @name = options.fetch(:name)
  @arguments = options.fetch(:arguments)
  @model = options.fetch(:model, nil)
  @cancelled = false
  @cookie = SecureRandom.hex
end

Instance Attribute Details

#resultp ⇒ Ractor::Port (readonly)

Returns The port the result is delivered to.

Returns:

  • (Ractor::Port) —

    The port the result is delivered to



27
28
29
# File 'lib/llm/function/ractor/task.rb', line 27

def resultp
  @resultp
end

#tracer ⇒ LLM::Tracer? (readonly)

Returns:



31
32
33
# File 'lib/llm/function/ractor/task.rb', line 31

def tracer
  @tracer
end

Returns:

  • (String)


35
36
37
# File 'lib/llm/function/ractor/task.rb', line 35

def cookie
  @cookie
end

#span ⇒ Object (readonly)

Returns:



39
40
41
# File 'lib/llm/function/ractor/task.rb', line 39

def span
  @span
end

Instance Method Details

#spawn ⇒ LLM::Function::Ractor::Task



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/llm/function/ractor/task.rb', line 64

def spawn
  @span = @tracer&.on_tool_start(
    id: @id, name: @name,
    arguments: @arguments, model: @model
  )
  return if intercepted?
  @resultp = Ractor::Port.new
  @exitp = Ractor::Port.new
  @ractor = build_task(@resultp)
  @ractor.monitor(@exitp)
  watch_exit
  if @cancelled
    @cancelled = false
    interrupt!
  end
  self
end

#alive? ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
87
# File 'lib/llm/function/ractor/task.rb', line 84

def alive?
  return false if @result
  @ractor ? !@exited : false
end

#interrupt! ⇒ nil Also known as: cancel!

Tells the tool to stop.

A cancel that arrives before spawn is remembered and delivered by it.

Returns:

  • (nil)


95
96
97
98
99
100
101
102
103
104
# File 'lib/llm/function/ractor/task.rb', line 95

def interrupt!
  if @ractor
    @ractor.send(:interrupt)
  else
    @cancelled = true
  end
  nil
rescue ::Ractor::ClosedError
  nil
end

#wait ⇒ LLM::Function::Return Also known as: value

Reads the result port, which holds the ractor's result or the ending the exit watcher forwarded. Later waits answer from memory.



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/llm/function/ractor/task.rb', line 112

def wait
  return @intercepted if intercepted?
  @result ||= begin
    spawn unless @resultp
    _, ready = Ractor.select(@resultp)
    if ready == EXITED
      Return.new(@id, @name, {error: true, type: "ractor ended without result"})
    else
      _, id, name, value, @finished_at = ready
      if Hash === value and value[:interrupt] and value[:cookie] == @cookie
        LLM::Interrupt.new
      else
        Return.new(id, name, value)
      end
    end
  end
end

#group_class ⇒ Class

Returns:

  • (Class)


133
134
135
# File 'lib/llm/function/ractor/task.rb', line 133

def group_class
  LLM::Function::Ractor::Group
end