Forráskód Böngészése

fix(app): skip legacy config reads for v2 (#40211)

twinkle 1 hete
szülő
commit
d4b85f8d83

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

@@ -8,6 +8,7 @@ import {
   bootstrapDirectory,
   loadAgentsQuery,
   loadCommands,
+  loadGlobalConfigQuery,
   loadPathQuery,
   loadProjectsQuery,
   loadProvidersQuery,
@@ -76,6 +77,7 @@ function directoryState() {
 
 describe("bootstrapDirectory", () => {
   test("uses legacy MCP endpoints while refreshing a v1 directory", async () => {
+    const legacyConfigReads: string[] = []
     const mcpReads: string[] = []
     const [store, setStore] = directoryState()
 
@@ -91,7 +93,12 @@ describe("bootstrapDirectory", () => {
       },
       sdk: {
         app: { agents: async () => ({ data: [{ name: "build", mode: "primary" }] }) },
-        config: { get: async () => ({ data: {} }) },
+        config: {
+          get: async () => {
+            legacyConfigReads.push("directory")
+            return { data: {} }
+          },
+        },
         session: { status: async () => ({ data: {} }) },
         vcs: { get: async () => ({ data: undefined }) },
         command: {
@@ -134,8 +141,88 @@ describe("bootstrapDirectory", () => {
     await new Promise((resolve) => setTimeout(resolve, 80))
 
     expect(store.status).toBe("complete")
+    expect(legacyConfigReads).toEqual(["directory"])
     expect(mcpReads.sort()).toEqual(["command", "resource", "status"])
   })
+
+  test("skips legacy config while refreshing a v2 directory", async () => {
+    const [store, setStore] = directoryState()
+
+    await bootstrapDirectory({
+      directory: "/project",
+      scope: ServerScope.local,
+      mcp: false,
+      global: {
+        config: {} satisfies Config,
+        path: { state: "", config: "", worktree: "/project", directory: "/project", home: "/home" },
+        project: [{ id: "project", worktree: "/project" } as Project],
+        provider,
+      },
+      sdk: {
+        config: {
+          get: async () => {
+            throw new Error("legacy directory config should not be called")
+          },
+        },
+      } as unknown as OpencodeClient,
+      api,
+      store,
+      setStore,
+      vcsCache: { setStore() {} } as unknown as VcsCache,
+      loadSessions() {},
+      translate: (key) => key,
+      queryClient: new QueryClient(),
+      protocol: Promise.resolve("v2"),
+    })
+
+    expect(store.status).toBe("partial")
+
+    await new Promise((resolve) => setTimeout(resolve, 80))
+
+    expect(store.status).toBe("complete")
+  })
+})
+
+describe("config queries", () => {
+  test("skips legacy global config for v2 servers", async () => {
+    const sdk = {
+      global: {
+        config: {
+          get: async () => {
+            throw new Error("legacy global config should not be called")
+          },
+        },
+      },
+    } as unknown as OpencodeClient
+
+    const result = await new QueryClient().fetchQuery(
+      loadGlobalConfigQuery(ServerScope.local, sdk, Promise.resolve("v2")),
+    )
+
+    expect(result).toEqual({})
+  })
+
+  test("loads legacy global config for v1 servers", async () => {
+    const calls: string[] = []
+    const config = { shell: "zsh" } satisfies Config
+    const sdk = {
+      global: {
+        config: {
+          get: async () => {
+            calls.push("global")
+            return { data: config }
+          },
+        },
+      },
+    } as unknown as OpencodeClient
+
+    const result = await new QueryClient().fetchQuery(
+      loadGlobalConfigQuery(ServerScope.local, sdk, Promise.resolve("v1")),
+    )
+
+    expect(result).toEqual(config)
+    expect(calls).toEqual(["global"])
+  })
 })
 
 describe("query keys", () => {

+ 14 - 4
packages/app/src/context/global-sync/bootstrap.ts

@@ -105,10 +105,17 @@ function showErrors(input: {
   })
 }
 
-export const loadGlobalConfigQuery = (scope: ServerScope, sdk: OpencodeClient) =>
+export const loadGlobalConfigQuery = (
+  scope: ServerScope,
+  sdk: OpencodeClient,
+  protocol?: Promise<ServerProtocol>,
+) =>
   queryOptions({
     queryKey: [scope, "config"],
-    queryFn: () => retry(() => sdk.global.config.get().then((x) => x.data!)),
+    queryFn: async () => {
+      if ((await protocol) !== "v1") return {}
+      return retry(() => sdk.global.config.get().then((x) => x.data!))
+    },
   })
 
 type ProjectApi = {
@@ -149,7 +156,7 @@ export async function bootstrapGlobal(input: {
   queryClient: QueryClient
 }) {
   const slow = [
-    () => input.queryClient.fetchQuery(loadGlobalConfigQuery(input.scope, input.serverSDK)),
+    () => input.queryClient.fetchQuery(loadGlobalConfigQuery(input.scope, input.serverSDK, input.protocol)),
     () =>
       input.queryClient.fetchQuery(
         loadProvidersQuery(input.scope, null, input.serverAPI, input.serverSDK, input.protocol),
@@ -376,7 +383,10 @@ export async function bootstrapDirectory(input: {
           .ensureQueryData(loadAgentsQuery(input.scope, input.directory, input.api.agent, input.sdk, input.protocol))
           .then((data) => input.setStore("agent", data)),
       () =>
-        retry(() => input.sdk.config.get().then((x) => input.setStore("config", reconcile(x.data!, { merge: false })))),
+        retry(async () => {
+          if ((await input.protocol) !== "v1") return
+          return input.sdk.config.get().then((x) => input.setStore("config", reconcile(x.data!, { merge: false })))
+        }),
       () =>
         retry(() =>
           (async () => {

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

@@ -184,7 +184,7 @@ function makeQueryOptionsApi(
   protocol: Promise<"v1" | "v2">,
 ) {
   return {
-    globalConfig: () => loadGlobalConfigQuery(scope, serverSDK()),
+    globalConfig: () => loadGlobalConfigQuery(scope, serverSDK(), protocol),
     projects: () => loadProjectsQuery(scope, serverAPI.project),
     providers: (directory: PathKey | null) =>
       loadProvidersQuery(scope, directory, serverAPI, directory ? sdkFor(directory) : serverSDK(), protocol),