From 0f5b9ae2089aefa10075924871495e25b34d9bd5 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Wed, 3 Dec 2025 15:32:48 +0200 Subject: [PATCH] Update ag-ui-example UI with STATE_DELTA instead of ACTIVITY_SNAPSHOT since these are not handled by copilotkit --- examples/ag-ui-research/backend/main.py | 30 ++- .../frontend/components/Agent.tsx | 2 + .../frontend/components/StateDisplay.tsx | 193 ++++++++---------- 3 files changed, 117 insertions(+), 108 deletions(-) diff --git a/examples/ag-ui-research/backend/main.py b/examples/ag-ui-research/backend/main.py index bae6a94c..32a2fec0 100644 --- a/examples/ag-ui-research/backend/main.py +++ b/examples/ag-ui-research/backend/main.py @@ -108,9 +108,35 @@ async def stream_research_agent(request: Request) -> StreamingResponse: async for event in emitter: # Log events for debugging logger.info(f"AG-UI Event: {event}") - # Filter out ACTIVITY_SNAPSHOT - not supported by CopilotKit - if event.get("type") == "ACTIVITY_SNAPSHOT": + event_type = event.get("type") + + # Convert ACTIVITY_SNAPSHOT to STATE_DELTA for CopilotKit + # As CopilotKit does not handle ACTIVITY_SNAPSHOT events + if event_type == "ACTIVITY_SNAPSHOT": + activity_type = event.get("activityType", "") + content = event.get("content", {}) + message = content.get("message", "") + + # Emit STATE_DELTA to patch activity info into state + # Use "add" op which creates or replaces the value + delta_event = { + "type": "STATE_DELTA", + "delta": [ + { + "op": "add", + "path": "/current_activity", + "value": activity_type, + }, + { + "op": "add", + "path": "/current_activity_message", + "value": message, + }, + ], + } + await send_stream.send(format_sse_event(delta_event)) continue + await send_stream.send(format_sse_event(event)) # Run agent and event forwarding concurrently diff --git a/examples/ag-ui-research/frontend/components/Agent.tsx b/examples/ag-ui-research/frontend/components/Agent.tsx index 87813d70..022e1100 100644 --- a/examples/ag-ui-research/frontend/components/Agent.tsx +++ b/examples/ag-ui-research/frontend/components/Agent.tsx @@ -70,6 +70,8 @@ interface ResearchState { gaps_identified: GapRecord[]; } | null; result?: ResearchReport; + current_activity?: string; + current_activity_message?: string; } function AgentContent() { diff --git a/examples/ag-ui-research/frontend/components/StateDisplay.tsx b/examples/ag-ui-research/frontend/components/StateDisplay.tsx index df08e64a..865e8c87 100644 --- a/examples/ag-ui-research/frontend/components/StateDisplay.tsx +++ b/examples/ag-ui-research/frontend/components/StateDisplay.tsx @@ -86,6 +86,8 @@ interface ResearchState { gaps_identified: GapRecord[]; } | null; result?: ResearchReport; + current_activity?: string; + current_activity_message?: string; } interface StateDisplayProps { @@ -187,112 +189,6 @@ export default function StateDisplay({ state }: StateDisplayProps) { gap: "1rem", }} > - {/* Current Status */} -
-
- Research Progress -
-
-
- {state.iterations === 0 - ? "Ready" - : state.result - ? "Complete" - : "Researching"} -
- {state.iterations > 0 && ( -
- Iteration {state.iterations} of {state.max_iterations} -
- )} -
- {/* Research Progress Bar */} - {state.iterations > 0 && ( -
-
- - Iterations - - - {state.iterations}/{state.max_iterations} - -
-
-
-
-
- )} -
- {/* Question */} {state.context.original_question && (
)} + {/* Research Progress - only show when research has started */} + {(state.iterations > 0 || (state.current_activity && !state.result)) && ( +
+ {/* Current Activity - hide when complete */} + {state.current_activity && !state.result && ( +
0 ? "1rem" : 0, + }} + > +
+ + + {state.current_activity.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())} + +
+ {state.current_activity_message && ( +
+ {state.current_activity_message} +
+ )} +
+ )} + {/* Iteration Progress Bar */} + {state.iterations > 0 && ( +
+
+ + Iterations + + + {state.iterations}/{state.max_iterations} + +
+
+
+
+
+ )} +
+ )} + {/* Confidence Meter */} {confidence > 0 && (