@@ -3526,12 +3526,22 @@ def _handle_doctor_command(args) -> int:
35263526 # System / CUDA / vLLM / pip-check report.
35273527 system_report = _doctor_system_report (include_pip_check = live )
35283528
3529+ # Circuit-breaker/bulkhead state for any provider that has been routed
3530+ # through effgen.reliability middleware this process — surfaces an open
3531+ # circuit or a saturated bulkhead without the caller instrumenting their
3532+ # own code.
3533+ reliability_report = _doctor_reliability_report ()
3534+
35293535 # Exit nonzero if a live probe was requested and a keyed provider failed.
35303536 # Computed once so every output format (JSON and human) agrees.
35313537 exit_code = _doctor_exit_code (results , live )
35323538
35333539 if getattr (args , 'output_json' , False ):
3534- print (_json .dumps ({"providers" : results , "system" : system_report }, indent = 2 ))
3540+ print (_json .dumps ({
3541+ "providers" : results ,
3542+ "system" : system_report ,
3543+ "reliability" : reliability_report ,
3544+ }, indent = 2 ))
35353545 return exit_code
35363546
35373547 # Pretty-print
@@ -3585,6 +3595,32 @@ def _handle_doctor_command(args) -> int:
35853595 sys_table .add_row (k , str (v ))
35863596 console .print (sys_table )
35873597
3598+ # Reliability section — only shown once a provider has actually been
3599+ # routed through circuit-breaker/bulkhead middleware this process.
3600+ if reliability_report :
3601+ console .print ("\n [bold cyan]Reliability[/bold cyan]" )
3602+ rel_table = Table (show_header = True )
3603+ rel_table .add_column ("Provider" , style = "cyan" , no_wrap = True )
3604+ rel_table .add_column ("Circuit" , style = "white" )
3605+ rel_table .add_column ("Bulkhead" , style = "white" )
3606+ for prov , rec in sorted (reliability_report .items ()):
3607+ cb = rec .get ("circuit_breaker" )
3608+ bh = rec .get ("bulkhead" )
3609+ if cb is None :
3610+ circuit_cell = "[dim]—[/dim]"
3611+ elif cb ["state" ] == "closed" :
3612+ circuit_cell = "[green]closed[/green]"
3613+ elif cb ["state" ] == "half_open" :
3614+ circuit_cell = "[yellow]half_open[/yellow]"
3615+ else :
3616+ circuit_cell = "[red]open[/red]"
3617+ if bh is None :
3618+ bulkhead_cell = "[dim]—[/dim]"
3619+ else :
3620+ bulkhead_cell = f"active={ bh ['active' ]} /{ bh ['max_concurrency' ]} , queued={ bh ['queued' ]} /{ bh ['queue_size' ]} "
3621+ rel_table .add_row (prov , circuit_cell , bulkhead_cell )
3622+ console .print (rel_table )
3623+
35883624 # Print hints for missing keys
35893625 missing = [p for p , i in results .items () if not i .get ("available" )]
35903626 if missing :
@@ -3609,6 +3645,17 @@ def _handle_doctor_command(args) -> int:
36093645 print ("\n System:" )
36103646 for k , v in system_report .items ():
36113647 print (f" { k } : { v } " )
3648+ if reliability_report :
3649+ print ("\n Reliability:" )
3650+ for prov , rec in sorted (reliability_report .items ()):
3651+ cb = rec .get ("circuit_breaker" )
3652+ bh = rec .get ("bulkhead" )
3653+ circuit_str = cb ["state" ] if cb else "—"
3654+ bulkhead_str = (
3655+ f"active={ bh ['active' ]} /{ bh ['max_concurrency' ]} , queued={ bh ['queued' ]} /{ bh ['queue_size' ]} "
3656+ if bh else "—"
3657+ )
3658+ print (f" { prov :12s} circuit={ circuit_str :10s} bulkhead={ bulkhead_str } " )
36123659 missing = [p for p , i in results .items () if not i .get ("available" )]
36133660 if missing :
36143661 print ("\n Missing keys — set in ~/.effgen/.env or export:" )
@@ -3635,6 +3682,27 @@ def _doctor_exit_code(results: dict[str, dict], live: bool) -> int:
36353682 return 0
36363683
36373684
3685+ def _doctor_reliability_report () -> dict [str , dict ]:
3686+ """Circuit-breaker/bulkhead state for providers routed through reliability
3687+ middleware this process, keyed by provider name (empty if none have).
3688+
3689+ A provider only appears once ``ProviderRegistry.get_circuit_breaker``/
3690+ ``get_bulkhead`` has been used for it — no calls yet made means no state
3691+ to report, which is the common case for a fresh CLI invocation.
3692+ """
3693+ try :
3694+ from effgen .models .registry import ProviderRegistry
3695+
3696+ stats = ProviderRegistry .reliability_stats ()
3697+ except Exception :
3698+ return {}
3699+ return {
3700+ prov : rec
3701+ for prov , rec in stats .items ()
3702+ if rec .get ("circuit_breaker" ) is not None or rec .get ("bulkhead" ) is not None
3703+ }
3704+
3705+
36383706def _doctor_system_report (* , include_pip_check : bool = False ) -> dict [str , Any ]:
36393707 """Collect a CUDA / torch / vLLM / pip-check diagnostic snapshot."""
36403708 report : dict [str , Any ] = {}
0 commit comments