+
    ӃiY                     L  a  R t!0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIHt ^ RIHt ^ RIHt ]P$                  ! ]4      t. ROtRs] ^ k ]P.                  ! R4      tR R ltR R	 ltR
 R ltR R lt. ROtRs] ^k R R lt ! R R]4      t R# )zDocker execution environment for sandboxed command execution.

Security hardened (cap-drop ALL, no-new-privileges, PID limits),
configurable resource limits (CPU, memory, disk), and optional filesystem
persistence via bind mounts.
N)Optional)BaseEnvironment)is_interruptedz^[A-Za-z_][A-Za-z0-9_]*$c                j    V ^8  d   QhR\         \        ,          R,          R\         \        ,          /# )   forward_envNreturn)liststr)formats   "6/home/ubuntu/hermes-agent/tools/environments/docker.py__annotate__r   '   s'      d3i$.> 49     c                   . p\        4       pT ;'       g    .  F  p\        V\        4      '       g   \        P	                  RV4       K1  VP                  4       pV'       g   KK  \        P                  V4      '       g   \        P	                  RV4       K~  WB9   d   K  VP                  V4       VP                  V4       K  	  V# )z?Return a deduplicated list of valid environment variable names.z0Ignoring non-string docker_forward_env entry: %rz-Ignoring invalid docker_forward_env entry: %r)
set
isinstancer
   loggerwarningstrip_ENV_VAR_NAME_REmatchaddappend)r   
normalizedseenitemkeys   &    r   _normalize_forward_env_namesr   '   s    JUD!!r!$$$NNMtTjjl%%c**NNJDQ;# "" r   c                `    V ^8  d   QhR\         R,          R\         \        \        3,          /# )r   envNr   dictr
   )r   s   "r   r   r   @   s&      TD[ T#s(^ r   c                8   V '       g   / # \        V \        4      '       g   \        P                  RV 4       / # / pV P	                  4        F  w  r#\        V\
        4      '       d*   \        P                  VP                  4       4      '       g   \        P                  RV4       K\  VP                  4       p\        V\
        4      '       gF   \        V\        \        \        34      '       d   \        V4      pM\        P                  RW#4       K  W1V&   K  	  V# )zValidate and normalize a docker_env dict to {str: str}.

Filters out entries with invalid variable names or non-string values.
zdocker_env is not a dict: %rz#Ignoring invalid docker_env key: %rz/Ignoring non-string docker_env value for %r: %r)r   r!   r   r   itemsr
   r   r   r   intfloatbool)r   r   r   values   &   r   _normalize_env_dictr(   @   s    
 	c4  5s;	!#Jiik
#s##+;+A+A#))++N+NNN@#Fiik%%% %#ud!344E
PRU]3 " r   c                F    V ^8  d   QhR\         \        \        3,          /# r   r   r    )r   s   "r   r   r   ^   s      tCH~ r   c                 X     ^ RI Hp  V ! 4       ;'       g    / #   \         d    / u # i ; i)zDLoad ~/.hermes/.env values without failing Docker command execution.load_env)hermes_cli.configr-   	Exceptionr,   s    r   _load_hermes_env_varsr0   ^   s.    .zR 	s     ))c                :    V ^8  d   QhR\         \        ,          /# r*   )r   r
   )r   s   "r   r   r   h   s      Xc] r   c                 \   \         e   \         # \        P                  ! R4      p V '       d   V s V # \         Fq  p\        P
                  P                  V4      '       g   K*  \        P                  ! V\        P                  4      '       g   KW  Vs \        P                  RV4       Vu # 	  R# )a!  Locate the docker CLI binary.

Checks ``shutil.which`` first (respects PATH), then probes well-known
install locations on macOS where Docker Desktop may not be in PATH
(e.g. when running as a gateway service via launchd).

Returns the absolute path, or ``None`` if docker cannot be found.
Ndockerz%Found docker at non-PATH location: %s)_docker_executableshutilwhich_DOCKER_SEARCH_PATHSospathisfileaccessX_OKr   info)foundr9   s     r   find_dockerr?   h   s|     %!!LL"E"$77>>$BIIdBGG$<$<!%KK?FK	 % r   c                    V ^8  d   QhRR/# )r   r   N )r   s   "r   r   r      s     ? ?$ ?r   c                 f   \        4       p V '       g!   \        P                  R4       \        R4      h \        P
                  ! V R.RR^R7      pVP                  ^ 8w  dF   \        P                  RV VP                  VP                  P                  4       4       \        R4      hR#   \         d%    \        P                  RT RR	7       \        R
4      h\        P                   d%    \        P                  RT RR	7       \        R4      h\         d    \        P                  RRR	7       h i ; i)zBest-effort check that the docker CLI is available before use.

Reuses ``find_docker()`` so this preflight stays consistent with the rest of
the Docker backend, including known non-PATH Docker Desktop locations.
zDocker backend selected but no docker executable was found in PATH or known install locations. Install Docker Desktop and ensure the CLI is available.z|Docker executable not found in PATH or known install locations. Install Docker and ensure the 'docker' command is available.versionTcapture_outputtexttimeoutzIDocker backend selected but '%s version' failed (exit code %d, stderr=%s)zXDocker command is available but 'docker version' failed. Check your Docker installation.zVDocker backend selected but the resolved docker executable '%s' could not be executed.)exc_infozHDocker executable could not be executed. Check your Docker installation.zYDocker backend selected but '%s version' timed out. The Docker daemon may not be running.zHDocker daemon is not responding. Ensure Docker is running and try again.z4Unexpected error while checking Docker availability.N)r?   r   errorRuntimeError
subprocessrun
returncodestderrr   FileNotFoundErrorTimeoutExpiredr/   )
docker_exeresults     r   _ensure_docker_availablerS      sR    J 	

 K
 	

-#	
B !LL,!!##% 2  "7  	
	 	 	
 V
 	
 $$ 	
4	 	 	
 V
 	
  B 	 	
 	s   B( (A D0),D0D0c                      a a ] tR t^t oRtRV3R lV 3R lllt]V3R lR l4       tRRRRR/V3R	 lR
 llltR t	Rt
VtV ;t# )DockerEnvironmentu  Hardened Docker container execution with resource limits and persistence.

Security: all capabilities dropped, no privilege escalation, PID limits,
size-limited tmpfs for scratch dirs. The container itself is the security
boundary — the filesystem inside is writable so agents can install packages
(pip, npm, apt) as needed. Writable workspace via tmpfs or bind mounts.

Persistence: when enabled, bind mounts preserve /workspace and /root
across container restarts.
Nc                   < V ^8  d   QhRS[ RS[ RS[RS[RS[RS[RS[RS[ R	S[R
S[S[ ,          R,          RS[R,          RS[RS[ RS[/# )r   imagecwdrG   cpumemorydiskpersistent_filesystemtask_idvolumesr   Nr   networkhost_cwdauto_mount_cwd)r
   r$   r%   r&   r	   r!   )r   __classdict__s   "r   r   DockerEnvironment.__annotate__   s     GW GWGW GW 	GW
 GW GW GW  $GW GW GW #Y%GW D[GW GW GW GWr   c                r  < VR 8X  d   Rp\         S%V `  W#R7       Wn        Wpn        Wn        \        V
4      V n        \        V4      V n        RV n	        \        P                  RV	 24       V	e2   \        V	\        4      '       g   \        P                  RV	: 24       . p	\        4        . pV^ 8  d   VP!                  R\#        V4      .4       V^ 8  d   VP!                  RV R2.4       V^ 8  dY   \$        P&                  R	8w  dD   V P)                  4       '       d   VP!                  R
RV R2.4       M\        P                  R4       V'       g   VP+                  R4       ^ RIHp . pRpT	;'       g    .  F  p\        V\"        4      '       g   \        P                  RV: 24       K4  VP1                  4       pV'       g   KN  RV9   d!   VP!                  RV.4       RV9   d   RpKs  Ku  \        P                  RV R24       K  	  V'       d=   \2        P4                  P7                  \2        P4                  P9                  V4      4      MRpT;'       dB    \;        V4      ;'       d/    \2        P4                  P=                  V4      ;'       d    V'       * pV'       dF   V'       d>   \2        P4                  P=                  V4      '       g   \        P?                  RV 24       RV n         RV n!        . pV P                  '       d   V! 4       R,          V,          p\#        VR,          4      V n!        \2        PD                  ! V PB                  RR7       VP!                  RV PB                   R2.4       V'       gb   V'       gZ   \#        VR,          4      V n         \2        PD                  ! V P@                  RR7       VP!                  RV P@                   R2.4       M6V'       g   V'       g   VP!                  RR.4       VP!                  . R=O4       V'       d#   \        P                  R V 24       RV R2.VOpMV'       d   \        P?                  R!4        ^ R"I#H$pH%pH&p V! 4        FO  pVP!                  RVR#,           RVR$,           R%2.4       \        P                  R&VR#,          VR$,          4       KQ  	  V! 4        FO  pVP!                  RVR#,           RVR$,           R%2.4       \        P                  R'VR#,          VR$,          4       KQ  	  V! 4        FO  pVP!                  RVR#,           RVR$,           R%2.4       \        P                  R(VR#,          VR$,          4       KQ  	  . p\Q        V P                  4       F,  p VP!                  R*V  R+V P                  V ,           2.4       K.  	  \        P                  R,V 24       \        \R        4      V,           V,           V,           V,           p!\        P                  R-V! 24       \U        4       ;'       g    RV n+        R.\X        PZ                  ! 4       P\                  R/,           2p"V PV                  R0R1R2V"R3V.V!OVNR4NR5Np#\        P?                  R6R7P_                  V#4       24       \`        Pb                  ! V#RR^xRR87      p$V$Pd                  P1                  4       V n	        \        P                  R9V" R:V P                  R;,           R<24       R#   \N         d"   p\        P?                  R)T4        Rp?ELRp?ii ; i)>~/root)rX   rG   NzDockerEnvironment volumes: z%docker_volumes config is not a list: z--cpusz--memorymdarwin--storage-optzsize=zDocker storage driver does not support per-container disk limits (requires overlay2 on XFS with pquota). Container will run without disk quota.z--network=none)get_sandbox_dirFz%Docker volume entry is not a string: :z-vz:/workspaceTzDocker volume 'z' missing colon, skipping z>Skipping docker cwd mount: host_cwd is not a valid directory: r3   home)exist_okz:/root	workspace--tmpfsz/workspace:rw,exec,size=10gz,Mounting configured host cwd to /workspace: zDSkipping docker cwd mount: /workspace already mounted by user config)get_credential_file_mountsget_skills_directory_mountget_cache_directory_mounts	host_pathcontainer_pathz:roz$Docker: mounting credential %s -> %sz$Docker: mounting skills dir %s -> %sz#Docker: mounting cache dir %s -> %sz1Docker: could not load credential file mounts: %s-e=zDocker volume_args: zDocker run_args: zhermes-:N   NrL   z-dz--name-wsleep2hzStarting container:  )rE   rF   rG   checkzStarted container z (:N   N))rp   z/home:rw,exec,size=1grp   z/root:rw,exec,size=1g)3super__init___base_image_persistent_task_idr   _forward_envr(   _env_container_idr   r=   r   r	   r   rS   extendr
   sysplatform_storage_opt_supportedr   tools.environments.baserj   r   r8   r9   abspath
expanduserr&   isdirdebug_workspace_dir	_home_dirmakedirstools.credential_filesrq   rr   rs   r/   sorted_SECURITY_ARGSr?   _docker_exeuuiduuid4hexjoinrK   rL   stdout)&selfrW   rX   rG   rY   rZ   r[   r\   r]   r^   r   r   r_   r`   ra   resource_argsrj   volume_argsworkspace_explicitly_mountedvolhost_cwd_absbind_host_cwdwritable_argssandboxrq   rr   rs   mount_entryskills_mountcache_mounteenv_argsr   all_run_argscontainer_namerun_cmdrR   	__class__s&   &&&&&&&&&&&&&&&                      r   r   DockerEnvironment.__init__   s   " #:CS2 08E',	,01';<z'4'@'@NNB7+NOG 	!" 7  (CH!56A:  *l!;<!80**,,$$otfA%GHe   !12
 	< ',$MMrMCc3''!FsgNO))+Ccz""D#;/ C'370 ( 5NOP " IQrwwrww'9'9('CDVX 1 1\"1 1l+1 1 10	 	 hrww}}\/J/JLLYZbYcde-1(,%'(2W<G 6!12DNKK6  (/"  !)E&)'K*?&@#D//$?$$T001=&  !)E$$<&     " 
 KKF|nUVL>!=LLK)LL_`.	Q   :;""";/0+>N2O1PPST$  :, 01  < !; <""#K01<@P3Q2RRUV$  : - !12 !=  :;""";/0+>N2O1PPST$  9, 01  < $))$COOTcU!DIIcN+;#<=> % 	*;-89N+m;mKkY\dd'~67 '=44H #4::<#3#3B#7"89eTn#
 	

 
 
 
 	+CHHW,=+>?@
 $]]002((84;M;Mc;R:SSTUVI  	QLLLaPP	Qs   #D\
 
\6\11\6c                    < V ^8  d   QhRS[ /# r*   )r&   )r   rb   s   "r   r   rc     s     % %D %r   c                 8   \         e   \         #  \        4       ;'       g    Rp \        P                  ! V RRR.RR^
R7      pVP                  P                  4       P                  4       pVR8w  d   Rs R# \        P                  ! V R	R
RR.RR^R7      pVP                  ^ 8X  dB   VP                  P                  4       pV'       d   \        P                  ! V RV.R^R7       Rs MRs  \        P                  R\         4       \         #   \         d    Rs  L/i ; i)zCheck if Docker's storage driver supports --storage-opt size=.

Only overlay2 on XFS with pquota supports per-container disk quotas.
Ubuntu (and most distros) default to ext4, where this flag errors out.
r3   r=   z--formatz{{.Driver}}TrD   overlay2Fcreateri   zsize=1mzhello-worldrm)rE   rG   z Docker --storage-opt support: %s)_storage_opt_okr?   rK   rL   r   r   lowerrM   r/   r   r   )r3   rR   driverprobecontainer_ids        r   r   (DockerEnvironment._storage_opt_supported  s    &""	$ ]..hF^^];#$F ]]((*002F#"' NN?I}M#$E 1$$||113NNFD,#?26C"&"' 	7I  	$#O	$s*   D	 AD	 5AD	 D	 &D	 	DDrG   
stdin_datac          
      T   < V ^8  d   QhRS[ RS[ RS[R,          RS[ R,          RS[/# )r   commandrX   rG   Nr   r   )r
   r$   r!   )r   rb   s   "r   r   rc     sI     cO cOs cO cOtcO$JcO26cOr   c                 aa V P                  V4      w  rVT;'       g    V P                  pT;'       g    V P                  pVe   Ve
   Wd,           p	M	Ve   Tp	MTp	VR8X  d	   RV 2pRpM<VP                  R4      '       d&   R\        P
                  ! VR,          4       RV 2pRpV P                  '       g   Q R4       hV P                  R	.p
V	e   V
P                  R
4       T
P                  RV.4       \        V P                  4      p\        V P                  4      p ^ RIHp W! 4       ,          pV'       d   \#        4       M/ p\%        V4       F8  p\&        P(                  ! V4      pVf   VP+                  V4      pVf   K4  VW&   K:  	  \%        V4       F!  pV
P                  RV RW,           2.4       K#  	  V
P                  V P                  RRV.4        . o\,        P.                  ! T
\,        P0                  \,        P2                  V	'       d   \,        P0                  M\,        P4                  RR7      oV	'       d7    SP6                  P9                  V	4       SP6                  P;                  4        VV3R lp\<        P>                  ! VRR7      pVPA                  4        \B        PD                  ! 4       V,           pSPG                  4       f   \I        4       '       dR   SPK                  4         SPM                  ^R7       VPS                  ^R7       RRPS                  S4      R,           R^/# \B        PD                  ! 4       V8  d4   SPQ                  4        VPS                  ^R7       V PU                  V4      # \B        PV                  ! R4       K  VPS                  ^R7       RRPS                  S4      RSPX                  /#   \          d     ELi ; i  \          d     ELti ; i  \,        PN                   d    SPQ                  4         ELi ; i  \          d   pRRT 2R^/u R p?# R p?ii ; i)Nre   zcd ~ && /z~/zcd ~/:r   NNz && zContainer not startedexecz-iry   )get_all_passthroughrv   rw   bashz-lcT)r   rN   stdinrF   c                  v   <  SP                    F  p SP                  V 4       K  	  R #   \         d     R # i ; i)N)r   r   r/   )line_output_chunksprocs    r   _drain)DockerEnvironment.execute.<locals>._drain  s6     $&--d3 !,  s   $) 88)targetdaemon)rG   outputrl   z
[Command interrupted]rM   g?zDocker execution error: )-_prepare_commandrX   rG   
startswithshlexquoter   r   r   r   r!   r   r   r   tools.env_passthroughr   r/   r0   r   r8   getenvgetrK   PopenPIPESTDOUTDEVNULLr   writeclose	threadingThreadstarttime	monotonicpollr   	terminatewaitrP   killr   _timeout_resultrz   rM   )r   r   rX   rG   r   exec_command
sudo_stdinwork_direffective_timeouteffective_stdincmdexec_envforward_keysr   
hermes_envr   r'   r   readerdeadliner   r   r   s   &&&$$                @@r   executeDockerEnvironment.execute  s    $(#8#8#A ??$((#33t|| !j&<(5O#(O(O s?%l^4LH  &&"5;;x|#<"=T,PLH!!!:#::!(&JJt

D(#$ $(		?4,,-	A/11L 1=*,"
,'CIIcNE}"s+  % ( (#CJJQx}o678 $

D&&|DE/	ON##!z/@/@)8jooj>P>P	D JJ$$_5JJ$$& %%VDAFLLN~~'*;;H))+%!##NN$$		!	, KKK* "''."9<U"U$c  >>#h.IIKKKK*//0ABB

3KKK"bggn5|T__UUw  		4 ! & &44 $		$  	O 8<lANN	Os   !O 8P  -P  5O" <A=P  :O4 -P  :AP  AP  OO"O1-P  0O11P  4%PP  PP   P>+P93P>9P>c           	        V P                   '       d    RV P                   RV P                    RV P                   RV P                    R2	p\        P                  ! VRR7       V P                  '       g5    \        P                  ! R
V P                   RV P                    R2RR7       R	V n         V P                  '       gD   V P                  V P                  3 F%  pV'       g   K  \        P                  ! VRR7       K'  	  R	# R	#   \         d,   p\
        P                  RT P                   T4        R	p?LR	p?ii ; i  \         d     Li ; i)zJStop and remove the container. Bind-mount dirs persist if persistent=True.z(timeout 60 z stop z || z rm -f z) >/dev/null 2>&1 &T)shellzFailed to stop container %s: %sNzsleep 3 && z >/dev/null 2>&1 &)ignore_errors)r   r   rK   r   r/   r   r   r   r   r   r5   rmtree)r   stop_cmdr   ds   &   r   cleanupDockerEnvironment.cleanup>  s:   Y #4#3#3"4F4;M;M:Nd''(0B0B/CCVX    6 ###$$%d&6&6%7wt?Q?Q>RRde" "&D))4>>:1MM!48 ;    Y@$BTBTVWXXY ! s*   AD 63E  D=!D88D= EE)	r   r   r   r   r   r   r   r   r   )rf   <       r   r   FdefaultNNNTNF)rl   )__name__
__module____qualname____firstlineno____doc__r   staticmethodr   r   r   __static_attributes____classdictcell____classcell__)r   rb   s   @@r   rU   rU      s[     	GW GWR % %NcO&*cO)-cO cOJ9 9r   rU   c                    V ^8  d   Qh/ ^ \         9   d   \        \        ,          ;R&   ^\         9   d   \        \        ,          ;R&   # )r   r4   r   )__conditional_annotations__r   r
   r&   )r   s   "r   r   r      s<      D ) (HSM (El ' &$ &mr   )z/usr/local/bin/dockerz/opt/homebrew/bin/dockerz6/Applications/Docker.app/Contents/Resources/bin/docker)z
--cap-dropALL	--cap-addDAC_OVERRIDEr  CHOWNr  FOWNERz--security-optzno-new-privilegesz--pids-limit256rp   z/tmp:rw,nosuid,size=512mrp   z#/var/tmp:rw,noexec,nosuid,size=256mrp   z/run:rw,noexec,nosuid,size=64m)"r  r   loggingr8   rer   r5   rK   r   r   r   r   typingr   r   r   tools.interruptr   	getLoggerr   r   r7   r4   compiler   r   r(   r0   r?   r   r   rS   rU   r   )r  s   @r   <module>r     s     	 	    
     3 *			8	$  %)  (::9: 2<D
 #' &?D}9 }9r   