Class: LittleGhost::CodeMode::Javascript::Session
- Defined in:
- lib/little_ghost/code_mode/javascript/session.rb
Overview
:nodoc: all
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, framework_prompt_scope: {}) ⇒ 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, framework_prompt_scope: {}) ⇒ 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 53 54 |
# 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, framework_prompt_scope: {}) @broker = broker @task_runner = broker.task_runner @client = client @sandbox = sandbox @workspace = workspace @framework_prompt_scope = framework_prompt_scope.freeze @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
106 107 108 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 106 def begin_client_termination(program_id) begin_termination([program_id]) end |
#close ⇒ Object
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 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 70 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 |
#enqueue_tool_calls(program_id:, calls:) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 198 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, prompt("code_mode/feedback/closed", resource: "session") 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
56 57 58 59 60 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 56 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
110 111 112 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 110 def finish_client_termination(program_id) wait_for_dispatches([program_id]) end |
#record_client_failure(program_id, error) ⇒ Object
114 115 116 117 118 119 120 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 114 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
66 67 68 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 66 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
62 63 64 |
# File 'lib/little_ghost/code_mode/javascript/session.rb', line 62 def wait(max_output_tokens: DEFAULT_OUTPUT_TOKENS, context: nil) with_control { wait_for_program(max_output_tokens:, context:) } end |