diff --git a/pipeline_service/agent_loop.py b/pipeline_service/agent_loop.py index 69cc10e..fd8bc37 100644 --- a/pipeline_service/agent_loop.py +++ b/pipeline_service/agent_loop.py @@ -2032,6 +2032,28 @@ def _parse_agent_action(raw): if isinstance(d, dict) and 'tool' in d: return {"action": "tool_call", "tool": d.get("tool", ""), "params": d.get("params") or {}} + # 裸 JSON 动作对象扫描(2026-09-15 pbls M1a 实测):LLM 连续输出多个无围栏的 + # {"action":"tool_call",...} 对象(一行一个)——整体 json.loads 失败(多对象拼接)、 + # 围栏扫描无命中 → 兜底把 tool_call 文本当交付件正文 deliver → 交付件 content + # 就是 JSON 文本、files_json 只有快照文件,QC 必退且退回理由失真。 + # raw_decode 逐个扫描,取第一个可解析的动作对象。 + _dec = json.JSONDecoder() + _idx = 0 + while True: + _b = raw.find('{', _idx) + if _b < 0: + break + try: + _d, _end = _dec.raw_decode(raw[_b:]) + except (json.JSONDecodeError, ValueError): + _idx = _b + 1 + continue + if isinstance(_d, dict) and 'action' in _d: + return _d + if isinstance(_d, dict) and 'tool' in _d: + return {"action": "tool_call", "tool": _d.get("tool", ""), "params": _d.get("params") or {}} + _idx = _b + max(_end, 1) + return {"action": "deliver", "result": raw}