ag-ui-protocol / ag-ui-protocol/ag-ui

[Feature]: Add AGUIStreamOptions.IncludeRawEvents to make rawEvent attachment opt-out (.NET)

Aperta
#2,297 1 commento 1 reazione 0 assegnatari Vedi su GitHub
enhancement
Lingua principale
Python
Stelle
15.9k
Fork
1.4k
Merge medio
1g 17h
PR unite (30g)
163

Descrizione

### Pre-flight Checklist

- [x] I have searched existing issues and this hasn't been requested yet.

### Problem or Motivation

`AsAGUIEventStreamAsync` serializes every `ChatResponseUpdate` and attaches it as `rawEvent` to each event derived from it (`TEXT_MESSAGE_*`, `TOOL_CALL_*`, `REASONING_ENCRYPTED_VALUE`). There is no way to turn it off.

Measured on this repo's own `Step*` server baselines: `rawEvent` is **66% of the wire** (425,009 → 145,716 bytes when stripped; `TEXT_MESSAGE_CONTENT` +213%, `TOOL_CALL_END` +648%). It rides protobuf as well as SSE.

Nothing reads it. The .NET client's only `RawEvent` reference is the *event type* (`EventStreamConverter.cs:341`); the TS client only writes the field on its own error events (`transform/http.ts:72`).

It is also a .NET-only divergence: no TS or Python server populates `rawEvent` (Python declares `raw_event: Optional[Any] = None` and never sets it), and `agui-cross-sdk-parity/SKILL.md:27` makes TypeScript canonical for wire format.

### Proposed Solution

An init-only `bool IncludeRawEvents` on `AGUIStreamOptions`, default `true` so nothing changes. Guard the serialization, not the assignment, so opting out also recovers the per-update CPU and allocations (`ChatResponseUpdateAGUIExtensions.cs:200`):

```csharp
JsonElement? raw = options.IncludeRawEvents
? JsonSerializer.SerializeToElement(chatResponse, jsonSerializerOptions.GetTypeInfo(typeof(ChatResponseUpdate)))
: null;
```

Every `Create` already takes `JsonElement?`, so this widens one internal signature (`ReasoningMessageTracker.EmitEncryptedValue`). Events the caller supplies — via `RawRepresentation` or a `Map*` callback — keep their own `RawEvent`. Event sequence is unchanged, so this is not a protocol change.

### Alternatives Considered

**A host-side stream filter** that nulls `RawEvent` before the formatter. Works (verified, −61% on a short stream) but still pays the serialization, must be reimplemented per host, and can't tell an SDK-attached payload from a deliberate one.

**Defaulting to `false`.** Arguably correct long-term — it is what puts .NET in parity — but flipping it breaks anyone reading the field and moves every baseline. Better as a separate, deliberate change.

**Emitting `BaseEvent`s via `RawRepresentation`** to hit the short-circuit above line 200. Avoids the serialization entirely, but means reimplementing text/tool/reasoning tracking.

### Additional Context

_No response_

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.