Compare commits

...

4 Commits

Author SHA1 Message Date
Saoud Rizwan edf7f3092d Merge branch 'main' into factor-out-getClineRules-function 2025-04-11 19:56:46 -07:00
Saoud Rizwan c32581db3e Update fs.ts 2025-04-11 19:55:33 -07:00
celestial-vault 8a96d463f1 changeset 2025-04-11 11:11:58 -07:00
celestial-vault e5205f8317 factor out cline rules functionality 2025-04-11 11:11:26 -07:00
4 changed files with 73 additions and 36 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"claude-dev": patch
---
Refactor: Remove cline rules functions from task/index.ts
@@ -0,0 +1,45 @@
import path from "path"
import { GlobalFileNames } from "../../../storage/disk"
import { fileExistsAtPath, isDirectory, readDirectory } from "../../../../utils/fs"
import { formatResponse } from "../../../prompts/responses"
import fs from "fs/promises"
export const getClineRules = async (cwd: string) => {
const clineRulesFilePath = path.resolve(cwd, GlobalFileNames.clineRules)
let clineRulesFileInstructions: string | undefined
if (await fileExistsAtPath(clineRulesFilePath)) {
if (await isDirectory(clineRulesFilePath)) {
try {
const rulesFilePaths = await readDirectory(path.join(cwd, GlobalFileNames.clineRules))
const rulesFilesTotalContent = await getClineRulesFilesTotalContent(rulesFilePaths, cwd)
clineRulesFileInstructions = formatResponse.clineRulesDirectoryInstructions(cwd, rulesFilesTotalContent)
} catch {
console.error(`Failed to read .clinerules directory at ${clineRulesFilePath}`)
}
} else {
try {
const ruleFileContent = (await fs.readFile(clineRulesFilePath, "utf8")).trim()
if (ruleFileContent) {
clineRulesFileInstructions = formatResponse.clineRulesFileInstructions(cwd, ruleFileContent)
}
} catch {
console.error(`Failed to read .clinerules file at ${clineRulesFilePath}`)
}
}
}
return clineRulesFileInstructions
}
const getClineRulesFilesTotalContent = async (rulesFilePaths: string[], cwd: string) => {
const ruleFilesTotalContent = await Promise.all(
rulesFilePaths.map(async (filePath) => {
const ruleFilePath = path.resolve(cwd, filePath)
const ruleFilePathRelative = path.relative(cwd, ruleFilePath)
return `${ruleFilePathRelative}\n` + (await fs.readFile(ruleFilePath, "utf8")).trim()
}),
).then((contents) => contents.join("\n\n"))
return ruleFilesTotalContent
}
+4 -36
View File
@@ -1,6 +1,5 @@
import { Anthropic } from "@anthropic-ai/sdk"
import cloneDeep from "clone-deep"
import fs from "fs/promises"
import getFolderSize from "get-folder-size"
import { setTimeout as setTimeoutPromise } from "node:timers/promises"
import os from "os"
@@ -73,18 +72,17 @@ import {
checkIsAnthropicContextWindowError,
checkIsOpenRouterContextWindowError,
} from "../context/context-management/context-error-handling"
import { Controller } from "../controller"
import {
ensureTaskDirectoryExists,
getSavedApiConversationHistory,
getSavedClineMessages,
saveApiConversationHistory,
saveClineMessages,
GlobalFileNames,
getTaskMetadata,
} from "../storage/disk"
import { McpHub } from "../../services/mcp/McpHub"
import WorkspaceTracker from "../../integrations/workspace/WorkspaceTracker"
import { getClineRules } from "../context/instructions/user-instructions/cline-rules"
import { getGlobalState } from "../storage/state"
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) ?? path.join(os.homedir(), "Desktop") // may or may not exist but fs checking existence would immediately ask for permission which would be bad UX, need to come up with a better solution
@@ -1277,38 +1275,8 @@ export class Task {
preferredLanguage && preferredLanguage !== DEFAULT_LANGUAGE_SETTINGS
? `# Preferred Language\n\nSpeak in ${preferredLanguage}.`
: ""
const clineRulesFilePath = path.resolve(cwd, GlobalFileNames.clineRules)
let clineRulesFileInstructions: string | undefined
if (await fileExistsAtPath(clineRulesFilePath)) {
if (await isDirectory(clineRulesFilePath)) {
try {
// Read all files in the .clinerules/ directory.
const ruleFiles = await fs
.readdir(clineRulesFilePath, { withFileTypes: true, recursive: true })
.then((files) => files.filter((file) => file.isFile()))
.then((files) => files.map((file) => path.resolve(file.parentPath, file.name)))
const ruleFilesTotalContent = await Promise.all(
ruleFiles.map(async (file) => {
const ruleFilePath = path.resolve(clineRulesFilePath, file)
const ruleFilePathRelative = path.relative(cwd, ruleFilePath)
return `${ruleFilePathRelative}\n` + (await fs.readFile(ruleFilePath, "utf8")).trim()
}),
).then((contents) => contents.join("\n\n"))
clineRulesFileInstructions = formatResponse.clineRulesDirectoryInstructions(cwd, ruleFilesTotalContent)
} catch {
console.error(`Failed to read .clinerules directory at ${clineRulesFilePath}`)
}
} else {
try {
const ruleFileContent = (await fs.readFile(clineRulesFilePath, "utf8")).trim()
if (ruleFileContent) {
clineRulesFileInstructions = formatResponse.clineRulesFileInstructions(cwd, ruleFileContent)
}
} catch {
console.error(`Failed to read .clinerules file at ${clineRulesFilePath}`)
}
}
}
const clineRulesFileInstructions = await getClineRules(cwd)
const clineIgnoreContent = this.clineIgnoreController.clineIgnoreContent
let clineIgnoreInstructions: string | undefined
+19
View File
@@ -74,3 +74,22 @@ export async function getFileSizeInKB(filePath: string): Promise<number> {
return 0
}
}
/**
* Recursively reads a directory and returns an array of absolute file paths.
*
* @param directoryPath - The path to the directory to read.
* @returns A promise that resolves to an array of absolute file paths.
* @throws Error if the directory cannot be read.
*/
export const readDirectory = async (directoryPath: string) => {
try {
const filePaths = await fs
.readdir(directoryPath, { withFileTypes: true, recursive: true })
.then((files) => files.filter((file) => file.isFile()))
.then((files) => files.map((file) => path.resolve(file.parentPath, file.name)))
return filePaths
} catch {
throw new Error(`Error reading directory at ${directoryPath}`)
}
}