Bump plugin to 2.39.0 with features from Matt Van Horn (@mvanhorn): context budget precheck, plan sequence numbers, review serial mode, agent-browser debugging commands, test-browser port detection, lfg phase gating, and Context7 API key auth. Also fixes MCP server merge order so plugin servers correctly overwrite stale entries during sync. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
48 lines
1.2 KiB
TypeScript
48 lines
1.2 KiB
TypeScript
import path from "path"
|
|
import { pathExists, readJson, writeJsonSecure } from "../utils/files"
|
|
|
|
type JsonObject = Record<string, unknown>
|
|
|
|
function isJsonObject(value: unknown): value is JsonObject {
|
|
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
}
|
|
|
|
export async function mergeJsonConfigAtKey(options: {
|
|
configPath: string
|
|
key: string
|
|
incoming: Record<string, unknown>
|
|
}): Promise<void> {
|
|
const { configPath, key, incoming } = options
|
|
const existing = await readJsonObjectSafe(configPath)
|
|
const existingEntries = isJsonObject(existing[key]) ? existing[key] : {}
|
|
const merged = {
|
|
...existing,
|
|
[key]: {
|
|
...existingEntries,
|
|
...incoming, // incoming plugin entries overwrite same-named servers
|
|
},
|
|
}
|
|
|
|
await writeJsonSecure(configPath, merged)
|
|
}
|
|
|
|
async function readJsonObjectSafe(configPath: string): Promise<JsonObject> {
|
|
if (!(await pathExists(configPath))) {
|
|
return {}
|
|
}
|
|
|
|
try {
|
|
const parsed = await readJson<unknown>(configPath)
|
|
if (isJsonObject(parsed)) {
|
|
return parsed
|
|
}
|
|
} catch {
|
|
// Fall through to warning and replacement.
|
|
}
|
|
|
|
console.warn(
|
|
`Warning: existing ${path.basename(configPath)} could not be parsed and will be replaced.`,
|
|
)
|
|
return {}
|
|
}
|