mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
partial changes
This commit is contained in:
parent
930536d2e6
commit
1789553e14
28 changed files with 370 additions and 295 deletions
|
|
@ -131,6 +131,14 @@ export const globalSettingsSchema = z.object({
|
|||
hasOpenedModeSelector: z.boolean().optional(),
|
||||
lastModeExportPath: z.string().optional(),
|
||||
lastModeImportPath: z.string().optional(),
|
||||
rulesSettings: z
|
||||
.object({
|
||||
selectedRuleTypes: z.array(z.string()),
|
||||
addToGitignore: z.boolean(),
|
||||
includeCustomRules: z.boolean(),
|
||||
customRulesText: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export type GlobalSettings = z.infer<typeof globalSettingsSchema>
|
||||
|
|
|
|||
|
|
@ -1976,6 +1976,27 @@ export const webviewMessageHandler = async (
|
|||
// Silently fail - not critical
|
||||
}
|
||||
break
|
||||
case "updateRulesSettings":
|
||||
// Save rules settings to global state
|
||||
await updateGlobalState("rulesSettings", {
|
||||
selectedRuleTypes: message.selectedRuleTypes || ["general", "code"],
|
||||
addToGitignore: message.addToGitignore !== undefined ? message.addToGitignore : true,
|
||||
includeCustomRules: message.includeCustomRules || false,
|
||||
customRulesText: message.customRulesText || "",
|
||||
})
|
||||
break
|
||||
case "getRulesSettings":
|
||||
// Send current rules settings to webview
|
||||
const rulesSettings = getGlobalState("rulesSettings") || {
|
||||
selectedRuleTypes: ["general", "code"],
|
||||
addToGitignore: true,
|
||||
}
|
||||
await provider.postMessageToWebview({
|
||||
type: "rulesSettings",
|
||||
selectedRuleTypes: rulesSettings.selectedRuleTypes,
|
||||
addToGitignore: rulesSettings.addToGitignore,
|
||||
})
|
||||
break
|
||||
case "humanRelayResponse":
|
||||
if (message.requestId && message.text) {
|
||||
vscode.commands.executeCommand(getCommand("handleHumanRelayResponse"), {
|
||||
|
|
|
|||
|
|
@ -109,10 +109,13 @@ export interface ExtensionMessage {
|
|||
| "existingRuleFiles"
|
||||
| "showDeleteMessageDialog"
|
||||
| "showEditMessageDialog"
|
||||
| "rulesSettings"
|
||||
text?: string
|
||||
payload?: any // Add a generic payload for now, can refine later
|
||||
files?: string[] // For existingRuleFiles
|
||||
sourceFileCount?: number // For existingRuleFiles to show warning for small repos
|
||||
selectedRuleTypes?: string[] // For rulesSettings
|
||||
addToGitignore?: boolean // For rulesSettings
|
||||
action?:
|
||||
| "chatButtonClicked"
|
||||
| "mcpButtonClicked"
|
||||
|
|
@ -195,6 +198,7 @@ export type ExtensionState = Pick<
|
|||
| "allowedMaxRequests"
|
||||
| "browserToolEnabled"
|
||||
| "browserViewportSize"
|
||||
| "rulesSettings"
|
||||
| "screenshotQuality"
|
||||
| "remoteBrowserEnabled"
|
||||
| "remoteBrowserHost"
|
||||
|
|
|
|||
|
|
@ -200,6 +200,8 @@ export interface WebviewMessage {
|
|||
| "requestCodeIndexSecretStatus"
|
||||
| "generateRules"
|
||||
| "checkExistingRuleFiles"
|
||||
| "updateRulesSettings"
|
||||
| "getRulesSettings"
|
||||
text?: string
|
||||
editedMessageContent?: string
|
||||
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account"
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
const [fileSearchResults, setFileSearchResults] = useState<SearchResult[]>([])
|
||||
const [searchLoading, setSearchLoading] = useState(false)
|
||||
const [searchRequestId, setSearchRequestId] = useState<string>("")
|
||||
const [waitingForRulesSettings, setWaitingForRulesSettings] = useState(false)
|
||||
|
||||
// Close dropdown when clicking outside.
|
||||
useEffect(() => {
|
||||
|
|
@ -158,12 +159,26 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
if (message.requestId === searchRequestId) {
|
||||
setFileSearchResults(message.results || [])
|
||||
}
|
||||
} else if (message.type === "rulesSettings") {
|
||||
// Only trigger generation if we're waiting for it (user used /make-rules command)
|
||||
if (waitingForRulesSettings) {
|
||||
setWaitingForRulesSettings(false)
|
||||
// Received rules settings, now trigger generation
|
||||
vscode.postMessage({
|
||||
type: "generateRules",
|
||||
selectedRuleTypes: message.selectedRuleTypes || ["general", "code"],
|
||||
addToGitignore: message.addToGitignore !== undefined ? message.addToGitignore : true,
|
||||
alwaysAllowWriteProtected: false,
|
||||
includeCustomRules: message.includeCustomRules || false,
|
||||
customRulesText: message.customRulesText || "",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", messageHandler)
|
||||
return () => window.removeEventListener("message", messageHandler)
|
||||
}, [setInputValue, searchRequestId])
|
||||
}, [setInputValue, searchRequestId, waitingForRulesSettings])
|
||||
|
||||
const [isDraggingOver, setIsDraggingOver] = useState(false)
|
||||
const [textAreaBaseHeight, setTextAreaBaseHeight] = useState<number | undefined>(undefined)
|
||||
|
|
@ -273,6 +288,18 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
return
|
||||
}
|
||||
|
||||
if (type === ContextMenuOptionType.Rules) {
|
||||
// Handle rules generation command
|
||||
setInputValue("")
|
||||
setShowContextMenu(false)
|
||||
// Set flag to indicate we're waiting for settings
|
||||
setWaitingForRulesSettings(true)
|
||||
// First get the saved settings
|
||||
vscode.postMessage({ type: "getRulesSettings" })
|
||||
// The actual generation will be triggered when we receive the settings
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
type === ContextMenuOptionType.File ||
|
||||
type === ContextMenuOptionType.Folder ||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { EXPERIMENT_IDS, experimentConfigsMap } from "@roo/experiments"
|
|||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { cn } from "@src/lib/utils"
|
||||
|
||||
import { SetExperimentEnabled } from "./types"
|
||||
import { SetExperimentEnabled, SetCachedStateField } from "./types"
|
||||
import { SectionHeader } from "./SectionHeader"
|
||||
import { Section } from "./Section"
|
||||
import { ExperimentalFeature } from "./ExperimentalFeature"
|
||||
|
|
@ -18,12 +18,21 @@ type ExperimentalSettingsProps = HTMLAttributes<HTMLDivElement> & {
|
|||
experiments: Experiments
|
||||
setExperimentEnabled: SetExperimentEnabled
|
||||
hasUnsavedChanges?: boolean
|
||||
rulesSettings?: {
|
||||
selectedRuleTypes: string[]
|
||||
addToGitignore: boolean
|
||||
includeCustomRules: boolean
|
||||
customRulesText: string
|
||||
}
|
||||
setCachedStateField: SetCachedStateField<"rulesSettings">
|
||||
}
|
||||
|
||||
export const ExperimentalSettings = ({
|
||||
experiments,
|
||||
setExperimentEnabled,
|
||||
hasUnsavedChanges,
|
||||
rulesSettings,
|
||||
setCachedStateField,
|
||||
className,
|
||||
...props
|
||||
}: ExperimentalSettingsProps) => {
|
||||
|
|
@ -70,7 +79,7 @@ export const ExperimentalSettings = ({
|
|||
})}
|
||||
</Section>
|
||||
|
||||
<RulesSettings className="mt-3" hasUnsavedChanges={hasUnsavedChanges} />
|
||||
<RulesSettings className="mt-3" rulesSettings={rulesSettings} setCachedStateField={setCachedStateField} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
import { HTMLAttributes, useState, useEffect } from "react"
|
||||
import { VSCodeTextArea } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useAppTranslation } from "@/i18n/TranslationContext"
|
||||
import { FileText, AlertTriangle, Info, Sparkles } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { FileText, AlertTriangle, Terminal } from "lucide-react"
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StandardTooltip } from "@/components/ui"
|
||||
import { VSCodeTextArea } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { SectionHeader } from "./SectionHeader"
|
||||
import { Section } from "./Section"
|
||||
import { SetCachedStateField } from "./types"
|
||||
|
||||
type RulesSettingsProps = HTMLAttributes<HTMLDivElement> & {
|
||||
hasUnsavedChanges?: boolean
|
||||
rulesSettings?: {
|
||||
selectedRuleTypes: string[]
|
||||
addToGitignore: boolean
|
||||
includeCustomRules: boolean
|
||||
customRulesText: string
|
||||
}
|
||||
setCachedStateField: SetCachedStateField<"rulesSettings">
|
||||
}
|
||||
|
||||
interface RuleType {
|
||||
|
|
@ -23,73 +27,127 @@ interface RuleType {
|
|||
exists?: boolean
|
||||
}
|
||||
|
||||
export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesSettingsProps) => {
|
||||
export const RulesSettings = ({ rulesSettings, setCachedStateField, className, ...props }: RulesSettingsProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
const [addToGitignore, setAddToGitignore] = useState(true)
|
||||
const [alwaysAllowWriteProtected, setAlwaysAllowWriteProtected] = useState(true)
|
||||
const [selectedApiConfig, setSelectedApiConfig] = useState<string>("")
|
||||
const [includeCustomRules, setIncludeCustomRules] = useState(false)
|
||||
const [customRulesText, setCustomRulesText] = useState("")
|
||||
const [sourceFileCount, setSourceFileCount] = useState<number | null>(null)
|
||||
|
||||
const { listApiConfigMeta, currentApiConfigName } = useExtensionState()
|
||||
|
||||
const [ruleTypes, setRuleTypes] = useState<RuleType[]>([
|
||||
const allRuleTypes = [
|
||||
{
|
||||
id: "general",
|
||||
label: t("settings:rules.types.general.label"),
|
||||
description: t("settings:rules.types.general.description"),
|
||||
checked: true,
|
||||
exists: false,
|
||||
},
|
||||
{
|
||||
id: "code",
|
||||
label: t("settings:rules.types.code.label"),
|
||||
description: t("settings:rules.types.code.description"),
|
||||
checked: true,
|
||||
exists: false,
|
||||
},
|
||||
{
|
||||
id: "architect",
|
||||
label: t("settings:rules.types.architect.label"),
|
||||
description: t("settings:rules.types.architect.description"),
|
||||
checked: true,
|
||||
exists: false,
|
||||
},
|
||||
{
|
||||
id: "debug",
|
||||
label: t("settings:rules.types.debug.label"),
|
||||
description: t("settings:rules.types.debug.description"),
|
||||
checked: true,
|
||||
exists: false,
|
||||
},
|
||||
{
|
||||
id: "docs-extractor",
|
||||
label: t("settings:rules.types.docsExtractor.label"),
|
||||
description: t("settings:rules.types.docsExtractor.description"),
|
||||
checked: true,
|
||||
exists: false,
|
||||
},
|
||||
])
|
||||
]
|
||||
|
||||
const [ruleTypes, setRuleTypes] = useState<RuleType[]>(
|
||||
allRuleTypes.map((ruleType) => ({
|
||||
...ruleType,
|
||||
checked: rulesSettings?.selectedRuleTypes.includes(ruleType.id) ?? true,
|
||||
exists: false,
|
||||
})),
|
||||
)
|
||||
|
||||
// Update rule types when rulesSettings prop changes
|
||||
useEffect(() => {
|
||||
if (rulesSettings) {
|
||||
setRuleTypes((prev) =>
|
||||
prev.map((ruleType) => ({
|
||||
...ruleType,
|
||||
checked: rulesSettings.selectedRuleTypes.includes(ruleType.id),
|
||||
})),
|
||||
)
|
||||
}
|
||||
}, [rulesSettings])
|
||||
|
||||
const handleRuleTypeToggle = (id: string) => {
|
||||
setRuleTypes((prev) => prev.map((rule) => (rule.id === id ? { ...rule, checked: !rule.checked } : rule)))
|
||||
|
||||
// Update the cached state using the proper pattern
|
||||
const updatedRules = ruleTypes.map((rule) => (rule.id === id ? { ...rule, checked: !rule.checked } : rule))
|
||||
const selectedRuleTypes = updatedRules.filter((rule) => rule.checked).map((rule) => rule.id)
|
||||
|
||||
setCachedStateField("rulesSettings", {
|
||||
selectedRuleTypes,
|
||||
addToGitignore: rulesSettings?.addToGitignore ?? true,
|
||||
includeCustomRules: rulesSettings?.includeCustomRules ?? false,
|
||||
customRulesText: rulesSettings?.customRulesText ?? "",
|
||||
})
|
||||
}
|
||||
|
||||
// Check for existing files and get current settings when component mounts
|
||||
const handleGitignoreToggle = (checked: boolean) => {
|
||||
setCachedStateField("rulesSettings", {
|
||||
selectedRuleTypes: rulesSettings?.selectedRuleTypes ?? [
|
||||
"general",
|
||||
"code",
|
||||
"architect",
|
||||
"debug",
|
||||
"docs-extractor",
|
||||
],
|
||||
addToGitignore: checked,
|
||||
includeCustomRules: rulesSettings?.includeCustomRules ?? false,
|
||||
customRulesText: rulesSettings?.customRulesText ?? "",
|
||||
})
|
||||
}
|
||||
|
||||
const handleIncludeCustomRulesToggle = (checked: boolean) => {
|
||||
setCachedStateField("rulesSettings", {
|
||||
selectedRuleTypes: rulesSettings?.selectedRuleTypes ?? [
|
||||
"general",
|
||||
"code",
|
||||
"architect",
|
||||
"debug",
|
||||
"docs-extractor",
|
||||
],
|
||||
addToGitignore: rulesSettings?.addToGitignore ?? true,
|
||||
includeCustomRules: checked,
|
||||
customRulesText: rulesSettings?.customRulesText ?? "",
|
||||
})
|
||||
}
|
||||
|
||||
const handleCustomRulesTextChange = (text: string) => {
|
||||
setCachedStateField("rulesSettings", {
|
||||
selectedRuleTypes: rulesSettings?.selectedRuleTypes ?? [
|
||||
"general",
|
||||
"code",
|
||||
"architect",
|
||||
"debug",
|
||||
"docs-extractor",
|
||||
],
|
||||
addToGitignore: rulesSettings?.addToGitignore ?? true,
|
||||
includeCustomRules: rulesSettings?.includeCustomRules ?? false,
|
||||
customRulesText: text,
|
||||
})
|
||||
}
|
||||
|
||||
// Check for existing files when component mounts
|
||||
useEffect(() => {
|
||||
vscode.postMessage({
|
||||
type: "checkExistingRuleFiles",
|
||||
})
|
||||
|
||||
// Request current state to get alwaysAllowWriteProtected value
|
||||
vscode.postMessage({ type: "webviewDidLaunch" })
|
||||
|
||||
// Set default API config
|
||||
if (currentApiConfigName && !selectedApiConfig) {
|
||||
setSelectedApiConfig(currentApiConfigName)
|
||||
}
|
||||
}, [currentApiConfigName, selectedApiConfig])
|
||||
// Request current rules settings
|
||||
vscode.postMessage({ type: "getRulesSettings" })
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const handleMessage = (event: MessageEvent) => {
|
||||
|
|
@ -106,11 +164,9 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
|
|||
if (message.sourceFileCount !== undefined) {
|
||||
setSourceFileCount(message.sourceFileCount)
|
||||
}
|
||||
} else if (message.type === "state") {
|
||||
// Update alwaysAllowWriteProtected from the extension state
|
||||
if (message.state?.alwaysAllowWriteProtected !== undefined) {
|
||||
setAlwaysAllowWriteProtected(message.state.alwaysAllowWriteProtected)
|
||||
}
|
||||
} else if (message.type === "rulesSettings") {
|
||||
// Update settings from saved preferences - this is now handled by props
|
||||
// The component will re-render when rulesSettings prop changes
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,27 +174,8 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
|
|||
return () => window.removeEventListener("message", handleMessage)
|
||||
}, [])
|
||||
|
||||
const handleGenerateRules = () => {
|
||||
const selectedRules = ruleTypes.filter((rule) => rule.checked)
|
||||
if (selectedRules.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// Send message to extension to generate rules
|
||||
vscode.postMessage({
|
||||
type: "generateRules",
|
||||
selectedRuleTypes: selectedRules.map((rule) => rule.id),
|
||||
addToGitignore,
|
||||
alwaysAllowWriteProtected,
|
||||
apiConfigName: selectedApiConfig,
|
||||
includeCustomRules,
|
||||
customRulesText: includeCustomRules ? customRulesText : "",
|
||||
})
|
||||
}
|
||||
|
||||
const existingRules = ruleTypes.filter((rule) => rule.checked && rule.exists)
|
||||
const hasExistingFiles = existingRules.length > 0
|
||||
const hasSelectedRules = ruleTypes.some((rule) => rule.checked)
|
||||
|
||||
return (
|
||||
<div className={cn("flex flex-col gap-2", className)} {...props}>
|
||||
|
|
@ -150,198 +187,139 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
|
|||
</SectionHeader>
|
||||
|
||||
<Section>
|
||||
<div className="space-y-6">
|
||||
{/* Magic Rules Generation subsection */}
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex items-center gap-2 font-bold">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<div>{t("settings:rules.magicGeneration.title")}</div>
|
||||
<div className="space-y-4">
|
||||
{/* Command Line Instructions */}
|
||||
<div className="flex items-start gap-2">
|
||||
<Terminal className="w-4 h-4 text-vscode-foreground mt-0.5 flex-shrink-0" />
|
||||
<div>
|
||||
<div className="font-medium mb-1">
|
||||
{t("settings:rules.commandTitle")}{" "}
|
||||
<code className="bg-vscode-textBlockQuote-background px-2 py-1 rounded">
|
||||
/make-rules
|
||||
</code>
|
||||
</div>
|
||||
<div className="text-vscode-descriptionForeground">
|
||||
{t("settings:rules.magicGeneration.description")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
|
||||
{/* Recommendation box */}
|
||||
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-infoBackground border border-vscode-inputValidation-infoBorder rounded-md">
|
||||
<Info className="w-4 h-4 text-vscode-inputValidation-infoForeground mt-0.5 flex-shrink-0" />
|
||||
<div className="text-sm text-vscode-inputValidation-infoForeground">
|
||||
{t("settings:rules.autoApproveRecommendation")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className="text-sm font-medium mb-3">{t("settings:rules.selectTypes")}</h4>
|
||||
<div className="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2">
|
||||
{ruleTypes.map((ruleType) => (
|
||||
<div
|
||||
key={ruleType.id}
|
||||
onClick={() => handleRuleTypeToggle(ruleType.id)}
|
||||
className={cn(
|
||||
"relative p-3 rounded-md border cursor-pointer transition-all",
|
||||
"hover:border-vscode-focusBorder",
|
||||
ruleType.checked
|
||||
? "bg-vscode-list-activeSelectionBackground border-vscode-focusBorder"
|
||||
: "bg-vscode-editor-background border-vscode-panel-border",
|
||||
)}>
|
||||
<div className="flex-1">
|
||||
<div className="text-sm font-medium flex items-center gap-1">
|
||||
{ruleType.label}
|
||||
{ruleType.exists && (
|
||||
<span
|
||||
className="text-vscode-testing-iconQueued"
|
||||
title={t("settings:rules.fileExists")}>
|
||||
•
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-1">
|
||||
{ruleType.description}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Small repository warning */}
|
||||
{sourceFileCount !== null && sourceFileCount > 0 && sourceFileCount < 20 && (
|
||||
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
|
||||
<AlertTriangle className="w-4 h-4 text-vscode-inputValidation-warningForeground mt-0.5 flex-shrink-0" />
|
||||
<div className="text-sm text-vscode-inputValidation-warningForeground">
|
||||
{t("settings:rules.smallRepoWarning", { count: sourceFileCount })}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{hasExistingFiles && (
|
||||
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
|
||||
<AlertTriangle className="w-4 h-4 text-vscode-inputValidation-warningForeground mt-0.5 flex-shrink-0" />
|
||||
<div className="text-sm text-vscode-inputValidation-warningForeground">
|
||||
<div>{t("settings:rules.overwriteWarning")}</div>
|
||||
<ul className="mt-1 ml-4 list-disc">
|
||||
{existingRules.map((rule) => (
|
||||
<li key={rule.id}>{rule.label}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="border-t border-vscode-panel-border pt-2 space-y-2">
|
||||
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={addToGitignore}
|
||||
onChange={(e) => setAddToGitignore(e.target.checked)}
|
||||
/>
|
||||
<div>
|
||||
<div className="text-sm font-medium">{t("settings:rules.addToGitignore")}</div>
|
||||
<div className="text-xs text-vscode-descriptionForeground">
|
||||
{t("settings:rules.addToGitignoreDescription")}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={alwaysAllowWriteProtected}
|
||||
onChange={(e) => {
|
||||
setAlwaysAllowWriteProtected(e.target.checked)
|
||||
vscode.postMessage({
|
||||
type: "alwaysAllowWriteProtected",
|
||||
bool: e.target.checked,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<div className="text-sm font-medium">
|
||||
{t("settings:rules.autoApproveProtected")}
|
||||
</div>
|
||||
<div className="text-xs text-vscode-descriptionForeground">
|
||||
{t("settings:rules.autoApproveProtectedDescription")}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={includeCustomRules}
|
||||
onChange={(e) => setIncludeCustomRules(e.target.checked)}
|
||||
/>
|
||||
<div>
|
||||
<div className="text-sm font-medium">
|
||||
{t("settings:rules.includeCustomRules")}
|
||||
</div>
|
||||
<div className="text-xs text-vscode-descriptionForeground">
|
||||
{t("settings:rules.includeCustomRulesDescription")}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
{includeCustomRules && (
|
||||
<div className="mt-3 pl-6">
|
||||
<VSCodeTextArea
|
||||
resize="vertical"
|
||||
value={customRulesText}
|
||||
onChange={(e) => {
|
||||
const value =
|
||||
(e as unknown as CustomEvent)?.detail?.target?.value ||
|
||||
((e as any).target as HTMLTextAreaElement).value
|
||||
setCustomRulesText(value)
|
||||
}}
|
||||
placeholder={t("settings:rules.customRulesPlaceholder")}
|
||||
rows={6}
|
||||
className="w-full"
|
||||
/>
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-1">
|
||||
{t("settings:rules.customRulesHint")}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 mt-3">
|
||||
<Select value={selectedApiConfig} onValueChange={setSelectedApiConfig}>
|
||||
<SelectTrigger className="w-fit min-w-[5rem] max-w-[8rem]">
|
||||
<SelectValue placeholder={t("settings:rules.selectApiConfig")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{(listApiConfigMeta || []).map((config) => (
|
||||
<SelectItem key={config.id} value={config.name}>
|
||||
{config.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<StandardTooltip
|
||||
content={
|
||||
hasUnsavedChanges
|
||||
? t("settings:rules.unsavedChangesError")
|
||||
: !hasSelectedRules
|
||||
? t("settings:rules.noRulesSelected")
|
||||
: t("settings:rules.generateButtonTooltip")
|
||||
}>
|
||||
<span className="w-full">
|
||||
<Button
|
||||
onClick={handleGenerateRules}
|
||||
disabled={!selectedApiConfig || hasUnsavedChanges || !hasSelectedRules}
|
||||
variant="default"
|
||||
size="default"
|
||||
className="w-full">
|
||||
<>
|
||||
<FileText className="mr-2 h-4 w-4" />
|
||||
{t("settings:rules.generateButton")}
|
||||
</>
|
||||
</Button>
|
||||
</span>
|
||||
</StandardTooltip>
|
||||
{t("settings:rules.commandDescription")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Settings Content */}
|
||||
<div className="pl-3 border-l-2 border-vscode-button-background space-y-4">
|
||||
{/* Add to .gitignore option */}
|
||||
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={rulesSettings?.addToGitignore ?? true}
|
||||
onChange={(e) => handleGitignoreToggle(e.target.checked)}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-medium">{t("settings:rules.addToGitignore")}</div>
|
||||
<div className="text-vscode-descriptionForeground text-sm">
|
||||
{t("settings:rules.addToGitignoreDescription")}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
{/* Rule Type Selection */}
|
||||
<div>
|
||||
<h4 className="font-medium mb-3">{t("settings:rules.selectTypes")}</h4>
|
||||
<div className="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2">
|
||||
{ruleTypes.map((ruleType) => (
|
||||
<div
|
||||
key={ruleType.id}
|
||||
onClick={() => handleRuleTypeToggle(ruleType.id)}
|
||||
className={cn(
|
||||
"relative p-3 rounded-md border cursor-pointer transition-all",
|
||||
"hover:border-vscode-focusBorder",
|
||||
ruleType.checked
|
||||
? "bg-vscode-list-activeSelectionBackground border-vscode-focusBorder"
|
||||
: "bg-vscode-editor-background border-vscode-panel-border",
|
||||
)}>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium flex items-center gap-1">
|
||||
{ruleType.label}
|
||||
{ruleType.exists && (
|
||||
<span
|
||||
className="text-vscode-testing-iconQueued"
|
||||
title={t("settings:rules.fileExists")}>
|
||||
•
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-vscode-descriptionForeground text-sm mt-1">
|
||||
{ruleType.description}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Custom Rules Section */}
|
||||
<div>
|
||||
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80 mb-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={rulesSettings?.includeCustomRules ?? false}
|
||||
onChange={(e) => handleIncludeCustomRulesToggle(e.target.checked)}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-medium">{t("settings:rules.includeCustomRules")}</div>
|
||||
<div className="text-vscode-descriptionForeground text-sm">
|
||||
{t("settings:rules.includeCustomRulesDescription")}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
{rulesSettings?.includeCustomRules && (
|
||||
<div className="mt-3">
|
||||
<label className="block font-medium mb-1">Custom Rules Template</label>
|
||||
<VSCodeTextArea
|
||||
resize="vertical"
|
||||
value={rulesSettings?.customRulesText ?? ""}
|
||||
onChange={(e) => {
|
||||
const value =
|
||||
(e as unknown as CustomEvent)?.detail?.target?.value ||
|
||||
((e as any).target as HTMLTextAreaElement).value
|
||||
handleCustomRulesTextChange(value)
|
||||
}}
|
||||
placeholder={t("settings:rules.customRulesPlaceholder")}
|
||||
rows={6}
|
||||
className="w-full"
|
||||
/>
|
||||
<div className="text-sm text-vscode-descriptionForeground mt-1">
|
||||
{t("settings:rules.customRulesHint")}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Small repository warning */}
|
||||
{sourceFileCount !== null && sourceFileCount > 0 && sourceFileCount < 20 && (
|
||||
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
|
||||
<AlertTriangle className="w-4 h-4 text-vscode-inputValidation-warningForeground mt-0.5 flex-shrink-0" />
|
||||
<div className="text-vscode-inputValidation-warningForeground">
|
||||
{t("settings:rules.smallRepoWarning", { count: sourceFileCount })}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Existing files warning */}
|
||||
{hasExistingFiles && (
|
||||
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
|
||||
<AlertTriangle className="w-4 h-4 text-vscode-inputValidation-warningForeground mt-0.5 flex-shrink-0" />
|
||||
<div className="text-vscode-inputValidation-warningForeground">
|
||||
<div>{t("settings:rules.overwriteWarning")}</div>
|
||||
<ul className="mt-1 ml-4 list-disc">
|
||||
{existingRules.map((rule) => (
|
||||
<li key={rule.id}>{rule.label}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
alwaysAllowFollowupQuestions,
|
||||
alwaysAllowUpdateTodoList,
|
||||
followupAutoApproveTimeoutMs,
|
||||
rulesSettings,
|
||||
} = cachedState
|
||||
|
||||
const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration])
|
||||
|
|
@ -702,6 +703,8 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
setExperimentEnabled={setExperimentEnabled}
|
||||
experiments={experiments}
|
||||
hasUnsavedChanges={isChangeDetected}
|
||||
rulesSettings={rulesSettings}
|
||||
setCachedStateField={setCachedStateField}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -229,6 +229,12 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
},
|
||||
codebaseIndexModels: { ollama: {}, openai: {} },
|
||||
alwaysAllowUpdateTodoList: true,
|
||||
rulesSettings: {
|
||||
selectedRuleTypes: ["general", "code", "architect", "debug", "docs-extractor"],
|
||||
addToGitignore: true,
|
||||
includeCustomRules: false,
|
||||
customRulesText: "",
|
||||
},
|
||||
})
|
||||
|
||||
const [didHydrateState, setDidHydrateState] = useState(false)
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ca/settings.json
generated
1
webview-ui/src/i18n/locales/ca/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Afegir automàticament els arxius de regles generats a .gitignore per evitar que es facin commit al control de versions",
|
||||
"autoApproveProtected": "Aprovar automàticament l'escriptura d'arxius protegits",
|
||||
"autoApproveProtectedDescription": "Permetre que Roo creï i escrigui al directori .roo sense requerir aprovació manual",
|
||||
"autoApproveRecommendation": "Per a la millor experiència de generació de regles, recomanem habilitar l'aprovació automàtica tant per a operacions de lectura com d'escriptura a la configuració d'Aprovació Automàtica de dalt.",
|
||||
"selectApiConfig": "Seleccionar configuració d'API",
|
||||
"includeCustomRules": "Incloure les meves regles personalitzades",
|
||||
"includeCustomRulesDescription": "Afegir instruccions personalitzades al prompt de generació de regles",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/de/settings.json
generated
1
webview-ui/src/i18n/locales/de/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Füge die generierten Regeldateien automatisch zu .gitignore hinzu, um zu verhindern, dass sie in die Versionskontrolle übernommen werden",
|
||||
"autoApproveProtected": "Geschützte Dateischreibvorgänge automatisch genehmigen",
|
||||
"autoApproveProtectedDescription": "Erlaube Roo, das .roo-Verzeichnis zu erstellen und zu beschreiben, ohne manuelle Genehmigung zu benötigen",
|
||||
"autoApproveRecommendation": "Für die beste Erfahrung beim Generieren von Regeln empfehlen wir, die automatische Genehmigung sowohl für Lese- als auch für Schreibvorgänge in den Auto-Approve-Einstellungen oben zu aktivieren.",
|
||||
"selectApiConfig": "API-Konfiguration auswählen",
|
||||
"includeCustomRules": "Meine eigenen Regeln einbeziehen",
|
||||
"includeCustomRulesDescription": "Füge benutzerdefinierte Anweisungen zur Regelgenerierungsaufforderung hinzu",
|
||||
|
|
|
|||
|
|
@ -653,13 +653,14 @@
|
|||
"addToGitignoreDescription": "Automatically add the generated rule files to .gitignore to prevent them from being committed to version control",
|
||||
"autoApproveProtected": "Auto-approve protected file writes",
|
||||
"autoApproveProtectedDescription": "Allow Roo to make and write to .roo directory without requiring manual approval",
|
||||
"autoApproveRecommendation": "For the best experience generating rules, we recommend enabling auto-approve for both read and write operations in the Auto-Approve settings above.",
|
||||
"selectApiConfig": "Select API configuration",
|
||||
"includeCustomRules": "Include my own rules",
|
||||
"includeCustomRulesDescription": "Add custom instructions to the rule generation prompt",
|
||||
"customRulesPlaceholder": "Enter your custom rules or instructions here...",
|
||||
"customRulesHint": "These will be included in the prompt when generating rules for your project",
|
||||
"smallRepoWarning": "This repository contains only {{count}} files. With limited code examples, the generated rules may be overly specific to your current implementation. Consider regenerating rules as your project grows."
|
||||
"smallRepoWarning": "This repository contains only {{count}} files. With limited code examples, the generated rules may be overly specific to your current implementation. Consider regenerating rules as your project grows.",
|
||||
"commandTitle": "Initialize rules using the chat command:",
|
||||
"commandDescription": "Type this command in the chat to generate AI rules based on your selected preferences below."
|
||||
},
|
||||
"promptCaching": {
|
||||
"label": "Disable prompt caching",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/es/settings.json
generated
1
webview-ui/src/i18n/locales/es/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Añadir automáticamente los archivos de reglas generados a .gitignore para evitar que se confirmen en el control de versiones",
|
||||
"autoApproveProtected": "Aprobar automáticamente escrituras de archivos protegidos",
|
||||
"autoApproveProtectedDescription": "Permitir a Roo crear y escribir en el directorio .roo sin requerir aprobación manual",
|
||||
"autoApproveRecommendation": "Para la mejor experiencia generando reglas, recomendamos habilitar la aprobación automática tanto para operaciones de lectura como de escritura en la configuración de Aprobación Automática arriba.",
|
||||
"selectApiConfig": "Seleccionar configuración de API",
|
||||
"includeCustomRules": "Incluir mis propias reglas",
|
||||
"includeCustomRulesDescription": "Añadir instrucciones personalizadas al prompt de generación de reglas",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/fr/settings.json
generated
1
webview-ui/src/i18n/locales/fr/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Ajouter automatiquement les fichiers de règles générés à .gitignore pour éviter qu'ils soient validés dans le contrôle de version",
|
||||
"autoApproveProtected": "Approuver automatiquement les écritures de fichiers protégés",
|
||||
"autoApproveProtectedDescription": "Permettre à Roo de créer et d'écrire dans le répertoire .roo sans nécessiter d'approbation manuelle",
|
||||
"autoApproveRecommendation": "Pour la meilleure expérience de génération de règles, nous recommandons d'activer l'approbation automatique pour les opérations de lecture et d'écriture dans les paramètres d'approbation automatique ci-dessus.",
|
||||
"selectApiConfig": "Sélectionner la configuration API",
|
||||
"includeCustomRules": "Inclure mes propres règles",
|
||||
"includeCustomRulesDescription": "Ajouter des instructions personnalisées à l'invite de génération de règles",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/hi/settings.json
generated
1
webview-ui/src/i18n/locales/hi/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "जेनेरेटेड रूल फाइलों को ऑटोमेटिकली .gitignore में ऐड करो ताकि वे वर्जन कंट्रोल में कमिट न हों",
|
||||
"autoApproveProtected": "प्रोटेक्टेड फाइल राइटिंग को ऑटो अप्रूव करो",
|
||||
"autoApproveProtectedDescription": "Roo को मैन्युअल अप्रूवल की जरूरत के बिना .roo डायरेक्टरी में क्रिएट और राइट करने की अनुमति दो",
|
||||
"autoApproveRecommendation": "बेस्ट रूल जेनेरेशन एक्सपीरियंस के लिए, हम ऊपर ऑटो अप्रूवल सेटिंग्स में रीड और राइट दोनों ऑपरेशन्स के लिए ऑटो अप्रूवल इनेबल करने की सिफारिश करते हैं।",
|
||||
"selectApiConfig": "API कॉन्फ़िगरेशन सेलेक्ट करो",
|
||||
"includeCustomRules": "मेरे कस्टम रूल्स इंक्लूड करो",
|
||||
"includeCustomRulesDescription": "रूल जेनेरेशन प्रॉम्प्ट में कस्टम इंस्ट्रक्शन्स ऐड करो",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/id/settings.json
generated
1
webview-ui/src/i18n/locales/id/settings.json
generated
|
|
@ -623,7 +623,6 @@
|
|||
"addToGitignoreDescription": "Secara otomatis menambahkan file aturan yang dihasilkan ke .gitignore untuk mencegah mereka di-commit ke version control",
|
||||
"autoApproveProtected": "Otomatis setujui penulisan file yang dilindungi",
|
||||
"autoApproveProtectedDescription": "Izinkan Roo untuk membuat dan menulis ke direktori .roo tanpa memerlukan persetujuan manual",
|
||||
"autoApproveRecommendation": "Untuk pengalaman generasi aturan terbaik, kami merekomendasikan mengaktifkan persetujuan otomatis untuk operasi baca dan tulis di pengaturan Auto Approval di atas.",
|
||||
"selectApiConfig": "Pilih Konfigurasi API",
|
||||
"includeCustomRules": "Sertakan aturan kustom saya",
|
||||
"includeCustomRulesDescription": "Tambahkan instruksi kustom ke prompt generasi aturan",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/it/settings.json
generated
1
webview-ui/src/i18n/locales/it/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Aggiungi automaticamente i file di regole generati a .gitignore per evitare che vengano committati nel controllo versione",
|
||||
"autoApproveProtected": "Approva automaticamente scritture file protetti",
|
||||
"autoApproveProtectedDescription": "Consenti a Roo di creare e scrivere nella directory .roo senza richiedere approvazione manuale",
|
||||
"autoApproveRecommendation": "Per la migliore esperienza nella generazione di regole, raccomandiamo di abilitare l'approvazione automatica sia per le operazioni di lettura che di scrittura nelle impostazioni di Approvazione Automatica sopra.",
|
||||
"selectApiConfig": "Seleziona configurazione API",
|
||||
"includeCustomRules": "Includi le mie regole",
|
||||
"includeCustomRulesDescription": "Aggiungi istruzioni personalizzate al prompt di generazione regole",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ja/settings.json
generated
1
webview-ui/src/i18n/locales/ja/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "生成されたルールファイルを自動的に.gitignoreに追加して、バージョン管理にコミットされないようにします",
|
||||
"autoApproveProtected": "保護されたファイル書き込みを自動承認",
|
||||
"autoApproveProtectedDescription": "Rooが手動承認を必要とせずに.rooディレクトリを作成・書き込みできるようにします",
|
||||
"autoApproveRecommendation": "ルール生成の最良の体験のために、上記の自動承認設定で読み取りと書き込み操作の両方の自動承認を有効にすることをお勧めします。",
|
||||
"selectApiConfig": "API設定を選択",
|
||||
"includeCustomRules": "独自のルールを含める",
|
||||
"includeCustomRulesDescription": "ルール生成プロンプトにカスタム指示を追加",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ko/settings.json
generated
1
webview-ui/src/i18n/locales/ko/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "생성된 규칙 파일을 자동으로 .gitignore에 추가하여 버전 관리에 커밋되지 않도록 합니다",
|
||||
"autoApproveProtected": "보호된 파일 쓰기 자동 승인",
|
||||
"autoApproveProtectedDescription": "Roo가 수동 승인 없이 .roo 디렉토리를 생성하고 쓸 수 있도록 허용",
|
||||
"autoApproveRecommendation": "최상의 규칙 생성 경험을 위해 위의 자동 승인 설정에서 읽기 및 쓰기 작업 모두에 대한 자동 승인을 활성화하는 것을 권장합니다.",
|
||||
"selectApiConfig": "API 구성 선택",
|
||||
"includeCustomRules": "내 규칙 포함",
|
||||
"includeCustomRulesDescription": "규칙 생성 프롬프트에 사용자 정의 지침 추가",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/nl/settings.json
generated
1
webview-ui/src/i18n/locales/nl/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Voeg gegenereerde regelbestanden automatisch toe aan .gitignore om te voorkomen dat ze worden gecommit naar versiebeheer",
|
||||
"autoApproveProtected": "Automatisch goedkeuren van schrijven naar beschermde bestanden",
|
||||
"autoApproveProtectedDescription": "Sta Roo toe om te maken en schrijven naar de .roo directory zonder handmatige goedkeuring te vereisen",
|
||||
"autoApproveRecommendation": "Voor de beste regelgeneratie-ervaring raden we aan om automatische goedkeuring in te schakelen voor zowel lees- als schrijfoperaties in de Auto Approval instellingen hierboven.",
|
||||
"selectApiConfig": "Selecteer API-configuratie",
|
||||
"includeCustomRules": "Mijn aangepaste regels opnemen",
|
||||
"includeCustomRulesDescription": "Voeg aangepaste instructies toe aan de regelgeneratie prompt",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/pl/settings.json
generated
1
webview-ui/src/i18n/locales/pl/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Automatycznie dodaj wygenerowane pliki zasad do .gitignore, aby zapobiec ich commitowaniu do kontroli wersji",
|
||||
"autoApproveProtected": "Automatycznie zatwierdź pisanie chronionych plików",
|
||||
"autoApproveProtectedDescription": "Pozwól Roo na tworzenie i pisanie do katalogu .roo bez wymagania ręcznego zatwierdzenia",
|
||||
"autoApproveRecommendation": "Dla najlepszego doświadczenia generowania zasad zalecamy włączenie automatycznego zatwierdzania zarówno dla operacji odczytu, jak i zapisu w ustawieniach Auto Approval powyżej.",
|
||||
"selectApiConfig": "Wybierz konfigurację API",
|
||||
"includeCustomRules": "Uwzględnij moje niestandardowe zasady",
|
||||
"includeCustomRulesDescription": "Dodaj niestandardowe instrukcje do promptu generowania zasad",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/pt-BR/settings.json
generated
1
webview-ui/src/i18n/locales/pt-BR/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Adicionar automaticamente os arquivos de regras gerados ao .gitignore para evitar que sejam commitados no controle de versão",
|
||||
"autoApproveProtected": "Aprovar automaticamente gravações de arquivos protegidos",
|
||||
"autoApproveProtectedDescription": "Permitir que o Roo crie e grave no diretório .roo sem exigir aprovação manual",
|
||||
"autoApproveRecommendation": "Para a melhor experiência gerando regras, recomendamos habilitar a aprovação automática tanto para operações de leitura quanto de escrita nas configurações de Aprovação Automática acima.",
|
||||
"selectApiConfig": "Selecionar configuração da API",
|
||||
"includeCustomRules": "Incluir minhas próprias regras",
|
||||
"includeCustomRulesDescription": "Adicionar instruções personalizadas ao prompt de geração de regras",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ru/settings.json
generated
1
webview-ui/src/i18n/locales/ru/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Автоматически добавить сгенерированные файлы правил в .gitignore, чтобы предотвратить их коммит в систему контроля версий",
|
||||
"autoApproveProtected": "Автоматически одобрять запись защищённых файлов",
|
||||
"autoApproveProtectedDescription": "Разрешить Roo создавать и записывать в директорию .roo без требования ручного одобрения",
|
||||
"autoApproveRecommendation": "Для лучшего опыта генерации правил мы рекомендуем включить автоматическое одобрение как для операций чтения, так и записи в настройках Автоматического Одобрения выше.",
|
||||
"selectApiConfig": "Выбрать конфигурацию API",
|
||||
"includeCustomRules": "Включить мои собственные правила",
|
||||
"includeCustomRulesDescription": "Добавить пользовательские инструкции в промпт генерации правил",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/tr/settings.json
generated
1
webview-ui/src/i18n/locales/tr/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Üretilen kural dosyalarını otomatik olarak .gitignore'a ekleyerek sürüm kontrolüne commit edilmesini önle",
|
||||
"autoApproveProtected": "Korumalı dosya yazımını otomatik onayla",
|
||||
"autoApproveProtectedDescription": "Roo'nun manuel onay gerektirmeden .roo dizininde oluşturma ve yazma yapmasına izin ver",
|
||||
"autoApproveRecommendation": "En iyi kural üretimi deneyimi için yukarıdaki Otomatik Onay ayarlarında hem okuma hem de yazma işlemleri için otomatik onayı etkinleştirmenizi öneririz.",
|
||||
"selectApiConfig": "API Yapılandırması Seç",
|
||||
"includeCustomRules": "Kendi kurallarımı dahil et",
|
||||
"includeCustomRulesDescription": "Kural üretimi promptuna özel talimatlar ekle",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/vi/settings.json
generated
1
webview-ui/src/i18n/locales/vi/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "Tự động thêm các tệp quy tắc được tạo vào .gitignore để ngăn chúng được commit vào kiểm soát phiên bản",
|
||||
"autoApproveProtected": "Tự động phê duyệt ghi tệp được bảo vệ",
|
||||
"autoApproveProtectedDescription": "Cho phép Roo tạo và ghi vào thư mục .roo mà không cần phê duyệt thủ công",
|
||||
"autoApproveRecommendation": "Để có trải nghiệm tạo quy tắc tốt nhất, chúng tôi khuyến nghị bật tự động phê duyệt cho cả hoạt động đọc và ghi trong cài đặt Tự động phê duyệt ở trên.",
|
||||
"selectApiConfig": "Chọn cấu hình API",
|
||||
"includeCustomRules": "Bao gồm quy tắc tùy chỉnh của tôi",
|
||||
"includeCustomRulesDescription": "Thêm hướng dẫn tùy chỉnh vào prompt tạo quy tắc",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/zh-CN/settings.json
generated
1
webview-ui/src/i18n/locales/zh-CN/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "自动将生成的规则文件添加到 .gitignore 以防止提交到版本控制",
|
||||
"autoApproveProtected": "自动批准受保护文件写入",
|
||||
"autoApproveProtectedDescription": "允许 Roo 创建和写入 .roo 目录而无需手动批准",
|
||||
"autoApproveRecommendation": "为获得最佳规则生成体验,我们建议在上方的自动批准设置中启用读取和写入操作的自动批准。",
|
||||
"selectApiConfig": "选择 API 配置",
|
||||
"includeCustomRules": "包含我的自定义规则",
|
||||
"includeCustomRulesDescription": "向规则生成提示添加自定义指令",
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/zh-TW/settings.json
generated
1
webview-ui/src/i18n/locales/zh-TW/settings.json
generated
|
|
@ -619,7 +619,6 @@
|
|||
"addToGitignoreDescription": "自動將產生的規則檔案新增到 .gitignore 以防止提交到版本控制",
|
||||
"autoApproveProtected": "自動核准受保護檔案寫入",
|
||||
"autoApproveProtectedDescription": "允許 Roo 建立和寫入 .roo 目錄而無需手動核准",
|
||||
"autoApproveRecommendation": "為獲得最佳規則產生體驗,我們建議在上方的自動核准設定中啟用讀取和寫入操作的自動核准。",
|
||||
"selectApiConfig": "選擇 API 設定",
|
||||
"includeCustomRules": "包含我的自訂規則",
|
||||
"includeCustomRulesDescription": "向規則產生提示新增自訂指令",
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ export enum ContextMenuOptionType {
|
|||
Git = "git",
|
||||
NoResults = "noResults",
|
||||
Mode = "mode", // Add mode type
|
||||
Rules = "rules", // Add rules type
|
||||
}
|
||||
|
||||
export interface ContextMenuQueryItem {
|
||||
|
|
@ -123,38 +124,70 @@ export function getContextMenuOptions(
|
|||
dynamicSearchResults: SearchResult[] = [],
|
||||
modes?: ModeConfig[],
|
||||
): ContextMenuQueryItem[] {
|
||||
// Handle slash commands for modes
|
||||
// Handle slash commands
|
||||
if (query.startsWith("/") && inputValue.startsWith("/")) {
|
||||
const modeQuery = query.slice(1)
|
||||
if (!modes?.length) return [{ type: ContextMenuOptionType.NoResults }]
|
||||
const commandQuery = query.slice(1).toLowerCase()
|
||||
|
||||
// Create searchable strings array for fzf
|
||||
const searchableItems = modes.map((mode) => ({
|
||||
original: mode,
|
||||
searchStr: mode.name,
|
||||
}))
|
||||
// Check if it's the make-rules command
|
||||
if (commandQuery === "" || "make-rules".startsWith(commandQuery)) {
|
||||
const rulesCommand: ContextMenuQueryItem = {
|
||||
type: ContextMenuOptionType.Rules,
|
||||
value: "make-rules",
|
||||
label: "Make Rules",
|
||||
description: "Generate AI rules for your project",
|
||||
icon: "$(book)",
|
||||
}
|
||||
|
||||
// Initialize fzf instance for fuzzy search
|
||||
const fzf = new Fzf(searchableItems, {
|
||||
selector: (item) => item.searchStr,
|
||||
})
|
||||
// If query is empty or matches "make-rules", show rules command
|
||||
if (commandQuery === "" || "make-rules".startsWith(commandQuery)) {
|
||||
// Also include mode options if query is empty
|
||||
if (commandQuery === "" && modes?.length) {
|
||||
const modeOptions = modes.map((mode) => ({
|
||||
type: ContextMenuOptionType.Mode,
|
||||
value: mode.slug,
|
||||
label: mode.name,
|
||||
description: getModeDescription(mode),
|
||||
}))
|
||||
return [rulesCommand, ...modeOptions]
|
||||
}
|
||||
return [rulesCommand]
|
||||
}
|
||||
}
|
||||
|
||||
// Get fuzzy matching items
|
||||
const matchingModes = modeQuery
|
||||
? fzf.find(modeQuery).map((result) => ({
|
||||
type: ContextMenuOptionType.Mode,
|
||||
value: result.item.original.slug,
|
||||
label: result.item.original.name,
|
||||
description: getModeDescription(result.item.original),
|
||||
}))
|
||||
: modes.map((mode) => ({
|
||||
type: ContextMenuOptionType.Mode,
|
||||
value: mode.slug,
|
||||
label: mode.name,
|
||||
description: getModeDescription(mode),
|
||||
}))
|
||||
// Handle mode selection
|
||||
if (modes?.length) {
|
||||
const modeQuery = commandQuery
|
||||
|
||||
return matchingModes.length > 0 ? matchingModes : [{ type: ContextMenuOptionType.NoResults }]
|
||||
// Create searchable strings array for fzf
|
||||
const searchableItems = modes.map((mode) => ({
|
||||
original: mode,
|
||||
searchStr: mode.name.toLowerCase(),
|
||||
}))
|
||||
|
||||
// Initialize fzf instance for fuzzy search
|
||||
const fzf = new Fzf(searchableItems, {
|
||||
selector: (item) => item.searchStr,
|
||||
})
|
||||
|
||||
// Get fuzzy matching items
|
||||
const matchingModes = modeQuery
|
||||
? fzf.find(modeQuery).map((result) => ({
|
||||
type: ContextMenuOptionType.Mode,
|
||||
value: result.item.original.slug,
|
||||
label: result.item.original.name,
|
||||
description: getModeDescription(result.item.original),
|
||||
}))
|
||||
: modes.map((mode) => ({
|
||||
type: ContextMenuOptionType.Mode,
|
||||
value: mode.slug,
|
||||
label: mode.name,
|
||||
description: getModeDescription(mode),
|
||||
}))
|
||||
|
||||
return matchingModes.length > 0 ? matchingModes : [{ type: ContextMenuOptionType.NoResults }]
|
||||
}
|
||||
|
||||
return [{ type: ContextMenuOptionType.NoResults }]
|
||||
}
|
||||
|
||||
const workingChanges: ContextMenuQueryItem = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue