Fix inverted tool approval badge in Duo chat

What does this MR do and why?

In Duo Agentic Chat, tool call status badges could show the opposite of the user's actual decision. When a tool call was denied and then another call of the same tool was approved, the denied card finalized as "Approved" and the approved card as "Cancelled".

The cause is in toolDenialTransformer. An approved request is followed by an executed tool message sharing its tool_info.name; a denied request has none. The transformer matched forward from each request, earliest first, so when a denied request came before an approved one for the same tool, the denied (earlier) request greedily claimed the later request's executed tool message — flipping both badges.

This changes the matching to start from each executed tool and claim the nearest preceding unclaimed request of the same name. That request is the one that was approved; requests left without a tool are denied. The pairing is now correct regardless of the order the user approved and denied same-named tools in, and every existing case (approve-first, different tools, pending, multiple denials) still behaves the same.

References

Closes #619249

Related: !248785 (merged) (added MSW coverage for Duo chat tool calls and documented the toolDenialTransformer Approved-vs-Cancelled behaviour this MR corrects).

Before / After

Deny the first tool approval prompt, then approve a second prompt for the same tool:

Tool call Before (badge) After (badge)
First (denied) Approved ❌ Cancelled ✅
Second (approved) Cancelled ❌ Approved ✅

How to set up and validate locally

yarn jest ee/spec/frontend/ai/duo_agentic_chat/transformers/tool_denial_transformer_spec.js

The spec adds a case for the denied-first / approved-second same-tool sequence that reproduced the inverted badges.

Edited by Bobby Nandigam

Merge request reports

Loading
Loading