diff --git a/src/package.json b/src/package.json index 599ff3abad..2453389f0a 100644 --- a/src/package.json +++ b/src/package.json @@ -83,7 +83,7 @@ { "command": "roo-cline.promptsButtonClicked", "title": "%command.prompts.title%", - "icon": "$(notebook)" + "icon": "$(organization)" }, { "command": "roo-cline.historyButtonClicked", diff --git a/src/package.nls.ca.json b/src/package.nls.ca.json index 91745efabf..7e1cb6f376 100644 --- a/src/package.nls.ca.json +++ b/src/package.nls.ca.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "Servidors MCP", - "command.prompts.title": "Indicacions", + "command.prompts.title": "Modes", "command.history.title": "Historial", "command.openInEditor.title": "Obrir a l'Editor", "command.settings.title": "Configuració", diff --git a/src/package.nls.de.json b/src/package.nls.de.json index 83c358a4b5..a967118150 100644 --- a/src/package.nls.de.json +++ b/src/package.nls.de.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "MCP Server", - "command.prompts.title": "Prompts", + "command.prompts.title": "Modi", "command.history.title": "Verlauf", "command.openInEditor.title": "Im Editor Öffnen", "command.settings.title": "Einstellungen", diff --git a/src/package.nls.es.json b/src/package.nls.es.json index a116a762a9..4f5734bdae 100644 --- a/src/package.nls.es.json +++ b/src/package.nls.es.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "Servidores MCP", - "command.prompts.title": "Indicaciones", + "command.prompts.title": "Modos", "command.history.title": "Historial", "command.openInEditor.title": "Abrir en Editor", "command.settings.title": "Configuración", diff --git a/src/package.nls.fr.json b/src/package.nls.fr.json index 55b56bf33c..34bdddc440 100644 --- a/src/package.nls.fr.json +++ b/src/package.nls.fr.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "Serveurs MCP", - "command.prompts.title": "Invites", + "command.prompts.title": "Modes", "command.history.title": "Historique", "command.openInEditor.title": "Ouvrir dans l'Éditeur", "command.settings.title": "Paramètres", diff --git a/src/package.nls.hi.json b/src/package.nls.hi.json index fdef15fff8..c9b7fd651b 100644 --- a/src/package.nls.hi.json +++ b/src/package.nls.hi.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "एमसीपी सर्वर", - "command.prompts.title": "प्रॉम्प्ट्स", + "command.prompts.title": "मोड्स", "command.history.title": "इतिहास", "command.openInEditor.title": "एडिटर में खोलें", "command.settings.title": "सेटिंग्स", diff --git a/src/package.nls.it.json b/src/package.nls.it.json index aa238eaae7..c3f875bff6 100644 --- a/src/package.nls.it.json +++ b/src/package.nls.it.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "Server MCP", - "command.prompts.title": "Prompt", + "command.prompts.title": "Modi", "command.history.title": "Cronologia", "command.openInEditor.title": "Apri nell'Editor", "command.settings.title": "Impostazioni", diff --git a/src/package.nls.ja.json b/src/package.nls.ja.json index cec6408ffd..fb76cd597b 100644 --- a/src/package.nls.ja.json +++ b/src/package.nls.ja.json @@ -6,7 +6,7 @@ "views.activitybar.title": "Roo Code", "command.newTask.title": "新しいタスク", "command.mcpServers.title": "MCPサーバー", - "command.prompts.title": "プロンプト", + "command.prompts.title": "モード", "command.history.title": "履歴", "command.openInEditor.title": "エディタで開く", "command.settings.title": "設定", diff --git a/src/package.nls.json b/src/package.nls.json index 4bcb49723a..b1ea6c1b58 100644 --- a/src/package.nls.json +++ b/src/package.nls.json @@ -6,7 +6,7 @@ "views.activitybar.title": "Roo Code", "command.newTask.title": "New Task", "command.mcpServers.title": "MCP Servers", - "command.prompts.title": "Prompts", + "command.prompts.title": "Modes", "command.history.title": "History", "command.openInEditor.title": "Open in Editor", "command.settings.title": "Settings", diff --git a/src/package.nls.ko.json b/src/package.nls.ko.json index 54d54a6709..9c090a03a9 100644 --- a/src/package.nls.ko.json +++ b/src/package.nls.ko.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "MCP 서버", - "command.prompts.title": "프롬프트", + "command.prompts.title": "모드", "command.history.title": "기록", "command.openInEditor.title": "에디터에서 열기", "command.settings.title": "설정", diff --git a/src/package.nls.nl.json b/src/package.nls.nl.json index 8cd0b0e71f..0e0e88f0b0 100644 --- a/src/package.nls.nl.json +++ b/src/package.nls.nl.json @@ -6,7 +6,7 @@ "views.activitybar.title": "Roo Code", "command.newTask.title": "Nieuwe Taak", "command.mcpServers.title": "MCP Servers", - "command.prompts.title": "Prompts", + "command.prompts.title": "Modi", "command.history.title": "Geschiedenis", "command.openInEditor.title": "Openen in Editor", "command.settings.title": "Instellingen", diff --git a/src/package.nls.pl.json b/src/package.nls.pl.json index c22b4e99e6..c17d30b1e0 100644 --- a/src/package.nls.pl.json +++ b/src/package.nls.pl.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "Serwery MCP", - "command.prompts.title": "Podpowiedzi", + "command.prompts.title": "Tryby", "command.history.title": "Historia", "command.openInEditor.title": "Otwórz w Edytorze", "command.settings.title": "Ustawienia", diff --git a/src/package.nls.pt-BR.json b/src/package.nls.pt-BR.json index 0b93b1fbfe..7bdd28595e 100644 --- a/src/package.nls.pt-BR.json +++ b/src/package.nls.pt-BR.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "Servidores MCP", - "command.prompts.title": "Prompts", + "command.prompts.title": "Modos", "command.history.title": "Histórico", "command.openInEditor.title": "Abrir no Editor", "command.settings.title": "Configurações", diff --git a/src/package.nls.ru.json b/src/package.nls.ru.json index ec122061a3..f484951102 100644 --- a/src/package.nls.ru.json +++ b/src/package.nls.ru.json @@ -6,7 +6,7 @@ "views.activitybar.title": "Roo Code", "command.newTask.title": "Новая задача", "command.mcpServers.title": "MCP серверы", - "command.prompts.title": "Промпты", + "command.prompts.title": "Режимы", "command.history.title": "История", "command.openInEditor.title": "Открыть в редакторе", "command.settings.title": "Настройки", diff --git a/src/package.nls.tr.json b/src/package.nls.tr.json index c980e90b91..b54776c1dd 100644 --- a/src/package.nls.tr.json +++ b/src/package.nls.tr.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "MCP Sunucuları", - "command.prompts.title": "Komut İstemleri", + "command.prompts.title": "Modlar", "command.history.title": "Geçmiş", "command.openInEditor.title": "Düzenleyicide Aç", "command.settings.title": "Ayarlar", diff --git a/src/package.nls.vi.json b/src/package.nls.vi.json index 34788bbef7..9cd3d9672c 100644 --- a/src/package.nls.vi.json +++ b/src/package.nls.vi.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "Máy Chủ MCP", - "command.prompts.title": "Lời Nhắc", + "command.prompts.title": "Chế Độ", "command.history.title": "Lịch Sử", "command.openInEditor.title": "Mở trong Trình Soạn Thảo", "command.settings.title": "Cài Đặt", diff --git a/src/package.nls.zh-CN.json b/src/package.nls.zh-CN.json index ac64f36bff..709cd9b32d 100644 --- a/src/package.nls.zh-CN.json +++ b/src/package.nls.zh-CN.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "MCP 服务器", - "command.prompts.title": "提示", + "command.prompts.title": "模式", "command.history.title": "历史记录", "command.openInEditor.title": "在编辑器中打开", "command.settings.title": "设置", diff --git a/src/package.nls.zh-TW.json b/src/package.nls.zh-TW.json index bb31058fc6..4a3a935539 100644 --- a/src/package.nls.zh-TW.json +++ b/src/package.nls.zh-TW.json @@ -17,7 +17,7 @@ "views.contextMenu.label": "Roo Code", "views.terminalMenu.label": "Roo Code", "command.mcpServers.title": "MCP 伺服器", - "command.prompts.title": "提示", + "command.prompts.title": "模式", "command.history.title": "歷史記錄", "command.openInEditor.title": "在編輯器中開啟", "command.settings.title": "設定", diff --git a/src/services/checkpoints/__tests__/ShadowCheckpointService.test.ts b/src/services/checkpoints/__tests__/ShadowCheckpointService.test.ts index ad155b36c3..9c1019f53a 100644 --- a/src/services/checkpoints/__tests__/ShadowCheckpointService.test.ts +++ b/src/services/checkpoints/__tests__/ShadowCheckpointService.test.ts @@ -658,7 +658,9 @@ describe.each([[RepoPerTaskCheckpointService, "RepoPerTaskCheckpointService"]])( it("creates checkpoint with changes regardless of allowEmpty setting", async () => { await fs.writeFile(testFile, "Modified content for allowEmpty test") - const resultWithAllowEmpty = await service.saveCheckpoint("With changes and allowEmpty", { allowEmpty: true }) + const resultWithAllowEmpty = await service.saveCheckpoint("With changes and allowEmpty", { + allowEmpty: true, + }) expect(resultWithAllowEmpty?.commit).toBeTruthy() await fs.writeFile(testFile, "Another modification for allowEmpty test") @@ -685,7 +687,7 @@ describe.each([[RepoPerTaskCheckpointService, "RepoPerTaskCheckpointService"]])( // First, create a checkpoint to ensure we're not in the initial state await fs.writeFile(testFile, "Setup content") await service.saveCheckpoint("Setup checkpoint") - + // Reset the file to original state await fs.writeFile(testFile, "Hello, world!") await service.saveCheckpoint("Reset to original") @@ -723,15 +725,15 @@ describe.each([[RepoPerTaskCheckpointService, "RepoPerTaskCheckpointService"]])( await testService.saveCheckpoint("Test logging with allowEmpty", { allowEmpty: true }) - const saveCheckpointLogs = logMessages.filter(msg => - msg.includes("starting checkpoint save") && msg.includes("allowEmpty: true") + const saveCheckpointLogs = logMessages.filter( + (msg) => msg.includes("starting checkpoint save") && msg.includes("allowEmpty: true"), ) expect(saveCheckpointLogs).toHaveLength(1) await testService.saveCheckpoint("Test logging without allowEmpty") - const defaultLogs = logMessages.filter(msg => - msg.includes("starting checkpoint save") && msg.includes("allowEmpty: false") + const defaultLogs = logMessages.filter( + (msg) => msg.includes("starting checkpoint save") && msg.includes("allowEmpty: false"), ) expect(defaultLogs).toHaveLength(1) }) @@ -776,7 +778,7 @@ describe.each([[RepoPerTaskCheckpointService, "RepoPerTaskCheckpointService"]])( // Get diff between regular commit and empty commit const diff = await service.getDiff({ from: beforeEmpty!.commit, - to: emptyCommit!.commit + to: emptyCommit!.commit, }) // Should have no differences since empty commit doesn't change anything @@ -802,7 +804,7 @@ describe.each([[RepoPerTaskCheckpointService, "RepoPerTaskCheckpointService"]])( // Restore to the new task checkpoint await service.restoreCheckpoint(newTaskCheckpoint!.commit) - + // File should be back to original state expect(await fs.readFile(testFile, "utf-8")).toBe("Hello, world!") }) diff --git a/src/services/mcp/McpHub.ts b/src/services/mcp/McpHub.ts index 1e8aabf1f5..e1009d9741 100644 --- a/src/services/mcp/McpHub.ts +++ b/src/services/mcp/McpHub.ts @@ -452,7 +452,7 @@ export class McpHub { args: configInjected.args, cwd: configInjected.cwd, env: { - ...(configInjected.env || {}), + ...(configInjected.env || {}), ...(process.env.PATH ? { PATH: process.env.PATH } : {}), ...(process.env.HOME ? { HOME: process.env.HOME } : {}), }, diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index 053c9f2456..b82d73a709 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -13,15 +13,15 @@ import HistoryView from "./components/history/HistoryView" import SettingsView, { SettingsViewRef } from "./components/settings/SettingsView" import WelcomeView from "./components/welcome/WelcomeView" import McpView from "./components/mcp/McpView" -import PromptsView from "./components/prompts/PromptsView" +import ModesView from "./components/modes/ModesView" import { HumanRelayDialog } from "./components/human-relay/HumanRelayDialog" -type Tab = "settings" | "history" | "mcp" | "prompts" | "chat" +type Tab = "settings" | "history" | "mcp" | "modes" | "chat" const tabsByMessageAction: Partial, Tab>> = { chatButtonClicked: "chat", settingsButtonClicked: "settings", - promptsButtonClicked: "prompts", + promptsButtonClicked: "modes", mcpButtonClicked: "mcp", historyButtonClicked: "history", } @@ -112,7 +112,7 @@ const App = () => { ) : ( <> - {tab === "prompts" && switchTab("chat")} />} + {tab === "modes" && switchTab("chat")} />} {tab === "mcp" && switchTab("chat")} />} {tab === "history" && switchTab("chat")} />} {tab === "settings" && ( diff --git a/webview-ui/src/__tests__/App.test.tsx b/webview-ui/src/__tests__/App.test.tsx index 3262cef69c..eeb173b206 100644 --- a/webview-ui/src/__tests__/App.test.tsx +++ b/webview-ui/src/__tests__/App.test.tsx @@ -56,12 +56,12 @@ jest.mock("@src/components/mcp/McpView", () => ({ }, })) -jest.mock("@src/components/prompts/PromptsView", () => ({ +jest.mock("@src/components/modes/ModesView", () => ({ __esModule: true, - default: function PromptsView({ onDone }: { onDone: () => void }) { + default: function ModesView({ onDone }: { onDone: () => void }) { return (
- Prompts View + Modes View
) }, diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/modes/ModesView.tsx similarity index 88% rename from webview-ui/src/components/prompts/PromptsView.tsx rename to webview-ui/src/components/modes/ModesView.tsx index 8ee63f3dfb..18f4bdf3d2 100644 --- a/webview-ui/src/components/prompts/PromptsView.tsx +++ b/webview-ui/src/components/modes/ModesView.tsx @@ -19,7 +19,6 @@ import { getAllModes, findModeBySlug as findCustomModeBySlug, } from "@roo/modes" -import { supportPrompt, SupportPromptType } from "@roo/support-prompt" import { TOOL_GROUPS } from "@roo/tools" import { vscode } from "@src/utils/vscode" @@ -51,7 +50,7 @@ const availableGroups = (Object.keys(TOOL_GROUPS) as ToolGroup[]).filter((group) type ModeSource = "global" | "project" -type PromptsViewProps = { +type ModesViewProps = { onDone: () => void } @@ -60,16 +59,13 @@ function getGroupName(group: GroupEntry): ToolGroup { return Array.isArray(group) ? group[0] : group } -const PromptsView = ({ onDone }: PromptsViewProps) => { +const ModesView = ({ onDone }: ModesViewProps) => { const { t } = useAppTranslation() const { customModePrompts, - customSupportPrompts, listApiConfigMeta, currentApiConfigName, - enhancementApiConfigId, - setEnhancementApiConfigId, mode, customInstructions, setCustomInstructions, @@ -86,15 +82,12 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { // Memoize modes to preserve array order const modes = useMemo(() => getAllModes(customModes), [customModes]) - const [testPrompt, setTestPrompt] = useState("") - const [isEnhancing, setIsEnhancing] = useState(false) const [isDialogOpen, setIsDialogOpen] = useState(false) const [selectedPromptContent, setSelectedPromptContent] = useState("") const [selectedPromptTitle, setSelectedPromptTitle] = useState("") const [isToolsEditMode, setIsToolsEditMode] = useState(false) const [showConfigMenu, setShowConfigMenu] = useState(false) const [isCreateModeDialogOpen, setIsCreateModeDialogOpen] = useState(false) - const [activeSupportOption, setActiveSupportOption] = useState("ENHANCE") const [isSystemPromptDisclosureOpen, setIsSystemPromptDisclosureOpen] = useState(false) // State for mode selection popover and search @@ -380,12 +373,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { useEffect(() => { const handler = (event: MessageEvent) => { const message = event.data - if (message.type === "enhancedPrompt") { - if (message.text) { - setTestPrompt(message.text) - } - setIsEnhancing(false) - } else if (message.type === "systemPrompt") { + if (message.type === "systemPrompt") { if (message.text) { setSelectedPromptContent(message.text) setSelectedPromptTitle(`System Prompt (${message.mode} mode)`) @@ -398,15 +386,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { return () => window.removeEventListener("message", handler) }, []) - const updateSupportPrompt = (type: SupportPromptType, value: string | undefined) => { - vscode.postMessage({ - type: "updateSupportPrompt", - values: { - [type]: value, - }, - }) - } - const handleAgentReset = (modeSlug: string, type: "roleDefinition" | "whenToUse" | "customInstructions") => { // Only reset for built-in modes const existingPrompt = customModePrompts?.[modeSlug] as PromptComponent @@ -420,27 +399,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { }) } - const handleSupportReset = (type: SupportPromptType) => { - vscode.postMessage({ - type: "resetSupportPrompt", - text: type, - }) - } - - const getSupportPromptValue = (type: SupportPromptType): string => { - return supportPrompt.get(customSupportPrompts, type) - } - - const handleTestEnhancement = () => { - if (!testPrompt.trim()) return - - setIsEnhancing(true) - vscode.postMessage({ - type: "enhancePrompt", - text: testPrompt, - }) - } - return ( @@ -1078,7 +1036,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { -
+

{t("prompts:globalCustomInstructions.title")}

@@ -1131,128 +1089,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { />
- -
-

{t("prompts:supportPrompts.title")}

-
- -
- - {/* Support prompt description */} -
- {t(`prompts:supportPrompts.types.${activeSupportOption}.description`)} -
- -
-
-
{t("prompts:supportPrompts.prompt")}
- -
- - { - const value = - (e as unknown as CustomEvent)?.detail?.target?.value || - ((e as any).target as HTMLTextAreaElement).value - const trimmedValue = value.trim() - updateSupportPrompt(activeSupportOption, trimmedValue || undefined) - }} - rows={6} - className="w-full" - /> - - {activeSupportOption === "ENHANCE" && ( - <> -
-
-
-
-
- {t("prompts:supportPrompts.enhance.apiConfiguration")} -
-
- {t("prompts:supportPrompts.enhance.apiConfigDescription")} -
-
- -
-
- -
- setTestPrompt((e.target as HTMLTextAreaElement).value)} - placeholder={t("prompts:supportPrompts.enhance.testPromptPlaceholder")} - rows={3} - className="w-full" - data-testid="test-prompt-textarea" - /> -
- -
-
- - )} -
-
{isCreateModeDialogOpen && ( @@ -1461,4 +1297,4 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { ) } -export default PromptsView +export default ModesView diff --git a/webview-ui/src/components/prompts/__tests__/PromptsView.test.tsx b/webview-ui/src/components/modes/__tests__/ModesView.test.tsx similarity index 87% rename from webview-ui/src/components/prompts/__tests__/PromptsView.test.tsx rename to webview-ui/src/components/modes/__tests__/ModesView.test.tsx index 3a92e4d3e1..e0a9736337 100644 --- a/webview-ui/src/components/prompts/__tests__/PromptsView.test.tsx +++ b/webview-ui/src/components/modes/__tests__/ModesView.test.tsx @@ -1,7 +1,7 @@ // npx jest src/components/prompts/__tests__/PromptsView.test.tsx import { render, screen, fireEvent, waitFor } from "@testing-library/react" -import PromptsView from "../PromptsView" +import ModesView from "../ModesView" import { ExtensionStateContext } from "@src/context/ExtensionStateContext" import { vscode } from "@src/utils/vscode" @@ -48,7 +48,7 @@ const renderPromptsView = (props = {}) => { const mockOnDone = jest.fn() return render( - + , ) } @@ -144,7 +144,7 @@ describe("PromptsView", () => { const { unmount } = render( - + , ) @@ -167,7 +167,7 @@ describe("PromptsView", () => { render( - + , ) @@ -175,24 +175,6 @@ describe("PromptsView", () => { expect(screen.queryByTestId("role-definition-reset")).not.toBeInTheDocument() }) - it("handles API configuration selection", async () => { - renderPromptsView() - - const trigger = screen.getByTestId("support-prompt-select-trigger") - fireEvent.click(trigger) - - const enhanceOption = await waitFor(() => screen.getByTestId("ENHANCE-option")) - fireEvent.click(enhanceOption) - - const apiConfig = await waitFor(() => screen.getByTestId("api-config-select")) - fireEvent.click(apiConfig) - - const config1 = await waitFor(() => screen.getByTestId("config1-option")) - fireEvent.click(config1) - - expect(mockExtensionState.setEnhancementApiConfigId).toHaveBeenCalledWith("config1") // Ensure this is not called by mode switch - }) - it("handles clearing custom instructions correctly", async () => { const setCustomInstructions = jest.fn() renderPromptsView({ diff --git a/webview-ui/src/components/settings/PromptsSettings.tsx b/webview-ui/src/components/settings/PromptsSettings.tsx new file mode 100644 index 0000000000..ffeffca8ea --- /dev/null +++ b/webview-ui/src/components/settings/PromptsSettings.tsx @@ -0,0 +1,193 @@ +import React, { useState, useEffect } from "react" +import { VSCodeTextArea } from "@vscode/webview-ui-toolkit/react" + +import { supportPrompt, SupportPromptType } from "@roo/support-prompt" + +import { vscode } from "@src/utils/vscode" +import { useAppTranslation } from "@src/i18n/TranslationContext" +import { useExtensionState } from "@src/context/ExtensionStateContext" +import { Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@src/components/ui" +import { SectionHeader } from "./SectionHeader" +import { Section } from "./Section" +import { MessageSquare } from "lucide-react" + +const PromptsSettings = () => { + const { t } = useAppTranslation() + + const { customSupportPrompts, listApiConfigMeta, enhancementApiConfigId, setEnhancementApiConfigId } = + useExtensionState() + + const [testPrompt, setTestPrompt] = useState("") + const [isEnhancing, setIsEnhancing] = useState(false) + const [activeSupportOption, setActiveSupportOption] = useState("ENHANCE") + + useEffect(() => { + const handler = (event: MessageEvent) => { + const message = event.data + if (message.type === "enhancedPrompt") { + if (message.text) { + setTestPrompt(message.text) + } + setIsEnhancing(false) + } + } + + window.addEventListener("message", handler) + return () => window.removeEventListener("message", handler) + }, []) + + const updateSupportPrompt = (type: SupportPromptType, value: string | undefined) => { + vscode.postMessage({ + type: "updateSupportPrompt", + values: { + [type]: value, + }, + }) + } + + const handleSupportReset = (type: SupportPromptType) => { + vscode.postMessage({ + type: "resetSupportPrompt", + text: type, + }) + } + + const getSupportPromptValue = (type: SupportPromptType): string => { + return supportPrompt.get(customSupportPrompts, type) + } + + const handleTestEnhancement = () => { + if (!testPrompt.trim()) return + + setIsEnhancing(true) + vscode.postMessage({ + type: "enhancePrompt", + text: testPrompt, + }) + } + + return ( +
+ +
+ +
{t("settings:sections.prompts")}
+
+
+ +
+
+ +
+ {t(`prompts:supportPrompts.types.${activeSupportOption}.description`)} +
+
+ +
+
+ + +
+ + { + const value = + (e as unknown as CustomEvent)?.detail?.target?.value || + ((e as any).target as HTMLTextAreaElement).value + const trimmedValue = value.trim() + updateSupportPrompt(activeSupportOption, trimmedValue || undefined) + }} + rows={6} + className="w-full" + /> + + {activeSupportOption === "ENHANCE" && ( +
+
+ + +
+ {t("prompts:supportPrompts.enhance.apiConfigDescription")} +
+
+ +
+ + setTestPrompt((e.target as HTMLTextAreaElement).value)} + placeholder={t("prompts:supportPrompts.enhance.testPromptPlaceholder")} + rows={3} + className="w-full" + data-testid="test-prompt-textarea" + /> +
+ +
+
+
+ )} +
+
+
+ ) +} + +export default PromptsSettings diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 8243632469..27b7859540 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -21,6 +21,7 @@ import { AlertTriangle, Globe, Info, + MessageSquare, LucideIcon, } from "lucide-react" @@ -62,6 +63,7 @@ import { ExperimentalSettings } from "./ExperimentalSettings" import { LanguageSettings } from "./LanguageSettings" import { About } from "./About" import { Section } from "./Section" +import PromptsSettings from "./PromptsSettings" import { cn } from "@/lib/utils" export const settingsTabsContainer = "flex flex-1 overflow-hidden [&.narrow_.tab-label]:hidden" @@ -83,6 +85,7 @@ const sectionNames = [ "notifications", "contextManagement", "terminal", + "prompts", "experimental", "language", "about", @@ -369,6 +372,7 @@ const SettingsView = forwardRef(({ onDone, t { id: "notifications", icon: Bell }, { id: "contextManagement", icon: Database }, { id: "terminal", icon: SquareTerminal }, + { id: "prompts", icon: MessageSquare }, { id: "experimental", icon: FlaskConical }, { id: "language", icon: Globe }, { id: "about", icon: Info }, @@ -635,6 +639,9 @@ const SettingsView = forwardRef(({ onDone, t /> )} + {/* Prompts Section */} + {activeTab === "prompts" && } + {/* Experimental Section */} {activeTab === "experimental" && (