-
Notifications
You must be signed in to change notification settings - Fork 788
FEAT: set the objective target's system prompt from the CoPyRIT GUI #2056
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ import { | |
| import { SendRegular, AttachRegular, DismissRegular, InfoRegular, AddRegular, CopyRegular, WarningRegular, SettingsRegular, ArrowShuffleRegular, OpenRegular } from '@fluentui/react-icons' | ||
| import { MessageAttachment, TargetInstance } from '../../types' | ||
| import { useChatInputAreaStyles } from './ChatInputArea.styles' | ||
| import SystemPromptSetup from './SystemPromptSetup' | ||
| import { PIECE_TYPE_TO_DATA_TYPE } from './converterTypes' | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
|
|
@@ -329,9 +330,13 @@ interface ChatInputAreaProps { | |
| /** Chip describing a text→file conversion (e.g. PDFConverter output). */ | ||
| convertedFileChip?: ConvertedFileChip | null | ||
| onClearConvertedFileChip?: () => void | ||
| /** Whether to show the system-prompt setup (only for a brand-new conversation). */ | ||
| showSystemPrompt?: boolean | ||
| systemPrompt?: string | ||
| onSystemPromptChange?: (value: string) => void | ||
| } | ||
|
|
||
| const ChatInputArea = forwardRef<ChatInputAreaHandle, ChatInputAreaProps>(function ChatInputArea({ onSend, disabled = false, activeTarget, singleTurnLimitReached = false, onNewConversation, operatorLocked = false, crossTargetLocked = false, onUseAsTemplate, attackOperator, noTargetSelected = false, onConfigureTarget, onToggleConverterPanel, isConverterPanelOpen = false, onInputChange, onAttachmentsChange, convertedValue, originalValue: _originalValue, onClearConversion, onConvertedValueChange, converterOutputDataTypes = [], mediaConversions = [], onClearMediaConversion, convertedFileChip, onClearConvertedFileChip }, ref) { | ||
| const ChatInputArea = forwardRef<ChatInputAreaHandle, ChatInputAreaProps>(function ChatInputArea({ onSend, disabled = false, activeTarget, singleTurnLimitReached = false, onNewConversation, operatorLocked = false, crossTargetLocked = false, onUseAsTemplate, attackOperator, noTargetSelected = false, onConfigureTarget, onToggleConverterPanel, isConverterPanelOpen = false, onInputChange, onAttachmentsChange, convertedValue, originalValue: _originalValue, onClearConversion, onConvertedValueChange, converterOutputDataTypes = [], mediaConversions = [], onClearMediaConversion, convertedFileChip, onClearConvertedFileChip, showSystemPrompt = false, systemPrompt = '', onSystemPromptChange }, ref) { | ||
| const styles = useChatInputAreaStyles() | ||
| const [input, setInput] = useState('') | ||
| const [attachments, setAttachments] = useState<MessageAttachment[]>([]) | ||
|
|
@@ -537,6 +542,14 @@ const ChatInputArea = forwardRef<ChatInputAreaHandle, ChatInputAreaProps>(functi | |
| ) : ( | ||
| <> | ||
| <div className={styles.inputWrapper}> | ||
| {showSystemPrompt && onSystemPromptChange && ( | ||
| <SystemPromptSetup | ||
| value={systemPrompt} | ||
| onChange={onSystemPromptChange} | ||
| disabled={!!activeTarget && activeTarget.capabilities?.supports_system_prompt !== true} | ||
| disabledReason="This target does not support system prompts." | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rich agrees with this comment but it is copilot generated: The editor is disabled whenever |
||
| /> | ||
| )} | ||
| <input | ||
| ref={fileInputRef} | ||
| type="file" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,7 @@ import LabelsBar from '../Labels/LabelsBar' | |
| import type { ChatInputAreaHandle } from './ChatInputArea' | ||
| import { attacksApi } from '../../services/api' | ||
| import { toApiError } from '../../services/errors' | ||
| import { buildMessagePieces, backendMessagesToFrontend } from '../../utils/messageMapper' | ||
| import { buildMessagePieces, backendMessagesToFrontend, buildSystemPrompt } from '../../utils/messageMapper' | ||
| import type { Message, MessageAttachment, TargetInstance, TargetInfo } from '../../types' | ||
| import type { ViewName } from '../Sidebar/Navigation' | ||
| import { useChatWindowStyles } from './ChatWindow.styles' | ||
|
|
@@ -70,6 +70,7 @@ export default function ChatWindow({ | |
| const [isPanelOpen, setIsPanelOpen] = useState(false) | ||
| const [isConverterPanelOpen, setIsConverterPanelOpen] = useState(false) | ||
| const [chatInputText, setChatInputText] = useState('') | ||
| const [systemPrompt, setSystemPrompt] = useState('') | ||
| const [attachmentTypes, setAttachmentTypes] = useState<string[]>([]) | ||
| const [attachmentData, setAttachmentData] = useState<Record<string, string>>({}) | ||
| const [pieceConversions, setPieceConversions] = useState<Record<string, PieceConversion>>({}) | ||
|
|
@@ -142,6 +143,7 @@ export default function ChatWindow({ | |
| if (!attackResultId) { | ||
| setMessages([]) | ||
| setLoadedConversationId(null) | ||
| setSystemPrompt('') | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rich agrees with this comment but it is copilot generated:
|
||
| } | ||
| } | ||
|
|
||
|
|
@@ -289,6 +291,9 @@ export default function ChatWindow({ | |
| const createResponse = await attacksApi.createAttack({ | ||
| target_registry_name: activeTarget.target_registry_name, | ||
| labels: labels, | ||
| prepended_conversation: activeTarget.capabilities?.supports_system_prompt | ||
| ? buildSystemPrompt(systemPrompt) | ||
| : undefined, | ||
| }) | ||
| currentAttackResultId = createResponse.attack_result_id | ||
| currentConversationId = createResponse.conversation_id | ||
|
|
@@ -617,6 +622,9 @@ export default function ChatWindow({ | |
| <ChatInputArea | ||
| ref={inputBoxRef} | ||
| onSend={handleSend} | ||
| showSystemPrompt={!attackResultId} | ||
| systemPrompt={systemPrompt} | ||
| onSystemPromptChange={setSystemPrompt} | ||
| disabled={isSending || !activeTarget || singleTurnLimitReached || isOperatorLocked || isCrossTargetLocked} | ||
| activeTarget={activeTarget} | ||
| singleTurnLimitReached={singleTurnLimitReached} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { makeStyles, tokens } from '@fluentui/react-components' | ||
|
|
||
| export const useSystemPromptSetupStyles = makeStyles({ | ||
| root: { | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| gap: tokens.spacingVerticalXS, | ||
| padding: `${tokens.spacingVerticalXS} ${tokens.spacingHorizontalL} 0`, | ||
| borderBottom: `1px solid ${tokens.colorNeutralStroke2}`, | ||
| }, | ||
| headerRow: { | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| gap: tokens.spacingHorizontalS, | ||
| }, | ||
| header: { | ||
| color: tokens.colorNeutralForeground2, | ||
| }, | ||
| body: { | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| gap: tokens.spacingVerticalXS, | ||
| paddingBottom: tokens.spacingVerticalS, | ||
| }, | ||
| textareaRoot: { | ||
| width: '100%', | ||
| }, | ||
| textareaInner: { | ||
| minHeight: '96px', | ||
| maxHeight: '30vh', | ||
| }, | ||
| counter: { | ||
| alignSelf: 'flex-end', | ||
| color: tokens.colorNeutralForeground3, | ||
| }, | ||
| counterOver: { | ||
| color: tokens.colorPaletteYellowForeground2, | ||
| }, | ||
| reason: { | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| gap: tokens.spacingHorizontalXXS, | ||
| color: tokens.colorPaletteYellowForeground2, | ||
| }, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rich agrees with this comment but it is copilot generated:
The
supports_system_promptrule is encoded twice in two different shapes. Here the editor is gated withcapabilities?.supports_system_prompt !== true, while ChatWindow gates the send with the inverse (capabilities?.supports_system_prompt ? buildSystemPrompt(...) : undefined). They agree today, but the source of truth is split between the input and the window. If they ever drift you get a silent failure: an enabled editor whose typed value is dropped on send, or vice-versa. Consider deriving onesupportsSystemPromptboolean in ChatWindow and passing it down so the editor's enabled state and the send-time gate can't disagree.