mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Add YAML support for .roomode files alongside JSON processing (#3711)
This commit is contained in:
parent
6a6df08fbd
commit
527050eeb0
4 changed files with 38 additions and 15 deletions
10
package-lock.json
generated
10
package-lock.json
generated
|
|
@ -65,6 +65,7 @@
|
|||
"vscode-material-icons": "^0.1.1",
|
||||
"web-tree-sitter": "^0.22.6",
|
||||
"workerpool": "^9.2.0",
|
||||
"yaml": "^2.8.0",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -20723,16 +20724,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz",
|
||||
"integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==",
|
||||
"dev": true,
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
|
||||
"integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 14.6"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
|
|
|
|||
|
|
@ -421,6 +421,7 @@
|
|||
"vscode-material-icons": "^0.1.1",
|
||||
"web-tree-sitter": "^0.22.6",
|
||||
"workerpool": "^9.2.0",
|
||||
"yaml": "^2.8.0",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { fileExistsAtPath } from "../../utils/fs"
|
|||
import { arePathsEqual, getWorkspacePath } from "../../utils/path"
|
||||
import { logger } from "../../utils/logging"
|
||||
import { GlobalFileNames } from "../../shared/globalFileNames"
|
||||
import * as yaml from "yaml"
|
||||
|
||||
const ROOMODES_FILENAME = ".roomodes"
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ export class CustomModesManager {
|
|||
private async loadModesFromFile(filePath: string): Promise<ModeConfig[]> {
|
||||
try {
|
||||
const content = await fs.readFile(filePath, "utf-8")
|
||||
const settings = JSON.parse(content)
|
||||
const settings = yaml.parse(content)
|
||||
const result = customModesSettingsSchema.safeParse(settings)
|
||||
if (!result.success) {
|
||||
return []
|
||||
|
|
@ -140,7 +141,7 @@ export class CustomModesManager {
|
|||
let config: any
|
||||
|
||||
try {
|
||||
config = JSON.parse(content)
|
||||
config = yaml.parse(content)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
vscode.window.showErrorMessage(errorMessage)
|
||||
|
|
@ -296,7 +297,7 @@ export class CustomModesManager {
|
|||
let settings
|
||||
|
||||
try {
|
||||
settings = JSON.parse(content)
|
||||
settings = yaml.parse(content)
|
||||
} catch (error) {
|
||||
console.error(`[CustomModesManager] Failed to parse JSON from ${filePath}:`, error)
|
||||
settings = { customModes: [] }
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { ModeConfig } from "../../../shared/modes"
|
|||
import { fileExistsAtPath } from "../../../utils/fs"
|
||||
import { getWorkspacePath, arePathsEqual } from "../../../utils/path"
|
||||
import { GlobalFileNames } from "../../../shared/globalFileNames"
|
||||
import * as yaml from "yaml"
|
||||
|
||||
jest.mock("vscode")
|
||||
jest.mock("fs/promises")
|
||||
|
|
@ -60,6 +61,26 @@ describe("CustomModesManager", () => {
|
|||
})
|
||||
|
||||
describe("getCustomModes", () => {
|
||||
it("should handle valid YAML in .roomodes file and JSON for global customModes", async () => {
|
||||
const settingsModes = [{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }]
|
||||
|
||||
const roomodesModes = [{ slug: "mode2", name: "Mode 2", roleDefinition: "Role 2", groups: ["read"] }]
|
||||
|
||||
;(fs.readFile as jest.Mock).mockImplementation(async (path: string) => {
|
||||
if (path === mockSettingsPath) {
|
||||
return JSON.stringify({ customModes: settingsModes })
|
||||
}
|
||||
if (path === mockRoomodes) {
|
||||
return yaml.stringify({ customModes: roomodesModes })
|
||||
}
|
||||
throw new Error("File not found")
|
||||
})
|
||||
|
||||
const modes = await manager.getCustomModes()
|
||||
|
||||
expect(modes).toHaveLength(2)
|
||||
})
|
||||
|
||||
it("should merge modes with .roomodes taking precedence", async () => {
|
||||
const settingsModes = [
|
||||
{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] },
|
||||
|
|
@ -423,10 +444,10 @@ describe("CustomModesManager", () => {
|
|||
;(fs.writeFile as jest.Mock).mockImplementation(
|
||||
async (path: string, content: string, _encoding?: string) => {
|
||||
if (path === mockSettingsPath) {
|
||||
settingsContent = JSON.parse(content)
|
||||
settingsContent = yaml.parse(content)
|
||||
}
|
||||
if (path === mockRoomodes) {
|
||||
roomodesContent = JSON.parse(content)
|
||||
roomodesContent = yaml.parse(content)
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
|
|
@ -439,7 +460,7 @@ describe("CustomModesManager", () => {
|
|||
|
||||
// Verify the content of the write
|
||||
const writeCall = (fs.writeFile as jest.Mock).mock.calls[0]
|
||||
const content = JSON.parse(writeCall[1])
|
||||
const content = yaml.parse(writeCall[1])
|
||||
expect(content.customModes).toContainEqual(
|
||||
expect.objectContaining({
|
||||
slug: "mode1",
|
||||
|
|
@ -493,7 +514,7 @@ describe("CustomModesManager", () => {
|
|||
})
|
||||
;(fs.writeFile as jest.Mock).mockImplementation(async (path: string, content: string) => {
|
||||
if (path === mockRoomodes) {
|
||||
roomodesContent = JSON.parse(content)
|
||||
roomodesContent = yaml.parse(content)
|
||||
}
|
||||
return Promise.resolve()
|
||||
})
|
||||
|
|
@ -550,7 +571,7 @@ describe("CustomModesManager", () => {
|
|||
;(fs.writeFile as jest.Mock).mockImplementation(
|
||||
async (path: string, content: string, _encoding?: string) => {
|
||||
if (path === mockSettingsPath) {
|
||||
settingsContent = JSON.parse(content)
|
||||
settingsContent = yaml.parse(content)
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
|
|
@ -659,7 +680,7 @@ describe("CustomModesManager", () => {
|
|||
;(fs.writeFile as jest.Mock).mockImplementation(
|
||||
async (path: string, content: string, encoding?: string) => {
|
||||
if (path === mockSettingsPath && encoding === "utf-8") {
|
||||
settingsContent = JSON.parse(content)
|
||||
settingsContent = yaml.parse(content)
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
|
|
@ -713,7 +734,7 @@ describe("CustomModesManager", () => {
|
|||
|
||||
// Verify that a valid JSON structure was written
|
||||
const writeCall = (fs.writeFile as jest.Mock).mock.calls[0]
|
||||
const writtenContent = JSON.parse(writeCall[1])
|
||||
const writtenContent = yaml.parse(writeCall[1])
|
||||
expect(writtenContent).toEqual({
|
||||
customModes: [
|
||||
expect.objectContaining({
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue