agent-scan: recover finish when LLM omits closing tags - #622
Conversation
Port the two parse fallbacks mcp-scan already has to agent-scan's copy of parse_tool_invocations: a bare <finish>...</finish> block, and a truncated <function=finish> whose closing tag the LLM omitted (e.g. output cut off by max_tokens). Without them the parser returns None, handle_no_tool() runs instead of finish, and the entire final report produced by the scan is silently lost while the loop idles to max_iter. Also hide bare <finish> blocks in clean_content(), matching mcp-scan. Verified: normal tool calls, closed finish, truncated finish, bare finish, tag-free and empty inputs all behave as intended.
|
Thanks @chaucerj — this is a clean, well-motivated port. I verified Two minor, non-blocking notes:
Otherwise correct and ready to merge. Nice catch on the silent-report-loss. (Note: I'm leaving this as a review comment only — not merging.) |
|
Thanks @boy-hack for the thorough verification — and for tracing the callers to confirm the silent-report-loss path. Both notes acknowledged:
Anything else needed from my side? If not, would you mind adding the formal approval so this can merge? |
agent-scan/agent_scan/utils/parse.pyis a copy of mcp-scan's parser, but it is missing the two finish fallbacks the mcp-scan copy already has:<finish>...</finish>block, and<function=finish>whose closing tag the LLM omitted (e.g. output cut off by max_tokens).finishis the only way the agent loop terminates. When the parser returnsNone,handle_no_tool()runs instead and the entire final report produced by the scan is silently lost while the loop idles tomax_iter.This ports both fallbacks from mcp-scan (keeping agent-scan's
dict | Nonesignature and its combined<parameter=/<parameter name=regex) and hides bare<finish>blocks inclean_content(), matching mcp-scan.Verified on: normal tool calls, closed finish, truncated finish, bare finish, tag-free and empty inputs — all behave as intended.