diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 86238f1a844c..3820c57b996d 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -230,7 +230,8 @@ const layer = Layer.effect( yield* Effect.promise(() => resolveLoadedPlugins(data, options.path)) if (!data.$schema) { data.$schema = "https://opencode.ai/config.json" - const updated = text.replace(/^\s*\{/, '{\n "$schema": "https://opencode.ai/config.json",') + const comma = Object.keys(parsed).length ? "," : "" + const updated = text.replace(/^\s*\{/, `{\n "$schema": "https://opencode.ai/config.json"${comma}`) yield* fs.writeFileString(options.path, updated).pipe(Effect.catch(() => Effect.void)) } return data diff --git a/packages/opencode/test/config/config.test.ts b/packages/opencode/test/config/config.test.ts index e281831ddfa8..4ac956e813d3 100644 --- a/packages/opencode/test/config/config.test.ts +++ b/packages/opencode/test/config/config.test.ts @@ -528,6 +528,19 @@ it.instance("preserves env variables when adding $schema to config", () => ), ) +it.instance("adds $schema to an empty JSON config without a trailing comma", () => + Effect.gen(function* () { + const test = yield* TestInstance + const file = path.join(test.directory, "opencode.json") + yield* FSUtil.use.writeWithDirs(file, "{}") + + yield* Config.use.get() + + const content = yield* FSUtil.use.readFileString(file) + expect(JSON.parse(content)).toEqual({ $schema: "https://opencode.ai/config.json" }) + }), +) + it.instance("handles file inclusion substitution", () => Effect.gen(function* () { const test = yield* TestInstance