o
    ưig{                     @   sj  d Z ddlZddlZddlmZmZmZmZ ddlm	Z	m
Z
mZmZmZ ddlZddlmZ ddlmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZm Z m!Z!m"Z" ddl#m$Z$ ddl%m&Z& e	 Z'deddfddZ(e)ej*+ddZ,e)ej*+ddZ-de dee.ef fddZ/e'j+ddge
egee  deddde
efded e0defd!d"Z1dd#l2m3Z4 e'j5ddge
ege de
efdedefd$d%Z6e'j+d&dge
ege de
efd'e.defd(d)Z7e'j8d&dge
ege de
efd'e.dedefd*d+Z9e'j:d&dge
ege de
efd'e.de"defd,d-Z;e'j<d&d.ge
egd/e
efd'e.defd0d1Z=e'j5d2dge
egede
efd'e.defd3d4Z>e'j5d5dge
egede
efde!defd6d7Z?e'j+d8d9ge
ege&ddddddd:d;de
ef	d<ee. d=ee. d>ee. d?ee. d@ee. dAe@dBe@dCee. defdDdEZAdS )Fz
Agent endpoints for registering + discovering agents via LiteLLM.

Follows the A2A Spec.

1. Register an agent via POST `/v1/agents`
2. Discover agents via GET `/v1/agents`
3. Get specific agent via GET `/v1/agents/{agent_id}`
    N)AnyDictListOptional)	APIRouterDependsHTTPExceptionQueryRequest)verbose_proxy_logger)get_async_httpx_client)CommonProxyErrorsLitellmUserRolesUserAPIKeyAuthuser_api_key_auth)check_feature_access_for_user)get_daily_activity)AgentConfigAgentMakePublicResponseAgentResponseMakeAgentsPublicRequestPatchAgentRequest)httpxSpecialProvider)SpendAnalyticsPaginatedResponseuser_api_key_dictreturnc                 C   s(   | j tjkrtddd| j iddS )z
    Raises HTTP 403 if the caller does not have permission to create, update,
    or delete agents.  Only PROXY_ADMIN users are allowed to perform these
    write operations.
      errorzDOnly proxy admins can create, update, or delete agents. Your role={}status_codedetailN)	user_roler   PROXY_ADMINr   format)r    r%   ^/home/app/Keep/.python/lib/python3.10/site-packages/litellm/proxy/agent_endpoints/endpoints.py"_check_agent_management_permission'   s   r'   Z"LITELLM_AGENT_HEALTH_CHECK_TIMEOUTz5.0Z)LITELLM_AGENT_HEALTH_CHECK_GATHER_TIMEOUTz30.0agentc              
      s   | j pi d}|s| jddS z)ttjdtid}||I dH }|jdkr4| jdd	|j d
W S | jddW S  tyU } z| jdt	|d
W  Y d}~S d}~ww )z
    Perform a GET request against the agent's URL and return the health result.

    Returns a dict with ``agent_id``, ``healthy`` (bool), and an optional
    ``error`` message.
    urlT)agent_idhealthytimeout)Zllm_providerparamsN  FzHTTP r*   r+   r   )
agent_card_paramsgetr*   r   r   ZAgentHealthCheck"AGENT_HEALTH_CHECK_TIMEOUT_SECONDSr    	Exceptionstr)r(   r)   clientresponseexcr%   r%   r&   _check_agent_url_health@   s.   	

r8   z
/v1/agentsz[beta] A2A Agents)tagsdependenciesZresponse_modelFzWhen true, performs a GET request to each agent's URL. Agents with reachable URLs (HTTP status < 500) and agents without a URL are returned; unreachable agents are filtered out.)descriptionrequesthealth_checkc              
      s6  t |dI dH  ddlm} ddlm} zg }|jtjks%|jtjjkr*|	 }n!|j
|dI dH  t dkr>|	 }n|	 } fdd|D }dd	lm} |durd
d |D }|r|jjjdd|iidI dH }	dd |	D }
|D ]}|j|
v r|
|j |_qv|D ]}|jdu ri |_tjduo|jtjv |jd< q|rdd |D }dd |D }ztjtjdd |D  tdI dH }W n tjy   tdt dd |D }Y nw dd |D fdd|D | }|W S  ty     ty } ztd t!| tdddt!| idd}~ww )a  
    Example usage:
    ```
    curl -X GET "http://localhost:4000/v1/agents"       -H "Content-Type: application/json"       -H "Authorization: Bearer your-key"     ```

    Pass `?health_check=true` to filter out agents whose URL is unreachable:
    ```
    curl -X GET "http://localhost:4000/v1/agents?health_check=true"       -H "Content-Type: application/json"       -H "Authorization: Bearer your-key"     ```

    Returns: List[AgentResponse]

    agentsNr   global_agent_registry)AgentRequestHandlerr   c                       g | ]	}|j  v r|qS r%   r*   .0r(   )allowed_agent_idsr%   r&   
<listcomp>   s    zget_agents.<locals>.<listcomp>prisma_clientc                 S   s   g | ]}|j qS r%   rC   rD   r%   r%   r&   rG      s    r*   inwherec                 S   s   i | ]}|j |jqS r%   )r*   spend)rE   ar%   r%   r&   
<dictcomp>   s    zget_agents.<locals>.<dictcomp>Z	is_publicc                 S   s    g | ]}|j pi d r|qS r)   r0   r1   rD   r%   r%   r&   rG          c                 S   s    g | ]}|j pi d s|qS rP   rQ   rD   r%   r%   r&   rG      rR   c                 S   s   g | ]}t |qS r%   )r8   rD   r%   r%   r&   rG      s    )r,   z4Agent health check gather timed out after %s secondsc                 S   s   g | ]	}|j d ddqS )FzHealth check timed outr/   rC   rD   r%   r%   r&   rG      s    c                 S   s   h | ]
}|d  r|d qS )r+   r*   r%   )rE   resultr%   r%   r&   	<setcomp>   s    zget_agents.<locals>.<setcomp>c                    rB   r%   rC   rD   )healthy_idsr%   r&   rG      s
    
zClitellm.proxy.agent_endpoints.get_agents(): Exception occurred - {}r.   r   zInternal server error: r   )"r   ,litellm.proxy.agent_endpoints.agent_registryr@   Z;litellm.proxy.agent_endpoints.auth.agent_permission_handlerrA   r"   r   r#   valueZget_agent_listZget_allowed_agentslenlitellm.proxy.proxy_serverrI   dblitellm_agentstable	find_manyr*   rM   Zlitellm_paramslitellmpublic_agent_groupsasynciowait_forgather)AGENT_HEALTH_CHECK_GATHER_TIMEOUT_SECONDSTimeoutErrorr   warningr   r3   	exceptionr$   r4   )r<   r=   r   r@   rA   Zreturned_agentsZ
all_agentsrI   	agent_idsZ	db_agentsZ	spend_mapr(   Zagents_with_urlZagents_without_urlZhealth_resultser%   )rF   rU   r&   
get_agentsb   s    









	
rh   r?   c           
         sT  t |dI dH  ddlm} t| |du rtdddzi|jp"d}tj| d	d
}|dur=tdd| d	 ddtj	| ||dI dH }|j
}|j}ztj|d td| d| d W |W S  ty } ztd| d| d|  W Y d}~|W S d}~ww  ty     ty }	 ztd|	  tdt|	dd}	~	ww )a:  
    Create a new agent

    Example Request:
    ```bash
    curl -X POST "http://localhost:4000/agents" \
        -H "Authorization: Bearer <your_api_key>" \
        -H "Content-Type: application/json" \
        -d '{
            "agent": {
                "agent_name": "my-custom-agent",
                "agent_card_params": {
                    "protocolVersion": "1.0",
                    "name": "Hello World Agent",
                    "description": "Just a hello world agent",
                    "url": "http://localhost:9999/",
                    "version": "1.0.0",
                    "defaultInputModes": ["text"],
                    "defaultOutputModes": ["text"],
                    "capabilities": {
                        "streaming": true
                    },
                    "skills": [
                        {
                            "id": "hello_world",
                            "name": "Returns hello world",
                            "description": "just returns hello world",
                            "tags": ["hello world"],
                            "examples": ["hi", "hello world"]
                        }
                    ]
                },
                "litellm_params": {
                    "make_public": true
                }
            }
        }'
    ```
    r>   Nr   rH   r.   Prisma client not initializedr   unknown
agent_namerk     Agent with name z already exists)r(   rI   
created_byZagent_configzSuccessfully registered agent '' (ID: ) in memoryzFailed to register agent 'z) in memory: zError adding agent to db: )r   rY   rI   r'   r   user_idAGENT_REGISTRYZget_agent_by_namer1   Zadd_agent_to_dbrk   r*   register_agentr   infor3   rd   re   r4   )
r<   r   rI   ro   existing_agentrS   rk   r*   Z	reg_errorrg   r%   r%   r&   create_agent   sR   1
rx   z/v1/agents/{agent_id}r*   c              
      sX  t |dI dH  ddlm} |du rtdddzotj| d}|du rc|jjjd	| id
didI dH }|durb|	 }|j
dur[z	|j
	 |d
< W n tyZ   |j
 |d
< Y nw tdi |}n|jjjd	| idI dH }|durx|j|_|du rtdd|  dd|W S  ty     ty } ztd|  tdt|dd}~ww )z
    Get a specific agent by ID

    Example Request:
    ```bash
    curl -X GET "http://localhost:4000/agents/123e4567-e89b-12d3-a456-426614174000" \
        -H "Authorization: Bearer <your_api_key>"
    ```
    r>   Nr   rH   r.   ri   r   rC   r*   object_permissionT)rL   includerK     Agent with ID 
 not foundzError getting agent from db: r%   )r   rY   rI   r   rt   get_agent_by_idrZ   r[   find_unique
model_dumpry   r3   dictr   rM   r   re   r4   )r*   r   rI   r(   Z	agent_rowZ
agent_dictZdb_rowrg   r%   r%   r&   r~   V  sR   


r~   c              
      0  t |dI dH  ddlm} t| |du rtdtjjdzU|jj	j
d| idI dH }|dur5t|}|du rCtd	d
|  dd|jpGd}tj| |||dI dH }tj|dd tj|d td|d d|  d |W S  ty|     ty } ztd|  tdt|dd}~ww a  
    Update an existing agent

    Example Request:
    ```bash
    curl -X PUT "http://localhost:4000/agents/123e4567-e89b-12d3-a456-426614174000" \
        -H "Authorization: Bearer <your_api_key>" \
        -H "Content-Type: application/json" \
        -d '{
            "agent": {
                "agent_name": "updated-agent",
                "agent_card_params": {
                    "protocolVersion": "1.0",
                    "name": "Updated Agent",
                    "description": "Updated description",
                    "url": "http://localhost:9999/",
                    "version": "1.1.0",
                    "defaultInputModes": ["text"],
                    "defaultOutputModes": ["text"],
                    "capabilities": {
                        "streaming": true
                    },
                    "skills": []
                },
                "litellm_params": {
                    "make_public": false
                }
            }
        }'
    ```
    r>   Nr   rH   r.   r   r*   rK   r{   r|   r}   rj   )r*   r(   rI   
updated_byrk   rl   rp   zSuccessfully updated agent 'rq   rr   zError updating agent: )r   rY   rI   r'   r   r   db_not_connected_errorrW   rZ   r[   r   r   rs   rt   Zupdate_agent_in_dbderegister_agentr1   ru   r   rv   r3   re   r4   r*   r<   r   rI   rw   r   rS   rg   r%   r%   r&   update_agent  L   *
r   c              
      r   r   )r   rY   rI   r'   r   r   r   rW   rZ   r[   r   r   rs   rt   Zpatch_agent_in_dbr   r1   ru   r   rv   r3   re   r4   r   r%   r%   r&   patch_agent  r   r   ZAgents)r9   r:   c              
      s  t |dI dH  ddlm} t| |du rtdddzC|jjjd| id	I dH }|dur7tt	t	f |}|du rEtd
d|  ddt
j| |dI dH  t
j|dd dd|  diW S  tyh     ty } ztd|  tdt|dd}~ww )aZ  
    Delete an agent

    Example Request:
    ```bash
    curl -X DELETE "http://localhost:4000/agents/123e4567-e89b-12d3-a456-426614174000" \
        -H "Authorization: Bearer <your_api_key>"
    ```

    Example Response:
    ```json
    {
        "message": "Agent 123e4567-e89b-12d3-a456-426614174000 deleted successfully"
    }
    ```
    r>   Nr   rH   r.   ri   r   r*   rK   r{   r|   z not found in DB.)r*   rI   rk   rl   messagezAgent z deleted successfullyzError deleting agent: )r   rY   rI   r'   r   rZ   r[   r   r   r   rt   Zdelete_agent_from_dbr   r1   r3   r   re   r4   )r*   r   rI   rw   rg   r%   r%   r&   delete_agentR  s8   r   z!/v1/agents/{agent_id}/make_publicc           	   
      s  ddl m} |du rtdtjjdzddl}ddlm} ddl m	} |j
tjkr6tdd	d
|j
id|j| d}|du rh|jjjd| idI dH }|durZtdi | }|du rhtdd|  dd|jdu rpg |_|j|jv rtdd|j dd|j|j | I dH }d|vs|d du ri |d< |j|d d< |j|dI dH  td|j d|j  d|j|jdW S  ty     ty } ztd|  tdt|dd}~ww )a  
    Make an agent publicly discoverable

    Example Request:
    ```bash
    curl -X POST "http://localhost:4000/v1/agents/123e4567-e89b-12d3-a456-426614174000/make_public" \
        -H "Authorization: Bearer <your_api_key>" \
        -H "Content-Type: application/json"
    ```

    Example Response:
    ```json
    {
        "agent_id": "123e4567-e89b-12d3-a456-426614174000",
        "agent_name": "my-custom-agent",
        "litellm_params": {
            "make_public": true
        },
        "agent_card_params": {...},
        "created_at": "2025-11-15T10:30:00Z",
        "updated_at": "2025-11-15T10:35:00Z",
        "created_by": "user123",
        "updated_by": "user123"
    }
    ```
    r   rH   Nr.   r   r?   proxy_configr   r   >Only proxy admins can update public model groups. Your role={}rC   r*   rK   r{   r|   r}   rm   rn   z already in public agent groupslitellm_settingsr^   Z
new_config Updated public agent groups to: 
 by user: (Successfully updated public agent groupsr   r^   r   Error making agent public: r%   ) rY   rI   r   r   r   rW   r]   rV   r@   r   r"   r   r#   r$   r~   rZ   r[   r   r   r   r^   r*   rk   append
get_configsave_configr   debugrs   r3   re   r4   )	r*   r   rI   r]   rt   r   r(   configrg   r%   r%   r&   make_agent_public  sp   $	
r   z/v1/agents/make_publicc           
   
      s  ddl m} |du rtdtjjdzddl}ddlm} ddl m	} |
 I dH }|jtjkr=tdd	d
|jid|jdu rEg |_| jD ]4}|j|d}|du r||jjjd|idI dH }|durntdi | }|du r|tdd| ddqH| j|_d|vs|d du ri |d< |j|d d< |j|dI dH  td|j d|j  d|j|jdW S  ty     ty }	 ztd|	  tdt|	dd}	~	ww )a(  
    Make multiple agents publicly discoverable

    Example Request:
    ```bash
    curl -X POST "http://localhost:4000/v1/agents/make_public" \
        -H "Authorization: Bearer <your_api_key>" \
        -H "Content-Type: application/json" \
        -d '{
            "agent_ids": ["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"]
        }'
    ```

    Example Response:
    ```json
    {
        "agent_id": "123e4567-e89b-12d3-a456-426614174000",
        "agent_name": "my-custom-agent",
        "litellm_params": {
            "make_public": true
        },
        "agent_card_params": {...},
        "created_at": "2025-11-15T10:30:00Z",
        "updated_at": "2025-11-15T10:35:00Z",
        "created_by": "user123",
        "updated_by": "user123"
    }
    ```
    r   rH   Nr.   r   r?   r   r   r   r   rC   r*   rK   r{   r|   r}   r   r^   r   r   r   r   r   r   r%   )rY   rI   r   r   r   rW   r]   rV   r@   r   r   r"   r   r#   r$   r^   rf   r~   rZ   r[   r   r   r   r   r   r   rs   r3   re   r4   )
r<   r   rI   r]   rt   r   r   r*   r(   rg   r%   r%   r&   make_agents_public   sj   '
	
r   z/agent/daily/activityzAgent Management   
   rf   
start_dateend_datemodelapi_keypage	page_sizeexclude_agent_idsc	                    s   t |dI dH  ddlm}	 |	du rtddtjjid| r$| dnd}
d}|r3|r1|dnd}i }|
r?d	t|
i|d
< |	j	j
j|dI dH }dd |D }t|	dd
|
||||||||dI dH S )zJ
    Get daily activity for specific agents or all accessible agents.
    r>   Nr   rH   r.   r   r   ,rJ   r*   rK   c                 S   s   i | ]	}|j d |jiqS rl   )r*   rk   rD   r%   r%   r&   rO     s    z,get_agent_daily_activity.<locals>.<dictcomp>Zlitellm_dailyagentspend)rI   Z
table_nameZentity_id_fieldZ	entity_idZentity_metadata_fieldZexclude_entity_idsr   r   r   r   r   r   )r   rY   rI   r   r   r   rW   splitlistrZ   r[   r\   r   )rf   r   r   r   r   r   r   r   r   rI   Zagent_ids_listZexclude_agent_ids_listZwhere_conditionZagent_recordsZagent_metadatar%   r%   r&   get_agent_daily_activityo  sH   
r   )B__doc__r_   ostypingr   r   r   r   Zfastapir   r   r   r	   r
   r]   Zlitellm._loggingr   Z&litellm.llms.custom_httpx.http_handlerr   Zlitellm.proxy._typesr   r   r   Z$litellm.proxy.auth.user_api_key_authr   Z%litellm.proxy.common_utils.rbac_utilsr   Z8litellm.proxy.management_endpoints.common_daily_activityr   Zlitellm.types.agentsr   r   r   r   r   Zlitellm.types.llms.custom_httpr   Z>litellm.types.proxy.management_endpoints.common_daily_activityr   Zrouterr'   floatenvironr1   r2   rb   r4   r8   boolrh   rV   r@   rt   postrx   r~   putr   patchr   deleter   r   r   intr   r%   r%   r%   r&   <module>   sR   


" ]<	W	W8ki	