1+ import datetime
12import json
3+ import os
24import time
5+ import traceback
36from typing import Optional
47from secrets import token_hex
58from lmos_openai_types import (
811 CreateChatCompletionRequest ,
912 CreateChatCompletionStreamResponse ,
1013 Function1 ,
14+ FinishReason1 ,
1115)
1216
1317from mcp_bridge .inference_engine_mappers .chat .requester import chat_completion_requester
1418from mcp_bridge .inference_engine_mappers .chat .stream_responder import (
1519 chat_completion_stream_responder ,
1620)
17- from .utils import call_tool , chat_completion_add_tools
21+ from .utils import (
22+ call_tool ,
23+ chat_completion_add_tools ,
24+ json_pretty_print ,
25+ salvage_parsable_json_object ,
26+ validate_if_json_object_parsable ,
27+ )
1828from mcp_bridge .models import SSEData , upstream_error
1929from mcp_bridge .http_clients import get_client
2030from loguru import logger
@@ -68,9 +78,9 @@ async def chat_completions(request: CreateChatCompletionRequest):
6878 # exclude_defaults=True, exclude_none=True, exclude_unset=True
6979 # )
7080
71- json_data = json . dumps (chat_completion_requester (request ))
81+ json_data = json_pretty_print (chat_completion_requester (request ))
7282
73- # logger.debug(json_data)
83+ logger .debug ("Request JSON: \n %s" % json_data )
7484
7585 last : Optional [CreateChatCompletionStreamResponse ] = None # last message
7686
@@ -211,6 +221,29 @@ async def chat_completions(request: CreateChatCompletionRequest):
211221 # save the last message
212222 last = parsed_data
213223
224+ # perform early stopping on parsable tool_call_json
225+ if tool_call_json :
226+ if tool_call_json .strip ().startswith ("{" ):
227+ if validate_if_json_object_parsable (tool_call_json ):
228+ logger .debug (
229+ f"tool call json '{ tool_call_json } ' is parsable now."
230+ )
231+ logger .debug ("exiting message receive loop" )
232+ last .choices [0 ].finish_reason = FinishReason1 .tool_calls
233+ break
234+ salvaged_json_object = salvage_parsable_json_object (
235+ tool_call_json
236+ )
237+ if salvaged_json_object :
238+ tool_call_json = salvaged_json_object
239+ logger .debug (
240+ f"tool call json '{ tool_call_json } ' is salvagable now."
241+ )
242+ logger .debug ("salvaged json content:" , tool_call_json )
243+ logger .debug ("exiting message receive loop" )
244+ last .choices [0 ].finish_reason = FinishReason1 .tool_calls
245+ break
246+
214247 # ideally we should check this properly
215248 assert last is not None
216249
@@ -229,6 +262,9 @@ async def chat_completions(request: CreateChatCompletionRequest):
229262 f"{ tool_call_name = } { tool_call_json = } "
230263 ) # this should not be error but its easier to debug
231264
265+ logger .debug ("clearing tool contexts to prevent tool call loops" )
266+ request .tools = None
267+
232268 # add received message to the history
233269 msg = ChatCompletionRequestMessage (
234270 role = "assistant" ,
0 commit comments