From 9b7cc1c82e49e63c910887a510695cf6acf34ea7 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Fri, 27 Jun 2025 19:51:49 +0200 Subject: [PATCH] fix(sdk-js): avoid stale client when fetching history --- libs/sdk-js/src/client.ts | 30 ++++++++++++++++++++++++++++++ libs/sdk-js/src/react/stream.tsx | 10 ++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index eb9a804f3..b2f1efc1d 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -1658,7 +1658,30 @@ export class Client< */ public "~ui": UiClient; + /** + * @internal Used to obtain a stable key representing the client. + */ + private "~configHash": string | undefined; + constructor(config?: ClientConfig) { + this["~configHash"] = (() => + JSON.stringify({ + apiUrl: config?.apiUrl, + apiKey: config?.apiKey, + timeoutMs: config?.timeoutMs, + defaultHeaders: config?.defaultHeaders, + + maxConcurrency: config?.callerOptions?.maxConcurrency, + maxRetries: config?.callerOptions?.maxRetries, + + callbacks: { + onFailedResponseHook: + config?.callerOptions?.onFailedResponseHook != null, + onRequest: config?.onRequest != null, + fetch: config?.callerOptions?.fetch != null, + }, + }))(); + this.assistants = new AssistantsClient(config); this.threads = new ThreadsClient(config); this.runs = new RunsClient(config); @@ -1667,3 +1690,10 @@ export class Client< this["~ui"] = new UiClient(config); } } + +/** + * @internal Used to obtain a stable key representing the client. + */ +export function getClientConfigHash(client: Client): string | undefined { + return client["~configHash"]; +} diff --git a/libs/sdk-js/src/react/stream.tsx b/libs/sdk-js/src/react/stream.tsx index 88a541f9a..5493fae2f 100644 --- a/libs/sdk-js/src/react/stream.tsx +++ b/libs/sdk-js/src/react/stream.tsx @@ -1,7 +1,7 @@ /* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */ "use client"; -import { Client, type ClientConfig } from "../client.js"; +import { Client, getClientConfigHash, type ClientConfig } from "../client.js"; import type { Command, DisconnectMode, @@ -321,11 +321,17 @@ function useThreadHistory>( ) { const [history, setHistory] = useState[]>([]); + const clientRef = useRef(client); + clientRef.current = client; + + const clientHash = getClientConfigHash(client); + const fetcher = useCallback( ( threadId: string | undefined | null, ): Promise[]> => { if (threadId != null) { + const client = clientRef.current; return fetchHistory(client, threadId).then((history) => { setHistory(history); return history; @@ -336,7 +342,7 @@ function useThreadHistory>( clearCallbackRef.current?.(); return Promise.resolve([]); }, - [], + [clientHash], ); useEffect(() => {