summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/directives/DirectiveDetail.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'makima/frontend/src/components/directives/DirectiveDetail.tsx')
-rw-r--r--makima/frontend/src/components/directives/DirectiveDetail.tsx91
1 files changed, 59 insertions, 32 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveDetail.tsx b/makima/frontend/src/components/directives/DirectiveDetail.tsx
index 98940d0..171654d 100644
--- a/makima/frontend/src/components/directives/DirectiveDetail.tsx
+++ b/makima/frontend/src/components/directives/DirectiveDetail.tsx
@@ -1,6 +1,7 @@
import { useState, useMemo, useEffect, useRef } from "react";
import type { DirectiveWithSteps, DirectiveStatus, UpdateDirectiveRequest } from "../../lib/api";
import { DirectiveDAG } from "./DirectiveDAG";
+import type { SpecializedStep } from "./DirectiveDAG";
import { DirectiveLogStream } from "./DirectiveLogStream";
import { useMultiTaskSubscription } from "../../hooks/useMultiTaskSubscription";
import { useSupervisorQuestions } from "../../contexts/SupervisorQuestionsContext";
@@ -108,6 +109,33 @@ export function DirectiveDetail({
return map;
}, [taskMapKey]); // eslint-disable-line react-hooks/exhaustive-deps
+ // Build specialized steps for DAG visualization
+ const specializedSteps = useMemo(() => {
+ const steps: SpecializedStep[] = [];
+
+ if (directive.orchestratorTaskId) {
+ steps.push({
+ id: `orchestrator-${directive.orchestratorTaskId}`,
+ name: taskMap.get(directive.orchestratorTaskId) || "Planning",
+ type: "orchestrator",
+ taskId: directive.orchestratorTaskId,
+ status: "running",
+ });
+ }
+
+ if (directive.completionTaskId) {
+ steps.push({
+ id: `completion-${directive.completionTaskId}`,
+ name: directive.prUrl ? "Updating PR" : "Creating PR",
+ type: "completion",
+ taskId: directive.completionTaskId,
+ status: "running",
+ });
+ }
+
+ return steps;
+ }, [directive.orchestratorTaskId, directive.completionTaskId, directive.prUrl, taskMap]);
+
// Subscribe to all task outputs
const { connected, entries, clearEntries } = useMultiTaskSubscription({
taskMap,
@@ -149,6 +177,36 @@ export function DirectiveDetail({
setEditingGoal(false);
};
+ // Build virtual steps for orchestrator tasks to display in the DAG
+ const virtualSteps = useMemo(() => {
+ const steps: VirtualStep[] = [];
+ if (directive.orchestratorTaskId) {
+ const hasOrchestratorQuestions = directiveQuestions.some(
+ (q) => q.taskId === directive.orchestratorTaskId
+ );
+ steps.push({
+ type: "planning",
+ taskId: directive.orchestratorTaskId,
+ status: "running",
+ label: "Planning",
+ hasQuestions: hasOrchestratorQuestions,
+ });
+ }
+ if (directive.completionTaskId) {
+ const hasCompletionQuestions = directiveQuestions.some(
+ (q) => q.taskId === directive.completionTaskId
+ );
+ steps.push({
+ type: directive.prUrl ? "pr-update" : "pr",
+ taskId: directive.completionTaskId,
+ status: "running",
+ label: directive.prUrl ? "Updating PR" : "Creating PR",
+ hasQuestions: hasCompletionQuestions,
+ });
+ }
+ return steps;
+ }, [directive.orchestratorTaskId, directive.completionTaskId, directive.prUrl, directiveQuestions]);
+
return (
<div className="flex flex-col h-full overflow-y-auto">
{/* Header */}
@@ -217,22 +275,6 @@ export function DirectiveDetail({
</span>
</div>
- {/* Orchestrator planning indicator */}
- {directive.orchestratorTaskId && (
- <div className="flex items-center gap-2 mb-2 px-2 py-1.5 bg-[#1a1a30] border border-[rgba(117,170,252,0.2)] rounded">
- <span className="inline-block w-2 h-2 rounded-full bg-[#75aafc] animate-pulse" />
- <span className="text-[10px] font-mono text-[#75aafc]">
- Planning in progress...
- </span>
- <a
- href={`/mesh/${directive.orchestratorTaskId}`}
- className="text-[9px] font-mono text-[#556677] hover:text-[#75aafc] underline ml-auto"
- >
- View task
- </a>
- </div>
- )}
-
{/* PR link */}
{directive.prUrl && (
<div className="flex items-center gap-2 mb-2 px-2 py-1.5 bg-[#0a1a10] border border-emerald-900 rounded">
@@ -251,22 +293,6 @@ export function DirectiveDetail({
</div>
)}
- {/* Completion task indicator */}
- {directive.completionTaskId && (
- <div className="flex items-center gap-2 mb-2 px-2 py-1.5 bg-[#1a1a10] border border-yellow-900 rounded">
- <span className="inline-block w-2 h-2 rounded-full bg-yellow-400 animate-pulse" />
- <span className="text-[10px] font-mono text-yellow-400">
- {directive.prUrl ? "Updating PR..." : "Creating PR..."}
- </span>
- <a
- href={`/mesh/${directive.completionTaskId}`}
- className="text-[9px] font-mono text-[#556677] hover:text-yellow-400 underline ml-auto"
- >
- View task
- </a>
- </div>
- )}
-
{/* Pending Questions */}
{directiveQuestions.length > 0 && (
<div className="mb-2 space-y-2">
@@ -423,6 +449,7 @@ export function DirectiveDetail({
</span>
<DirectiveDAG
steps={directive.steps}
+ specializedSteps={specializedSteps}
onComplete={onCompleteStep}
onFail={onFailStep}
onSkip={onSkipStep}