fix(tui): restore forms on reconnect
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
parent
52ad916ba4
commit
9c54291ae8
@@ -1074,6 +1074,16 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||||||
)
|
)
|
||||||
setStore("session", "permission", reconcile(permissions))
|
setStore("session", "permission", reconcile(permissions))
|
||||||
}),
|
}),
|
||||||
|
sdk.api.form.listRequests({ location: locationQuery(defaultLocation()) }).then((response) => {
|
||||||
|
const forms = mutable(response.data).reduce<Record<string, FormInfo[]>>(
|
||||||
|
(result, form) => ({
|
||||||
|
...result,
|
||||||
|
[form.sessionID]: [...(result[form.sessionID] ?? []), form],
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
setStore("session", "form", reconcile(forms))
|
||||||
|
}),
|
||||||
result.location.refresh(),
|
result.location.refresh(),
|
||||||
result.location.agent.refresh(),
|
result.location.agent.refresh(),
|
||||||
result.location.integration.refresh(),
|
result.location.integration.refresh(),
|
||||||
|
|||||||
@@ -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<typeof useData>
|
||||||
|
|
||||||
|
function Probe() {
|
||||||
|
data = useData()
|
||||||
|
return <box />
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = await testRender(() => (
|
||||||
|
<TestTuiContexts>
|
||||||
|
<SDKProvider client={createClient(fetch.fetch)} api={createApi(fetch.fetch)}>
|
||||||
|
<ProjectProvider>
|
||||||
|
<DataProvider>
|
||||||
|
<Probe />
|
||||||
|
</DataProvider>
|
||||||
|
</ProjectProvider>
|
||||||
|
</SDKProvider>
|
||||||
|
</TestTuiContexts>
|
||||||
|
))
|
||||||
|
|
||||||
|
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 () => {
|
test("settles pending tools when a live failure arrives", async () => {
|
||||||
const events = createEventStream()
|
const events = createEventStream()
|
||||||
const calls = createFetch((url) => {
|
const calls = createFetch((url) => {
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ export function createFetch(override?: FetchHandler, events?: ReturnType<typeof
|
|||||||
if (url.pathname === "/api/session/active") return json({ data: {} })
|
if (url.pathname === "/api/session/active") return json({ data: {} })
|
||||||
if (url.pathname === "/api/permission/request")
|
if (url.pathname === "/api/permission/request")
|
||||||
return json({ location: { directory, project: { id: "proj_test", directory: worktree } }, data: [] })
|
return json({ location: { directory, project: { id: "proj_test", directory: worktree } }, data: [] })
|
||||||
|
if (url.pathname === "/api/form/request")
|
||||||
|
return json({ location: { directory, project: { id: "proj_test", directory: worktree } }, data: [] })
|
||||||
if (/^\/api\/session\/[^/]+\/form$/.test(url.pathname)) return json({ data: [] })
|
if (/^\/api\/session\/[^/]+\/form$/.test(url.pathname)) return json({ data: [] })
|
||||||
if (
|
if (
|
||||||
["/api/agent", "/api/model", "/api/provider", "/api/integration", "/api/command", "/api/skill"].includes(
|
["/api/agent", "/api/model", "/api/provider", "/api/integration", "/api/command", "/api/skill"].includes(
|
||||||
|
|||||||
Reference in New Issue
Block a user