diff --git a/canvas/src/components/tabs/ConfigTab.tsx b/canvas/src/components/tabs/ConfigTab.tsx index 2250f3f1..ab229632 100644 --- a/canvas/src/components/tabs/ConfigTab.tsx +++ b/canvas/src/components/tabs/ConfigTab.tsx @@ -21,20 +21,39 @@ interface Props { // --- Agent Card Section --- function AgentCardSection({ workspaceId }: { workspaceId: string }) { - const [card, setCard] = useState | null>(null); - const [loading, setLoading] = useState(true); + // Initial card value comes from the canvas store — node.data.agentCard + // is hydrated by the platform stream when the workspace appears in the + // graph, so reading it here avoids a duplicate `GET /workspaces/${id}` + // (the parent ConfigTab.loadConfig already fetches workspace metadata, + // and refetching here adds a serialised RTT to the panel-open path — + // contributed to the ~20s detail-panel load reported in core#11). + // Local state still tracks the edited/saved value so the editor flow + // is unchanged. + const storeCard = useCanvasStore((s) => { + // Defensive against test mocks that omit `nodes` (some test files + // stub the store with a minimal shape). In production `nodes` is + // always an array — empty or not — so the optional chaining only + // matters for the test path. + const node = s.nodes?.find?.((n) => n.id === workspaceId); + return (node?.data.agentCard as + | Record + | null + | undefined) ?? null; + }); + const [card, setCard] = useState | null>(storeCard); const [editing, setEditing] = useState(false); const [draft, setDraft] = useState(""); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); + // If the store updates while this section is mounted (another tab + // pushed an update via the platform event stream), reflect that — + // unless the user is mid-edit, in which case we don't clobber their + // unsaved draft. useEffect(() => { - api.get>(`/workspaces/${workspaceId}`) - .then((ws) => setCard((ws.agent_card as Record) || null)) - .catch(() => {}) - .finally(() => setLoading(false)); - }, [workspaceId]); + if (!editing) setCard(storeCard); + }, [storeCard, editing]); const handleSave = async () => { setError(null); @@ -53,9 +72,7 @@ function AgentCardSection({ workspaceId }: { workspaceId: string }) { return (
- {loading ? ( -
Loading...
- ) : editing ? ( + {editing ? (