From 229cdafcc43ef53611a12dc2e8137575669e8706 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Thu, 5 Feb 2026 18:10:35 -0800 Subject: [PATCH] fix(config): handle $ character with {file:} pattern (#12390) Co-authored-by: Hank Stoever <1109058+hstove@users.noreply.github.com> --- packages/opencode/src/config/config.ts | 2 +- packages/opencode/test/config/config.test.ts | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index ed1b15500..c56bd6c78 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1267,7 +1267,7 @@ export namespace Config { }) ).trim() // escape newlines/quotes, strip outer quotes - text = text.replace(match, JSON.stringify(fileContent).slice(1, -1)) + text = text.replace(match, () => JSON.stringify(fileContent).slice(1, -1)) } } diff --git a/packages/opencode/test/config/config.test.ts b/packages/opencode/test/config/config.test.ts index dee633110..91b87f649 100644 --- a/packages/opencode/test/config/config.test.ts +++ b/packages/opencode/test/config/config.test.ts @@ -193,6 +193,25 @@ test("handles file inclusion substitution", async () => { }) }) +test("handles file inclusion with replacement tokens", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + await Bun.write(path.join(dir, "included.md"), "const out = await Bun.$`echo hi`") + await writeConfig(dir, { + $schema: "https://opencode.ai/config.json", + theme: "{file:included.md}", + }) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const config = await Config.get() + expect(config.theme).toBe("const out = await Bun.$`echo hi`") + }, + }) +}) + test("validates config schema and throws on invalid fields", async () => { await using tmp = await tmpdir({ init: async (dir) => {