Commit Graph

2 Commits

  • .NET: fix: avoid AGUI tool result message id collisions (#5800)
    * fix: avoid AGUI tool result message id collisions
    
    * fix: split mixed tool result message ids
  • .NET: BugFix #3433 ChatClientAgent streaming responses missing messageid (#4615)
    * Changes
    
    * Fix ChatClientAgent streaming responses missing MessageId
    
    Generate fallback MessageId in ChatClientAgent.RunCoreStreamingAsync when
    the underlying LLM provider does not set ChatResponseUpdate.MessageId.
    Without a MessageId the AGUI converter's null==null check silently drops
    all text content, causing CopilotKit Zod validation errors.
    
    Changes:
    - ChatClientAgent: generate msg_{Guid} fallback via ??= in streaming loop
    - AgentResponseExtensions: sync wrapper MessageId back to RawRepresentation
      in AsChatResponseUpdate() so downstream consumers see the value
    - Add unit tests for both fixes and AGUI streaming MessageId scenarios
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR #4615 review comments
    
    - Fix MessageId seeding: use first-seen provider MessageId (or generate
      fallback) and apply consistently to all chunks in the stream, preventing
      message splitting when providers set MessageId only on the first chunk
    - Add test for mixed MessageId scenario (first chunk only)
    - Fix skipped TextStreaming test: assert Empty (not NotEmpty) to match
      actual null==null behavior
    - Fix skipped ToolCalls test: assert empty ParentMessageId to match
      actual empty-string passthrough behavior
    
    * Handle empty MessageId in AsChatResponseUpdate sync
    
    Treat empty/whitespace MessageId the same as null when syncing from
    the AgentResponseUpdate wrapper back to RawRepresentation. Providers
    that return empty string MessageId (e.g. tool call responses) now get
    the wrapper value recovered correctly.
    
    Add test for empty string MessageId recovery scenario.
    
    * Move MessageId fallback generation to AGUI layer
    
    Move fallback MessageId generation from ChatClientAgent to
    AsAGUIEventStreamAsync, addressing the architectural concern that
    MessageId is nullable in the AIAgent abstraction and the requirement
    for non-null values is specific to the AGUI protocol.
    
    The AGUI layer now generates a fallback MessageId for null or
    empty/whitespace values, covering all agent types (not just
    ChatClientAgent) including external implementations.
    
    Changes:
    - Revert MessageId generation from ChatClientAgent.RunCoreStreamingAsync
    - Add fallback MessageId generation in AsAGUIEventStreamAsync for
      null/empty MessageId values (handles both null and whitespace)
    - Unskip and update AGUI tests to verify fallback generation
    - Update ChatClientAgent tests to reflect passthrough behavior
    
    * Revert AsChatResponseUpdate MessageId sync-back
    
    Remove the MessageId sync-back logic from AsChatResponseUpdate() as it
    is no longer needed. With fallback generation moved to the AGUI layer,
    the abstraction layer should not mutate the RawRepresentation object.
    
    Revert to the original passthrough behavior for AsChatResponseUpdate()
    and update tests accordingly.
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>