Class: LittleGhost::Run
- Inherits:
-
Object
- Object
- LittleGhost::Run
- Includes:
- Enumerable
- Defined in:
- lib/little_ghost/run.rb
Overview
Observe one top-level agent or workflow execution from start to finish. A run records its response, outcome, usage, error, and owned resources.
run = CustomerSupportAgent.ask("Why is transfer 481 pending?")
run.completed? # => true
run.outcome # => "completed"
run.response # => "Transfer 481 is waiting for the receiving bank."
The class-level ask helper or standalone ask method consumes the event stream and returns the Run. For a live interface, the class-level streaming helper or standalone streaming method yields StreamEvent objects and returns the same run after enumeration. A run can execute only once.
Completion, failure, deadline, and cancellation become the completed,
failed, partial, and cancelled outcomes. Ordinary execution failures
are available through error and the terminal stream event; cleanup, event
delivery, or instrumentation failures may still raise because the framework
cannot safely report a clean stop.
The run opens its workspace, sandbox, session, and entrypoint, then closes
registered resources in reverse order. register extends that lifecycle for
application resources. Interruption is available only while an agent
entrypoint is active and unambiguous.
Instance Attribute Summary collapse
-
#agent_class ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#cancellation_token ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#entrypoint_class ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#error ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#invocation ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#operation_id ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#outcome ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#response ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#result ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#runtime ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#sandbox ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#session ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#usage ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
-
#workspace ⇒ Object
readonly
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Instance Method Summary collapse
-
#call ⇒ Object
Consumes the event stream and returns
self. -
#cancelled? ⇒ Boolean
True when cancellation stopped the run without a response.
-
#close ⇒ Object
Closes registered resources in reverse order.
-
#completed? ⇒ Boolean
True after successful completion.
-
#context(state: {}, metadata: {}) ⇒ Object
Creates a RunContext with this run's cancellation token and deadline.
-
#each ⇒ Object
Yields events and returns
selfafter the terminal event. -
#failed? ⇒ Boolean
True after execution or cleanup failed.
-
#initialize(invocation:, agent_class:, runtime:, entrypoint_class: agent_class, cancellation_token: Support::CancellationToken.new, workspace: nil, sandbox: nil) ⇒ Run
constructor
Creates a dormant run for
invocation. -
#interrupt_response(message, interruption_id: nil, batch_key: nil, metadata: {}, cancellation_token: Support::CancellationToken.new, deadline: nil) ⇒ Object
Adds an interruption to the active entrypoint and waits for its response.
-
#once(key) ⇒ Object
Performs the block at most once successfully for
keyduring this run. -
#partial? ⇒ Boolean
True when the deadline preserved a partial response.
-
#prepare_interruption(payload) ⇒ Object
:nodoc:.
-
#publish(type, **data) ⇒ Object
:nodoc:.
-
#register(resource = nil, &closer) ⇒ Object
Adds a resource or closer to reverse-order cleanup and returns the resource.
-
#synchronize_exclusive_tools(&block) ⇒ Object
:nodoc:.
Constructor Details
#initialize(invocation:, agent_class:, runtime:, entrypoint_class: agent_class, cancellation_token: Support::CancellationToken.new, workspace: nil, sandbox: nil) ⇒ Run
Creates a dormant run for invocation.
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 |
# File 'lib/little_ghost/run.rb', line 41 def initialize(invocation:, agent_class:, runtime:, entrypoint_class: agent_class, cancellation_token: Support::CancellationToken.new, workspace: nil, sandbox: nil) @runtime = runtime @agent_class = agent_class @entrypoint_class = entrypoint_class @invocation = invocation @cancellation_token = cancellation_token @workspace = workspace @sandbox = sandbox @operation_id = SecureRandom.uuid @resources = [] @closed = false @started = false @mutex = Mutex.new @event_mutex = Mutex.new @subagent_instrumentation_mutex = Mutex.new @subagent_instrumentation = {} @exclusive_tools_mutex = Mutex.new @once_mutex = Mutex.new @once_keys = {} @interruption_mutex = Mutex.new @interruption_state = :not_started @entrypoint = nil @usage = Usage.new end |
Instance Attribute Details
#agent_class ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def agent_class @agent_class end |
#cancellation_token ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def cancellation_token @cancellation_token end |
#entrypoint_class ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def entrypoint_class @entrypoint_class end |
#error ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def error @error end |
#invocation ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def invocation @invocation end |
#operation_id ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def operation_id @operation_id end |
#outcome ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def outcome @outcome end |
#response ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def response @response end |
#result ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def result @result end |
#runtime ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def runtime @runtime end |
#sandbox ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def sandbox @sandbox end |
#session ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def session @session end |
#usage ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def usage @usage end |
#workspace ⇒ Object (readonly)
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
37 38 39 |
# File 'lib/little_ghost/run.rb', line 37 def workspace @workspace end |
Instance Method Details
#call ⇒ Object
Consumes the event stream and returns self.
68 69 70 71 |
# File 'lib/little_ghost/run.rb', line 68 def call each { |_event| } self end |
#cancelled? ⇒ Boolean
True when cancellation stopped the run without a response.
99 |
# File 'lib/little_ghost/run.rb', line 99 def cancelled? = outcome == "cancelled" |
#close ⇒ Object
Closes registered resources in reverse order.
The operation is idempotent. It attempts every closer and then raises the first LittleGhost::CleanupError, or otherwise the first cleanup exception.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/little_ghost/run.rb', line 194 def close callbacks = @mutex.synchronize do return if @closed @closed = true @resources.reverse end errors = [] callbacks.each do |callback| callback.call rescue => error errors << error end cleanup_error = errors.find { |caught| caught.is_a?(CleanupError) } || errors.first begin finish_remaining_subagent_instrumentation( outcome: cleanup_error ? :error : :cancelled, error_type: cleanup_error&.class&.name ) rescue => error errors << error end error = errors.find { |caught| caught.is_a?(CleanupError) } || errors.first raise error if error end |
#completed? ⇒ Boolean
True after successful completion.
90 |
# File 'lib/little_ghost/run.rb', line 90 def completed? = outcome == "completed" |
#context(state: {}, metadata: {}) ⇒ Object
Creates a RunContext with this run's cancellation token and deadline.
138 139 140 141 142 143 144 145 |
# File 'lib/little_ghost/run.rb', line 138 def context(state: {}, metadata: {}) RunContext.new( state:, cancellation_token:, deadline: invocation.deadline_at, metadata: ) end |
#each ⇒ Object
Yields events and returns self after the terminal event.
Without a block, returns an Enumerator. A second execution raises Error.
76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/little_ghost/run.rb', line 76 def each return enum_for(__method__) unless block_given? begin_execution! @emitter = ->(event) { yield_event(event) { |value| yield value } } Instrumentation.with_context(correlation_attributes.except(:operation_id)) do execute { |event| yield event } end self ensure @emitter = nil end |
#failed? ⇒ Boolean
True after execution or cleanup failed.
93 |
# File 'lib/little_ghost/run.rb', line 93 def failed? = outcome == "failed" |
#interrupt_response(message, interruption_id: nil, batch_key: nil, metadata: {}, cancellation_token: Support::CancellationToken.new, deadline: nil) ⇒ Object
Adds an interruption to the active entrypoint and waits for its response.
Raises LittleGhost::AgentInterruptError before the entrypoint is ready, after it finishes, or when the entrypoint does not support interruptions.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/little_ghost/run.rb', line 105 def interrupt_response( , interruption_id: nil, batch_key: nil, metadata: {}, cancellation_token: Support::CancellationToken.new, deadline: nil ) entrypoint = @interruption_mutex.synchronize do case @interruption_state when :not_started, :starting raise AgentInterruptError, "Run entrypoint is not ready for interruptions" when :terminal raise AgentInterruptError, "Run has already finished" end @entrypoint end unless entrypoint.is_a?(Agent) raise AgentInterruptError, "Run entrypoint does not support interruptions" end entrypoint.interrupt_response( , interruption_id:, batch_key:, metadata:, cancellation_token:, deadline: ) end |
#once(key) ⇒ Object
Performs the block at most once successfully for key during this run.
Concurrent callers are serialized. The caller that performs the block
receives its value; later callers receive nil. If the block raises, the
key is not recorded and a later call may retry it.
176 177 178 179 180 181 182 183 184 |
# File 'lib/little_ghost/run.rb', line 176 def once(key) @once_mutex.synchronize do return if @once_keys.key?(key) value = yield @once_keys[key] = true value end end |
#partial? ⇒ Boolean
True when the deadline preserved a partial response.
96 |
# File 'lib/little_ghost/run.rb', line 96 def partial? = outcome == "partial" |
#prepare_interruption(payload) ⇒ Object
:nodoc:
186 187 188 |
# File 'lib/little_ghost/run.rb', line 186 def prepare_interruption(payload) # :nodoc: runtime.prepare_interruption(self, payload) end |
#publish(type, **data) ⇒ Object
:nodoc:
147 148 149 150 151 152 |
# File 'lib/little_ghost/run.rb', line 147 def publish(type, **data) # :nodoc: event = StreamEvent.build(type, **data) @event_mutex.synchronize { @emitter&.call(event) } instrument_event(type, data) event end |
#register(resource = nil, &closer) ⇒ Object
Adds a resource or closer to reverse-order cleanup and returns the resource.
A resource must respond to close unless a block supplies the cleanup
operation. Registering after the run has closed raises Error.
158 159 160 161 162 163 164 165 |
# File 'lib/little_ghost/run.rb', line 158 def register(resource = nil, &closer) callback = closer || close_callback(resource) @mutex.synchronize do raise Error, "run is already closed" if @closed @resources << callback end resource end |
#synchronize_exclusive_tools(&block) ⇒ Object
:nodoc:
167 168 169 |
# File 'lib/little_ghost/run.rb', line 167 def synchronize_exclusive_tools(&block) # :nodoc: @exclusive_tools_mutex.synchronize(&block) end |