diff options
| author | soryu <soryu@soryu.co> | 2026-01-29 02:23:56 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-29 02:23:56 +0000 |
| commit | c3fc0fb4b7a91308f62bd23d6a71d4a5fccfd32e (patch) | |
| tree | 274faa2561f99bda2fd8137e2d3f4ac9ae980a7f /makima/frontend | |
| parent | 7fa15385e4d47d4b304d55a1e31e13ede121d0d6 (diff) | |
| parent | 45a433c0eb63cae1322203ee14292f1c427a09c9 (diff) | |
| download | soryu-c3fc0fb4b7a91308f62bd23d6a71d4a5fccfd32e.tar.gz soryu-c3fc0fb4b7a91308f62bd23d6a71d4a5fccfd32e.zip | |
Merge branch 'master' into makima/fix-hf-cli-commandmakima/fix-hf-cli-command
Diffstat (limited to 'makima/frontend')
| -rw-r--r-- | makima/frontend/src/components/contracts/ContractList.tsx | 5 | ||||
| -rw-r--r-- | makima/frontend/src/hooks/useSpeakWebSocket.ts | 2 | ||||
| -rw-r--r-- | makima/frontend/src/lib/api.ts | 12 | ||||
| -rw-r--r-- | makima/frontend/src/routes/contracts.tsx | 78 | ||||
| -rw-r--r-- | makima/frontend/tsconfig.tsbuildinfo | 2 |
5 files changed, 91 insertions, 8 deletions
diff --git a/makima/frontend/src/components/contracts/ContractList.tsx b/makima/frontend/src/components/contracts/ContractList.tsx index 98f8ff6..532ab87 100644 --- a/makima/frontend/src/components/contracts/ContractList.tsx +++ b/makima/frontend/src/components/contracts/ContractList.tsx @@ -136,6 +136,11 @@ export function ContractList({ Local </span> )} + {contract.redTeamEnabled && ( + <span className="px-1.5 py-0.5 font-mono text-[9px] uppercase text-cyan-400 border border-cyan-400/30 bg-cyan-400/10 shrink-0" title="Red Team monitoring enabled"> + 🔍 Red Team + </span> + )} </div> <span className={`text-[10px] font-mono uppercase shrink-0 ${ diff --git a/makima/frontend/src/hooks/useSpeakWebSocket.ts b/makima/frontend/src/hooks/useSpeakWebSocket.ts index 3ef8851..d9fb826 100644 --- a/makima/frontend/src/hooks/useSpeakWebSocket.ts +++ b/makima/frontend/src/hooks/useSpeakWebSocket.ts @@ -22,7 +22,7 @@ export function useSpeakWebSocket() { const wsRef = useRef<WebSocket | null>(null); const audioContextRef = useRef<AudioContext | null>(null); - const audioQueueRef = useRef<Float32Array[]>([]); + const audioQueueRef = useRef<Float32Array<ArrayBuffer>[]>([]); const isPlayingRef = useRef(false); const modelLoadingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); const nextPlayTimeRef = useRef(0); diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts index ca04ce7..8838dbd 100644 --- a/makima/frontend/src/lib/api.ts +++ b/makima/frontend/src/lib/api.ts @@ -1636,6 +1636,8 @@ export interface ContractTypeTemplate { defaultPhase: ContractPhase; /** Whether this is a built-in type (always available) */ isBuiltin: boolean; + /** Optional mapping from phase ID to display name */ + phaseNames?: Record<string, string>; } /** Response from list contract types endpoint */ @@ -1680,6 +1682,8 @@ export interface ContractSummary { supervisorTaskId: string | null; /** When true, tasks won't auto-push or create PRs - use patch files instead */ localOnly: boolean; + /** When true, a red team task monitors work output for quality */ + redTeamEnabled: boolean; fileCount: number; taskCount: number; repositoryCount: number; @@ -1704,6 +1708,10 @@ export interface Contract { phaseGuard: boolean; /** When true, tasks won't auto-push or create PRs - use patch files instead */ localOnly: boolean; + /** When true, a red team task monitors work output for quality */ + redTeamEnabled: boolean; + /** Custom criteria for the red team to evaluate */ + redTeamPrompt: string | null; version: number; createdAt: string; updatedAt: string; @@ -1739,6 +1747,10 @@ export interface CreateContractRequest { initialPhase?: ContractPhase; /** When true, tasks won't auto-push or create PRs - use patch files instead */ localOnly?: boolean; + /** When true, spawn a red team task to monitor work output */ + redTeamEnabled?: boolean; + /** Custom criteria for the red team to evaluate */ + redTeamPrompt?: string; } export interface UpdateContractRequest { diff --git a/makima/frontend/src/routes/contracts.tsx b/makima/frontend/src/routes/contracts.tsx index aa62bd9..bb66215 100644 --- a/makima/frontend/src/routes/contracts.tsx +++ b/makima/frontend/src/routes/contracts.tsx @@ -93,6 +93,8 @@ function ContractsPageContent() { const [contractTypes, setContractTypes] = useState<ContractTypeTemplate[]>([]); const [contractTypesLoading, setContractTypesLoading] = useState(false); const [localOnly, setLocalOnly] = useState(false); + const [redTeamEnabled, setRedTeamEnabled] = useState(false); + const [redTeamPrompt, setRedTeamPrompt] = useState(""); // Fetch contract types when modal opens - merges built-in types with user templates useEffect(() => { @@ -108,11 +110,12 @@ function ContractsPageContent() { // Convert user templates to ContractTypeTemplate format, excluding built-ins return templates .filter((t: { isBuiltIn?: boolean }) => !t.isBuiltIn) - .map((t: { id: string; name: string; description: string; phases: { id: string }[] }) => ({ + .map((t: { id: string; name: string; description: string; phases: { id: string; name: string }[] }) => ({ id: t.id, name: t.name, description: t.description, phases: t.phases.map((p: { id: string }) => p.id) as ContractPhase[], + phaseNames: Object.fromEntries(t.phases.map((p: { id: string; name: string }) => [p.id, p.name])), defaultPhase: (t.phases[0]?.id || "execute") as ContractPhase, isBuiltin: false, })); @@ -265,6 +268,8 @@ function ContractsPageContent() { contractType: contractType, initialPhase: initialPhase !== defaultPhaseForType ? initialPhase : undefined, localOnly: localOnly || undefined, + redTeamEnabled: redTeamEnabled || undefined, + redTeamPrompt: redTeamEnabled && redTeamPrompt.trim() ? redTeamPrompt.trim() : undefined, }; try { @@ -340,6 +345,8 @@ function ContractsPageContent() { setRepoUrl(""); setRepoPath(""); setLocalOnly(false); + setRedTeamEnabled(false); + setRedTeamPrompt(""); setCreateError(null); }, []); @@ -652,11 +659,17 @@ function ContractsPageContent() { onChange={(e) => setInitialPhase(e.target.value as ContractPhase)} className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-sm focus:outline-none focus:border-[#75aafc]" > - {(contractTypes.find((t) => t.id === contractType)?.phases || []).map((phase) => ( - <option key={phase} value={phase}> - {phase.charAt(0).toUpperCase() + phase.slice(1)} - </option> - ))} + {(() => { + const template = contractTypes.find((t) => t.id === contractType); + return (template?.phases || []).map((phase) => { + const displayName = template?.phaseNames?.[phase] || (phase.charAt(0).toUpperCase() + phase.slice(1)); + return ( + <option key={phase} value={phase}> + {displayName} + </option> + ); + }); + })()} </select> <p className="mt-1 font-mono text-xs text-[#8b949e]"> {contractType === "simple" @@ -705,6 +718,59 @@ function ContractsPageContent() { </p> </div> + {/* Red Team Monitoring */} + <div className="border-t border-[rgba(117,170,252,0.2)] pt-4"> + <div className="flex items-center gap-3"> + <button + type="button" + onClick={() => setRedTeamEnabled(!redTeamEnabled)} + className={`w-5 h-5 flex items-center justify-center border transition-colors ${ + redTeamEnabled + ? "bg-[#0f3c78] border-[#75aafc] text-[#dbe7ff]" + : "bg-[#0d1b2d] border-[#3f6fb3] text-transparent" + }`} + > + {redTeamEnabled && ( + <svg + xmlns="http://www.w3.org/2000/svg" + width="12" + height="12" + viewBox="0 0 24 24" + fill="none" + stroke="currentColor" + strokeWidth="3" + strokeLinecap="round" + strokeLinejoin="round" + > + <polyline points="20 6 9 17 4 12" /> + </svg> + )} + </button> + <label + className="font-mono text-sm text-[#dbe7ff] cursor-pointer select-none" + onClick={() => setRedTeamEnabled(!redTeamEnabled)} + > + Enable Red Team Monitoring + </label> + </div> + <p className="font-mono text-xs text-[#8b949e] pl-8"> + Spawns a parallel task to monitor work output for quality and compliance. + </p> + {redTeamEnabled && ( + <div className="mt-3 pl-8"> + <label className="block font-mono text-xs text-[#75aafc] uppercase mb-2"> + Custom Review Criteria (Optional) + </label> + <textarea + value={redTeamPrompt} + onChange={(e) => setRedTeamPrompt(e.target.value)} + placeholder="e.g., 'Focus on security best practices' or 'Ensure all functions have tests'" + className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] text-sm font-mono h-20 resize-none focus:border-[#75aafc] focus:outline-none" + /> + </div> + )} + </div> + {/* Repository Configuration */} <div className="border-t border-[rgba(117,170,252,0.2)] pt-4"> <label className="block font-mono text-xs text-[#75aafc] uppercase mb-3"> diff --git a/makima/frontend/tsconfig.tsbuildinfo b/makima/frontend/tsconfig.tsbuildinfo index b02179d..804859b 100644 --- a/makima/frontend/tsconfig.tsbuildinfo +++ b/makima/frontend/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/components/gridoverlay.tsx","./src/components/japanesehovertext.tsx","./src/components/logo.tsx","./src/components/masthead.tsx","./src/components/navstrip.tsx","./src/components/phaseconfirmationnotification.tsx","./src/components/protectedroute.tsx","./src/components/rewritelink.tsx","./src/components/simplemarkdown.tsx","./src/components/supervisorquestionnotification.tsx","./src/components/charts/chartrenderer.tsx","./src/components/contracts/autopilotpanel.tsx","./src/components/contracts/contractcliinput.tsx","./src/components/contracts/contractcontextmenu.tsx","./src/components/contracts/contractdetail.tsx","./src/components/contracts/contractlist.tsx","./src/components/contracts/phasebadge.tsx","./src/components/contracts/phaseconfirmationmodal.tsx","./src/components/contracts/phasedeliverablespanel.tsx","./src/components/contracts/phasehint.tsx","./src/components/contracts/phaseprogressbar.tsx","./src/components/contracts/quickactionbuttons.tsx","./src/components/contracts/repositorypanel.tsx","./src/components/contracts/taskderivationpreview.tsx","./src/components/files/bodyrenderer.tsx","./src/components/files/cliinput.tsx","./src/components/files/conflictnotification.tsx","./src/components/files/elementcontextmenu.tsx","./src/components/files/filedetail.tsx","./src/components/files/filelist.tsx","./src/components/files/reposyncindicator.tsx","./src/components/files/updatenotification.tsx","./src/components/files/versionhistorydropdown.tsx","./src/components/history/checkpointcard.tsx","./src/components/history/checkpointlist.tsx","./src/components/history/conversationmessage.tsx","./src/components/history/conversationview.tsx","./src/components/history/historyfilters.tsx","./src/components/history/resumecontrols.tsx","./src/components/history/timelineeventcard.tsx","./src/components/history/timelinelist.tsx","./src/components/history/index.ts","./src/components/listen/contractpickermodal.tsx","./src/components/listen/controlpanel.tsx","./src/components/listen/speakerpanel.tsx","./src/components/listen/transcriptanalysispanel.tsx","./src/components/listen/transcriptpanel.tsx","./src/components/mesh/branchtaskmodal.tsx","./src/components/mesh/contractcompletequestion.tsx","./src/components/mesh/directoryinput.tsx","./src/components/mesh/gitactionspanel.tsx","./src/components/mesh/inlinesubtaskeditor.tsx","./src/components/mesh/mergeconflictresolver.tsx","./src/components/mesh/overlaydiffviewer.tsx","./src/components/mesh/prpreview.tsx","./src/components/mesh/patcheslistpanel.tsx","./src/components/mesh/subtasktree.tsx","./src/components/mesh/taskdetail.tsx","./src/components/mesh/tasklist.tsx","./src/components/mesh/taskoutput.tsx","./src/components/mesh/tasktree.tsx","./src/components/mesh/unifiedmeshchatinput.tsx","./src/components/mesh/worktreefilespanel.tsx","./src/components/templates/templateeditor.tsx","./src/components/workflow/phasecolumn.tsx","./src/components/workflow/workflowboard.tsx","./src/components/workflow/workflowcontractcard.tsx","./src/contexts/authcontext.tsx","./src/contexts/supervisorquestionscontext.tsx","./src/hooks/usecontracts.ts","./src/hooks/usefilesubscription.ts","./src/hooks/usefiles.ts","./src/hooks/usemeshchathistory.ts","./src/hooks/usemicrophone.ts","./src/hooks/usetasksubscription.ts","./src/hooks/usetasks.ts","./src/hooks/usetextscramble.ts","./src/hooks/useversionhistory.ts","./src/hooks/usewebsocket.ts","./src/lib/api.ts","./src/lib/listenapi.ts","./src/lib/markdown.ts","./src/lib/supabase.ts","./src/routes/_index.tsx","./src/routes/contract-file.tsx","./src/routes/contracts.tsx","./src/routes/files.tsx","./src/routes/history.tsx","./src/routes/listen.tsx","./src/routes/login.tsx","./src/routes/mesh.tsx","./src/routes/settings.tsx","./src/routes/templates.tsx","./src/routes/workflow.tsx","./src/types/messages.ts","./src/types/templates.ts"],"version":"5.9.3"}
\ No newline at end of file +{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/components/gridoverlay.tsx","./src/components/japanesehovertext.tsx","./src/components/logo.tsx","./src/components/masthead.tsx","./src/components/navstrip.tsx","./src/components/phaseconfirmationnotification.tsx","./src/components/protectedroute.tsx","./src/components/rewritelink.tsx","./src/components/simplemarkdown.tsx","./src/components/supervisorquestionnotification.tsx","./src/components/charts/chartrenderer.tsx","./src/components/contracts/autopilotpanel.tsx","./src/components/contracts/contractcliinput.tsx","./src/components/contracts/contractcontextmenu.tsx","./src/components/contracts/contractdetail.tsx","./src/components/contracts/contractlist.tsx","./src/components/contracts/phasebadge.tsx","./src/components/contracts/phaseconfirmationmodal.tsx","./src/components/contracts/phasedeliverablespanel.tsx","./src/components/contracts/phasehint.tsx","./src/components/contracts/phaseprogressbar.tsx","./src/components/contracts/quickactionbuttons.tsx","./src/components/contracts/repositorypanel.tsx","./src/components/contracts/taskderivationpreview.tsx","./src/components/files/bodyrenderer.tsx","./src/components/files/cliinput.tsx","./src/components/files/conflictnotification.tsx","./src/components/files/elementcontextmenu.tsx","./src/components/files/filedetail.tsx","./src/components/files/filelist.tsx","./src/components/files/reposyncindicator.tsx","./src/components/files/updatenotification.tsx","./src/components/files/versionhistorydropdown.tsx","./src/components/history/checkpointcard.tsx","./src/components/history/checkpointlist.tsx","./src/components/history/conversationmessage.tsx","./src/components/history/conversationview.tsx","./src/components/history/historyfilters.tsx","./src/components/history/resumecontrols.tsx","./src/components/history/timelineeventcard.tsx","./src/components/history/timelinelist.tsx","./src/components/history/index.ts","./src/components/listen/contractpickermodal.tsx","./src/components/listen/controlpanel.tsx","./src/components/listen/speakerpanel.tsx","./src/components/listen/transcriptanalysispanel.tsx","./src/components/listen/transcriptpanel.tsx","./src/components/mesh/branchtaskmodal.tsx","./src/components/mesh/contractcompletequestion.tsx","./src/components/mesh/directoryinput.tsx","./src/components/mesh/gitactionspanel.tsx","./src/components/mesh/inlinesubtaskeditor.tsx","./src/components/mesh/mergeconflictresolver.tsx","./src/components/mesh/overlaydiffviewer.tsx","./src/components/mesh/prpreview.tsx","./src/components/mesh/patcheslistpanel.tsx","./src/components/mesh/subtasktree.tsx","./src/components/mesh/taskdetail.tsx","./src/components/mesh/tasklist.tsx","./src/components/mesh/taskoutput.tsx","./src/components/mesh/tasktree.tsx","./src/components/mesh/unifiedmeshchatinput.tsx","./src/components/mesh/worktreefilespanel.tsx","./src/components/templates/templateeditor.tsx","./src/components/workflow/phasecolumn.tsx","./src/components/workflow/workflowboard.tsx","./src/components/workflow/workflowcontractcard.tsx","./src/contexts/authcontext.tsx","./src/contexts/supervisorquestionscontext.tsx","./src/hooks/usecontracts.ts","./src/hooks/usefilesubscription.ts","./src/hooks/usefiles.ts","./src/hooks/usemeshchathistory.ts","./src/hooks/usemicrophone.ts","./src/hooks/usespeakwebsocket.ts","./src/hooks/usetasksubscription.ts","./src/hooks/usetasks.ts","./src/hooks/usetextscramble.ts","./src/hooks/useversionhistory.ts","./src/hooks/usewebsocket.ts","./src/lib/api.ts","./src/lib/listenapi.ts","./src/lib/markdown.ts","./src/lib/supabase.ts","./src/routes/_index.tsx","./src/routes/contract-file.tsx","./src/routes/contracts.tsx","./src/routes/files.tsx","./src/routes/history.tsx","./src/routes/listen.tsx","./src/routes/login.tsx","./src/routes/mesh.tsx","./src/routes/settings.tsx","./src/routes/speak.tsx","./src/routes/templates.tsx","./src/routes/workflow.tsx","./src/types/messages.ts","./src/types/templates.ts"],"version":"5.9.3"}
\ No newline at end of file |
