
    *"hj                      U d Z ddlm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mZ ddlZerddlmZ  ej&                  e      Z ej,                         dz  d	z  Z ej,                         d
z  Zed	z  Z ej,                         dz  dz  dz  Z ej,                         dz  Zedz  Zedz  Zed	z  Z ej,                         dz  dz  dz  Z ej,                         dz  Z e dz  Z!e d	z  Z" ej,                         dz  dz  dz  Z# ej,                         dz  dz  Z$e$dz  Z%e$d	z  Z& ej,                         dz  dz  dz  Z'dVdZ(dVdZ)dWdZ*dWdZ+dXdZ,dYdZ-dZdZ.	 	 	 	 	 	 	 	 	 	 	 	 	 	 d[dZ/d\dZ0d]d Z1d^d!Z2d_d"Z3d`d#Z4dad$Z5dbd%Z6dcd&Z7ddd'Z8ded(Z9dfd)Z:dXd*Z;dVd+Z<dgd,Z=dhdid-Z>dVd.Z?djd/Z@ded0ZAdfd1ZBdkd2ZCdld3ZDdVd4ZEdgd5ZFdhdid6ZGdmd7ZHdfd8ZIdVd9ZJdgd:ZKdhdid;ZLded<ZMdfd=ZNdVd>ZOdVd?ZPdgd@ZQdhdidAZRdndodBZSdpdCZTdqdDZUdVdEZVdVdFZWdrdsdGZXdVdHZYdVdIZZdtdJZ[dVdKZ\dfdLZ]dVdMZ^dudNZ_dVdOZ`e)e<eEeJePeVeWeYeZe\e^e`dPZadQebdR<    ecea      ZddSebdT<   	 dv	 	 	 	 	 	 	 dwdUZey)xu  
Claw adapter: auto-configures the active CLI agent to use the SkillClaw proxy.

Supported agents:
  openclaw  — runs `openclaw config set …` + `openclaw gateway restart`
  opencode  — patches ~/.config/opencode/opencode.json to register SkillClaw provider
  hermes    — patches ~/.hermes/config.yaml to point model traffic at SkillClaw
  codex     — patches ~/.codex/config.toml to register an opt-in SkillClaw profile
  claude    — patches ~/.claude/settings.json to route Anthropic traffic via SkillClaw
  qwenpaw   — patches QwenPaw model config, selects SkillClaw as active model
  ironclaw  — patches ~/.ironclaw/.env, runs `ironclaw service restart`
  picoclaw  — patches ~/.picoclaw/config.json model_list, runs `picoclaw gateway restart`
  zeroclaw  — patches ~/.zeroclaw/config.toml, runs `zeroclaw service restart`
  nanoclaw  — patches nanoclaw's .env (ANTHROPIC_BASE_URL), restarts via launchd/systemd
  nemoclaw  — registers skillclaw provider in OpenShell, sets inference route
  none      — skip auto-configuration entirely

Add more claws by implementing a `_configure_<name>` function and registering
it in ``_ADAPTERS``.
    )annotationsN)Path)TYPE_CHECKINGCallable   )SkillClawConfigz
.skillclawskillsz.hermesbackupshermesz.codexconfig.tomlzskillclaw.config.tomlcodexz.claudezsettings.jsonclaude.configopencodezopencode.jsonc                    t        | dd      }t        | dd      }|sd}t        j                  |      }|t        j	                  d|       y ||        y)z@Dispatch to the appropriate claw adapter based on cfg.claw_type.	claw_typeopenclawconfigure_openclawTnoneNuB   [ClawAdapter] Unknown claw_type=%r — skipping auto-configuration)getattr	_ADAPTERSgetloggerwarning)cfgclawconfigure_flagadapters       1/root/.hermes/SkillClaw/skillclaw/claw_adapter.pyconfigure_clawr    B   sV    3Z0D S"6=NmmD!G[]abCL    c                   | j                   xs | j                  xs d}t        j                  dd| j                   d| j
                  xs d||ddgddddd	d
ddgd      }ddddd|gddddd| gg dg dg}t        d|       y)z3Auto-configure OpenClaw to use the SkillClaw proxy.skillclaw-modelopenai-completionshttp://127.0.0.1:/v1	skillclawFtextr   inputoutput	cacheRead
cacheWrite       idname	reasoningr*   costcontextWindow	maxTokens)apibaseUrlapiKeymodelsr   configsetzmodels.providers.skillclawz--jsonzagents.defaults.model.primary
skillclaw/)r   r;   r<   zagents.defaults.sandbox.modeoffr   gatewayrestartN)served_model_namellm_model_idjsondumps
proxy_portproxy_api_key_run_commands)r   model_idprovider_jsoncommandss       r   _configure_openclawrL   W   s    $$M(8(8M<MHJJ'*3>>*:#>''6; #$!&$X&'11TUV%*!%
		
M( 
Xu&BHm\	Xu&ET\S]G^_L*	H *h'r!   c                0   | j                         si S 	 t        j                  | j                  d            xs i }t        |t              r|S t
        j                  d||        i S # t        $ r$}t
        j                  d|| |       i cY d}~S d}~ww xY w)z6Load a YAML mapping, falling back to an empty mapping.utf-8encoding-[ClawAdapter] Failed to read %s config %s: %sN9[ClawAdapter] %s config %s is not a mapping; replacing it)	existsyaml	safe_load	read_text	Exceptionr   r   
isinstancedictpathlabelloadedes       r   _load_yaml_mappingr_   {   s    ;;=	 @AGR
 &$
NNC
 I  FtUVW	   )A( (	B1B
BBc                0   | j                         si S 	 t        j                  | j                  d            xs i }t        |t              r|S t
        j                  d||        i S # t        $ r$}t
        j                  d|| |       i cY d}~S d}~ww xY w)z6Load a JSON mapping, falling back to an empty mapping.rN   rO   rQ   NrR   )	rS   rD   loadsrV   rW   r   r   rX   rY   rZ   s       r   _load_json_mappingrc      s    ;;=	DNNGN<=C
 &$
NNC
 I  FtUVW	r`   c                   | j                   j                  dd       d}	 t        j                  dd| j                   d| j                   dd      5 }t        |j                        }|j                  t        |             |j                          t        j                  |j                                ddd       t        j                  ||        t        j                  d	||        ||j#                  d       yy# 1 sw Y   LxY w# t        $ r"}t        j!                  d
|| |       Y d}~Hd}~ww xY w# ||j#                  d       w w xY w)z(Atomically write a YAML mapping to disk.Tparentsexist_okNwrN   .FmoderP   dirprefixdelete#[ClawAdapter] %s config updated: %s.[ClawAdapter] Failed to write %s config %s: %s
missing_ok)parentmkdirtempfileNamedTemporaryFiler2   r   write_yaml_mapping_to_textflushosfsyncfilenoreplacer   inforW   errorunlinkr[   datar\   tmp_pathhandler^   s         r   _write_yaml_mapping_atomicr      s(   KKdT2 H-((tyyk#
 
	& FKK(HLL.t45LLNHHV]]_%
	& 	

8T"95$G OOtO,  !
	& 
	&  WEudTUVVW OOtO,  sB   2D A#D65D D
D 	D8D3.D; 3D88D; ;Ec                2    t        j                  | dd      S )NFT)	sort_keysallow_unicode)rT   	safe_dump)r   s    r   rx   rx      s    >>$%tDDr!   c                   | j                   j                  dd       d }	 t        j                  dd| j                   d| j                   dd      5 }t        |j                        }|j                  |       |j                          t        j                  |j                                d d d        t        j                  ||        t        j                  d||        ||j!                  d
       y y # 1 sw Y   LxY w# t        $ r"}t        j                  d	|| |       Y d }~Hd }~ww xY w# ||j!                  d
       w w xY w)NTre   rh   rN   ri   Frj   z[ClawAdapter] %s updated: %sz'[ClawAdapter] Failed to write %s %s: %srq   )rs   rt   ru   rv   r2   r   rw   ry   rz   r{   r|   r}   r   r~   rW   r   r   )r[   r(   r\   r   r   r^   s         r   _write_text_atomicr      s!   KKdT2 H-((tyyk#
 
	& FKK(HLLLLNHHV]]_%
	& 	

8T"2E4@ OOtO,  !
	& 
	&  P>tQOOP OOtO,  sB   2D AC8-5D 8D=D 	D/D*%D2 *D//D2 2E	c               j   | j                         sy	 | j                  d      }||k(  ry|j                  dd       t        j                  j                  t        j                  j                        j                  d      }|| d| d| z  }	|| d	| z  }
	 |	j                  |d       |
j                  |d       t        j                  d
||	       |	S # t        $ r!}t        j	                  d| |       Y d}~yd}~ww xY w# t        $ r!}t        j	                  d||       Y d}~yd}~ww xY w)z9Save a timestamped backup before overwriting a text file.NrN   rO   z.[ClawAdapter] Failed to read %s for backup: %sTre   z%Y%m%dT%H%M%SZri   .latest.z![ClawAdapter] %s backup saved: %sz*[ClawAdapter] Failed to save %s backup: %s)rS   rV   rW   r   r   rt   datetimenowtimezoneutcstrftime
write_textr~   )r[   new_text
backup_dirbackup_stembackup_suffixr\   current_textr^   	timestampbackup_pathlatest_paths              r   _backup_text_file_if_changedr      s0    ;;=~~w~7
 xTD1!!%%h&7&7&;&;<EEFVWI+a	{!M?KKK+h}oFFK|g>|g>7L  GqQ   CUANs/   C >D 	D$D  D	D2D--D2c                    | | d| z  }|j                         r|S | j                         sy t        | j                  | d|             }|r|d   S d S )Nr   z.*.)rS   is_dirsortedglob)r   r   r   r   r
   s        r   _latest_backup_pathr     sg    +h}oFFKZ__}C%GHIG!72;+t+r!   c                    t        | t              r| rdS dS t        | t              rt        |       S t        | t              rt        |       S t        j                  t        |       d      S )NtruefalseF)ensure_ascii)rX   boolintstrfloatreprrD   rE   )values    r   _format_toml_valuer     sV    %v+G+%5z%E{::c%ju55r!   c                    | j                         }t        |      dk\  r8|j                  d      r'|j                  d      r	 t	        j
                  |      S |dk(  ry|dk(  ry|S # t        $ r |dd cY S w xY w)	N   "r   r   r   Tr   F)striplen
startswithendswithrD   rb   rW   )rawr   s     r   _parse_toml_valuer     s}    IIKE
5zQ5++C0U^^C5H	::e$$ L  	2;	s   A% %A65A6c           	        | j                         }t        |      }t        |      D ]<  \  }}|j                         }|j	                  d      s(|j                  d      s:|} n |d| }||d }t               }	g }
|D ]  }|j                         }|j	                  d      sd|vr|
j                  |       :|j                  dd      d   j                         }||v r4|
j                  | dt        ||                 |	j                  |       |
j                  |        |D cg c]	  }||	vs| }}|rb|
r$|
d	   j                         r|
j                  d
       |D ]$  }|
j                  | dt        ||                 & |r|
j                  d
       |
|z   }dj                  |      j                         dz   S c c}w )z@Update simple top-level TOML assignments before the first table.[]N#=r   r   z = r    
)
splitlinesr   	enumerater   r   r   r<   appendsplitr   addjoinrstrip)r(   updateslinesfirst_table_indexidxlinestrippedpreamble	remainderseenupdated_preamblekeymissing_keysmergeds                 r   _upsert_top_level_toml_keysr   $  s   OOEE
u% 	T::<s#(9(9#(> #	 ''(H'()IUD"$ 
&::<s#s(':##D)nnS!$Q'--/'>##se3/A'#,/O.P$QRHHSM%
& $+>CcoC>L> 0 4 : : <##B' 	SC##se3/A'#,/O.P$QR	S##B'	)F99V##%,, ?s   *	G4Gc                   | j                         }t        |      }t        |      D ]<  \  }}|j                         }|j	                  d      s(|j                  d      s:|} n |d| }||d }g }	|D ]r  }|j                         }|j	                  d      sd|vr|	j                  |       :|j                  dd      d   j                         }
|
|vsb|	j                  |       t dj                  |	|z         j                         dz   S )	zBRemove selected top-level assignments before the first TOML table.r   r   Nr   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )r(   keysr   r   r   r   r   r   r   keptr   s              r   _remove_top_level_toml_keysr   L  s   OOEE
u% 	T::<s#(9(9#(> #	 ''(H'()ID ::<s#s(':KKnnS!$Q'--/d?KK 99TI%&--/$66r!   c                4   | j                         }g }d}d| d}|D ]X  }|j                         }|j                  d      xr |j                  d      }|r|rd}||k(  rd}E|rH|j	                  |       Z dj                  |      j                         dz   S )z-Remove a TOML table and its body, if present.Fr   r   Tr   )r   r   r   r   r   r   r   )	r(   
table_namer   r   skippingtarget_headerr   r   	is_headers	            r   _remove_toml_tabler   d  s    OOEDH
|1%M ::<'',G1B1B31G	 =(D 99T?!!#d**r!   c                T   i }| j                         }d| d}d}|D ]  }|j                         }|j                  d      r|j                  d      r|r |S ||k(  }@|r|j                  d      sd|vrX|j	                  dd      \  }}	t        |	      ||j                         <    |S )z1Extract simple key/value pairs from a TOML table.r   r   Fr   r   r   r   r   r   r   r   r   )
r(   r   resultr   r   insider   r   r   	raw_values
             r   _extract_toml_tabler   {  s     "FOOE
|1%MF 
;::<s#(9(9#(> M .F,,S1S5H!Q/Y/	:syy{
; Mr!   c                ,   | j                         D ]  }|j                         }|j                  d      r|j                  d      r y|j                  d      sd|vrM|j	                  dd      \  }}|j                         |k(  svt        |      c S  y)z?Read a simple top-level TOML assignment before the first table.r   r   r   r   r   Nr   )r(   r   r   r   current_keyr   s         r   _extract_top_level_toml_valuer     s    ! 0::<s#(9(9#(>  s#s(':!)Q!7Y#%$Y//0 r!   c                    | j                  dd       t        j                         syt        t        |       }|dkD  rt        j                  d||       yy)zLPrepare an agent-native skill directory without overwriting existing skills.Tre   Nr   zF[ClawAdapter] migrated %d legacy SkillClaw skill(s) into %s skills dir)rt   _LEGACY_SKILLCLAW_SKILLS_DIRr   _copy_missing_skill_dirsr   r~   )
target_dirr\   migrateds      r   _prepare_external_skills_dirr     sR    TD1'..0'(DjQH!|T	
 r!   c                ,    t        | |t        ddd      S )zDSave the current Hermes config before overwriting it, if it changed.r;   rT   zHermes configr   r   r   r\   )r   _HERMES_BACKUP_DIRconfig_pathr   s     r    _backup_hermes_config_if_changedr     s!    '% r!   c                 $    t        t        dd      S )Nr;   rT   )r   r    r!   r   _latest_hermes_backup_pathr     s    18VDDr!   c                   | j                   j                  dd       d}	 t        j                  dd| j                   d| j                   dd      5 }t        |j                        }t        j                  ||d	d
       |j                  d       |j                          t        j                  |j                                ddd       t        j                  ||        t        j                  d||        ||j%                  d       yy# 1 sw Y   LxY w# t         $ r"}t        j#                  d|| |       Y d}~Hd}~ww xY w# ||j%                  d       w w xY w)z(Atomically write a JSON mapping to disk.Tre   Nrh   rN   ri   Frj   r   indentr   r   ro   rp   rq   )rs   rt   ru   rv   r2   r   rD   dumprw   ry   rz   r{   r|   r}   r   r~   rW   r   r   r   s         r   _write_json_mapping_atomicr     s4   KKdT2 H-((tyyk#
 	& FKK(HIIdF15ALLLLNHHV]]_%	& 	

8T"95$G OOtO,  #	& 	&  WEudTUVVW OOtO,  sB   2D A3D5D DD 	E&E>E EE E"c                   t         dz  }| j                  xs | j                  xs d}| j                  xs d}d| j                   d}t        |        t        |d      }|j                  d      }t        |t              s&t        |t              r|j                         rd|ini }d	|d
<   ||d<   ||d<   ||d<   d|d<   ||d<   t        |t        |             t        ||d       y)z?Auto-configure Hermes to route model traffic through SkillClaw.config.yamlr#   r'   r%   r&   Hermesmodeldefaultcustomproviderbase_urlapi_keyr   api_modeN)_HERMES_HOMErB   rC   rG   rF   _prepare_hermes_skills_dirr_   r   rX   rY   r   r   r   rx   r   )r   r   rI   r  r  r   r   s          r   _configure_hermesr    s    .K$$M(8(8M<MH.;G"3>>"2#6Hs#k84DHHWEeT"&0&<E"TV E* E*E)E)E*DM$[2G2MN{D(;r!   c           	        t         dz  }| j                  xs | j                  xs d}d| j                   d}| j                  xs d}t        t        t        | dd      xs t                    j                         }t        |d      }t        |t              r|j                  d	      ni }t        |t              st        |t              r|rd
|ini }t        |j                  dd      xs d      }t        |j                  dd      xs d      }	t        |j                  d
d      xs d      }
t        |j                  dd      xs d      }t               }|dk(  xr |	|k(  xr |
|k(  xr ||k(  }t        j!                         }|t        k(  }g }ddg}g }|j#                         s|j%                  d       |s"|j%                  d       |j%                  d       |j!                         s(|j%                  d|        |j%                  d|        |r|j%                  dt         d       |s|j%                  d       i d|sdnddt        |      d|j#                         ddd |d!|d"|xs d#d$|	xs d#d%|
xs d#d&|d't        |      d(|j!                         d)|rd*ndd+t        t              d,|d-|rt        |      nd.d/d0|||d1S )2zCReturn a diagnostic snapshot of the local Hermes integration state.r   r#   r%   r&   r'   
skills_dirr   r   r   r   r   r  r  r   zZThis integration only rewrites Hermes-local config and does not touch other claw adapters.z{Hermes session capture still relies on explicit session headers when available, with proxy-side heuristics as the fallback.z/Hermes config is missing: ~/.hermes/config.yamlzBHermes model routing is not pointing at the local SkillClaw proxy.z=Start SkillClaw once so it can rewrite ~/.hermes/config.yaml.z$Hermes skills directory is missing: z/Create or prepare the Hermes skills directory: z&Legacy SkillClaw skills were found at z?; missing skills are copied into the Hermes library on startup.z\Run SkillClaw once before relying on `skillclaw restore hermes`, so a backup can be created.statusokr   r   config_existsintegration_scopezhermes-onlyexpected_modelexpected_base_urlconfigured_provider(unset)configured_base_urlconfigured_modelproxy_matchexpected_skills_dirskills_dir_existsskills_dir_modezhermes-defaultlegacy_skillclaw_skills_dirlegacy_skillclaw_skills_presentlatest_backup(none)session_boundary_modez8explicit headers if provided, proxy heuristics otherwise)issuesnotes
next_steps)r  rB   rC   rF   rG   r   r   r   _HERMES_SKILLS_DIR
expanduserr_   rX   rY   r   r   r   r   rS   r   )r   r   r  r  expected_api_keyr  r   r   r  r  configured_defaultconfigured_api_keyr   r  legacy_presentuses_default_skills_dirr  r  r  s                      r   inspect_hermes_configr&    sy   .K**Sc.>.>SBSN+CNN+;3?((7Ks73b#A#WEWXYddfk84D!+D$!7DHHWREeT"&0&<E"Beii
B7=2>eii
B7=2>UYYy"5;<UYYy"5;<,.Kx' 	3#44	3.0	3 "22	  288:N15GGFd	BE
 JGHZ[YZ%%'<=P<QRSKL_K`ab45Q4R SM M	
 j	
f$)s;' 	++- 	]	
 	. 	. 	2?i 	2?i 	.;) 	{ 	s#67 	0779 	/F+H 	&s+G'H 	*>  	[[)h!" 	 ![#$  ) r!   c                   | t        |       j                         n	t               }||j                         st	        d      |j                  d      }t        dz  }t        ||d       t        |      t        |      dS )zDRestore ~/.hermes/config.yaml from the latest or a specified backup.zNo Hermes backup foundrN   rO   r   zHermes config restoresourcetarget)	r   r   r   rS   FileNotFoundErrorrV   r  r   r   r   r)  r(   r*  s       r   restore_hermes_configr-  >  sv    /:/FT+))+LfLhF~V]]_ 899W-DM)Fvt%<=&kS[99r!   c           	     V   t        t        t        | dd      xs t                    j	                         }|j                  dd       |t        k7  rt        j                  d|       yt        j                         syt        t        |      }|dkD  rt        j                  d|       yy)	zGPrepare the Hermes-local skill directory without touching other agents.r  r   Tre   z/[ClawAdapter] Hermes uses custom skills dir: %sNr   zJ[ClawAdapter] migrated %d legacy SkillClaw skill(s) into Hermes skills dir)r   r   r   r  r   rt   r   r~   r   r   r   )r   r   r   s      r   r  r  J  s    c'#|R8N<NOP[[]JTD1''=	
 	'..0'(DjQH!|X	
 r!   c                   d}t        | j                               D ]i  }|j                         s|dz  }|j                         s*||j                  z  }|dz  }|j                         rOt        j                  ||       |dz  }k |S )zECopy only skill folders that do not already exist in the destination.r   zSKILL.mdr   )r   iterdirr   is_filer2   rS   shutilcopytree)src_rootdst_rootcopiedentrysrc_skill_mddst_dirdst_skill_mds          r   r   r   a  s    F((*+ ||~z)##%UZZ'+ w'! Mr!   c                ,    t        | |t        ddd      S )Nr;   tomlCodex configr   )r   _CODEX_BACKUP_DIRr   s     r   _backup_codex_config_if_changedr?  x  s!    '$ r!   c                 $    t        t        dd      S )Nr;   r<  )r   r>  r   r!   r   _latest_codex_backup_pathrA    s    0(FCCr!   c                h    dddt        |        ddt        |       g}dj                  |      dz   S )Nz[model_providers.skillclaw]zname = "SkillClaw"zbase_url = zwire_api = "responses"zexperimental_bearer_token = r   r   r   )r  r  r   s      r   _build_codex_provider_blockrD    sJ    %
(234 
&'9''B&CDE 99Ud""r!   c                J    dt        |        dg}dj                  |      dz   S )Nzmodel = zmodel_provider = "skillclaw"r   rC  )rI   r   s     r   _build_codex_profile_blockrF    s3    
%h/01&E 99Ud""r!   c                   | j                   xs | j                  xs d}| j                  xs d}d| j                   d}t        }t
        }t        t        d       d}|j                         r	 |j                  d      }|}t        t        |d      xs d      dk(  rt        |ddh      }t!        |d      j#                         dz   }t!        |d      j#                         dz   }t%        |      dz   t'        ||      z   }	t)        ||       t+        ||d       t+        ||	d       y
# t        $ r!}t        j                  d	||       Y d
}~d
}~ww xY w)zRegister SkillClaw as an opt-in Codex profile.

    Do not change Codex's global ``model`` / ``model_provider`` defaults.
    Users opt in explicitly with ``codex --profile skillclaw``.
    r#   r'   r%   r&   Codexr   rN   rO   0[ClawAdapter] Failed to read Codex config %s: %sNmodel_providerr   model_providers.skillclawz

zprofiles.skillclawr   r=  zCodex SkillClaw profile config)rB   rC   rG   rF   _CODEX_CONFIG_PATH_CODEX_PROFILE_CONFIG_PATHr   _CODEX_SKILLS_DIRrS   rV   rW   r   r   r   r   r   r   r   rF  rD  r?  r   )
r   rI   r  r  r   profile_config_pathexisting_textr^   updatedprofile_texts
             r   _configure_codexrS    sY    $$M(8(8M<MH.;G"3>>"2#6H$K4 !2G<M	_'1171CM G
(2BCIrJkY-gAQ7RS *EFMMORXXG *>?FFH6QG-h7$>A\]egnAooL#K9{G^<*L:Z[  	_NNM{\]^^	_s   .D( (	E1EEc           	        t         }t        }| j                  xs | j                  xs d}d| j                   d}| j
                  xs d}t        }t        t        t        | dd      xs |            j                         }d}|j                         r	 |j                  d      }d}
|j                         r	 |j                  d      }
t        t!        |d      xs d      }t        t!        |d      xs d      }t#        |
d      }t        |j%                  d      xs d      }t        |j%                  d      xs d      }t        |j%                  d      xs d      }t        t!        |
d      xs d      }t        t!        |
d      xs d      }||k(  xr |dk(  xr ||k(  xr |dk(  xr ||k(  }t'               }||k(  }g }g d}g }|j                         s|j)                  d       |j                         s|j)                  d       |s"|j)                  d       |j)                  d       |dk(  r"|j)                  d       |j)                  d       |j+                         s(|j)                  d|        |j)                  d|        |s-|j)                  d| d| d       |j)                  d| d        |s|j)                  d!       i d"|sd#nd$d%t        |      d&|j                         d'd(d)|d*|xs d+d,dd-|xs d+d.|xs d+d/|d0|xs d+d1|xs d+d2|d3t        |      d4|j+                         d5|rd6nd7d8t        |      |xs d+|rt        |      nd9d:|||d;S # t        $ r"}	t        j                  d	||	       Y d
}	~	d
}	~	ww xY w# t        $ r"}	t        j                  d||	       Y d
}	~	d
}	~	ww xY w)<zBReturn a diagnostic snapshot of the local Codex integration state.r#   r%   r&   r'   r  r   rN   rO   rI  Nz8[ClawAdapter] Failed to read Codex profile config %s: %sr   rJ  rK  r  wire_apiexperimental_bearer_token	responses)z>Codex can opt into SkillClaw with `codex --profile skillclaw`.zVSkillClaw registers a Codex profile and does not change Codex's global model defaults.zrCodex session boundaries fall back to proxy-side heuristics because Codex does not send SkillClaw session headers.z-Codex config is missing: ~/.codex/config.tomlzICodex SkillClaw profile config is missing: ~/.codex/skillclaw.config.tomlzPCodex SkillClaw profile is missing or not pointing at the local SkillClaw proxy.z^Start SkillClaw once with `claw_type=codex` so it can register ~/.codex/skillclaw.config.toml.z\Codex global model_provider still points at SkillClaw; normal Codex runs may be intercepted.zQRemove top-level `model_provider = "skillclaw"` or run `skillclaw restore codex`.z#Codex skills directory is missing: z.Create or prepare the Codex skills directory: ,SkillClaw is configured to evolve skills in z, but Codex reads skills from ri   Set `skills.dir` to z" when using the Codex integration.z[Run SkillClaw once before relying on `skillclaw restore codex`, so a backup can be created.r	  r
  r   r   r  r  zcodex-profile-onlyr  r  r  expected_profileconfigured_profile_modelconfigured_profile_providerr  r  r  r  r  r  r  zcodex-defaultr   configured_skillclaw_skills_dirr  proxy heuristics)configured_wire_apir  r  r  r  r  )rL  rM  rB   rC   rF   rG   rN  r   r   r   r   rS   rV   rW   r   r   r   r   r   rA  r   r   )r   r   rO  r  r  r!  r  r]  r(   r^   rR  r  r  provider_cfgr  r_  configured_tokenr[  r\  r  r   skills_dir_matchr  r  r  s                            r   inspect_codex_configrc    s   $K4**Sc.>.>SBSN+CNN+;3?((7K+&*GCr*A.AB'jl $ D	_(('(:D L!!#	o.88'8JL 8wGM2N;DBRSYWYZ&|5PQLl..z:@bAl..z:@bA<++,GHNBO"#@w#W#][]^"%&CLRb&c&igi"j 	!N2 	1';6	1#44	1  ;.	1  00  ,-K6:MMFE JEF%%'abhil	
 k)tumn%%';<O;PQRJK^J_`a:;Z:[ \++>*?qB	
 	01D0EEghiwxf$)s;' 	++- 	1	
 	. 	,9	 	K 	#$<$I	 	&'B'Oi 	. 	2?i 	2?i 	{ 	s#67 	0779  	.>?H!" 	*3/N+O#$  3?i-8[)h!3 / {  	_NNM{\]^^	_  	oNNUWjlmnn	os0   M7 :N% 7	N" NN"%	O.OOc                f   | t        |       j                         n	t               }||j                         st	        d      |j                  d      }t        }t        ||d       t        }d}|j                         r|j                          d}t        |      t        |      t        |      dS )zCRestore ~/.codex/config.toml from the latest or a specified backup.zNo Codex backup foundrN   rO   zCodex config restoreFT)r)  r*  removed_profile)r   r   rA  rS   r+  rV   rL  r   rM  r   r   )r   r)  r(   r*  profile_targetre  s         r   restore_codex_configrg  "  s    /:/FT+))+LeLgF~V]]_ 788W-DFvt%;</NO&kS[SQ`Mabbr!   c                ,    t        | |t        ddd      S )NsettingsrD   Claude Code settingsr   )r   _CLAUDE_BACKUP_DIR)settings_pathr   s     r   "_backup_claude_settings_if_changedrm  8  s!    '%$ r!   c                 $    t        t        dd      S )Nri  rD   )r   rk  r   r!   r   _latest_claude_backup_pathro  C  s    1:vFFr!   c                R   t         }| j                  xs d}d| j                   }t        t        d       t        |d      }|j                  d      }t        |t              si }||d<   ||d<   ||d<   t        j                  |dd	      d
z   }t        ||       t        ||d       y)z6Auto-configure Claude Code to use the SkillClaw proxy.r'   r%   Claude CodeenvANTHROPIC_BASE_URLANTHROPIC_AUTH_TOKENr   Fr   r   rj  N)_CLAUDE_SETTINGS_PATHrG   rF   r   _CLAUDE_SKILLS_DIRrc   r   rX   rY   rD   rE   rm  r   )r   rl  r  r  r   rr  r   s          r   _configure_clauderw  G  s    )M.;G"3>>"23H !3]Cm];D
((5/Cc4  (C")CDKzz$qu=DH&}h?}h0FGr!   c           	        t         }d| j                   }| j                  xs d}t        }t	        t        t        | dd      xs |            j                         }t        |d      }t        |j                  d      t              r|j                  d      ni }t        |j                  dd      xs d      }t        |j                  dd      xs d      }	t        |j                  d	d      xs d      }
||k(  xr |	|k(  }t               }||k(  }g }d
dg}g }|j                         s|j                  d       |s"|j                  d       |j                  d       |j                         s(|j                  d|        |j                  d|        |s-|j                  d| d| d       |j                  d| d       |s|j                  d       i d|sdnddt        |      d|j                         ddd|
xs dd |d!|xs dd"d#d$|d%t        |      d&|j                         d'|rd(nd)d*t        |      d+|rt        |      nd,d-d.d/|d0|d1|iS )2zHReturn a diagnostic snapshot of the local Claude Code integration state.r%   r'   r  r   rq  rr  rs  rt  r   znClaude Code uses SkillClaw through `ANTHROPIC_BASE_URL` and `ANTHROPIC_AUTH_TOKEN` in ~/.claude/settings.json.z~Claude Code session boundaries fall back to proxy-side heuristics because Claude Code does not send SkillClaw session headers.z9Claude Code settings are missing: ~/.claude/settings.jsonz9Claude Code is not pointing at the local SkillClaw proxy.zWStart SkillClaw once with `claw_type=claude` so it can rewrite ~/.claude/settings.json.z)Claude Code skills directory is missing: z4Create or prepare the Claude Code skills directory: rX  z$, but Claude Code reads skills from ri   rY  z( when using the Claude Code integration.z\Run SkillClaw once before relying on `skillclaw restore claude`, so a backup can be created.r	  r
  r   r   r  r  zclaude-onlyr  r  r  r  r  zanthropic-envr  r  r  r  zclaude-defaultr   r]  r  r  r  r^  r  r  r  )ru  rF   rG   rv  r   r   r   r   rc   rX   r   rY   ro  rS   r   r   )r   rl  r  r!  r  r]  r   rr  r  ra  r  r  r   rb  r  r  r  s                    r   inspect_claude_configry  [  s   )M+CNN+;<((7K,&*GCr*A.AB'jl $ m];D'>$((5/BCcgg&:B?E2F377#92>D"E488GR06B7%)::c?OSc?cK,.K6:MMF	>	HE J!QRQRst%%'ABUAVWXPQdPefg:;Z:[ \11D0EQH	
 	01D0EEmnoj	
f$)s=) 	--/ 	]	
 	,9	 	. 	2?i 	 	{ 	s#67 	0779 	/?+X 	*3/N+O 	[[)h 	 !3  	&!" 	#$ 	j% r!   c                    | t        |       j                         n	t               }||j                         st	        d      |j                  d      }t        }t        ||d       t        |      t        |      dS )zFRestore ~/.claude/settings.json from the latest or a specified backup.zNo Claude Code backup foundrN   rO   zClaude Code settings restorer(  )	r   r   ro  rS   r+  rV   ru  r   r   r,  s       r   restore_claude_configr{    sq    /:/FT+))+LfLhF~V]]_ =>>W-D"Fvt%CD&kS[99r!   c                ,    t        | |t        ddd      S )Nr   rD   zOpenCode configr   )r   _OPENCODE_BACKUP_DIRr   s     r   "_backup_opencode_config_if_changedr~    s!    '' r!   c                 $    t        t        dd      S )Nr   rD   )r   r}  r   r!   r   _latest_opencode_backup_pathr    s    3ZHHr!   c           	         t        t        t        | dd      xs t                    j	                         }t        |d       y )Nr  r   OpenCode)r   r   r   _OPENCODE_SKILLS_DIRr   r   )r   r   s     r   _prepare_opencode_skills_dirr    s3    c'#|R8P<PQR]]_J Z8r!   c                   t         }| j                  xs | j                  xs d}| j                  xs d}d| j                   d}t        |        t        |d      }|j                  d      }t        |t              si }||d<   dd||d	|||d
dgddddddddid|d<   d| |d<   t        j                  |dd
      dz   }t        ||       t        ||d       y)z3Auto-configure OpenCode to use the SkillClaw proxy.r#   r'   r%   r&   r  r   r$   	SkillClaw)r9   baseURLFr(   r   r)   r.   r/   r0   )r7   r2   optionsr:   r=   r   r   r   r   N)_OPENCODE_CONFIG_PATHrB   rC   rG   rF   r  rc   r   rX   rY   rD   rE   r~  r   )r   r   rI   r  r  r   provider_blockr   s           r   _configure_opencoder    s   'K$$M(8(8M<MH.;G"3>>"2#6H %k:6DXXj)Nnd+)Z $

  " "#qqPQR!&!

#N;( !
+DMzz$qu=DH&{H={D*=r!   c           	     v   t         }| j                  xs | j                  xs d}d| j                   d}t	        t        t        | dd      xs t                    j                         }t        |d      }t        |t              r|j                  d      ni }t        |t              si }|j                  d      }t        |t              si }|j                  d	      }t        |t              si }t        |j                  d
d      xs d      }	t        |j                  dd      xs d      }
t        |j                  dd      xs d      }t        |j                  dd      xs d      }|dk(  xr |	|k(  xr |d| k(  }t               }|t        k(  }g }ddg}g }|j                         s|j                  d       |s"|j                  d       |j                  d       |j!                         s(|j                  d|        |j                  d|        |s|j                  d       i d|sdnddt        |      d|j                         ddd|d |d!|xs d"d#|	xs d"d$|xs d"d%|
rd&nd"d'|d(t        |      d)|j!                         d*|rd+nd,d-|rt        |      nd.d/d0d1|||d2S )3zEReturn a diagnostic snapshot of the local OpenCode integration state.r#   r%   r&   r  r   r  r   r'   r  r  r9   r   r7   r$   r=   z\OpenCode uses SkillClaw through a custom provider block in ~/.config/opencode/opencode.json.zOpenCode session capture falls back to proxy-side heuristics because OpenCode does not send explicit SkillClaw session headers.z<OpenCode config is missing: ~/.config/opencode/opencode.jsonzDOpenCode model routing is not pointing at the local SkillClaw proxy.zbStart SkillClaw once with `claw_type=opencode` so it can rewrite ~/.config/opencode/opencode.json.z&OpenCode skills directory is missing: z1Create or prepare the OpenCode skills directory: z^Run SkillClaw once before relying on `skillclaw restore opencode`, so a backup can be created.r	  r
  r   r   r  r  zopencode-onlyr  r  configured_apir  r  r  r#  z
(obscured)r  r  r  r  zopencode-defaultr   r  r  r  r^  r  )r  r  )r  rB   rC   rF   r   r   r   r  r   rc   rX   rY   r   r  rS   r   r   )r   r   r  r  r  r   r  skillclaw_blockskillclaw_optionsr  r#  r  r  r  r   r%  r  r  r  s                      r   inspect_opencode_configr    s^   'K**Sc.>.>SBSN+CNN+;3?s73b#A#YEYZ[ffhk:6D-7d-CTXXj)Nnd+$((5Oot,'++I6'./33IrBHbI.228R@FBG488GR06B7,,UB7=2>N 	.. 	>#44	>*^,< ==  /0K15IIFf	NE
 JTU\]p	
 %%'>?R>STUMNaMbcdl	
f$)s;' 	++- 	_	
 	. 	. 	.5I 	2?i 	,9	 	.@li 	{ 	s#67 	0779 	1H-h 	[[)h  	 !3!" 	&#$  ' r!   c                    | t        |       j                         n	t               }||j                         st	        d      |j                  d      }t        }t        ||d       t        |      t        |      dS )zORestore ~/.config/opencode/opencode.json from the latest or a specified backup.zNo OpenCode backup foundrN   rO   zOpenCode config restorer(  )	r   r   r  rS   r+  rV   r  r   r   r,  s       r   restore_opencode_configr  >  sq    /:/FT+))+LhLjF~V]]_ :;;W-D"Fvt%>?&kS[99r!   c                b    | t         j                  v rt        t         j                  |          S |S )zLook up a QwenPaw env var.)rz   environr   )r   r   s     r   _get_qwenpaw_envr  O  s&    
bjj2::c?##Nr!   c                     t        t        dd            j                         j                         } t        t        d|  d            j                         j                         }| |fS )z+Resolve QwenPaw working/secret directories.QWENPAW_WORKING_DIRz
~/.qwenpawQWENPAW_SECRET_DIRz.secret)r   r  r   resolve)working_dir
secret_dirs     r   _resolve_qwenpaw_dirsr  V  sj     	2LA	
 
	  	1k]'3JK	
 
	  
""r!   c                T   g }t        | t              r2| D ]-  }t        |t              s|j                  t        |             / |D ]J  }t	        |j                  dd            j                         |k(  s0|j                  d      xs ||d<   |c S  |j                  ||d       |S )z7Ensure a model list contains the SkillClaw proxy model.r1   r   r2   )r1   r2   )rX   listrY   r   r   r   r   )r:   rI   
normalizeditemr   s        r   _upsert_model_infor  i  s    *,J&$ 	.D$%!!$t*-	.  uyyr"#))+x7!IIf-9E&M
 Xx89r!   c                T   t               \  }}|dz  }|dz  dz  dz  }|dz  dz  }| j                  xs | j                  xs d}| j                  xs d}d| j                   d	}t        |d
      }	t        |	j                  d      t              si |	d<   d|||d|	d   d<   t        ||	d
       t        |d      }
d|
d<   d|
d<   t        |
j                  d      xs d      |
d<   ||
d<   ||
d<   t        |
j                  d      xs d      |
d<   d|
d<   d|
d<   d|
d<   d|
d<   t        |
j                  d d            |
d <   t        |
j                  d!d            |
d!<   t        |
j                  d"      t              r|
d"   ni |
d"<   t        |
j                  d#      t              r|
d#   ni |
d#<   t        |
j                  d      t              r|
d   ng |
d<   t        |
j                  d$      |      |
d$<   t        ||
d       d|d%}t        ||d&       t        d'g d(gd)       y*)+a  Auto-configure QwenPaw to use the SkillClaw proxy.

    QwenPaw stores model provider state under ``<secret>/providers`` while
    its app config lives in ``<working>/config.json``. Update both shapes so
    SkillClaw can point QwenPaw at the local proxy in one step.
    config.json	providersbuiltinzqwenpaw-local.jsonzactive_model.jsonr#   r'   r%   r&   QwenPawr:   openai_compatibler   r   r  r  r   zQwenPaw providerzqwenpaw-localr1   zQwenPaw Localr2   
chat_modelOpenAIChatModelr  r  api_key_prefixr   Tis_localF
freeze_urlrequire_api_key	is_customsupport_model_discoverysupport_connection_checkgenerate_kwargsmetaextra_models)provider_idr   zQwenPaw active modelqwenpaw)r  daemonrA   ignore_missingN)r  rB   rC   rG   rF   rc   rX   r   rY   r   r   r   r  r  rH   )r   r  r  r   provider_pathactive_model_pathrI   r  r  config_dataprovider_dataactive_models               r   _configure_qwenpawr  z  s    45K-K,y8;OOM"[03FF$$M(8(8M<MH.;G"3>>"2#6H %[)<Kkooh/6 "H'	(K)$ {KC '}6HIM)M$+M&"%,'<+<#M, !)M*&M)&)-*;*;<L*M*SQS&TM"# $M*"'M,',M#$!&M+/33U;0M+, 154d;1M,- -7}7H7HIZ7[]a,b'(hj #$ 6@@Q@QRX@Y[_5`M&1fhM&9CMDUDUV^D_ae9fmH5lnM($6.)%M.! }m=OP#2XFL0,@VW )>?PTUr!   c                    t        j                         dz  dz  }| j                  xs | j                  xs d}dd| j                   d|| j
                  xs dd}t        ||       t        d	g d
gd       y)a   Auto-configure IronClaw to use the SkillClaw proxy.

    Patches ~/.ironclaw/.env to set LLM_BACKEND=openai_compatible and
    point LLM_BASE_URL at the SkillClaw proxy port.  Triggers a service
    restart so the new env vars take effect immediately.
    z	.ironclaw.envr#   r  r%   r&   r'   )LLM_BACKENDLLM_BASE_URL	LLM_MODELLLM_API_KEYironclaw)r  servicerA   Tr  N)r   homerB   rC   rF   rG   _patch_dotenvrH   )r   env_pathrI   new_varss       r   _configure_ironclawr    s     yy{[(61H$$M(8(8M<MH ++CNN+;3?((7K	H (H% 	+,r!   c                   g }| j                         r!	 | j                  d      j                         }t               }g }|D ]  }|j                         }|j                  d      sd|vr|j                  |       :|j                  dd      d   j                         }	|	|v r+|j                  |	 d||	           |j                  |	       |j                  |        |j                         D ]   \  }	}
|	|vs|j                  |	 d|
        " 	 | j                  j                  d	d	
       | j                  dj!                  |      dz   d       t        j#                  d||        y# t        $ r"}t        j                  d| |       Y d}~ad}~ww xY w# t        $ r!}t        j%                  d| |       Y d}~yd}~ww xY w)zEUpdate or insert KEY=VALUE lines in a .env file (preserves comments).rN   rO   #[ClawAdapter] Failed to read %s: %sNr   r   r   r   Tre   r   z![ClawAdapter] %s .env updated: %s$[ClawAdapter] Failed to write %s: %srS   rV   r   rW   r   r   r<   r   r   r   r   r   itemsrs   rt   r   r   r~   r   )r  r  r\   r   r^   rQ  	new_linesr   r   r   vals              r   r  r    s   E	O&&&8CCEE GI 
#::<s#s(':T"nnS!$Q'--/(?uAhsm_56KKT"
# NN$ -SguAcU^,-JdT:DIIi047'J7I5  	ONN@(ANN	O6  J;XqIIJs0    E/ AF /	F8FF	G&GGc                >   t        j                         dz  dz  }| j                  xs | j                  xs d}i }|j	                         r&	 t        j                  |j                  d            }dd	| | j                  xs dd
| j                   dd}|j                  d      }t        |t              sg }|D cg c]  }|j                  d      dk7  s| }}|j!                  |       ||d<   t        |j                  d      t"              si |d<   t        |d   j                  d      t"              si |d   d<   d|d   d   d<   	 |j$                  j'                  dd       |j)                  t        j*                  |dd      dz   d       t        j-                  d|       t1        dg dgd       y# t        $ r"}t        j                  d||       Y d}~td}~ww xY wc c}w # t        $ r!}t        j/                  d||       Y d}~yd}~ww xY w)zAuto-configure PicoClaw to use the SkillClaw proxy.

    Injects a ``skillclaw`` entry into the ``model_list`` array in
    ``~/.picoclaw/config.json`` and sets it as the default model via
    ``agents.defaults.model_name``.
    z	.picoclawr  r#   rN   rO   r  Nr'   zopenai/r%   r&   )
model_namer   r  api_base
model_listr  agentsdefaultsTre   r   Fr   r   z)[ClawAdapter] PicoClaw config updated: %sr  picoclaw)r  r@   rA   r  )r   r  rB   rC   rS   rD   rb   rV   rW   r   r   rG   rF   r   rX   r  r   rY   rs   rt   r   rE   r~   r   rH   )r   r   rI   r   r^   skillclaw_entryr  ms           r   _configure_picoclawr    s    ))++m;K$$M(8(8M<MHD	R::k33W3EFD "8*%$$3''7s;	O ,'Jj$'
'N155+>++M!NJNo&#D dhhx($/Xd8n((4d;%'Xz"/:DN:|,	   =JJtAE:TA 	 	
 	?M
 	+,M  	RNN@+qQQ	R  O$  ;[!Ls=   %F? >G-G-AG2 ?	G*G%%G*2	H;HHc                    t        j                         dz  dz  }| j                  xs | j                  xs d}d|| j                  xs dd| j
                   dd}t        ||       t        d	g d
gd       y)a  Auto-configure ZeroClaw to use the SkillClaw proxy.

    Patches ``~/.zeroclaw/config.toml`` to set the provider to
    ``openai-compatible`` pointing at the SkillClaw proxy.  Falls back to
    a simple line-based patcher to avoid a hard dependency on a TOML
    write library.
    z	.zeroclawr   r#   zopenai-compatibler'   r%   r&   r  zeroclaw)r  r  rA   Tr  N)r   r  rB   rC   rG   rF   _patch_tomlrH   )r   r   rI   r  s       r   _configure_zeroclawr  E  s     ))++m;K$$M(8(8M<MH ($$3''7s;	H X&	+,r!   c                   g }| j                         r!	 | j                  d      j                         }t               }g }|D ]  }|j                         }|j                  d      sd|vr|j                  |       :|j                  dd      d   j                         }||v r,|j                  | d	||    d
       |j                  |       |j                  |        |j                         D ]!  \  }}	||vs|j                  | d	|	 d
       # 	 | j                  j                  dd       | j                  dj!                  |      dz   d       t        j#                  d|        y# t        $ r"}t        j                  d| |       Y d}~bd}~ww xY w# t        $ r!}t        j%                  d| |       Y d}~yd}~ww xY w)a  Update or insert key = "value" lines in a TOML file.

    This is a minimal line-based patcher (no full TOML parser required).
    It handles simple ``key = "value"`` pairs at the top level.  Existing
    keys are updated in-place; missing keys are appended.
    rN   rO   r  Nr   r   r   r   z = "r   Tre   r   z.[ClawAdapter] ZeroClaw config.toml updated: %sr  r  )
	toml_pathr  r   r^   rQ  r  r   r   r   r  s
             r   r  r  `  s    E	P'''9DDFE GI 
#::<s#s(':T"nnS!$Q'--/(?uD#q9:KKT"
# NN$ 1SguDQ/01Ktd;TYYy1D87KDiP3  	PNN@)QOO	P4  K;YJJKs0    E0 AF 0	F9FF	G'GGc           	        t               }|0t        j                  d| j                  | j                  xs d       yd| j                   | j                  xs dd}t        ||d       t        j                         dk(  r-d	dl} |j                         }t        d
dddd| dggd       yt        d
g dgd       y)a  Auto-configure NanoClaw to route API calls through SkillClaw proxy.

    NanoClaw uses an Anthropic-compatible credential proxy (credential-proxy.ts)
    that forwards container API calls to ANTHROPIC_BASE_URL.  SkillClaw exposes
    a /v1/messages Anthropic-compatible endpoint, so we point ANTHROPIC_BASE_URL
    at the SkillClaw proxy and restart the service.

    Config file location is discovered in priority order:
      1. WorkingDirectory from ~/Library/LaunchAgents/com.nanoclaw.plist (macOS)
      2. WorkingDirectory from ~/.config/systemd/user/nanoclaw.service (Linux)
      3. Common install locations: ~/nanoclaw, ~/code/nanoclaw, ~/.nanoclaw
    Nu   [ClawAdapter] Could not locate nanoclaw .env — set ANTHROPIC_BASE_URL=http://127.0.0.1:%d and ANTHROPIC_API_KEY=%s in nanoclaw's .env manually.r'   r%   )rs  ANTHROPIC_API_KEYNanoClaw)r\   Darwinr   nanoclaw	launchctl	kickstartz-kzgui/z/com.nanoclawTr  )	systemctlz--userrA   r  )_find_nanoclaw_envr   r   rF   rG   r  platformsystemrz   getuidrH   )r   r  r  rz   uids        r   _configure_nanoclawr    s     "#H@ NN,	
 	 !2#..1AB ..=+H (HJ7 H$biik;SE.GHI	
 	;<	
r!   c                    t        j                         } | dz  dz  dz  }|j                         rh	 ddl}t	        |d      5 }|j                  |      }ddd       j                  d      }|r*t        |      dz  }|j                  j                         r|S | d
z  dz  dz  dz  }|j                         r	 |j                  d      j                         D ]s  }	|	j                         }
|
j                  d      s%|
j!                  dd      d   j                         }t        |      dz  }|j                  j                         sq|c S  	 | dz  dz  | dz  dz  dz  | dz  dz  fD ]0  }|j                         s|j                  j                         s.|c S  y# 1 sw Y   KxY w# t        $ r!}t        j                  d	|       Y d}~6d}~ww xY w# t        $ r }t        j                  d|       Y d}~d}~ww xY w)zDLocate nanoclaw's project-root .env file by probing known locations.LibraryLaunchAgentszcom.nanoclaw.plistr   NrbWorkingDirectoryr  z0[ClawAdapter] failed to parse nanoclaw plist: %sr   systemduserznanoclaw.servicerN   rO   zWorkingDirectory=r   r   z7[ClawAdapter] failed to parse nanoclaw service file: %sr  codez	.nanoclaw)r   r  rS   plistlibopenloadr   rs   r   rW   r   debugrV   r   r   r   r   )r  
plist_pathr  fplistwork_dir	candidater^   service_pathr   r   s              r   r  r    s   99;D 	!N25IIJ	Pj$' )1 a()yy!34H NV3	##**,$$
 )#i/&8;MML		W$...@KKM )::<&&':;'~~c15a8>>@H $X 7I ''..0(() 	zF"v
"V+{V# 	
 !1!1!8!8!: C) )  	PLLKQOO	P  	WLLRTUVV	Ws\   F) FAF) 7AG <AG G G F&!F) )	G2GG	G?G::G?c                   | j                   xs | j                  xs d}| j                  xs d}d| j                   d}dddddd	d
dd| dd| g}	 t	        j
                  |ddd      }|j                  dk7  r||j                  xs d}d|v sd|j                         v r1t        j                  d       t        ddddddd| dd| gg       n:t        j                  d|j                                yt        j                  d       t        ddddd dd!|gg       t!        |||       t        dg d"gd#       y# t        $ r t        j                  d       Y yt        $ r }t        j                  d|       Y d}~yd}~ww xY w)$a  Auto-configure NemoClaw to route inference through SkillClaw proxy.

    NemoClaw runs OpenClaw inside an OpenShell sandbox with a pluggable
    inference provider.  We register (or update) a 'skillclaw' OpenAI-compatible
    provider via the openshell CLI and set it as the active inference route.
    The config is also persisted to ~/.nemoclaw/config.json so that
    `openclaw nemoclaw status` reflects the current state.
    r#   r'   r%   r&   	openshellr   createz--namez--typeopenaiz--credentialzOPENAI_API_KEY=z--configzOPENAI_BASE_URL=T   capture_outputr(   timeoutr   r   AlreadyExistszalready existsu@   [ClawAdapter] openshell provider 'skillclaw' exists — updatingnemoclawupdatez2[ClawAdapter] openshell provider create failed: %sNu8   [ClawAdapter] openshell provider create skillclaw → okuL   [ClawAdapter] 'openshell' not found in PATH — configure NemoClaw manually.z1[ClawAdapter] openshell provider create error: %s	inferencer<   z
--providerz--modelr?   r  )rB   rC   rG   rF   
subprocessrun
returncodestderrlowerr   r~   rH   r   r   r+  rW   _write_nemoclaw_config)r   rI   r  r  
create_cmdr   r  r^   s           r   _configure_nemoclawr    s    $$M(8(8M<MH.;G"3>>"2#6H 	
'#
8*%J'	
 !]](bF&(,<,N^_ (&$'*-gY7&.xj9	  HLLN KKRS  
	
  8Xw7 *ABSWX7  ef JANs%   B#D? 7D? ?FF'FFc                   t        j                         dz  dz  }d| d|ddt        j                  j                         j	                         dz   d}	 |j
                  j                  d	d	
       |j                  t        j                  |dd      dz   d       t        j                  d|       y# t        $ r!}t        j                  d||       Y d}~yd}~ww xY w)zIWrite ~/.nemoclaw/config.json to record SkillClaw as the active provider.z	.nemoclawr  r   NncpOPENAI_API_KEYZ)endpointTypeendpointUrl
ncpPartnerr   profilecredentialEnvonboardedAtTre   r   Fr   r   rN   rO   z)[ClawAdapter] NemoClaw config updated: %sr  )r   r  r   utcnow	isoformatrs   rt   r   rD   rE   r   r~   rW   r   )endpoint_urlr   r  r   r   r^   s         r   r  r  L  s    ))++m;K #)((//1;;=CDM   =JJtAE:TA 	 	
 	?M M;[!LLMs   AB3 3	C<CCc                .    t         j                  d       y )Nu<   [ClawAdapter] claw_type=none — skipping auto-configuration)r   r~   )r   s    r   _configure_noner&  h  s    
KKNOr!   )r   r   r   r   r   r  r  r  r  r  r  r   z.dict[str, Callable[['SkillClawConfig'], None]]r   z	list[str]
CLAW_TYPESc           	        |D ]  }	 t        j                  |ddd      }|j                  dk7  r@t        j	                  d| dj                  |      |j                  j                                n(t        j                  ddj                  |d d               y # t        $ r< |rt        j                  d	|d          Y  y t        j	                  d
|d   |        Y  y t        $ r!}t        j	                  d| |       Y d }~d }~ww xY w)NTr  r	  r   z0[ClawAdapter] %s command failed: %s
  stderr: %s u   [ClawAdapter] %s → ok   u>   [ClawAdapter] '%s' not found in PATH — skipping restart stepuU   [ClawAdapter] '%s' not found in PATH — skipping auto-config. Configure %s manually.z"[ClawAdapter] %s command error: %s)r  r  r  r   r   r   r  r   r~   r+  r  rW   )
agent_namerK   r  cmdr   r^   s         r   rH   rH     s   
  P	P^^#	F   A%GHHSMMM'')	 5sxxBQ7HI!P" ! 	TF  kF
  	PNN?QOO	Ps$   BB$DDD&DD)r   'SkillClawConfig'returnNone)r[   r   r\   r   r.  rY   )r[   r   r   rY   r\   r   r.  r/  )r   rY   r.  r   )r[   r   r(   r   r\   r   r.  r/  )r[   r   r   r   r   r   r   r   r   r   r\   r   r.  Path | None)r   r   r   r   r   r   r.  r0  )r   objectr.  r   )r   r   r.  r1  )r(   r   r   dict[str, object]r.  r   )r(   r   r   zset[str]r.  r   )r(   r   r   r   r.  r   )r(   r   r   r   r.  r2  )r(   r   r   r   r.  zobject | None)r   r   r\   r   r.  r/  )r   r   r   r   r.  r0  )r.  r0  )r   r-  r.  r2  )N)r   r0  r.  dict[str, str])r4  r   r5  r   r.  r   )r  r   r  r   r.  r   )rI   r   r.  r   )rl  r   r   r   r.  r0  )r   )r   r   r   r   r.  r   )r.  ztuple[Path, Path])r:   r1  rI   r   r.  zlist[dict[str, object]])IronClaw)r  r   r  r3  r\   r   r.  r/  )r  r   r  r3  r.  r/  )r$  r   r   r   r  r   r.  r/  )F)r+  r   rK   zlist[list[str]]r  r   r.  r/  )f__doc__
__future__r   r   rD   loggingrz   r  r2  r  ru   pathlibr   typingr   r   rT   r;   r   	getLogger__name__r   r  r   r  r  r   _CODEX_HOMErL  rM  rN  r>  _CLAUDE_HOMEru  rv  rk  _OPENCODE_CONFIG_DIRr  r  r}  r    rL   r_   rc   r   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r&  r-  r  r   r?  rA  rD  rF  rS  rc  rg  rm  ro  rw  ry  r{  r~  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r&  r   __annotations__r  r'  rH   r   r!   r   <module>r@     su  * #    	      * '			8	$(tyy{\9HD tyy{Y&!H, TYY[</);hF diikH$ =0 (+BB (* DIIK,.:WD tyy{Y&$6 !H, TYY[</);hF  tyy{Y.; ,> +h6  tyy{\1I=
J *(H,,-4E-2!
!! 	!
 ! ! ! !H,6%-P70+.*
	E-6<2JZ	:
..D##\@ePc,GH(BJ	:"I9
'>TL^	:"#&">VL6"JT8@6&K\-
`+fXYvM8P $#!#####=	9   Y
I ' !$P$P$P $P 
	$Pr!   