Merge pull request #753 from RooVetGit/visual_fixes

Slight visual fixes
This commit is contained in:
Matt Rubens 2025-02-03 15:09:45 -05:00 committed by GitHub
commit f2d7cbebbe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 82 additions and 59 deletions

View file

@ -9,8 +9,8 @@ describe("mode-validator", () => {
it("allows all code mode tools", () => {
const mode = getModeConfig(codeMode)
// Code mode has all groups
Object.entries(TOOL_GROUPS).forEach(([_, tools]) => {
tools.forEach((tool) => {
Object.entries(TOOL_GROUPS).forEach(([_, config]) => {
config.tools.forEach((tool: string) => {
expect(isToolAllowedForMode(tool, codeMode, [])).toBe(true)
})
})
@ -25,7 +25,11 @@ describe("mode-validator", () => {
it("allows configured tools", () => {
const mode = getModeConfig(architectMode)
// Architect mode has read, browser, and mcp groups
const architectTools = [...TOOL_GROUPS.read, ...TOOL_GROUPS.browser, ...TOOL_GROUPS.mcp]
const architectTools = [
...TOOL_GROUPS.read.tools,
...TOOL_GROUPS.browser.tools,
...TOOL_GROUPS.mcp.tools,
]
architectTools.forEach((tool) => {
expect(isToolAllowedForMode(tool, architectMode, [])).toBe(true)
})
@ -36,7 +40,7 @@ describe("mode-validator", () => {
it("allows configured tools", () => {
const mode = getModeConfig(askMode)
// Ask mode has read, browser, and mcp groups
const askTools = [...TOOL_GROUPS.read, ...TOOL_GROUPS.browser, ...TOOL_GROUPS.mcp]
const askTools = [...TOOL_GROUPS.read.tools, ...TOOL_GROUPS.browser.tools, ...TOOL_GROUPS.mcp.tools]
askTools.forEach((tool) => {
expect(isToolAllowedForMode(tool, askMode, [])).toBe(true)
})

View file

@ -66,7 +66,7 @@ export function getToolDescriptionsForMode(
const groupName = getGroupName(groupEntry)
const toolGroup = TOOL_GROUPS[groupName]
if (toolGroup) {
toolGroup.forEach((tool) => {
toolGroup.tools.forEach((tool) => {
if (isToolAllowedForMode(tool as ToolName, mode, customModes ?? [], experiments ?? {})) {
tools.add(tool)
}

View file

@ -59,7 +59,8 @@ export function getToolsForMode(groups: readonly GroupEntry[]): string[] {
// Add tools from each group
groups.forEach((group) => {
const groupName = getGroupName(group)
TOOL_GROUPS[groupName].forEach((tool) => tools.add(tool))
const groupConfig = TOOL_GROUPS[groupName]
groupConfig.tools.forEach((tool: string) => tools.add(tool))
})
// Always add required tools
@ -190,8 +191,10 @@ export function isToolAllowedForMode(
const groupName = getGroupName(group)
const options = getGroupOptions(group)
// If the tool isn't in this group, continue to next group
if (!TOOL_GROUPS[groupName].includes(tool)) {
const groupConfig = TOOL_GROUPS[groupName]
// If the tool isn't in this group's tools, continue to next group
if (!groupConfig.tools.includes(tool)) {
continue
}

View file

@ -1,5 +1,8 @@
// Define tool group values
export type ToolGroupValues = readonly string[]
// Define tool group configuration
export type ToolGroupConfig = {
tools: readonly string[]
alwaysAvailable?: boolean // Whether this group is always available and shouldn't show in prompts view
}
// Map of tool slugs to their display names
export const TOOL_DISPLAY_NAMES = {
@ -20,13 +23,26 @@ export const TOOL_DISPLAY_NAMES = {
} as const
// Define available tool groups
export const TOOL_GROUPS: Record<string, ToolGroupValues> = {
read: ["read_file", "search_files", "list_files", "list_code_definition_names"],
edit: ["write_to_file", "apply_diff", "insert_content", "search_and_replace"],
browser: ["browser_action"],
command: ["execute_command"],
mcp: ["use_mcp_tool", "access_mcp_resource"],
modes: ["switch_mode", "new_task"],
export const TOOL_GROUPS: Record<string, ToolGroupConfig> = {
read: {
tools: ["read_file", "search_files", "list_files", "list_code_definition_names"],
},
edit: {
tools: ["write_to_file", "apply_diff", "insert_content", "search_and_replace"],
},
browser: {
tools: ["browser_action"],
},
command: {
tools: ["execute_command"],
},
mcp: {
tools: ["use_mcp_tool", "access_mcp_resource"],
},
modes: {
tools: ["switch_mode", "new_task"],
alwaysAvailable: true,
},
}
export type ToolGroup = keyof typeof TOOL_GROUPS

View file

@ -994,7 +994,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
}}>
{showAnnouncement && <Announcement version={version} hideAnnouncement={hideAnnouncement} />}
<div style={{ padding: "0 20px", flexShrink: 0 }}>
<h2>What can I do for you?</h2>
<h2>What can Roo do for you?</h2>
<p>
Thanks to the latest breakthroughs in agentic coding capabilities, I can handle complex
software development tasks step-by-step. With tools that let me create & edit files, explore

View file

@ -26,8 +26,8 @@ import {
import { TOOL_GROUPS, GROUP_DISPLAY_NAMES, ToolGroup } from "../../../../src/shared/tool-groups"
import { vscode } from "../../utils/vscode"
// Get all available groups from GROUP_DISPLAY_NAMES
const availableGroups = Object.keys(TOOL_GROUPS) as ToolGroup[]
// Get all available groups that should show in prompts view
const availableGroups = (Object.keys(TOOL_GROUPS) as ToolGroup[]).filter((group) => !TOOL_GROUPS[group].alwaysAvailable)
type PromptsViewProps = {
onDone: () => void
@ -65,6 +65,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
const [isToolsEditMode, setIsToolsEditMode] = useState(false)
const [isCreateModeDialogOpen, setIsCreateModeDialogOpen] = useState(false)
const [activeSupportTab, setActiveSupportTab] = useState<SupportPromptType>("ENHANCE")
const [selectedModeTab, setSelectedModeTab] = useState<string>(mode)
// Direct update functions
const updateAgentPrompt = useCallback(
@ -110,26 +111,23 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
text: slug,
})
}, [])
// Handle mode switching with explicit state initialization
// Handle mode tab selection without actually switching modes
const handleModeSwitch = useCallback(
(modeConfig: ModeConfig) => {
if (modeConfig.slug === mode) return // Prevent unnecessary updates
if (modeConfig.slug === selectedModeTab) return // Prevent unnecessary updates
// First switch the mode
switchMode(modeConfig.slug)
// Exit tools edit mode when switching modes
// Update selected tab and reset tools edit mode
setSelectedModeTab(modeConfig.slug)
setIsToolsEditMode(false)
},
[mode, switchMode, setIsToolsEditMode],
[selectedModeTab, setIsToolsEditMode],
)
// Helper function to get current mode's config
const getCurrentMode = useCallback((): ModeConfig | undefined => {
const findMode = (m: ModeConfig): boolean => m.slug === mode
const findMode = (m: ModeConfig): boolean => m.slug === selectedModeTab
return customModes?.find(findMode) || modes.find(findMode)
}, [mode, customModes, modes])
}, [selectedModeTab, customModes, modes])
// Helper function to safely access mode properties
const getModeProperty = <T extends keyof ModeConfig>(
@ -155,6 +153,11 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
}
}, [isCreateModeDialogOpen])
// Keep selected tab in sync with actual mode
useEffect(() => {
setSelectedModeTab(mode)
}, [mode])
// Helper function to generate a unique slug from a name
const generateSlug = useCallback((name: string, attempt = 0): string => {
const baseSlug = name
@ -184,22 +187,13 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
groups: newModeGroups,
}
updateCustomMode(newModeSlug, newMode)
switchMode(newModeSlug)
setIsCreateModeDialogOpen(false)
setNewModeName("")
setNewModeSlug("")
setNewModeRoleDefinition("")
setNewModeCustomInstructions("")
setNewModeGroups(availableGroups)
}, [
newModeName,
newModeSlug,
newModeRoleDefinition,
newModeCustomInstructions,
newModeGroups,
updateCustomMode,
switchMode,
])
}, [newModeName, newModeSlug, newModeRoleDefinition, newModeCustomInstructions, newModeGroups, updateCustomMode])
const isNameOrSlugTaken = useCallback(
(name: string, slug: string) => {
@ -479,7 +473,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
padding: "4px 0",
}}>
{modes.map((modeConfig) => {
const isActive = mode === modeConfig.slug
const isActive = selectedModeTab === modeConfig.slug
return (
<button
key={modeConfig.slug}
@ -507,20 +501,22 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
<div style={{ marginBottom: "20px" }}>
{/* Only show name and delete for custom modes */}
{mode && findModeBySlug(mode, customModes) && (
{selectedModeTab && findModeBySlug(selectedModeTab, customModes) && (
<div style={{ display: "flex", gap: "12px", marginBottom: "16px" }}>
<div style={{ flex: 1 }}>
<div style={{ fontWeight: "bold", marginBottom: "4px" }}>Name</div>
<div style={{ display: "flex", gap: "8px" }}>
<VSCodeTextField
value={getModeProperty(findModeBySlug(mode, customModes), "name") ?? ""}
value={
getModeProperty(findModeBySlug(selectedModeTab, customModes), "name") ?? ""
}
onChange={(e: Event | React.FormEvent<HTMLElement>) => {
const target =
(e as CustomEvent)?.detail?.target ||
((e as any).target as HTMLInputElement)
const customMode = findModeBySlug(mode, customModes)
const customMode = findModeBySlug(selectedModeTab, customModes)
if (customMode) {
updateCustomMode(mode, {
updateCustomMode(selectedModeTab, {
...customMode,
name: target.value,
})
@ -534,7 +530,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
onClick={() => {
vscode.postMessage({
type: "deleteCustomMode",
slug: mode,
slug: selectedModeTab,
})
}}>
<span className="codicon codicon-trash"></span>
@ -552,7 +548,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
marginBottom: "4px",
}}>
<div style={{ fontWeight: "bold" }}>Role Definition</div>
{!findModeBySlug(mode, customModes) && (
{!findModeBySlug(selectedModeTab, customModes) && (
<VSCodeButton
appearance="icon"
onClick={() => {
@ -578,24 +574,28 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
</div>
<VSCodeTextArea
value={(() => {
const customMode = findModeBySlug(mode, customModes)
const prompt = customModePrompts?.[mode] as PromptComponent
return customMode?.roleDefinition ?? prompt?.roleDefinition ?? getRoleDefinition(mode)
const customMode = findModeBySlug(selectedModeTab, customModes)
const prompt = customModePrompts?.[selectedModeTab] as PromptComponent
return (
customMode?.roleDefinition ??
prompt?.roleDefinition ??
getRoleDefinition(selectedModeTab)
)
})()}
onChange={(e) => {
const value =
(e as CustomEvent)?.detail?.target?.value ||
((e as any).target as HTMLTextAreaElement).value
const customMode = findModeBySlug(mode, customModes)
const customMode = findModeBySlug(selectedModeTab, customModes)
if (customMode) {
// For custom modes, update the JSON file
updateCustomMode(mode, {
updateCustomMode(selectedModeTab, {
...customMode,
roleDefinition: value.trim() || "",
})
} else {
// For built-in modes, update the prompts
updateAgentPrompt(mode, {
updateAgentPrompt(selectedModeTab, {
roleDefinition: value.trim() || undefined,
})
}
@ -760,25 +760,25 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
</div>
<VSCodeTextArea
value={(() => {
const customMode = findModeBySlug(mode, customModes)
const prompt = customModePrompts?.[mode] as PromptComponent
const customMode = findModeBySlug(selectedModeTab, customModes)
const prompt = customModePrompts?.[selectedModeTab] as PromptComponent
return customMode?.customInstructions ?? prompt?.customInstructions ?? ""
})()}
onChange={(e) => {
const value =
(e as CustomEvent)?.detail?.target?.value ||
((e as any).target as HTMLTextAreaElement).value
const customMode = findModeBySlug(mode, customModes)
const customMode = findModeBySlug(selectedModeTab, customModes)
if (customMode) {
// For custom modes, update the JSON file
updateCustomMode(mode, {
updateCustomMode(selectedModeTab, {
...customMode,
customInstructions: value.trim() || undefined,
})
} else {
// For built-in modes, update the prompts
const existingPrompt = customModePrompts?.[mode] as PromptComponent
updateAgentPrompt(mode, {
const existingPrompt = customModePrompts?.[selectedModeTab] as PromptComponent
updateAgentPrompt(selectedModeTab, {
...existingPrompt,
customInstructions: value.trim() || undefined,
})