Class: LittleGhost::CodeMode::Javascript::Session
- Inherits:
-
Session
- Object
- Session
- LittleGhost::CodeMode::Javascript::Session
show all
- Defined in:
- lib/little_ghost/code_mode/javascript/session.rb
Overview
Defined Under Namespace
Classes: Deadline, ToolBatch, ToolCall
Constant Summary
collapse
- OBSERVATION_SECONDS =
60
- DEFAULT_OUTPUT_TOKENS =
10_000
- MAX_OUTPUT_TOKENS =
Javascript::Client::MAX_BUFFERED_OUTPUT_BYTES / 4
- MAX_PENDING_TOOL_CALLS =
1_024
- CLEANUP_TIMEOUT =
5
Instance Method Summary
collapse
-
#begin_client_termination(program_id) ⇒ Object
-
#close ⇒ Object
-
#enqueue_tool_calls(program_id:, calls:) ⇒ Object
-
#execute(source:, catalog:, frame: nil, max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil) ⇒ Object
-
#finish_client_termination(program_id) ⇒ Object
-
#initialize(broker:, client:, sandbox: nil, workspace: nil, max_concurrency: 8, wall_seconds: 3_600, observation_seconds: OBSERVATION_SECONDS, cleanup_timeout: CLEANUP_TIMEOUT) ⇒ Session
constructor
A new instance of Session.
-
#record_client_failure(program_id, error) ⇒ Object
-
#stop(max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil) ⇒ Object
-
#wait(max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil) ⇒ Object
Constructor Details
#initialize(broker:, client:, sandbox: nil, workspace: nil, max_concurrency: 8, wall_seconds: 3_600, observation_seconds: OBSERVATION_SECONDS, cleanup_timeout: CLEANUP_TIMEOUT) ⇒ Session
Returns a new instance of Session.
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
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 19
def initialize(broker:, client:, sandbox: nil, workspace: nil, max_concurrency: 8,
wall_seconds: 3_600, observation_seconds: OBSERVATION_SECONDS, cleanup_timeout: CLEANUP_TIMEOUT)
@broker = broker
@task_runner = broker.task_runner
@client = client
@sandbox = sandbox
@workspace = workspace
@max_concurrency = Integer(max_concurrency)
raise ArgumentError, "max_concurrency must be positive" unless @max_concurrency.positive?
@wall_seconds = Float(wall_seconds)
@observation_seconds = Float(observation_seconds)
@cleanup_timeout = Float(cleanup_timeout)
raise ArgumentError, "wall_seconds must be positive" unless @wall_seconds.positive?
raise ArgumentError, "observation_seconds must be positive" unless @observation_seconds.positive?
raise ArgumentError, "cleanup_timeout must be positive" unless @cleanup_timeout.positive?
@frames = {}
@frames_mutex = Mutex.new
@dispatch_counts = Hash.new(0)
@terminating_programs = {}
@fatal_errors = {}
@discarded_programs = {}
@dispatch_mutex = Mutex.new
@dispatch_condition = ConditionVariable.new
@queue = SizedQueue.new(MAX_PENDING_TOOL_CALLS)
@closed = false
@poisoned = false
@control_mutex = Mutex.new
@mutex = Mutex.new
@worker = nil
@deadline_mutex = Mutex.new
@deadline_condition = ConditionVariable.new
@deadlines = {}
@pending_deadline_errors = []
end
|
Instance Method Details
#begin_client_termination(program_id) ⇒ Object
104
105
106
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 104
def begin_client_termination(program_id)
begin_termination([program_id])
end
|
#close ⇒ Object
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
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 68
def close
cancel_all_deadlines
program_ids = begin_termination
already_closed, worker = @mutex.synchronize do
if @closed
[true, nil]
else
@closed = true
drain_dispatch_queue
@queue.push(:close, true)
[false, @worker]
end
end
return if already_closed
begin
@client.close_owner(self)
wait_for_dispatches(program_ids)
if worker
begin
worker.wait(deadline: Time.now + @cleanup_timeout)
rescue LittleGhost::DeadlineExceededError
raise LittleGhost::CleanupError, "Code-mode dispatch worker cleanup timed out"
end
end
ensure
@client.close
@sandbox&.close
@workspace&.close
@frames_mutex.synchronize { @frames.clear }
@current_program_id = nil
end
raise_pending_failure!
raise_pending_deadline_error!
end
|
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 186
def enqueue_tool_calls(program_id:, calls:)
if !calls.is_a?(Array) || calls.length > MAX_PENDING_TOOL_CALLS
raise LittleGhost::ProtocolError, "Code-mode program exceeded the pending tool-call limit"
end
batch = Array(calls).map do |call|
raise LittleGhost::ProtocolError, "Code-mode host returned an invalid tool call" unless call.is_a?(Hash)
ToolCall.new(
program_id:, call_id: call.fetch("call_id"), name: call.fetch("name"),
arguments: call.fetch("arguments")
)
end
@mutex.synchronize do
raise LittleGhost::ToolError, "Code-mode session is closed" if @closed
ensure_worker
register_dispatch(batch)
@queue.push(ToolBatch.new(calls: batch), true)
end
rescue ThreadError
batch&.calls&.each { |call| reject(call, "Code-mode tool queue is full") }
finish_dispatch(batch&.calls)
rescue KeyError, TypeError
raise LittleGhost::ProtocolError, "Code-mode host returned an invalid tool call"
end
|
#execute(source:, catalog:, frame: nil, max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil) ⇒ Object
54
55
56
57
58
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 54
def execute(source:, catalog:, frame: nil, max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil)
with_control do
execute_program(source:, catalog:, frame:, max_output_tokens:, context:)
end
end
|
#finish_client_termination(program_id) ⇒ Object
108
109
110
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 108
def finish_client_termination(program_id)
wait_for_dispatches([program_id])
end
|
#record_client_failure(program_id, error) ⇒ Object
112
113
114
115
116
117
118
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 112
def record_client_failure(program_id, error)
@dispatch_mutex.synchronize do
return if @discarded_programs[program_id]
@fatal_errors[program_id] ||= fatal_error(error)
end
end
|
#stop(max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil) ⇒ Object
64
65
66
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 64
def stop(max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil)
with_control { stop_program(max_output_tokens:, context:) }
end
|
#wait(max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil) ⇒ Object
60
61
62
|
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 60
def wait(max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil)
with_control { wait_for_program(max_output_tokens:, context:) }
end
|