Skip to content

Commit ce373b2

Browse files
committed
feat: add Frontend Developer mode
- Add new Frontend Developer mode to DEFAULT_MODES - Configure mode with UI/UX focus and mobile-first principles - Restrict file editing to frontend-specific directories and files - Add comprehensive tests for the new mode Fixes #6704
1 parent d90bab7 commit ce373b2

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { describe, it, expect } from "vitest"
2+
import { DEFAULT_MODES, modeConfigSchema } from "../mode.js"
3+
4+
describe("DEFAULT_MODES", () => {
5+
it("should include the Frontend Developer mode", () => {
6+
const frontEndMode = DEFAULT_MODES.find((mode) => mode.slug === "front-end-developer")
7+
expect(frontEndMode).toBeDefined()
8+
expect(frontEndMode?.name).toBe("🎨 Front End Developer")
9+
})
10+
11+
it("should have valid configuration for Frontend Developer mode", () => {
12+
const frontEndMode = DEFAULT_MODES.find((mode) => mode.slug === "front-end-developer")
13+
expect(frontEndMode).toBeDefined()
14+
15+
// Validate against schema
16+
const result = modeConfigSchema.safeParse(frontEndMode)
17+
expect(result.success).toBe(true)
18+
})
19+
20+
it("should have correct groups for Frontend Developer mode", () => {
21+
const frontEndMode = DEFAULT_MODES.find((mode) => mode.slug === "front-end-developer")
22+
expect(frontEndMode).toBeDefined()
23+
expect(frontEndMode?.groups).toHaveLength(3)
24+
expect(frontEndMode?.groups[0]).toBe("read")
25+
expect(frontEndMode?.groups[2]).toBe("command")
26+
27+
// Check edit group with file regex
28+
const editGroup = frontEndMode?.groups[1]
29+
expect(Array.isArray(editGroup)).toBe(true)
30+
if (Array.isArray(editGroup)) {
31+
expect(editGroup[0]).toBe("edit")
32+
expect(editGroup[1]).toHaveProperty("fileRegex")
33+
expect(editGroup[1]).toHaveProperty("description", "UI code and design asset files only")
34+
}
35+
})
36+
37+
it("should have correct file regex pattern for Frontend Developer mode", () => {
38+
const frontEndMode = DEFAULT_MODES.find((mode) => mode.slug === "front-end-developer")
39+
const editGroup = frontEndMode?.groups[1]
40+
41+
if (Array.isArray(editGroup) && editGroup[1]?.fileRegex) {
42+
const regex = new RegExp(editGroup[1].fileRegex)
43+
44+
// Test valid UI files
45+
expect(regex.test("src/components/Button.tsx")).toBe(true)
46+
expect(regex.test("src/styles/main.css")).toBe(true)
47+
expect(regex.test("src/pages/Home.jsx")).toBe(true)
48+
expect(regex.test("src/ui/Modal.tsx")).toBe(true)
49+
expect(regex.test("src/hooks/useAuth.ts")).toBe(true)
50+
expect(regex.test("src/main.css")).toBe(true)
51+
expect(regex.test("public/index.html")).toBe(true)
52+
expect(regex.test("assets/logo.svg")).toBe(true)
53+
expect(regex.test("static/banner.png")).toBe(true)
54+
55+
// Test invalid files (backend/server files)
56+
expect(regex.test("server.js")).toBe(false)
57+
expect(regex.test("README.md")).toBe(false)
58+
expect(regex.test("package.json")).toBe(false)
59+
expect(regex.test("src/api/routes.ts")).toBe(false)
60+
expect(regex.test("src/App.jsx")).toBe(false) // App.jsx at root of src is not in allowed folders
61+
expect(regex.test("src/server/index.ts")).toBe(false)
62+
}
63+
})
64+
65+
it("should have all required fields for Frontend Developer mode", () => {
66+
const frontEndMode = DEFAULT_MODES.find((mode) => mode.slug === "front-end-developer")
67+
68+
expect(frontEndMode).toMatchObject({
69+
slug: "front-end-developer",
70+
name: "🎨 Front End Developer",
71+
roleDefinition: expect.stringContaining("front end development specialist"),
72+
whenToUse: expect.stringContaining("UI code"),
73+
description: "Create stunning UI/UX with mobile-first design",
74+
groups: expect.any(Array),
75+
})
76+
})
77+
78+
it("should maintain correct order of modes with Frontend Developer added", () => {
79+
const modeNames = DEFAULT_MODES.map((mode) => mode.slug)
80+
expect(modeNames).toContain("architect")
81+
expect(modeNames).toContain("code")
82+
expect(modeNames).toContain("ask")
83+
expect(modeNames).toContain("debug")
84+
expect(modeNames).toContain("orchestrator")
85+
expect(modeNames).toContain("front-end-developer")
86+
87+
// Frontend Developer should be the last mode
88+
expect(modeNames[modeNames.length - 1]).toBe("front-end-developer")
89+
})
90+
})

packages/types/src/mode.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,25 @@ export const DEFAULT_MODES: readonly ModeConfig[] = [
192192
customInstructions:
193193
"Your role is to coordinate complex workflows by delegating tasks to specialized modes. As an orchestrator, you should:\n\n1. When given a complex task, break it down into logical subtasks that can be delegated to appropriate specialized modes.\n\n2. For each subtask, use the `new_task` tool to delegate. Choose the most appropriate mode for the subtask's specific goal and provide comprehensive instructions in the `message` parameter. These instructions must include:\n * All necessary context from the parent task or previous subtasks required to complete the work.\n * A clearly defined scope, specifying exactly what the subtask should accomplish.\n * An explicit statement that the subtask should *only* perform the work outlined in these instructions and not deviate.\n * An instruction for the subtask to signal completion by using the `attempt_completion` tool, providing a concise yet thorough summary of the outcome in the `result` parameter, keeping in mind that this summary will be the source of truth used to keep track of what was completed on this project.\n * A statement that these specific instructions supersede any conflicting general instructions the subtask's mode might have.\n\n3. Track and manage the progress of all subtasks. When a subtask is completed, analyze its results and determine the next steps.\n\n4. Help the user understand how the different subtasks fit together in the overall workflow. Provide clear reasoning about why you're delegating specific tasks to specific modes.\n\n5. When all subtasks are completed, synthesize the results and provide a comprehensive overview of what was accomplished.\n\n6. Ask clarifying questions when necessary to better understand how to break down complex tasks effectively.\n\n7. Suggest improvements to the workflow based on the results of completed subtasks.\n\nUse subtasks to maintain clarity. If a request significantly shifts focus or requires a different expertise (mode), consider creating a subtask rather than overloading the current one.",
194194
},
195+
{
196+
slug: "front-end-developer",
197+
name: "🎨 Front End Developer",
198+
roleDefinition:
199+
"You are Roo Code, a front end development specialist with mastery in UI/UX, visual design, and mobile-first principles. Your expertise includes: - Creating stunning, responsive user interfaces - Applying modern design systems and best practices - Ensuring pixel-perfect layouts and excellent taste - Advocating for accessibility and usability - Deep knowledge of HTML, CSS, JavaScript, TypeScript, and frameworks like React, Vue, and Svelte - Strong insistence on mobile-first, adaptive, and responsive design You never compromise on design quality or user experience.",
200+
whenToUse:
201+
"Use this mode for tasks involving UI code (HTML, CSS, JS/TS, React, Vue, Svelte) and design assets (SVG, PNG, JPG, GIF, WebP). Do not use for backend, server, or documentation files.",
202+
description: "Create stunning UI/UX with mobile-first design",
203+
groups: [
204+
"read",
205+
[
206+
"edit",
207+
{
208+
fileRegex:
209+
"^(src/(components|pages|views|ui|styles|layouts|hooks|utils|lib|features)/.*\\.(js|jsx|ts|tsx|css|scss|sass|less|html|svg)$|src/.*\\.(css|scss|sass|less)$|public/.*\\.(css|scss|sass|less|html|svg|png|jpg|jpeg|gif|webp)$|assets/.*\\.(svg|png|jpg|jpeg|gif|webp)$|static/.*\\.(svg|png|jpg|jpeg|gif|webp)$)",
210+
description: "UI code and design asset files only",
211+
},
212+
],
213+
"command",
214+
],
215+
},
195216
] as const

0 commit comments

Comments
 (0)