From 27f838f249615a356f3ef65d83ddde0285e6e847 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Wed, 2 Sep 2026 21:12:52 -0400 Subject: [PATCH] fix(client): refresh references for the updated location (#46935) --- packages/app/src/runtime/server/sync.tsx | 2 - packages/client/src/solid/data.ts | 4 +- packages/client/test/solid-data.test.ts | 60 ++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/packages/app/src/runtime/server/sync.tsx b/packages/app/src/runtime/server/sync.tsx index 09dde826df8..d10c4c3658f 100644 --- a/packages/app/src/runtime/server/sync.tsx +++ b/packages/app/src/runtime/server/sync.tsx @@ -230,8 +230,6 @@ export function createServerSyncContextInner(serverSDK: ServerSDK, data: Data) { children.mark(key) if (event.type === "config.updated" || event.type === "agent.updated") queue.push(key) if (event.type === "worktree.updated") void bootstrap.refetch() - if (event.type === "reference.updated" && children.active(key)) - void data.location.reference.sync({ directory: key }).catch(() => undefined) }) onCleanup(unsub) diff --git a/packages/client/src/solid/data.ts b/packages/client/src/solid/data.ts index 75ecaee3dc4..d18de907126 100644 --- a/packages/client/src/solid/data.ts +++ b/packages/client/src/solid/data.ts @@ -1180,8 +1180,8 @@ export function createData(config: CreateDataInput) { })) break case "reference.updated": - result.location.reference.invalidate() - void result.location.reference.sync() + result.location.reference.invalidate(location) + void result.location.reference.sync(location) break case "integration.updated": result.location.integration.invalidate(location) diff --git a/packages/client/test/solid-data.test.ts b/packages/client/test/solid-data.test.ts index 79251e607bb..0743791514d 100644 --- a/packages/client/test/solid-data.test.ts +++ b/packages/client/test/solid-data.test.ts @@ -409,6 +409,66 @@ test("refreshes global credential events across every loaded location and worksp } }) +test("refreshes references for the location an update names", async () => { + const listeners = new Set[0]>() + const requests: URL[] = [] + const api = OpenCode.make({ + baseUrl: "http://opencode.local", + fetch: async (input, init) => { + const request = input instanceof Request ? input : new Request(input, init) + const url = new URL(request.url) + requests.push(url) + const directory = url.searchParams.get("location[directory]") ?? "/project" + return Response.json({ + location: { + directory, + workspaceID: url.searchParams.get("location[workspace]") ?? undefined, + project: { id: "project", directory, canonical: directory }, + }, + data: [], + }) + }, + }) + const setup = createRoot((dispose) => ({ + data: createData({ + api: () => api, + directory: "/project", + event: { + on: () => () => {}, + listen(handler) { + listeners.add(handler) + return () => listeners.delete(handler) + }, + }, + connection: { status: () => "connected" }, + }), + dispose, + })) + const other = { directory: "/other", workspaceID: "workspace-other" } + + try { + await Promise.all([setup.data.location.reference.sync(), setup.data.location.reference.sync(other)]) + requests.length = 0 + + const updated: OpenCodeEvent = { + id: "evt_reference.updated", + created: 1, + type: "reference.updated", + location: other, + data: {}, + } + listeners.forEach((listener) => listener({ name: updated.type, details: updated })) + await wait(() => requests.length === 1) + expect([ + requests[0]!.pathname, + requests[0]!.searchParams.get("location[directory]"), + requests[0]!.searchParams.get("location[workspace]"), + ]).toEqual(["/api/reference", "/other", "workspace-other"]) + } finally { + setup.dispose() + } +}) + test("reports optimistic sessions as creating until the request settles", async () => { const release = Promise.withResolvers() const api = OpenCode.make({