Class: LittleGhost::RunContext
- Inherits:
-
Object
- Object
- LittleGhost::RunContext
- Defined in:
- lib/little_ghost/run_context.rb
Overview
RunContext gives tools and workflows one place for shared state, cancellation, deadlines, checkpoints, and accumulated usage. It travels with work inside a run without becoming global process state.
Tools and workflows use it to share JSON-like state, check cancellation and deadlines, checkpoint messages, and accumulate usage. Framework-managed fields remain safe when calls overlap on threads or fibers.
Instance Attribute Summary collapse
-
#agent_operation_id ⇒ Object
readonly
Active Agent operation identifier, after the context is bound.
-
#cancellation_token ⇒ Object
readonly
Token used to cooperatively stop the current work.
-
#conversation_id ⇒ Object
readonly
Durable subagent conversation identifier, when present.
-
#deadline ⇒ Object
readonly
Wall-clock deadline for the current work, when present.
-
#metadata ⇒ Object
readonly
Framework metadata attached to this context.
-
#state ⇒ Object
readonly
Mutable DataMap state supplied to this invocation.
Instance Method Summary collapse
-
#activate_interjection(metadata:, ids:) ⇒ Object
:nodoc:.
-
#bind_agent_operation_id(operation_id) ⇒ Object
:nodoc:.
-
#check! ⇒ Object
Raises LittleGhost::CancelledError or LittleGhost::DeadlineExceededError when execution should stop.
-
#checkpoint(messages) ⇒ Object
Sends
messagesand current state to the configured checkpoint callback. -
#initialize(state: {}, cancellation_token: Support::CancellationToken.new, deadline: nil, metadata: {}, checkpoint: nil, conversation_id: nil, interjection_metadata: nil, interjection_ids: []) ⇒ RunContext
constructor
Creates a context with optional checkpoint and interjection state.
-
#interjection_ids ⇒ Object
:nodoc:.
-
#interjection_metadata ⇒ Object
:nodoc:.
-
#record_tool_calls!(count, maximum:) ⇒ Object
:nodoc:.
-
#record_usage(value) ⇒ Object
Adds
valueto accumulated model usage. -
#remaining_time(maximum = nil) ⇒ Object
Calculates seconds remaining before the deadline.
-
#structured_result ⇒ Object
Finds the latest validated structured result, if any.
-
#submit_structured_result(result) ⇒ Object
Stores a validated LittleGhost::StructuredResult and returns it.
-
#usage ⇒ Object
Takes a snapshot of accumulated usage.
Constructor Details
#initialize(state: {}, cancellation_token: Support::CancellationToken.new, deadline: nil, metadata: {}, checkpoint: nil, conversation_id: nil, interjection_metadata: nil, interjection_ids: []) ⇒ RunContext
Creates a context with optional checkpoint and interjection state.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/little_ghost/run_context.rb', line 32 def initialize( state: {}, cancellation_token: Support::CancellationToken.new, deadline: nil, metadata: {}, checkpoint: nil, conversation_id: nil, interjection_metadata: nil, interjection_ids: [] ) if conversation_id conversation_id = String(conversation_id) raise ArgumentError, "conversation_id cannot be empty" if conversation_id.empty? conversation_id = conversation_id.dup.freeze end @state = DataMap.new(state) @cancellation_token = cancellation_token @deadline = deadline @metadata = .freeze @checkpoint = checkpoint @conversation_id = conversation_id @usage = Usage.new @usage_mutex = Mutex.new @tool_call_count = 0 @tool_call_count_mutex = Mutex.new @structured_result = nil @structured_result_mutex = Mutex.new @agent_operation_id = nil @agent_operation_id_mutex = Mutex.new @interjection_mutex = Mutex.new @interjection_metadata = &.to_h @interjection_ids = Array(interjection_ids).map { |id| String(id).dup.freeze }.freeze end |
Instance Attribute Details
#agent_operation_id ⇒ Object (readonly)
Active Agent operation identifier, after the context is bound.
27 28 29 |
# File 'lib/little_ghost/run_context.rb', line 27 def agent_operation_id @agent_operation_id end |
#cancellation_token ⇒ Object (readonly)
Token used to cooperatively stop the current work.
21 22 23 |
# File 'lib/little_ghost/run_context.rb', line 21 def cancellation_token @cancellation_token end |
#conversation_id ⇒ Object (readonly)
Durable subagent conversation identifier, when present.
29 30 31 |
# File 'lib/little_ghost/run_context.rb', line 29 def conversation_id @conversation_id end |
#deadline ⇒ Object (readonly)
Wall-clock deadline for the current work, when present.
23 24 25 |
# File 'lib/little_ghost/run_context.rb', line 23 def deadline @deadline end |
#metadata ⇒ Object (readonly)
Framework metadata attached to this context.
25 26 27 |
# File 'lib/little_ghost/run_context.rb', line 25 def @metadata end |
#state ⇒ Object (readonly)
Mutable DataMap state supplied to this invocation. A top-level Run starts with restored Session state merged with current Invocation context; child Assemblies may receive copied, mapped, or empty state. Application code must synchronize mutations when parallel Tools share this map, or use exclusive Tools. String and Symbol keys address the same value; persisted snapshots use canonical String keys.
19 20 21 |
# File 'lib/little_ghost/run_context.rb', line 19 def state @state end |
Instance Method Details
#activate_interjection(metadata:, ids:) ⇒ Object
:nodoc:
133 134 135 136 137 138 139 140 |
# File 'lib/little_ghost/run_context.rb', line 133 def activate_interjection(metadata:, ids:) # :nodoc: value = &.to_h values = Array(ids).map { |id| String(id).dup.freeze }.freeze @interjection_mutex.synchronize do @interjection_metadata = value @interjection_ids = values end end |
#bind_agent_operation_id(operation_id) ⇒ Object
:nodoc:
142 143 144 145 146 147 148 149 150 |
# File 'lib/little_ghost/run_context.rb', line 142 def bind_agent_operation_id(operation_id) # :nodoc: @agent_operation_id_mutex.synchronize do if @agent_operation_id && @agent_operation_id != operation_id raise Error, "run context is already bound to an agent operation" end @agent_operation_id ||= operation_id end end |
#check! ⇒ Object
Raises LittleGhost::CancelledError or LittleGhost::DeadlineExceededError when execution should stop.
68 69 70 71 |
# File 'lib/little_ghost/run_context.rb', line 68 def check! cancellation_token.raise_if_cancelled! raise DeadlineExceededError, "The run deadline was reached" if deadline && Time.now >= deadline end |
#checkpoint(messages) ⇒ Object
Sends messages and current state to the configured checkpoint callback.
With no checkpoint callback, this method does nothing and returns nil.
75 76 77 78 79 80 81 82 83 |
# File 'lib/little_ghost/run_context.rb', line 75 def checkpoint() return unless @checkpoint if agent_operation_id @checkpoint.call(messages:, state:, parent_operation_id: agent_operation_id) else @checkpoint.call(messages:, state:) end end |
#interjection_ids ⇒ Object
:nodoc:
129 130 131 |
# File 'lib/little_ghost/run_context.rb', line 129 def interjection_ids # :nodoc: @interjection_mutex.synchronize { @interjection_ids } end |
#interjection_metadata ⇒ Object
:nodoc:
125 126 127 |
# File 'lib/little_ghost/run_context.rb', line 125 def # :nodoc: @interjection_mutex.synchronize { @interjection_metadata } end |
#record_tool_calls!(count, maximum:) ⇒ Object
:nodoc:
95 96 97 98 99 100 |
# File 'lib/little_ghost/run_context.rb', line 95 def record_tool_calls!(count, maximum:) # :nodoc: @tool_call_count_mutex.synchronize do @tool_call_count += Integer(count) raise ProtocolError, "The agent reached its maximum tool calls" if @tool_call_count > Integer(maximum) end end |
#record_usage(value) ⇒ Object
Adds value to accumulated model usage.
86 87 88 |
# File 'lib/little_ghost/run_context.rb', line 86 def record_usage(value) @usage_mutex.synchronize { @usage += value } end |
#remaining_time(maximum = nil) ⇒ Object
Calculates seconds remaining before the deadline.
When maximum is provided, the result is capped at that value. With no
deadline, returns maximum.
106 107 108 109 110 111 112 |
# File 'lib/little_ghost/run_context.rb', line 106 def remaining_time(maximum = nil) check! return maximum unless deadline remaining = deadline - Time.now maximum ? [remaining, maximum].min : remaining end |
#structured_result ⇒ Object
Finds the latest validated structured result, if any.
121 122 123 |
# File 'lib/little_ghost/run_context.rb', line 121 def structured_result @structured_result_mutex.synchronize { @structured_result } end |
#submit_structured_result(result) ⇒ Object
Stores a validated LittleGhost::StructuredResult and returns it.
115 116 117 118 |
# File 'lib/little_ghost/run_context.rb', line 115 def submit_structured_result(result) @structured_result_mutex.synchronize { @structured_result = result } result end |
#usage ⇒ Object
Takes a snapshot of accumulated usage.
91 92 93 |
# File 'lib/little_ghost/run_context.rb', line 91 def usage @usage_mutex.synchronize { @usage } end |