Module: Legion::CLI::Chat::Subagent
- Defined in:
- lib/legion/cli/chat/subagent.rb
Constant Summary collapse
- MAX_CONCURRENCY =
3- TIMEOUT =
5 minutes
300
Class Attribute Summary collapse
-
.max_concurrency ⇒ Object
Returns the value of attribute max_concurrency.
-
.timeout ⇒ Object
Returns the value of attribute timeout.
Class Method Summary collapse
- .at_capacity? ⇒ Boolean
- .configure(max_concurrency: MAX_CONCURRENCY, timeout: TIMEOUT) ⇒ Object
- .configure_from_settings ⇒ Object
- .running ⇒ Object
- .running_count ⇒ Object
- .spawn(task:, model: nil, provider: nil, on_complete: nil) ⇒ Object
- .wait_all(timeout: @timeout || TIMEOUT) ⇒ Object
Class Attribute Details
.max_concurrency ⇒ Object
Returns the value of attribute max_concurrency.
19 20 21 |
# File 'lib/legion/cli/chat/subagent.rb', line 19 def max_concurrency @max_concurrency end |
.timeout ⇒ Object
Returns the value of attribute timeout.
19 20 21 |
# File 'lib/legion/cli/chat/subagent.rb', line 19 def timeout @timeout end |
Class Method Details
.at_capacity? ⇒ Boolean
73 74 75 |
# File 'lib/legion/cli/chat/subagent.rb', line 73 def at_capacity? @mutex.synchronize { @running.length >= @max_concurrency } end |
.configure(max_concurrency: MAX_CONCURRENCY, timeout: TIMEOUT) ⇒ Object
21 22 23 24 25 |
# File 'lib/legion/cli/chat/subagent.rb', line 21 def configure(max_concurrency: MAX_CONCURRENCY, timeout: TIMEOUT) @max_concurrency = max_concurrency @timeout = timeout @running = [] end |
.configure_from_settings ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/legion/cli/chat/subagent.rb', line 27 def configure_from_settings mc = begin Legion::Settings.dig(:chat, :subagent, :max_concurrency) rescue StandardError => e Legion::Logging.warn("Subagent#configure_from_settings max_concurrency read failed: #{e.}") if defined?(Legion::Logging) nil end to = begin Legion::Settings.dig(:chat, :subagent, :timeout) rescue StandardError => e Legion::Logging.warn("Subagent#configure_from_settings timeout read failed: #{e.}") if defined?(Legion::Logging) nil end @max_concurrency = mc || MAX_CONCURRENCY @timeout = to || TIMEOUT end |
.running ⇒ Object
65 66 67 |
# File 'lib/legion/cli/chat/subagent.rb', line 65 def running @mutex.synchronize { @running.map { |a| { id: a[:id], task: a[:task], elapsed: Time.now - a[:started_at] } } } end |
.running_count ⇒ Object
69 70 71 |
# File 'lib/legion/cli/chat/subagent.rb', line 69 def running_count @mutex.synchronize { @running.length } end |
.spawn(task:, model: nil, provider: nil, on_complete: nil) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/legion/cli/chat/subagent.rb', line 44 def spawn(task:, model: nil, provider: nil, on_complete: nil) return { error: "Max concurrency reached (#{@max_concurrency}). Wait for a subagent to finish." } if at_capacity? agent_id = "agent-#{Time.now.strftime('%H%M%S')}-#{rand(1000)}" thread = Thread.new do result = run_headless(task: task, model: model, provider: provider) @mutex.synchronize { @running.delete_if { |a| a[:id] == agent_id } } on_complete&.call(agent_id, result) rescue StandardError => e Legion::Logging.error("Subagent#spawn thread error for #{agent_id}: #{e.}") if defined?(Legion::Logging) @mutex.synchronize { @running.delete_if { |a| a[:id] == agent_id } } on_complete&.call(agent_id, { error: e. }) end entry = { id: agent_id, task: task, thread: thread, started_at: Time.now } @mutex.synchronize { @running << entry } { id: agent_id, status: 'running', task: task } end |
.wait_all(timeout: @timeout || TIMEOUT) ⇒ Object
77 78 79 80 81 82 83 84 85 |
# File 'lib/legion/cli/chat/subagent.rb', line 77 def wait_all(timeout: @timeout || TIMEOUT) deadline = Time.now + timeout @running.each do |agent| remaining = deadline - Time.now break if remaining <= 0 agent[:thread]&.join(remaining) end end |