From 9e724358438e7a6da69657260a218aedd76f1911 Mon Sep 17 00:00:00 2001
From: soryu <soryu@soryu.co>
Date: Wed, 21 Jan 2026 16:20:05 +0000
Subject: feat(frontend): Add branch task handler to mesh route

- Import branchTask API function
- Add handleBranch callback that calls branchTask and navigates to new task
- Pass onBranch prop to TaskDetail component

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 makima/frontend/src/routes/mesh.tsx | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

(limited to 'makima/frontend/src/routes/mesh.tsx')

diff --git a/makima/frontend/src/routes/mesh.tsx b/makima/frontend/src/routes/mesh.tsx
index a8d3574..157d70f 100644
--- a/makima/frontend/src/routes/mesh.tsx
+++ b/makima/frontend/src/routes/mesh.tsx
@@ -8,7 +8,7 @@ import { UnifiedMeshChatInput } from "../components/mesh/UnifiedMeshChatInput";
 import { useTasks } from "../hooks/useTasks";
 import { useTaskSubscription, type TaskUpdateEvent, type TaskOutputEvent } from "../hooks/useTaskSubscription";
 import type { TaskWithSubtasks, MeshChatContext, ContractSummary, ContractWithRelations, DaemonDirectory, TaskSummary } from "../lib/api";
-import { startTask as startTaskApi, stopTask as stopTaskApi, getTaskOutput, listContracts, getContract, getDaemonDirectories, continueTask as continueTaskApi, resumeSupervisor } from "../lib/api";
+import { startTask as startTaskApi, stopTask as stopTaskApi, getTaskOutput, listContracts, getContract, getDaemonDirectories, continueTask as continueTaskApi, resumeSupervisor, branchTask } from "../lib/api";
 import { DirectoryInput } from "../components/mesh/DirectoryInput";
 import { useAuth } from "../contexts/AuthContext";
 import { useSupervisorQuestions } from "../contexts/SupervisorQuestionsContext";
@@ -452,6 +452,25 @@ export default function MeshPage() {
     [editTask, taskDetail]
   );
 
+  const handleBranch = useCallback(
+    async (taskId: string, message: string, name?: string) => {
+      try {
+        const result = await branchTask(taskId, {
+          message,
+          name,
+          includeConversation: true,
+        });
+        console.log(`[Mesh] Task branched, new task ID: ${result.task.id}`);
+        // Navigate to the new branched task
+        navigate(`/mesh/${result.task.id}`);
+      } catch (e) {
+        console.error("Failed to branch task:", e);
+        throw e; // Re-throw so the modal can display the error
+      }
+    },
+    [navigate]
+  );
+
   // Open contract selection modal
   const handleCreate = useCallback(async () => {
     if (creating || contractsLoading) return;
@@ -733,6 +752,7 @@ export default function MeshPage() {
                       onToggleSubtaskOutput={handleToggleSubtaskOutput}
                       viewingSubtaskId={viewingSubtaskId}
                       onViewContract={(contractId) => navigate(`/contracts/${contractId}`)}
+                      onBranch={handleBranch}
                       contractTasks={taskDetail.isSupervisor ? contractTasks : undefined}
                     />
                   </div>
-- 
cgit v1.2.3

