
    iBT                     $   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ZddlZddlZddl	Z	ddl
Z
ddlmZ ddlmZ dZe dZe dZe dZd	d
dd	dZddddddddZdZdZ G d d      Z G d d      ZdedefdZdedefdZd Zedk(  r e        yy)aX  
=============================================================================
Genesis Gemini Swarm Launcher
=============================================================================
Launches N parallel Gemini CLI processes, each with a specific task.
Each process is a subprocess (not exec), so crashes are isolated and
the launcher can respawn workers automatically.

Usage:
    python gemini_swarm_launcher.py --tasks tasks.json --workers 10
    python gemini_swarm_launcher.py --tasks tasks.json --workers 5 --dry-run
    python gemini_swarm_launcher.py --list-tasks tasks.json

Task file format (JSON):
    [
        {
            "id": "task_001",
            "priority": 1,
            "type": "browser|code|research|content",
            "prompt": "Your full task prompt here",
            "model": "gemini-2.5-pro",   (optional, defaults to config)
            "timeout_seconds": 300        (optional, default 180)
        },
        ...
    ]

Output: /mnt/e/genesis-system/swarm-output/gemini/{task_id}_{timestamp}.txt
=============================================================================
    N)datetime)Pathz/mnt/e/genesis-systemz/swarm-output/geminiz/Credentials/gemini_api_key.txtz&/.gemini/knowledge/WORK_QUEUE_TODAY.mdg      ?g?333333?)gemini-2.5-progemini-2.5-flashzgemini-2.0-flash-litedefaultr   r   )browserresearchcodecontentscrapingqar         c                   b    e Zd ZdZ	 ddededededef
dZdefd	Z	defd
Z
ddedededefdZy)GeminiWorkerz8Single Gemini CLI worker running a task as a subprocess.task
output_dir	worker_idyolodry_runc                    || _         || _        || _        || _        || _        |j                  dd|d      | _        |j                  d      xs- t        j                  |j                  dd      t        d         | _        |j                  dt              | _
        d| _        d	| _        d | _        d | _        d | _        y )
Nidtask_03dmodeltyper   timeout_secondsr   pending)r   r   r   r   r   gettask_idTASK_TYPE_TO_MODELr   DEFAULT_TIMEOUTtimeoutretriesstatusoutput_file
started_atfinished_at)selfr   r   r   r   r   s         6/mnt/e/genesis-system/scripts/gemini_swarm_launcher.py__init__zGeminiWorker.__init__N   s    	$"	xxi_&=>XXg& 
*<*@*@HHVY');I)F+

 xx 1?C    returnc                    | j                   j                  dd      }| j                   j                  dd      }| j                   j                  dd      }d| j                   d| d	| d
| j                   dt	        j
                         j                          d| d}t        j                  ddd| j                   ddd      }|j                  |       |j                          |j                          |j                  S )zBWrite prompt to a temp file so we can pass it to gemini via stdin.prompt r   generalpriorityc   z# Genesis Task: z
## Priority: z	 | Type: z | Worker: z
## Timestamp: zZ

---

u   

---

## Completion Requirements
- Execute the task completely
- Write all outputs to the specified file paths
- Print a brief summary when done (max 5 lines)
- Do NOT ask for confirmation — JUST EXECUTE
w.txtgenesis_task__z/tmpF)modesuffixprefixdirdelete)r   r    r!   r   r   utcnow	isoformattempfileNamedTemporaryFilewriteflushclosename)r*   r0   	task_typer3   full_prompttmps         r+   _build_prompt_filezGeminiWorker._build_prompt_file`   s    x,IIMM&)4	99==R0*4<<. 9Zy;t~~6F G **,- .  		" ))V"4<<.2	
 			+				xxr-   c                    t        j                         j                         | _        d| _        t        j                         j                  d      }| j                   d| j                   d| d| _        t        d| j                  dd| j                   d	| j                   d
| j                   d	       | j                  rft        d| j                  dd| j                          d| _        t        j                         j                         | _        | j                  dd      S d}	 | j!                         }dg}| j"                  r|j%                  d       t'        |d      5 }|j)                         }ddd       t*        j,                  j/                         }| j                  |d<   t'        | j                  d      5 }|j1                  d       |j1                  d| j                   d       |j1                  d| j                   d       |j1                  d| j                   d       |j1                  d| j                   d       |j1                  dd d       |j3                          t5        j6                  |t4        j8                  |||t:        d      }	 |j=                  | j                          |j>                  }		 ddd       	d&k(  r;d'| _        t        d| j                  dd(| j                   d)| j                          n1d*| _        t        d| j                  dd+| j                   d,|	 d-       t        j                         j                         | _        | j                  | j                  d.|	 | j                  /      |r6t*        jF                  jI                  |      rt+        jJ                  |       S S S # 1 sw Y   \xY w# t4        j@                  $ r |jC                          |jE                          d!| _        t        j                         j                         | _        t        d| j                  dd"| j                   d#| j                   d       | j                  d!d$| j                   d%      cY cddd       |r6t*        jF                  jI                  |      rt+        jJ                  |       S S S w xY w# 1 sw Y   xY w# tL        $ r d0| _        t        j                         j                         | _        d1}
t        d| j                  dd2|
        | j                  d0|
      cY |r6t*        jF                  jI                  |      rt+        jJ                  |       S S S tN        $ r}d0| _        t        j                         j                         | _        t        d| j                  dd2| j                   d3|        | j                  d0tQ        |            cY d}~|r6t*        jF                  jI                  |      rt+        jJ                  |       S S S d}~ww xY w# |r6t*        jF                  jI                  |      rt+        jJ                  |       w w w xY w)4zAExecute the task as a Gemini CLI subprocess. Returns result dict.running%Y%m%d_%H%M%S/r8   r6     [W02dz] Starting z	 (model: z, timeout: zs)u   ] DRY RUN — would execute: r   u   Dry run — no executionNgeminiz--yolorGEMINI_MODELr5   z# Gemini Task Output
z# Task ID: 
z	# Model: z# Started: z
# Worker: z# z<============================================================

T)stdinstdoutstderrenvcwdtext)inputr$   r$   z] TIMEOUT: z (exceeded zTimed out after sr   successz] DONE: z -> failedz
] FAILED: z (exit code: )zExit code: )r'   errorzCgemini binary not found. Install: npm install -g @google/gemini-cliz	] ERROR: : ))r   r>   r?   r(   r&   strftimer   r!   r'   printr   r   r$   r   r)   _resultrI   r   appendopenreadosenvironcopyrB   rC   
subprocessPopenPIPEGENESIS_ROOTcommunicate
returncodeTimeoutExpiredkillwaitpathexistsunlinkFileNotFoundError	Exceptionstr)r*   tsprompt_filecmdpfprompt_contentrX   outfproc	exit_codemsgexcs               r+   runzGeminiWorker.run   s   "//+557__''8"oo.a~Qrd$GT^^C(DLL>4::, W,,r+ 	, <<D,,I$,,XY#DK'0::<D<<	+EFFO	'113K
 *Cyy

8$ k3' +2!#+ **//#C"&**C d&&, W

35

[b9:

Ytzzl"56

[(9<=

Z'7r:;

Rxt,-

!''$//$W$$>4<<$P $I-W@ A~'T^^C0 G ,,-/ 0 'T^^C0
4<<. I%%.Kq2 3  (0::<D<<{9+-F,0,<,<   >" rww~~k:		+&  ;{G+ +> "00 WIIKIIK"+DK'/'8'B'B'DD$D 4K~ N''+||nB8 9<<	5Edll^ST3UVV=W Wv rww~~k:		+&  ;{IW/W WZ ! 	.!DK'0::<DWCD,IcU;<<<-- rww~~k:		+&  ;{  	3!DK'0::<DD,Idll^2cUKL<<S22 rww~~k:		+&  ;{	3 rww~~k:		+&  ;{s   ,<S) (O9AS) C!S&)O C
S) OS)  B5SS	S) SSS&!S) )A'YY	 
YA1YYY	 YY	 	:ZNr&   messager'   c           	          | j                   | j                  | j                  |||xs | j                  | j                  | j
                  dS )N)r!   r   r   r&   r   r'   r(   r)   )r!   r   r   r'   r(   r)   )r*   r&   r   r'   s       r+   rd   zGeminiWorker._result   sE    ||ZZ&:$*:*://++	
 		
r-   )TF)N)__name__
__module____qualname____doc__dictry   intboolr,   rI   r   rd    r-   r+   r   r   K   sq    B 5: T  s  s   -1 $ C  Da'T a'F

c 

C 

c 

T 

r-   r   c                   T    e Zd ZdZdeddfdedededed	ef
d
Z	de
fdZdefdZd Zy)GeminiSwarmu   
    Manages a pool of parallel Gemini CLI workers.
    Each worker is an independent subprocess — crashes are isolated.
       TFtasksmax_workersr   r   r   c                 ^   t        |d       | _        || _        || _        || _        || _        t        j                         | _        g | _	        t        j                         | _        i | _        t        j                         | _        t        j                         | _        d| _        | j                  D ]  }| j                  j%                  |        t'        |      j)                  dd       t+        j,                         j/                  d      }| d| d| _        | d	| d
| _        y )Nc                 &    | j                  dd      S )Nr3   r4   )r    )ts    r+   <lambda>z&GeminiSwarm.__init__.<locals>.<lambda>   s    z21F r-   )keyr   T)parentsexist_okrL   z/swarm_results_z.jsonlz/swarm_manifest_z.json)sortedr   r   r   r   r   queueQueue
task_queueresults	threadingLockresults_lockactive_workersworkers_lockEvent	_shutdown_worker_counterputr   mkdirr   r>   rb   results_filemanifest_file)r*   r   r   r   r   r   r   rz   s           r+   r,   zGeminiSwarm.__init__   s    E'FG
&$	++-%NN, %NN,"*  JJ 	&DOO%	& 	Ztd; __''8)l/"VD *|+;B4uEr-   r   c                    | j                   5  | xj                  dz  c_        | j                  }ddd       |j                  d      xs- t        j                  |j                  dd      t        d         }t        j                  |t        d         }t        j                  |       t        || j                  | j                  | j                        }|j                         }|d   dv r|j                  t        k  rq|xj                  dz  c_        t        d	|d
d|d    d|j                   dt         d	       t        j                  d|j                  z         |j                         }| j                  5  | j                   j#                  |       t%        | j&                  d      5 }|j)                  t+        j,                  |      dz          ddd       ddd       | j                   5  | j.                  j1                  |d       ddd       y# 1 sw Y   xY w# 1 sw Y   PxY w# 1 sw Y   TxY w# 1 sw Y   yxY w)z4Thread function: runs one GeminiWorker for one task.   Nr   r   r   )r   r   r&   )r^   r`   rN   rO   z] Retrying r   z
 (attempt rM   z)...r   arS   )r   r   r    r"   RATE_LIMIT_WINDOWStimesleepr   r   r   r   r   r%   MAX_RETRIESrc   r   r   re   rf   r   rB   jsondumpsr   pop)r*   r   wid
task_modelgapworkerresultfs           r+   _worker_threadzGeminiSwarm._worker_thread  s    	'  A% &&C	'
 hhw' L(,,TXXfi-H-?	-JL 	 !$$Z%7	%BD

3dDOOS#'99dllD (22v~~7SNNaNDS	T$ZL 9$nn-Q{m4A BJJq6>>)*ZZ\F  	3LL'd''- 3

6*T123	3
  	/##C.	/ 	/=	' 	'63 3	3 	3
	/ 	/s;   "H>2H30(H'H34H?H$'H0	,H33H<?Ir.   c                     t         j                        }t        dd        t        d       t        d        t        d|        t        d j                   d       t        d j                          t        d j
                          t        d	 j                          t        d
 j                          t        d d       |dk(  rt        d       g S t        j                         j                         | j                   j                  D cg c]5  }|j                  d      |j                  d      |j                  d      d7 c}d}t         j                  d      5 }t        j                  ||d       ddd        fd}t!        j                   t         j"                  |       g }t%         j                        }|s|rB j&                  j)                         s'|rt        |       j                  k  r|j+                  d      }t-        j.                   j0                  |fd      }|j3                          |j5                  |       t        |      }	t        |      }
||	z
  |
z
  }t        d|j                  d       d|
 d| d|        |rt        |       j                  k  r|D cg c]  }|j7                         s| }}|s|rt9        j:                  d       |s|r j&                  j)                         s'|D ]  }|j=                  d         j?                           j@                  S c c}w # 1 sw Y   xY wc c}w ) z;Run all tasks using a thread pool. Returns list of results.rS   F======================================================================z  GENESIS GEMINI SWARM LAUNCHERz	  Tasks: z  Workers: z	 parallelz
  Output: z  YOLO: z  Dry run: z  Results: r   z  No tasks to process.r   r   r3   )r   r   r3   )r(   total_tasksr   r   r5   r   )indentNc                 P    t        d       j                  j                          y )NzB

  Swarm shutdown requested (Ctrl+C). Finishing active workers...)rc   r   set)sigframer*   s     r+   _sigint_handlerz(GeminiSwarm.run.<locals>._sigint_handlerV  s    XYNN r-   T)targetargsdaemonz  [swarm] Dispatched z | Active: z	 | Done: rM   r   r   )r$   )!lenr   rc   r   r   r   r   r   r   r>   r?   r    rf   r   r   dumpsignalSIGINTlistr   is_setr   r   Threadr   startre   is_aliver   r   join_print_reportr   )r*   totalr   manifestr   r   active_threadsr   r   	remainingactivedones   `           r+   r   zGeminiSwarm.run8  s   DJJ6(m/1	%!"D,,-Y78
4??+,-$%DLL>*+D--./0mA:*+I #//+557 ++@D

L;< UU4[!%%-$%EE*$57 L	
 $$$c* 	-aIIh!,	-	! 	fmm_5tzz".$..2G2G2Ic.1D4D4DD{{1~$$..
 	%%a(L	^,y(61-dhhtn-= >!!'	$qA B c.1D4D4DD  *8HA1::<aHNH.

3) .$..2G2G2I.   	AFF1F	 	||WL	- 	-< Is   :M
3MM"M"Mc           
      f   t        | j                        }t        d | j                  D              }t        d | j                  D              }t        d | j                  D              }t        d | j                  D              }t        d | j                  D              }t        dd        t        d       t        d        t        d	|        t        d
|        t        d|        t        d|        t        d|        |rt        d|        t                t        d| j                          t        d| j
                          ||z   |z   dkD  rAt        d       | j                  D ]'  }|d   dvst        d|d    d|d    d|d           ) t        d d       y)zPrint execution summary.c              3   2   K   | ]  }|d    dk(  sd  ywr&   r]   r   Nr   .0rQ   s     r+   	<genexpr>z,GeminiSwarm._print_report.<locals>.<genexpr>  s     JA8	1IaJ   c              3   2   K   | ]  }|d    dk(  sd  yw)r&   r^   r   Nr   r   s     r+   r   z,GeminiSwarm._print_report.<locals>.<genexpr>  s     H1(x0GQHr   c              3   2   K   | ]  }|d    dk(  sd  yw)r&   r`   r   Nr   r   s     r+   r   z,GeminiSwarm._print_report.<locals>.<genexpr>  s     G1(w0FQGr   c              3   2   K   | ]  }|d    dk(  sd  yw)r&   r$   r   Nr   r   s     r+   r   z,GeminiSwarm._print_report.<locals>.<genexpr>       KQ!H+2JqKr   c              3   2   K   | ]  }|d    dk(  sd  yw)r&   r   r   Nr   r   s     r+   r   z,GeminiSwarm._print_report.<locals>.<genexpr>  r   r   rS   r   z  SWARM COMPLETEz  Total tasks:  z  Success:      z  Failed:       z  Errors:       z  Timeouts:     z  Dry runs:     z  Results log:  z  Output dir:   r   z
  FAILED TASKS:r&   )r]   r   z    - r!   ra   u    — r   N)r   r   sumrc   r   r   )r*   r   r]   r^   errorstimeoutsdry_runsrQ   s           r+   r   zGeminiSwarm._print_report|  s   DLL!JJJHHHGGGK$,,KKK$,,KK6(m " () 	*+ )* )* 
+,$XJ/0c
 !2!2 345  123F?X%)%'\\ UX;&<<F1Y<.1X;-uQy\NSTU 	mr-   N)r   r   r   r   DEFAULT_OUTPUT_DIRr   r   ry   r   r,   r   r   r   r   r   r-   r+   r   r      sf    
 89#5"EFd F F FF-1F8!/4 !/FBT BHr-   r   filepathr.   c                     t        | d      5 }t        j                  |      }ddd       t        t              r|S t        |t
              r	d|v r|d   S t        d|        # 1 sw Y   BxY w)z!Load tasks from a JSON task file.rQ   Nr   z2Expected JSON array or object with 'tasks' key in )rf   r   load
isinstancer   r   
ValueError)r   r   datas      r+   load_tasks_from_jsonr     sl    	h	 yy|$$'T/G}
I(T
UU s   A$$A-c                    g }t        | d      5 }|j                         }ddd       j                  d      }d}d}|D ]  }|j                  d      rd|v r|r|j	                  |       |j                  dd      }|d   j                         j                  dd      }	t        |      dkD  r|d   j                         nd	| }
	 t        |	      }|dz  }d
| d|
j                         j                  dd      dd  |dd|
 ddd}||dxx   |dz   z  cc<    |r|j	                  |       |S # 1 sw Y   xY w# t        $ r |}Y }w xY w)zj
    Convert a WORK_QUEUE_TODAY.md file into a task list.
    Parses P0, P1, P2... sections as tasks.
    rQ   NrS   r   z## Pu   —r   r1   zTask pr8       r	   z# Task: rT   iX  )r   r3   r   r0   r   r0   )rf   rg   split
startswithre   stripreplacer   r   r   lower)r   r   r   r   linescurrent_taskpriority_counterlinepartspriority_strtitler3   s               r+   load_tasks_from_work_queuer    s}   
 E	h	 &&( MM$EL 2??6"u}\*JJua(E 8>>+33FB?L(+E
QE!HNN$eDTCU<VE,|, !(1U[[]%:%:3%DSb%I$JK$!$UG40#&L %"dTk1"+2. \"LC "  ,+,s   D4E4D>EEc                     t        j                  d      } | j                  dd d       | j                  dt        dd	       | j                  d
t        dt         d       | j                  ddd       | j                  ddd       | j                  ddd       | j                  dd d       | j                  ddd       | j                         }|j                  dkD  r t        d|j                   d       d|_        t        j                  j                  d      st        j                  j                  t              r\t        t              5 }|j                         j!                         }d d d        t        j                  d<   t        dt                nt        dt                |j"                  rd d!d"|j"                  |j$                  d#g}n|j&                  rQ|j&                  }|j)                  d$      rt        d%|        t+        |      }nt        d&|        t-        |      }nmt.        }t        j                  j                  |      rt        d'|        t+        |      }n.t        d(|        t        d)       t1        j2                  d*       |j4                  rt        d+t7               d,       |D ]p  }t        d-|j                  d.d/       d0|d1    d2|j                  d3d"       d4|j                  d5t8        j                  |j                  d3d"      d"                    r y t;        |j                  |j<                  |j>                   |j@                  6      }|jC                         }	tE        d7 |	D              }
t1        j2                  |
t7        |	      k(  rd!       y d*       y # 1 sw Y   VxY w)8Nu=   Genesis Gemini Swarm Launcher — parallel Gemini CLI workers)descriptionz--tasksz-Path to JSON task file or WORK_QUEUE_TODAY.md)r   helpz	--workersr   z6Max parallel workers (default: 5, max recommended: 20))r   r   r  z--output-dirzOutput directory (default: r_   z	--no-yolo
store_truez5Disable YOLO mode (interactive confirmation required))actionr  z	--dry-runzPrint tasks but do not executez--list-taskszList tasks from file and exitz--promptz)Single prompt to run (bypasses task file)z--modelr   zModel to use for --prompt mode   z	Warning: z7 workers requested. Capping at 20 to avoid rate limits.GOOGLE_API_KEYzLoaded GOOGLE_API_KEY from z4Warning: No GOOGLE_API_KEY set and no creds file at single_promptr   r   )r   r3   r   r0   r   z.mdzParsing work queue: zLoading task file: zLoading default work queue: z.No task file specified and default not found: z:Usage: python gemini_swarm_launcher.py --tasks <file.json>r   z
Tasks in queue (z total):z  Pr3   ?z | r   z | type=r   z	 | model=r   )r   r   r   r   r   c              3   2   K   | ]  }|d    dk(  sd  ywr   r   r   s     r+   r   zmain.<locals>.<genexpr>4  s     GaakY.FGr   )#argparseArgumentParseradd_argumentr   r   
parse_argsworkersrc   rh   ri   r    rt   ru   
CREDS_FILErf   rg   r   r0   r   r   endswithr  r   DEFAULT_TASK_FILEsysexit
list_tasksr   r"   r   r   no_yolor   r   r   )parserr   r   r   r   	task_pathwqr   swarmr   success_counts              r+   mainr    s   $$SF 4<   #qE    2*+=*>a@   LD   L-   |,   D8   --   D ||b	$,, (4 5 	6 ::>>*+77>>*%j! 'Qffhnn&'+.BJJ'(/
|<=HUV {{!kkZZ
  
JJ	e$(45.y9E'	{34(3E 77>>"056.r2EB2$GHNOHHQK"3u:,h78 	iACj#./s1T7) <%%	23 455*<*@*@viAXZc*defh i	i 	LL??E iikGG7GGMHH-3w</Q7Q7i' 's   OO__main__)r   r  r   rh   rk   r  r   r   r   r   r@   r   pathlibr   rn   r   r  r  r   r"   r   r#   r   r   ry   r   r   r  r  r   r   r-   r+   <module>r!     s   <   	  
        '$~%9: ~<=
#n$JK   	  #"$$$$$  d
 d
Pe eRV3 V4 V' ' 'Vc8L zF r-   