Skip to content

Commit b27673e

Browse files
fix: normalize Windows paths to forward slashes in mode export (#6308)
Co-authored-by: Roo Code <[email protected]>
1 parent 4effcec commit b27673e

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

src/core/config/CustomModesManager.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,9 @@ export class CustomModesManager {
786786
const relativePath = isGlobalMode
787787
? path.relative(baseDir, filePath)
788788
: path.relative(path.join(baseDir, ".roo"), filePath)
789-
rulesFiles.push({ relativePath, content: content.trim() })
789+
// Normalize path to use forward slashes for cross-platform compatibility
790+
const normalizedRelativePath = relativePath.toPosix()
791+
rulesFiles.push({ relativePath: normalizedRelativePath, content: content.trim() })
790792
}
791793
}
792794
}

src/core/config/__tests__/CustomModesManager.spec.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,5 +1699,59 @@ describe("CustomModesManager", () => {
16991699
expect(result.yaml).toContain("global-test-mode")
17001700
expect(result.yaml).toContain("Global rule content")
17011701
})
1702+
1703+
it("should normalize paths to use forward slashes in exported YAML", async () => {
1704+
const roomodesContent = {
1705+
customModes: [
1706+
{
1707+
slug: "test-mode",
1708+
name: "Test Mode",
1709+
roleDefinition: "Test Role",
1710+
groups: ["read"],
1711+
},
1712+
],
1713+
}
1714+
1715+
;(fileExistsAtPath as Mock).mockImplementation(async (path: string) => {
1716+
return path === mockRoomodes
1717+
})
1718+
;(fs.readFile as Mock).mockImplementation(async (path: string) => {
1719+
if (path === mockRoomodes) {
1720+
return yaml.stringify(roomodesContent)
1721+
}
1722+
if (path.includes("rules-test-mode")) {
1723+
return "Rule content"
1724+
}
1725+
throw new Error("File not found")
1726+
})
1727+
;(fs.stat as Mock).mockResolvedValue({ isDirectory: () => true })
1728+
1729+
// Mock readdir to return entries with subdirectories
1730+
;(fs.readdir as Mock).mockResolvedValue([
1731+
{ name: "rule1.md", isFile: () => true },
1732+
{ name: "rule2.md", isFile: () => true },
1733+
])
1734+
1735+
const result = await manager.exportModeWithRules("test-mode")
1736+
1737+
expect(result.success).toBe(true)
1738+
1739+
// Parse the YAML to check the paths
1740+
const exportedData = yaml.parse(result.yaml!)
1741+
const rulesFiles = exportedData.customModes[0].rulesFiles
1742+
1743+
// Verify that all paths use forward slashes
1744+
expect(rulesFiles).toBeDefined()
1745+
expect(rulesFiles.length).toBe(2)
1746+
1747+
// Check that all paths use forward slashes
1748+
rulesFiles.forEach((file: any) => {
1749+
expect(file.relativePath).not.toContain("\\")
1750+
expect(file.relativePath).toMatch(/^rules-test-mode\//)
1751+
})
1752+
1753+
// Ensure no backslashes in the entire exported YAML
1754+
expect(result.yaml).not.toContain("\\")
1755+
})
17021756
})
17031757
})

0 commit comments

Comments
 (0)