diff --git a/packages/cli-workflow/src/commands/serve/routes-live.ts b/packages/cli-workflow/src/commands/serve/routes-live.ts index 4fbc5b5..9cdd271 100644 --- a/packages/cli-workflow/src/commands/serve/routes-live.ts +++ b/packages/cli-workflow/src/commands/serve/routes-live.ts @@ -310,6 +310,12 @@ export function createLiveRoutes(storageRoot: string): Hono { // If thread is not actively running, emit all records and close — don't keep SSE open const runningPath = join(storageRoot, "logs", threadTarget.bundleHash, `${threadId}.running`); if (!existsSync(runningPath)) { + eventId.n++; + await stream.writeSSE({ + event: "done", + data: JSON.stringify({ reason: "not-running" }), + id: String(eventId.n), + }); return; } diff --git a/packages/workflow-dashboard/src/use-sse.ts b/packages/workflow-dashboard/src/use-sse.ts index d65ae83..267b4cd 100644 --- a/packages/workflow-dashboard/src/use-sse.ts +++ b/packages/workflow-dashboard/src/use-sse.ts @@ -148,6 +148,16 @@ export function useSSE(agent: string | null, threadId: string | null): UseSSERet }), ); + es.addEventListener("done", () => { + if (cancelled) { + return; + } + completedRef.current = true; + setCompleted(true); + setConnected(false); + cleanupEs(); + }); + es.onerror = () => { if (cancelled || completedRef.current) { return;