diff --git a/src/plugin-config.ts b/src/plugin-config.ts index 78350cfda..b7e8ff72a 100644 --- a/src/plugin-config.ts +++ b/src/plugin-config.ts @@ -177,6 +177,13 @@ export function loadPluginConfig( ? userDetected.path : path.join(configDir, "oh-my-opencode.json"); + if (userDetected.legacyPath) { + log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", { + canonicalPath: userDetected.path, + legacyPath: userDetected.legacyPath, + }); + } + // Auto-copy legacy config file to canonical name if needed if (userDetected.format !== "none" && path.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) { migrateLegacyConfigFile(userDetected.path); @@ -190,6 +197,13 @@ export function loadPluginConfig( ? projectDetected.path : path.join(projectBasePath, "oh-my-opencode.json"); + if (projectDetected.legacyPath) { + log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", { + canonicalPath: projectDetected.path, + legacyPath: projectDetected.legacyPath, + }); + } + // Auto-copy legacy project config file to canonical name if needed if (projectDetected.format !== "none" && path.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) { migrateLegacyConfigFile(projectDetected.path); diff --git a/src/shared/jsonc-parser.test.ts b/src/shared/jsonc-parser.test.ts index 54c529399..26c0914e2 100644 --- a/src/shared/jsonc-parser.test.ts +++ b/src/shared/jsonc-parser.test.ts @@ -268,7 +268,7 @@ describe("detectConfigFile", () => { describe("detectPluginConfigFile", () => { const testDir = join(__dirname, ".test-detect-plugin") - test("prefers oh-my-opencode over oh-my-openagent", () => { + test("prefers oh-my-openagent over oh-my-opencode when both jsonc files exist", () => { // given if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true }) writeFileSync(join(testDir, "oh-my-openagent.jsonc"), "{}") @@ -279,7 +279,8 @@ describe("detectPluginConfigFile", () => { // then expect(result.format).toBe("jsonc") - expect(result.path).toBe(join(testDir, "oh-my-opencode.jsonc")) + expect(result.path).toBe(join(testDir, "oh-my-openagent.jsonc")) + expect(result.legacyPath).toBe(join(testDir, "oh-my-opencode.jsonc")) rmSync(testDir, { recursive: true, force: true }) }) @@ -295,13 +296,15 @@ describe("detectPluginConfigFile", () => { // then expect(result.format).toBe("jsonc") expect(result.path).toBe(join(testDir, "oh-my-opencode.jsonc")) + expect(result.legacyPath).toBeUndefined() rmSync(testDir, { recursive: true, force: true }) }) - test("falls back to oh-my-opencode.json when no jsonc exists", () => { + test("loads oh-my-openagent.json before oh-my-opencode.json when no jsonc exists", () => { // given if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true }) + writeFileSync(join(testDir, "oh-my-openagent.json"), "{}") writeFileSync(join(testDir, "oh-my-opencode.json"), "{}") // when @@ -309,7 +312,8 @@ describe("detectPluginConfigFile", () => { // then expect(result.format).toBe("json") - expect(result.path).toBe(join(testDir, "oh-my-opencode.json")) + expect(result.path).toBe(join(testDir, "oh-my-openagent.json")) + expect(result.legacyPath).toBe(join(testDir, "oh-my-opencode.json")) rmSync(testDir, { recursive: true, force: true }) }) @@ -324,12 +328,12 @@ describe("detectPluginConfigFile", () => { // then expect(result.format).toBe("none") - expect(result.path).toBe(join(emptyDir, "oh-my-opencode.json")) + expect(result.path).toBe(join(emptyDir, "oh-my-openagent.json")) rmSync(testDir, { recursive: true, force: true }) }) - test("prefers oh-my-opencode.json over oh-my-openagent.jsonc", () => { + test("prefers canonical jsonc over legacy json when both exist", () => { // given if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true }) writeFileSync(join(testDir, "oh-my-opencode.json"), "{}") @@ -339,8 +343,25 @@ describe("detectPluginConfigFile", () => { const result = detectPluginConfigFile(testDir) // then - expect(result.format).toBe("json") - expect(result.path).toBe(join(testDir, "oh-my-opencode.json")) + expect(result.format).toBe("jsonc") + expect(result.path).toBe(join(testDir, "oh-my-openagent.jsonc")) + expect(result.legacyPath).toBe(join(testDir, "oh-my-opencode.json")) + + rmSync(testDir, { recursive: true, force: true }) + }) + + test("loads oh-my-openagent when only canonical jsonc exists", () => { + // given + if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true }) + writeFileSync(join(testDir, "oh-my-openagent.jsonc"), "{}") + + // when + const result = detectPluginConfigFile(testDir) + + // then + expect(result.format).toBe("jsonc") + expect(result.path).toBe(join(testDir, "oh-my-openagent.jsonc")) + expect(result.legacyPath).toBeUndefined() rmSync(testDir, { recursive: true, force: true }) }) diff --git a/src/shared/jsonc-parser.ts b/src/shared/jsonc-parser.ts index 7431ad9a2..66c886310 100644 --- a/src/shared/jsonc-parser.ts +++ b/src/shared/jsonc-parser.ts @@ -2,6 +2,8 @@ import { existsSync, readFileSync } from "node:fs" import { join } from "node:path" import { parse, ParseError, printParseErrorCode } from "jsonc-parser" +import { CONFIG_BASENAME, LEGACY_CONFIG_BASENAME } from "./plugin-identity" + export interface JsoncParseResult { data: T | null errors: Array<{ message: string; offset: number; length: number }> @@ -66,15 +68,24 @@ export function detectConfigFile(basePath: string): { return { format: "none", path: jsonPath } } -const PLUGIN_CONFIG_NAMES = ["oh-my-opencode", "oh-my-openagent"] as const - export function detectPluginConfigFile(dir: string): { format: "json" | "jsonc" | "none" path: string + legacyPath?: string } { - for (const name of PLUGIN_CONFIG_NAMES) { - const result = detectConfigFile(join(dir, name)) - if (result.format !== "none") return result + const canonicalResult = detectConfigFile(join(dir, CONFIG_BASENAME)) + const legacyResult = detectConfigFile(join(dir, LEGACY_CONFIG_BASENAME)) + + if (canonicalResult.format !== "none") { + return { + ...canonicalResult, + legacyPath: legacyResult.format !== "none" ? legacyResult.path : undefined, + } } - return { format: "none", path: join(dir, PLUGIN_CONFIG_NAMES[0] + ".json") } + + if (legacyResult.format !== "none") { + return legacyResult + } + + return { format: "none", path: join(dir, `${CONFIG_BASENAME}.json`) } } diff --git a/src/shared/plugin-config-detection.test.ts b/src/shared/plugin-config-detection.test.ts deleted file mode 100644 index 34ad9b434..000000000 --- a/src/shared/plugin-config-detection.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { describe, expect, test } from "bun:test" -import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs" -import { join } from "node:path" -import { detectPluginConfigFile } from "./jsonc-parser" - -describe("detectPluginConfigFile - canonical config detection", () => { - const testDir = join(__dirname, ".test-detect-plugin-canonical") - - test("detects oh-my-openagent config when no legacy config exists", () => { - //#given - if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true }) - writeFileSync(join(testDir, "oh-my-openagent.jsonc"), "{}") - - //#when - const result = detectPluginConfigFile(testDir) - - //#then - expect(result.format).toBe("jsonc") - expect(result.path).toBe(join(testDir, "oh-my-openagent.jsonc")) - - rmSync(testDir, { recursive: true, force: true }) - }) -})