Class: Rubino::Config::Configuration
- Inherits:
-
Object
- Object
- Rubino::Config::Configuration
- Defined in:
- lib/rubino/config/configuration.rb
Overview
Central configuration object providing typed accessors for all config sections. Wraps the raw hash loaded by Config::Loader with convenient method access.
Instance Attribute Summary collapse
-
#raw ⇒ Object
readonly
Returns the value of attribute raw.
Instance Method Summary collapse
-
#agent_budget_extension_prompt? ⇒ Boolean
At the iteration cap, prompt to continue/summarize/abort (#399).
-
#agent_budget_extension_step ⇒ Object
The "+N" one budget extension grants.
- #agent_disabled_toolsets ⇒ Object
-
#agent_max_tool_iterations ⇒ Object
-- Agent section -- Iteration/time caps fall back to the built-in defaults when the config value is nil/missing (e.g.
config set agent.max_tool_iterations nil, whose writer coerces "nil" -> nil). - #agent_max_turn_seconds ⇒ Object
-
#api_allow_public_bind? ⇒ Boolean
-- API section -- Whether the HTTP API server may bind to a non-loopback address.
-
#approvals_readonly_commands ⇒ Object
Extra command names / leading-token prefixes merged into the built-in read-only set (Security::ReadonlyCommands::SAFE_COMMANDS).
-
#approvals_wait_timeout ⇒ Object
-- Security section -- Seconds a run blocks on a human approval/clarification before the gate gives up and AUTO-DENIES (freeing the worker thread).
-
#auto_allow_readonly? ⇒ Boolean
Auto-allow provably read-only shell commands (ls, cat, grep, git log, ...) without an approval prompt.
-
#auxiliary_config(task) ⇒ Object
Generic accessor for auxiliary task config blocks.
-
#auxiliary_on_main_endpoint?(task) ⇒ Boolean
True when the auxiliary
taskresolves to the SAME server ENDPOINT as the main model — i.e. -
#auxiliary_vision_config ⇒ Object
-- Auxiliary section --.
-
#clarify_timeout ⇒ Object
Bound (seconds) an interactive
question/clarify waits for the human to answer before it EXPIRES CLEANLY and the agent proceeds with its best judgement (#552). -
#compression_enabled? ⇒ Boolean
-- Compression section --.
- #compression_preserve_tool_pairs? ⇒ Boolean
-
#confirm_policy ⇒ Object
Effective shell prompt policy and SOLE source of truth (item 7): the legacy security.require_confirmation_for_shell alias was REMOVED — no back-compat mapping.
-
#database_path ⇒ Object
-- Database section -- Resolves the sqlite path.
-
#dig(*keys) ⇒ Object
-- Generic access --.
-
#display_code_highlight? ⇒ Boolean
Syntax-highlight committed code blocks (display.code_highlight).
-
#display_input_max_rows ⇒ Object
Cap on the chat input's visual rows (display.input_max_rows).
-
#display_live_markdown? ⇒ Boolean
Render the in-flight streamed block as formatted markdown in the live region (display.live_markdown).
-
#display_statusbar? ⇒ Boolean
The status bar under the chat input (display.statusbar, default true).
-
#display_streaming? ⇒ Boolean
-- Display section --.
-
#display_synchronized_output? ⇒ Boolean
Wrap each live-region frame in DEC-2026 synchronized output (display.synchronized_output).
-
#display_tool_output_preview_lines ⇒ Object
Transcript preview budget for tool output (display.tool_output_preview_lines): head lines shown before the "… +N lines (full output → context)" marker.
-
#doom_loop_hard_stop? ⇒ Boolean
-- Doom-loop guard (#414) -- Default WARN-not-block (hard_stop false): a tripped detector surfaces a warning to the model but does not deny the call.
-
#doom_loop_threshold ⇒ Object
Identical-consecutive-call threshold.
-
#initialize(raw: nil, home_path: nil) ⇒ Configuration
constructor
A new instance of Configuration.
- #memory_auto_extract? ⇒ Boolean
-
#memory_auto_extract_interval ⇒ Object
Throttle interval (in turns) for memory.auto_extract (#412).
-
#memory_enabled? ⇒ Boolean
-- Memory section --.
-
#model_supports_vision? ⇒ Boolean
Returns true when the primary model can ingest images directly.
- #notifications_bell? ⇒ Boolean
- #notifications_command ⇒ Object
-
#notifications_enabled? ⇒ Boolean
-- Notifications section (UI::Notifier: attention bell + hook) -- enabled/bell are on unless explicitly false; command is nil unless a non-empty string is set; min_turn_seconds falls back to the default.
- #notifications_min_turn_seconds ⇒ Object
-
#paste_collapse_chars ⇒ Object
A paste with MORE than this many CHARACTERS also collapses to a placeholder, even on a single line — a big one-line paste (a long token, URL, minified JSON) would otherwise flood the composer because the line-count trigger never fired.
-
#paste_collapse_lines ⇒ Object
-- Paste section (UI::PasteStore: the file-backed paste pipeline) -- A paste with MORE than this many lines collapses to a "[Pasted text #N +M lines]" placeholder in the composer (expanded to the full body at send).
-
#paste_file_threshold_tokens ⇒ Object
A paste estimated above this many tokens (chars/4, the same rule compaction uses) overflows to
/sessions/ /paste_N.txt and the message carries a read-tool pointer instead of the content. - #prompts_environment_enabled? ⇒ Boolean
- #prompts_environment_extra_utilities ⇒ Object
-
#prompts_override_for(role) ⇒ Object
Returns the override string for a given role name, or nil if the built-in default prompt should be used.
-
#prompts_preamble ⇒ Object
-- Prompts section -- The customer-facing preamble prepended to every assembled system prompt.
-
#provider_config(name) ⇒ Object
-- Providers section --.
- #reload! ⇒ Object
-
#run_idle_event_timeout ⇒ Object
-- Run lifecycle section -- Returns Float seconds (or nil to disable).
-
#security_command_allowlist ⇒ Object
The pre-approved command allowlist, always returned as an Array.
- #set(*keys, value) ⇒ Object
-
#skills_auto_distill? ⇒ Boolean
Post-turn skill distillation.
-
#skills_auto_distill_interval ⇒ Object
Throttle interval (in turns) for skills.auto_distill (#414).
-
#streaming_enabled? ⇒ Boolean
-- Streaming section --.
-
#tasks_max_children_per_node ⇒ Object
Maximum number of LIVE direct children a single node (the human/top-level or one subagent) may have at once.
-
#tasks_max_concurrent_total ⇒ Object
Hard global ceiling on the total number of LIVE subagents across the whole tree, so depth × fan-out cannot blow past the process's thread/cost budget.
-
#tasks_max_depth ⇒ Object
-- Tasks / nested-subagent caps -- Maximum nesting depth for the
taskdelegation tree. -
#tasks_max_live_probes_per_child ⇒ Object
Per-child budget for BILLED live probes (
probe(live:true)). -
#tool_enabled?(name) ⇒ Boolean
-- Tools section --.
-
#tool_output_capture_max_bytes ⇒ Object
Hard RAM ceiling for the shell capture seam (#539).
- #tool_output_compression_code ⇒ Object
-
#tool_output_compression_code_languages ⇒ Object
Source languages the code skeletoner is enabled for (e.g. ["ruby"]).
-
#tool_output_compression_diff ⇒ Object
DIFF compression config.
-
#tool_output_compression_enabled? ⇒ Boolean
Deterministic, reversible compression of tool-read results (whole-file Ruby reads → skeleton).
-
#tool_output_compression_json ⇒ Object
JSON compression config.
-
#tool_output_compression_logs ⇒ Object
LOG/command-output compression config.
- #tool_output_compression_logs_enabled? ⇒ Boolean
-
#ui_verbose? ⇒ Boolean
-- UI section --.
Constructor Details
#initialize(raw: nil, home_path: nil) ⇒ Configuration
Returns a new instance of Configuration.
10 11 12 13 |
# File 'lib/rubino/config/configuration.rb', line 10 def initialize(raw: nil, home_path: nil) @home_path = home_path @raw = raw || load_from_file end |
Instance Attribute Details
#raw ⇒ Object (readonly)
Returns the value of attribute raw.
8 9 10 |
# File 'lib/rubino/config/configuration.rb', line 8 def raw @raw end |
Instance Method Details
#agent_budget_extension_prompt? ⇒ Boolean
At the iteration cap, prompt to continue/summarize/abort (#399). Defaults to true; an explicit false forces the old always-summarize behaviour. Independent of TTY — the headless guarantee lives in @ui.select returning nil, not here.
166 167 168 169 |
# File 'lib/rubino/config/configuration.rb', line 166 def agent_budget_extension_prompt? v = dig("agent", "budget_extension_prompt") v.nil? ? Defaults.dig("agent", "budget_extension_prompt") : v == true end |
#agent_budget_extension_step ⇒ Object
The "+N" one budget extension grants. nil/blank ⇒ max_tool_iterations, so an extension doubles the per-turn runway (the Cline/Roo "reset the counter, keep context" amount). Coerced to a positive Integer; a bad value falls back to the iteration cap.
175 176 177 178 179 |
# File 'lib/rubino/config/configuration.rb', line 175 def agent_budget_extension_step raw = dig("agent", "budget_extension_step") n = Integer(raw, exception: false) n&.positive? ? n : agent_max_tool_iterations end |
#agent_disabled_toolsets ⇒ Object
181 182 183 |
# File 'lib/rubino/config/configuration.rb', line 181 def agent_disabled_toolsets dig("agent", "disabled_toolsets") || [] end |
#agent_max_tool_iterations ⇒ Object
-- Agent section --
Iteration/time caps fall back to the built-in defaults when the config
value is nil/missing (e.g. config set agent.max_tool_iterations nil,
whose writer coerces "nil" -> nil). A bare nil here would crash every
turn in IterationBudget's numeric comparisons (#139).
154 155 156 |
# File 'lib/rubino/config/configuration.rb', line 154 def agent_max_tool_iterations dig("agent", "max_tool_iterations") || Defaults.dig("agent", "max_tool_iterations") end |
#agent_max_turn_seconds ⇒ Object
158 159 160 |
# File 'lib/rubino/config/configuration.rb', line 158 def agent_max_turn_seconds dig("agent", "max_turn_seconds") || Defaults.dig("agent", "max_turn_seconds") end |
#api_allow_public_bind? ⇒ Boolean
-- API section -- Whether the HTTP API server may bind to a non-loopback address. SAFE BY DEFAULT (#577): false REFUSES a routable bind (the API runs shell tools); set true to deliberately publish the listener (use TLS + a strong key).
484 485 486 |
# File 'lib/rubino/config/configuration.rb', line 484 def api_allow_public_bind? dig("api", "allow_public_bind") == true end |
#approvals_readonly_commands ⇒ Object
Extra command names / leading-token prefixes merged into the built-in read-only set (Security::ReadonlyCommands::SAFE_COMMANDS).
392 393 394 |
# File 'lib/rubino/config/configuration.rb', line 392 def approvals_readonly_commands dig("approvals", "readonly_commands") || [] end |
#approvals_wait_timeout ⇒ Object
-- Security section -- Seconds a run blocks on a human approval/clarification before the gate gives up and AUTO-DENIES (freeing the worker thread). nil = wait indefinitely (interruptible only by an explicit stop). Used by ApprovalGate as its default await deadline so an abandoned approval never parks a server worker for the whole window (W1).
376 377 378 379 380 381 |
# File 'lib/rubino/config/configuration.rb', line 376 def approvals_wait_timeout raw = dig("approvals", "wait_timeout_seconds") return nil if raw.nil? raw.to_f end |
#auto_allow_readonly? ⇒ Boolean
Auto-allow provably read-only shell commands (ls, cat, grep, git log, ...) without an approval prompt. Default ON (key absent = on); the hardline floor and permissions:deny still precede it.
386 387 388 |
# File 'lib/rubino/config/configuration.rb', line 386 def auto_allow_readonly? dig("approvals", "auto_allow_readonly") != false end |
#auxiliary_config(task) ⇒ Object
Generic accessor for auxiliary task config blocks. Returns {} when the task isn't defined, so callers can chain .dig safely.
440 441 442 |
# File 'lib/rubino/config/configuration.rb', line 440 def auxiliary_config(task) dig("auxiliary", task.to_s) || {} end |
#auxiliary_on_main_endpoint?(task) ⇒ Boolean
True when the auxiliary task resolves to the SAME server ENDPOINT as the
main model — i.e. its LLM calls land on the main model server's KV slot.
Slot-sharing is about the endpoint (provider + base_url), NOT the model: a
different model on the SAME server still shares the single slot. At the
defaults (auxiliary.
It matters for local single-slot servers: an aux call sharing the slot OVERWRITES the live conversation's KV-cache prefix, so the next user turn re-prefills the whole context (the "freeze after N turns"). The post-turn extraction/distill gates use this to stay OFF the interactive slot, mirroring how Hermes/Claude Code keep automatic memory work off the live conversation (extract at session end instead). A DISTINCT aux endpoint (its own server/slot) does not evict, so inter-turn extraction stays on.
457 458 459 460 461 462 463 464 465 466 467 |
# File 'lib/rubino/config/configuration.rb', line 457 def auxiliary_on_main_endpoint?(task) cfg = auxiliary_config(task) provider = cfg["provider"].to_s.strip aux_provider = provider.empty? || provider == "main" ? dig("model", "provider").to_s : provider aux_base = cfg["base_url"].to_s.strip aux_base = provider_config(aux_provider)["base_url"].to_s.strip if aux_base.empty? main_base = provider_config(dig("model", "provider").to_s)["base_url"].to_s.strip aux_provider == dig("model", "provider").to_s && aux_base == main_base end |
#auxiliary_vision_config ⇒ Object
-- Auxiliary section --
434 435 436 |
# File 'lib/rubino/config/configuration.rb', line 434 def auxiliary_vision_config dig("auxiliary", "vision") || {} end |
#clarify_timeout ⇒ Object
Bound (seconds) an interactive question/clarify waits for the human to
answer before it EXPIRES CLEANLY and the agent proceeds with its best
judgement (#552). Mirrors the Hermes clarify_timeout convention — a
generous upper bound (default 600s = 10 min, well above
human reading/deliberation time), never the 30s stale-chunk window and
never "forever". An abandoned clarify self-heals into the NO_ANSWER
outcome instead of hanging the run or being killed by the stale watchdog.
222 223 224 |
# File 'lib/rubino/config/configuration.rb', line 222 def clarify_timeout dig("clarify", "timeout") || Defaults.dig("clarify", "timeout") end |
#compression_enabled? ⇒ Boolean
-- Compression section --
270 271 272 |
# File 'lib/rubino/config/configuration.rb', line 270 def compression_enabled? dig("compression", "enabled") == true end |
#compression_preserve_tool_pairs? ⇒ Boolean
274 275 276 |
# File 'lib/rubino/config/configuration.rb', line 274 def compression_preserve_tool_pairs? dig("compression", "preserve_tool_pairs") == true end |
#confirm_policy ⇒ Object
Effective shell prompt policy and SOLE source of truth (item 7): the
legacy security.require_confirmation_for_shell alias was REMOVED — no
back-compat mapping. :dangerous_only (DEFAULT — safe shell commands run
unprompted; only DangerousPatterns matches prompt) or :confirm_all (every
not-otherwise-allowed shell command prompts). An unset or unrecognized
value falls back to the seeded :dangerous_only default. A config that
still carries the removed key is NOT silently honored — Validator.warnings
flags it at load + in rubino doctor.
404 405 406 407 408 409 |
# File 'lib/rubino/config/configuration.rb', line 404 def confirm_policy raw = dig("security", "confirm_policy") return raw.to_sym if %w[confirm_all dangerous_only].include?(raw.to_s) :dangerous_only end |
#database_path ⇒ Object
-- Database section -- Resolves the sqlite path. The DEFAULT (sentinel) follows the resolved home so RUBINO_HOME relocates the DB alongside config/.env/skills, avoiding the split brain where config went to the isolated home but the DB to the real ~/.rubino (issue #96). An EXPLICIT database.path in config.yml wins and is expanded verbatim.
21 22 23 24 25 26 27 28 |
# File 'lib/rubino/config/configuration.rb', line 21 def database_path path = dig("database", "path") if path == Defaults::DEFAULT_DATABASE_PATH File.join(resolved_home, "rubino.sqlite3") else File.(path) end end |
#dig(*keys) ⇒ Object
-- Generic access --
489 490 491 |
# File 'lib/rubino/config/configuration.rb', line 489 def dig(*keys) @raw.dig(*keys) end |
#display_code_highlight? ⇒ Boolean
Syntax-highlight committed code blocks (display.code_highlight). Default true; only an explicit false falls back to plain (uncoloured) code.
79 80 81 |
# File 'lib/rubino/config/configuration.rb', line 79 def display_code_highlight? dig("display", "code_highlight") != false end |
#display_input_max_rows ⇒ Object
Cap on the chat input's visual rows (display.input_max_rows). Falls back to the composer default for nil/zero/garbage so a bad value can never collapse or unbound the input block.
58 59 60 61 |
# File 'lib/rubino/config/configuration.rb', line 58 def display_input_max_rows value = dig("display", "input_max_rows").to_i value.positive? ? value : UI::BottomComposer::MAX_INPUT_ROWS end |
#display_live_markdown? ⇒ Boolean
Render the in-flight streamed block as formatted markdown in the live region (display.live_markdown). Default true; only an explicit false falls back to the legacy raw live tail.
66 67 68 |
# File 'lib/rubino/config/configuration.rb', line 66 def display_live_markdown? dig("display", "live_markdown") != false end |
#display_statusbar? ⇒ Boolean
The status bar under the chat input (display.statusbar, default true). Only an explicit false disables it.
42 43 44 |
# File 'lib/rubino/config/configuration.rb', line 42 def dig("display", "statusbar") != false end |
#display_streaming? ⇒ Boolean
-- Display section --
36 37 38 |
# File 'lib/rubino/config/configuration.rb', line 36 def display_streaming? dig("display", "streaming") == true end |
#display_synchronized_output? ⇒ Boolean
Wrap each live-region frame in DEC-2026 synchronized output (display.synchronized_output). Default true; only an explicit false falls back to the legacy per-write frames.
73 74 75 |
# File 'lib/rubino/config/configuration.rb', line 73 def display_synchronized_output? dig("display", "synchronized_output") != false end |
#display_tool_output_preview_lines ⇒ Object
Transcript preview budget for tool output (display.tool_output_preview_lines): head lines shown before the "… +N lines (full output → context)" marker. 0 = no collapse (full dump). Display-only — the model-facing output is untouched.
50 51 52 53 |
# File 'lib/rubino/config/configuration.rb', line 50 def display_tool_output_preview_lines value = dig("display", "tool_output_preview_lines") value.nil? ? 3 : value.to_i end |
#doom_loop_hard_stop? ⇒ Boolean
-- Doom-loop guard (#414) -- Default WARN-not-block (hard_stop false): a tripped detector surfaces a warning to the model but does not deny the call.
138 139 140 |
# File 'lib/rubino/config/configuration.rb', line 138 def doom_loop_hard_stop? dig("doom_loop", "hard_stop") == true end |
#doom_loop_threshold ⇒ Object
Identical-consecutive-call threshold. Falls back to the detector default when absent/garbage so a bad config value can't disable the guard.
144 145 146 147 |
# File 'lib/rubino/config/configuration.rb', line 144 def doom_loop_threshold n = Integer(dig("doom_loop", "threshold"), exception: false) n && n >= 2 ? n : Security::DoomLoopDetector::DEFAULT_THRESHOLD end |
#memory_auto_extract? ⇒ Boolean
283 284 285 |
# File 'lib/rubino/config/configuration.rb', line 283 def memory_auto_extract? dig("memory", "auto_extract") == true end |
#memory_auto_extract_interval ⇒ Object
Throttle interval (in turns) for memory.auto_extract (#412). Returns a positive Integer; nil/<=1 (or absent) ⇒ 1 = every turn. The lifecycle only enqueues ExtractMemoryJob when turns-since-last >= this.
290 291 292 |
# File 'lib/rubino/config/configuration.rb', line 290 def memory_auto_extract_interval positive_interval(dig("memory", "auto_extract_interval")) end |
#memory_enabled? ⇒ Boolean
-- Memory section --
279 280 281 |
# File 'lib/rubino/config/configuration.rb', line 279 def memory_enabled? dig("memory", "enabled") == true end |
#model_supports_vision? ⇒ Boolean
Returns true when the primary model can ingest images directly. Honours
an explicit model.supports_vision override; otherwise falls back to
ContentBuilder's name-pattern heuristic. Used by VisionTool to decide
whether to expose itself (no point delegating if the primary can see).
473 474 475 476 477 478 |
# File 'lib/rubino/config/configuration.rb', line 473 def model_supports_vision? raw = dig("model", "supports_vision") return raw == true unless raw.nil? LLM::ContentBuilder.supports_vision?(dig("model", "default").to_s) end |
#notifications_bell? ⇒ Boolean
116 117 118 |
# File 'lib/rubino/config/configuration.rb', line 116 def notifications_bell? dig("notifications", "bell") != false end |
#notifications_command ⇒ Object
120 121 122 123 |
# File 'lib/rubino/config/configuration.rb', line 120 def notifications_command value = dig("notifications", "command").to_s value.empty? ? nil : value end |
#notifications_enabled? ⇒ Boolean
-- Notifications section (UI::Notifier: attention bell + hook) -- enabled/bell are on unless explicitly false; command is nil unless a non-empty string is set; min_turn_seconds falls back to the default.
112 113 114 |
# File 'lib/rubino/config/configuration.rb', line 112 def notifications_enabled? dig("notifications", "enabled") != false end |
#notifications_min_turn_seconds ⇒ Object
125 126 127 128 |
# File 'lib/rubino/config/configuration.rb', line 125 def notifications_min_turn_seconds value = dig("notifications", "min_turn_seconds") (value.nil? ? Defaults.dig("notifications", "min_turn_seconds") : value).to_f end |
#paste_collapse_chars ⇒ Object
A paste with MORE than this many CHARACTERS also collapses to a placeholder, even on a single line — a big one-line paste (a long token, URL, minified JSON) would otherwise flood the composer because the line-count trigger never fired. Falls back for nil/zero/garbage.
96 97 98 99 |
# File 'lib/rubino/config/configuration.rb', line 96 def paste_collapse_chars value = dig("paste", "collapse_chars").to_i value.positive? ? value : UI::PasteStore::DEFAULT_COLLAPSE_CHARS end |
#paste_collapse_lines ⇒ Object
-- Paste section (UI::PasteStore: the file-backed paste pipeline) -- A paste with MORE than this many lines collapses to a "[Pasted text #N +M lines]" placeholder in the composer (expanded to the full body at send). Falls back for nil/zero/garbage.
87 88 89 90 |
# File 'lib/rubino/config/configuration.rb', line 87 def paste_collapse_lines value = dig("paste", "collapse_lines").to_i value.positive? ? value : UI::PasteStore::DEFAULT_COLLAPSE_LINES end |
#paste_file_threshold_tokens ⇒ Object
A paste estimated above this many tokens (chars/4, the same rule
compaction uses) overflows to
104 105 106 107 |
# File 'lib/rubino/config/configuration.rb', line 104 def paste_file_threshold_tokens value = dig("paste", "file_threshold_tokens").to_i value.positive? ? value : UI::PasteStore::DEFAULT_THRESHOLD_TOKENS end |
#prompts_environment_enabled? ⇒ Boolean
237 238 239 240 241 242 |
# File 'lib/rubino/config/configuration.rb', line 237 def prompts_environment_enabled? # Default to on when the key is absent — env injection is the cheap # win we don't want a forgetful config.yml to disable accidentally. value = dig("prompts", "environment", "enabled") value.nil? || value == true end |
#prompts_environment_extra_utilities ⇒ Object
244 245 246 |
# File 'lib/rubino/config/configuration.rb', line 244 def prompts_environment_extra_utilities Array(dig("prompts", "environment", "extra_utilities")).map(&:to_s) end |
#prompts_override_for(role) ⇒ Object
Returns the override string for a given role name, or nil if the built-in default prompt should be used.
250 251 252 253 254 255 256 |
# File 'lib/rubino/config/configuration.rb', line 250 def prompts_override_for(role) value = dig("prompts", "overrides", role.to_s) return nil if value.nil? text = value.to_s.strip text.empty? ? nil : text end |
#prompts_preamble ⇒ Object
-- Prompts section -- The customer-facing preamble prepended to every assembled system prompt. nil/empty disables the layer.
229 230 231 232 233 234 235 |
# File 'lib/rubino/config/configuration.rb', line 229 def prompts_preamble value = dig("prompts", "preamble") return nil if value.nil? text = value.to_s.strip text.empty? ? nil : text end |
#provider_config(name) ⇒ Object
-- Providers section --
429 430 431 |
# File 'lib/rubino/config/configuration.rb', line 429 def provider_config(name) dig("providers", name.to_s) || {} end |
#reload! ⇒ Object
502 503 504 |
# File 'lib/rubino/config/configuration.rb', line 502 def reload! @raw = load_from_file end |
#run_idle_event_timeout ⇒ Object
-- Run lifecycle section -- Returns Float seconds (or nil to disable). EventsOperation uses this to bound how long a "running" row can go without producing a new event before the watchdog promotes it to failed.
262 263 264 265 266 267 |
# File 'lib/rubino/config/configuration.rb', line 262 def run_idle_event_timeout raw = dig("run", "idle_event_timeout") return nil if raw.nil? raw.to_f end |
#security_command_allowlist ⇒ Object
The pre-approved command allowlist, always returned as an Array.
YAML lets a user write command_allowlist: git status (a scalar) where
a sequence was meant. The matcher (CommandAllowlist#allowlist_token_lists)
calls #filter_map on this value; a bare String would raise an unhandled
NoMethodError out of the approval path (a crash, not the clean
fail-closed contract — CFG-R3-1). Coerce a scalar to a single-entry
array and drop any nil so the matcher always receives a well-formed list.
419 420 421 422 423 424 425 426 |
# File 'lib/rubino/config/configuration.rb', line 419 def security_command_allowlist raw = dig("security", "command_allowlist") case raw when Array then raw when nil then [] else [raw] end end |
#set(*keys, value) ⇒ Object
493 494 495 496 497 498 499 500 |
# File 'lib/rubino/config/configuration.rb', line 493 def set(*keys, value) hash = @raw keys[0..-2].each do |key| hash[key] ||= {} hash = hash[key] end hash[keys.last] = value end |
#skills_auto_distill? ⇒ Boolean
Post-turn skill distillation. Defaults to true (skills feature on + distill key absent ⇒ distill on), mirroring memory_auto_extract? as the gate for an aux-spending background job. Turning skills off disables it too, since there is no point distilling skills that won't be loaded.
298 299 300 301 302 303 |
# File 'lib/rubino/config/configuration.rb', line 298 def skills_auto_distill? return false unless dig("skills", "enabled") != false value = dig("skills", "auto_distill") value.nil? || value == true end |
#skills_auto_distill_interval ⇒ Object
Throttle interval (in turns) for skills.auto_distill (#414). Mirrors memory_auto_extract_interval. nil/<=1 ⇒ every eligible turn.
307 308 309 |
# File 'lib/rubino/config/configuration.rb', line 307 def skills_auto_distill_interval positive_interval(dig("skills", "auto_distill_interval")) end |
#streaming_enabled? ⇒ Boolean
-- Streaming section --
131 132 133 |
# File 'lib/rubino/config/configuration.rb', line 131 def streaming_enabled? dig("streaming", "enabled") == true end |
#tasks_max_children_per_node ⇒ Object
Maximum number of LIVE direct children a single node (the human/top-level or one subagent) may have at once. Default 3.
197 198 199 |
# File 'lib/rubino/config/configuration.rb', line 197 def tasks_max_children_per_node dig("tasks", "max_children_per_node") || Defaults.dig("tasks", "max_children_per_node") end |
#tasks_max_concurrent_total ⇒ Object
Hard global ceiling on the total number of LIVE subagents across the whole tree, so depth × fan-out cannot blow past the process's thread/cost budget. Default 8.
204 205 206 |
# File 'lib/rubino/config/configuration.rb', line 204 def tasks_max_concurrent_total dig("tasks", "max_concurrent_total") || Defaults.dig("tasks", "max_concurrent_total") end |
#tasks_max_depth ⇒ Object
-- Tasks / nested-subagent caps --
Maximum nesting depth for the task delegation tree. depth 0 is a
human/top-level-spawned child; the cap bounds how deep a chain of
subagents-spawning-subagents may go. Default 2 ⇒ human→child→grandchild.
Falls back to the built-in default when missing/nil so the numeric caps
in BackgroundTask#reserve never crash on a bare nil.
191 192 193 |
# File 'lib/rubino/config/configuration.rb', line 191 def tasks_max_depth dig("tasks", "max_depth") || Defaults.dig("tasks", "max_depth") end |
#tasks_max_live_probes_per_child ⇒ Object
Per-child budget for BILLED live probes (probe(live:true)). Over budget,
the model is steered to the FREE live:false snapshot. Free snapshots are
unlimited. Default 5.
211 212 213 |
# File 'lib/rubino/config/configuration.rb', line 211 def tasks_max_live_probes_per_child dig("tasks", "max_live_probes_per_child") || Defaults.dig("tasks", "max_live_probes_per_child") end |
#tool_enabled?(name) ⇒ Boolean
-- Tools section --
312 313 314 |
# File 'lib/rubino/config/configuration.rb', line 312 def tool_enabled?(name) dig("tools", name.to_s) == true end |
#tool_output_capture_max_bytes ⇒ Object
Hard RAM ceiling for the shell capture seam (#539). Defaults via the defaults hash; coerced to a sane positive floor so a misconfig can't disable the cap and re-open the unbounded-producer OOM.
319 320 321 322 |
# File 'lib/rubino/config/configuration.rb', line 319 def tool_output_capture_max_bytes value = dig("tool_output", "capture_max_bytes").to_i value.positive? ? value : 2_000_000 end |
#tool_output_compression_code ⇒ Object
331 332 333 |
# File 'lib/rubino/config/configuration.rb', line 331 def tool_output_compression_code dig("tool_output_compression", "code") || {} end |
#tool_output_compression_code_languages ⇒ Object
Source languages the code skeletoner is enabled for (e.g. ["ruby"]). A whole-file read whose language isn't in this list passes through verbatim. Ruby uses the built-in Prism parser; later languages need their own parser registered before being added here.
339 340 341 |
# File 'lib/rubino/config/configuration.rb', line 339 def tool_output_compression_code_languages tool_output_compression_code["languages"] || [] end |
#tool_output_compression_diff ⇒ Object
DIFF compression config. Like code, it has NO own enabled sub-flag:
it is active whenever the master tool_output_compression.enabled is on.
The DiffCompressor's saving guard (min_lines + min_saving) is the real
gate — a small/tight diff passes through byte-identical on its own.
347 348 349 |
# File 'lib/rubino/config/configuration.rb', line 347 def tool_output_compression_diff dig("tool_output_compression", "diff") || {} end |
#tool_output_compression_enabled? ⇒ Boolean
Deterministic, reversible compression of tool-read results (whole-file Ruby reads → skeleton). OFF by default: when false the read tool is byte-for-byte unchanged. See Compression::Compressor.
327 328 329 |
# File 'lib/rubino/config/configuration.rb', line 327 def tool_output_compression_enabled? dig("tool_output_compression", "enabled") == true end |
#tool_output_compression_json ⇒ Object
JSON compression config. Like code/diff, it has NO own enabled
sub-flag: it is active whenever the master tool_output_compression.enabled
is on. The JsonCompressor's saving + size guards are the real gate — small
JSON the model wants verbatim passes through byte-identical on its own.
362 363 364 |
# File 'lib/rubino/config/configuration.rb', line 362 def tool_output_compression_json dig("tool_output_compression", "json") || {} end |
#tool_output_compression_logs ⇒ Object
LOG/command-output compression config. Independently gated from code
via its own enabled flag, so we can flip the high-ROI log channel on
without touching the code-skeleton channel.
354 355 356 |
# File 'lib/rubino/config/configuration.rb', line 354 def tool_output_compression_logs dig("tool_output_compression", "logs") || {} end |
#tool_output_compression_logs_enabled? ⇒ Boolean
366 367 368 |
# File 'lib/rubino/config/configuration.rb', line 366 def tool_output_compression_logs_enabled? tool_output_compression_logs["enabled"] == true end |
#ui_verbose? ⇒ Boolean
-- UI section --
31 32 33 |
# File 'lib/rubino/config/configuration.rb', line 31 def ui_verbose? dig("ui", "verbose") == true end |