Update ag-ui-example UI with STATE_DELTA instead of ACTIVITY_SNAPSHOT since these are not handled by copilotkit
This commit is contained in:
parent
84f25f0627
commit
0f5b9ae208
3 changed files with 117 additions and 108 deletions
|
|
@ -108,9 +108,35 @@ async def stream_research_agent(request: Request) -> StreamingResponse:
|
||||||
async for event in emitter:
|
async for event in emitter:
|
||||||
# Log events for debugging
|
# Log events for debugging
|
||||||
logger.info(f"AG-UI Event: {event}")
|
logger.info(f"AG-UI Event: {event}")
|
||||||
# Filter out ACTIVITY_SNAPSHOT - not supported by CopilotKit
|
event_type = event.get("type")
|
||||||
if event.get("type") == "ACTIVITY_SNAPSHOT":
|
|
||||||
|
# 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
|
continue
|
||||||
|
|
||||||
await send_stream.send(format_sse_event(event))
|
await send_stream.send(format_sse_event(event))
|
||||||
|
|
||||||
# Run agent and event forwarding concurrently
|
# Run agent and event forwarding concurrently
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ interface ResearchState {
|
||||||
gaps_identified: GapRecord[];
|
gaps_identified: GapRecord[];
|
||||||
} | null;
|
} | null;
|
||||||
result?: ResearchReport;
|
result?: ResearchReport;
|
||||||
|
current_activity?: string;
|
||||||
|
current_activity_message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AgentContent() {
|
function AgentContent() {
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,8 @@ interface ResearchState {
|
||||||
gaps_identified: GapRecord[];
|
gaps_identified: GapRecord[];
|
||||||
} | null;
|
} | null;
|
||||||
result?: ResearchReport;
|
result?: ResearchReport;
|
||||||
|
current_activity?: string;
|
||||||
|
current_activity_message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StateDisplayProps {
|
interface StateDisplayProps {
|
||||||
|
|
@ -187,7 +189,8 @@ export default function StateDisplay({ state }: StateDisplayProps) {
|
||||||
gap: "1rem",
|
gap: "1rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Current Status */}
|
{/* Question */}
|
||||||
|
{state.context.original_question && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: "white",
|
background: "white",
|
||||||
|
|
@ -200,52 +203,60 @@ export default function StateDisplay({ state }: StateDisplayProps) {
|
||||||
style={{
|
style={{
|
||||||
fontSize: "0.875rem",
|
fontSize: "0.875rem",
|
||||||
color: "#718096",
|
color: "#718096",
|
||||||
marginBottom: "0.5rem",
|
marginBottom: "0.25rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Research Progress
|
Question
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", gap: "0.75rem", alignItems: "center" }}>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: "0.5rem 1rem",
|
fontSize: "1.125rem",
|
||||||
background:
|
fontWeight: "bold",
|
||||||
state.iterations === 0
|
color: "#2d3748",
|
||||||
? "#e2e8f0"
|
}}
|
||||||
: state.result
|
>
|
||||||
? "#d1fae5"
|
{state.context.original_question}
|
||||||
: "#dbeafe",
|
</div>
|
||||||
color:
|
</div>
|
||||||
state.iterations === 0
|
)}
|
||||||
? "#718096"
|
|
||||||
: state.result
|
{/* Research Progress - only show when research has started */}
|
||||||
? "#065f46"
|
{(state.iterations > 0 || (state.current_activity && !state.result)) && (
|
||||||
: "#1e40af",
|
<div
|
||||||
|
style={{
|
||||||
|
background: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
padding: "1.5rem",
|
||||||
|
boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Current Activity - hide when complete */}
|
||||||
|
{state.current_activity && !state.result && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: "0.75rem",
|
||||||
|
background: "#ebf8ff",
|
||||||
borderRadius: "6px",
|
borderRadius: "6px",
|
||||||
fontSize: "1rem",
|
border: "1px solid #90cdf4",
|
||||||
fontWeight: "700",
|
marginBottom: state.iterations > 0 ? "1rem" : 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{state.iterations === 0
|
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
||||||
? "Ready"
|
<span>⏳</span>
|
||||||
: state.result
|
<span style={{ fontWeight: "600", color: "#2b6cb0" }}>
|
||||||
? "Complete"
|
{state.current_activity.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())}
|
||||||
: "Researching"}
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{state.iterations > 0 && (
|
{state.current_activity_message && (
|
||||||
<div
|
<div style={{ fontSize: "0.875rem", color: "#4299e1", marginTop: "0.25rem", marginLeft: "1.5rem" }}>
|
||||||
style={{
|
{state.current_activity_message}
|
||||||
fontSize: "0.875rem",
|
|
||||||
color: "#4a5568",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Iteration {state.iterations} of {state.max_iterations}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* Research Progress Bar */}
|
)}
|
||||||
|
{/* Iteration Progress Bar */}
|
||||||
{state.iterations > 0 && (
|
{state.iterations > 0 && (
|
||||||
<div style={{ marginTop: "1rem" }}>
|
<div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
|
@ -284,7 +295,7 @@ export default function StateDisplay({ state }: StateDisplayProps) {
|
||||||
style={{
|
style={{
|
||||||
width: `${researchProgress}%`,
|
width: `${researchProgress}%`,
|
||||||
height: "100%",
|
height: "100%",
|
||||||
background: "#48bb78",
|
background: state.result ? "#48bb78" : "#4299e1",
|
||||||
transition: "width 0.3s ease",
|
transition: "width 0.3s ease",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -292,36 +303,6 @@ export default function StateDisplay({ state }: StateDisplayProps) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Question */}
|
|
||||||
{state.context.original_question && (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: "white",
|
|
||||||
borderRadius: "8px",
|
|
||||||
padding: "1.5rem",
|
|
||||||
boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
fontSize: "0.875rem",
|
|
||||||
color: "#718096",
|
|
||||||
marginBottom: "0.25rem",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Question
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
fontSize: "1.125rem",
|
|
||||||
fontWeight: "bold",
|
|
||||||
color: "#2d3748",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{state.context.original_question}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Confidence Meter */}
|
{/* Confidence Meter */}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue