fix: finalize session after memory promotion
This commit is contained in:
@@ -125,6 +125,31 @@ test("WIP icon toggles the Model activity panel and shows the streamed text", as
|
||||
expect(screen.getByText(/FIRSTLINE/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("session finalization shows the completion banner and returns to landing", async () => {
|
||||
useSessionStore.getState().resetSession();
|
||||
let finalized = false;
|
||||
server.use(
|
||||
http.post("http://localhost:8787/sessions/:id/resume", () => new HttpResponse(null, { status: 204 })),
|
||||
http.get("http://localhost:8787/sessions", () =>
|
||||
HttpResponse.json(finalized ? [{ ...LIST[0], status: "finalized" }] : LIST)),
|
||||
);
|
||||
wrap();
|
||||
await userEvent.click(await screen.findByText("Attiva uno"));
|
||||
await userEvent.click(await screen.findByRole("button", { name: /resume/i }));
|
||||
// The final turn ends: the session is now finalized on disk and agent_end
|
||||
// arrives — the shell must refetch immediately (not wait for the 10s poll)
|
||||
// and surface the new-session invite.
|
||||
finalized = true;
|
||||
act(() => {
|
||||
useSessionStore.getState().applyEvent({ type: "system_event", event: "agent_end" } as any);
|
||||
});
|
||||
const cta = await screen.findByRole("button", { name: /start a new question/i });
|
||||
expect(screen.getByText(/session completed and finalized/i)).toBeInTheDocument();
|
||||
await userEvent.click(cta);
|
||||
// Landing state: the composer invites a brand-new question.
|
||||
expect(await screen.findByText(/type your question/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("renaming a group reassigns its members via setSessionGroup", async () => {
|
||||
const groupSets: Array<{ id: string; group: string }> = [];
|
||||
server.use(
|
||||
|
||||
@@ -177,9 +177,13 @@ export function AppShell() {
|
||||
// stopSession already does, and this effect must stay side-effect-free on the
|
||||
// backend if the session is already inactive.
|
||||
useEffect(() => {
|
||||
if (lastSystemEvent?.type === "system_event" && (lastSystemEvent as any).event === "session_exit") {
|
||||
stopSession();
|
||||
}
|
||||
if (lastSystemEvent?.type !== "system_event") return;
|
||||
const ev = (lastSystemEvent as any).event;
|
||||
if (ev === "session_exit") stopSession();
|
||||
// The final workflow turn ends with the session already finalized on disk:
|
||||
// refetch now instead of waiting for the 10s poll, so the completed state
|
||||
// (and the new-session invite below the transcript) appears immediately.
|
||||
if (ev === "agent_end") refresh();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [lastSystemEvent]);
|
||||
|
||||
@@ -241,6 +245,17 @@ export function AppShell() {
|
||||
<>
|
||||
<CentralStatus working={working} />
|
||||
<WidgetHost sessionId={activeSessionId} />
|
||||
{finalized && !agentActive && (
|
||||
<div className="rounded-2xl border border-border/80 bg-card p-5 text-center shadow-md">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Session completed and finalized — the SQL and all phase
|
||||
documents are saved.
|
||||
</p>
|
||||
<Button className="mt-3" onClick={startNewSession}>
|
||||
Start a new question
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<EmptyState />
|
||||
|
||||
Reference in New Issue
Block a user