Skip to content

Commit d4b85f8

Browse files
authored
fix(app): skip legacy config reads for v2 (#40211)
1 parent 1882c33 commit d4b85f8

3 files changed

Lines changed: 103 additions & 6 deletions

File tree

packages/app/src/context/global-sync/bootstrap.test.ts

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
bootstrapDirectory,
99
loadAgentsQuery,
1010
loadCommands,
11+
loadGlobalConfigQuery,
1112
loadPathQuery,
1213
loadProjectsQuery,
1314
loadProvidersQuery,
@@ -76,6 +77,7 @@ function directoryState() {
7677

7778
describe("bootstrapDirectory", () => {
7879
test("uses legacy MCP endpoints while refreshing a v1 directory", async () => {
80+
const legacyConfigReads: string[] = []
7981
const mcpReads: string[] = []
8082
const [store, setStore] = directoryState()
8183

@@ -91,7 +93,12 @@ describe("bootstrapDirectory", () => {
9193
},
9294
sdk: {
9395
app: { agents: async () => ({ data: [{ name: "build", mode: "primary" }] }) },
94-
config: { get: async () => ({ data: {} }) },
96+
config: {
97+
get: async () => {
98+
legacyConfigReads.push("directory")
99+
return { data: {} }
100+
},
101+
},
95102
session: { status: async () => ({ data: {} }) },
96103
vcs: { get: async () => ({ data: undefined }) },
97104
command: {
@@ -134,8 +141,88 @@ describe("bootstrapDirectory", () => {
134141
await new Promise((resolve) => setTimeout(resolve, 80))
135142

136143
expect(store.status).toBe("complete")
144+
expect(legacyConfigReads).toEqual(["directory"])
137145
expect(mcpReads.sort()).toEqual(["command", "resource", "status"])
138146
})
147+
148+
test("skips legacy config while refreshing a v2 directory", async () => {
149+
const [store, setStore] = directoryState()
150+
151+
await bootstrapDirectory({
152+
directory: "/project",
153+
scope: ServerScope.local,
154+
mcp: false,
155+
global: {
156+
config: {} satisfies Config,
157+
path: { state: "", config: "", worktree: "/project", directory: "/project", home: "/home" },
158+
project: [{ id: "project", worktree: "/project" } as Project],
159+
provider,
160+
},
161+
sdk: {
162+
config: {
163+
get: async () => {
164+
throw new Error("legacy directory config should not be called")
165+
},
166+
},
167+
} as unknown as OpencodeClient,
168+
api,
169+
store,
170+
setStore,
171+
vcsCache: { setStore() {} } as unknown as VcsCache,
172+
loadSessions() {},
173+
translate: (key) => key,
174+
queryClient: new QueryClient(),
175+
protocol: Promise.resolve("v2"),
176+
})
177+
178+
expect(store.status).toBe("partial")
179+
180+
await new Promise((resolve) => setTimeout(resolve, 80))
181+
182+
expect(store.status).toBe("complete")
183+
})
184+
})
185+
186+
describe("config queries", () => {
187+
test("skips legacy global config for v2 servers", async () => {
188+
const sdk = {
189+
global: {
190+
config: {
191+
get: async () => {
192+
throw new Error("legacy global config should not be called")
193+
},
194+
},
195+
},
196+
} as unknown as OpencodeClient
197+
198+
const result = await new QueryClient().fetchQuery(
199+
loadGlobalConfigQuery(ServerScope.local, sdk, Promise.resolve("v2")),
200+
)
201+
202+
expect(result).toEqual({})
203+
})
204+
205+
test("loads legacy global config for v1 servers", async () => {
206+
const calls: string[] = []
207+
const config = { shell: "zsh" } satisfies Config
208+
const sdk = {
209+
global: {
210+
config: {
211+
get: async () => {
212+
calls.push("global")
213+
return { data: config }
214+
},
215+
},
216+
},
217+
} as unknown as OpencodeClient
218+
219+
const result = await new QueryClient().fetchQuery(
220+
loadGlobalConfigQuery(ServerScope.local, sdk, Promise.resolve("v1")),
221+
)
222+
223+
expect(result).toEqual(config)
224+
expect(calls).toEqual(["global"])
225+
})
139226
})
140227

141228
describe("query keys", () => {

packages/app/src/context/global-sync/bootstrap.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,17 @@ function showErrors(input: {
105105
})
106106
}
107107

108-
export const loadGlobalConfigQuery = (scope: ServerScope, sdk: OpencodeClient) =>
108+
export const loadGlobalConfigQuery = (
109+
scope: ServerScope,
110+
sdk: OpencodeClient,
111+
protocol?: Promise<ServerProtocol>,
112+
) =>
109113
queryOptions({
110114
queryKey: [scope, "config"],
111-
queryFn: () => retry(() => sdk.global.config.get().then((x) => x.data!)),
115+
queryFn: async () => {
116+
if ((await protocol) !== "v1") return {}
117+
return retry(() => sdk.global.config.get().then((x) => x.data!))
118+
},
112119
})
113120

114121
type ProjectApi = {
@@ -149,7 +156,7 @@ export async function bootstrapGlobal(input: {
149156
queryClient: QueryClient
150157
}) {
151158
const slow = [
152-
() => input.queryClient.fetchQuery(loadGlobalConfigQuery(input.scope, input.serverSDK)),
159+
() => input.queryClient.fetchQuery(loadGlobalConfigQuery(input.scope, input.serverSDK, input.protocol)),
153160
() =>
154161
input.queryClient.fetchQuery(
155162
loadProvidersQuery(input.scope, null, input.serverAPI, input.serverSDK, input.protocol),
@@ -376,7 +383,10 @@ export async function bootstrapDirectory(input: {
376383
.ensureQueryData(loadAgentsQuery(input.scope, input.directory, input.api.agent, input.sdk, input.protocol))
377384
.then((data) => input.setStore("agent", data)),
378385
() =>
379-
retry(() => input.sdk.config.get().then((x) => input.setStore("config", reconcile(x.data!, { merge: false })))),
386+
retry(async () => {
387+
if ((await input.protocol) !== "v1") return
388+
return input.sdk.config.get().then((x) => input.setStore("config", reconcile(x.data!, { merge: false })))
389+
}),
380390
() =>
381391
retry(() =>
382392
(async () => {

packages/app/src/context/server-sync.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ function makeQueryOptionsApi(
184184
protocol: Promise<"v1" | "v2">,
185185
) {
186186
return {
187-
globalConfig: () => loadGlobalConfigQuery(scope, serverSDK()),
187+
globalConfig: () => loadGlobalConfigQuery(scope, serverSDK(), protocol),
188188
projects: () => loadProjectsQuery(scope, serverAPI.project),
189189
providers: (directory: PathKey | null) =>
190190
loadProvidersQuery(scope, directory, serverAPI, directory ? sdkFor(directory) : serverSDK(), protocol),

0 commit comments

Comments
 (0)