Skip to content

Commit 2c82f4c

Browse files
Add a built-in /init slash command (RooCodeInc#7381)
Co-authored-by: Hannes Rudolph <[email protected]>
1 parent c7d2b72 commit 2c82f4c

File tree

28 files changed

+486
-53
lines changed

28 files changed

+486
-53
lines changed

src/__tests__/command-integration.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe("Command Integration Tests", () => {
1515
commands.forEach((command) => {
1616
expect(command.name).toBeDefined()
1717
expect(typeof command.name).toBe("string")
18-
expect(command.source).toMatch(/^(project|global)$/)
18+
expect(command.source).toMatch(/^(project|global|built-in)$/)
1919
expect(command.content).toBeDefined()
2020
expect(typeof command.content).toBe("string")
2121
})
@@ -43,7 +43,7 @@ describe("Command Integration Tests", () => {
4343

4444
expect(loadedCommand).toBeDefined()
4545
expect(loadedCommand?.name).toBe(firstCommand.name)
46-
expect(loadedCommand?.source).toMatch(/^(project|global)$/)
46+
expect(loadedCommand?.source).toMatch(/^(project|global|built-in)$/)
4747
expect(loadedCommand?.content).toBeDefined()
4848
expect(typeof loadedCommand?.content).toBe("string")
4949
}

src/core/webview/webviewMessageHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,7 @@ export const webviewMessageHandler = async (
26192619
source: command.source,
26202620
filePath: command.filePath,
26212621
description: command.description,
2622+
argumentHint: command.argumentHint,
26222623
}))
26232624
await provider.postMessageToWebview({
26242625
type: "commands",
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { describe, it, expect } from "vitest"
2+
import { getBuiltInCommands, getBuiltInCommand, getBuiltInCommandNames } from "../built-in-commands"
3+
4+
describe("Built-in Commands", () => {
5+
describe("getBuiltInCommands", () => {
6+
it("should return all built-in commands", async () => {
7+
const commands = await getBuiltInCommands()
8+
9+
expect(commands).toHaveLength(1)
10+
expect(commands.map((cmd) => cmd.name)).toEqual(expect.arrayContaining(["init"]))
11+
12+
// Verify all commands have required properties
13+
commands.forEach((command) => {
14+
expect(command.name).toBeDefined()
15+
expect(typeof command.name).toBe("string")
16+
expect(command.content).toBeDefined()
17+
expect(typeof command.content).toBe("string")
18+
expect(command.source).toBe("built-in")
19+
expect(command.filePath).toMatch(/^<built-in:.+>$/)
20+
expect(command.description).toBeDefined()
21+
expect(typeof command.description).toBe("string")
22+
})
23+
})
24+
25+
it("should return commands with proper content", async () => {
26+
const commands = await getBuiltInCommands()
27+
28+
const initCommand = commands.find((cmd) => cmd.name === "init")
29+
expect(initCommand).toBeDefined()
30+
expect(initCommand!.content).toContain("AGENTS.md")
31+
expect(initCommand!.content).toContain(".roo/rules-")
32+
expect(initCommand!.description).toBe(
33+
"Analyze codebase and create concise AGENTS.md files for AI assistants",
34+
)
35+
})
36+
})
37+
38+
describe("getBuiltInCommand", () => {
39+
it("should return specific built-in command by name", async () => {
40+
const initCommand = await getBuiltInCommand("init")
41+
42+
expect(initCommand).toBeDefined()
43+
expect(initCommand!.name).toBe("init")
44+
expect(initCommand!.source).toBe("built-in")
45+
expect(initCommand!.filePath).toBe("<built-in:init>")
46+
expect(initCommand!.content).toContain("AGENTS.md")
47+
expect(initCommand!.description).toBe(
48+
"Analyze codebase and create concise AGENTS.md files for AI assistants",
49+
)
50+
})
51+
52+
it("should return undefined for non-existent command", async () => {
53+
const nonExistentCommand = await getBuiltInCommand("non-existent")
54+
expect(nonExistentCommand).toBeUndefined()
55+
})
56+
57+
it("should handle empty string command name", async () => {
58+
const emptyCommand = await getBuiltInCommand("")
59+
expect(emptyCommand).toBeUndefined()
60+
})
61+
})
62+
63+
describe("getBuiltInCommandNames", () => {
64+
it("should return all built-in command names", async () => {
65+
const names = await getBuiltInCommandNames()
66+
67+
expect(names).toHaveLength(1)
68+
expect(names).toEqual(expect.arrayContaining(["init"]))
69+
// Order doesn't matter since it's based on filesystem order
70+
expect(names.sort()).toEqual(["init"])
71+
})
72+
73+
it("should return array of strings", async () => {
74+
const names = await getBuiltInCommandNames()
75+
76+
names.forEach((name) => {
77+
expect(typeof name).toBe("string")
78+
expect(name.length).toBeGreaterThan(0)
79+
})
80+
})
81+
})
82+
83+
describe("Command Content Validation", () => {
84+
it("init command should have comprehensive content", async () => {
85+
const command = await getBuiltInCommand("init")
86+
const content = command!.content
87+
88+
// Should contain key sections
89+
expect(content).toContain("Please analyze this codebase")
90+
expect(content).toContain("Build/lint/test commands")
91+
expect(content).toContain("Code style guidelines")
92+
expect(content).toContain("mode-specific rule directories")
93+
expect(content).toContain("analysis_workflow")
94+
95+
// Should mention important concepts
96+
expect(content).toContain("AGENTS.md")
97+
expect(content).toContain(".roo/rules-")
98+
expect(content).toContain("rules-code")
99+
expect(content).toContain("rules-debug")
100+
expect(content).toContain("rules-ask")
101+
expect(content).toContain("rules-architect")
102+
})
103+
})
104+
})

src/services/command/__tests__/frontmatter-commands.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ vi.mock("../roo-config", () => ({
99
getGlobalRooDirectory: vi.fn(() => "/mock/global/.roo"),
1010
getProjectRooDirectoryForCwd: vi.fn(() => "/mock/project/.roo"),
1111
}))
12+
vi.mock("../built-in-commands", () => ({
13+
getBuiltInCommands: vi.fn(() => Promise.resolve([])),
14+
getBuiltInCommand: vi.fn(() => Promise.resolve(undefined)),
15+
getBuiltInCommandNames: vi.fn(() => Promise.resolve([])),
16+
}))
1217

1318
const mockFs = vi.mocked(fs)
1419

0 commit comments

Comments
 (0)