History

rm pagination

Rhys Sullivan committed 8 months ago

Commit 8b105e81 parent f0963694 files · +23 −155Browse files

Unified · Split

4 files
  1. executor/apps/web/src/hooks/use/workspace-tools.ts +19 −155
  2. executor/packages/database/convex/_generated/api.d.ts +1 −0
  3. executor/packages/database/convex/executorNode.ts +2 −0
  4. executor/packages/database/src/runtime/workspace_tools.ts +1 −0
executor/apps/web/src/hooks/use/workspace-tools.ts+19−155
@@ -1,7 +1,7 @@
11 "use client";
22
3−import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4−import { useInfiniteQuery, type InfiniteData } from "@tanstack/react-query";
3+import { useCallback, useEffect, useRef } from "react";
4+import { useQuery } from "@tanstack/react-query";
55 import { useAction, useQuery as useConvexQuery } from "convex/react";
66 import { convexApi } from "@/lib/convex-api";
77 import type { OpenApiSourceQuality, SourceAuthProfile, ToolDescriptor } from "@/lib/types";
@@ -55,22 +55,9 @@ type ListToolsWithWarningsAction = (args: { · 47 unmodified lines
5555 cursor?: string;
5656 limit?: number;
5757 buildId?: string;
58+ fetchAll?: boolean;
5859 }) => Promise<WorkspaceToolsQueryResult>;
5960
60−interface ToolInventoryPageParam {
61− cursor?: string;
62− buildId?: string;
63−}
64−
65−interface SourceToolPageState {
66− tools: ToolDescriptor[];
67− nextCursor?: string | null;
68− buildId?: string;
69− loading: boolean;
70−}
71−
72−const DEFAULT_PAGE_SIZE = 250;
73−
7461 /**
7562 * Fetches tool metadata from a Convex action, cached by TanStack Query.
7663 *
@@ -85,7 +72,6 @@ export function useWorkspaceTools( · 8 unmodified lines
8572 const listToolsWithWarningsRaw = useAction(convexApi.executorNode.listToolsWithWarnings);
8673 const listToolsWithWarnings = listToolsWithWarningsRaw as ListToolsWithWarningsAction;
8774 const detailsCacheRef = useRef<Map<string, ToolDescriptor>>(new Map());
88− const [sourcePages, setSourcePages] = useState<Record<string, SourceToolPageState>>({});
8975
9076 // Watch tool sources reactively so we invalidate when sources change
9177 const toolSources = useConvexQuery(
@@ -93,7 +79,7 @@ export function useWorkspaceTools( · 1 unmodified line
9379 context ? { workspaceId: context.workspaceId, sessionId: context.sessionId } : "skip",
9480 );
9581
96− const inventoryQuery = useInfiniteQuery<WorkspaceToolsQueryResult, Error, InfiniteData<WorkspaceToolsQueryResult>, unknown[], ToolInventoryPageParam>({
82+ const inventoryQuery = useQuery<WorkspaceToolsQueryResult, Error>({
9783 queryKey: [
9884 "workspace-tools-inventory",
9985 context?.workspaceId,
@@ -102,7 +88,7 @@ export function useWorkspaceTools( · 2 unmodified lines
10288 includeDetails,
10389 toolSources,
10490 ],
105− queryFn: async ({ pageParam }): Promise<WorkspaceToolsQueryResult> => {
91+ queryFn: async (): Promise<WorkspaceToolsQueryResult> => {
10692 if (!context) {
10793 return {
10894 tools: [],
@@ -127,27 +113,12 @@ export function useWorkspaceTools( · 18 unmodified lines
127113 ...(context.clientId && { clientId: context.clientId }),
128114 ...(context.sessionId && { sessionId: context.sessionId }),
129115 includeDetails,
130− limit: DEFAULT_PAGE_SIZE,
131− ...(pageParam?.cursor ? { cursor: pageParam.cursor } : {}),
132− ...(pageParam?.buildId ? { buildId: pageParam.buildId } : {}),
116+ fetchAll: true,
133117 });
134118 },
135− initialPageParam: {},
136− getNextPageParam: (lastPage) => {
137− const nextCursor = lastPage.nextCursor;
138− if (!nextCursor) {
139− return undefined;
140− }
141− return {
142− cursor: nextCursor,
143− buildId: lastPage.inventoryStatus.readyBuildId,
144− };
145− },
146119 enabled: !!context,
147120 refetchInterval: (query) => {
148− const data = query.state.data as InfiniteData<WorkspaceToolsQueryResult> | undefined;
149− const first = data?.pages[0];
150− const state = first?.inventoryStatus.state;
121+ const state = query.state.data?.inventoryStatus.state;
151122 if (state === "initializing" || state === "rebuilding") {
152123 return 2_000;
153124 }
@@ -156,106 +127,8 @@ export function useWorkspaceTools( · 2 unmodified lines
156127 placeholderData: (previousData) => previousData,
157128 });
158129
159− const pages = inventoryQuery.data?.pages ?? [];
160− const inventoryData = pages[0];
161− const tools = useMemo(() => {
162− const merged = new Map<string, ToolDescriptor>();
163− for (const page of pages) {
164− for (const tool of page.tools) {
165− merged.set(tool.path, tool);
166− }
167− }
168− for (const sourcePage of Object.values(sourcePages)) {
169− for (const tool of sourcePage.tools) {
170− merged.set(tool.path, tool);
171− }
172− }
173− return [...merged.values()];
174− }, [pages, sourcePages]);
175−
176− const loadMoreToolsForSource = useCallback(async (
177− source: { source: string; sourceName: string },
178− ): Promise<void> => {
179− if (!context) {
180− return;
181− }
182−
183− const current = sourcePages[source.sourceName];
184− if (current?.loading || current?.nextCursor === null) {
185− return;
186− }
187−
188− setSourcePages((prev) => ({
189− ...prev,
190− [source.sourceName]: {
191− tools: prev[source.sourceName]?.tools ?? [],
192− nextCursor: prev[source.sourceName]?.nextCursor,
193− buildId: prev[source.sourceName]?.buildId,
194− loading: true,
195− },
196− }));
197−
198− try {
199− const response = await listToolsWithWarnings({
200− workspaceId: context.workspaceId,
201− ...(context.accountId && { accountId: context.accountId }),
202− ...(context.clientId && { clientId: context.clientId }),
203− ...(context.sessionId && { sessionId: context.sessionId }),
204− includeDetails,
205− source: source.source,
206− sourceName: source.sourceName,
207− limit: DEFAULT_PAGE_SIZE,
208− ...(current?.nextCursor ? { cursor: current.nextCursor } : {}),
209− ...(current?.buildId ? { buildId: current.buildId } : {}),
210− });
211−
212− setSourcePages((prev) => {
213− const existingTools = prev[source.sourceName]?.tools ?? [];
214− const merged = new Map<string, ToolDescriptor>();
215− for (const tool of existingTools) {
216− merged.set(tool.path, tool);
217− }
218− for (const tool of response.tools) {
219− merged.set(tool.path, tool);
220− }
221− return {
222− ...prev,
223− [source.sourceName]: {
224− tools: [...merged.values()],
225− nextCursor: response.nextCursor ?? null,
226− buildId: response.inventoryStatus.readyBuildId,
227− loading: false,
228− },
229− };
230− });
231− } catch {
232− setSourcePages((prev) => ({
233− ...prev,
234− [source.sourceName]: {
235− tools: prev[source.sourceName]?.tools ?? [],
236− nextCursor: prev[source.sourceName]?.nextCursor ?? null,
237− buildId: prev[source.sourceName]?.buildId,
238− loading: false,
239− },
240− }));
241− }
242− }, [context, includeDetails, listToolsWithWarnings, sourcePages]);
243−
244− const sourceLoadingMoreTools = useMemo(() => {
245− const result: Record<string, boolean> = {};
246− for (const [sourceName, state] of Object.entries(sourcePages)) {
247− result[sourceName] = state.loading;
248− }
249− return result;
250− }, [sourcePages]);
251−
252− const sourceHasMoreTools = useMemo(() => {
253− const result: Record<string, boolean> = {};
254− for (const [sourceName, state] of Object.entries(sourcePages)) {
255− result[sourceName] = state.nextCursor !== null;
256− }
257− return result;
258− }, [sourcePages]);
130+ const inventoryData = inventoryQuery.data;
131+ const tools = inventoryData?.tools ?? [];
259132
260133 const loadToolDetails = useCallback(async (toolPaths: string[]): Promise<Record<string, ToolDescriptor>> => {
261134 const requested = [...new Set(toolPaths.filter((path) => path.length > 0))];
@@ -299,16 +172,6 @@ export function useWorkspaceTools( · 37 unmodified lines
299172 detailsCacheRef.current.clear();
300173 }, [context?.workspaceId, context?.accountId, context?.clientId, context?.sessionId]);
301174
302− useEffect(() => {
303− setSourcePages({});
304− }, [
305− context?.workspaceId,
306− context?.accountId,
307− context?.clientId,
308− context?.sessionId,
309− inventoryData?.inventoryStatus.readyBuildId,
310− ]);
311−
312175 useEffect(() => {
313176 if (!inventoryData || !includeDetails) {
314177 return;
@@ -320,11 +183,12 @@ export function useWorkspaceTools( · 5 unmodified lines
320183 }, [inventoryData, includeDetails]);
321184
322185 const loadMoreTools = useCallback(async () => {
323− if (!inventoryQuery.hasNextPage || inventoryQuery.isFetchingNextPage) {
324− return;
325− }
326− await inventoryQuery.fetchNextPage();
327− }, [inventoryQuery]);
186+ return;
187+ }, []);
188+
189+ const loadMoreToolsForSource = useCallback(async () => {
190+ return;
191+ }, []);
328192
329193 return {
330194 tools,
@@ -338,11 +202,11 @@ export function useWorkspaceTools( · 7 unmodified lines
338202 loadingSources: inventoryData?.inventoryStatus.loadingSourceNames ?? [],
339203 loadingTools: !!context && inventoryQuery.isLoading,
340204 refreshingTools: !!context && inventoryQuery.isFetching,
341− loadingMoreTools: inventoryQuery.isFetchingNextPage,
342− hasMoreTools: Boolean(inventoryQuery.hasNextPage),
205+ loadingMoreTools: false,
206+ hasMoreTools: false,
343207 loadMoreTools,
344− sourceHasMoreTools,
345− sourceLoadingMoreTools,
208+ sourceHasMoreTools: {} as Record<string, boolean>,
209+ sourceLoadingMoreTools: {} as Record<string, boolean>,
346210 loadMoreToolsForSource,
347211 totalTools: inventoryData?.totalTools ?? tools.length,
348212 loadedTools: tools.length,
executor/packages/database/convex/_generated/api.d.ts+1−0
@@ -138,6 +138,7 @@ export declare const api: { · 137 unmodified lines
138138 buildId?: string;
139139 clientId?: string;
140140 cursor?: string;
141+ fetchAll?: boolean;
141142 includeDetails?: boolean;
142143 includeSourceMeta?: boolean;
143144 limit?: number;
executor/packages/database/convex/executorNode.ts+2−0
@@ -36,6 +36,7 @@ export const listToolsWithWarnings = customAction({ · 35 unmodified lines
3636 cursor: v.optional(v.string()),
3737 limit: v.optional(v.number()),
3838 buildId: v.optional(v.string()),
39+ fetchAll: v.optional(v.boolean()),
3940 },
4041 handler: async (
4142 ctx,
@@ -69,6 +70,7 @@ export const listToolsWithWarnings = customAction({ · 27 unmodified lines
6970 cursor: args.cursor,
7071 limit: args.limit,
7172 buildId: args.buildId,
73+ fetchAll: args.fetchAll,
7274 });
7375
7476 return inventory;
executor/packages/database/src/runtime/workspace_tools.ts+1−0
@@ -1279,6 +1279,7 @@ export async function listToolsWithWarningsForContext( · 1278 unmodified lines
12791279 cursor?: string;
12801280 limit?: number;
12811281 buildId?: string;
1282+ fetchAll?: boolean;
12821283 } = {},
12831284 ): Promise<{
12841285 tools: ToolDescriptor[];