From dd17b4c7178b3c089790ad64cde00b8e5bd8f95f Mon Sep 17 00:00:00 2001 From: MumuTW Date: Fri, 6 Mar 2026 05:44:29 +0000 Subject: [PATCH 1/3] fix(core): read local profile title from global config name --- core/config/profile/LocalProfileLoader.ts | 23 +++++--- .../profile/LocalProfileLoader.vitest.ts | 53 +++++++++++++++++++ 2 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 core/config/profile/LocalProfileLoader.vitest.ts diff --git a/core/config/profile/LocalProfileLoader.ts b/core/config/profile/LocalProfileLoader.ts index 9c57ae94c9c..9534504a4b4 100644 --- a/core/config/profile/LocalProfileLoader.ts +++ b/core/config/profile/LocalProfileLoader.ts @@ -1,4 +1,5 @@ import { ConfigResult, parseConfigYaml } from "@continuedev/config-yaml"; +import fs from "node:fs"; import { ControlPlaneClient } from "../../control-plane/client.js"; import { ContinueConfig, IDE, ILLMLogger } from "../../index.js"; @@ -21,6 +22,7 @@ export default class LocalProfileLoader implements IProfileLoader { | { path: string; content: string } | undefined, ) { + const defaultTitle = "Local Config"; const description: ProfileDescription = { id: overrideAssistantFile?.path ?? LocalProfileLoader.ID, profileType: "local", @@ -32,7 +34,7 @@ export default class LocalProfileLoader implements IProfileLoader { iconUrl: "", title: overrideAssistantFile?.path ? getUriPathBasename(overrideAssistantFile.path) - : "Local Config", + : defaultTitle, errors: undefined, uri: overrideAssistantFile?.path ?? @@ -40,12 +42,21 @@ export default class LocalProfileLoader implements IProfileLoader { rawYaml: undefined, }; this.description = description; - if (overrideAssistantFile?.content) { + let configContent = overrideAssistantFile?.content; + if (!configContent) { try { - const parsedAssistant = parseConfigYaml( - overrideAssistantFile?.content ?? "", - ); - this.description.title = parsedAssistant.name; + configContent = fs.readFileSync(getPrimaryConfigFilePath(), "utf8"); + } catch (e) { + console.error("Failed to read config file: ", e); + } + } + if (configContent) { + try { + const parsedAssistant = parseConfigYaml(configContent); + this.description.title = + parsedAssistant.name?.trim() || + this.description.title || + defaultTitle; } catch (e) { console.error("Failed to parse config file: ", e); } diff --git a/core/config/profile/LocalProfileLoader.vitest.ts b/core/config/profile/LocalProfileLoader.vitest.ts new file mode 100644 index 00000000000..be24a229ab7 --- /dev/null +++ b/core/config/profile/LocalProfileLoader.vitest.ts @@ -0,0 +1,53 @@ +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +import { afterEach, describe, expect, it, vi } from "vitest"; + +async function createLoader(configYaml?: string) { + const tempDir = fs.mkdtempSync( + path.join(os.tmpdir(), "continue-local-profile-loader-"), + ); + process.env.CONTINUE_GLOBAL_DIR = tempDir; + + if (configYaml !== undefined) { + fs.writeFileSync(path.join(tempDir, "config.yaml"), configYaml); + } + + vi.resetModules(); + const { default: LocalProfileLoader } = await import("./LocalProfileLoader"); + + return { + tempDir, + loader: new LocalProfileLoader({} as any, {} as any, {} as any), + }; +} + +afterEach(() => { + delete process.env.CONTINUE_GLOBAL_DIR; + vi.restoreAllMocks(); +}); + +describe("LocalProfileLoader", () => { + it("uses name from default local config.yaml for the profile title", async () => { + const { loader, tempDir } = await createLoader( + "name: Custom Local Profile", + ); + expect(loader.description.title).toBe("Custom Local Profile"); + fs.rmSync(tempDir, { recursive: true, force: true }); + }); + + it("falls back to Local Config when default config.yaml is malformed", async () => { + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + const { loader, tempDir } = await createLoader("name: ["); + expect(loader.description.title).toBe("Local Config"); + expect(errorSpy).toHaveBeenCalled(); + fs.rmSync(tempDir, { recursive: true, force: true }); + }); + + it("falls back to Local Config when name is missing", async () => { + const { loader, tempDir } = await createLoader("models: []"); + expect(loader.description.title).toBe("Local Config"); + fs.rmSync(tempDir, { recursive: true, force: true }); + }); +}); From e2dc0b30b0c48ab9f9a0cfbda50c620996c0a040 Mon Sep 17 00:00:00 2001 From: MumuTW Date: Fri, 6 Mar 2026 09:52:14 +0000 Subject: [PATCH 2/3] fix: include required version field in LocalProfileLoader test config The configYamlSchema requires both name and version fields. The test only provided name, causing parseConfigYaml to reject the config and falling back to the default "Local Config" title. Co-Authored-By: Claude Opus 4.6 --- core/config/profile/LocalProfileLoader.vitest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/config/profile/LocalProfileLoader.vitest.ts b/core/config/profile/LocalProfileLoader.vitest.ts index be24a229ab7..924e8254c45 100644 --- a/core/config/profile/LocalProfileLoader.vitest.ts +++ b/core/config/profile/LocalProfileLoader.vitest.ts @@ -31,7 +31,7 @@ afterEach(() => { describe("LocalProfileLoader", () => { it("uses name from default local config.yaml for the profile title", async () => { const { loader, tempDir } = await createLoader( - "name: Custom Local Profile", + "name: Custom Local Profile\nversion: '1.0'", ); expect(loader.description.title).toBe("Custom Local Profile"); fs.rmSync(tempDir, { recursive: true, force: true }); From ac7cc6648b6ffbe887f3bee96a37375a36efa924 Mon Sep 17 00:00:00 2001 From: MumuTW Date: Sat, 7 Mar 2026 13:17:23 +0000 Subject: [PATCH 3/3] fix: use strict undefined check for override content fallback An empty override file should not fall back to global config. Co-Authored-By: Claude Opus 4.6 --- core/config/profile/LocalProfileLoader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/config/profile/LocalProfileLoader.ts b/core/config/profile/LocalProfileLoader.ts index 9534504a4b4..bfd4473dc0d 100644 --- a/core/config/profile/LocalProfileLoader.ts +++ b/core/config/profile/LocalProfileLoader.ts @@ -43,7 +43,7 @@ export default class LocalProfileLoader implements IProfileLoader { }; this.description = description; let configContent = overrideAssistantFile?.content; - if (!configContent) { + if (configContent === undefined) { try { configContent = fs.readFileSync(getPrimaryConfigFilePath(), "utf8"); } catch (e) {