Class: RubynCode::Agent::Loop
- Inherits:
-
Object
- Object
- RubynCode::Agent::Loop
- Includes:
- BackgroundJobHandler, FeedbackHandler, LlmCaller, ResponseParser, SystemPromptBuilder, ToolProcessor
- Defined in:
- lib/rubyn_code/agent/loop.rb
Overview
rubocop:disable Metrics/ClassLength -- core agent loop: LLM calls, tool dispatch, recovery, hooks
Constant Summary collapse
- MAX_ITERATIONS =
Config::Defaults::MAX_ITERATIONS
- GOAL_MAX_ITERATIONS =
Config::Defaults::GOAL_MAX_ITERATIONS
Constants included from FeedbackHandler
FeedbackHandler::NEGATIVE_PATTERNS, FeedbackHandler::POSITIVE_PATTERNS
Constants included from ToolProcessor
ToolProcessor::CORE_TOOLS, ToolProcessor::PLAN_MODE_RISK_LEVELS
Constants included from UsageTracker
UsageTracker::TASK_BUDGET_TOTAL
Constants included from SystemPromptBuilder
SystemPromptBuilder::INSTRUCTION_FILES
Constants included from Prompts
Prompts::PLAN_MODE_PROMPT, Prompts::SYSTEM_PROMPT
Instance Attribute Summary collapse
- #codebase_index ⇒ Index::CodebaseIndex? readonly
- #plan_mode ⇒ Boolean
-
#todo_store ⇒ Tools::TodoStore
readonly
Shared checklist store, exposed for the REPL renderer.
Instance Method Summary collapse
-
#allowed_tools_override=(allowed) ⇒ Object
Restrict the available tool set for the next LLM call only.
-
#append_user_message(user_input, blocks) ⇒ Object
Append the user turn to the conversation.
-
#initialize(**opts) ⇒ Loop
constructor
A new instance of Loop.
-
#model_override=(model_name) ⇒ Object
Apply a one-shot model override for the duration of the next LLM call.
-
#send_message(user_input, blocks: nil) ⇒ String
Send a user message and run the agent loop until a final text response is produced or the iteration limit is reached.
Constructor Details
#initialize(**opts) ⇒ Loop
Returns a new instance of Loop.
39 40 41 42 43 44 |
# File 'lib/rubyn_code/agent/loop.rb', line 39 def initialize(**opts) assign_dependencies(opts) assign_callbacks(opts) @plan_mode = false @static_prompt_sections = nil end |
Instance Attribute Details
#codebase_index ⇒ Index::CodebaseIndex? (readonly)
50 51 52 |
# File 'lib/rubyn_code/agent/loop.rb', line 50 def codebase_index @codebase_index end |
#plan_mode ⇒ Boolean
47 48 49 |
# File 'lib/rubyn_code/agent/loop.rb', line 47 def plan_mode @plan_mode end |
#todo_store ⇒ Tools::TodoStore (readonly)
Returns shared checklist store, exposed for the REPL renderer.
98 99 100 |
# File 'lib/rubyn_code/agent/loop.rb', line 98 def todo_store @todo_store end |
Instance Method Details
#allowed_tools_override=(allowed) ⇒ Object
Restrict the available tool set for the next LLM call only.
109 110 111 |
# File 'lib/rubyn_code/agent/loop.rb', line 109 def allowed_tools_override=(allowed) @allowed_tools_override = allowed.is_a?(Array) && !allowed.empty? ? allowed : nil end |
#append_user_message(user_input, blocks) ⇒ Object
Append the user turn to the conversation. If image blocks were passed
via blocks:, the message is stored as a mixed content array with a
leading text block and the image blocks appended in order.
88 89 90 91 92 93 94 95 |
# File 'lib/rubyn_code/agent/loop.rb', line 88 def (user_input, blocks) if blocks.is_a?(Array) && !blocks.empty? content = [{ type: 'text', text: user_input.to_s }, *blocks] @conversation.(content) else @conversation.(user_input) end end |
#model_override=(model_name) ⇒ Object
Apply a one-shot model override for the duration of the next LLM call.
Used by Context#with_optional_model for custom-command frontmatter.
102 103 104 105 |
# File 'lib/rubyn_code/agent/loop.rb', line 102 def model_override=(model_name) stripped = model_name.to_s.strip @model_override = stripped.empty? ? nil : stripped end |
#send_message(user_input, blocks: nil) ⇒ String
Send a user message and run the agent loop until a final text response is produced or the iteration limit is reached.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/rubyn_code/agent/loop.rb', line 60 def (user_input, blocks: nil) initialize_session! check_user_feedback(user_input) drain_background_notifications inject_skill_listing unless @skills_injected @decision_compactor&.detect_topic_switch(user_input) @skill_ttl&.tick! autoload_triggered_skills(user_input) (user_input, blocks) reset_system_prompt_cache! reset_iteration_state iteration = 0 loop do result = run_iteration(iteration) return result if result iteration += 1 break unless (iteration) end RubynCode::Debug.warn("Hit iteration limit (#{iteration})") max_iterations_warning(iteration) end |