a6d4266c93
The agent loop previously kept running when the LLM emitted final_answer with malformed JSON arguments: observe.analyzeResponse strictly json.Unmarshal'd the raw args and returned isDone=false on failure, while act.runToolCall separately repaired the JSON and executed the tool. The mismatch made final_answer non-terminal, so the LLM saw its own answer in the next round's tool result and re-emitted final_answer, surfacing near-identical answers multiple times to the user (issue #1008). Fix by unifying parsing in a new tools.ParseFinalAnswerArgs helper with three fallbacks (strict -> RepairJSON -> regex extraction) and making final_answer always terminal in analyzeResponse. When no answer can be recovered, emit a user-visible fallback message and a Done=true event so the UI still resolves. Also route final_answer.Execute through the same helper so tool execution and loop termination stay consistent. Adds regression tests in observe_test.go and final_answer_test.go covering valid args, RepairJSON recovery, unrecoverable args, and garbage input. Refs: Tencent/WeKnora#1008