mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-05-01 22:38:23 +00:00
* Refactor API fetch calls to use a unified fetch function; enhance chat history loading with new hooks and UI components - Replaced `fetchWithAuth` with a generic `fetch` function across various API modules for consistency. - Updated `useThreadStream` and `useThreadHistory` hooks to manage chat history loading, including loading states and pagination. - Introduced `LoadMoreHistoryIndicator` component for better user experience when loading more chat history. - Enhanced message handling in `MessageList` to accommodate new loading states and history management. - Added support for run messages in the thread context, improving the overall message handling logic. - Updated translations for loading indicators in English and Chinese. * Fix test assertions for run ordering in RunManager tests - Updated assertions in `test_list_by_thread` to reflect correct ordering of runs. - Modified `test_list_by_thread_is_stable_when_timestamps_tie` to ensure stable ordering when timestamps are tied.
150 lines
3.8 KiB
TypeScript
150 lines
3.8 KiB
TypeScript
import { fetch } from "../api/fetcher";
|
|
import { getBackendBaseURL } from "../config";
|
|
|
|
import type {
|
|
MemoryFactInput,
|
|
MemoryFactPatchInput,
|
|
UserMemory,
|
|
} from "./types";
|
|
|
|
async function readMemoryResponse(
|
|
response: Response,
|
|
fallbackMessage: string,
|
|
): Promise<UserMemory> {
|
|
function formatErrorDetail(detail: unknown): string | null {
|
|
if (typeof detail === "string") {
|
|
return detail;
|
|
}
|
|
|
|
if (Array.isArray(detail)) {
|
|
const parts = detail
|
|
.map((item) => {
|
|
if (typeof item === "string") {
|
|
return item;
|
|
}
|
|
|
|
if (item && typeof item === "object") {
|
|
const record = item as Record<string, unknown>;
|
|
if (typeof record.msg === "string") {
|
|
return record.msg;
|
|
}
|
|
|
|
try {
|
|
return JSON.stringify(record);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return String(item);
|
|
})
|
|
.filter(Boolean);
|
|
|
|
return parts.length > 0 ? parts.join("; ") : null;
|
|
}
|
|
|
|
if (detail && typeof detail === "object") {
|
|
try {
|
|
return JSON.stringify(detail);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (
|
|
typeof detail === "string" ||
|
|
typeof detail === "number" ||
|
|
typeof detail === "boolean" ||
|
|
typeof detail === "bigint"
|
|
) {
|
|
return String(detail);
|
|
}
|
|
|
|
if (typeof detail === "symbol") {
|
|
return detail.description ?? null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
if (!response.ok) {
|
|
const errorData = (await response.json().catch(() => ({}))) as {
|
|
detail?: unknown;
|
|
};
|
|
const detailMessage = formatErrorDetail(errorData.detail);
|
|
throw new Error(
|
|
detailMessage ?? `${fallbackMessage}: ${response.statusText}`,
|
|
);
|
|
}
|
|
|
|
return response.json() as Promise<UserMemory>;
|
|
}
|
|
|
|
export async function loadMemory(): Promise<UserMemory> {
|
|
const response = await fetch(`${getBackendBaseURL()}/api/memory`);
|
|
return readMemoryResponse(response, "Failed to fetch memory");
|
|
}
|
|
|
|
export async function clearMemory(): Promise<UserMemory> {
|
|
const response = await fetch(`${getBackendBaseURL()}/api/memory`, {
|
|
method: "DELETE",
|
|
});
|
|
return readMemoryResponse(response, "Failed to clear memory");
|
|
}
|
|
|
|
export async function deleteMemoryFact(factId: string): Promise<UserMemory> {
|
|
const response = await fetch(
|
|
`${getBackendBaseURL()}/api/memory/facts/${encodeURIComponent(factId)}`,
|
|
{
|
|
method: "DELETE",
|
|
},
|
|
);
|
|
return readMemoryResponse(response, "Failed to delete memory fact");
|
|
}
|
|
|
|
export async function exportMemory(): Promise<UserMemory> {
|
|
const response = await fetch(`${getBackendBaseURL()}/api/memory/export`);
|
|
return readMemoryResponse(response, "Failed to export memory");
|
|
}
|
|
|
|
export async function importMemory(memory: UserMemory): Promise<UserMemory> {
|
|
const response = await fetch(`${getBackendBaseURL()}/api/memory/import`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(memory),
|
|
});
|
|
return readMemoryResponse(response, "Failed to import memory");
|
|
}
|
|
|
|
export async function createMemoryFact(
|
|
input: MemoryFactInput,
|
|
): Promise<UserMemory> {
|
|
const response = await fetch(`${getBackendBaseURL()}/api/memory/facts`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(input),
|
|
});
|
|
return readMemoryResponse(response, "Failed to create memory fact");
|
|
}
|
|
|
|
export async function updateMemoryFact(
|
|
factId: string,
|
|
input: MemoryFactPatchInput,
|
|
): Promise<UserMemory> {
|
|
const response = await fetch(
|
|
`${getBackendBaseURL()}/api/memory/facts/${encodeURIComponent(factId)}`,
|
|
{
|
|
method: "PATCH",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(input),
|
|
},
|
|
);
|
|
return readMemoryResponse(response, "Failed to update memory fact");
|
|
}
|