From f49aaa39a32661b54c109ba002d24cbdf73f4ea3 Mon Sep 17 00:00:00 2001 From: soryu Date: Mon, 9 Mar 2026 17:20:52 +0000 Subject: feat: worktree diff/commit endpoints and frontend diff viewing (#88) * feat: soryu-co/soryu - makima: Fix worktree info failing when origin ref is missing * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Add worktree commit endpoint and diff endpoint for regular users * feat: soryu-co/soryu - makima: Add frontend diff viewing with clickable worktree files --- .../src/components/mesh/GitActionsPanel.tsx | 40 +++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'makima/frontend/src/components/mesh/GitActionsPanel.tsx') diff --git a/makima/frontend/src/components/mesh/GitActionsPanel.tsx b/makima/frontend/src/components/mesh/GitActionsPanel.tsx index be2e06d..ff1dc7d 100644 --- a/makima/frontend/src/components/mesh/GitActionsPanel.tsx +++ b/makima/frontend/src/components/mesh/GitActionsPanel.tsx @@ -1,5 +1,5 @@ import { useState, useCallback } from "react"; -import { exportTaskPatch, pushTaskBranch, createTaskPR, type ExportPatchResponse } from "../../lib/api"; +import { exportTaskPatch, pushTaskBranch, createTaskPR, commitWorktree, type ExportPatchResponse } from "../../lib/api"; interface GitActionsPanelProps { taskId: string; @@ -20,6 +20,8 @@ export function GitActionsPanel({ const [isExporting, setIsExporting] = useState(false); const [isPushing, setIsPushing] = useState(false); const [isCreatingPR, setIsCreatingPR] = useState(false); + const [isCommitting, setIsCommitting] = useState(false); + const [commitMessage, setCommitMessage] = useState(""); const [toast, setToast] = useState(null); const [exportedPatch, setExportedPatch] = useState(null); @@ -82,6 +84,23 @@ export function GitActionsPanel({ } }, [taskId, isLocalOnly]); + const handleCommit = useCallback(async () => { + setIsCommitting(true); + try { + const result = await commitWorktree(taskId, commitMessage || undefined); + if (result.success) { + showToast("success", `Committed: ${result.commitSha?.substring(0, 8) || "done"}`); + setCommitMessage(""); + } else { + showToast("error", result.error || "Failed to commit"); + } + } catch (e) { + showToast("error", e instanceof Error ? e.message : "Failed to commit"); + } finally { + setIsCommitting(false); + } + }, [taskId, commitMessage]); + return (
{/* Section Header */} @@ -112,6 +131,25 @@ export function GitActionsPanel({
)} + {/* Commit section */} +
+ setCommitMessage(e.target.value)} + placeholder="Commit message (optional)" + className="flex-1 px-2 py-1.5 font-mono text-xs bg-transparent border border-[rgba(117,170,252,0.2)] text-[#dbe7ff] placeholder:text-[#555] focus:border-[#75aafc] focus:outline-none" + onKeyDown={(e) => { if (e.key === "Enter") handleCommit(); }} + /> + +
+ {/* Action buttons */}