From d28f5fff5535c17c806f0f7e901c37027dd121eb Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Sat, 28 Mar 2026 09:38:01 +0800 Subject: [PATCH 1/3] fix: normalize CRLF line endings in prompt file parser Strip \r\n to \n at the start of parsePromptFile() so the frontmatter separator split works on Windows-style line endings. Signed-off-by: majiayu000 <1835304752@qq.com> --- core/promptFiles/parsePromptFile.ts | 3 +- core/promptFiles/parsePromptFile.vitest.ts | 37 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 core/promptFiles/parsePromptFile.vitest.ts diff --git a/core/promptFiles/parsePromptFile.ts b/core/promptFiles/parsePromptFile.ts index 4b6cf6917b8..fd96e6f4230 100644 --- a/core/promptFiles/parsePromptFile.ts +++ b/core/promptFiles/parsePromptFile.ts @@ -3,7 +3,8 @@ import * as YAML from "yaml"; import { getLastNPathParts } from "../util/uri"; export function parsePromptFile(path: string, content: string) { - let [preambleRaw, prompt] = content.split("\n---\n"); + const normalizedContent = content.replace(/\r\n/g, "\n"); + let [preambleRaw, prompt] = normalizedContent.split("\n---\n"); if (prompt === undefined) { prompt = preambleRaw; preambleRaw = ""; diff --git a/core/promptFiles/parsePromptFile.vitest.ts b/core/promptFiles/parsePromptFile.vitest.ts new file mode 100644 index 00000000000..8ab66038a2b --- /dev/null +++ b/core/promptFiles/parsePromptFile.vitest.ts @@ -0,0 +1,37 @@ +import { describe, expect, it } from "vitest"; +import { parsePromptFile } from "./parsePromptFile"; + +describe("parsePromptFile", () => { + const path = "test.prompt"; + + it("should parse LF content correctly", () => { + const content = "name: test\ndescription: a test\n---\nHello world"; + const result = parsePromptFile(path, content); + expect(result.name).toBe("test"); + expect(result.description).toBe("a test"); + expect(result.prompt).toBe("Hello world"); + }); + + it("should parse CRLF content correctly", () => { + const content = "name: test\r\ndescription: a test\r\n---\r\nHello world"; + const result = parsePromptFile(path, content); + expect(result.name).toBe("test"); + expect(result.description).toBe("a test"); + expect(result.prompt).toBe("Hello world"); + }); + + it("should handle no frontmatter", () => { + const content = "Just a prompt"; + const result = parsePromptFile(path, content); + expect(result.prompt).toBe("Just a prompt"); + expect(result.name).toBe("test"); + }); + + it("should parse system tag with CRLF", () => { + const content = + "name: test\r\n---\r\nYou are helpful\r\nHello"; + const result = parsePromptFile(path, content); + expect(result.systemMessage).toBe("You are helpful"); + expect(result.prompt).toBe("Hello"); + }); +}); From 9dc633df0af26392d7d36d314c91a66a70af35fa Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Sat, 28 Mar 2026 09:41:23 +0800 Subject: [PATCH 2/3] test: add unit tests for parsePromptFile CRLF handling Signed-off-by: majiayu000 <1835304752@qq.com> --- core/promptFiles/parsePromptFile.test.ts | 61 ++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 core/promptFiles/parsePromptFile.test.ts diff --git a/core/promptFiles/parsePromptFile.test.ts b/core/promptFiles/parsePromptFile.test.ts new file mode 100644 index 00000000000..9d1dfcb7720 --- /dev/null +++ b/core/promptFiles/parsePromptFile.test.ts @@ -0,0 +1,61 @@ +import { parsePromptFile } from "./parsePromptFile"; + +describe("parsePromptFile", () => { + const path = "prompts/test.prompt"; + + it("should parse frontmatter with LF line endings", () => { + const content = "name: greet\ndescription: Say hello\n---\nHello {{ name }}"; + const result = parsePromptFile(path, content); + expect(result.name).toBe("greet"); + expect(result.description).toBe("Say hello"); + expect(result.prompt).toBe("Hello {{ name }}"); + expect(result.systemMessage).toBeUndefined(); + }); + + it("should parse frontmatter with CRLF line endings", () => { + const content = + "name: greet\r\ndescription: Say hello\r\n---\r\nHello {{ name }}"; + const result = parsePromptFile(path, content); + expect(result.name).toBe("greet"); + expect(result.description).toBe("Say hello"); + expect(result.prompt).toBe("Hello {{ name }}"); + }); + + it("should handle mixed line endings", () => { + const content = + "name: mixed\r\ndescription: Mixed endings\n---\r\nSome prompt text"; + const result = parsePromptFile(path, content); + expect(result.name).toBe("mixed"); + expect(result.description).toBe("Mixed endings"); + expect(result.prompt).toBe("Some prompt text"); + }); + + it("should fall back to filename when no frontmatter", () => { + const content = "Just a prompt with no frontmatter"; + const result = parsePromptFile(path, content); + expect(result.name).toBe("test"); + expect(result.description).toBe("test"); + expect(result.prompt).toBe("Just a prompt with no frontmatter"); + }); + + it("should parse tag with CRLF", () => { + const content = + "name: sys\r\ndescription: With system\r\n---\r\n\r\nYou are helpful.\r\n\r\nUser prompt here"; + const result = parsePromptFile(path, content); + expect(result.name).toBe("sys"); + expect(result.systemMessage).toBe("You are helpful."); + expect(result.prompt).toBe("User prompt here"); + }); + + it("should default version to 2", () => { + const content = "name: ver\n---\nHello"; + const result = parsePromptFile(path, content); + expect(result.version).toBe(2); + }); + + it("should respect version in frontmatter", () => { + const content = "name: ver\nversion: 1\n---\nHello"; + const result = parsePromptFile(path, content); + expect(result.version).toBe(1); + }); +}); From 89482b4d1c5167af056282a4f5f81c9ed461121d Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Sat, 28 Mar 2026 09:57:04 +0800 Subject: [PATCH 3/3] fix: remove redundant test file failing prettier check The .test.ts file duplicated the .vitest.ts tests and did not match project conventions, causing the prettier CI check to fail. Signed-off-by: majiayu000 <1835304752@qq.com> --- core/promptFiles/parsePromptFile.test.ts | 61 ------------------------ 1 file changed, 61 deletions(-) delete mode 100644 core/promptFiles/parsePromptFile.test.ts diff --git a/core/promptFiles/parsePromptFile.test.ts b/core/promptFiles/parsePromptFile.test.ts deleted file mode 100644 index 9d1dfcb7720..00000000000 --- a/core/promptFiles/parsePromptFile.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { parsePromptFile } from "./parsePromptFile"; - -describe("parsePromptFile", () => { - const path = "prompts/test.prompt"; - - it("should parse frontmatter with LF line endings", () => { - const content = "name: greet\ndescription: Say hello\n---\nHello {{ name }}"; - const result = parsePromptFile(path, content); - expect(result.name).toBe("greet"); - expect(result.description).toBe("Say hello"); - expect(result.prompt).toBe("Hello {{ name }}"); - expect(result.systemMessage).toBeUndefined(); - }); - - it("should parse frontmatter with CRLF line endings", () => { - const content = - "name: greet\r\ndescription: Say hello\r\n---\r\nHello {{ name }}"; - const result = parsePromptFile(path, content); - expect(result.name).toBe("greet"); - expect(result.description).toBe("Say hello"); - expect(result.prompt).toBe("Hello {{ name }}"); - }); - - it("should handle mixed line endings", () => { - const content = - "name: mixed\r\ndescription: Mixed endings\n---\r\nSome prompt text"; - const result = parsePromptFile(path, content); - expect(result.name).toBe("mixed"); - expect(result.description).toBe("Mixed endings"); - expect(result.prompt).toBe("Some prompt text"); - }); - - it("should fall back to filename when no frontmatter", () => { - const content = "Just a prompt with no frontmatter"; - const result = parsePromptFile(path, content); - expect(result.name).toBe("test"); - expect(result.description).toBe("test"); - expect(result.prompt).toBe("Just a prompt with no frontmatter"); - }); - - it("should parse tag with CRLF", () => { - const content = - "name: sys\r\ndescription: With system\r\n---\r\n\r\nYou are helpful.\r\n\r\nUser prompt here"; - const result = parsePromptFile(path, content); - expect(result.name).toBe("sys"); - expect(result.systemMessage).toBe("You are helpful."); - expect(result.prompt).toBe("User prompt here"); - }); - - it("should default version to 2", () => { - const content = "name: ver\n---\nHello"; - const result = parsePromptFile(path, content); - expect(result.version).toBe(2); - }); - - it("should respect version in frontmatter", () => { - const content = "name: ver\nversion: 1\n---\nHello"; - const result = parsePromptFile(path, content); - expect(result.version).toBe(1); - }); -});