Class: Aidp::Harness::ThinkingDepthManager
- Inherits:
-
Object
- Object
- Aidp::Harness::ThinkingDepthManager
- Includes:
- MessageDisplay
- Defined in:
- lib/aidp/harness/thinking_depth_manager.rb
Overview
Manages thinking depth tier selection and escalation Integrates with CapabilityRegistry and Configuration to select appropriate models
Constant Summary
Constants included from MessageDisplay
Instance Attribute Summary collapse
-
#configuration ⇒ Object
readonly
Returns the value of attribute configuration.
-
#escalation_count ⇒ Object
readonly
Get escalation attempt count.
-
#registry ⇒ Object
readonly
Returns the value of attribute registry.
Instance Method Summary collapse
-
#can_escalate? ⇒ Boolean
Check if we can escalate to next tier.
-
#current_tier ⇒ Object
Get current tier (defaults to config default_tier if not set).
-
#current_tier=(tier) ⇒ Object
Set current tier (validates against max_tier).
-
#de_escalate_tier(reason: nil) ⇒ Object
De-escalate to next lower tier Returns new tier or nil if already at minimum.
-
#default_tier ⇒ Object
Get default tier from configuration.
-
#escalate_tier(reason: nil) ⇒ Object
Escalate to next higher tier Returns new tier or nil if already at max.
-
#initialize(configuration, registry: nil, root_dir: nil) ⇒ ThinkingDepthManager
constructor
A new instance of ThinkingDepthManager.
-
#max_tier ⇒ Object
Get maximum allowed tier (respects session override).
-
#max_tier=(tier) ⇒ Object
Set maximum tier for this session (temporary override).
-
#permission_for_current_tier ⇒ Object
Get permission level for current tier.
-
#recommend_tier_for_complexity(complexity_score) ⇒ Object
Get tier recommendation based on complexity score (0.0-1.0).
-
#reset_to_default ⇒ Object
Reset to default tier.
-
#select_model_for_tier(tier = nil, provider: nil) ⇒ Object
Select best model for current tier and provider Returns [provider_name, model_name, model_data] or nil.
-
#should_escalate_on_complexity?(context) ⇒ Boolean
Check if should escalate based on complexity thresholds.
-
#should_escalate_on_failures?(failure_count) ⇒ Boolean
Check if should escalate based on failure count.
-
#tier_for_model(provider, model) ⇒ Object
Get tier for a specific model.
-
#tier_history ⇒ Object
Get tier change history.
-
#tier_info(tier) ⇒ Object
Get information about a specific tier.
-
#tier_override_for(key) ⇒ Object
Check if tier override exists for skill/template.
Methods included from MessageDisplay
#display_message, included, #message_display_prompt
Constructor Details
#initialize(configuration, registry: nil, root_dir: nil) ⇒ ThinkingDepthManager
Returns a new instance of ThinkingDepthManager.
16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 16 def initialize(configuration, registry: nil, root_dir: nil) @configuration = configuration @registry = registry || CapabilityRegistry.new(root_dir: root_dir || configuration.instance_variable_get(:@project_dir)) @current_tier = nil @session_max_tier = nil @tier_history = [] @escalation_count = 0 Aidp.log_debug("thinking_depth_manager", "Initialized", default_tier: default_tier, max_tier: max_tier) end |
Instance Attribute Details
#configuration ⇒ Object (readonly)
Returns the value of attribute configuration.
14 15 16 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 14 def configuration @configuration end |
#escalation_count ⇒ Object (readonly)
Get escalation attempt count
350 351 352 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 350 def escalation_count @escalation_count end |
#registry ⇒ Object (readonly)
Returns the value of attribute registry.
14 15 16 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 14 def registry @registry end |
Instance Method Details
#can_escalate? ⇒ Boolean
Check if we can escalate to next tier
94 95 96 97 98 99 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 94 def can_escalate? next_tier = @registry.next_tier(current_tier) return false unless next_tier @registry.compare_tiers(next_tier, max_tier) <= 0 end |
#current_tier ⇒ Object
Get current tier (defaults to config default_tier if not set)
30 31 32 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 30 def current_tier @current_tier || default_tier end |
#current_tier=(tier) ⇒ Object
Set current tier (validates against max_tier)
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 35 def current_tier=(tier) validate_tier!(tier) old_tier = current_tier @current_tier = enforce_max_tier(tier) if @current_tier != tier Aidp.log_warn("thinking_depth_manager", "Tier capped at max", requested: tier, applied: @current_tier, max: max_tier) end if @current_tier != old_tier log_tier_change(old_tier, @current_tier, "manual_set") end end |
#de_escalate_tier(reason: nil) ⇒ Object
De-escalate to next lower tier Returns new tier or nil if already at minimum
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 129 def de_escalate_tier(reason: nil) prev_tier = @registry.previous_tier(current_tier) unless prev_tier Aidp.log_debug("thinking_depth_manager", "Cannot de-escalate", current: current_tier) return nil end old_tier = current_tier @current_tier = prev_tier @escalation_count = [@escalation_count - 1, 0].max log_tier_change(old_tier, prev_tier, reason || "de-escalation") Aidp.log_info("thinking_depth_manager", "De-escalated tier", from: old_tier, to: prev_tier, reason: reason) prev_tier end |
#default_tier ⇒ Object
Get default tier from configuration
75 76 77 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 75 def default_tier configuration.default_tier end |
#escalate_tier(reason: nil) ⇒ Object
Escalate to next higher tier Returns new tier or nil if already at max
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 103 def escalate_tier(reason: nil) unless can_escalate? Aidp.log_warn("thinking_depth_manager", "Cannot escalate", current: current_tier, max: max_tier, reason: reason) return nil end old_tier = current_tier new_tier = @registry.next_tier(current_tier) @current_tier = new_tier @escalation_count += 1 log_tier_change(old_tier, new_tier, reason || "escalation") Aidp.log_info("thinking_depth_manager", "Escalated tier", from: old_tier, to: new_tier, reason: reason, count: @escalation_count) new_tier end |
#max_tier ⇒ Object
Get maximum allowed tier (respects session override)
53 54 55 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 53 def max_tier @session_max_tier || configuration.max_tier end |
#max_tier=(tier) ⇒ Object
Set maximum tier for this session (temporary override)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 58 def max_tier=(tier) validate_tier!(tier) old_max = max_tier @session_max_tier = tier # If current tier exceeds new max, cap it if @registry.compare_tiers(current_tier, tier) > 0 self.current_tier = tier end Aidp.log_info("thinking_depth_manager", "Max tier updated", old: old_max, new: tier, current: current_tier) end |
#permission_for_current_tier ⇒ Object
Get permission level for current tier
345 346 347 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 345 def configuration.(current_tier) end |
#recommend_tier_for_complexity(complexity_score) ⇒ Object
Get tier recommendation based on complexity score (0.0-1.0)
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 307 def recommend_tier_for_complexity(complexity_score) tier = @registry.recommend_tier_for_complexity(complexity_score) # Cap at max_tier if @registry.compare_tiers(tier, max_tier) > 0 Aidp.log_debug("thinking_depth_manager", "Recommended tier capped", recommended: tier, complexity: complexity_score, capped_to: max_tier) return max_tier end Aidp.log_debug("thinking_depth_manager", "Recommended tier", tier: tier, complexity: complexity_score) tier end |
#reset_to_default ⇒ Object
Reset to default tier
80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 80 def reset_to_default old_tier = current_tier @current_tier = nil @session_max_tier = nil @escalation_count = 0 Aidp.log_info("thinking_depth_manager", "Reset to default", old: old_tier, new: current_tier) current_tier end |
#select_model_for_tier(tier = nil, provider: nil) ⇒ Object
Select best model for current tier and provider Returns [provider_name, model_name, model_data] or nil
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 152 def select_model_for_tier(tier = nil, provider: nil) tier ||= current_tier validate_tier!(tier) # First, try to get models from user's configuration for this tier and provider if provider configured_models = configuration.models_for_tier(tier, provider) if configured_models.any? # Use first configured model for this provider and tier model_name = configured_models.first # Check if model is deprecated and try to upgrade require_relative "ruby_llm_registry" unless defined?(Aidp::Harness::RubyLLMRegistry) llm_registry = Aidp::Harness::RubyLLMRegistry.new if llm_registry.model_deprecated?(model_name, provider) Aidp.log_warn("thinking_depth_manager", "Configured model is deprecated", tier: tier, provider: provider, model: model_name) # Try to find replacement replacement = llm_registry.find_replacement_model(model_name, provider: provider) if replacement Aidp.log_info("thinking_depth_manager", "Auto-upgrading to non-deprecated model", tier: tier, provider: provider, old_model: model_name, new_model: replacement) model_name = replacement else # Try next model in config list non_deprecated = configured_models.find { |m| !llm_registry.model_deprecated?(m, provider) } if non_deprecated Aidp.log_info("thinking_depth_manager", "Using alternate configured model", tier: tier, provider: provider, skipped: model_name, selected: non_deprecated) model_name = non_deprecated else Aidp.log_warn("thinking_depth_manager", "All configured models deprecated, falling back to catalog", tier: tier, provider: provider) # Fall through to catalog selection model_name = nil end end end if model_name Aidp.log_debug("thinking_depth_manager", "Selected model from user config", tier: tier, provider: provider, model: model_name) return [provider, model_name, {}] end end # Provider specified but has no models for this tier in config # Try catalog for the specified provider before switching providers Aidp.log_debug("thinking_depth_manager", "Provider has no configured models for tier, trying catalog", tier: tier, provider: provider) # Continue to catalog-based selection below (will try specified provider first) else # No provider specified - this should not happen in normal flow # Log warning and fall through to catalog-based selection Aidp.log_warn("thinking_depth_manager", "select_model_for_tier called without provider", tier: tier) end # Fall back to catalog-based selection if no models in user config # If provider specified, try to find model for that provider in catalog if provider model_name, model_data = @registry.best_model_for_tier(tier, provider) if model_name Aidp.log_debug("thinking_depth_manager", "Selected model from catalog", tier: tier, provider: provider, model: model_name) return [provider, model_name, model_data] end # If provider doesn't support tier and switching allowed, try others unless configuration.allow_provider_switch_for_tier? Aidp.log_warn("thinking_depth_manager", "Provider lacks tier in catalog, switching disabled", tier: tier, provider: provider) return nil end end # Try all providers in catalog if provider && !configuration.allow_provider_switch_for_tier? return nil end providers_to_try = provider ? [@registry.provider_names - [provider]].flatten : @registry.provider_names providers_to_try.each do |prov_name| model_name, model_data = @registry.best_model_for_tier(tier, prov_name) if model_name Aidp.log_info("thinking_depth_manager", "Selected model from catalog (alternate provider)", tier: tier, original_provider: provider, selected_provider: prov_name, model: model_name) return [prov_name, model_name, model_data] end end # No model found for requested tier - try fallback to other tiers Aidp.log_warn("thinking_depth_manager", "No model found for requested tier, trying fallback", tier: tier, provider: provider) result = try_fallback_tiers(tier, provider) unless result # Enhanced error message with discovery hints display_enhanced_tier_error(tier, provider) Aidp.log_error("thinking_depth_manager", "No model found for tier or fallback tiers", tier: tier, provider: provider) end result end |
#should_escalate_on_complexity?(context) ⇒ Boolean
Check if should escalate based on complexity thresholds
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 364 def should_escalate_on_complexity?(context) thresholds = configuration.escalation_complexity_threshold return false if thresholds.empty? files_changed = context[:files_changed] || 0 modules_touched = context[:modules_touched] || 0 exceeds_threshold = false if thresholds[:files_changed] && files_changed >= thresholds[:files_changed] exceeds_threshold = true end if thresholds[:modules_touched] && modules_touched >= thresholds[:modules_touched] exceeds_threshold = true end if exceeds_threshold Aidp.log_debug("thinking_depth_manager", "Complexity check", files: files_changed, modules: modules_touched, exceeds: exceeds_threshold) end exceeds_threshold end |
#should_escalate_on_failures?(failure_count) ⇒ Boolean
Check if should escalate based on failure count
358 359 360 361 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 358 def should_escalate_on_failures?(failure_count) threshold = configuration.escalation_fail_attempts failure_count >= threshold end |
#tier_for_model(provider, model) ⇒ Object
Get tier for a specific model
286 287 288 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 286 def tier_for_model(provider, model) @registry.tier_for_model(provider, model) end |
#tier_history ⇒ Object
Get tier change history
353 354 355 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 353 def tier_history @tier_history.dup end |
#tier_info(tier) ⇒ Object
Get information about a specific tier
291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 291 def tier_info(tier) validate_tier!(tier) { tier: tier, priority: @registry.tier_priority(tier), next_tier: @registry.next_tier(tier), previous_tier: @registry.previous_tier(tier), available_models: @registry.models_by_tier(tier), at_max: tier == max_tier, at_min: @registry.previous_tier(tier).nil?, can_escalate: can_escalate_to?(tier) } end |
#tier_override_for(key) ⇒ Object
Check if tier override exists for skill/template
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/aidp/harness/thinking_depth_manager.rb', line 326 def tier_override_for(key) override = configuration.tier_override_for(key) return nil unless override validate_tier!(override) # Cap at max_tier if @registry.compare_tiers(override, max_tier) > 0 Aidp.log_warn("thinking_depth_manager", "Override tier exceeds max", key: key, override: override, max: max_tier) return max_tier end override end |