
    *"hj                        d Z ddlmZ ddlZddlZddlZddlmZmZ ddlm	Z	m
Z
 ddlmZ ddlmZmZ  ej                   e      Zdd	Z G d
 d      Zy)a  
Shared storage helpers for distributed client-side validation.

The validation flow uses the same object store boundary as the rest of
SkillClaw. Jobs are produced by the evolve server, validated by opted-in
clients, and later finalized by the evolve server.
    )annotationsN)datetimetimezone)AnyOptional)build_skill_md   )build_object_storeis_not_found_errorc                 d    t        j                  t        j                        j	                         S )N)r   nowr   utc	isoformat     5/root/.hermes/SkillClaw/skillclaw/validation_store.py_utc_now_isor      s    <<%//11r   c                      e Zd ZdZddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZedd       ZddZddZdd	Z	dd
Z
ddZddZddZddZd dZd!dZd"dZd#dZd$dZddZddd%dZy)&ValidationStorez<Persist validation jobs/results/decisions in shared storage. default)regionsession_token
local_rootgroup_idc       	   
     B    t        ||||||||      | _        |	| _        y )N)backendendpointbucketaccess_key_idsecret_access_keyr   r   r   )r
   _bucket	_group_id)
selfr   r   r   r    r!   r   r   r   r   s
             r   __init__zValidationStore.__init__   s1     *'/'!	
 "r   c                    ddl m} |j                  |      }|t        d      | j	                  |       }|j
                  |_        t        t        |dd      xs d      |_        |S )Nr	   )SkillHubzBvalidation storage requires local/OSS/S3; Nacos stores skills onlysharing_group_idr   )		skill_hubr'   object_storage_from_config
ValueError__new__r"   strgetattrr#   )clsconfigr'   hubstores        r   from_configzValidationStore.from_config8   s`    '11&9;abbC gf.@)LYPYZr   c                     | j                    dS )N/)r#   )r$   s    r   _prefixzValidationStore._prefixD   s    ..!##r   c                .    | j                          d| dS )Nvalidation_jobs/.jsonr6   r$   job_ids     r   _job_keyzValidationStore._job_keyG   s    ,,.!!1&??r   c                .    | j                          d| dS )Nzcandidate_skills/z	/SKILL.mdr:   r;   s     r   _candidate_skill_keyz$ValidationStore._candidate_skill_keyJ   s    ,,.!!26()DDr   c                4    | j                          d| d| dS )Nvalidation_results/r5   r9   r:   )r$   r<   
user_aliass      r   _result_keyzValidationStore._result_keyM   s#    ,,.!!4VHAj\OOr   c                .    | j                          d| dS )Nzvalidation_decisions/r9   r:   r;   s     r   _decision_keyzValidationStore._decision_keyP   s    ,,.!!6vheDDr   c                   t        |xs d      j                         j                         j                  dd      }dj	                  d |D              j                  d      xs d}t        j                  t        j                        j                  d      }| d| dt        j                         j                  d d  S )N	candidate_-r   c              3  N   K   | ]  }|j                         s|d k(  r|nd   yw)rI   N)isalnum).0chs     r   	<genexpr>z.ValidationStore.make_job_id.<locals>.<genexpr>U   s#     OBRZZ\R3YrC?Os   #%z%Y%m%d%H%M%S   )r-   striplowerreplacejoinr   r   r   r   strftimeuuiduuid4hex)r$   
skill_nameslug	timestamps       r   make_job_idzValidationStore.make_job_idS   s    :,-335;;=EEc3OwwO$OOUUVYZi^iLL.77G	AdV1TZZ\%5%5bq%9$:;;r   c                4   t        |j                  dd      xs d      }|st        d      t        |      }|j	                  dt                      | j                  j                  | j                  |      t        j                  |dd      j                  d             |j                  d	      }t        |t              rV|j                  d
      rD| j                  j                  | j                  |      t        |      j                  d             y y y )Nr<   r   zvalidation job requires job_id
created_atF   ensure_asciiindentutf-8candidate_skillname)r-   getr+   dict
setdefaultr   r"   
put_objectr=   jsondumpsencode
isinstancer?   r   )r$   jobr<   payloadrc   s        r   save_jobzValidationStore.save_jobY   s    SWWXr*0b1=>>s)<8MM&!JJwU1=DDWM	
 "++&78ot,1D1DV1LLL##))&1/66w? 2M,r   c                (   	 t        j                  | j                  j                  | j	                  |            j                         j                  d            S # t        $ r,}t        |      st        j                  d||       Y d }~y d }~ww xY w)Nrb   z+[ValidationStore] failed to load job %s: %s)ri   loadsr"   
get_objectr=   readdecode	Exceptionr   loggerwarningr$   r<   excs      r   load_jobzValidationStore.load_jobj   sp    	::dll55dmmF6KLQQSZZ[bcdd 	%c*LfVYZ	   AA 	B%"BBc                   g }| j                          d}| j                  j                  |      D ]  }|j                  j	                  d      s	 |j                  t        j                  | j                  j                  |j                        j                         j                  d                    |j                  d        |S # t        $ r+}t        j                  d|j                  |       Y d }~d }~ww xY w)Nr8   prefixr9   rb   ([ValidationStore] failed to parse %s: %sc                8    t        | j                  dd            S )Nr]   r   r-   re   items    r   <lambda>z+ValidationStore.list_jobs.<locals>.<lambda>|   s    3txxb'A#B r   keyr6   r"   iter_objectsr   endswithappendri   rq   rr   rs   rt   ru   rv   rw   sort)r$   jobsr~   objry   s        r   	list_jobszValidationStore.list_jobsr   s    %'LLN##34<<,,F,; 	YC77##G,YDJJt||'>'>sww'G'L'L'N'U'UV]'^_`		Y 			B	C  YI377TWXXYs   A$C	D!C<<Dc                   t        |      }||d<   ||d<   |j                  dt                      | j                  j	                  | j                  ||      t        j                  |dd      j                  d             y )Nr<   rB   r]   Fr^   r_   rb   )	rf   rg   r   r"   rh   rC   ri   rj   rk   )r$   r<   rB   resultrn   s        r   save_resultzValidationStore.save_result   sn    v," *<8VZ0JJwU1=DDWM	
r   c                ,   	 t        j                  | j                  j                  | j	                  ||            j                         j                  d            S # t        $ r-}t        |      st        j                  d|||       Y d }~y d }~ww xY w)Nrb   z5[ValidationStore] failed to load result for %s/%s: %s)ri   rq   r"   rr   rC   rs   rt   ru   r   rv   rw   )r$   r<   rB   ry   s       r   load_resultzValidationStore.load_result   s|    
	::dll55d6F6Fvz6Z[``biijqrss 	%c*K	 	s   AA 	B&#BBc                   | j                          d| d}g }| j                  j                  |      D ]  }|j                  j	                  d      s	 |j                  t        j                  | j                  j                  |j                        j                         j                  d                    |j                  d        |S # t        $ r+}t        j                  d|j                  |       Y d }~d }~ww xY w)	NrA   r5   r}   r9   rb   r   c                n    t        | j                  dd            t        | j                  dd            fS )Nr]   r   rB   r   r   s    r   r   z.ValidationStore.list_results.<locals>.<lambda>   s-    s488L"+E'FDHHUaceLfHg&h r   r   r   )r$   r<   r~   resultsr   ry   s         r   list_resultszValidationStore.list_results   s    LLN##6vha@(*<<,,F,; 	YC77##G,Ytzz$,,*A*A#''*J*O*O*Q*X*XY`*abc		Y 	hi  YI377TWXXYs   A$C	D!C??Dc                    t        |      }||d<   |j                  dt                      | j                  j	                  | j                  |      t        j                  |dd      j                  d             y )Nr<   
decided_atFr^   r_   rb   )	rf   rg   r   r"   rh   rE   ri   rj   rk   )r$   r<   decisionrn   s       r   save_decisionzValidationStore.save_decision   sb    x."<8v&JJwU1=DDWM	
r   c                (   	 t        j                  | j                  j                  | j	                  |            j                         j                  d            S # t        $ r,}t        |      st        j                  d||       Y d }~y d }~ww xY w)Nrb   z0[ValidationStore] failed to load decision %s: %s)ri   rq   r"   rr   rE   rs   rt   ru   r   rv   rw   rx   s      r   load_decisionzValidationStore.load_decision   ss    	::dll55d6H6H6PQVVX__`ghii 	%c*QSY[^_	r{   )rB   c                   g }| j                         D ]\  }t        |j                  dd      xs d      }|s%| j                  |      r7|r| j	                  ||      rL|j                  |       ^ |S )Nr<   r   )r   r-   re   r   r   r   )r$   rB   r   rm   r<   s        r   list_open_jobszValidationStore.list_open_jobs   sv    %'>># 	C2.4"5F!!&)d..vzBKK	 r   N)r   r-   r   r-   r   r-   r    r-   r!   r-   r   r-   r   r-   r   r-   r   r-   returnNone)r   z'ValidationStore'r   r-   )r<   r-   r   r-   )r<   r-   rB   r-   r   r-   )rX   r-   r   r-   )rm   dict[str, Any]r   r   )r<   r-   r   Optional[dict[str, Any]])r   list[dict[str, Any]])r<   r-   rB   r-   r   r   r   r   )r<   r-   rB   r-   r   r   )r<   r-   r   r   )r<   r-   r   r   r   r   )rB   r-   r   r   )__name__
__module____qualname____doc__r%   classmethodr3   r6   r=   r?   rC   rE   r[   ro   rz   r   r   r   r   r   r   r   r   r   r   r   r      s    F !" " 	"
 " " " " " " " 
"2 	 	$@EPE<"

 35 r   r   r   )r   
__future__r   ri   loggingrU   r   r   typingr   r   evolve_server.core.utilsr   object_storer
   r   	getLoggerr   rv   r   r   r   r   r   <module>r      sG    #    '   3 @			8	$2c cr   