summaryrefslogtreecommitdiff
path: root/frontend/src/components/ContractCreateModal.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-27 11:04:20 +0000
committerGitHub <noreply@github.com>2026-01-27 11:04:20 +0000
commitc618174e60e4632d36d7352d83399508c72b2f42 (patch)
treefbca74b921a57165aea046b959a44ab00589532f /frontend/src/components/ContractCreateModal.tsx
parentb6f239c19f0d3130515f3745f842e17a69212295 (diff)
downloadsoryu-c618174e60e4632d36d7352d83399508c72b2f42.tar.gz
soryu-c618174e60e4632d36d7352d83399508c72b2f42.zip
Add Red Team CLI command and frontend UI (#39)
* Add Red Team CLI command and frontend UI Backend additions: - Add `makima red-team notify` CLI command for red team tasks - Add RedTeamCommand enum with Notify subcommand - Add red_team API client module for notify endpoint - Add RedTeamNotifyArgs with severity, task, file, context options Frontend additions: - Add ContractCreateModal with red team toggle and prompt input - Update ContractDetail with red-team tab for notifications - Update ContractList with red team enabled badge - Add TypeScript types for RedTeamNotification and related interfaces Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add CSS styles for Red Team frontend components Add comprehensive styling for: - Contract list and detail containers - Red team badge styling with gradient backgrounds - Tab navigation with red team specific styling - Red team notifications panel with severity indicators - Contract creation modal form elements - Task badges for supervisor and red team roles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix missing local_only field in TUI CreateContractRequest Add the missing local_only field to the CreateContractRequest struct initialization in the TUI contract creation handler. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [WIP] Heartbeat checkpoint - 2026-01-27 03:07:28 UTC --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'frontend/src/components/ContractCreateModal.tsx')
-rw-r--r--frontend/src/components/ContractCreateModal.tsx185
1 files changed, 185 insertions, 0 deletions
diff --git a/frontend/src/components/ContractCreateModal.tsx b/frontend/src/components/ContractCreateModal.tsx
new file mode 100644
index 0000000..e1d9732
--- /dev/null
+++ b/frontend/src/components/ContractCreateModal.tsx
@@ -0,0 +1,185 @@
+import React, { useState } from 'react'
+
+interface ContractCreateModalProps {
+ isOpen: boolean
+ onClose: () => void
+ onCreated: () => void
+}
+
+interface CreateContractForm {
+ name: string
+ description: string
+ contractType: string
+ redTeamEnabled: boolean
+ redTeamPrompt: string
+}
+
+export function ContractCreateModal({ isOpen, onClose, onCreated }: ContractCreateModalProps) {
+ const [form, setForm] = useState<CreateContractForm>({
+ name: '',
+ description: '',
+ contractType: 'simple',
+ redTeamEnabled: false,
+ redTeamPrompt: '',
+ })
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState<string | null>(null)
+
+ if (!isOpen) return null
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault()
+ setLoading(true)
+ setError(null)
+
+ try {
+ const response = await fetch('/api/v1/contracts', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ name: form.name,
+ description: form.description || undefined,
+ contract_type: form.contractType,
+ red_team_enabled: form.redTeamEnabled,
+ red_team_prompt: form.redTeamEnabled && form.redTeamPrompt ? form.redTeamPrompt : undefined,
+ }),
+ })
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}))
+ throw new Error(errorData.message || `Failed to create contract: ${response.statusText}`)
+ }
+
+ // Reset form and close modal
+ setForm({
+ name: '',
+ description: '',
+ contractType: 'simple',
+ redTeamEnabled: false,
+ redTeamPrompt: '',
+ })
+ onCreated()
+ onClose()
+ } catch (err) {
+ setError(err instanceof Error ? err.message : 'Unknown error')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ return (
+ <div className="modal-overlay" onClick={onClose}>
+ <div className="settings-modal contract-create-modal" onClick={(e) => e.stopPropagation()}>
+ <div className="modal-header">
+ <h2 className="modal-title">Create Contract</h2>
+ <button className="modal-close-btn" onClick={onClose}>
+ ×
+ </button>
+ </div>
+
+ <form onSubmit={handleSubmit}>
+ <div className="modal-content">
+ {error && (
+ <div className="form-error">
+ {error}
+ </div>
+ )}
+
+ <div className="settings-section">
+ <h3>Contract Details</h3>
+
+ <div className="setting-item">
+ <label>
+ Name
+ <input
+ type="text"
+ value={form.name}
+ onChange={(e) => setForm({ ...form, name: e.target.value })}
+ placeholder="Enter contract name"
+ required
+ className="form-input"
+ />
+ </label>
+ </div>
+
+ <div className="setting-item">
+ <label>
+ Description
+ <textarea
+ value={form.description}
+ onChange={(e) => setForm({ ...form, description: e.target.value })}
+ placeholder="Enter contract description (optional)"
+ className="form-textarea"
+ rows={3}
+ />
+ </label>
+ </div>
+
+ <div className="setting-item">
+ <label>
+ Contract Type
+ <select
+ value={form.contractType}
+ onChange={(e) => setForm({ ...form, contractType: e.target.value })}
+ className="form-select"
+ >
+ <option value="simple">Simple</option>
+ <option value="specification">Specification</option>
+ <option value="execute">Execute</option>
+ </select>
+ </label>
+ </div>
+ </div>
+
+ <div className="settings-section">
+ <h3>Red Team Monitoring</h3>
+
+ <div className="setting-item">
+ <label className="checkbox-label">
+ <input
+ type="checkbox"
+ checked={form.redTeamEnabled}
+ onChange={(e) => setForm({ ...form, redTeamEnabled: e.target.checked })}
+ />
+ <span>Enable Red Team monitoring</span>
+ </label>
+ <div className="setting-description">
+ Spawns a parallel task that monitors work output for quality and compliance
+ </div>
+ </div>
+
+ {form.redTeamEnabled && (
+ <div className="setting-item red-team-prompt-container">
+ <label>
+ Custom review criteria (optional)
+ <textarea
+ value={form.redTeamPrompt}
+ onChange={(e) => setForm({ ...form, redTeamPrompt: e.target.value })}
+ placeholder="Enter custom criteria for the red team to evaluate against... (e.g., 'Ensure all functions have proper error handling', 'Verify security best practices are followed')"
+ className="form-textarea"
+ rows={4}
+ />
+ </label>
+ <div className="setting-description">
+ Provide specific criteria for the red team to focus on during reviews
+ </div>
+ </div>
+ )}
+ </div>
+ </div>
+
+ <div className="modal-footer">
+ <button type="button" className="modal-btn secondary" onClick={onClose} disabled={loading}>
+ Cancel
+ </button>
+ <button type="submit" className="modal-btn primary" disabled={loading || !form.name.trim()}>
+ {loading ? 'Creating...' : 'Create Contract'}
+ </button>
+ </div>
+ </form>
+ </div>
+ </div>
+ )
+}