From 6a34a6f3c423a7c57616762eb4cea2b7da52eaf3 Mon Sep 17 00:00:00 2001 From: soryu Date: Sun, 22 Feb 2026 14:39:14 +0000 Subject: feat: Add daemon page with download binary and Cloudflare Agent setup (#77) * feat: soryu-co/soryu - makima: Create DaemonList and DaemonDetail page components * feat: soryu-co/soryu - makima: Add daemon page routes, CSS styles, and navigation * feat: soryu-co/soryu - makima: Create daemon page with download and monitoring * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Integrate Cloudflare Agent setup into daemon page --- .../frontend/src/hooks/useMultiTaskSubscription.ts | 84 ---------------------- 1 file changed, 84 deletions(-) (limited to 'makima/frontend/src/hooks') diff --git a/makima/frontend/src/hooks/useMultiTaskSubscription.ts b/makima/frontend/src/hooks/useMultiTaskSubscription.ts index 41489c7..b229e90 100644 --- a/makima/frontend/src/hooks/useMultiTaskSubscription.ts +++ b/makima/frontend/src/hooks/useMultiTaskSubscription.ts @@ -31,8 +31,6 @@ export function useMultiTaskSubscription(options: UseMultiTaskSubscriptionOption const backfilledTasksRef = useRef>(new Set()); const taskMapRef = useRef(taskMap); const enabledRef = useRef(enabled); - /** Track which task IDs have already been backfilled to avoid re-fetching */ - const backfilledTasksRef = useRef>(new Set()); // Keep refs in sync useEffect(() => { @@ -43,88 +41,6 @@ export function useMultiTaskSubscription(options: UseMultiTaskSubscriptionOption enabledRef.current = enabled; }, [enabled]); - /** Max number of historical events to backfill per task */ - const MAX_BACKFILL_PER_TASK = 200; - - /** - * Convert a TaskEvent (from the REST API) into a MultiTaskOutputEntry. - * Only converts events with event_type === 'output'. - */ - const convertTaskEventToEntry = useCallback( - (event: TaskEvent): MultiTaskOutputEntry | null => { - if (event.eventType !== "output") return null; - const data = event.eventData; - if (!data) return null; - - return { - taskId: event.taskId, - messageType: (data.messageType as string) || "system", - content: (data.content as string) || "", - toolName: data.toolName as string | undefined, - toolInput: data.toolInput as Record | undefined, - isError: data.isError as boolean | undefined, - costUsd: data.costUsd as number | undefined, - durationMs: data.durationMs as number | undefined, - isPartial: false, - taskLabel: - taskMapRef.current.get(event.taskId) || event.taskId, - receivedAt: new Date(event.createdAt).getTime(), - isBackfill: true, - }; - }, - [] - ); - - /** - * Backfill historical log entries for a task from the REST API. - * Only fetches once per task ID (tracked in backfilledTasksRef). - */ - const backfillTask = useCallback( - async (taskId: string) => { - if (backfilledTasksRef.current.has(taskId)) return; - backfilledTasksRef.current.add(taskId); - - try { - const response = await listTaskEvents(taskId); - const events = response.events; - - // The API returns events in DESC order; reverse to get chronological ASC - const chronologicalEvents = [...events].reverse(); - - // Filter to output events and convert, limiting to MAX_BACKFILL_PER_TASK - const backfillEntries: MultiTaskOutputEntry[] = []; - for (const event of chronologicalEvents) { - const entry = convertTaskEventToEntry(event); - if (entry) { - backfillEntries.push(entry); - if (backfillEntries.length >= MAX_BACKFILL_PER_TASK) break; - } - } - - if (backfillEntries.length === 0) return; - - // Prepend historical entries before any existing live entries for this task, - // maintaining overall chronological order across all tasks - setEntries((prev) => { - // Merge backfill entries with existing entries, maintaining chronological order - const merged = [...backfillEntries, ...prev]; - // Sort by receivedAt to ensure proper chronological ordering - merged.sort((a, b) => a.receivedAt - b.receivedAt); - // Trim to maxEntries - if (merged.length > maxEntries) { - return merged.slice(merged.length - maxEntries); - } - return merged; - }); - } catch (e) { - console.error(`Failed to backfill task events for ${taskId}:`, e); - // Remove from backfilled set so it can be retried - backfilledTasksRef.current.delete(taskId); - } - }, - [convertTaskEventToEntry, maxEntries] - ); - // Derive task IDs from the map, stabilized to avoid unnecessary effect triggers const taskIdsKey = useMemo(() => Array.from(taskMap.keys()).sort().join(","), [taskMap]); const taskIds = useMemo(() => Array.from(taskMap.keys()), [taskIdsKey]); // eslint-disable-line react-hooks/exhaustive-deps -- cgit v1.2.3