Initial commit: deerflow-server (frontend-web + offline-backend-20260512)

This commit is contained in:
吉鑫升 committed 2026-05-13 09:36:15 +08:00
commit e7a455f22e
560 files changed
+101331

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
"use client";
import { Client as LangGraphClient } from "@langchain/langgraph-sdk/client";
import { getAuthorizationHeaderValue } from "../auth";
import { getLangGraphBaseURL } from "../config";
import { sanitizeRunStreamOptions } from "./stream-mode";
function createCompatibleClient(isMock?: boolean): LangGraphClient {
const client = new LangGraphClient({
apiUrl: getLangGraphBaseURL(isMock),
onRequest(_url, init) {
const headers = new Headers(init.headers ?? {});
const authHeader = getAuthorizationHeaderValue();
if (authHeader && !headers.has("Authorization")) {
headers.set("Authorization", authHeader);
}
return {
...init,
headers,
};
},
});
const originalRunStream = client.runs.stream.bind(client.runs);
client.runs.stream = ((threadId, assistantId, payload) =>
originalRunStream(
threadId,
assistantId,
sanitizeRunStreamOptions(payload),
)) as typeof client.runs.stream;
const originalJoinStream = client.runs.joinStream.bind(client.runs);
client.runs.joinStream = ((threadId, runId, options) =>
originalJoinStream(
threadId,
runId,
sanitizeRunStreamOptions(options),
)) as typeof client.runs.joinStream;
return client;
}
const _clients = new Map<string, LangGraphClient>();
export function getAPIClient(isMock?: boolean): LangGraphClient {
const cacheKey = isMock ? "mock" : "default";
let client = _clients.get(cacheKey);
if (!client) {
client = createCompatibleClient(isMock);
_clients.set(cacheKey, client);
}
return client;
}
+18
View File
@@ -0,0 +1,18 @@
import { getAuthorizationHeaderValue } from "@/core/auth";
function withAuthHeaders(headers?: HeadersInit): Headers {
const next = new Headers(headers ?? {});
const authHeader = getAuthorizationHeaderValue();
if (authHeader && !next.has("Authorization")) {
next.set("Authorization", authHeader);
}
return next;
}
export function apiFetch(input: RequestInfo | URL, init?: RequestInit) {
return fetch(input, {
...init,
headers: withAuthHeaders(init?.headers),
});
}
+2
View File
@@ -0,0 +1,2 @@
export * from "./api-client";
export * from "./fetch-client";
+68
View File
@@ -0,0 +1,68 @@
const SUPPORTED_RUN_STREAM_MODES = new Set([
"values",
"messages",
"messages-tuple",
"updates",
"events",
"debug",
"tasks",
"checkpoints",
"custom",
] as const);
const warnedUnsupportedStreamModes = new Set<string>();
export function warnUnsupportedStreamModes(
modes: string[],
warn: (message: string) => void = console.warn,
) {
const unseenModes = modes.filter((mode) => {
if (warnedUnsupportedStreamModes.has(mode)) {
return false;
}
warnedUnsupportedStreamModes.add(mode);
return true;
});
if (unseenModes.length === 0) {
return;
}
warn(
`[deer-flow] Dropped unsupported LangGraph stream mode(s): ${unseenModes.join(", ")}`,
);
}
export function sanitizeRunStreamOptions<T>(options: T): T {
if (
typeof options !== "object" ||
options === null ||
!("streamMode" in options)
) {
return options;
}
const streamMode = options.streamMode;
if (streamMode == null) {
return options;
}
const requestedModes = Array.isArray(streamMode) ? streamMode : [streamMode];
const sanitizedModes = requestedModes.filter((mode) =>
SUPPORTED_RUN_STREAM_MODES.has(mode),
);
if (sanitizedModes.length === requestedModes.length) {
return options;
}
const droppedModes = requestedModes.filter(
(mode) => !SUPPORTED_RUN_STREAM_MODES.has(mode),
);
warnUnsupportedStreamModes(droppedModes);
return {
...options,
streamMode: Array.isArray(streamMode) ? sanitizedModes : sanitizedModes[0],
};
}