6565REPO: {repo_url}
6666"""
6767
68- TOOLS = [
69- {
70- "type" : "function" ,
71- "function" : {
72- "name" : " shell" ,
73- "description" : " Execute a shell command in the Docker container. Returns stdout+stderr and exit code." ,
74- "parameters" : {
68+ def _get_tools ():
69+ from swe_forge . llm . client import ToolDefinition
70+ return [
71+ ToolDefinition . create (
72+ "shell" ,
73+ "Execute a shell command in the Docker container. Returns stdout+stderr and exit code." ,
74+ {
7575 "type" : "object" ,
7676 "properties" : {
77- "command" : {
78- "type" : "string" ,
79- "description" : "The shell command to execute" ,
80- },
81- "timeout" : {
82- "type" : "integer" ,
83- "description" : "Timeout in seconds (default 300)" ,
84- },
77+ "command" : {"type" : "string" , "description" : "The shell command to execute" },
78+ "timeout" : {"type" : "integer" , "description" : "Timeout in seconds (default 300)" },
8579 },
8680 "required" : ["command" ],
8781 },
88- },
89- },
90- {
91- "type" : "function" ,
92- "function" : {
93- "name" : "read_file" ,
94- "description" : "Read a file from the container." ,
95- "parameters" : {
82+ ),
83+ ToolDefinition .create (
84+ "read_file" ,
85+ "Read a file from the container." ,
86+ {
9687 "type" : "object" ,
9788 "properties" : {
9889 "path" : {"type" : "string" , "description" : "Absolute path in the container" },
9990 },
10091 "required" : ["path" ],
10192 },
102- },
103- },
104- {
105- "type" : "function" ,
106- "function" : {
107- "name" : "done" ,
108- "description" : "Signal that setup is complete. Call with success=true when fail_to_pass FAIL on base AND PASS after patch." ,
109- "parameters" : {
93+ ),
94+ ToolDefinition .create (
95+ "done" ,
96+ "Signal that setup is complete. Call with success=true when fail_to_pass FAIL on base AND PASS after patch." ,
97+ {
11098 "type" : "object" ,
11199 "properties" : {
112100 "success" : {"type" : "boolean" },
113101 "error" : {"type" : "string" , "description" : "Error description if success=false" },
114102 },
115103 "required" : ["success" ],
116104 },
117- },
118- },
119- ]
105+ ),
106+ ]
120107
121108
122109def _docker_exec (container : str , cmd : str , timeout : int = SHELL_TIMEOUT ) -> tuple [int , str ]:
@@ -259,7 +246,7 @@ async def _run_agent_loop(
259246 install_commands : list [str ],
260247 ) -> bool :
261248 """Run the LLM agent loop to set up the environment."""
262- from swe_forge .llm import Message
249+ from swe_forge .llm . client import GenerationRequest , Message
263250
264251 system = SYSTEM_PROMPT .format (
265252 max_turns = self ._max_turns ,
@@ -269,30 +256,33 @@ async def _run_agent_loop(
269256 repo_url = repo_url ,
270257 )
271258
272- messages : list [dict [str , Any ]] = [{"role" : "system" , "content" : system }]
273- messages .append ({"role" : "user" , "content" : (
274- f"Set up this repo and validate the tests. Start by exploring the repo structure "
275- f"to understand what language/framework is used, then install dependencies."
276- )})
259+ tools = _get_tools ()
260+ messages : list [Message ] = [
261+ Message .system (system ),
262+ Message .user (
263+ "Set up this repo and validate the tests. Start by exploring the repo structure "
264+ "to understand what language/framework is used, then install dependencies."
265+ ),
266+ ]
277267
278268 for turn in range (self ._max_turns ):
279- response = await self ._llm .chat (
280- messages = messages ,
269+ request = GenerationRequest (
281270 model = self ._model ,
282- tools = TOOLS ,
271+ messages = messages ,
272+ tools = tools ,
283273 temperature = 0.2 ,
284274 max_tokens = 4096 ,
285275 )
276+ response = await self ._llm .complete_with_tools (request )
286277
287278 msg = response .choices [0 ].message
288- messages .append (msg . model_dump ( exclude_none = True ) )
279+ messages .append (msg )
289280
290281 if not msg .tool_calls :
291- # Model responded with text, no tool call -- nudge it
292282 if msg .content and ("done" in msg .content .lower () or "success" in msg .content .lower ()):
293- messages .append ({ "role" : " user" , "content" : " You must call the done() tool to finish."} )
283+ messages .append (Message . user ( " You must call the done() tool to finish.") )
294284 else :
295- messages .append ({ "role" : " user" , "content" : " Continue. Use tools to make progress."} )
285+ messages .append (Message . user ( " Continue. Use tools to make progress.") )
296286 continue
297287
298288 for tc in msg .tool_calls :
@@ -326,11 +316,7 @@ async def _run_agent_loop(
326316 else :
327317 tool_result = f"Unknown tool: { fn } "
328318
329- messages .append ({
330- "role" : "tool" ,
331- "tool_call_id" : tc .id ,
332- "content" : tool_result [:8000 ],
333- })
319+ messages .append (Message (role = "tool" , content = tool_result [:8000 ], tool_call_id = tc .id ))
334320
335321 logger .warning ("[%s] Agent exhausted %d turns" , task_id , self ._max_turns )
336322 return False
0 commit comments