From 9c54291ae8d6e6dbeb4a9acaf7d16ff040881234 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Tue, 7 Jul 2026 22:47:13 +0000 Subject: [PATCH] fix(tui): restore forms on reconnect Co-authored-by: opencode-agent[bot] --- packages/tui/src/context/data.tsx | 10 ++++++ packages/tui/test/cli/tui/data.test.tsx | 46 +++++++++++++++++++++++++ packages/tui/test/fixture/tui-sdk.ts | 2 ++ 3 files changed, 58 insertions(+) diff --git a/packages/tui/src/context/data.tsx b/packages/tui/src/context/data.tsx index 0a03f81549..7b15781ffc 100644 --- a/packages/tui/src/context/data.tsx +++ b/packages/tui/src/context/data.tsx @@ -1074,6 +1074,16 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ ) setStore("session", "permission", reconcile(permissions)) }), + sdk.api.form.listRequests({ location: locationQuery(defaultLocation()) }).then((response) => { + const forms = mutable(response.data).reduce>( + (result, form) => ({ + ...result, + [form.sessionID]: [...(result[form.sessionID] ?? []), form], + }), + {}, + ) + setStore("session", "form", reconcile(forms)) + }), result.location.refresh(), result.location.agent.refresh(), result.location.integration.refresh(), diff --git a/packages/tui/test/cli/tui/data.test.tsx b/packages/tui/test/cli/tui/data.test.tsx index 480dcbbec7..fdd5980fb5 100644 --- a/packages/tui/test/cli/tui/data.test.tsx +++ b/packages/tui/test/cli/tui/data.test.tsx @@ -1637,6 +1637,52 @@ test("adds, dismisses, and refreshes form requests", async () => { } }) +test("reconciles all pending form requests when the event stream reconnects", async () => { + const events = createEventStream() + let requests = [ + { id: "frm_old", sessionID: "ses_old", mode: "form" as const, fields: [] }, + { id: "frm_keep", sessionID: "ses_keep", mode: "url" as const, url: "https://example.com" }, + ] + let calls = 0 + const fetch = createFetch((url) => { + if (url.pathname !== "/api/form/request") return + calls++ + return json({ location: { directory, project: { id: "proj_test", directory } }, data: requests }) + }, events) + let data!: ReturnType + + function Probe() { + data = useData() + return + } + + const app = await testRender(() => ( + + + + + + + + + + )) + + try { + await wait(() => data.session.form.list("ses_old")?.[0]?.id === "frm_old") + expect(data.session.form.list("ses_keep")?.[0]?.id).toBe("frm_keep") + + requests = [{ id: "frm_new", sessionID: "ses_new", mode: "form" as const, fields: [] }] + events.disconnect() + + await wait(() => calls === 2 && data.session.form.list("ses_new")?.[0]?.id === "frm_new") + expect(data.session.form.list("ses_old")).toBeUndefined() + expect(data.session.form.list("ses_keep")).toBeUndefined() + } finally { + app.renderer.destroy() + } +}) + test("settles pending tools when a live failure arrives", async () => { const events = createEventStream() const calls = createFetch((url) => { diff --git a/packages/tui/test/fixture/tui-sdk.ts b/packages/tui/test/fixture/tui-sdk.ts index 5752009911..2c10ed43a2 100644 --- a/packages/tui/test/fixture/tui-sdk.ts +++ b/packages/tui/test/fixture/tui-sdk.ts @@ -103,6 +103,8 @@ export function createFetch(override?: FetchHandler, events?: ReturnType