import { useState, useEffect, useCallback } from "react"; import type { InspectorClientProtocol } from "../mcp/inspectorClientProtocol.js"; import type { PagedRequestorTasksState, PagedRequestorTasksStateEventMap, LoadPageResult, } from "../mcp/state/pagedRequestorTasksState.js"; import type { Task } from "@modelcontextprotocol/client"; import type { TypedEventGeneric } from "../mcp/typedEventTarget.js"; export interface UsePagedRequestorTasksResult { tasks: Task[]; loadPage: (cursor?: string) => Promise; clear: () => void; nextCursor: string | undefined; } /** * React hook that subscribes to PagedRequestorTasksState and returns tasks, * loadPage, clear, and nextCursor. */ export function usePagedRequestorTasks( client: InspectorClientProtocol | null, pagedRequestorTasksState: PagedRequestorTasksState | null, ): UsePagedRequestorTasksResult { const [tasks, setTasks] = useState( pagedRequestorTasksState?.getTasks() ?? [], ); const [nextCursor, setNextCursor] = useState( pagedRequestorTasksState?.getNextCursor() ?? undefined, ); useEffect(() => { if (!pagedRequestorTasksState) { setTasks([]); setNextCursor(undefined); return; } setTasks(pagedRequestorTasksState.getTasks()); setNextCursor(pagedRequestorTasksState.getNextCursor() ?? undefined); const onTasksChange = ( event: TypedEventGeneric, ) => { setTasks(event.detail); setNextCursor(pagedRequestorTasksState.getNextCursor() ?? undefined); }; pagedRequestorTasksState.addEventListener("tasksChange", onTasksChange); return () => { pagedRequestorTasksState.removeEventListener( "tasksChange", onTasksChange, ); }; }, [pagedRequestorTasksState]); const loadPage = useCallback( async (cursor?: string): Promise => { if (!pagedRequestorTasksState || !client) { return { tasks: [], nextCursor: undefined }; } const result = await pagedRequestorTasksState.loadPage(cursor); setTasks(pagedRequestorTasksState.getTasks()); setNextCursor(pagedRequestorTasksState.getNextCursor() ?? undefined); return result; }, [client, pagedRequestorTasksState], ); const clear = useCallback(() => { pagedRequestorTasksState?.clear(); }, [pagedRequestorTasksState]); return { tasks, loadPage, clear, nextCursor }; }