
    PL
j_                       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 ddlmZ ddlmZ ddlmZmZ dd	lmZ d
ZdZ ej        dej                  Z ej        dej                  ZdZdZd:dZ d;dZ!d<dZ"d;dZ#d=dZ$d>d!Z%d?d"Z&	 	 	 d@dAd*Z'dBd,Z(dCd/Z)dDd3Z* G d4 d5          Z+ G d6 d7          Z, G d8 d9          Z-dS )Eat  OpenAI-compatible shim that forwards Hermes requests to `copilot --acp`.

This adapter lets Hermes treat the GitHub Copilot ACP server as a chat-style
backend. Each request starts a short-lived ACP session, sends the formatted
conversation as a single prompt, collects text chunks, and converts the result
back into the minimal shape Hermes expects from an OpenAI client.
    )annotationsN)deque)Path)SimpleNamespace)Any)get_read_block_erroris_write_denied)redact_sensitive_textzacp://copilotg      @z&<tool_call>\s*(\{.*?\})\s*</tool_call>zd\{\s*\"id\"\s*:\s*\"[^\"]+\"\s*,\s*\"type\"\s*:\s*\"function\"\s*,\s*\"function\"\s*:\s*\{.*?\}\s*\})z
gh-copilot)zhas been deprecatedzno commands will be executedstderr_textstrreturnboolc                    |                                  t          fdt          D                       sdS t          fdt          D                       S )zHTrue iff stderr looks like the deprecated gh-copilot extension's banner.c              3      K   | ]}|v V  	d S N ).0reqlowers     </home/kuhnn/.hermes/hermes-agent/agent/copilot_acp_client.py	<genexpr>z5_is_gh_copilot_deprecation_message.<locals>.<genexpr>3   s'      ==se|======    Fc              3      K   | ]}|v V  	d S r   r   )r   markerr   s     r   r   z5_is_gh_copilot_deprecation_message.<locals>.<genexpr>5   s'      BB6vBBBBBBr   )r   any_DEPRECATION_REQUIRED_DEPRECATION_MARKERS)r   r   s    @r   "_is_gh_copilot_deprecation_messager   /   se     E===='<===== uBBBB-ABBBBBBr   c                     t          j        dd                                          p(t          j        dd                                          pdS )NHERMES_COPILOT_ACP_COMMAND COPILOT_CLI_PATHcopilot)osgetenvstripr   r   r   _resolve_commandr'   8   sL    
	.3399;; 	9',,2244	r   	list[str]c                     t          j        dd                                          } | sddgS t          j        |           S )NHERMES_COPILOT_ACP_ARGSr!   z--acpz--stdio)r$   r%   r&   shlexsplit)raws    r   _resolve_argsr.   @   sC    
)-r
2
2
8
8
:
:C $##;sr   c                    	 ddl m}   |             }|r|S n# t          $ r Y nw xY wt          j                            dd                                          }|r|S t          j                            d          }|r|dk    r|S 	 ddl	}|
                    t          j                              j                                        }|r|S n# t          $ r Y nw xY wdS )z-Return a stable HOME for child ACP processes.r   )get_subprocess_homeHOMEr!   ~Nz/tmp)hermes_constantsr0   	Exceptionr$   environgetr&   path
expanduserpwdgetpwuidgetuidpw_dir)r0   profile_homehomeexpandedr9   resolveds         r   _resolve_home_dirrA   G   s!   888888**,, 	 	     :>>&"%%++--D w!!#&&H HOO


<<	,,399;; 	O	    6s    
$$AC 
CCdict[str, str]c                 d    t           j                                        } t                      | d<   | S )Nr1   )r$   r5   copyrA   )envs    r   _build_subprocess_envrF   j   s'    
*//

C#%%CKJr   
message_idr   codeintmessagedict[str, Any]c                    d| ||ddS )N2.0)rH   rJ   )jsonrpciderrorr   )rG   rH   rJ   s      r   _jsonrpc_errorrQ   p   s'    
 
  r   c                    d| dddiidS )NrM   outcome	cancelledrN   rO   resultr   )rG   s    r   _permission_deniedrW   {   s)    ;
  r   messageslist[dict[str, Any]]model
str | Nonetoolslist[dict[str, Any]] | Nonetool_choicec           	     h   g d}|r|                     d|            t          |t                    r|r
g }|D ]}t          |t                    s|                    d          pi }t          |t                    sE|                    d          }t          |t
                    r|                                s|                     |                                |                    dd          |                    di           d           |r,|                     d	t          j        |d
          z              |,|                     dt          j        |d
                      g }	| D ]}
t          |
t                    st          |
                    d          pd                                          	                                }|dk    rd}n|dvrd}|
                    d          }t          |          }|sdddddd                    ||                                          }|	                     | d|            |	r+|                     dd                    |	          z              |                     d           d                    d |D                       S )N)z>You are being used as the active ACP agent backend for Hermes.z'Use ACP capabilities to complete tasks.zIMPORTANT: If you take an action with a tool, you MUST output tool calls using <tool_call>{...}</tool_call> blocks with JSON exactly in OpenAI function-call shape.z&If no tool is needed, answer normally.zHermes requested model hint: functionnamedescriptionr!   
parameters)ra   rb   rc   zAvailable tools (OpenAI function schema). When using a tool, emit ONLY <tool_call>{...}</tool_call> with one JSON object containing id/type/function{name,arguments}. arguments must be a JSON string.
Fensure_asciizTool choice hint: roleunknowntool>   usersystem	assistantcontextcontentSystemUser	AssistantToolContext)rj   ri   rk   rh   rl   z:
zConversation transcript:

z

z7Continue the conversation from the latest user request.c              3  j   K   | ].}||                                 |                                 V  /d S r   r&   )r   sections     r   r   z-_format_messages_as_prompt.<locals>.<genexpr>   s<      ^^7'^gmmoo^w}}^^^^^^r   )append
isinstancelistdictr6   r   r&   jsondumpsr   _render_message_contenttitlejoin)rX   rZ   r\   r^   sections
tool_specstfnra   
transcriptrJ   rf   rm   renderedlabels                  r   _format_messages_as_promptr      s	     H  A???@@@% 5 +-
 	 	Aa&& z""(bBb$'' 66&>>DdC(( 

  JJLL#%66-#<#<"$&&r":":      	OOb *Ze<<<=   ZTZRW-X-X-XZZ[[[J 3 3'4(( 	7;;v&&3)44::<<BBDD6>>DD888D++i((*733 	 $ 
 
 #dDJJLL
!
! 	 	U11x112222 R6Z9P9PPQQQOOMNNN;;^^h^^^^^^r   rm   c                   | dS t          | t                    r|                                 S t          | t                    rd| v r6t          |                     d          pd                                          S d| v r^t          |                     d          t                    r6t          |                     d          pd                                          S t          j        | d          S t          | t                    rg }| D ]}t          |t                    r|                    |           -t          |t                    re|                    d          }t          |t                    r;|                                r'|                    |                                           d	                    |                                          S t          |                                           S )Nr!   textrm   Trd   
)
rw   r   r&   ry   r6   rz   r{   rx   rv   r~   )rm   partsitemr   s       r   r|   r|      s   r'3 }}'4   6Ww{{6**0b1177999Jw{{9/E/Es$K$Kw{{9--344::<<<z'5555'4   	( 	/ 	/D$$$ /T""""D$'' /xx''dC(( /TZZ\\ /LL...yy%%'''w<<r   r   !tuple[list[SimpleNamespace], str]c                   t          | t                    r|                                 sg dfS g g }dfd}t                              |           D ]]}|                    d          } ||           |                    |                                |                                f           ^sxt                              |           D ]]}|                    d          } ||           |                    |                                |                                f           ^|s|                                 fS |
                                 g }|D ]^\  }}|r||d	         d         k    r|                    ||f           1|d	         d         t          |d	         d         |          f|d	<   _g }d}	|D ]8\  }}|	|k     r|                    | |	|                    t          |	|          }	9|	t          |           k     r|                    | |	d                     d
                    d |D                                                       }
|
fS )Nr!   raw_jsonr   r   Nonec                   	 t          j        |           }n# t          $ r Y d S w xY wt          |t                    sd S |                    d          }t          |t                    sd S |                    d          }t          |t                    r|                                sd S |                    dd          }t          |t                    st          j        |d          }|                    d          }t          |t                    r|                                sdt                    d	z    }
                    t          ||d dt          |                                |
                               d S )Nr`   ra   	argumentsz{}Frd   rO   	acp_call_   )ra   r   )rO   call_idresponse_item_idtyper`   )rz   loadsr4   rw   ry   r6   r   r&   r{   lenrv   r   )r   objr   fn_namefn_argsr   	extracteds         r   _try_add_tool_callz9_extract_tool_calls_from_text.<locals>._try_add_tool_call   s   	*X&&CC 	 	 	FF	#t$$ 	FWWZ  "d## 	F&&..'3'' 	w}} 	F&&d++'3'' 	>ju===G''$--'3'' 	5w}} 	54#i.."244G!%(gmmooQQQ  	
 	
 	
 	
 	
s    
&&r   r   r   c              3  j   K   | ].}||                                 |                                 V  /d S r   rt   )r   ps     r   r   z0_extract_tool_calls_from_text.<locals>.<genexpr>/  s<      DDaAD!''))D		DDDDDDr   )r   r   r   r   )rw   r   r&   _TOOL_CALL_BLOCK_REfinditergrouprv   startend_TOOL_CALL_JSON_REsortmaxr   r~   )r   consumed_spansr   mr-   mergedr   r   r   cursorcleanedr   s              @r   _extract_tool_calls_from_textr      s   dC   

 2v')I,.N
 
 
 
 
 
< !))$// 4 4ggajj3qwwyy!%%''23333  8#,,T22 	8 	8A''!**Cs###!!17799aeegg"67777 '$**,,&&$&F$ B B
s 	BA..MM5#,'''' *Q-VBZ]C)@)@AF2JJEF " "
sE>>LLfUl+,,,VS!!D		T&'']###iiDD5DDDDDJJLLGgr   	path_textcwdr   c                T   t          |           }|                                st          d          |                                }t          |                                          }	 |                    |           n)# t
          $ r}t          d| d| d          |d }~ww xY w|S )Nz'ACP file-system paths must be absolute.zPath 'z' is outside the session cwd 'z'.)r   is_absolutePermissionErrorresolverelative_to
ValueError)r   r   	candidater@   rootexcs         r   _ensure_path_within_cwdr   4  s    YI  "" IGHHH  ""H99DbT"""" b b bWxWWtWWWXX^aabOs   )A? ?
B%	B  B%c                      e Zd Zd	dZd
dZdS )_ACPChatCompletionsclient'CopilotACPClient'c                    || _         d S r   )_clientselfr   s     r   __init__z_ACPChatCompletions.__init__B  s    r   kwargsr   r   c                &     | j         j        di |S )Nr   )r   _create_chat_completion)r   r   s     r   createz_ACPChatCompletions.createE  s    3t|3==f===r   Nr   r   )r   r   r   r   )__name__
__module____qualname__r   r   r   r   r   r   r   A  s<           > > > > > >r   r   c                      e Zd ZddZdS )_ACPChatNamespacer   r   c                .    t          |          | _        d S r   )r   completionsr   s     r   r   z_ACPChatNamespace.__init__J  s    .v66r   Nr   )r   r   r   r   r   r   r   r   r   I  s(        7 7 7 7 7 7r   r   c            	      \    e Zd ZdZdddddddddd-dZd.dZddddddd/dZd0d#Zd1d,ZdS )2CopilotACPClientz8Minimal OpenAI-client-compatible facade for Copilot ACP.N)api_keybase_urldefault_headersacp_commandacp_argsacp_cwdcommandargsr   r[   r   r   dict[str, str] | Noner   r   list[str] | Noner   r   r   _r   c                  |pd| _         |pt          | _        t          |pi           | _        |p|pt                      | _        t          |p|pt                                | _	        t          t          |pt          j                                                                        | _        t!          |           | _        d| _        d | _        t)          j                    | _        d S )Ncopilot-acpF)r   ACP_MARKER_BASE_URLr   ry   _default_headersr'   _acp_commandrx   r.   	_acp_argsr   r   r$   getcwdr   _acp_cwdr   chat	is_closed_active_process	threadingLock_active_process_lock)
r   r   r   r   r   r   r   r   r   r   s
             r   r   zCopilotACPClient.__init__Q  s     /- 7$7 $_%: ; ;'H7H6F6H6HhA$A-//BBD!7BIKK88@@BBCC%d++	=A$-N$4$4!!!r   r   r   c                <   | j         5  | j        }d | _        d d d            n# 1 swxY w Y   d| _        |d S 	 |                                 |                    d           d S # t
          $ r+ 	 |                                 Y d S # t
          $ r Y Y d S w xY ww xY w)NT   timeout)r   r   r   	terminatewaitr4   kill)r   procs     r   closezCopilotACPClient.closei  s	   & 	( 	('D#'D 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( <F	NNIIaI      	 	 			   	s5   #''*A& &
B1B
BBBB)rZ   rX   r   r\   r^   rZ   rX   r]   r   float | Noner\   r^   c                   t          |pg |||          }t          }n^t          t          t          f          rt	                    }n2fddD             }	d |	D             }
|
rt          |
          nt          }|                     ||          \  }}t          |          \  }}t          dddt          d                    }t          |||pd |pd d 	          }|rd
nd}t          ||          }t          |g||pd          S )N)rZ   r\   r^   c                2    g | ]}t          |d           S r   )getattr)r   attrr   s     r   
<listcomp>z<CopilotACPClient._create_chat_completion.<locals>.<listcomp>  s5        t,,  r   )readwriteconnectpoolr   c                d    g | ]-}t          |t          t          f          t          |          .S r   )rw   rI   float)r   vs     r   r   z<CopilotACPClient._create_chat_completion.<locals>.<listcomp>  s1    UUUQAU|9T9TUaUUUr   )timeout_secondsr   )cached_tokens)prompt_tokenscompletion_tokenstotal_tokensprompt_tokens_details)rm   
tool_calls	reasoningreasoning_contentreasoning_detailsr  stop)rJ   finish_reasonr   )choicesusagerZ   )	r   _DEFAULT_TIMEOUT_SECONDSrw   rI   r   r   _run_promptr   r   )r   rZ   rX   r   r\   r^   r   prompt_text_effective_timeout_candidates_numericresponse_textreasoning_textr  cleaned_textr  assistant_messager  choices      `               r   r   z(CopilotACPClient._create_chat_completionz  s    1N#	
 
 
 ?!9#u.. 
	Y!&w   K  K VU+UUUH2:!XX@X(,(8(8. )9 )
 )
%~
 $A#O#O 
L"1"B"B"B	
 
 
 , !$,,4"
 
 
 )3> ):-XXXH(=
 
 
 	
r   r  r   r  r   tuple[str, str]c                   	 t          j         j        g j        z   t           j        t           j        t           j        dd j        t                                n+# t          $ r}t          d j         d          |d }~ww xY wj	        j
        #                                 t          d          d _         j        5   _        d d d            n# 1 swxY w Y   t          j                    t#          d	          d+fd}d+fd}t%          j        |d          }t%          j        |d          }|                                 |                                 dd d dd, fd}	  |ddddddidddd d!            |d" j        g d#          pi }	t+          |	                    d$          pd%                                          }
|
st          d&          g }g } |d'|
d(|d)gd*||           d%                    |          d%                    |          f                                  S #                                   w xY w)-NTr   )stdinstdoutstderrr   bufsizer   rE   z%Could not start Copilot ACP command 'zQ'. Install GitHub Copilot CLI or set HERMES_COPILOT_ACP_COMMAND/COPILOT_CLI_PATH.z6Copilot ACP process did not expose stdin/stdout pipes.F(   )maxlenr   r   c                     j         d S j         D ]d} 	                     t          j        |                      +# t          $ r-                     d|                     d          i           Y aw xY wd S )Nr-   r   )r  putrz   r   r4   rstrip)lineinboxr   s    r   _stdout_readerz4CopilotACPClient._run_prompt.<locals>._stdout_reader  s    {" : ::IIdj..////  : : :IIudkk$&7&7899999:: :s   '=4A43A4c                 ~    j         d S j         D ]*}                     |                     d                     +d S )Nr   )r  rv   r$  )r%  r   stderr_tails    r   _stderr_readerz4CopilotACPClient._run_prompt.<locals>._stderr_reader  sN    {" 6 6""4;;t#4#455556 6r   )targetdaemonr   )
text_partsreasoning_partsmethodr   paramsrK   r-  r   r.  r   c                  dz  }d|| |d}j                             t          j        |          dz              j                                          t          j                    z   }t          j                    |k     r։                                n	 
                    d          }n# t          j
        $ r Y Uw xY w                    |j        ||          ry|                    d          |k    rd	|v rA|                    d	          pi }t          d
|  d|                    d          p|           |                    d          S d                                                              }	                                5|	r3t!          |	          rt          d|	           t          d|	           t#          d|  d          )Nr   rM   )rN   rO   r/  r0  r   g?r   )processr   r-  r.  rO   rP   zCopilot ACP z	 failed: rJ   rV   a0  Hermes ACP mode requires the NEW GitHub Copilot CLI (github.com/github/copilot-cli), but the binary it just spawned is the deprecated `gh copilot` extension.

Install the new CLI:
  npm install -g @github/copilot
  # then verify with: copilot --help

If `copilot` already resolves to the new CLI but you still see this,
point Hermes at it explicitly:
  export HERMES_COPILOT_ACP_COMMAND=/path/to/new/copilot

Alternative: use the `copilot` provider (no ACP, hits the Copilot API
directly with a Copilot subscription token) via `hermes setup`.

Original error:
z"Copilot ACP process exited early: z.Timed out waiting for Copilot ACP response to .)r  r   rz   r{   flushtime	monotonicpollr6   queueEmpty_handle_server_messager   RuntimeErrorr~   r&   r   TimeoutError)r/  r0  r-  r.  
request_idpayloaddeadlinemsgerrr   r&  next_idr   r   r)  r  s             r   _requestz.CopilotACPClient._run_prompt.<locals>._request  s&   qLG J    	 G JTZ0047888J~''/9H.""X--99;;*))C)00CC{   H .. )$3 /    774==J..c>>'''**0bC&SvSS	8J8J8QcSS   wwx((())K006688Kyy{{&;&5kBB &: -8: :   ##U#U#UVVVYPVYYYZZZs   B2 2CC
initializefs)readTextFilewriteTextFilezhermes-agentzHermes Agentz0.0.0)ra   r}   version)protocolVersionclientCapabilities
clientInfozsession/new)r   
mcpServers	sessionIdr!   z'Copilot ACP did not return a sessionId.zsession/promptr   )r   r   )rM  promptr   r   )
r/  r   r0  rK   r-  r   r.  r   r   r   )
subprocessPopenr   r   PIPEr   rF   FileNotFoundErrorr;  r  r  r   r   r   r   r8  Queuer   r   Threadr   r   r6   r&   r~   r   )r   r  r  r   r'  r*  
out_thread
err_threadrC  session
session_idr-  r.  r&  rB  r   r)  s   ` `          @@@@r   r  zCopilotACPClient._run_prompt  s   	#"#dn4 o!!M)++	 	 	DD ! 	 	 	a8I a a a  	 :!4IIKKKWXXX& 	( 	(#'D 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( .3[]]"'r"2"2"2	: 	: 	: 	: 	: 	: 	:	6 	6 	6 	6 	6 	6 	6 %^DIII
%^DIII
\`  GK :	[ :	[ :	[ :	[ :	[ :	[ :	[ :	[ :	[ :	[ :	[ :	[ :	[x/	H'(,0-1 + !/!/#*# #   " h="$      W[[55;<<BBDDJ N"#LMMM$&J)+OH !+ %+$/   & /    77:&&(@(@@JJLLLLDJJLLLLs7   AA" "
B
,BB
C  C$'C$B9I I&r@  rK   r2  subprocess.Popen[str]r   r-  r.  r   c                  |                     d          }t          |t                    sdS |dk    r|                     d          pi }|                     d          pi }t          |                     d          pd                                          }	|                     d          pi }
d}t          |
t                    r$t          |
                     d	          pd          }|	d
k    r|r||                    |           n|	dk    r|r||                    |           dS |j        dS |                     d          }|                     d          pi }|dk    rt          |          }n|dk    r|	 t          t          |                     d          pd          |          }t          t          |                    }|rt          |          |                                r|                                nd}
|                     d          }|                     d          }t          |t                    r`|dk    rZ|
                    d          }|dz
  }t          |t                    r|dk    r||z   nd }d                    |||                   }
|
rt!          |
d          }
d|d|
id}nB# t"          $ r)}t%          |dt          |                    }Y d }~nd }~ww xY w|dk    r	 t          t          |                     d          pd          |          }t'          t          |                    rt          d| d          |j                            dd           |                    t          |                     d          pd                     d|d d}nJ# t"          $ r(}t%          |dt          |                    }Y d }~nd }~ww xY wt%          |dd| d           }|j                            t1          j        |          d!z              |j                                         dS )"Nr/  Fzsession/updater0  updatesessionUpdater!   rm   r   agent_message_chunkagent_thought_chunkTrO   zsession/request_permissionzfs/read_text_filer7   r%  limitr   )keependsr   )forcerM   rU   izfs/write_text_filezWrite denied: 'z(' is a protected system/credential file.)parentsexist_okizACP client method 'z!' is not supported by Hermes yet.r   )r6   rw   r   r&   ry   rv   r  rW   r   r   r   exists	read_textrI   
splitlinesr~   r
   r4   rQ   r	   parentmkdir
write_textr   rz   r{   r4  )r   r@  r2  r   r-  r.  r/  r0  r\  kindrm   
chunk_textrG   responser7   block_errorr%  r`  linesr   r   r   s                         r   r:  z'CopilotACPClient._handle_server_messageV  s    ""&#&& 	5%%%WWX&&,"FZZ))/RFvzz/228b99??AADjj++1rGJ'4(( < V!4!4!:;;
,,,,
@V!!*----...:./B]&&z2224= 4WWT]]
""(b111)*55HH***H.s6::f3E3E3K/L/LcRR23t99== 7)+666.2kkmmC$..***zz&))

7++dC(( 8TAXX#...==E 1HE+5eS+A+AYeaii%%--UYC ggeE#I&677G I3G4HHHG$$!7   H H H)*fc#hhGGH+++H.s6::f3E3E3K/L/LcRR"3t99-- )X$XXX   !!$!>>>FJJy$9$9$?R @ @AAA$$" 
  H H H)*fc#hhGGH &OfOOO H 	DJx0047888ts2   >EK 
K6K11K6 B:N; ;
O-O((O-)r   r[   r   r[   r   r   r   r[   r   r   r   r[   r   r[   r   r   r   r   rO  )rZ   r[   rX   r]   r   r   r\   r]   r^   r   r   r   r   r   )r  r   r  r   r   r  )r@  rK   r2  rZ  r   r   r-  r   r.  r   r   r   )	r   r   r   __doc__r   r   r   r  r:  r   r   r   r   r   N  s        BB
 ##15"&%)""!%5 5 5 5 5 50   ( !04 $-1:
 :
 :
 :
 :
 :
x^ ^ ^ ^@U U U U U Ur   r   )r   r   r   r   )r   r   )r   r(   )r   rB   )rG   r   rH   rI   rJ   r   r   rK   )rG   r   r   rK   )NNN)
rX   rY   rZ   r[   r\   r]   r^   r   r   r   )rm   r   r   r   )r   r   r   r   )r   r   r   r   r   r   ).rp  
__future__r   rz   r$   r8  rer+   rP  r   r5  collectionsr   pathlibr   typesr   typingr   agent.file_safetyr   r	   agent.redactr
   r   r  compileDOTALLr   r   r   r   r   r'   r.   rA   rF   rQ   rW   r   r|   r   r   r   r   r   r   r   r   <module>r{     s    # " " " " "  				  				                       ! ! ! ! ! !       C C C C C C C C . . . . . .%    bj!JBIVV RZ  !H  JL  JS  T  T  (  C C C C             F      	 	 	 	 )-	H_ H_ H_ H_ H_V       0F F F FT
 
 
 
> > > > > > > >7 7 7 7 7 7 7 7
] ] ] ] ] ] ] ] ] ]r   