mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-19 12:24:46 +08:00
fix: load all thread pages in thread lists (#1044)
* fix(frontend): load all thread pages in thread lists * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,27 +1,84 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
export function POST() {
|
type ThreadSearchRequest = {
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
sortBy?: "updated_at" | "created_at";
|
||||||
|
sortOrder?: "asc" | "desc";
|
||||||
|
};
|
||||||
|
|
||||||
|
type MockThreadSearchResult = Record<string, unknown> & {
|
||||||
|
thread_id: string;
|
||||||
|
updated_at: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function POST(request: Request) {
|
||||||
|
const body = ((await request.json().catch(() => ({}))) ?? {}) as ThreadSearchRequest;
|
||||||
|
|
||||||
|
const rawLimit = body.limit;
|
||||||
|
let limit = 50;
|
||||||
|
if (typeof rawLimit === "number") {
|
||||||
|
const normalizedLimit = Math.max(0, Math.floor(rawLimit));
|
||||||
|
if (!Number.isNaN(normalizedLimit)) {
|
||||||
|
limit = normalizedLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawOffset = body.offset;
|
||||||
|
let offset = 0;
|
||||||
|
if (typeof rawOffset === "number") {
|
||||||
|
const normalizedOffset = Math.max(0, Math.floor(rawOffset));
|
||||||
|
if (!Number.isNaN(normalizedOffset)) {
|
||||||
|
offset = normalizedOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sortBy = body.sortBy ?? "updated_at";
|
||||||
|
const sortOrder = body.sortOrder ?? "desc";
|
||||||
|
|
||||||
const threadsDir = fs.readdirSync(
|
const threadsDir = fs.readdirSync(
|
||||||
path.resolve(process.cwd(), "public/demo/threads"),
|
path.resolve(process.cwd(), "public/demo/threads"),
|
||||||
{
|
{
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const threadData = threadsDir
|
const threadData = threadsDir
|
||||||
.map((threadId) => {
|
.map<MockThreadSearchResult | null>((threadId) => {
|
||||||
if (threadId.isDirectory() && !threadId.name.startsWith(".")) {
|
if (threadId.isDirectory() && !threadId.name.startsWith(".")) {
|
||||||
const threadData = fs.readFileSync(
|
const threadData = JSON.parse(
|
||||||
path.resolve(`public/demo/threads/${threadId.name}/thread.json`),
|
fs.readFileSync(
|
||||||
"utf8",
|
path.resolve(`public/demo/threads/${threadId.name}/thread.json`),
|
||||||
);
|
"utf8",
|
||||||
|
),
|
||||||
|
) as Record<string, unknown>;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
...threadData,
|
||||||
thread_id: threadId.name,
|
thread_id: threadId.name,
|
||||||
values: JSON.parse(threadData).values,
|
updated_at:
|
||||||
|
typeof threadData.updated_at === "string"
|
||||||
|
? threadData.updated_at
|
||||||
|
: typeof threadData.created_at === "string"
|
||||||
|
? threadData.created_at
|
||||||
|
: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return false;
|
return null;
|
||||||
})
|
})
|
||||||
.filter(Boolean);
|
.filter((thread): thread is MockThreadSearchResult => thread !== null)
|
||||||
return Response.json(threadData);
|
.sort((a, b) => {
|
||||||
|
const aTimestamp = a[sortBy];
|
||||||
|
const bTimestamp = b[sortBy];
|
||||||
|
const aParsed =
|
||||||
|
typeof aTimestamp === "string" ? Date.parse(aTimestamp) : 0;
|
||||||
|
const bParsed =
|
||||||
|
typeof bTimestamp === "string" ? Date.parse(bTimestamp) : 0;
|
||||||
|
const aValue = Number.isNaN(aParsed) ? 0 : aParsed;
|
||||||
|
const bValue = Number.isNaN(bParsed) ? 0 : bParsed;
|
||||||
|
return sortOrder === "asc" ? aValue - bValue : bValue - aValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
const pagedThreads = threadData.slice(offset, offset + limit);
|
||||||
|
return Response.json(pagedThreads);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,8 +372,55 @@ export function useThreads(
|
|||||||
return useQuery<AgentThread[]>({
|
return useQuery<AgentThread[]>({
|
||||||
queryKey: ["threads", "search", params],
|
queryKey: ["threads", "search", params],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const response = await apiClient.threads.search<AgentThreadState>(params);
|
const maxResults = params.limit;
|
||||||
return response as AgentThread[];
|
const initialOffset = params.offset ?? 0;
|
||||||
|
const DEFAULT_PAGE_SIZE = 50;
|
||||||
|
|
||||||
|
// Preserve prior semantics: if a non-positive limit is explicitly provided,
|
||||||
|
// delegate to a single search call with the original parameters.
|
||||||
|
if (maxResults !== undefined && maxResults <= 0) {
|
||||||
|
const response = await apiClient.threads.search<AgentThreadState>(params);
|
||||||
|
return response as AgentThread[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageSize =
|
||||||
|
typeof maxResults === "number" && maxResults > 0
|
||||||
|
? Math.min(DEFAULT_PAGE_SIZE, maxResults)
|
||||||
|
: DEFAULT_PAGE_SIZE;
|
||||||
|
|
||||||
|
const threads: AgentThread[] = [];
|
||||||
|
let offset = initialOffset;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (typeof maxResults === "number" && threads.length >= maxResults) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentLimit =
|
||||||
|
typeof maxResults === "number"
|
||||||
|
? Math.min(pageSize, maxResults - threads.length)
|
||||||
|
: pageSize;
|
||||||
|
|
||||||
|
if (typeof maxResults === "number" && currentLimit <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = (await apiClient.threads.search<AgentThreadState>({
|
||||||
|
...params,
|
||||||
|
limit: currentLimit,
|
||||||
|
offset,
|
||||||
|
})) as AgentThread[];
|
||||||
|
|
||||||
|
threads.push(...response);
|
||||||
|
|
||||||
|
if (response.length < currentLimit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += response.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return threads;
|
||||||
},
|
},
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user