From 78cb861412850889424ae7d5ae5cd952a2b90295 Mon Sep 17 00:00:00 2001 From: soryu Date: Mon, 2 Mar 2026 15:18:31 +0000 Subject: feat: move daemon reauth to daemons page, add contract-backed directive steps, rename Mesh to Exec (#84) * feat: soryu-co/soryu - makima: Rename Mesh to Exec in navigation * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Add contract-backed steps to directive flow * WIP: heartbeat checkpoint --- makima/frontend/src/components/NavStrip.tsx | 2 +- .../components/PhaseConfirmationNotification.tsx | 2 +- .../components/SupervisorQuestionNotification.tsx | 2 +- .../src/components/contracts/CommandModePanel.tsx | 2 +- .../src/components/directives/DirectiveDAG.tsx | 2 +- .../components/directives/OrchestratorStepNode.tsx | 2 +- .../src/components/directives/StepNode.tsx | 25 ++++- makima/frontend/src/components/mesh/TaskOutput.tsx | 110 ++++----------------- 8 files changed, 45 insertions(+), 102 deletions(-) (limited to 'makima/frontend/src/components') diff --git a/makima/frontend/src/components/NavStrip.tsx b/makima/frontend/src/components/NavStrip.tsx index 9556458..17013ac 100644 --- a/makima/frontend/src/components/NavStrip.tsx +++ b/makima/frontend/src/components/NavStrip.tsx @@ -14,7 +14,7 @@ const NAV_LINKS: NavLink[] = [ { label: "Directives", href: "/directives", requiresAuth: true }, { label: "Orders", href: "/orders", requiresAuth: true }, { label: "Contracts", href: "/contracts", requiresAuth: true }, - { label: "Mesh", href: "/mesh", requiresAuth: true }, + { label: "Exec", href: "/exec", requiresAuth: true }, { label: "Daemons", href: "/daemons", requiresAuth: true }, { label: "History", href: "/history", requiresAuth: true }, ]; diff --git a/makima/frontend/src/components/PhaseConfirmationNotification.tsx b/makima/frontend/src/components/PhaseConfirmationNotification.tsx index 516211f..2681fdc 100644 --- a/makima/frontend/src/components/PhaseConfirmationNotification.tsx +++ b/makima/frontend/src/components/PhaseConfirmationNotification.tsx @@ -86,7 +86,7 @@ export function PhaseConfirmationToast() { const handleGoToTask = (question: PendingQuestion) => { dismissNotification(question.questionId); - navigate(`/mesh/${question.taskId}`); + navigate(`/exec/${question.taskId}`); }; return ( diff --git a/makima/frontend/src/components/SupervisorQuestionNotification.tsx b/makima/frontend/src/components/SupervisorQuestionNotification.tsx index b1cbacc..e62638c 100644 --- a/makima/frontend/src/components/SupervisorQuestionNotification.tsx +++ b/makima/frontend/src/components/SupervisorQuestionNotification.tsx @@ -16,7 +16,7 @@ export function SupervisorQuestionNotification() { const handleGoToTask = (questionId: string, taskId: string) => { dismissNotification(questionId); - navigate(`/mesh/${taskId}`); + navigate(`/exec/${taskId}`); }; return ( diff --git a/makima/frontend/src/components/contracts/CommandModePanel.tsx b/makima/frontend/src/components/contracts/CommandModePanel.tsx index 832d5ec..b39b309 100644 --- a/makima/frontend/src/components/contracts/CommandModePanel.tsx +++ b/makima/frontend/src/components/contracts/CommandModePanel.tsx @@ -65,7 +65,7 @@ export function CommandModePanel({ contract, onUpdate }: CommandModePanelProps) const handleGoToSupervisor = useCallback(() => { if (supervisorStatus.supervisorTaskId) { - navigate(`/mesh/${supervisorStatus.supervisorTaskId}`); + navigate(`/exec/${supervisorStatus.supervisorTaskId}`); } }, [supervisorStatus.supervisorTaskId, navigate]); const config = statusConfig[supervisorStatus.status]; diff --git a/makima/frontend/src/components/directives/DirectiveDAG.tsx b/makima/frontend/src/components/directives/DirectiveDAG.tsx index 142df41..f225356 100644 --- a/makima/frontend/src/components/directives/DirectiveDAG.tsx +++ b/makima/frontend/src/components/directives/DirectiveDAG.tsx @@ -146,7 +146,7 @@ function SpecializedStepNode({ step }: { step: SpecializedStep }) { {step.name} View task diff --git a/makima/frontend/src/components/directives/OrchestratorStepNode.tsx b/makima/frontend/src/components/directives/OrchestratorStepNode.tsx index 9c8e95e..3fccb4b 100644 --- a/makima/frontend/src/components/directives/OrchestratorStepNode.tsx +++ b/makima/frontend/src/components/directives/OrchestratorStepNode.tsx @@ -151,7 +151,7 @@ export function OrchestratorStepNode({ {/* Task link */} {status === "running" ? "View running task" : "View task"} diff --git a/makima/frontend/src/components/directives/StepNode.tsx b/makima/frontend/src/components/directives/StepNode.tsx index 2844b4a..775b898 100644 --- a/makima/frontend/src/components/directives/StepNode.tsx +++ b/makima/frontend/src/components/directives/StepNode.tsx @@ -28,10 +28,11 @@ interface StepNodeProps { export function StepNode({ step, onComplete, onFail, onSkip }: StepNodeProps) { const colors = STATUS_COLORS[step.status] || STATUS_COLORS.pending; const label = STATUS_LABELS[step.status] || step.status.toUpperCase(); + const isContractBacked = !!step.contractType; return (
@@ -41,14 +42,32 @@ export function StepNode({ step, onComplete, onFail, onSkip }: StepNodeProps) { {label}
+ {isContractBacked && ( +
+ + CONTRACT + + + {step.contractType} + +
+ )} {step.description && (

{step.description}

)} - {step.taskId && ( + {step.contractId && ( +
+ {step.status === "running" ? "Contract running..." : "View contract"} + + )} + {step.taskId && !step.contractId && ( {step.status === "running" ? "Auto-executing..." : "View task"} diff --git a/makima/frontend/src/components/mesh/TaskOutput.tsx b/makima/frontend/src/components/mesh/TaskOutput.tsx index 2db4250..1a376ad 100644 --- a/makima/frontend/src/components/mesh/TaskOutput.tsx +++ b/makima/frontend/src/components/mesh/TaskOutput.tsx @@ -309,7 +309,21 @@ function OutputEntryRenderer({ entry, pendingQuestionIds, onAnswerQuestion }: Ou ); case "auth_required": - return ; + return ( +
+
+ + Authentication Expired{entry.toolInput?.hostname ? ` (${entry.toolInput.hostname})` : ""} +
+

+ The daemon's OAuth token has expired. Go to the{" "} + + Daemons page + {" "} + to reauthorize, then retry this task. +

+
+ ); case "supervisor_question": return ( @@ -501,98 +515,8 @@ function SupervisorQuestionEntry({ ); } -function AuthRequiredEntry({ entry }: { entry: TaskOutputEvent }) { - const [authCode, setAuthCode] = useState(""); - const [submitting, setSubmitting] = useState(false); - const [submitted, setSubmitted] = useState(false); - const [error, setError] = useState(null); - - const loginUrl = entry.toolInput?.loginUrl as string | undefined; - const hostname = entry.toolInput?.hostname as string | undefined; - // Get taskId from entry or fallback to toolInput (for robustness) - const taskId = entry.taskId || (entry.toolInput?.taskId as string | undefined); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - if (!authCode.trim() || !taskId) return; - - setSubmitting(true); - setError(null); - - try { - // Send the auth code to the task via the message endpoint - await sendTaskMessage(taskId, `AUTH_CODE:${authCode.trim()}`); - setSubmitted(true); - } catch (err) { - setError(err instanceof Error ? err.message : "Failed to submit code"); - } finally { - setSubmitting(false); - } - }; - - if (submitted) { - return ( -
-
- - Authentication code submitted -
-

- Waiting for authentication to complete... -

-
- ); - } - - return ( -
-
- 🔐 - Authentication Required{hostname ? ` (${hostname})` : ""} -
-

- The daemon's OAuth token has expired. Click the button to login, then paste the code below: -

- -
- {loginUrl ? ( - - 1. Login to Claude - - ) : ( -

Login URL not available

- )} - -
- setAuthCode(e.target.value)} - placeholder="2. Paste authentication code here" - className="flex-1 bg-[#0a1525] border border-amber-500/30 rounded px-3 py-2 text-amber-100 placeholder-amber-500/50 focus:outline-none focus:border-amber-400" - disabled={submitting} - /> - -
- - {error && ( -

{error}

- )} -
-
- ); -} +// AuthRequiredEntry has been removed - auth flow is now on the Daemons page. +// The "auth_required" case in OutputEntryRenderer shows a redirect message instead. /** Entry for phase transition confirmations */ function PhaseConfirmationEntry({ -- cgit v1.2.3