Merge pull request #3055 from code-yeongyu/fix/p1-8-legacy-config-canonical-priority
fix: prefer canonical plugin config files
This commit is contained in:
@@ -177,6 +177,13 @@ export function loadPluginConfig(
|
|||||||
? userDetected.path
|
? userDetected.path
|
||||||
: path.join(configDir, "oh-my-opencode.json");
|
: 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
|
// Auto-copy legacy config file to canonical name if needed
|
||||||
if (userDetected.format !== "none" && path.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
|
if (userDetected.format !== "none" && path.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
|
||||||
migrateLegacyConfigFile(userDetected.path);
|
migrateLegacyConfigFile(userDetected.path);
|
||||||
@@ -190,6 +197,13 @@ export function loadPluginConfig(
|
|||||||
? projectDetected.path
|
? projectDetected.path
|
||||||
: path.join(projectBasePath, "oh-my-opencode.json");
|
: 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
|
// Auto-copy legacy project config file to canonical name if needed
|
||||||
if (projectDetected.format !== "none" && path.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
|
if (projectDetected.format !== "none" && path.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
|
||||||
migrateLegacyConfigFile(projectDetected.path);
|
migrateLegacyConfigFile(projectDetected.path);
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ describe("detectConfigFile", () => {
|
|||||||
describe("detectPluginConfigFile", () => {
|
describe("detectPluginConfigFile", () => {
|
||||||
const testDir = join(__dirname, ".test-detect-plugin")
|
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
|
// given
|
||||||
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
||||||
writeFileSync(join(testDir, "oh-my-openagent.jsonc"), "{}")
|
writeFileSync(join(testDir, "oh-my-openagent.jsonc"), "{}")
|
||||||
@@ -279,7 +279,8 @@ describe("detectPluginConfigFile", () => {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.format).toBe("jsonc")
|
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 })
|
rmSync(testDir, { recursive: true, force: true })
|
||||||
})
|
})
|
||||||
@@ -295,13 +296,15 @@ describe("detectPluginConfigFile", () => {
|
|||||||
// then
|
// then
|
||||||
expect(result.format).toBe("jsonc")
|
expect(result.format).toBe("jsonc")
|
||||||
expect(result.path).toBe(join(testDir, "oh-my-opencode.jsonc"))
|
expect(result.path).toBe(join(testDir, "oh-my-opencode.jsonc"))
|
||||||
|
expect(result.legacyPath).toBeUndefined()
|
||||||
|
|
||||||
rmSync(testDir, { recursive: true, force: true })
|
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
|
// given
|
||||||
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
||||||
|
writeFileSync(join(testDir, "oh-my-openagent.json"), "{}")
|
||||||
writeFileSync(join(testDir, "oh-my-opencode.json"), "{}")
|
writeFileSync(join(testDir, "oh-my-opencode.json"), "{}")
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -309,7 +312,8 @@ describe("detectPluginConfigFile", () => {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.format).toBe("json")
|
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 })
|
rmSync(testDir, { recursive: true, force: true })
|
||||||
})
|
})
|
||||||
@@ -324,12 +328,12 @@ describe("detectPluginConfigFile", () => {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.format).toBe("none")
|
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 })
|
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
|
// given
|
||||||
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
if (!existsSync(testDir)) mkdirSync(testDir, { recursive: true })
|
||||||
writeFileSync(join(testDir, "oh-my-opencode.json"), "{}")
|
writeFileSync(join(testDir, "oh-my-opencode.json"), "{}")
|
||||||
@@ -339,8 +343,25 @@ describe("detectPluginConfigFile", () => {
|
|||||||
const result = detectPluginConfigFile(testDir)
|
const result = detectPluginConfigFile(testDir)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.format).toBe("json")
|
expect(result.format).toBe("jsonc")
|
||||||
expect(result.path).toBe(join(testDir, "oh-my-opencode.json"))
|
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 })
|
rmSync(testDir, { recursive: true, force: true })
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { existsSync, readFileSync } from "node:fs"
|
|||||||
import { join } from "node:path"
|
import { join } from "node:path"
|
||||||
import { parse, ParseError, printParseErrorCode } from "jsonc-parser"
|
import { parse, ParseError, printParseErrorCode } from "jsonc-parser"
|
||||||
|
|
||||||
|
import { CONFIG_BASENAME, LEGACY_CONFIG_BASENAME } from "./plugin-identity"
|
||||||
|
|
||||||
export interface JsoncParseResult<T> {
|
export interface JsoncParseResult<T> {
|
||||||
data: T | null
|
data: T | null
|
||||||
errors: Array<{ message: string; offset: number; length: number }>
|
errors: Array<{ message: string; offset: number; length: number }>
|
||||||
@@ -66,15 +68,24 @@ export function detectConfigFile(basePath: string): {
|
|||||||
return { format: "none", path: jsonPath }
|
return { format: "none", path: jsonPath }
|
||||||
}
|
}
|
||||||
|
|
||||||
const PLUGIN_CONFIG_NAMES = ["oh-my-opencode", "oh-my-openagent"] as const
|
|
||||||
|
|
||||||
export function detectPluginConfigFile(dir: string): {
|
export function detectPluginConfigFile(dir: string): {
|
||||||
format: "json" | "jsonc" | "none"
|
format: "json" | "jsonc" | "none"
|
||||||
path: string
|
path: string
|
||||||
|
legacyPath?: string
|
||||||
} {
|
} {
|
||||||
for (const name of PLUGIN_CONFIG_NAMES) {
|
const canonicalResult = detectConfigFile(join(dir, CONFIG_BASENAME))
|
||||||
const result = detectConfigFile(join(dir, name))
|
const legacyResult = detectConfigFile(join(dir, LEGACY_CONFIG_BASENAME))
|
||||||
if (result.format !== "none") return result
|
|
||||||
|
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`) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user