Make event listeners a callback

This commit is contained in:
Tat Dat Duong
2025-02-12 09:11:44 -08:00
parent 77a3cffa7f
commit b6aff521e5
2 changed files with 33 additions and 49 deletions
+1 -1
View File
@@ -68,7 +68,7 @@ export function getApiKey(apiKey?: string): string | undefined {
return undefined;
}
interface ClientConfig {
export interface ClientConfig {
apiUrl?: string;
apiKey?: string;
callerOptions?: AsyncCallerParams;
+32 -48
View File
@@ -1,7 +1,7 @@
/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */
"use client";
import { Client, ClientConfig } from "../client.js";
import { Client, type ClientConfig } from "../client.js";
import type {
Command,
DisconnectMode,
@@ -188,15 +188,16 @@ export function useStream<
apiUrl: ClientConfig["apiUrl"];
apiKey?: ClientConfig["apiKey"];
callerOptions?: ClientConfig["callerOptions"];
timeoutMs?: ClientConfig["timeoutMs"];
defaultHeaders?: ClientConfig["defaultHeaders"];
withMessages?: string;
onError?: (error: unknown) => void;
onFinish?: (state: ThreadState<StateType>) => void;
onUpdateEvent?: (data: UpdatesStreamEvent<UpdateType>["data"]) => void;
onCustomEvent?: (data: CustomStreamEvent<CustomType>["data"]) => void;
onMetadataEvent?: (data: MetadataStreamEvent["data"]) => void;
// TODO: can we make threadId uncontrollable / controllable?
threadId?: string | null;
onThreadId?: (threadId: string) => void;
@@ -214,26 +215,14 @@ export function useStream<
| FeedbackStreamEvent;
const { assistantId, threadId, withMessages, onError, onFinish } = options;
const [client] = useState<Client>(
() =>
new Client({
apiUrl: options.apiUrl,
apiKey: options.apiKey,
callerOptions: options.callerOptions,
timeoutMs: options.timeoutMs,
defaultHeaders: options.defaultHeaders,
}),
const client = useMemo(
() => new Client({ apiUrl: options.apiUrl, apiKey: options.apiKey }),
[options.apiKey, options.apiUrl],
);
if (client == null) {
throw new Error(
"LangGraph SDK not provided. Either pass a client to `useStream` or wrap your app in a `LangGraphConfig` provider and pass the client there.",
);
}
const [branchPath, setBranchPath] = useState<string[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [events, setEvents] = useState<EventStreamEvent[]>([]);
const [_, setEvents] = useState<EventStreamEvent[]>([]);
const [streamError, setStreamError] = useState<unknown>(undefined);
const [streamValues, setStreamValues] = useState<StateType | null>(null);
@@ -254,6 +243,16 @@ export function useStream<
[],
);
const hasUpdateListener = options.onUpdateEvent != null;
const hasCustomListener = options.onCustomEvent != null;
const callbackStreamMode = useMemo(() => {
const modes: Exclude<StreamMode, "debug" | "messages">[] = [];
if (hasUpdateListener) modes.push("updates");
if (hasCustomListener) modes.push("custom");
return modes;
}, [hasUpdateListener, hasCustomListener]);
const clearCallbackRef = useRef<() => void>(null!);
clearCallbackRef.current = () => {
setStreamError(undefined);
@@ -480,6 +479,7 @@ export function useStream<
const streamMode = unique([
...(submitOptions?.streamMode ?? []),
...trackStreamModeRef.current,
...callbackStreamMode,
]);
const checkpoint =
@@ -499,8 +499,6 @@ export function useStream<
onCompletion: submitOptions?.onCompletion,
onDisconnect: submitOptions?.onDisconnect ?? "cancel",
// TODO: check if integration on FE would work nice
feedbackKeys: submitOptions?.feedbackKeys,
signal: abortRef.current.signal,
checkpoint,
@@ -539,6 +537,18 @@ export function useStream<
break;
}
if (event === "updates") {
options.onUpdateEvent?.(data);
}
if (event === "custom") {
options.onCustomEvent?.(data);
}
if (event === "metadata") {
options.onMetadataEvent?.(data);
}
if (event === "values") {
setStreamValues(data);
}
@@ -604,30 +614,6 @@ export function useStream<
const error = isLoading ? streamError : historyError;
const values = streamValues ?? historyValues;
const stream = {
get custom() {
trackStreamMode("custom");
return events
.filter((item) => item.event === "custom")
.map(({ data }) => data as CustomType);
},
get events() {
trackStreamMode("events");
return events;
},
get updates() {
trackStreamMode("updates");
return events
.filter(
(item): item is UpdatesStreamEvent<UpdateType> =>
item.event === "updates",
)
.map(({ data }) => data);
},
};
const setBranch = useCallback(
(path: string) => setBranchPath(path.split(">")),
@@ -647,8 +633,6 @@ export function useStream<
submit,
setBranch,
stream,
get messages() {
trackStreamMode("messages-tuple");