Skip to content

Commit 8390379

Browse files
committed
basically working
1 parent 586e237 commit 8390379

File tree

6 files changed

+433
-32
lines changed

6 files changed

+433
-32
lines changed

src/core/webview/webviewMessageHandler.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,12 +1899,38 @@ export const webviewMessageHandler = async (
18991899
// Import the rules generation service
19001900
const { createRulesGenerationTaskMessage } = await import("../../services/rules/rulesGenerator")
19011901

1902+
// Get selected rule types and options from the message
1903+
const selectedRuleTypes = message.selectedRuleTypes || ["general"]
1904+
const addToGitignore = message.addToGitignore || false
1905+
const alwaysAllowWriteProtected = message.alwaysAllowWriteProtected || false
1906+
const apiConfigName = message.apiConfigName
1907+
1908+
// Save current API config to restore later
1909+
const currentApiConfig = getGlobalState("currentApiConfigName")
1910+
1911+
// Temporarily switch to the selected API config if provided
1912+
if (apiConfigName && apiConfigName !== currentApiConfig) {
1913+
await updateGlobalState("currentApiConfigName", apiConfigName)
1914+
await provider.postStateToWebview()
1915+
}
1916+
19021917
// Create a comprehensive message for the rules generation task using existing analysis logic
1903-
const rulesGenerationMessage = await createRulesGenerationTaskMessage(workspacePath)
1918+
const rulesGenerationMessage = await createRulesGenerationTaskMessage(
1919+
workspacePath,
1920+
selectedRuleTypes,
1921+
addToGitignore,
1922+
alwaysAllowWriteProtected,
1923+
)
19041924

19051925
// Spawn a new task in code mode to generate the rules
19061926
await provider.initClineWithTask(rulesGenerationMessage)
19071927

1928+
// Restore the original API config
1929+
if (apiConfigName && apiConfigName !== currentApiConfig) {
1930+
await updateGlobalState("currentApiConfigName", currentApiConfig)
1931+
await provider.postStateToWebview()
1932+
}
1933+
19081934
// Send success message back to webview indicating task was created
19091935
await provider.postMessageToWebview({
19101936
type: "rulesGenerationStatus",
@@ -1927,6 +1953,45 @@ export const webviewMessageHandler = async (
19271953
})
19281954
}
19291955
break
1956+
case "checkExistingRuleFiles":
1957+
// Check which rule files already exist
1958+
try {
1959+
const workspacePath = getWorkspacePath()
1960+
if (!workspacePath) {
1961+
break
1962+
}
1963+
1964+
const { fileExistsAtPath } = await import("../../utils/fs")
1965+
const path = await import("path")
1966+
1967+
const ruleTypeToPath: Record<string, string> = {
1968+
general: path.join(workspacePath, ".roo", "rules", "coding-standards.md"),
1969+
code: path.join(workspacePath, ".roo", "rules-code", "implementation-rules.md"),
1970+
architect: path.join(workspacePath, ".roo", "rules-architect", "architecture-rules.md"),
1971+
debug: path.join(workspacePath, ".roo", "rules-debug", "debugging-rules.md"),
1972+
"docs-extractor": path.join(
1973+
workspacePath,
1974+
".roo",
1975+
"rules-docs-extractor",
1976+
"documentation-rules.md",
1977+
),
1978+
}
1979+
1980+
const existingFiles: string[] = []
1981+
for (const [type, filePath] of Object.entries(ruleTypeToPath)) {
1982+
if (await fileExistsAtPath(filePath)) {
1983+
existingFiles.push(type)
1984+
}
1985+
}
1986+
1987+
await provider.postMessageToWebview({
1988+
type: "existingRuleFiles",
1989+
files: existingFiles,
1990+
})
1991+
} catch (error) {
1992+
// Silently fail - not critical
1993+
}
1994+
break
19301995
case "humanRelayResponse":
19311996
if (message.requestId && message.text) {
19321997
vscode.commands.executeCommand(getCommand("handleHumanRelayResponse"), {

src/services/rules/rulesGenerator.ts

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -204,19 +204,73 @@ async function generateCodebaseSummary(workspacePath: string, config: ProjectCon
204204
/**
205205
* Creates a comprehensive task message for rules generation that can be used with initClineWithTask
206206
*/
207-
export async function createRulesGenerationTaskMessage(workspacePath: string): Promise<string> {
207+
export async function createRulesGenerationTaskMessage(
208+
workspacePath: string,
209+
selectedRuleTypes: string[],
210+
addToGitignore: boolean,
211+
alwaysAllowWriteProtected: boolean = false,
212+
): Promise<string> {
208213
// Analyze the project to get context
209214
const config = await analyzeProjectConfig(workspacePath)
210215
const codebaseSummary = await generateCodebaseSummary(workspacePath, config)
211216

212-
// Ensure .roo/rules directory exists at project root
213-
const rooRulesDir = path.join(workspacePath, ".roo", "rules")
214-
try {
215-
await fs.mkdir(rooRulesDir, { recursive: true })
216-
} catch (error) {
217-
// Directory might already exist, which is fine
217+
// Ensure all necessary directories exist at project root
218+
const directoriesToCreate = [
219+
path.join(workspacePath, ".roo", "rules"),
220+
path.join(workspacePath, ".roo", "rules-code"),
221+
path.join(workspacePath, ".roo", "rules-architect"),
222+
path.join(workspacePath, ".roo", "rules-debug"),
223+
path.join(workspacePath, ".roo", "rules-docs-extractor"),
224+
]
225+
226+
for (const dir of directoriesToCreate) {
227+
try {
228+
await fs.mkdir(dir, { recursive: true })
229+
} catch (error) {
230+
// Directory might already exist, which is fine
231+
}
218232
}
219233

234+
// Create rule-specific instructions based on selected types
235+
interface RuleInstruction {
236+
path: string
237+
focus: string
238+
}
239+
240+
const ruleInstructions: RuleInstruction[] = selectedRuleTypes
241+
.map((type) => {
242+
switch (type) {
243+
case "general":
244+
return {
245+
path: ".roo/rules/coding-standards.md",
246+
focus: "General coding standards that apply to all modes, including naming conventions, file organization, and general best practices",
247+
}
248+
case "code":
249+
return {
250+
path: ".roo/rules-code/implementation-rules.md",
251+
focus: "Specific rules for code implementation, focusing on syntax patterns, code structure, error handling, testing approaches, and detailed implementation guidelines",
252+
}
253+
case "architect":
254+
return {
255+
path: ".roo/rules-architect/architecture-rules.md",
256+
focus: "High-level system design rules, focusing on file layout, module organization, architectural patterns, and system-wide design principles",
257+
}
258+
case "debug":
259+
return {
260+
path: ".roo/rules-debug/debugging-rules.md",
261+
focus: "Debugging workflow rules, including error investigation approaches, logging strategies, troubleshooting patterns, and debugging best practices",
262+
}
263+
case "docs-extractor":
264+
return {
265+
path: ".roo/rules-docs-extractor/documentation-rules.md",
266+
focus: "Documentation extraction and formatting rules, including documentation style guides, API documentation patterns, and content organization",
267+
}
268+
default:
269+
return null
270+
}
271+
})
272+
.filter((rule): rule is RuleInstruction => rule !== null)
273+
220274
// Create a comprehensive message for the rules generation task
221275
const taskMessage = `Analyze this codebase and generate comprehensive rules for AI agents working in this repository.
222276
@@ -233,18 +287,35 @@ ${codebaseSummary}
233287
- Project-specific conventions and best practices
234288
- File organization patterns
235289
236-
3. **Save the rules** to the file at exactly this path: .roo/rules/coding-standards.md
237-
- The .roo/rules directory has already been created for you
238-
- Always overwrite the existing file if it exists
239-
- Use the \`write_to_file\` tool to save the content
290+
3. **Generate and save the following rule files**:
291+
${ruleInstructions
292+
.map(
293+
(rule, index) => `
294+
${index + 1}. **${rule.path}**
295+
- Focus: ${rule.focus}
296+
- The directory has already been created for you
297+
- Always overwrite the existing file if it exists
298+
- Use the \`write_to_file\` tool to save the content${alwaysAllowWriteProtected ? "\n - Note: Auto-approval for protected file writes is enabled, so you can write to .roo directories without manual approval" : ""}`,
299+
)
300+
.join("\n")}
240301
241302
4. **Open the generated file** in the editor for review
242303
243304
The rules should be about 20-30 lines long and focus on the most important guidelines for this specific project. Make them actionable and specific to help AI agents work effectively in this codebase.
244305
245306
If there are existing rules files (like CLAUDE.md, .cursorrules, .cursor/rules, .github/copilot-instructions.md), incorporate and improve upon them.
246307
247-
Use the \`safeWriteJson\` utility from \`src/utils/safeWriteJson.ts\` for any JSON file operations to ensure atomic writes.`
308+
Use the \`safeWriteJson\` utility from \`src/utils/safeWriteJson.ts\` for any JSON file operations to ensure atomic writes.
309+
310+
${
311+
addToGitignore
312+
? `5. **Add the generated files to .gitignore**:
313+
- After generating all rule files, add entries to .gitignore to prevent them from being committed
314+
- Add each generated file path to .gitignore (e.g., .roo/rules/coding-standards.md)
315+
- If .gitignore doesn't exist, create it
316+
- If the entries already exist in .gitignore, don't duplicate them`
317+
: ""
318+
}`
248319

249320
return taskMessage
250321
}

src/shared/ExtensionMessage.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,10 @@ export interface ExtensionMessage {
106106
| "codeIndexSettingsSaved"
107107
| "codeIndexSecretStatus"
108108
| "rulesGenerationStatus"
109+
| "existingRuleFiles"
109110
text?: string
110111
payload?: any // Add a generic payload for now, can refine later
112+
files?: string[] // For existingRuleFiles
111113
action?:
112114
| "chatButtonClicked"
113115
| "mcpButtonClicked"

src/shared/WebviewMessage.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ export interface WebviewMessage {
195195
| "saveCodeIndexSettingsAtomic"
196196
| "requestCodeIndexSecretStatus"
197197
| "generateRules"
198+
| "checkExistingRuleFiles"
198199
text?: string
199200
editedMessageContent?: string
200201
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account"
@@ -236,6 +237,11 @@ export interface WebviewMessage {
236237
visibility?: ShareVisibility // For share visibility
237238
hasContent?: boolean // For checkRulesDirectoryResult
238239
checkOnly?: boolean // For deleteCustomMode check
240+
selectedRuleTypes?: string[] // For generateRules
241+
addToGitignore?: boolean // For generateRules
242+
alwaysAllowWriteProtected?: boolean // For generateRules
243+
apiConfigName?: string // For generateRules
244+
files?: string[] // For existingRuleFiles response
239245
codeIndexSettings?: {
240246
// Global state settings
241247
codebaseIndexEnabled: boolean

0 commit comments

Comments
 (0)