Skip to content

feat: implement live run synchronization and event handling#18

Merged
Emiyaaaaa merged 2 commits into
Emiyaaaaa:mainfrom
cambriayang:feature/sse
Jun 2, 2026
Merged

feat: implement live run synchronization and event handling#18
Emiyaaaaa merged 2 commits into
Emiyaaaaa:mainfrom
cambriayang:feature/sse

Conversation

@cambriayang

Copy link
Copy Markdown
Contributor
  • Introduced live synchronization for runs using SSE, allowing real-time updates in the runs list and detail pages.
  • Enhanced the RunsPage component to display live run status and update frequency.
  • Updated RunDetailPage to utilize live updates for run events, improving user experience during run execution.
  • Created utility functions for managing run events and live synchronization logic in the new useRunLiveSync and useRunEventSource hooks.
  • Refactored EventStream component to handle event streaming more efficiently and display connection status.

- Introduced live synchronization for runs using SSE, allowing real-time updates in the runs list and detail pages.
- Enhanced the RunsPage component to display live run status and update frequency.
- Updated RunDetailPage to utilize live updates for run events, improving user experience during run execution.
- Created utility functions for managing run events and live synchronization logic in the new useRunLiveSync and useRunEventSource hooks.
- Refactored EventStream component to handle event streaming more efficiently and display connection status.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Replaces the polling-based run list/detail refresh with a live SSE-backed synchronization layer. A reusable run-event connection helper is extracted from EventStream, and new hooks merge SSE events into the React Query cache for both the runs list and the run detail page.

Changes:

  • New run-event-connection.ts (SSE connection with reconnect/backoff and status reporting) and run-events.ts (event reducers: applyRunEvent, patchRunInList, terminal/live helpers).
  • New useRunEventSource / useMultiRunEventSource / useRunWithLiveUpdates / useRunsListLiveSync hooks plus a useDebouncedCallback utility.
  • RunsPage and RunDetailPage switch from refetchInterval polling to live SSE updates; EventStream becomes a presentational component receiving events and status as props.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/lib/run-event-connection.ts New EventSource wrapper with status callbacks, manual reconnect/backoff, and terminal handling.
frontend/lib/run-events.ts Event constants and pure reducers that fold SSE events into Run snapshots and list rows.
frontend/lib/useRunEventSource.ts Hooks wrapping the connection helper for single-run and multi-run subscriptions.
frontend/lib/useRunLiveSync.ts Higher-level hooks integrating SSE events with React Query caches plus a debounced reconcile.
frontend/lib/useDebouncedCallback.ts Generic debounce hook with a cancel method, used to coalesce reconciles.
frontend/components/EventStream.tsx Refactored to a stateless presentational component driven by events/status props.
frontend/app/runs/page.tsx Drops 3s polling, derives live run IDs, subscribes via useRunsListLiveSync, updates header label.
frontend/app/runs/[id]/page.tsx Replaces polling useQuery with useRunWithLiveUpdates; removes terminal-invalidation prop on EventStream.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +102
const runKey = runIds.slice().sort().join(",");

useEffect(() => {
if (!runKey) return;

const ids = runKey.split(",");
const connections = ids.map((runId) =>
createRunEventConnection(runId, {
onEvent: (event) => {
onEventRef.current?.(event);
},
onTerminal: (event) => {
onTerminalRef.current?.(event);
},
}),
);

return () => {
connections.forEach((connection) => connection.close());
};
}, [runKey]);
Comment on lines +165 to +193
function patchToolCall(
step: Step,
data: Record<string, unknown>,
at: string,
): Step {
const name = typeof data.name === "string" ? data.name : "";
const toolCalls = [...step.tool_calls];
let index = toolCalls.findIndex((call) => call.name === name);
if (index === -1) {
toolCalls.push(appendToolCall(step, data));
index = toolCalls.length - 1;
}

toolCalls[index] = {
...toolCalls[index],
result:
"result" in data
? (data.result as Record<string, unknown> | null)
: toolCalls[index].result,
error:
typeof data.error === "string" ? data.error : toolCalls[index].error,
latency_ms:
typeof data.latency_ms === "number"
? data.latency_ms
: toolCalls[index].latency_ms,
};

return { ...step, tool_calls: toolCalls, updated_at: at };
}
Comment thread frontend/lib/run-event-connection.ts Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@Emiyaaaaa Emiyaaaaa merged commit 174e042 into Emiyaaaaa:main Jun 2, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants