@@ -59,6 +59,19 @@ def _verify_dashboard_auth(request: Request) -> None:
5959 raise HTTPException (401 , error )
6060
6161
62+ def _parse_positive_float (value : Any , field : str , fallback : float ) -> float :
63+ """Validate *value* as a positive float, returning *fallback* if None."""
64+ if value is None :
65+ return fallback
66+ try :
67+ result = float (value )
68+ if result <= 0 :
69+ raise ValueError
70+ except (ValueError , TypeError ):
71+ raise HTTPException (status_code = 400 , detail = f"{ field } must be a positive number" )
72+ return result
73+
74+
6275def create_dashboard_router (
6376 blackboard : Blackboard ,
6477 health_monitor : HealthMonitor | None ,
@@ -552,16 +565,14 @@ async def api_update_agent_config(agent_id: str, request: Request) -> dict:
552565 if "budget" in body :
553566 budget_val = body ["budget" ]
554567 if isinstance (budget_val , dict ):
555- daily = budget_val .get ("daily_usd" )
556- if daily is not None :
557- try :
558- daily = float (daily )
559- if daily <= 0 :
560- raise ValueError
561- except (ValueError , TypeError ):
562- raise HTTPException (status_code = 400 , detail = "Budget must be a positive number" )
563- _update_agent_field (agent_id , "budget" , {"daily_usd" : daily })
564- cost_tracker .set_budget (agent_id , daily_usd = daily )
568+ raw_daily = budget_val .get ("daily_usd" )
569+ raw_monthly = budget_val .get ("monthly_usd" )
570+ if raw_daily is not None or raw_monthly is not None :
571+ current = cost_tracker .check_budget (agent_id )
572+ daily = _parse_positive_float (raw_daily , "daily_usd" , current .get ("daily_limit" , 10.0 ))
573+ monthly = _parse_positive_float (raw_monthly , "monthly_usd" , current .get ("monthly_limit" , 200.0 ))
574+ _update_agent_field (agent_id , "budget" , {"daily_usd" : daily , "monthly_usd" : monthly })
575+ cost_tracker .set_budget (agent_id , daily_usd = daily , monthly_usd = monthly )
565576 updated .append ("budget" )
566577
567578 if "thinking" in body :
@@ -633,17 +644,17 @@ async def api_update_budget(agent_id: str, request: Request) -> dict:
633644 if agent_id not in agent_registry :
634645 raise HTTPException (status_code = 404 , detail = "Agent not found" )
635646 body = await request .json ()
636- daily_usd = body .get ("daily_usd" )
637- try :
638- daily_usd = float ( daily_usd )
639- if daily_usd <= 0 :
640- raise ValueError
641- except ( ValueError , TypeError ):
642- raise HTTPException ( status_code = 400 , detail = "daily_usd must be a positive number" )
643- cost_tracker .set_budget (agent_id , daily_usd = daily_usd )
647+ raw_daily = body .get ("daily_usd" )
648+ raw_monthly = body . get ( "monthly_usd" )
649+ if raw_daily is None and raw_monthly is None :
650+ raise HTTPException ( status_code = 400 , detail = "Provide daily_usd and/or monthly_usd" )
651+ current = cost_tracker . check_budget ( agent_id )
652+ daily_usd = _parse_positive_float ( raw_daily , "daily_usd" , current . get ( "daily_limit" , 10.0 ))
653+ monthly_usd = _parse_positive_float ( raw_monthly , "monthly_usd" , current . get ( "monthly_limit" , 200.0 ) )
654+ cost_tracker .set_budget (agent_id , daily_usd = daily_usd , monthly_usd = monthly_usd )
644655 from src .cli .config import _update_agent_field
645- _update_agent_field (agent_id , "budget" , {"daily_usd" : daily_usd })
646- return {"updated" : True , "agent" : agent_id , "daily_usd" : daily_usd }
656+ _update_agent_field (agent_id , "budget" , {"daily_usd" : daily_usd , "monthly_usd" : monthly_usd })
657+ return {"updated" : True , "agent" : agent_id , "daily_usd" : daily_usd , "monthly_usd" : monthly_usd }
647658
648659 @api_router .get ("/api/agents/{agent_id}/permissions" )
649660 async def api_agent_permissions (agent_id : str ) -> dict :
0 commit comments