From be2492b48d010859948ca4faddf05ea1241c7ef5 Mon Sep 17 00:00:00 2001 From: deseltrus Date: Sun, 15 Mar 2026 07:19:09 +0100 Subject: [PATCH] fix(prefs): break parse/serialize cycle for empty arrays and objects The preferences parser treated [] and {} as strings instead of empty array/object. On next serialize, yamlSafeString quoted them as "[]" and "{}", permanently corrupting the preferences file. This caused the wizard to show empty fields (models, auto_supervisor, etc.). Fix: parseScalar now recognizes [] and {} (quoted or unquoted) as empty array/object. Serializer omits empty values entirely instead of writing key: [] or key: {}. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/resources/extensions/gsd/commands.ts | 6 ++---- src/resources/extensions/gsd/preferences.ts | 8 ++++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/resources/extensions/gsd/commands.ts b/src/resources/extensions/gsd/commands.ts index e3dc2f59c..eae9b2214 100644 --- a/src/resources/extensions/gsd/commands.ts +++ b/src/resources/extensions/gsd/commands.ts @@ -448,8 +448,7 @@ function serializePreferencesToFrontmatter(prefs: Record): stri if (Array.isArray(value)) { if (value.length === 0) { - lines.push(`${prefix}${key}: []`); - return; + return; // Omit empty arrays — avoids parse/serialize cycle bug with "[]" strings } lines.push(`${prefix}${key}:`); for (const item of value) { @@ -480,8 +479,7 @@ function serializePreferencesToFrontmatter(prefs: Record): stri if (typeof value === "object") { const entries = Object.entries(value as Record); if (entries.length === 0) { - lines.push(`${prefix}${key}: {}`); - return; + return; // Omit empty objects — avoids parse/serialize cycle bug with "{}" strings } lines.push(`${prefix}${key}:`); for (const [k, v] of entries) { diff --git a/src/resources/extensions/gsd/preferences.ts b/src/resources/extensions/gsd/preferences.ts index 283f2dda4..0d271497b 100644 --- a/src/resources/extensions/gsd/preferences.ts +++ b/src/resources/extensions/gsd/preferences.ts @@ -482,16 +482,20 @@ function parseFrontmatterBlock(frontmatter: string): GSDPreferences { return root as GSDPreferences; } -function parseScalar(value: string): string | number | boolean { +function parseScalar(value: string): unknown { if (value === "true") return true; if (value === "false") return false; + // Recognize empty array/object literals (with or without surrounding quotes) + const unquoted = value.replace(/^['\"]|['\"]$/g, ""); + if (unquoted === "[]") return []; + if (unquoted === "{}") return {}; if (/^-?\d+$/.test(value)) { const n = Number(value); // Keep large integers (e.g. Discord channel IDs) as strings to avoid precision loss if (Number.isSafeInteger(n)) return n; return value; } - return value.replace(/^['\"]|['\"]$/g, ""); + return unquoted; } /**