mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-03 06:12:14 +08:00
fix(uploads): persist thread uploads canonically and fail fast on upload errors (#943)
* fix(uploads): persist thread uploads canonically and fail fast on upload errors - write uploads to thread-scoped storage first to guarantee agent visibility - sync files to sandbox virtual path only for non-local sandboxes - fix markdown conversion flow to operate on canonical saved files and sync converted files when needed - prevent silent attachment upload failures in frontend submit flow (show error + abort submit) - add regression tests for local vs non-local upload behavior - update upload docs with thread-first persistence and troubleshooting notes * Update frontend/src/core/threads/hooks.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(uploads): reject "." and ".." filenames in upload sanitization (#944) * Initial plan * fix(uploads): reject '.' and '..' filenames in upload sanitization Co-authored-by: WillemJiang <219644+WillemJiang@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: WillemJiang <219644+WillemJiang@users.noreply.github.com> Co-authored-by: Willem Jiang <willem.jiang@gmail.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import type { ThreadsClient } from "@langchain/langgraph-sdk/client";
|
||||
import { useStream, type UseStream } from "@langchain/langgraph-sdk/react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useCallback } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import type { PromptInputMessage } from "@/components/ai-elements/prompt-input";
|
||||
|
||||
@@ -122,17 +123,31 @@ export function useSubmitThread({
|
||||
return null;
|
||||
});
|
||||
|
||||
const files = (await Promise.all(filePromises)).filter(
|
||||
const conversionResults = await Promise.all(filePromises);
|
||||
const files = conversionResults.filter(
|
||||
(file): file is File => file !== null,
|
||||
);
|
||||
const failedConversions = conversionResults.length - files.length;
|
||||
|
||||
if (files.length > 0 && threadId) {
|
||||
if (failedConversions > 0) {
|
||||
throw new Error(
|
||||
`Failed to prepare ${failedConversions} attachment(s) for upload. Please retry.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!threadId) {
|
||||
throw new Error("Thread is not ready for file upload.");
|
||||
}
|
||||
|
||||
if (files.length > 0) {
|
||||
await uploadFiles(threadId, files);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to upload files:", error);
|
||||
// Continue with message submission even if upload fails
|
||||
// You might want to show an error toast here
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : "Failed to upload files.";
|
||||
toast.error(errorMessage);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user