
    8i<                        U d Z ddlZddlZddlZddlZddlZddlmZmZmZ ddl	m
Z
  e
d      Zedz  dz  Zedz  d	z  Zedz  d
z  Zej                  j!                  d ee             dZdZ ed      Zddg dddddg dddddg dddddg dddd d!g d"d#dd$d%g d&d'dd(Zeeef   ed)<   i d*d+d,d+d-d+d.d+d/d+d0d+d1d2d3d2d4d2d5d2d6d2d7d2d8d9d:d9d;d9d<d9d=d>d>d>d>d?d?d@Zeeef   edA<   dBefdCZdBefdDZdBefdEZdBefdFZdGedBdfdHZdIedBee ef   fdJZ!dKedLedMe"dNedOedBdfdPZ#dOedBefdQZ$dRedMe"dSe"dBefdTZ%	 	 	 	 d]dOedSe"dUe"dRedVe dBefdWZ&d^dXZ'd^dYZ(d^dZZ)d^d[Z*e+d\k(  r e         e*        yy)_a
  
Genesis $50/Day Swarm Launcher
================================
Budget: $50 USD/day = ~8,000 MiniMax stories at $0.006/story

Usage:
    python3 launch_swarm_50.py --mission "Build X" --stories 50
    python3 launch_swarm_50.py --mission "Research Y" --agents 20 --model minimax
    python3 launch_swarm_50.py --budget-check      # Show remaining daily budget
    python3 launch_swarm_50.py --list-models       # Show available models and costs
    python3 launch_swarm_50.py --status            # Show all active swarms
    N)datetimetimezone	timedelta)Pathz/mnt/e/genesis-systemconfigzsecrets.envdatazdaily_budget.jsonswarm_progressg      I@g      4@
   )hourszgoogle/gemini-2.5-flashgMb`?)research
extractionbulki  )openrouter_idcost_per_call_usdbest_forstories_per_dollarzminimax/minimax-01g~jtx?)codingbackendapi   zdeepseek/deepseek-chatgMbP?)r   classificationkgi  zmoonshot/moonshot-v1-8kg~jth?)frontenduireacthtmliM  zanthropic/claude-haiku-4-5gMbp?)testingsummarizationvoice   zanthropic/claude-sonnet-4-5g~jt?)architecturecomplexreviewS   )gemini-flashminimaxdeepseekkimihaikusonnetMODELSr   r%   findsearchanalyseanalyzescrapebuildr&   code	implementfixr   r   extractr'   classifyr   	knowledger   r(   r)   )r   r   r   test	summarizeTASK_TO_MODELreturnc                     t         j                         st        dt                 yt         j                         j	                         D ]w  } | j                         } | j                  d      s%| j                  dd      }t        |      dk(  sF|d   j                         j                  d      j                  d      c S  t        j                  j                  dd      S )	z0Load OPENROUTER_API_KEY from config/secrets.env.z [ERROR] Secrets file not found:  OPENROUTER_API_KEY=      "')SECRETS_FILEexistsprint	read_text
splitlinesstrip
startswithsplitlenosenvironget)linepartss     0/mnt/e/genesis-system/scripts/launch_swarm_50.pyload_openrouter_keyrS   m   s     0?@&&(335 >zz|??/0JJsA&E5zQQx~~'--c288==> ::>>.33    c                  t    t        j                  t        j                        t        z   j                  d      S )Nz%Y-%m-%d)r   nowr   utcAEST_OFFSETstrftime rT   rR   _today_aestr[      s%    LL&4>>zJJrT   c                  d    t        j                  t        j                        j	                         S )N)r   rV   r   rW   	isoformatrZ   rT   rR   _now_tsr^      s    <<%//11rT   c                     t         j                  j                  dd       t               } t         j	                         r?	 t        j                  t         j                               }|j                  d      | k(  r|S 	 | ddg t               d}t         j                  t        j                  |d             t        d	|  d
t        d       |S # t
        j                  t        f$ r Y mw xY w)z%Load or initialise daily budget JSON.Tparentsexist_ok	date_aest        r   )rc   total_spent_usdstory_count
agent_runslast_updatedrA   indentz&[BUDGET] Initialised daily budget for u    — $0.00 / $.2f)DAILY_BUDGET_FILEparentmkdirr[   rE   jsonloadsrG   rO   JSONDecodeErrorOSErrorr^   
write_textdumpsrF   DAILY_BUDGET_LIMIT_USD)todayr   freshs      rR   load_budgetrx      s    ""4$"?ME!	::/99;<Dxx$- . 	E   E!!<=	25'H^_bGc
deL $$g. 		s   <C C-,C-budgetc                 r    t               | d<   t        j                  t        j                  | d             y )Nrh   rA   ri   )r^   rl   rs   ro   rt   )ry   s    rR   save_budgetr{      s'    $YF>  F1!=>rT   estimated_costc                 Z    t               }|j                  dd      }t        |z
  }| |k  |fS )zs
    Check if we have budget for estimated_cost.

    Returns
    -------
    (ok: bool, remaining_usd: float)
    re   rd   )rx   rO   ru   )r|   ry   spent	remainings       rR   check_budgetr      s6     ]FJJ(#.E&.IY&	11rT   run_idmodelagent_countcostmissionc           	          t               }|j                  dd      |z   |d<   |j                  dd      |z   |d<   |j                  dg       j                  | |dd |||t	               d       t        |       y)	z*Record a spend event in daily_budget.json.re   rd   rf   r   rg   NP   )r   r   r   agentscost_usd	timestamp)rx   rO   
setdefaultappendr^   r{   )r   r   r   r   r   ry   s         rR   record_spendr      s    ]F &

+<c BT IF"JJ}a8;FF=
lB'..3B<Y0  rT   c                 l    | j                         }t        j                         D ]  \  }}||v s|c S  y)z,Select best model based on mission keywords.r&   )lowerr:   items)r   mission_lowerkeyword	model_keys       rR   auto_select_modelr      s=    MMOM+113 m# rT   r   storiesc                     t         j                  | t         d         }t        d|t        d|      z        }|d   |z  |z  S )z$Estimate total cost for a swarm run.r&   r@   r   )r+   rO   max)r   r   r   r   calls_per_agents        rR   estimate_costr      sE    JJy&"34E!WA{(;;<O$%3oEErT   r   dry_runc                    t         j                  dd       |r|t        vrt        |       }t        |   }t	        |||      }t        d       t        d| dd         t        d|        t        d|        t        d	| d
|d    d       t        d|d       t        ddj                  |d                 t        |      \  }}t        d|ddt        d       |s%t        d|dd|dd       t        d       dd|dS |t        kD  r(t        d|ddt        d       t        d       dd|d S |rt        d!       d"||d#S d$t        j                         j                  dd%  }	t               }
|
st        d&       t        d'       d(d)d*S |	| |d   |||d+d+d,|t               t        t         |	z        d-}t         |	 d.z  }|j!                  t#        j$                  |d/0             t'        |	|d   |||        t        d1|	        t        d2| d3| d4|        t        d5       t        d6|        |S )7a  
    Launch a swarm for a given mission.

    Parameters
    ----------
    mission : str
        High-level task description
    stories : int
        Target number of stories/tasks to complete
    agents : int
        Number of parallel agents
    model_key : str
        Model shortname (minimax, gemini-flash, deepseek, kimi, haiku, sonnet)
        Auto-selected if empty.
    dry_run : bool
        If True, show estimate but don't launch

    Returns
    -------
    dict with run metadata
    Tr`   z
[SWARM LAUNCHER]z  Mission   : Nr   z  Stories   : z  Agents    : z  Model     : z (r   )z  Est. Cost : $.4fz  Best for  : , r   z  Remaining : $rk    / $z'
[KILL SWITCH] Daily budget exceeded! $z remaining < $z needed.zT[KILL SWITCH] Refusing to launch new agents. Wait for budget reset at midnight AEST.rejectedbudget_exceeded)statusreasonremaining_usdz
[WARNING] Single-run cost $z exceeds kill threshold $z>[WARNING] Reduce agent count or story count to proceed safely.per_run_kill_threshold)r   r   r|   z9
[DRY RUN] Estimation complete. Pass --execute to launch.r   )r   r|   r   swarm_   z:[ERROR] OPENROUTER_API_KEY not found in config/secrets.envz)[ERROR] Add: OPENROUTER_API_KEY=sk-or-...errormissing_api_key)r   r   r   running)r   r   r   r   r   stories_totalstories_completedstories_completed_this_hourr   estimated_cost_usd
started_at
output_dirz.jsonrA   ri   z
[LAUNCHED] Swarm z[LAUNCHED] z
 agents x z stories via uK   [LAUNCHED] Framework-only mode — attach live API calls in agent_runner.pyz[LAUNCHED] State: )SWARM_PROGRESS_DIRrn   r+   r   r   rF   joinr   ru   KILL_THRESHOLD_USDuuiduuid4hexrS   r^   strrs   ro   rt   r   )r   r   r   r   r   
model_infor|   	budget_okr   r   api_keyswarm_state
state_files                rR   launch_swarmr      s   8 TD9 	/%g.		"J"9fg>N	 	N73B<.
)*	N7)
$%	N6(
#$	N9+R
?(C'DA
FG	ON3/
01	N499Z
%;<=
>? (7Iy	OIc?$/Ec.J
KL83~VdehUiiqrsde$0AT]^^**-nS-AAZ[mnqZrstNO$0H\jkkJK#~PYZZ djjl&&r*+,F!#GJK9:!->?? O, '(,i,v56K $&66J$**[;< O4fngV	x
()	Kxz'-	{
KL	WY	zl
+, rT   c                  r   t               } | j                  dd      }t        |z
  }|t        z  dz  }t        d|z  dz        }d|z  dd|z
  z  z   }| j                  dg       }t	        d| j                  d	d
       d       t	        d|ddt        d       t	        d| d|dd       t	        d|d       t	        d| j                  dd              t	        dt        |              |rFt	        d       |dd  D ]2  }t	        d|d    d|d   d d  d|d     d!|d"   dd#|d$   d d%  
       4 y y )&Nre   rd   d      #-rg   u   
[BUDGET — rc   unknownz AEST]z  Spent    : $r   r   rk   z  Progress : [z] z.1f%z  Remaining: $z  Stories  : rf   r   z  Runs     : z
  Recent runs:z    [r   r      z xr   u    — $r   u    — r   (   )rx   rO   ru   intrF   rL   )ry   r~   r   pct
bar_filledbarrunsruns           rR   show_budgetr   L  s   ]FJJ(#.E&.I))S
0CR#X^$J


SBO4
4C::lB'D	N6::k9=>f
EF	N5+T*@)E
FG	N3%r#c!
,-	N9S/
*+	M&**]A67
89	M#d)
%& "9 	FCE#h-3w<+<*=RHfUXYcUdehTiinors|o}  B  @B  pC  oD  E  F	F rT   c                  P   t         j                         st        d       y t        t         j	                  d            } | st        d       y t        dt        |        d       t        dddd	d
dddddddddddd
       t        d       | dd  D ]  }	 t        j                  |j                               }|j                  d      xs |j                  d|j                        }|j                  dd      }|j                  dd      d d }|j                  dd      }|j                  dd      }|j                  dd      }t        |dd|d
d|dd|dd|dd|d
        y # t        j                  t        f$ r t        |j                  dd       Y w xY w)Nz+[STATUS] No swarm progress directory found.z*.jsonz[STATUS] No swarms found.u   
[SWARM STATUS — z total]zRUN IDz<20 GENERALz<12MODELz<30AGENTSz>6DONEz>5STATUSzZ------------------------------------------------------------------------------------------ir   swarm_idgeneral?r      r   r   r   r   z [corrupt state file])r   rE   rF   sortedglobrL   ro   rp   rG   rO   stemrq   rr   )	filesfdr   r   r   r   doner   s	            rR   show_statusr   a  s   $$&;<%**845E)*	 UG
45	XcN!Ic?!GC=(2ar{RST\]`Sa
bc	(O34[ 8
	8

1;;=)AUU8_Aj!&&(AFeeIs+GEE'3',EUU=!,F55,a0DUU8S)FVCL'#ac{!F2;aRyPQRXY\Q]^_8 $$g. 	8QVVCL 567	8s   CE//2F%$F%c                     t        d       t        ddddddddd	       t        d
       t        j                         D ]6  \  } }t        | dd|d   dd|d   dddj                  |d                 8 t        d       y )Nz"
[AVAILABLE MODELS via OpenRouter]KEYz<14r   zOPENROUTER IDz<35z$/CALLz>8z
  BEST FORzP--------------------------------------------------------------------------------r   z $r   z>6.4fz  r   r   zC
OpenRouter endpoint: https://openrouter.ai/api/v1/chat/completions)rF   r+   r   r   )keyinfos     rR   list_modelsr   |  s    	/1	U3Kq-Qxm:
FG	(O\\^ z	TS	405R=P8QRW7XXZ[_[d[deijteu[vZwxyz	PRrT   c                  $   t        j                  dt         j                  t              } | j	                  ddd       | j	                  ddt
        d	d
       | j	                  ddt
        dd       | j	                  dddj                  t        j                                       | j	                  ddd       | j	                  ddd       | j	                  ddd       | j	                  ddd       | j                         }|j                  rt                y |j                  rt                t                y |j                  rt                y |j                  s;| j!                          t#        d       t#        d       t%        j&                  d       t)        |j                  |j*                  |j,                  |j.                  xs d |j0                   !      }|j3                  d"      d#k(  rt%        j&                  d$       y y )%NzGenesis $50/Day Swarm Launcher)descriptionformatter_classepilogz	--missionz-mzTask/mission description)helpz	--storiesz-s2   zTarget story count (default 50))typedefaultr   z--agentsz-ar
   zParallel agents (default 10)z--modelzModel key: r   z	--execute
store_truez"Actually launch (default: dry-run))actionr   z--budget-checkzShow daily budget statusz--statuszShow all swarm statusesz--list-modelszList available modelsz(
[ERROR] --mission is required. Example:zR  python3 launch_swarm_50.py --mission 'Build the voice widget checkout' --executer@   r=   )r   r   r   r   r   r   r   rA   )argparseArgumentParserRawDescriptionHelpFormatter__doc__add_argumentr   r   r+   keys
parse_argsbudget_checkr   r   r   r   r   
print_helprF   sysexitr   r   r   r   executerO   )parserargsresults      rR   mainr     s   $$4 <<F
 T0JK
TRFgh

DsBEcd
	+dii6N5O(PQ
L?cd
(D^_

<>WX
CZ[D{{<<9:bc{{**"LL F zz(z) *rT   __main__)r   r
   r=   F)r;   N),r   r   ro   rM   r   r   r   r   r   pathlibr   	REPO_ROOTrD   rl   r   pathinsertr   ru   r   rX   r+   dict__annotations__r:   rS   r[   r^   rx   r{   floattupleboolr   r   r   r   r   r   r   r   r   r   __name__rZ   rT   rR   <module>r     sY     	 
  2 2 
 ()	8#m3&)<< '*::  3y> "  b! 3"6!	 ."0!	 2":"	 3"7!	 6"9!	 7"9 	?%S$Y %N!!
N! n! ~	!
 ~! n! Y! I! ! 
9! y! 
9! z! 
! 	*!  !!" #!$ -!tCH~ <4S 4&KS K2 2T 4? ? ?
2 25u+= 2 S s % RU Z^ (s s FS Fs FS FU F hhh h 	h
 h 
h^F*86S-` zMF rT   