
    epj*\                       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m	Z	m
Z
 ddlmZmZmZ ddlmZmZ  ej        e          ZdZd	ZdhdZdidZdjdZdkdZdldZdmdZdmdZdndZdodZdpd Z dqd"Z!drd$Z"dsd)Z#dtd,Z$dud/Z%dud0Z&dvdwd2Z'dud3Z(dxd6Z)dydzd;Z*dud<Z+ ed=e,e,e-e,ef         d>d?@          Z. edAe,e.dBd?@          Z/dCdDdEdFddGdHdIidgdJd>dBdCdKdLdFdGdMdIdGdNdIdGdOdIdPdd&gdJd>dBdCdQdRdFi dSd>dBdCdTdUdFdGdVdIdWdXdIdYd'gdJd>dBdCdZd[dFdGd\dIdGd]dIdGg d^d_d`dGdadIdbd4d&gdJd>dBdcZ0dde1de<   e%e&e'e(e+dcZ2d{dgZ3dS )|u  
A2A client tools — let the Hermes agent talk to *other* agents as a peer.

Tools (registered in the ``a2a`` toolset):
  - a2a_discover(url)         -> fetch + summarize a peer's Agent Card
  - a2a_call(agent, message)  -> send a task to a peer, return its reply
  - a2a_list()                -> list configured peers + persisted conversations
  - a2a_history(context_id)   -> recall a persisted A2A conversation
  - a2a_orchestrate(...)      -> fan-out task to multiple peers by capability

Peers are resolved from config.yaml under ``a2a_agents``::

    a2a_agents:
      researcher:
        url: "http://localhost:9999"
        auth: { type: bearer, token: "sk-..." }
        timeout: 120
        capabilities: [web_search, research]

Transport is stdlib urllib (no a2a-sdk dependency). The wire format is the A2A
v1.0 JSON-RPC ``message/send`` method; replies from v0.3 peers still parse.
    )annotationsN)ThreadPoolExecutoras_completed)AnyOptional	TypedDict   )protocolsecurityx      returndictc                 L    	 ddl m}   |             pi S # t          $ r i cY S w xY w)Nr   load_config)hermes_cli.configr   	Exceptionr   s    A/home/thesage/.hermes/hermes-agent/plugins/platforms/a2a/tools.py_load_configr   -   sN    111111{}}""   			s    ##agentstrOptional[dict]c                   |                      d          s|                      d          r| i t          g dS t                      }|                    d          pi }|                    |           }|sdS |                    dd          |                    di           pi t	          |                    d	t                              |                    d
g           pg |                    dd          dS )zWResolve a peer name to {url, auth, timeout, capabilities}, or treat ``agent`` as a URL.zhttp://zhttps://)urlauthtimeoutcapabilities
a2a_agentsNr    r   r   r   tenant)r   r   r   r   r!   )
startswith_DEFAULT_TIMEOUTr   getint)r   cfgpeersentrys       r   _resolve_peerr)   5   s    	"" [e&6&6z&B&B [b5EWYZZZ
..CGGL!!'REIIeE tyy##		&"%%+uyy,<==>>		."55;))Hb))      r   c                    | r;|                      d          dk    r"|                      d          rdd| d          iS i S )NtypebearertokenAuthorizationzBearer )r$   )r   s    r   _auth_headerr0   G   sN     <  H,,'1B1B,!:4=!:!:;;Ir*   r   headersr   r%   c                .   t           j                            | |d          }t           j                            ||          5 }t	          j        |                                                    d                    cd d d            S # 1 swxY w Y   d S )NGET)r1   methodr   utf-8)urllibrequestRequesturlopenjsonloadsreaddecode)r   r1   r   reqresps        r   _http_get_jsonrA   Q   s    
.
 
 ge
 
D
DC			W		5	5 7z$))++,,W55667 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7s   9B

BBbodyc                   t          j        |                              d          }dt          j        d|}t
          j                            | ||d          }t
          j                            ||          5 }t          j	        |
                                                    d                    cd d d            S # 1 swxY w Y   d S )Nr6   zapplication/json)zContent-TypezA2A-VersionPOST)datar1   r4   r5   )r;   dumpsencoder
   PROTOCOL_VERSIONr7   r8   r9   r:   r<   r=   r>   )r   rB   r1   r   rE   hdrsr?   r@   s           r   _http_post_jsonrJ   W   s    :d""7++D.x?Xdd\cdD
.
 
 4f
 
M
MC			W		5	5 7z$))++,,W55667 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7s   =9CC
Cbase_urlc                2    |                      d          dz   S )N/z/.well-known/agent-card.jsonrstriprK   s    r   	_card_urlrQ   _   s     ??3"@@@r*   c                2    |                      d          dz   S )NrM   z/.well-known/agent.jsonrN   rP   s    r   _legacy_card_urlrS   e   s    ??3";;;r*   c                    	 t          t          |           ||          S # t          j        j        $ r}|j        dk    r Y d }~nd }~ww xY wt          t          |           ||          S )Ni  )rA   rQ   r7   error	HTTPErrorcoderS   )rK   r1   r   es       r   _fetch_cardrY   i   s}    i117GDDD<!   6S== ==== *844gwGGGs     A
AA
cardc                    t          | t                    rb|                     dg           pg D ]I}t          |t                    r2|                    d          dk    r|                    d          r|c S Jd S )NsupportedInterfacesprotocolBindingJSONRPCr   
isinstancer   r$   )rZ   ifaces     r   _select_jsonrpc_interfacerb   r   s    $ XX3R88>B 	 	E%&& 5995F+G+G9+T+TY^YbYbchYiYi+T4r*   c                   t          |          }|rt          |d                   S t          |t                    r8t          |                    d          t                    r|d         r|d         S |                     d          S )zPrefer the card's JSONRPC interface (v1.0 supportedInterfaces), then the
    card's legacy top-level url, then the configured base.r   rM   )rb   r   r`   r   r$   rO   )rK   rZ   ra   s      r   _rpc_urlrd   z   s     &d++E !5<   $ *TXXe__c"B"B tE{ E{??3r*   peerc                    t          |           }|r*|                    d          rt          |d                   S t          |                    d          pd          S )Nr!   r    )rb   r$   r   )rZ   re   ra   s      r   _interface_tenantrg      s[    %d++E $8$$ $5?###txx!!'R(((r*   statec                    | r<|                      dd                               dd                                          ndS )zDTASK_STATE_COMPLETED -> completed (also passes through v0.3 states).TASK_STATE_r    _-)replacelower)rh   s    r   _short_statero      s=    INV5==++33C==CCEEETVVr*   agent_labelmessage
context_idtuple[str, str, str]c           	        |                     dd          }t          |                     di           pi           }t          |                     dt                              }d}	 t	          ||t          |d                    }n# t          $ r Y nw xY w|pt          j                    }t          j
        |          }	dt          j                    dd	t          j        t          j        |	|
          id}
t          ||          }|r||
d         d<   t          j        d| |
d         |	           t          j        |d|	|
d                    t          j        xj        dz  c_        t'          t)          ||          |
||          }d|v r1|d         }t+          d|  d|                     d	|                     |                     di           }t          j        |          }t/          |          }|d}}t1          |t2                    rA|                     d|          }|                     d          pi                      dd          }t          j        |d||
d                    t          j        xj        dz  c_        |||fS )zSend one message/send to a peer. Returns (reply_text, context_id, state).

    Raises urllib errors / ValueError for the caller to format. Handles
    outbound redaction, audit, persistence, and metrics.
    r   r    r   r   N   z2.0SendMessagerq   )rr   )jsonrpcidr4   paramsry   r!   outboundrx   userr	   rU   zPeer 'z' returned an error: result	contextIdstatusrh   r   )r$   r0   r%   r#   rY   minr   r
   new_context_idr   redact_outboundnew_task_idtext_message	ROLE_USERrg   auditpersist_messagemetricsoutbound_totalrJ   rd   
ValueErrorunwrap_send_message_response_reply_text_from_resultr`   r   inbound_total)rp   re   rq   rr   rK   r1   r   rZ   ctxsafe_messagerpc_bodyr!   r@   errr|   payloadreply	reply_ctxrh   s                      r   
_send_taskr      s    xxr""H488FB//5266G$((9&67788G D8Wc'2.>.>??    
1/11C+G44L "$$x,X-?Z]^^^
	 H tT**F .'-8$N:{HTNLIIIS&,GGG##q(##8Hd33XwPPD$7m]+]]CGGIWZD[D[]]^^^XXh##F3F;;G#G,,EBuI'4   ?KKS11	X&&,"11'2>>YGGG""a'"")U""s   'B 
BBr|   r   c                   t          j        |           } t          | t                    st	          |           S |                     dg           pg D ]}t          j        |          }|r|c S |                     di           pi }|                    d          }|rt          j        |          S t          j        |           S )N	artifactsr~   rq   )r
   r   r`   r   r   r$   extract_text)r|   artifacttxtr~   msgs        r   r   r      s    26::Ffd## 6{{JJ{B//52  #H-- 	JJJ	ZZ"%%+F
**Y

C
 *$S))) (((r*   argsrk   c                   t          |                     d          pd                                          }|sdS 	 t          |i t                    }nJ# t
          j        j        $ r}d|j         d| dcY d}~S d}~wt          $ r}d| d	| dcY d}~S d}~ww xY w|                    d
d          }|                    dd          }|                    di           pi }|                    dg           pg }|                    d          rdnd}	|                    dg           pg }
d
                    d |
D                       pd|                    dd           d}d| d| dt          ||           d| dt          |                    d                     dt          |                    d                     d |	 d!t          |           d"g}|dd#         D ]Y}|                    d$|                    d
|                    d%d                     d&|                    dd                      Zd'
                    |          S )(z.Fetch and summarize the Agent Card at ``url``.r   r    z6Error: 'url' is required (e.g. http://localhost:9999).u!   Error: discovery failed — HTTP z from .NzError: could not reach u    — name?descriptionr   skillsr   yesnor\   , c              3     K   | ]H}t          |t                    |                    d d           d|                    dd           V  IdS )r]   r   z vprotocolVersionNr_   ).0is     r   	<genexpr>za2a_discover.<locals>.<genexpr>   sq        :a..55"C((KKAEE2CS,I,IKK     r*   vr   z (pre-1.0 card)zAgent: zDescription: zURL: z
Protocol: zStreaming: 	streamingz  Push: pushNotificationsz  Auth required: zSkills ():     - rx   : 
)r   r$   striprY   r#   r7   rU   rV   rW   r   joinrd   boollenappend)r   rk   r   rZ   rX   r   desccapsr   r   ifacesprotolinesss                 r   a2a_discoverr      s   
dhhuoo#
$
$
*
*
,
,C HGG83$455<! H H HG16GGGGGGGGGGG 8 8 877717777777778 88FC  D88M2&&D88NB''-2DXXh##)rFHHZ((255dDXX+R006BFII       ? 
?TXX'--	>	>	> 

 	$%d##%%Uwd488K0011ww4I\@]@];^;^wwquww"3v;;"""E CRC[ [ [YAEE&!%%c*:*:;;YYquu]TV?W?WYYZZZZ99Us/   A B'A:4B:BBBBc                v   t          |                     d          p+|                     d          p|                     d          pd                                          }t          |                     d          p+|                     d          p|                     d          pd                                          }t          |                     d          p|                     d	          pd                                          }|r|sd
S t          |          }|r|                    d          sd| dS 	 t	          ||||          \  }}}n# t
          j        j        $ rJ}	|	j        dv rd| d|	j         dcY d}	~	S |	j        dk    rd| dcY d}	~	S d| d|	j         dcY d}	~	S d}	~	wt          $ r}	t          |	          cY d}	~	S d}	~	wt          $ r}	d| d|	 dcY d}	~	S d}	~	ww xY wd| d| }
|r|
dt          |           z  }
|
dz  }
|pd}|t          j        k    r	|d| dz  }|
 d | S )!zSend a task to a peer agent and return its reply.

    ``agent`` is a configured peer name (from ``a2a_agents``) or a direct URL.
    ``context_id`` continues a prior exchange (multi-turn) when provided.
    r   
agent_namer   r    rq   texttaskrr   r}   z/Error: both 'agent' and 'message' are required.r   zError: unknown agent 'zP'. Configure it under 'a2a_agents' in config.yaml or pass a full http(s):// URL.)i  i  zError: peer 'z' rejected auth (HTTP z). Check the configured token.Ni  z*' rate limited us (HTTP 429). Retry later.zError: call to 'u   ' failed — HTTP r   u   ' failed — [u    · context u    · ]z(no text reply)uS   

(The peer needs more input — answer by calling a2a_call again with context_id 'z'.)r   )r   r$   r   r)   r   r7   rU   rV   rW   r   r   ro   r
   STATE_INPUT_REQUIRED)r   rk   r   rq   rr   re   r   r   rh   rX   headerrB   s               r   a2a_callr     s    !!UTXXl%;%;Utxx?O?OUSUVV\\^^E$((9%%S&)9)9STXXf=M=MSQSTTZZ\\GTXXl++Jtxx/D/DJKKQQSSJ A A@@D 
txx 
:U : : :	

;",UD':"N"Ny%%<! E E E6Zf5fffffffffff6S==T5TTTTTTTTTD%DD16DDDDDDDDD   1vv ; ; ;:%::a:::::::::; 0//I//F /.e,,...
cMF%%D---/ )/ / /	
 sZ   ?E G0*F/ G0F/G0F/)G0/G0<G
G0G0G+%G0+G0dict | Nonec                l   t                      }|                    d          pi }g }|r|                    dt          |           d           |                                D ]\  }}|                    d          pi                     dd          }|                    dg           }|rdd	                    |           nd
}	|                    d| d|                    dd           d| d|	            n|                    d           t          j                    }
|
r`|                    d
           |                    dt          |
           d           |
dd         D ]}|                    d|            t          j        	                                }|                    d
           |                    d|d          d|d          d|d          d|d          d|d          d |d!          d"|d#          d$|d%          d&|d'          d(           d)                    |          S )*z:List configured A2A peers and any persisted conversations.r   zConfigured peers (r   r   r,   noner   z caps: r   r    r   r   r   r   z (auth: )z@No peers configured. Add them under 'a2a_agents' in config.yaml.zPersisted conversations (u   ) — recall with a2a_history:N   z	Metrics: r   z in / r   z out, tasks_completedz completed, tasks_failedz	 failed, streams_startedz
 streams, 	push_sentz push sent, anti_loop_triggersz anti-loop, rate_limit_triggersz rate-limited, avg avg_latency_msmsr   )
r   r$   r   r   itemsr   r
   list_conversationsr   snapshot)r   rk   r&   r'   r   r   r(   r   r   cap_strconvoscms                r   a2a_listr   1  s   
..CGGL!!'REE Y8#e**888999 ;;== 	Y 	YKD%IIf%%+00@@D99^R00D59A1		$111rGLLWWW		%(=(=WWtWWgWWXXXX		Y 	WXXX(**F %R\V\\\]]] 	% 	%ALL$$$$ 	!!##A	LL	LL 0Q/ 0 0q9I7J 0 0'(0 0676G0 0'(0 045kN0 0 *+0 0 :;;P9Q0 0 *+	0 0 0 1 1 1 99Ur*   c           
        t          |                     d          p|                     d          pd                                          }|sdS 	 t          dt	          t          |                     d          pd          d                    }n# t          t          f$ r d}Y nw xY wt          j	        ||	          }|sd
| dS d| dt          |           dg}|D ]|}|                    dd          }|                    d          pd                                }t          |          dk    r|dd         dz   }|                    d| d|            }d                    |          S )zRecall a persisted A2A conversation by context_id.

    This is how prior A2A exchanges survive compaction/restarts: every turn is
    written to ~/.hermes/a2a_conversations/<context>.jsonl and can be reloaded
    here.
    rr   r}   r    zGError: 'context_id' is required (see a2a_list for known conversations).r	   limit2      )r   z'No persisted conversation for context ''.zConversation z (last z messages):roler   r   i  Nu    …[truncated]r   z] r   )r   r$   r   maxr   r%   r   	TypeErrorr
   load_conversationr   r   r   )	r   rk   rr   r   messagesr   r   r   r   s	            r   a2a_historyr   S  s    TXXl++Jtxx/D/DJKKQQSSJ YXXAs3txx006B77==>>	"   )*EBBBH HGGGGGJZJJHJJJKE ) )uuVS!!f#**,,t99t;!22D'''''((((99Us   A B B('B(
capabilitylist[tuple[str, dict]]c                    t                      }|                    d          pi }g }|                                D ]>\  }}|                    dg           pg }| |v s| dk    r|                    ||f           ?|S )z:Find configured peers that advertise the given capability.r   r   *)r   r$   r   r   )r   r&   r'   matchesr   r(   r   s          r   _match_peers_by_capabilityr   r  s    
..CGGL!!'REG{{}} * *eyy,,2s!2!2NND%=)))Nr*   r    r   
peer_entrytuple[str, str]c                $   	 |                     dd          |                     di           pi t          |                     dt                              d}t          | |||          \  }}}| |pdfS # t          $ r}| d| fcY d}~S d}~ww xY w)	zCCall a single peer synchronously. Returns (agent_name, reply_text).r   r    r   r   )r   r   r   z
(no reply)Error: N)r$   r%   r#   r   r   )	r   r   rq   rr   re   r   _ctx_staterX   s	            r   _call_peer_syncr   ~  s    	+>>%,,NN62..4":>>)5EFFGG
 

 )T7JOOtVE1\22 + + +MaMM*******+s   A1A4 4
B>B
B
Bc                @   t          |                     d          pd                                          }t          |                     d          p|                     d          pd                                          t          |                     d          pd                                                                          }t          |                     d          pd                                          sdS |sd	S t	          |          }|sd
| dS |dvrd}g t          t          t          |          t                              5 fd|D             }t          |          D ]}||         }	 
                    |                                           |dk    r<d         d                             d          s|D ]}|                                  n2u# t          $ r$}	
                    |d|	 f           Y d}	~	d}	~	ww xY wddd           n# 1 swxY w Y                       d            d D             }
d'fd}|dk    r2|
s
 |            S t!          |
d           }d|d          d|d          S |dk    r|
s
 |            S |
d         \  }}d | d| S d!| d"t          |           d#g}D ]3\  }}|
                    d$| d%           |
                    |           4d&                    |          S )(u  Fan-out a task to multiple peer agents by capability.

    Modes:
      - ``all``: send to all peers matching the capability, return all replies.
      - ``first``: send to all matching peers, return the first successful reply.
      - ``best``: send to all, return the longest successful reply (a coarse
        detail heuristic — use ``all`` when you want to judge yourself).

    Configured peers advertise capabilities in config.yaml::

      a2a_agents:
        researcher:
          url: "http://localhost:9991"
          capabilities: [web_search, research]
        coder:
          url: "http://localhost:9992"
          capabilities: [code, debug]
    r   r    rq   r   modeallrr   zError: 'message' is required.z;Error: 'capability' is required (or use '*' for all peers).z1Error: no configured peers advertise capability 'r   r   firstbest)max_workersc           	     T    i | ]$\  }}                     t          ||          |%S  )submitr   )r   r   r(   rr   rq   pools      r   
<dictcomp>z#a2a_orchestrate.<locals>.<dictcomp>  sC     
 
 
e KKugzJJD
 
 
r*   r   r	   Error:r   Nc                    | d         S )Nr   r   rs    r   <lambda>z!a2a_orchestrate.<locals>.<lambda>  s
    qt r*   )keyc                F    g | ]\  }}|                     d           ||fS )r  )r"   )r   r   r   s      r   
<listcomp>z#a2a_orchestrate.<locals>.<listcomp>  s4    \\\;4AQAQRZA[A[\$\\\r*   r   r   c                 z    dg} D ] \  }}|                      d| d|            !d                    |           S )NzAll peers failed:z  r   r   )r   r   )r   r   r   resultss      r   _all_failedz$a2a_orchestrate.<locals>._all_failed  sV    $%" 	/ 	/KD%LL-d--e--....yyr*   r   c                ,    t          | d                   S )Nr	   )r   r  s    r   r  z!a2a_orchestrate.<locals>.<lambda>  s    C!II r*   z[best: r   z]
z[first: zOrchestrated 'z' to z	 peer(s):z
--- z ---r   )r   r   )r   r$   r   rn   r   r   r   r   _ORCHESTRATE_MAX_WORKERSr   r   r|   r"   cancelr   sortr   r   )r   rk   r   r   r   futuresfutr   frX   	successesr  r   r   r   rr   rq   r   r
  s                  @@@@r   a2a_orchestrater    s   & TXXl++1r2288::J$((9%%?&)9)9?R@@FFHHGtxx(5))//117799DTXXl++1r2288::J /.. MLL(44G RQ:QQQQ+++ &(G	CLL:R(S(S	T	T	T 6X\
 
 
 
 
 
&
 
 
  (( 
	6 
	6C3<D6szz||,,,7??72;q>+D+DX+N+N?$ # #



E 6 6 6mmm45555555566 6 6 6 6 6 6 6 6 6 6 6 6 6 6$ LL^^L$$$\\'\\\I            v~~ 	!;== 9"5"5666.a..T!W...	 	!;== le*$**5***J*JJ3w<<JJJK" 	  	 KD%LL,$,,,---LLyys=   *H-A'G0-H-0
H:HH-HH--H14H1_FunctionSchema)r   r   
parametersF)total_ToolSchema)r,   functionr  r   zFetch and summarize another agent's A2A Agent Card from a URL (its name, description, capabilities, and skills). Use this to find out what a remote agent can do before calling it.objectstringz<Base URL of the remote A2A agent, e.g. http://localhost:9999)r,   r   )r,   
propertiesrequiredr   zSend a natural-language task to a remote A2A agent and return its reply. The agent is a peer (any A2A-compliant framework), not a sub-agent you control. Pass 'context_id' from a previous reply to continue a multi-turn exchange.z@Configured peer name (from a2a_agents) or a full http(s):// URL.z9The task / message to send the peer, in natural language.zFOptional: context id from a prior reply, to continue the conversation.)r   rq   rr   r   zJList configured A2A peer agents, persisted A2A conversations, and metrics.)r,   r  r   zRecall a persisted A2A conversation transcript by context_id (survives restarts and context compaction). Use a2a_list to see known context ids.z)Context id of the conversation to recall.integerz-Max messages to return (default 50, max 200).)rr   r   r  zFan-out a task to multiple peer agents by capability. Peers are matched from config.yaml a2a_agents.*.capabilities. Modes: 'all' (return all replies), 'first' (first successful), 'best' (longest successful reply).zCCapability to match (e.g. 'research', 'code') or '*' for all peers.z'The task to send to all matching peers.r   z)How to aggregate results. Default: 'all'.)r,   enumr   z*Optional: shared context id for all peers.)r   rq   r   rr   )r   r   r   r   r  zdict[str, _ToolSchema]_SCHEMASNonec           	         t                                           D ]7\  }}|                     |d|t          |         |d         d         d           8dS )z1Register the client tools in the ``a2a`` toolset.a2ar  r   u   🧩)r   toolsetschemahandlerr   emojiN)r   r   register_tool	_HANDLERS)r   r   r%  s      r   register_toolsr*  I  sk     (( 
 
fdOz*=9 	 	
 	
 	
 	

 
r*   )r   r   )r   r   r   r   )r   r   r   r   )r   r   r1   r   r   r%   r   r   )
r   r   rB   r   r1   r   r   r%   r   r   )rK   r   r   r   )rK   r   r1   r   r   r%   r   r   )rZ   r   r   r   )rK   r   rZ   r   r   r   )rZ   r   re   r   r   r   )rh   r   r   r   )
rp   r   re   r   rq   r   rr   r   r   rs   )r|   r   r   r   )r   r   rk   r   r   r   )N)r   r   rk   r   r   r   )r   r   r   r   )r    )
r   r   r   r   rq   r   rr   r   r   r   )r   r!  )4__doc__
__future__r   r;   loggingurllib.errorr7   urllib.requestconcurrent.futuresr   r   typingr   r   r   r    r
   r   	getLogger__name__loggerr#   r  r   r)   r0   rA   rJ   rQ   rS   rY   rb   rd   rg   ro   r   r   r   r   r   r   r   r   r  r   r   r  r  r   __annotations__r)  r*  r   r*   r   <module>r6     s    . # " " " " "           ? ? ? ? ? ? ? ? + + + + + + + + + +                		8	$	$        $   7 7 7 77 7 7 7A A A A< < < <H H H H          ) ) ) )W W W W
3# 3# 3# 3#l) ) ) )*       F+ + + +\    D   >	 	 	 	+ + + + +P  P  P  P n )-C_cdgildl_m/n/nv{|||i'Q'QY^___ "I
 !H={|| #G 
 
 & ; !&.  @B  C  C(0A|}}+3  EM  #N  #N 
 %i0 
 
 , g#+2>>
 
  !)
 !+3Do"p"p&/@opp  *N 
 
 ( %% !+3  EJ  #K  #K(0Ajkk%-7O7O7O  aL  M  M+3Dp"q"q	  *95	 	
 
 GY$ Y$ Y Y Y Yx !& 	

 

 

 

 

 

r*   