Skip to content

Commit f398eea

Browse files
committed
Fixes #5219: Make system prompt warning dismissible
- Add systemPromptWarningDismissed boolean setting to GlobalSettings schema - Update ExtensionState type to include the new setting - Add state management through ExtensionStateContext with getter and setter - Modify SystemPromptWarning component to include dismiss button with X icon - Update ChatView to conditionally render warning based on both hasSystemPromptOverride and !systemPromptWarningDismissed - Add test coverage for SystemPromptWarning component - Dismiss functionality persists user preference through extension state system
1 parent 3a8ba27 commit f398eea

File tree

6 files changed

+105
-2
lines changed

6 files changed

+105
-2
lines changed

packages/types/src/global-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export const globalSettingsSchema = z.object({
105105
historyPreviewCollapsed: z.boolean().optional(),
106106
profileThresholds: z.record(z.string(), z.number()).optional(),
107107
hasOpenedModeSelector: z.boolean().optional(),
108+
systemPromptWarningDismissed: z.boolean().optional(),
108109
})
109110

110111
export type GlobalSettings = z.infer<typeof globalSettingsSchema>

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ export type ExtensionState = Pick<
217217
| "codebaseIndexConfig"
218218
| "codebaseIndexModels"
219219
| "profileThresholds"
220+
| "systemPromptWarningDismissed"
220221
> & {
221222
version: string
222223
clineMessages: ClineMessage[]

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
9595
customModes,
9696
telemetrySetting,
9797
hasSystemPromptOverride,
98+
systemPromptWarningDismissed,
9899
historyPreviewCollapsed, // Added historyPreviewCollapsed
99100
soundEnabled,
100101
soundVolume,
@@ -1381,7 +1382,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
13811382
onClose={handleTaskCloseButtonClick}
13821383
/>
13831384

1384-
{hasSystemPromptOverride && (
1385+
{hasSystemPromptOverride && !systemPromptWarningDismissed && (
13851386
<div className="px-3">
13861387
<SystemPromptWarning />
13871388
</div>

webview-ui/src/components/chat/SystemPromptWarning.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
import React from "react"
22
import { useAppTranslation } from "@/i18n/TranslationContext"
3+
import { useExtensionState } from "@/context/ExtensionStateContext"
34

45
export const SystemPromptWarning: React.FC = () => {
56
const { t } = useAppTranslation()
7+
const { setSystemPromptWarningDismissed } = useExtensionState()
8+
9+
const handleDismiss = () => {
10+
setSystemPromptWarningDismissed(true)
11+
}
612

713
return (
814
<div className="flex items-center px-4 py-2 mb-2 text-sm rounded bg-vscode-editorWarning-foreground text-vscode-editor-background">
915
<div className="flex items-center justify-center w-5 h-5 mr-2">
1016
<span className="codicon codicon-warning" />
1117
</div>
12-
<span>{t("chat:systemPromptWarning")}</span>
18+
<span className="flex-1">{t("chat:systemPromptWarning")}</span>
19+
<button
20+
onClick={handleDismiss}
21+
className="flex items-center justify-center w-5 h-5 ml-2 hover:bg-vscode-editor-background hover:bg-opacity-20 rounded"
22+
title="Dismiss warning">
23+
<span className="codicon codicon-close" />
24+
</button>
1325
</div>
1426
)
1527
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// npx vitest run src/components/chat/__tests__/SystemPromptWarning.spec.tsx
2+
3+
import { describe, it, expect, vi } from "vitest"
4+
import { render, screen, fireEvent } from "@testing-library/react"
5+
import { SystemPromptWarning } from "../SystemPromptWarning"
6+
import { useExtensionState } from "@/context/ExtensionStateContext"
7+
import { useAppTranslation } from "@/i18n/TranslationContext"
8+
9+
// Mock the hooks
10+
vi.mock("@/context/ExtensionStateContext")
11+
vi.mock("@/i18n/TranslationContext")
12+
13+
const mockSetSystemPromptWarningDismissed = vi.fn()
14+
const mockT = vi.fn((key: string) => {
15+
if (key === "chat:systemPromptWarning") {
16+
return "WARNING: Custom system prompt override active. This can severely break functionality and cause unpredictable behavior."
17+
}
18+
return key
19+
})
20+
21+
describe("SystemPromptWarning", () => {
22+
beforeEach(() => {
23+
vi.clearAllMocks()
24+
;(useExtensionState as any).mockReturnValue({
25+
setSystemPromptWarningDismissed: mockSetSystemPromptWarningDismissed,
26+
})
27+
;(useAppTranslation as any).mockReturnValue({
28+
t: mockT,
29+
})
30+
})
31+
32+
it("renders the warning message", () => {
33+
render(<SystemPromptWarning />)
34+
35+
expect(screen.getByText(/WARNING: Custom system prompt override active/)).toBeInTheDocument()
36+
})
37+
38+
it("renders the warning icon", () => {
39+
render(<SystemPromptWarning />)
40+
41+
const warningIcon = document.querySelector(".codicon-warning")
42+
expect(warningIcon).toBeInTheDocument()
43+
})
44+
45+
it("renders the dismiss button", () => {
46+
render(<SystemPromptWarning />)
47+
48+
const dismissButton = screen.getByRole("button")
49+
expect(dismissButton).toBeInTheDocument()
50+
expect(dismissButton).toHaveAttribute("title", "Dismiss warning")
51+
})
52+
53+
it("renders the close icon in dismiss button", () => {
54+
render(<SystemPromptWarning />)
55+
56+
const closeIcon = document.querySelector(".codicon-close")
57+
expect(closeIcon).toBeInTheDocument()
58+
})
59+
60+
it("calls setSystemPromptWarningDismissed when dismiss button is clicked", () => {
61+
render(<SystemPromptWarning />)
62+
63+
const dismissButton = screen.getByRole("button")
64+
fireEvent.click(dismissButton)
65+
66+
expect(mockSetSystemPromptWarningDismissed).toHaveBeenCalledWith(true)
67+
expect(mockSetSystemPromptWarningDismissed).toHaveBeenCalledTimes(1)
68+
})
69+
70+
it("has correct CSS classes for styling", () => {
71+
render(<SystemPromptWarning />)
72+
73+
const container = document.querySelector(".flex.items-center.px-4.py-2.mb-2")
74+
expect(container).toBeInTheDocument()
75+
expect(container).toHaveClass("bg-vscode-editorWarning-foreground", "text-vscode-editor-background")
76+
})
77+
78+
it("uses translation for the warning text", () => {
79+
render(<SystemPromptWarning />)
80+
81+
expect(mockT).toHaveBeenCalledWith("chat:systemPromptWarning")
82+
})
83+
})

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export interface ExtensionStateContextType extends ExtensionState {
4040
mdmCompliant?: boolean
4141
hasOpenedModeSelector: boolean // New property to track if user has opened mode selector
4242
setHasOpenedModeSelector: (value: boolean) => void // Setter for the new property
43+
systemPromptWarningDismissed?: boolean // New property to track if system prompt warning is dismissed
44+
setSystemPromptWarningDismissed: (value: boolean) => void // Setter for the new property
4345
condensingApiConfigId?: string
4446
setCondensingApiConfigId: (value: string) => void
4547
customCondensingPrompt?: string
@@ -183,6 +185,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
183185
condensingApiConfigId: "", // Default empty string for condensing API config ID
184186
customCondensingPrompt: "", // Default empty string for custom condensing prompt
185187
hasOpenedModeSelector: false, // Default to false (not opened yet)
188+
systemPromptWarningDismissed: false, // Default to false (not dismissed yet)
186189
autoApprovalEnabled: false,
187190
customModes: [],
188191
maxOpenTabsContext: 20,
@@ -431,6 +434,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
431434
setHistoryPreviewCollapsed: (value) =>
432435
setState((prevState) => ({ ...prevState, historyPreviewCollapsed: value })),
433436
setHasOpenedModeSelector: (value) => setState((prevState) => ({ ...prevState, hasOpenedModeSelector: value })),
437+
setSystemPromptWarningDismissed: (value) =>
438+
setState((prevState) => ({ ...prevState, systemPromptWarningDismissed: value })),
434439
setAutoCondenseContext: (value) => setState((prevState) => ({ ...prevState, autoCondenseContext: value })),
435440
setAutoCondenseContextPercent: (value) =>
436441
setState((prevState) => ({ ...prevState, autoCondenseContextPercent: value })),

0 commit comments

Comments
 (0)