
    *"hjw                       d Z ddlmZ ddlZddlZddlZddlmZ 	 ddlZddlmZ ddlmZmZ dxd	Zdyd
ZdzdZd{dZd Zd|dZd}dZd~ddZd ZdddZdddZ	 	 	 	 	 	 	 	 ddZ ej:                         d        Zej?                         d        Z ej?                          ejB                  de"dd       ejB                  ddddd       ejB                  d  ej                  de#!      dd"      dd#                            Z$ej?                         d$        Z%ej?                         d%        Z&ej?                  d&'       ejN                  d(       ejN                  d)d*      dd+                     Z(ej;                         d,        Z)e)j?                  d-'      d.        Z*e)j?                  d/'      d0        Z+e)j?                  d1'      d2        Z,e)j?                  d3'      d4        Z-ej;                         d5        Z.e.j?                  d-'       ejB                  d6d7 ej                  dde#8      dd9      dd:              Z/e.j?                  d/'       ejB                  d6d7 ej                  dde#8      dd;      dd<              Z0e.j?                  d1'       ejB                  d6d7 ej                  dde#8      dd=      dd>              Z1e.j?                  d3'       ejB                  d6d7 ej                  dde#8      dd?      dd@              Z2ej;                         dA        Z3e3j?                  dB'      dC        Z4e3j?                  dD'       ejB                  dEddFG      ddH              Z5ej;                         dI        Z6ddddddddddJ		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddKZ7e6j?                  dL'       ejB                  dM ej                  de#!      ddN       ejB                  dO ej                  de#P      ddQ       ejB                  dRe#ddS       ejB                  dTe#ddU       ejB                  dVddWX       ejB                  dYe#ddZ      	 	 	 	 	 	 	 	 	 	 	 	 dd[                                                 Z8e6j?                  d\'       ejB                  d]e#dd^       ejB                  de"dd_       ejB                  dM ej                  de#!      ddN       ejB                  d`ddda       ejB                  dO ej                  de#P      ddb       ejB                  dRe#ddS       ejB                  dTe#ddU       ejB                  dVddWX       ejB                  dYe#ddZ      	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddc                                                                      Z9ej;                         dd        Z:ddeZ;ddfZ<ddgZ=e:j?                  dh'       ejB                  diddjG      dk               Z>e:j?                  dl'       ejN                  dm       ejN                  dn       ejB                  doddpG      dq                             Z?e:j?                  dr'      ds        Z@e:j?                  dL'      dt        ZAe:j?                  du'      dv        ZBeCdwk(  r e        yy# e	$ r  e
d        ej                  d       Y w xY w)u  
SkillClaw CLI entry point.

Usage:
    skillclaw setup          — interactive first-time configuration wizard
    skillclaw start          — start the proxy + skill injection
    skillclaw stop           — stop a running SkillClaw instance
    skillclaw status         — check whether SkillClaw is running
    skillclaw config KEY VAL — set a config value
    skillclaw config show    — show current config
    )annotationsNPathz>SkillClaw requires 'click'. Install it with: pip install click   )runtime_state)CONFIG_FILEConfigStorec                 6    t        j                         dz  dz  S )N
.skillclawzskillclaw.log)r   home     (/root/.hermes/SkillClaw/skillclaw/cli.py_default_daemon_log_pathr      s    99;%77r   c                F    |r|S t        | j                  d      xs d      S )N
proxy.port0u  )intget)config_storeoverride_ports     r   _effective_proxy_portr   #   s&    |-677r   c                ,    t        j                  |       S N)r   process_alivepids    r   _is_process_aliver   )   s    &&s++r   c                 *    t        j                         S r   )r   read_pidr   r   r   	_read_pidr!   -   s    !!##r   c                 ,    t        j                          y r   )r   	clear_pidr   r   r   
_clear_pidr$   1   s    r   c                .    t        j                  |        y r   )r   clear_pid_if_matchesr   s    r   _clear_pid_if_matchesr'   5   s    &&s+r   c                   g d}h d}t               }|D ]5  }|| vrt        j                  | d| |           |j                  |       7 | j	                         D ](  \  }}||v s||v rt        j                  | d|        * dD ]s  }| j                  |      }t        |t              s%t        j                  | d       |st        j                  d       U|D ]  }t        j                  d|         u y )N)statusintegration_scopeconfig_pathconfig_existsexpected_modelconfigured_modelexpected_base_urlconfigured_base_urlconfigured_providerproxy_matchexpected_skills_dirskills_dir_existsskills_dir_modelegacy_skillclaw_skills_dirlegacy_skillclaw_skills_presentlatest_backupsession_boundary_mode>   notesissues
next_steps: )r;   r:   r<   :z  (none)  - )setclickechoadditemsr   
isinstancelist)reportordered_keys	list_keysemittedkeyvalueitems          r   _echo_reportrN   9   s   L& 2IG f

cU"VC[M*+C	 lln &
U'>SI-

cU"UG$%&
 1 	&

3%&

cU!9JJz" 	&DJJdV}%	&	&r   c                T   dd l }	 |j                  j                  d|  d|      5 }|j                  dk7  r
	 d d d        yt	        j
                  |j                         j                  d            }|j                  d      d	u cd d d        S # 1 sw Y   y xY w# t        $ r Y yw xY w)
Nr   zhttp://127.0.0.1:z/healthztimeout   Futf-8okT)
urllib.requestrequesturlopenr)   jsonloadsreaddecoder   	Exception)portrQ   urllibresppayloads        r   _healthz_readyra   g   s    ^^##&7vX$FPW#X 	-\`{{c!	- 	- jj!3!3G!<=G;;t$,		- 	- 	-
  s:   !B BB AB	B BB B 	B'&B'c                 z    t               } | y t        |       st                y t        j                  d|  d      )Nz"SkillClaw is already running (PID=zY). Use 'skillclaw status' to inspect it or 'skillclaw stop' before starting a new daemon.)r!   r   r$   rA   ClickExceptionr   s    r   _ensure_daemon_not_runningrd   t   sG    
+C
{S!



,SE 2a 	a r   c                B   dd l }|j                         |z   }|j                         |k  r^| j                         }|t        j                  d| d|       t        |      ry |j                  d       |j                         |k  r^t        j                  d|       )Nr   z"SkillClaw daemon exited with code z. Check logs: g?z=SkillClaw daemon did not become healthy in time. Check logs: )time	monotonicpollrA   rc   ra   sleep)procr]   log_path	timeout_srf   deadline
returncodes          r   _wait_for_daemon_readyro      s    ~~)+H
..
X
%YY[
!&&)KJ<Wefneo'pqq$

3 ..
X
% 

!^_g^hi
jjr   c                    t        t        j                  j                  dd            j	                         }|s| S 	 t        |      }|dkD  r|S | S # t        $ r | cY S w xY w)N SKILLCLAW_DAEMON_READY_TIMEOUT_S r   )strosenvironr   stripfloat
ValueError)defaultrawrL   s      r   _daemon_ready_timeout_secondsr{      sd    
bjjnn?D
E
K
K
MCc
 AI5*7*  s   A AAc                   dd l }dd l}dd l}|rt        |      j	                         n	t               }|j                  j                  dd       	 t        j                         5  t                t        j                  dddg}| r|j                  dt        |       g       |j                  d      5 }|j                   j#                         }	d	|	d
<   t        |      |	d<   |j$                  ||j&                  d|	d}
|j(                  dk(  r#t+        |dd      t+        |dd      z  }|r||
d<   nd|
d<    |j,                  |fi |
}d d d        	 t/        ||t1                      |j:                  |fcd d d        S # 1 sw Y   8xY w# t2        $ r 	 j5                         |j(                  dk(  r|j7                          n' |j8                  |j:                  |j<                         	 |j?                  d       nn# |j@                  $ r\ |j(                  dk(  r|jC                          n' |j8                  |j:                  |jD                         |j?                  d       Y nw xY wn# t2        $ r Y nw xY wtG        j:                          w xY w# 1 sw Y   y xY w# tH        $ r<}|jJ                  r|jJ                  d   nd}tM        jN                  d| d      d d }~ww xY w)Nr   T)parentsexist_okz-m	skillclawstart--portabdaemonSKILLCLAW_RUNTIME_KINDSKILLCLAW_RUNTIME_LOG_PATH)stdinstdoutstderr	close_fdsenvntDETACHED_PROCESSCREATE_NEW_PROCESS_GROUPcreationflagsstart_new_session)rl      rP   ?z?Another 'skillclaw start --daemon' is already in progress (PID=z>). Wait for it to finish or stop that process before retrying.)(rt   signal
subprocessr   
expanduserr   parentmkdirr   daemon_start_lockrd   sys
executableextendrs   openru   copyDEVNULLSTDOUTnamegetattrPopenro   r{   r\   rh   	terminatekillpgr   SIGTERMwaitTimeoutExpiredkillSIGKILLr'   RuntimeErrorargsrA   rc   )r]   log_fileeffective_portrt   r   r   rk   cmd
log_handle	child_envpopen_kwargsr   rj   exc	owner_pids                  r   _spawn_daemon_processr      s   
 .6tH~((*<T<VHOO$6?,,. 8	&&(>>4g>C

Hc$i01t$ =
JJOO-	6>	23:=h-	67'//((//!%$  77d?$+J8JA$NQX"$>R %M %8E_58<L!45'z''<|<'=*&";=	6 88X%q8	& 8	&= =8  yy{*77d? NN,%BIIdhh?1 IIaI0)88 1!ww$ $		 )		$((FNN C IIaI01 !  &dhh/'G8	& 8	&r  #&88CHHQK	""Mi[ YJ J
 	s   J# $AJ2BE=JF	&J3	J# =F	J	
JAI.,G?>I.?A(I*'I.)I**I.-J.	I:7J9I::JJJ J#  J# #	K(,7K##K(c                      y)uK   SkillClaw — Claw agent skill injection and cloud session data collection.Nr   r   r   r   r   r          r   c                 :    ddl m}   |        j                          y)z,Interactive first-time configuration wizard.r   SetupWizardN)setup_wizardr   runr   s    r   setupr      s     *Mr   r   z%Override proxy port for this session.)typery   helpz--daemonz-dTFz Run SkillClaw in the background.)is_flagry   r   z
--log-file)dir_okay	path_typezBLog file used with --daemon (default: ~/.skillclaw/skillclaw.log).c                   ddl }ddlm}  |        t               }|j	                         s,t        j                  dd       t        j                  d       |r8t        | |t        ||             \  }}t        j                  d	| d
| d       y| rddl}ddl}	ddlm}
 |j                         }| |j                  di       d<   |j!                  dddd      }	 |	j#                  ||       |j%                          t'        |j(                        } |
|      }nd}ddlm}  ||      }	 |j/                  |j1                                ||j7                  d       yy# |j%                          w xY w# t2        $ r( t        j                  d       |j5                          Y [w xY w# ||j7                  d       w w xY w)z9Start SkillClaw (proxy + skill injection + optional PRM).r   Nr   )setup_loggingz-No config found. Run 'skillclaw setup' first.Terr)r   z%SkillClaw started in background (PID=z	). Logs: zI. Use 'skillclaw status' to check health and 'skillclaw stop' to stop it.)r	   proxyr]   wz.yamlFrS   )modesuffixdeleteencoding)config_file)SkillClawLauncheru$   
Interrupted — stopping SkillClaw.
missing_ok)asyncio	log_colorr   r	   existsrA   rB   r   exitr   r   tempfileyamlr   load
setdefaultNamedTemporaryFiledumpcloser   r   launcherr   r   r   KeyboardInterruptstopunlink)r]   r   r   r   r   csr   rk   r   r   _CSdatatmptmp_pathr   r   s                   r   r   r      s   , (O	B99;

;	
 	-0T:
X
 	

3C5	( LV V	
 	4wwy/3$V,))s75[b)c	IIdC IIK>X&+ $H-HNN$%
 OOtO,   IIK  

:; OOtO,  s0   E$ /E9 $E69.F*'F- )F**F- -Gc                 <   ddl } ddl}ddlm}  |j                         dz  dz  }|j                         st        j                  d       y	 t        |j                         j                               } | j                  ||j                         |j                  d       t        j                  d	| d
       y# t        $ r* t        j                  d       |j                  d       Y yt        $ r$}t        j                  d| d       Y d}~yd}~ww xY w)z"Stop a running SkillClaw instance.r   Nr   r   zskillclaw.pidz-SkillClaw is not running (no PID file found).Tr   zSent SIGTERM to PID .u1   Process not found — cleaning up stale PID file.zError stopping SkillClaw: r   )rt   r   pathlibr   r   r   rA   rB   r   	read_textrv   r   r   r   ProcessLookupErrorr\   )rt   r   r   pid_filer   es         r   r   r   H  s     tyy{\)O;H??

BC	?($$&,,./V^^$4(

)#a01 )

FG4( ?

/s3>>?s   A/B= =0D/D7DDc                 ~   t               } | t        j                  d       yt        |       s t        j                  d       t	                yt               }t        |j                  d      xs d      }t        |d      }|rt        j                  d|  d	| d
       yt        j                  d|  d	| d
       y)z#Check whether SkillClaw is running.NzSkillClaw: not runningz'SkillClaw: not running (stale PID file)r   r   g       @rP   zSkillClaw: running  (PID=z	, proxy=:)zSkillClaw: starting (PID=)	r!   rA   rB   r   r$   r	   r   r   ra   )r   r   r]   healthys       r   r)   r)   _  s     +C
{

+,S!

<=	Brvvl#,u-DT3/G

.se9TF!DE

.se9TF!DEr   config)r   key_or_actionrL   )requiredc                   t               }| dk(  rg|j                         st        j                  d       yt        j                  dt         d       t        j                  |j                                y|G|j                  |       }|t        j                  |  d       yt        j                  |  d|        y|j                  | |       t        j                  d|  d	|j                  |               y)
ztGet or set a config value.

    Examples:

      skillclaw config show

      skillclaw config proxy.port 30001
    show2No config file found. Run 'skillclaw setup' first.NzConfig file: 
z: (not set)r=   zSet z = )r	   r   rA   rB   r   describer   r@   )r   rL   r   results       r   
config_cmdr   v  s     
Byy{JJKL

];-r23

2;;=!}&>JJ-45 	 JJ-6(34FF=% 	JJm_C}(='>?@r   c                      y)zIntegration diagnostics.Nr   r   r   r   doctorr     r   r   hermesc                     ddl m}  t               }|j                         st	        j
                  d       | |j                               }t        |       y)z+Inspect the local Hermes integration state.r   )inspect_hermes_configr   N)claw_adapterr   r	   r   rA   rc   to_skillclaw_configrN   )r   r   rG   s      r   doctor_hermesr     D     4	B99;""#WXX"2#9#9#;<Fr   codexc                     ddl m}  t               }|j                         st	        j
                  d       | |j                               }t        |       y)z*Inspect the local Codex integration state.r   )inspect_codex_configr   N)r   r  r	   r   rA   rc   r   rN   )r  r   rG   s      r   doctor_codexr    sD     3	B99;""#WXX!""8"8":;Fr   claudec                     ddl m}  t               }|j                         st	        j
                  d       | |j                               }t        |       y)z0Inspect the local Claude Code integration state.r   )inspect_claude_configr   N)r   r  r	   r   rA   rc   r   rN   )r  r   rG   s      r   doctor_clauder    r   r   opencodec                     ddl m}  t               }|j                         st	        j
                  d       | |j                               }t        |       y)z-Inspect the local OpenCode integration state.r   )inspect_opencode_configr   N)r   r
  r	   r   rA   rc   r   rN   )r
  r   rG   s      r   doctor_opencoder    sD     6	B99;""#WXX$R%;%;%=>Fr   c                      y)z-Restore agent integration state from backups.Nr   r   r   r   restorer    r   r   z--backupbackup_path)r   r   r   zHRestore from a specific backup file instead of the latest Hermes backup.c                    ddl m} 	  || rt        |       j                         nd      }t        j                  d|d    d|d           y# t        $ r$}t        j                  t        |            dd}~ww xY w)z2Restore ~/.hermes/config.yaml from a saved backup.r   )restore_hermes_configNzRestored Hermes config: target <- source)	r   r  r   r   FileNotFoundErrorrA   rc   rs   rB   )r  r  r   r   s       r   restore_hermesr    sz     47&tK'8'C'C'EZ^_ 
JJ)&*:);4x@P?QRS  7""3s8,$67   #A 	A:A55A:zGRestore from a specific backup file instead of the latest Codex backup.c                N   ddl m} 	  || rt        |       j                         nd      }t        j                  d|d    d|d           |j                  d      d	k(  rt        j                  d
       yy# t        $ r$}t        j                  t        |            dd}~ww xY w)z1Restore ~/.codex/config.toml from a saved backup.r   )restore_codex_configNzRestored Codex config: r  r  r  removed_profileTruezFRemoved Codex SkillClaw profile config: ~/.codex/skillclaw.config.toml)
r   r  r   r   r  rA   rc   rs   rB   r   )r  r  r   r   s       r   restore_codexr    s     37%d;&7&B&B&DY]^ 
JJ()9(:$vh?O>PQRzz#$.

[\ /	  7""3s8,$67s   #A7 7	B$ BB$zMRestore from a specific backup file instead of the latest Claude Code backup.c                    ddl m} 	  || rt        |       j                         nd      }t        j                  d|d    d|d           y# t        $ r$}t        j                  t        |            dd}~ww xY w)z4Restore ~/.claude/settings.json from a saved backup.r   )restore_claude_configNzRestored Claude Code settings: r  r  r  )	r   r  r   r   r  rA   rc   rs   rB   )r  r  r   r   s       r   restore_clauder    sz     47&tK'8'C'C'EZ^_ 
JJ01A0B$vhGWFXYZ  7""3s8,$67r  zJRestore from a specific backup file instead of the latest OpenCode backup.c                    ddl m} 	  || rt        |       j                         nd      }t        j                  d|d    d|d           y# t        $ r$}t        j                  t        |            dd}~ww xY w)z=Restore ~/.config/opencode/opencode.json from a saved backup.r   )restore_opencode_configNzRestored OpenCode config: r  r  r  )	r   r   r   r   r  rA   rc   rs   rB   )r  r   r   r   s       r   restore_opencoder!    sz     67(;k):)E)E)G\`a 
JJ+F8,<+=T&BRASTU  7""3s8,$67r  c                      y)zBackground validation commands.Nr   r   r   r   
validationr#  %  r   r   r)   c                     ddl m}  t               }|j                         } | |      }|j	                         }|j                         D ]  \  }}t        j                  | d|        ! y)zBShow background validation configuration and current availability.r   ValidationWorkerr=   N)validation_workerr&  r	   r   status_snapshotrD   rA   rB   )r&  r   cfgworkersnapshotrK   rL   s          r   validation_statusr,  *  se     4	B

 
 
"Cc"F%%'Hnn& &
U

cU"UG$%&r   zrun-oncez--forcez7Run one validation poll even if the client is not idle.)r   r   c                   ddl }ddlm} t               }|j	                         } ||      }|j                  |j                  |             }|j                         D ]  \  }}t        j                  | d|        ! y)z0Run one background validation polling iteration.r   Nr   r%  )forcer=   )
r   r'  r&  r	   r   r   run_oncerD   rA   rB   )	r.  r   r&  r   r)  r*  r   rK   rL   s	            r   validation_run_oncer0  7  sr     3	B

 
 
"Cc"F[[u56Flln &
U

cU"UG$%&r   c                      y)z+Dashboard and skill visualization commands.Nr   r   r   r   	dashboardr2  G  r   r   	hostr]   db_pathno_sync_on_startsharing_local_rootsharing_group_idsharing_user_aliasinclude_sharedevolve_server_urlc       	            |r|| _         |r|| _        |r|| _        |rd| _        |rd| _        d| _        || _        |r|| _        |r|| _        ||| _	        |	|	| _
        | S )NFTlocal)dashboard_hostdashboard_portdashboard_db_pathdashboard_sync_on_startsharing_enabledsharing_backendr7  r8  r9  dashboard_include_shareddashboard_evolve_server_url)
r)  r4  r]   r5  r6  r7  r8  r9  r:  r;  s
             r   "_apply_dashboard_runtime_overridesrF  L  s     !! '&+#"%!3/!3!'5$$*;'Jr   syncz	--db-pathz$Override dashboard SQLite file path.z--sharing-local-root)	file_okayr   zOUse a local filesystem directory as the shared storage root for dashboard sync.z--sharing-group-idz!Override shared storage group id.z--sharing-user-aliaszOverride sharing user alias.z$--include-shared/--no-include-sharedzEControl whether shared storage is included in the dashboard snapshot.)ry   r   z--evolve-server-urlz Override evolve server base URL.c           	        ddl m} t               }t        |j	                         | |||||      } ||      }	|	j                         }
|
d   }t        j                  d|d    d|d    d	|d
    d       t        j                  d|j                          |j                  d      xs g }|r5t        j                  d       |D ]  }t        j                  d|         yy)z(Refresh the dashboard SQLite projection.r   )DashboardService)r5  r7  r8  r9  r:  r;  summaryzDashboard snapshot synced: skillsz	 skills, sessionsz sessions, validation_jobsz validation jobs.zSQLite: warningsz	Warnings:r?   N)
dashboard_serverrJ  r	   rF  r   rG  rA   rB   r@  r   )r5  r7  r8  r9  r:  r;  rJ  r   r)  servicer   rK  rO  rM   s                 r   dashboard_syncrR  p  s    < 3	B
,
 -)-%+C s#G\\^FYG	JJ
%8
Y:
{$%
&&7	9 
JJ#//012{{:&,"H

; 	&DJJdV}%	& r   servez--hostzOverride dashboard host.zOverride dashboard port.z--no-sync-on-startz:Start the dashboard without rebuilding the snapshot first.zXUse a local filesystem directory as the shared storage root while serving the dashboard.c	                    ddl m}	 t               }
t        |
j	                         | ||||||||
      }t        j                  d|j                   d|j                   d|j                   d        |	|       y)	zServe the dashboard UI and API.r   )serve_dashboardr3  z'Starting SkillClaw dashboard at http://r>   z (db: r   N)
rP  rU  r	   rF  r   rA   rB   r>  r?  r@  )r4  r]   r5  r6  r7  r8  r9  r:  r;  rU  r   r)  s               r   dashboard_serverV    s    R 2	B
,
 )-)-%+C 
JJ
1#2D2D1EQsGYGYFZ [%%&a	) Cr   c                      y)zSkill management commands.Nr   r   r   r   rL  rL    r   r   c                   t        t        | dd      xs d      j                         j                         xs6 t        t        | dd      xs d      j                         j                         }|r|S t        | dd      ryy)Nsharing_skill_backendrr   rC  r7  r=  oss)rs   r   rv   lower)r)  backends     r   _sharing_backendr]    s|    GC0"5;<BBDJJL 	Jws-r28b9??AGGI  s("-r   c                   t        |       }t        | dd      }|dk(  rd| j                   d| dS |dk(  r}t        | dd	      xsH t        t        | d
d	      xs d	      j	                         j                         dk(  rt        | dd	      nd	}t        | dd      }t        | dd      }d| d| d| dS t        | dd	      }t        | dd	      }|r| d| n|}|r| d| d| dS | d| dS )Nr8  ry   r=  zlocal storage (/r   nacossharing_nacos_serverrr   rC  sharing_endpointsharing_nacos_namespace_idpublicsharing_nacos_labellatestznacos (z, label=z @ sharing_bucketz
 storage ()r]  r   r7  rs   rv   r[  )	r)  r\  groupservernamespace_idlabelbucketendpointr  s	            r   _sharing_targetrn    s;   s#GC+Y7E' !7!7 8%BB'4b9 
73 126<"=CCEKKMQXX C+R0 	
 s$@(K2H=hugSBBS*B/Fs.3H$*xq F*VHCz;;Yj**r   c                n   | j                         }|j                  st        j                  d      t	        |      }|dk(  r"|j
                  sMt        j                  d      |dk(  rN|j                  st        j                  d      |j                  r|j                  st        j                  d      |dk(  rZ|j                  r|j                  st        j                  d      |j                  r|j                  st        j                  d	      |d
k(  rlt        t        |dd      xs d      j                         j                         d
k(  rt        |dd      nd}t        |dd      s,|s*t        j                  d      t        j                  d      ddlm} |j!                  |      }||fS )zSValidate that sharing is enabled and configured. Returns (cfg, SkillHub) or raises.zlSkill sharing is not enabled. Run 'skillclaw config sharing.enabled true' or 'skillclaw setup' to configure.r=  zFLocal sharing backend is not configured. Set sharing.local_root first.s3z6S3 bucket is not configured. Set sharing.bucket first.z[S3 credentials are not configured. Set sharing.access_key_id and sharing.secret_access_key.rZ  zXOSS endpoint or bucket is not configured. Set sharing.endpoint and sharing.bucket first.z\OSS credentials are not configured. Set sharing.access_key_id and sharing.secret_access_key.r`  rC  rr   rb  ra  z~Nacos skill backend is not configured. Set sharing.nacos_server first (legacy sharing.backend=nacos may use sharing.endpoint).zSSharing backend is not configured. Set sharing.backend to local, s3, oss, or nacos.r   )SkillHub)r   rB  rA   rc   r]  r7  rg  sharing_access_key_idsharing_secret_access_keyrb  rs   r   rv   r[  	skill_hubrq  from_config)r   r)  r\  legacy_endpointrq  hubs         r   _require_sharingrx    s   

 
 
"C""]
 	
 s#G'%%&&'opp	D!!&&'_``((0M0M&&m  
E	##3+=+=&&j  ((0M0M&&n  
G	 73 126<"=CCEKKMQXX C+R0 	
 3R8O&&K 
 ""a
 	
 $


s
#C8Or   pushz--no-filterz Skip effectiveness quality gate.c                   t               }t        |      \  }}t        j                  dt	        |       d       d}| st
        j                  j                  |j                  d      }t
        j                  j                  |      rGddl
}	 t        |d      5 } |j                  |      }ddd       |j                  |j                  d}|j!                  |j                  |	      }	t        j                  d
|	d    d|	d    d|	j#                  dd       d|	j#                  dd       d|	d    d       y# 1 sw Y   xY w# t        $ r Y w xY w)z&Push local skills to the shared cloud.zPushing skills to  ...Nzskill_stats.jsonr   rS   )r   )statsmin_injectionsmin_effectiveness)skill_filterDone: uploaded uploaded, skipped unchanged, filteredz filtered, 	submittedz submitted, total_localz total local skills.)r	   rx  rA   rB   rn  rt   pathjoin
skills_dirr   rX   r   r   sharing_push_min_injectionssharing_push_min_effectivenessr\   push_skillsr   )
	no_filterr   r)  rw  r  
stats_pathrX   fr|  r   s
             r   skills_pushr  C  sH    
B#HC	JJ#OC$8#9>?LWW\\#..2DE
77>>*%	*w7 )1%DIIaLE) #&)&E&E),)K)K  __S^^,_GF	JJ

#$K)
\::j!$
%[::k1%
&l- 
!!5		7) )  s*   E D;-"E ;E E 	EEpublishr   versionz--no-update-latestz6Publish the version without updating the latest label.c           	        t               }t        |      \  }}t        |      dk7  st        |d      st	        j
                  d      |j                  | ||       }t	        j                  d|d    d|d    d	|d
    d       y)z(Publish an approved Nacos skill version.r`  publish_skillzEskills publish is only available when sharing.skill_backend is nacos.)update_latest_labelz
Published 
skill_name r  z (updated latest: updated_latest_labelz).N)r	   rx  r]  hasattrrA   rc   r  rB   )r   r  no_update_latestr   r)  rw  r   s          r   skills_publishr  d  s     
B#HC'wsO/L""#jkktWFVBVWF	JJ
VL)*!F9,=+>>PQWXnQoPpprsr   pullc                    t               } t        |       \  }}t        j                  dt	        |       d       |j                  |j                        }d|d    d|d    d|j                  dd	       d
|j                  dd	       d|d    d}|j                  d      r'|ddj                  |j                  dg              z  }|j                  d      r|d|j                  dd       z  }t        j                  |       y)z"Pull shared skills from the cloud.zPulling skills from r{  r  
downloaded downloaded, r  r  failedr   z	 failed, deletedz
 deleted, total_remotez total remote skills.failed_namesz	 Failed: z, restored_from_backupz Restored from backup: 
backup_dirrr   N)	r	   rx  rA   rB   rn  pull_skillsr  r   r  )r   r)  rw  r   msgs        r   skills_pullr  x  s    
B#HC	JJ%oc&:%;4@A__S^^,F
%&m)
\::h"
#9::i#
$J.!
""7		9  zz.!499VZZ%CDEFFzz()(L")E(FGG	JJsOr   c                    t               } t        |       \  }}t        j                  dt	        |       d       |j                  |j                        }|d   }|d   }t        j                  d|d    d|d    d	|d
    d|d    d	       y)z#Bidirectional sync: pull then push.zSyncing skills with r{  r  ry  zPull: r  r  r  z unchanged
Push: r  r  z
 unchangedN)r	   rx  rA   rB   rn  sync_skillsr  )r   r)  rw  r   prpss         r   skills_syncr    s     
B#HC	JJ%oc&:%;4@A__S^^,F	B	B	JJ
L!"-9 ?J ByM?*	Fr   zlist-remotec                    t               } t        |       \  }}|j                         }|st        j                  d       yt        j                  dd        t        j                  dt        |       d       t        j                  d d       t        |d       D ]  }|j                  d	d
      }|j                  dd      }|j                  dd      }|j                  dd
      }|j                  dd
      }	t        j                  d| d| d       |rt        j                  d|        t        j                  d| d|	        t        j                           y)z4List skills available in the shared storage backend.zNo skills found on the cloud.Nr   z<============================================================z  Shared Skills (z total)c                &    | j                  dd      S )Nr   rr   )r   )rs    r   <lambda>z$skills_list_remote.<locals>.<lambda>  s    AEE&",= r   )rK   r   r   descriptionrr   categorygeneraluploaded_byuploaded_atz  z  []z    z    by z  at )r	   rx  list_remoterA   rB   lensortedr   )
r   r)  rw  remoterecr   desccatbyats
             r   skills_list_remoter    s/    
B#HC__F

23	JJH:	JJ"3v;-w78	JJ(2f"=> 
wwvs#ww}b)ggj),WW]C(WW]C(

RvSQ'(JJdV}%

WRDbT*+


r   __main__)returnr   )r   r	   r   
int | Noner  r   )r   r   r  bool)r  r  )r   r   )rG   zdict[str, object]r  None)g      ?)r]   r   rQ   rw   r  r  )g      .@)r]   r   rk   r   rl   rw   )ry   rw   r  rw   )r]   r  r   
str | Noner   r   r  ztuple[int, Path])r]   r  r   r  r   r  )r   rs   rL   r  )r  r  )r.  r  )r4  r  r]   r  r5  r  r6  r  r7  r  r8  r  r9  r  r:  bool | Noner;  r  )r5  r  r7  r  r8  r  r9  r  r:  r  r;  r  )r  rs   )r   r	   )D__doc__
__future__r   rX   rt   r   r   r   rA   ImportErrorprintr   rr   r   r   r   r	   r   r   r   r!   r$   r'   rN   ra   rd   ro   r{   r   rh  r   commandr   optionr   rs   r   r   r)   argumentr   r   r   r  r  r  r  r  r  r  r!  r#  r,  r0  r2  rF  rR  rV  rL  r]  rn  rx  r  r  r  r  r  __name__r   r   r   <module>r     s	  
 #  	 
 
  288,$,+&\
k+K
KK K 	K\ V V   		0	 	+ 	Uc	2	M	9- (9-x ? ?, F F, ! %(A ) ! "A8 # # X	 	 W	 	 X	 	 Z 	 !	 8 8 	h	4%3	?	S	T  	T 	g	4%3	?	R] ] 	h	4%3	?	X	[  	[ 	j!	4%3	?	U	V "	V * * "	& #	& $i,ef& g %& 6 6 "%)#'%)"&$(! ! 	!
 ! ! #! !! #!  ! "!H 	Uc	2	/	 	es	3	Z	 "dAde$3Cab*	P
 ##tBde#&#&"#& !#& #	#&
  #& "#& f c f  *#&L  hS$5OPhS$5OP	Uc	2	/	 	E	 	es	3	c	 "dAde$3Cab*	P
 ##tBde 
 
    	 
 #  !  #     "  f c f Q Q !: F % %	+,.b VmT0RS T > Y		A
	    	 V ( V  ]# $0 zK }  	
JKCHHQKs   [ [%$[%