feat(FN-4854): complete Step 2 — hydrate agents cache

Fusion-Task-Id: FN-4854
Fusion-Task-Lineage: 969ec04a-efe3-4dee-b183-2d4f2de6b388
This commit is contained in:
Fusion (runfusion.ai)
2026-05-17 00:22:40 -07:00
committed by gsxdsm
parent 228daa8f35
commit 0f9c08ace7
2 changed files with 19 additions and 4 deletions

View File

@@ -45,6 +45,7 @@ describe("useAgents", () => {
beforeEach(() => {
MockEventSource.instances = [];
window.sessionStorage.clear();
window.localStorage.clear();
mockFetchAgents.mockReset().mockResolvedValue([]);
mockFetchAgentStats.mockReset().mockResolvedValue(defaultStats);
vi.spyOn(console, "error").mockImplementation(() => {});

View File

@@ -1,8 +1,9 @@
import { useState, useEffect, useCallback } from "react";
import { useState, useEffect, useCallback, useRef } from "react";
import type { Agent, AgentState, AgentCapability, AgentStats } from "../api";
import { fetchAgents, fetchAgentStats } from "../api";
import { isEphemeralAgent } from "@fusion/core";
import { subscribeSse } from "../sse-bus";
import { readCache, SWR_CACHE_KEYS, writeCache } from "../utils/swrCache";
interface UseAgentsOptions {
filterState?: AgentState | "all";
@@ -16,12 +17,21 @@ interface AgentFilter {
}
export function useAgents(projectId?: string, options?: UseAgentsOptions) {
const [agents, setAgents] = useState<Agent[]>([]);
const [stats, setStats] = useState<AgentStats | null>(null);
const [agents, setAgents] = useState<Agent[]>(() => {
const cached = readCache<Agent[]>(SWR_CACHE_KEYS.AGENTS);
return Array.isArray(cached) ? cached : [];
});
const [stats, setStats] = useState<AgentStats | null>(() => {
const cached = readCache<AgentStats>(SWR_CACHE_KEYS.AGENT_STATS);
return cached ?? null;
});
const [isLoading, setIsLoading] = useState(false);
const hasCachedHydrationRef = useRef(agents.length > 0 || stats !== null);
const loadAgents = useCallback(async (filter?: AgentFilter) => {
setIsLoading(true);
if (!hasCachedHydrationRef.current) {
setIsLoading(true);
}
try {
const filterState = options?.filterState;
const baseFilter = filterState && filterState !== "all" ? { state: filterState } : undefined;
@@ -40,6 +50,8 @@ export function useAgents(projectId?: string, options?: UseAgentsOptions) {
// with duplicate-key warnings until the dashboard runs out of heap.
const unique = Array.from(new Map(data.map((a) => [a.id, a])).values());
setAgents(unique);
writeCache(SWR_CACHE_KEYS.AGENTS, unique, { maxBytes: 500_000 });
hasCachedHydrationRef.current = hasCachedHydrationRef.current || unique.length > 0;
} catch (err) {
console.error("Failed to load agents:", err);
} finally {
@@ -51,6 +63,8 @@ export function useAgents(projectId?: string, options?: UseAgentsOptions) {
try {
const data = await fetchAgentStats(projectId);
setStats(data);
writeCache(SWR_CACHE_KEYS.AGENT_STATS, data, { maxBytes: 500_000 });
hasCachedHydrationRef.current = true;
} catch (err) {
console.error("Failed to load agent stats:", err);
}