diff options
Diffstat (limited to 'makima/frontend/src/components/directives')
| -rw-r--r-- | makima/frontend/src/components/directives/DirectiveDetail.tsx | 230 |
1 files changed, 1 insertions, 229 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveDetail.tsx b/makima/frontend/src/components/directives/DirectiveDetail.tsx index 369cdaa..f9e7eed 100644 --- a/makima/frontend/src/components/directives/DirectiveDetail.tsx +++ b/makima/frontend/src/components/directives/DirectiveDetail.tsx @@ -1,8 +1,7 @@ import { useState, useMemo, useEffect, useRef } from "react"; -import type { DirectiveWithSteps, DirectiveStatus, MemoryCategory } from "../../lib/api"; +import type { DirectiveWithSteps, DirectiveStatus } from "../../lib/api"; import { DirectiveDAG } from "./DirectiveDAG"; import { DirectiveLogStream } from "./DirectiveLogStream"; -import { useDirectiveMemories } from "../../hooks/useDirectiveMemories"; import { useMultiTaskSubscription } from "../../hooks/useMultiTaskSubscription"; const STATUS_BADGE: Record<DirectiveStatus, { color: string; label: string }> = { @@ -13,18 +12,6 @@ const STATUS_BADGE: Record<DirectiveStatus, { color: string; label: string }> = archived: { color: "text-[#556677] border-[#2a3a5a]", label: "ARCHIVED" }, }; -const CATEGORY_COLORS: Record<MemoryCategory, { text: string; border: string; bg: string; label: string }> = { - decision: { text: "text-amber-400", border: "border-amber-800", bg: "bg-amber-900/20", label: "Decision" }, - context: { text: "text-cyan-400", border: "border-cyan-800", bg: "bg-cyan-900/20", label: "Context" }, - preference: { text: "text-violet-400", border: "border-violet-800", bg: "bg-violet-900/20", label: "Preference" }, - learning: { text: "text-emerald-400", border: "border-emerald-800", bg: "bg-emerald-900/20", label: "Learning" }, - issue: { text: "text-red-400", border: "border-red-800", bg: "bg-red-900/20", label: "Issue" }, - progress: { text: "text-blue-400", border: "border-blue-800", bg: "bg-blue-900/20", label: "Progress" }, - other: { text: "text-[#7788aa]", border: "border-[#2a3a5a]", bg: "bg-[#1a2540]", label: "Other" }, -}; - -const ALL_CATEGORIES: MemoryCategory[] = ["decision", "context", "preference", "learning", "issue", "progress", "other"]; - interface DirectiveDetailProps { directive: DirectiveWithSteps; onStart: () => void; @@ -66,25 +53,6 @@ export function DirectiveDetail({ const terminalStatuses = new Set(["completed", "failed", "skipped"]); const hasTerminalTasks = directive.steps.some((s) => s.taskId && terminalStatuses.has(s.status)); - // Memory panel state - const [memoryOpen, setMemoryOpen] = useState(false); - const [addingMemory, setAddingMemory] = useState(false); - const [newCategory, setNewCategory] = useState<MemoryCategory>("context"); - const [newContent, setNewContent] = useState(""); - const [confirmClear, setConfirmClear] = useState(false); - - const { - grouped, - loading: memoryLoading, - error: memoryError, - add: addMemory, - remove: removeMemory, - clearAll: clearMemories, - refresh: refreshMemories, - } = useDirectiveMemories(directive.id); - - const totalMemories = Object.values(grouped).reduce((sum, arr) => sum + arr.length, 0); - // Build task map from directive steps and orchestrator const taskMap = useMemo(() => { const map = new Map<string, string>(); @@ -123,21 +91,6 @@ export function DirectiveDetail({ setEditingGoal(false); }; - const handleAddMemory = async () => { - if (!newContent.trim()) return; - await addMemory({ - category: newCategory, - content: newContent.trim(), - }); - setNewContent(""); - setAddingMemory(false); - }; - - const handleClearAll = async () => { - await clearMemories(); - setConfirmClear(false); - }; - return ( <div className="flex flex-col h-full overflow-y-auto"> {/* Header */} @@ -346,187 +299,6 @@ export function DirectiveDetail({ )} </div> - {/* Memory Panel */} - <div className="px-4 py-3 border-b border-[rgba(117,170,252,0.1)]"> - {/* Memory header — always visible */} - <div className="flex items-center justify-between"> - <button - type="button" - onClick={() => setMemoryOpen((v) => !v)} - className="flex items-center gap-1.5 group" - > - <span className="text-[10px] font-mono text-[#556677] group-hover:text-[#9bc3ff] transition-colors"> - {memoryOpen ? "\u25BC" : "\u25B6"} - </span> - <span className="text-[10px] font-mono text-[#9bc3ff] uppercase tracking-wide"> - Memory - </span> - {totalMemories > 0 && ( - <span className="text-[9px] font-mono text-[#556677] ml-1"> - ({totalMemories}) - </span> - )} - </button> - <div className="flex items-center gap-2" /> - </div> - - {/* Collapsible content */} - {memoryOpen && ( - <div className="mt-2"> - {memoryError && ( - <div className="text-[10px] font-mono text-red-400 mb-2 px-2 py-1 bg-red-900/10 border border-red-800/30 rounded"> - {memoryError} - </div> - )} - - {memoryLoading ? ( - <div className="text-[10px] font-mono text-[#556677] py-2">Loading...</div> - ) : totalMemories === 0 ? ( - <div className="text-[10px] font-mono text-[#556677] py-2"> - No memory entries yet. - </div> - ) : ( - /* Grouped entries */ - <div className="flex flex-col gap-2"> - {ALL_CATEGORIES.map((cat) => { - const entries = grouped[cat]; - if (entries.length === 0) return null; - const style = CATEGORY_COLORS[cat]; - return ( - <div key={cat}> - <div className="flex items-center gap-1.5 mb-1"> - <span className={`text-[9px] font-mono ${style.text} uppercase tracking-wider`}> - {style.label} - </span> - <span className="text-[9px] font-mono text-[#556677]"> - ({entries.length}) - </span> - </div> - <div className="flex flex-col gap-1"> - {entries.map((entry) => ( - <div - key={entry.id} - className={`flex items-start gap-2 px-2 py-1.5 rounded border ${style.border} ${style.bg}`} - > - <div className="flex-1 min-w-0"> - <p className="text-[10px] font-mono text-[#c0d0e0] whitespace-pre-wrap break-words"> - {entry.content} - </p> - </div> - <button - type="button" - onClick={() => removeMemory(entry.id)} - className="text-[9px] font-mono text-[#556677] hover:text-red-400 shrink-0 mt-0.5" - title="Delete entry" - > - x - </button> - </div> - ))} - </div> - </div> - ); - })} - </div> - )} - - {/* Action bar: Add + Clear */} - <div className="flex items-center gap-2 mt-2 pt-2 border-t border-[rgba(117,170,252,0.1)]"> - <button - type="button" - onClick={() => setAddingMemory((v) => !v)} - className="text-[10px] font-mono text-[#75aafc] hover:text-white border border-[rgba(117,170,252,0.2)] rounded px-2 py-0.5" - > - {addingMemory ? "Cancel" : "+ Add"} - </button> - {totalMemories > 0 && ( - <> - {confirmClear ? ( - <div className="flex items-center gap-1.5 ml-auto"> - <span className="text-[9px] font-mono text-red-400">Clear all?</span> - <button - type="button" - onClick={handleClearAll} - className="text-[9px] font-mono text-red-400 hover:text-red-300 border border-red-800 rounded px-1.5 py-0.5" - > - Yes - </button> - <button - type="button" - onClick={() => setConfirmClear(false)} - className="text-[9px] font-mono text-[#7788aa] hover:text-white border border-[#2a3a5a] rounded px-1.5 py-0.5" - > - No - </button> - </div> - ) : ( - <button - type="button" - onClick={() => setConfirmClear(true)} - className="text-[10px] font-mono text-[#556677] hover:text-red-400 ml-auto" - > - Clear all - </button> - )} - </> - )} - <button - type="button" - onClick={refreshMemories} - className="text-[9px] font-mono text-[#556677] hover:text-[#75aafc]" - title="Refresh memories" - > - [refresh] - </button> - </div> - - {/* Add form */} - {addingMemory && ( - <div className="mt-2 p-2 bg-[#0a1628] border border-[rgba(117,170,252,0.15)] rounded flex flex-col gap-2"> - <div className="flex items-center gap-2"> - <label className="text-[9px] font-mono text-[#7788aa] shrink-0">Category</label> - <select - value={newCategory} - onChange={(e) => setNewCategory(e.target.value as MemoryCategory)} - className="bg-[#1a2540] border border-[rgba(117,170,252,0.2)] rounded px-1.5 py-0.5 text-[10px] font-mono text-white flex-1" - > - {ALL_CATEGORIES.map((c) => ( - <option key={c} value={c}> - {CATEGORY_COLORS[c].label} - </option> - ))} - </select> - </div> - <textarea - value={newContent} - onChange={(e) => setNewContent(e.target.value)} - placeholder="Memory content..." - className="w-full bg-[#1a2540] border border-[rgba(117,170,252,0.2)] rounded px-2 py-1.5 text-[10px] font-mono text-white resize-y min-h-[40px] placeholder:text-[#556677]" - rows={2} - /> - <div className="flex gap-1.5"> - <button - type="button" - onClick={handleAddMemory} - disabled={!newContent.trim()} - className="text-[10px] font-mono text-emerald-400 hover:text-emerald-300 border border-emerald-800 rounded px-2 py-0.5 disabled:opacity-40 disabled:cursor-not-allowed" - > - Save - </button> - <button - type="button" - onClick={() => { setAddingMemory(false); setNewContent(""); }} - className="text-[10px] font-mono text-[#7788aa] hover:text-white border border-[#2a3a5a] rounded px-2 py-0.5" - > - Cancel - </button> - </div> - </div> - )} - </div> - )} - </div> - {/* DAG */} <div className="px-4 py-3 flex-1"> <span className="text-[10px] font-mono text-[#9bc3ff] uppercase tracking-wide block mb-2"> |
