diff options
| author | soryu <soryu@soryu.co> | 2026-03-04 16:47:12 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-04 16:47:12 +0000 |
| commit | ec9738a069e61529be040eff065318972b8a11e2 (patch) | |
| tree | d1b15d3b22d4980acff4fba8a12b99920035025c /makima/frontend/src/components/directives/DirectiveDetail.tsx | |
| parent | 78cb861412850889424ae7d5ae5cd952a2b90295 (diff) | |
| download | soryu-ec9738a069e61529be040eff065318972b8a11e2.tar.gz soryu-ec9738a069e61529be040eff065318972b8a11e2.zip | |
feat: task slide-out panel, 3-way reconcile toggle, daemon reauth fix (#85)
* WIP: heartbeat checkpoint
* WIP: heartbeat checkpoint
* feat: soryu-co/soryu - makima: Fix daemon reauth flow for new claude setup-token output format
* feat: soryu-co/soryu - makima: Update frontend reconcile toggle to three-way switch
* feat: soryu-co/soryu - makima: Add task slide-out panel to directive page
Diffstat (limited to 'makima/frontend/src/components/directives/DirectiveDetail.tsx')
| -rw-r--r-- | makima/frontend/src/components/directives/DirectiveDetail.tsx | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveDetail.tsx b/makima/frontend/src/components/directives/DirectiveDetail.tsx index 8f39207..5f3489a 100644 --- a/makima/frontend/src/components/directives/DirectiveDetail.tsx +++ b/makima/frontend/src/components/directives/DirectiveDetail.tsx @@ -3,6 +3,7 @@ import type { DirectiveWithSteps, DirectiveStatus, UpdateDirectiveRequest } from import { DirectiveDAG } from "./DirectiveDAG"; import type { SpecializedStep } from "./DirectiveDAG"; import { DirectiveLogStream } from "./DirectiveLogStream"; +import { TaskSlideOutPanel } from "./TaskSlideOutPanel"; import { useMultiTaskSubscription } from "../../hooks/useMultiTaskSubscription"; import { useSupervisorQuestions } from "../../contexts/SupervisorQuestionsContext"; @@ -53,6 +54,11 @@ export function DirectiveDetail({ const [pickingUpOrders, setPickingUpOrders] = useState(false); const [pickUpResult, setPickUpResult] = useState<string | null>(null); const [creatingPR, setCreatingPR] = useState(false); + const [slideOutTaskId, setSlideOutTaskId] = useState<string | null>(null); + + const handleViewTask = (taskId: string) => { + setSlideOutTaskId(taskId); + }; // Sync goalText and reset editing state when directive changes useEffect(() => { @@ -178,7 +184,15 @@ export function DirectiveDetail({ }; + // Find the task name for the slide-out panel + const slideOutTaskName = slideOutTaskId + ? (directive.steps.find((s) => s.taskId === slideOutTaskId)?.name ?? + taskMap.get(slideOutTaskId) ?? + undefined) + : undefined; + return ( + <> <div className="flex flex-col h-full overflow-y-auto"> {/* Header */} <div className="px-4 py-3 border-b border-dashed border-[rgba(117,170,252,0.2)]"> @@ -228,21 +242,31 @@ export function DirectiveDetail({ {/* Reconcile mode toggle */} <div className="flex items-center gap-2 mb-2"> - <button - type="button" - onClick={() => onUpdate({ reconcileMode: !directive.reconcileMode })} - className={`text-[10px] font-mono border rounded px-2 py-0.5 transition-colors ${ - directive.reconcileMode - ? "text-amber-400 border-amber-800 bg-amber-900/20" - : "text-[#556677] border-[#2a3a5a] hover:text-[#7788aa]" - }`} - > - {directive.reconcileMode ? "Reconcile: ON" : "Reconcile: OFF"} - </button> + <div className="flex items-center border border-[#2a3a5a] rounded overflow-hidden"> + {(["auto", "semi-auto", "manual"] as const).map((mode) => { + const isActive = directive.reconcileMode === mode; + const modeStyles: Record<string, string> = { + auto: isActive ? "text-[#9bc3ff] bg-[#1a2540]" : "text-[#445566] hover:text-[#7788aa]", + "semi-auto": isActive ? "text-amber-400 bg-amber-900/20" : "text-[#445566] hover:text-[#7788aa]", + manual: isActive ? "text-orange-400 bg-orange-900/20" : "text-[#445566] hover:text-[#7788aa]", + }; + const labels: Record<string, string> = { auto: "Auto", "semi-auto": "Semi", manual: "Manual" }; + return ( + <button + key={mode} + type="button" + onClick={() => onUpdate({ reconcileMode: mode })} + className={`text-[10px] font-mono px-2 py-0.5 transition-colors border-r border-[#2a3a5a] last:border-r-0 ${modeStyles[mode]}`} + > + {labels[mode]} + </button> + ); + })} + </div> <span className="text-[9px] font-mono text-[#445566]"> - {directive.reconcileMode - ? "Questions pause execution" - : "Questions timeout after 30s"} + {directive.reconcileMode === "auto" && "Questions timeout after 30s"} + {directive.reconcileMode === "semi-auto" && "Questions pause execution"} + {directive.reconcileMode === "manual" && "Tasks ask clarifying questions"} </span> </div> @@ -424,6 +448,7 @@ export function DirectiveDetail({ onComplete={onCompleteStep} onFail={onFailStep} onSkip={onSkipStep} + onViewTask={handleViewTask} /> </div> @@ -445,6 +470,14 @@ export function DirectiveDetail({ </div> )} </div> + + <TaskSlideOutPanel + taskId={slideOutTaskId || ""} + taskName={slideOutTaskName} + isOpen={!!slideOutTaskId} + onClose={() => setSlideOutTaskId(null)} + /> + </> ); } |
