fix(setup): name client configuration syntax from one reader table (#10586)

* fix(setup): name client configuration syntax from one reader table

Each client format now maps to one reader description (syntax, strict or
JSONC, BOM and empty-file handling, strict-JSON repair). The document
parser, the strict-JSON rewrite decision and uninstall's diagnostic all
read it, so uninstall no longer re-derives a syntax name that called
Goose's YAML and JSONC-admitting clients "JSON".

* test(hopper): retry cleanup after confirmed application exit
This commit is contained in:
morluto authored and GitHub committed 2026-11-14 14:37:04 -05:00
1 parent e83e3fa8a0
commit 9ca6b41ee0
4 files changed
+193 -47

No files matched your search

@@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
import {
ClientConfigurationShapeError,
clientConfigurationSyntaxName,
parseClientConfiguration,
shadowedClientServers,
} from "./ClientConfigurationDocument.js";
@@ -27,6 +28,44 @@ describe("parseClientConfiguration shape diagnostics", () => {
expect(error.message).toContain("object");
});
// The diagnostic syntax name must describe what the reader actually admits.
it.each([
["json", "JSONC"],
["vscode", "JSONC"],
["opencode", "JSONC"],
["kilo", "JSONC"],
["zed", "JSONC"],
["amp", "JSONC"],
["copilot_cli", "JSONC"],
["fx", "JSONC"],
["claude_code", "JSON"],
["pi", "JSON"],
["kimi", "JSON"],
["lm_studio", "JSON"],
["zcode", "JSON"],
["toml", "TOML"],
["grok", "TOML"],
["goose", "YAML"],
["hermes", "YAML"],
] as const)("names %s configuration syntax %s", (format, name) => {
expect(clientConfigurationSyntaxName(format)).toBe(name);
const accepts = (text: string): boolean => {
try {
parseClientConfiguration(text, format);
return true;
} catch {
return false;
}
};
if (name === "TOML") expect(accepts("keep = 1\n")).toBe(true);
if (name === "YAML") expect(accepts("keep: 1\n")).toBe(true);
if (name === "JSON" || name === "JSONC") {
expect(accepts('{"keep":1}')).toBe(true);
expect(accepts('{"keep":1,}')).toBe(name === "JSONC");
expect(accepts('{"keep":1 /* comment */}')).toBe(name === "JSONC");
}
});
it("still rejects unparsable JSON with SyntaxError", () => {
expect(() => parseClientConfiguration("not-json", "json")).toThrow(
SyntaxError,