Skip to content

Commit a48982d

Browse files
committed
Update button styling to match About section and fix lint warnings
- Updated import/export buttons to use fixed width (w-28) - Added Upload/Download icons from lucide-react - Wrapped buttons in flex container with gap-2 spacing - Buttons now match the style of those in the About Roo Code section - Removed unused state variables to fix lint warnings
1 parent d926cad commit a48982d

File tree

25 files changed

+601
-387
lines changed

25 files changed

+601
-387
lines changed

src/core/config/CustomModesManager.ts

Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ export class CustomModesManager {
493493
}
494494
}
495495

496-
public async consolidateRulesForMode(slug: string): Promise<{ success: boolean; error?: string }> {
496+
public async exportModeWithRules(slug: string): Promise<{ success: boolean; yaml?: string; error?: string }> {
497497
try {
498498
// Get all current modes
499499
const allModes = await this.getCustomModes()
@@ -536,73 +536,108 @@ export class CustomModesManager {
536536
// Check for .roo/rules-{slug}/ directory
537537
const modeRulesDir = path.join(workspacePath, ".roo", `rules-${slug}`)
538538

539+
let rulesFiles: Array<{ relativePath: string; content: string }> = []
539540
try {
540541
const stats = await fs.stat(modeRulesDir)
541-
if (!stats.isDirectory()) {
542-
return { success: false, error: "Rules directory not found" }
543-
}
544-
} catch (error) {
545-
return { success: false, error: "Rules directory not found" }
546-
}
547-
548-
// Extract content specific to this mode by looking for the mode-specific rules
549-
let modeSpecificRules = ""
550-
try {
551-
const entries = await fs.readdir(modeRulesDir, { withFileTypes: true, recursive: true })
552-
const files: Array<{ filename: string; content: string }> = []
553-
554-
for (const entry of entries) {
555-
if (entry.isFile()) {
556-
const filePath = path.join(entry.parentPath || modeRulesDir, entry.name)
557-
const content = await fs.readFile(filePath, "utf-8")
558-
if (content.trim()) {
559-
files.push({ filename: filePath, content: content.trim() })
542+
if (stats.isDirectory()) {
543+
// Extract content specific to this mode by looking for the mode-specific rules
544+
const entries = await fs.readdir(modeRulesDir, { withFileTypes: true, recursive: true })
545+
546+
for (const entry of entries) {
547+
if (entry.isFile()) {
548+
const filePath = path.join(entry.parentPath || modeRulesDir, entry.name)
549+
const content = await fs.readFile(filePath, "utf-8")
550+
if (content.trim()) {
551+
// Calculate relative path from .roo directory
552+
const relativePath = path.relative(path.join(workspacePath, ".roo"), filePath)
553+
rulesFiles.push({ relativePath, content: content.trim() })
554+
}
560555
}
561556
}
562557
}
558+
} catch (error) {
559+
// Directory doesn't exist, which is fine - mode might not have rules
560+
}
563561

564-
if (files.length === 0) {
565-
return { success: false, error: "No rule files found in the directory" }
566-
}
562+
// Create an export mode with rules files preserved
563+
const exportMode: ModeConfig & { rulesFiles?: Array<{ relativePath: string; content: string }> } = {
564+
...mode,
565+
// Remove source property for export
566+
source: undefined as any,
567+
}
567568

568-
// Format the content without filename headers to avoid confusing the LLM
569-
modeSpecificRules = files.map((file) => file.content).join("\n\n")
570-
} catch (error) {
571-
return { success: false, error: "Failed to read rule files" }
569+
// Add rules files if any exist
570+
if (rulesFiles.length > 0) {
571+
exportMode.rulesFiles = rulesFiles
572572
}
573573

574-
if (!modeSpecificRules) {
575-
return { success: false, error: "No rule content found" }
574+
// Generate YAML
575+
const exportData = {
576+
customModes: [exportMode],
576577
}
577578

578-
// Combine existing custom instructions with the consolidated rules
579-
const existingInstructions = mode.customInstructions || ""
580-
const separator = existingInstructions ? "\n\n" : ""
581-
const newInstructions = existingInstructions + separator + modeSpecificRules
579+
const yamlContent = yaml.stringify(exportData)
582580

583-
// Update the mode with the new instructions
584-
const updatedMode: ModeConfig = {
585-
...mode,
586-
customInstructions: newInstructions,
581+
return { success: true, yaml: yamlContent }
582+
} catch (error) {
583+
const errorMessage = error instanceof Error ? error.message : String(error)
584+
logger.error("Failed to export mode with rules", { slug, error: errorMessage })
585+
return { success: false, error: errorMessage }
586+
}
587+
}
588+
589+
public async importModeWithRules(yamlContent: string): Promise<{ success: boolean; error?: string }> {
590+
try {
591+
// Parse the YAML content
592+
const importData = yaml.parse(yamlContent)
593+
594+
if (
595+
!importData?.customModes ||
596+
!Array.isArray(importData.customModes) ||
597+
importData.customModes.length === 0
598+
) {
599+
return { success: false, error: "Invalid import format: no custom modes found" }
600+
}
601+
602+
const workspacePath = getWorkspacePath()
603+
if (!workspacePath) {
604+
return { success: false, error: "No workspace found" }
587605
}
588606

589-
await this.updateCustomMode(slug, updatedMode)
607+
// Process each mode in the import
608+
for (const importMode of importData.customModes) {
609+
const { rulesFiles, ...modeConfig } = importMode
590610

591-
// Remove the source directory after successful consolidation
592-
try {
593-
await fs.rm(modeRulesDir, { recursive: true, force: true })
594-
} catch (removeError) {
595-
// Log the error but don't fail the operation since consolidation was successful
596-
logger.error("Warning: Could not remove rules directory after consolidation", {
597-
directory: modeRulesDir,
598-
error: removeError instanceof Error ? removeError.message : String(removeError),
611+
// Import the mode configuration
612+
await this.updateCustomMode(importMode.slug, {
613+
...modeConfig,
614+
source: "project", // Always import as project mode
599615
})
616+
617+
// Import rules files if they exist
618+
if (rulesFiles && Array.isArray(rulesFiles)) {
619+
for (const ruleFile of rulesFiles) {
620+
if (ruleFile.relativePath && ruleFile.content) {
621+
const targetPath = path.join(workspacePath, ".roo", ruleFile.relativePath)
622+
623+
// Ensure directory exists
624+
const targetDir = path.dirname(targetPath)
625+
await fs.mkdir(targetDir, { recursive: true })
626+
627+
// Write the file
628+
await fs.writeFile(targetPath, ruleFile.content, "utf-8")
629+
}
630+
}
631+
}
600632
}
601633

634+
// Refresh the modes after import
635+
await this.refreshMergedState()
636+
602637
return { success: true }
603638
} catch (error) {
604639
const errorMessage = error instanceof Error ? error.message : String(error)
605-
logger.error("Failed to consolidate rules for mode", { slug, error: errorMessage })
640+
logger.error("Failed to import mode with rules", { error: errorMessage })
606641
return { success: false, error: errorMessage }
607642
}
608643
}

0 commit comments

Comments
 (0)