8
8
SystemMessage ,
9
9
UserMessage ,
10
10
)
11
-
12
- # from agnext.components.tools import FunctionTool
13
11
from agnext .core import CancellationToken
14
12
15
13
from ...markdown_browser import RequestsMarkdownBrowser
18
16
# from typing_extensions import Annotated
19
17
from ._tools import TOOL_FIND_NEXT , TOOL_FIND_ON_PAGE_CTRL_F , TOOL_OPEN_LOCAL_FILE , TOOL_PAGE_DOWN , TOOL_PAGE_UP
20
18
21
- # async def read_local_file(file_path: Annotated[str, "relative or absolute path of file to read"]) -> str:
22
- # """Read contents of a file."""
23
- # try:
24
- # async with aiofiles.open(file_path, mode="r") as file:
25
- # file_contents = str(await file.read())
26
- # return f"""
27
- # Here are the contents of the file at path: {file_path}
28
- # ```
29
- # {file_contents}
30
- # ```
31
- # """
32
-
33
- # except FileNotFoundError:
34
- # return f"File not found: {file_path}"
35
-
36
-
37
- # def list_files_and_dirs_like_tree(dir_path: str) -> str:
38
- # """List files and directories in a directory in a format similar to 'tree' command with level 1."""
39
- # path = Path(dir_path)
40
- # if not path.is_dir():
41
- # return f"{dir_path} is not a valid directory."
42
-
43
- # items = [f"{dir_path}"]
44
- # for item in path.iterdir():
45
- # if item.is_dir():
46
- # items.append(f"├── {item.name}/") # Indicate directories with a trailing slash
47
- # else:
48
- # items.append(f"├── {item.name}") # List files as is
49
- # return "\n".join(items)
50
-
51
19
52
20
class FileSurfer (BaseWorker ):
53
21
"""An agent that uses tools to read and navigate local files."""
@@ -72,18 +40,6 @@ def __init__(
72
40
self ._system_messages = system_messages
73
41
self ._browser = browser
74
42
self ._tools = [TOOL_OPEN_LOCAL_FILE , TOOL_PAGE_UP , TOOL_PAGE_DOWN , TOOL_FIND_ON_PAGE_CTRL_F , TOOL_FIND_NEXT ]
75
- # self._tools = [
76
- # FunctionTool(
77
- # read_local_file,
78
- # description="Use this function to read the contents of a local file whose relative or absolute path is given.",
79
- # name="read_local_file",
80
- # ),
81
- # FunctionTool(
82
- # list_files_and_dirs_like_tree,
83
- # description="List files and directories in a directory in a format similar to 'tree' command with level 1",
84
- # name="list_files_and_dirs_like_tree",
85
- # ),
86
- # ]
87
43
88
44
def _get_browser_state (self ) -> Tuple [str , str ]:
89
45
"""
@@ -110,49 +66,6 @@ def _get_browser_state(self) -> Tuple[str, str]:
110
66
111
67
return (header , self ._browser .viewport )
112
68
113
- # async def _generate_reply(self, cancellation_token: CancellationToken) -> Tuple[bool, UserContent]:
114
-
115
- # if self._browser is None:
116
- # self._browse = RequestsMarkdownBrowser(viewport_size=1024 * 5, downloads_folder="coding")
117
-
118
- # response = await self._model_client.create(self._system_messages + self._chat_history, tools=self._tools)
119
-
120
- # if isinstance(response.content, str):
121
- # final_result = response.content
122
-
123
- # elif isinstance(response.content, list) and all(isinstance(item, FunctionCall) for item in response.content):
124
- # results = await asyncio.gather(*[self.send_message(call, self.id) for call in response.content])
125
- # for result in results:
126
- # assert isinstance(result, FunctionExecutionResult)
127
- # final_result = "\n".join(result.content for result in results)
128
- # else:
129
- # raise ValueError(f"Unexpected response type: {response.content}")
130
-
131
- # assert isinstance(final_result, str)
132
-
133
- # return "TERMINATE" in final_result, final_result
134
-
135
- # @message_handler
136
- # async def handle_tool_call(
137
- # self, message: FunctionCall, cancellation_token: CancellationToken
138
- # ) -> FunctionExecutionResult:
139
- # """Handle a tool execution task. This method executes the tool and publishes the result."""
140
- # function_call = message
141
- # # Find the tool
142
- # tool = next((tool for tool in self._tools if tool.name == function_call.name), None)
143
- # if tool is None:
144
- # result_as_str = f"Error: Tool not found: {function_call.name}"
145
- # else:
146
- # try:
147
- # arguments = json.loads(function_call.arguments)
148
- # result = await tool.run_json(args=arguments, cancellation_token=cancellation_token)
149
- # result_as_str = tool.return_value_as_string(result)
150
- # except json.JSONDecodeError:
151
- # result_as_str = f"Error: Invalid arguments: {function_call.arguments}"
152
- # except Exception as e:
153
- # result_as_str = f"Error: {e}"
154
- # return FunctionExecutionResult(content=result_as_str, call_id=function_call.id)
155
-
156
69
async def _generate_reply (self , cancellation_token : CancellationToken ) -> Tuple [bool , str ]:
157
70
if self ._browser is None :
158
71
self ._browser = RequestsMarkdownBrowser (viewport_size = 1024 * 5 , downloads_folder = "coding" )
@@ -164,7 +77,6 @@ async def _generate_reply(self, cancellation_token: CancellationToken) -> Tuple[
164
77
task_content = last_message .content # the last message from the sender is the task
165
78
166
79
assert self ._browser is not None
167
- # assert self._browser.page_title is not None
168
80
169
81
context_message = UserMessage (
170
82
source = "user" ,
@@ -189,7 +101,12 @@ async def _generate_reply(self, cancellation_token: CancellationToken) -> Tuple[
189
101
function_calls = response
190
102
for function_call in function_calls :
191
103
tool_name = function_call .name
192
- arguments = json .loads (function_call .arguments )
104
+
105
+ try :
106
+ arguments = json .loads (function_call .arguments )
107
+ except json .JSONDecodeError as e :
108
+ error_str = f"File surfer encountered an error decoding JSON arguments: { e } "
109
+ return False , error_str
193
110
194
111
if tool_name == "open_local_file" :
195
112
path = arguments ["path" ]
0 commit comments