Class: RubynCode::Autonomous::Daemon
- Inherits:
-
Object
- Object
- RubynCode::Autonomous::Daemon
- Defined in:
- lib/rubyn_code/autonomous/daemon.rb
Overview
The GOLEM daemon — an always-on autonomous agent that cycles between working on tasks and polling for new work. The lifecycle is:
spawned → working ⇄ idle → shutting_down → stopped
Safety limits (max_runs, max_cost, idle_timeout) prevent runaway execution. Signal traps (SIGTERM, SIGINT) trigger graceful shutdown.
Unlike the REPL, the daemon runs a full Agent::Loop per task — meaning it can read files, write code, run specs, and use every tool available.
Constant Summary collapse
- LIFECYCLE_STATES =
rubocop:disable Metrics/ClassLength – daemon lifecycle + retry + audit + cost
%i[spawned working idle shutting_down stopped].freeze
- MAX_TASK_RETRIES =
3
Instance Attribute Summary collapse
-
#agent_name ⇒ Object
readonly
Returns the value of attribute agent_name.
-
#role ⇒ Object
readonly
Returns the value of attribute role.
-
#runs_completed ⇒ Object
readonly
Returns the value of attribute runs_completed.
-
#state ⇒ Object
readonly
Returns the value of attribute state.
-
#total_cost ⇒ Object
readonly
Returns the value of attribute total_cost.
Instance Method Summary collapse
-
#initialize(agent_name:, role:, llm_client:, project_root:, task_manager:, mailbox:, max_runs: 100, max_cost: 10.0, poll_interval: 5, idle_timeout: 60, on_state_change: nil, on_task_complete: nil, on_task_error: nil, session_persistence: nil) ⇒ Daemon
constructor
A new instance of Daemon.
- #running? ⇒ Boolean
-
#start! ⇒ Symbol
Enters the work-idle-work cycle.
-
#status ⇒ Hash
Snapshot of daemon status.
-
#stop! ⇒ void
Requests a graceful shutdown.
Constructor Details
#initialize(agent_name:, role:, llm_client:, project_root:, task_manager:, mailbox:, max_runs: 100, max_cost: 10.0, poll_interval: 5, idle_timeout: 60, on_state_change: nil, on_task_complete: nil, on_task_error: nil, session_persistence: nil) ⇒ Daemon
Returns a new instance of Daemon.
37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 37 def initialize( # rubocop:disable Metrics/ParameterLists agent_name:, role:, llm_client:, project_root:, task_manager:, mailbox:, max_runs: 100, max_cost: 10.0, poll_interval: 5, idle_timeout: 60, on_state_change: nil, on_task_complete: nil, on_task_error: nil, session_persistence: nil ) assign_core_attrs(agent_name:, role:, llm_client:, project_root:, task_manager:, mailbox:) assign_limits(max_runs:, max_cost:, poll_interval:, idle_timeout:) assign_callbacks_and_state(on_state_change, on_task_complete, on_task_error) @session_persistence = session_persistence end |
Instance Attribute Details
#agent_name ⇒ Object (readonly)
Returns the value of attribute agent_name.
21 22 23 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 21 def agent_name @agent_name end |
#role ⇒ Object (readonly)
Returns the value of attribute role.
21 22 23 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 21 def role @role end |
#runs_completed ⇒ Object (readonly)
Returns the value of attribute runs_completed.
21 22 23 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 21 def runs_completed @runs_completed end |
#state ⇒ Object (readonly)
Returns the value of attribute state.
21 22 23 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 21 def state @state end |
#total_cost ⇒ Object (readonly)
Returns the value of attribute total_cost.
21 22 23 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 21 def total_cost @total_cost end |
Instance Method Details
#running? ⇒ Boolean
91 92 93 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 91 def running? %i[working idle].include?(@state) end |
#start! ⇒ Symbol
Enters the work-idle-work cycle. Blocks the calling thread until the daemon shuts down (via safety limits, idle timeout, or #stop!).
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 53 def start! install_signal_handlers! transition_to(:working) loop do break if @stop_requested break if safety_limit_reached? task = TaskClaimer.call(task_manager: @task_manager, agent_name: @agent_name) if task run_work_phase(task) @runs_completed += 1 else result = run_idle_phase case result when :shutdown, :interrupted break when :resume transition_to(:working) next end end end shutdown! end |
#status ⇒ Hash
Returns snapshot of daemon status.
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 96 def status { agent_name: @agent_name, role: @role, state: @state, runs_completed: @runs_completed, total_cost: @total_cost, max_runs: @max_runs, max_cost: @max_cost, stop_requested: @stop_requested } end |
#stop! ⇒ void
This method returns an undefined value.
Requests a graceful shutdown. The daemon will finish its current work unit and then stop.
85 86 87 88 |
# File 'lib/rubyn_code/autonomous/daemon.rb', line 85 def stop! @stop_requested = true @idle_poller&.interrupt! end |