Follow-up to the salvaged #114442 (@hteo1337), which closes each ACP tool call
from its own ``tool.completed`` (the mechanism PR #50741 by @liuhao1024 filed in
June, and PR #27854 by @godlin-gh filed first in May via ``tool_complete_callback``) and fails whatever is still open at turn end, draining
``tool_call_ids`` and ``tool_call_meta`` together.
Live repro of the fallback path exposed a third mechanism the issue did not
name: ``make_step_cb`` passed ``prev_tools[i]["arguments"]`` — the wire JSON
*string* — as ``function_args`` into ``build_tool_complete``, whose content
builders index it as a dict. The ``.get`` on a str raised inside the swallowed
step callback, so a ``write_file`` close never reached the client even when a
next step existed. Coerce with ``coerce_tool_args`` (meta args when absent).
Tests: the contributor's six tests folded into two invariants — a call is
closed exactly once from ``tool.completed`` with the step closer standing down;
the step fallback survives JSON-string arguments and the turn-end flush fails
the remaining call while emptying BOTH per-turn dicts.
Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
Co-authored-by: godlin <ganlinbupt@gmail.com>