Stabilize product data export flow
This commit is contained in:
+48
-3
@@ -832,8 +832,15 @@ class LocalCodingAgent:
|
||||
return result
|
||||
# fall through to the normal tool-call branch below
|
||||
# normal error path if not recovered
|
||||
final_output = str(exc)
|
||||
session.append_assistant(
|
||||
final_output,
|
||||
message_id=f'assistant_{len(session.messages)}',
|
||||
stop_reason='backend_error',
|
||||
)
|
||||
_append_final_text_stream_events(stream_events, final_output)
|
||||
result = AgentRunResult(
|
||||
final_output=str(exc),
|
||||
final_output=final_output,
|
||||
turns=max(turn_index - 1, 0),
|
||||
tool_calls=tool_calls,
|
||||
transcript=session.transcript(),
|
||||
@@ -1535,15 +1542,42 @@ class LocalCodingAgent:
|
||||
usage=usage,
|
||||
)
|
||||
assistant_message = session.messages[assistant_index]
|
||||
try:
|
||||
parsed_tool_calls = self._tool_calls_from_message(assistant_message.tool_calls)
|
||||
except OpenAICompatError:
|
||||
self._scrub_malformed_assistant_tool_calls(session, assistant_index)
|
||||
raise
|
||||
turn = AssistantTurn(
|
||||
content=assistant_message.content,
|
||||
tool_calls=self._tool_calls_from_message(assistant_message.tool_calls),
|
||||
tool_calls=parsed_tool_calls,
|
||||
finish_reason=finish_reason,
|
||||
raw_message=assistant_message.to_openai_message(),
|
||||
usage=usage,
|
||||
)
|
||||
return turn, tuple(events)
|
||||
|
||||
def _scrub_malformed_assistant_tool_calls(
|
||||
self,
|
||||
session: AgentSessionState,
|
||||
assistant_index: int,
|
||||
) -> None:
|
||||
message = session.messages[assistant_index]
|
||||
filtered_blocks = tuple(
|
||||
block
|
||||
for block in message.blocks
|
||||
if block.get('type') not in {'tool_use', 'tool_call'}
|
||||
)
|
||||
session.messages[assistant_index] = replace(
|
||||
message,
|
||||
tool_calls=(),
|
||||
blocks=filtered_blocks,
|
||||
stop_reason='malformed_tool_arguments',
|
||||
metadata={
|
||||
**message.metadata,
|
||||
'malformed_tool_arguments': True,
|
||||
},
|
||||
)
|
||||
|
||||
def _tool_calls_from_message(
|
||||
self,
|
||||
tool_calls: tuple[dict[str, object], ...],
|
||||
@@ -1558,7 +1592,18 @@ class LocalCodingAgent:
|
||||
continue
|
||||
raw_arguments = function_block.get('arguments', '')
|
||||
if isinstance(raw_arguments, str) and raw_arguments.strip():
|
||||
arguments = json.loads(raw_arguments)
|
||||
try:
|
||||
arguments = json.loads(raw_arguments)
|
||||
except json.JSONDecodeError as exc:
|
||||
preview = raw_arguments[:240].replace('\n', '\\n')
|
||||
raise OpenAICompatError(
|
||||
'模型返回的工具参数不是合法 JSON,已停止本轮以避免执行错误工具。'
|
||||
f'工具:{name};位置:line {exc.lineno} column {exc.colno};'
|
||||
f'原因:{exc.msg};参数片段:{preview!r}。'
|
||||
'请回复“继续”,我会要求模型重新生成合法 JSON 参数;'
|
||||
'对于大段 dataset draft,应分批或使用 draft_path/records_path,'
|
||||
'不要把大量带引号的文本一次性塞进工具参数。'
|
||||
) from exc
|
||||
if not isinstance(arguments, dict):
|
||||
raise OpenAICompatError(
|
||||
f'Tool arguments must decode to an object, got {type(arguments).__name__}'
|
||||
|
||||
Reference in New Issue
Block a user