77
88from app .logger import logger
99from app .tool .base import BaseTool
10- from app . tool . did_auth_client import DIDAuthClient
10+ from agent_connect . authentication import DIDWbaAuthHeader
1111
1212class ANPTool (BaseTool ):
1313 name : str = "anp_tool"
14- description : str = """使用 Agent Network Protocol (ANP) 与其他智能体进行交互。
15- 第一次使用时,请输入 URL: https://agent-search.ai/ad.json,这是一个智能体搜索服务,可以利用里面的接口查询能够提供酒店、门票景点的智能体。
16- 收到智能体的描述文档后,你可以根据智能体描述文档中的数据链接URL,爬取数据。中间过程中可以调用API完成服务。知道你认为任务完成。
17- 注意,使用ANPTool获得的任何URL,必须使用ANPTool调用,不要自己直接调用。
14+ description : str = """Use Agent Network Protocol (ANP) to interact with other agents.
15+ 1. For the first use, please enter the URL: https://agent-search.ai/ad.json, which is an agent search service. You can use the interfaces inside to query agents that can provide hotels, tickets, and attractions.
16+ 2. After receiving the agent's description document, you can crawl data based on the data link URL in the agent's description document.
17+ 3. During the process, you can call the API to complete the service until you think the task is completed.
18+ 4. Note, any URL obtained using ANPTool must be called using ANPTool, do not call it directly yourself.
1819"""
1920 parameters : dict = {
2021 "type" : "object" ,
2122 "properties" : {
2223 "url" : {
2324 "type" : "string" ,
24- "description" : "(required) 智能体描述文件或 API 端点的 URL " ,
25+ "description" : "(required) URL of the agent description file or API endpoint " ,
2526 },
2627 "method" : {
2728 "type" : "string" ,
28- "description" : "(optional) HTTP 方法,如 GET、 POST、 PUT 等,默认为 GET" ,
29+ "description" : "(optional) HTTP method, such as GET, POST, PUT, etc., default is GET" ,
2930 "enum" : ["GET" , "POST" , "PUT" , "DELETE" , "PATCH" ],
3031 "default" : "GET" ,
3132 },
3233 "headers" : {
3334 "type" : "object" ,
34- "description" : "(optional) HTTP 请求头 " ,
35+ "description" : "(optional) HTTP request headers " ,
3536 "default" : {},
3637 },
3738 "params" : {
3839 "type" : "object" ,
39- "description" : "(optional) URL 查询参数 " ,
40+ "description" : "(optional) URL query parameters " ,
4041 "default" : {},
4142 },
4243 "body" : {
4344 "type" : "object" ,
44- "description" : "(optional) 请求体,用于 POST/PUT 请求 " ,
45+ "description" : "(optional) Request body for POST/PUT requests " ,
4546 },
4647 },
4748 "required" : ["url" ],
4849 }
4950
50- # 声明 auth_client 字段
51- auth_client : Optional [DIDAuthClient ] = None
51+ # Declare auth_client field
52+ auth_client : Optional [DIDWbaAuthHeader ] = None
5253
5354 def __init__ (self , ** data ):
5455 super ().__init__ (** data )
5556
56- # 获取当前脚本目录
57+ # Get current script directory
5758 current_dir = Path (__file__ ).parent
58- # 获取项目根目录
59+ # Get project root directory
5960 base_dir = current_dir .parent .parent
6061
61- # 初始化 DID 身份验证客户端
62+ # Initialize DID authentication client
6263 did_path = str (base_dir / "config/did_test_public_doc/did.json" )
6364 key_path = str (base_dir / "config/did_test_public_doc/key-1_private.pem" )
6465
65- logger .info (f"ANPTool 初始化 - DID路径 : { did_path } , 私钥路径 : { key_path } " )
66+ logger .info (f"ANPTool initialized - DID path : { did_path } , private key path : { key_path } " )
6667
67- self .auth_client = DIDAuthClient (
68+ self .auth_client = DIDWbaAuthHeader (
6869 did_document_path = did_path ,
6970 private_key_path = key_path
7071 )
@@ -78,145 +79,124 @@ async def execute(
7879 body : Dict [str , Any ] = None
7980 ) -> Dict [str , Any ]:
8081 """
81- 执行 HTTP 请求与其他智能体交互
82+ Execute HTTP request to interact with other agents
8283
8384 Args:
84- url (str): 智能体描述文件或 API 端点的 URL
85- method (str, optional): HTTP 方法,默认为 "GET"
86- headers (Dict[str, str], optional): HTTP 请求头
87- params (Dict[str, Any], optional): URL 查询参数
88- body (Dict[str, Any], optional): 请求体,用于 POST/PUT 请求
85+ url (str): URL of the agent description file or API endpoint
86+ method (str, optional): HTTP method, default is "GET"
87+ headers (Dict[str, str], optional): HTTP request headers
88+ params (Dict[str, Any], optional): URL query parameters
89+ body (Dict[str, Any], optional): Request body for POST/PUT requests
8990
9091 Returns:
91- Dict[str, Any]: 响应内容
92+ Dict[str, Any]: Response content
9293 """
9394
9495 if headers is None :
9596 headers = {}
9697 if params is None :
9798 params = {}
9899
99- logger .info (f"ANP请求 : { method } { url } " )
100+ logger .info (f"ANP request : { method } { url } " )
100101
101- # 添加基本请求头
102+ # Add basic request headers
102103 if "Content-Type" not in headers and method in ["POST" , "PUT" , "PATCH" ]:
103104 headers ["Content-Type" ] = "application/json"
104105
105- # 添加 DID 身份验证
106+ # Add DID authentication
106107 if self .auth_client :
107108 try :
108109 auth_headers = self .auth_client .get_auth_header (url )
109110 headers .update (auth_headers )
110111 except Exception as e :
111- logger .error (f"获取身份验证头失败 : { str (e )} " )
112+ logger .error (f"Failed to get authentication header : { str (e )} " )
112113
113114
114115 async with aiohttp .ClientSession () as session :
115- # 准备请求参数
116+ # Prepare request parameters
116117 request_kwargs = {
117118 "url" : url ,
118119 "headers" : headers ,
119120 "params" : params ,
120121 }
121122
122- # 如果有请求体且方法支持,添加请求体
123+ # If there is a request body and the method supports it, add the request body
123124 if body is not None and method in ["POST" , "PUT" , "PATCH" ]:
124125 request_kwargs ["json" ] = body
125126
126- # 执行请求
127+ # Execute request
127128 http_method = getattr (session , method .lower ())
128129
129130 try :
130131 async with http_method (** request_kwargs ) as response :
131- logger .info (f"ANP响应: 状态码 { response .status } " )
132+ logger .info (f"ANP response: status code { response .status } " )
132133
133- # 检查响应状态
134+ # Check response status
134135 if response .status == 401 and "Authorization" in headers and self .auth_client :
135- logger .warning ("认证失败 (401),尝试重新获取身份验证 " )
136- # 如果认证失败且使用了令牌,清除令牌并重试
136+ logger .warning ("Authentication failed (401), trying to get authentication again " )
137+ # If authentication fails and a token was used, clear the token and retry
137138 self .auth_client .clear_token (url )
138- # 重新获取身份验证头
139+ # Get authentication header again
139140 headers .update (self .auth_client .get_auth_header (url , force_new = True ))
140- # 重新执行请求
141+ # Execute request again
141142 request_kwargs ["headers" ] = headers
142143 async with http_method (** request_kwargs ) as retry_response :
143- logger .info (f"ANP重试响应: 状态码 { retry_response .status } " )
144+ logger .info (f"ANP retry response: status code { retry_response .status } " )
144145 return await self ._process_response (retry_response , url )
145146
146147 return await self ._process_response (response , url )
147148 except aiohttp .ClientError as e :
148- logger .error (f"HTTP 请求失败 : { str (e )} " )
149+ logger .error (f"HTTP request failed : { str (e )} " )
149150 return {
150- "error" : f"HTTP 请求失败 : { str (e )} " ,
151+ "error" : f"HTTP request failed : { str (e )} " ,
151152 "status_code" : 500
152153 }
153154
154155
155156 async def _process_response (self , response , url ):
156- """处理 HTTP 响应 """
157- # 如果认证成功,更新令牌
157+ """Process HTTP response """
158+ # If authentication is successful, update the token
158159 if response .status == 200 and self .auth_client :
159160 try :
160161 self .auth_client .update_token (url , dict (response .headers ))
161162 except Exception as e :
162- logger .error (f"更新令牌失败 : { str (e )} " )
163+ logger .error (f"Failed to update token : { str (e )} " )
163164
164- # 获取响应内容类型
165+ # Get response content type
165166 content_type = response .headers .get ('Content-Type' , '' ).lower ()
166167
167- # 获取响应文本
168+ # Get response text
168169 text = await response .text ()
169170
170- # 根据内容类型处理响应
171+ # Process response based on content type
171172 if 'application/json' in content_type :
172- # 处理 JSON 响应
173+ # Process JSON response
173174 try :
174175 result = json .loads (text )
175- logger .info ("成功解析 JSON 响应 " )
176+ logger .info ("Successfully parsed JSON response " )
176177 except json .JSONDecodeError :
177- logger .warning ("Content-Type 声明为 JSON 但解析失败,返回原始文本 " )
178+ logger .warning ("Content-Type declared as JSON but parsing failed, returning raw text " )
178179 result = {"text" : text , "format" : "text" , "content_type" : content_type }
179180 elif 'application/yaml' in content_type or 'application/x-yaml' in content_type :
180- # 处理 YAML 响应
181+ # Process YAML response
181182 try :
182183 result = yaml .safe_load (text )
183- logger .info ("成功解析 YAML 响应 " )
184+ logger .info ("Successfully parsed YAML response " )
184185 result = {"data" : result , "format" : "yaml" , "content_type" : content_type }
185186 except yaml .YAMLError :
186- logger .warning ("Content-Type 声明为 YAML 但解析失败,返回原始文本 " )
187+ logger .warning ("Content-Type declared as YAML but parsing failed, returning raw text " )
187188 result = {"text" : text , "format" : "text" , "content_type" : content_type }
188189 else :
189- # 尝试自动检测格式
190- # 首先尝试解析为 JSON
191- try :
192- result = json .loads (text )
193- logger .info ("自动检测到 JSON 格式并成功解析" )
194- result = {"data" : result , "format" : "json" , "content_type" : content_type }
195- except json .JSONDecodeError :
196- # 然后尝试解析为 YAML
197- if text .strip () and (':' in text or '-' in text ): # 简单检查是否可能是 YAML
198- try :
199- result = yaml .safe_load (text )
200- if isinstance (result , (dict , list )): # 确认是结构化数据
201- logger .info ("自动检测到 YAML 格式并成功解析" )
202- result = {"data" : result , "format" : "yaml" , "content_type" : content_type }
203- else :
204- # 可能是纯文本但恰好符合 YAML 语法
205- result = {"text" : text , "format" : "text" , "content_type" : content_type }
206- except yaml .YAMLError :
207- # 不是 YAML,返回原始文本
208- result = {"text" : text , "format" : "text" , "content_type" : content_type }
209- else :
210- # 不像是 YAML,返回原始文本
211- result = {"text" : text , "format" : "text" , "content_type" : content_type }
212-
213- # 添加状态码到结果
190+ # Default to text
191+ result = {"text" : text , "format" : "text" , "content_type" : content_type }
192+
193+ # Add status code to result
214194 if isinstance (result , dict ):
215195 result ["status_code" ] = response .status
216196 else :
217197 result = {"data" : result , "status_code" : response .status , "format" : "unknown" , "content_type" : content_type }
218198
219- # 添加 URL 到结果,方便追踪
199+ # Add URL to result for tracking
220200 result ["url" ] = str (url )
221201
222202 return result
0 commit comments