From 1e767c06539cdec79f78a611e7be19bb7cd8b9cc Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 20:05:08 +0100 Subject: [PATCH 01/10] feat(sdk): add `bulk_update_state` in SDK --- libs/sdk-js/package.json | 2 +- libs/sdk-js/src/client.ts | 6 +- libs/sdk-py/langgraph_sdk/client.py | 134 ++++++++++++++++++++++------ libs/sdk-py/pyproject.toml | 2 +- 4 files changed, 113 insertions(+), 31 deletions(-) diff --git a/libs/sdk-js/package.json b/libs/sdk-js/package.json index 6c3d5a06c..6f1cd8d0b 100644 --- a/libs/sdk-js/package.json +++ b/libs/sdk-js/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/langgraph-sdk", - "version": "0.0.59", + "version": "0.0.60", "description": "Client library for interacting with the LangGraph API", "type": "module", "packageManager": "yarn@1.22.19", diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index 52051f1e8..c0ed9a8c9 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -641,6 +641,10 @@ export class ThreadsClient< /** * Create a new thread from a batch states. + * + * @param supersteps An array of supersteps. + * @param options Additional options. + * @returns The created thread. */ async bulkUpdateState( supersteps: Array<{ @@ -653,7 +657,7 @@ export class ThreadsClient< ifExists?: OnConflictBehavior; }, ): Promise> { - return this.fetch>("/threads/state/batch", { + return this.fetch>("/threads/state/bulk", { method: "POST", json: { supersteps: supersteps.map((s) => ({ diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index 6f4583b7f..8d96f7129 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -1142,6 +1142,55 @@ class ThreadsClient: payload["as_node"] = as_node return await self.http.post(f"/threads/{thread_id}/state", json=payload) + async def bulk_update_state( + self, + supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]], + *, + graph_id: Optional[str] = None, + thread_id: Optional[str] = None, + metadata: Optional[dict[str, Any]] = None, + if_exists: Optional[OnConflictBehavior] = None, + ) -> Thread: + """Create a new thread from a batch of states. + + Args: + supersteps: A sequence of supersteps, each containing a sequence of updates. + Each update has `values` or `command` and `as_node`. + graph_id: Optional graph ID to associate with the thread. + thread_id: Optional thread ID to use. If not provided, a new one will be generated. + metadata: Optional metadata to associate with the thread. + if_exists: Optional behavior when `thread_id` already exists. + + Returns: + The created thread. + """ + + payload: Dict[str, Any] = { + "supersteps": [ + { + "updates": [ + { + "values": u["values"], + "command": u.get("command"), + "as_node": u["as_node"], + } + for u in s["updates"] + ] + } + for s in supersteps + ], + } + if thread_id: + payload["thread_id"] = thread_id + if metadata or graph_id: + payload["metadata"] = { + **(metadata or {}), + **({"graph_id": graph_id} if graph_id else {}), + } + if if_exists: + payload["if_exists"] = if_exists + return await self.http.post("/threads/state/batch", json=payload) + async def get_history( self, thread_id: str, @@ -3294,38 +3343,18 @@ class SyncThreadsClient: checkpoint: Optional[Checkpoint] = None, checkpoint_id: Optional[str] = None, # deprecated ) -> ThreadUpdateStateResponse: - """Update the state of a thread. + """Add state to a thread. Args: - thread_id: The ID of the thread to update. - values: The values to update the state with. - as_node: Update the state as if this node had just executed. - checkpoint: The checkpoint to update the state of. + thread_id: The ID of the thread. + values: The values to add to the thread state. + as_node: The node to add the state as. + checkpoint: The checkpoint to add the state to. + checkpoint_id: The ID of the checkpoint to add the state to. Deprecated. Returns: - ThreadUpdateStateResponse: Response after updating a thread's state. - - Example Usage: - - response = client.threads.update_state( - thread_id="my_thread_id", - values={"messages":[{"role": "user", "content": "hello!"}]}, - as_node="my_node", - ) - print(response) - - ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - { - 'checkpoint': { - 'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2', - 'checkpoint_ns': '', - 'checkpoint_id': '1ef4a9b8-e6fb-67b1-8001-abd5184439d1', - 'checkpoint_map': {} - } - } - - """ # noqa: E501 + The response from the server. + """ payload: Dict[str, Any] = { "values": values, } @@ -3337,6 +3366,55 @@ class SyncThreadsClient: payload["as_node"] = as_node return self.http.post(f"/threads/{thread_id}/state", json=payload) + def bulk_update_state( + self, + supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]], + *, + graph_id: Optional[str] = None, + thread_id: Optional[str] = None, + metadata: Optional[dict[str, Any]] = None, + if_exists: Optional[OnConflictBehavior] = None, + ) -> Thread: + """Create a new thread from a batch of states. + + Args: + supersteps: A sequence of supersteps, each containing a sequence of updates. + Each update has `values` or `command` and `as_node`. + graph_id: Optional graph ID to associate with the thread. + thread_id: Optional thread ID to use. If not provided, a new one will be generated. + metadata: Optional metadata to associate with the thread. + if_exists: Optional behavior when `thread_id` already exists. + + Returns: + The created thread. + """ + + payload: Dict[str, Any] = { + "supersteps": [ + { + "updates": [ + { + "values": u["values"], + "command": u.get("command"), + "as_node": u["as_node"], + } + for u in s["updates"] + ] + } + for s in supersteps + ], + } + if thread_id: + payload["thread_id"] = thread_id + if metadata or graph_id: + payload["metadata"] = { + **(metadata or {}), + **({"graph_id": graph_id} if graph_id else {}), + } + if if_exists: + payload["if_exists"] = if_exists + return self.http.post("/threads/state/bulk", json=payload) + def get_history( self, thread_id: str, diff --git a/libs/sdk-py/pyproject.toml b/libs/sdk-py/pyproject.toml index 75e402fee..92e942441 100644 --- a/libs/sdk-py/pyproject.toml +++ b/libs/sdk-py/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langgraph-sdk" -version = "0.1.57" +version = "0.1.58" description = "SDK for interacting with LangGraph API" authors = [] license = "MIT" From a2d7631f476e5c52c49ad7d885ab9a96fd2bd0f9 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 20:10:42 +0100 Subject: [PATCH 02/10] Fix in async client --- libs/sdk-py/langgraph_sdk/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index 8d96f7129..f46525f1d 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -1189,7 +1189,7 @@ class ThreadsClient: } if if_exists: payload["if_exists"] = if_exists - return await self.http.post("/threads/state/batch", json=payload) + return await self.http.post("/threads/state/bulk", json=payload) async def get_history( self, From 972ab1a93520f6f444c3aa8ee1c9f2962aa7bdb6 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 20:22:05 +0100 Subject: [PATCH 03/10] Revert docstring for update_state --- libs/sdk-py/langgraph_sdk/client.py | 36 ++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index f46525f1d..f284711b7 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -3343,18 +3343,38 @@ class SyncThreadsClient: checkpoint: Optional[Checkpoint] = None, checkpoint_id: Optional[str] = None, # deprecated ) -> ThreadUpdateStateResponse: - """Add state to a thread. + """Update the state of a thread. Args: - thread_id: The ID of the thread. - values: The values to add to the thread state. - as_node: The node to add the state as. - checkpoint: The checkpoint to add the state to. - checkpoint_id: The ID of the checkpoint to add the state to. Deprecated. + thread_id: The ID of the thread to update. + values: The values to update the state with. + as_node: Update the state as if this node had just executed. + checkpoint: The checkpoint to update the state of. Returns: - The response from the server. - """ + ThreadUpdateStateResponse: Response after updating a thread's state. + + Example Usage: + + response = await client.threads.update_state( + thread_id="my_thread_id", + values={"messages":[{"role": "user", "content": "hello!"}]}, + as_node="my_node", + ) + print(response) + + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + { + 'checkpoint': { + 'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2', + 'checkpoint_ns': '', + 'checkpoint_id': '1ef4a9b8-e6fb-67b1-8001-abd5184439d1', + 'checkpoint_map': {} + } + } + + """ # noqa: E501 payload: Dict[str, Any] = { "values": values, } From e779c8e0b1aeb77630dfdb06c8d28bf419a6b528 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 20:42:48 +0100 Subject: [PATCH 04/10] Merge into `create` --- libs/sdk-py/langgraph_sdk/client.py | 162 ++++++++++------------------ 1 file changed, 59 insertions(+), 103 deletions(-) diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index f284711b7..4dcb6eee3 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -839,6 +839,8 @@ class ThreadsClient: metadata: Json = None, thread_id: Optional[str] = None, if_exists: Optional[OnConflictBehavior] = None, + from_supersteps: Optional[Sequence[dict[str, Sequence[dict[str, Any]]]]] = None, + graph_id: Optional[str] = None, ) -> Thread: """Create a new thread. @@ -848,13 +850,16 @@ class ThreadsClient: If None, ID will be a randomly generated UUID. if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood. Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread). + from_supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates. + Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments. + graph_id: Optional graph ID to associate with the thread. Returns: Thread: The created thread. Example Usage: - thread = await client.threads.create( + thread = client.threads.create( metadata={"number":1}, thread_id="my-thread-id", if_exists="raise" @@ -863,10 +868,32 @@ class ThreadsClient: payload: Dict[str, Any] = {} if thread_id: payload["thread_id"] = thread_id - if metadata: - payload["metadata"] = metadata + if metadata or graph_id: + payload["metadata"] = { + **(metadata or {}), + **({"graph_id": graph_id} if graph_id else {}), + } if if_exists: payload["if_exists"] = if_exists + if from_supersteps: + payload["supersteps"] = { + "supersteps": [ + { + "updates": [ + { + "values": u["values"], + "command": u.get("command"), + "as_node": u["as_node"], + } + for u in s["updates"] + ] + } + for s in from_supersteps + ], + } + + if payload.get("supersteps") is not None: + return self.http.post("/threads/state/bulk", json=payload) return await self.http.post("/threads", json=payload) async def update(self, thread_id: str, *, metadata: dict[str, Any]) -> Thread: @@ -1142,55 +1169,6 @@ class ThreadsClient: payload["as_node"] = as_node return await self.http.post(f"/threads/{thread_id}/state", json=payload) - async def bulk_update_state( - self, - supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]], - *, - graph_id: Optional[str] = None, - thread_id: Optional[str] = None, - metadata: Optional[dict[str, Any]] = None, - if_exists: Optional[OnConflictBehavior] = None, - ) -> Thread: - """Create a new thread from a batch of states. - - Args: - supersteps: A sequence of supersteps, each containing a sequence of updates. - Each update has `values` or `command` and `as_node`. - graph_id: Optional graph ID to associate with the thread. - thread_id: Optional thread ID to use. If not provided, a new one will be generated. - metadata: Optional metadata to associate with the thread. - if_exists: Optional behavior when `thread_id` already exists. - - Returns: - The created thread. - """ - - payload: Dict[str, Any] = { - "supersteps": [ - { - "updates": [ - { - "values": u["values"], - "command": u.get("command"), - "as_node": u["as_node"], - } - for u in s["updates"] - ] - } - for s in supersteps - ], - } - if thread_id: - payload["thread_id"] = thread_id - if metadata or graph_id: - payload["metadata"] = { - **(metadata or {}), - **({"graph_id": graph_id} if graph_id else {}), - } - if if_exists: - payload["if_exists"] = if_exists - return await self.http.post("/threads/state/bulk", json=payload) - async def get_history( self, thread_id: str, @@ -3085,6 +3063,8 @@ class SyncThreadsClient: metadata: Json = None, thread_id: Optional[str] = None, if_exists: Optional[OnConflictBehavior] = None, + from_supersteps: Optional[Sequence[dict[str, Sequence[dict[str, Any]]]]] = None, + graph_id: Optional[str] = None, ) -> Thread: """Create a new thread. @@ -3094,6 +3074,9 @@ class SyncThreadsClient: If None, ID will be a randomly generated UUID. if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood. Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread). + from_supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates. + Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments. + graph_id: Optional graph ID to associate with the thread. Returns: Thread: The created thread. @@ -3109,10 +3092,32 @@ class SyncThreadsClient: payload: Dict[str, Any] = {} if thread_id: payload["thread_id"] = thread_id - if metadata: - payload["metadata"] = metadata + if metadata or graph_id: + payload["metadata"] = { + **(metadata or {}), + **({"graph_id": graph_id} if graph_id else {}), + } if if_exists: payload["if_exists"] = if_exists + if from_supersteps: + payload["supersteps"] = { + "supersteps": [ + { + "updates": [ + { + "values": u["values"], + "command": u.get("command"), + "as_node": u["as_node"], + } + for u in s["updates"] + ] + } + for s in from_supersteps + ], + } + + if payload.get("supersteps") is not None: + return self.http.post("/threads/state/bulk", json=payload) return self.http.post("/threads", json=payload) def update(self, thread_id: str, *, metadata: dict[str, Any]) -> Thread: @@ -3386,55 +3391,6 @@ class SyncThreadsClient: payload["as_node"] = as_node return self.http.post(f"/threads/{thread_id}/state", json=payload) - def bulk_update_state( - self, - supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]], - *, - graph_id: Optional[str] = None, - thread_id: Optional[str] = None, - metadata: Optional[dict[str, Any]] = None, - if_exists: Optional[OnConflictBehavior] = None, - ) -> Thread: - """Create a new thread from a batch of states. - - Args: - supersteps: A sequence of supersteps, each containing a sequence of updates. - Each update has `values` or `command` and `as_node`. - graph_id: Optional graph ID to associate with the thread. - thread_id: Optional thread ID to use. If not provided, a new one will be generated. - metadata: Optional metadata to associate with the thread. - if_exists: Optional behavior when `thread_id` already exists. - - Returns: - The created thread. - """ - - payload: Dict[str, Any] = { - "supersteps": [ - { - "updates": [ - { - "values": u["values"], - "command": u.get("command"), - "as_node": u["as_node"], - } - for u in s["updates"] - ] - } - for s in supersteps - ], - } - if thread_id: - payload["thread_id"] = thread_id - if metadata or graph_id: - payload["metadata"] = { - **(metadata or {}), - **({"graph_id": graph_id} if graph_id else {}), - } - if if_exists: - payload["if_exists"] = if_exists - return self.http.post("/threads/state/bulk", json=payload) - def get_history( self, thread_id: str, From 0cb189347500167158397ed67fab437c51c5a900 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 20:46:22 +0100 Subject: [PATCH 05/10] Update for JS as well --- libs/sdk-js/src/client.ts | 92 +++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index c0ed9a8c9..433834229 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -482,17 +482,55 @@ export class ThreadsClient< * Metadata for the thread. */ metadata?: Metadata; + /** + * ID of the thread to create. + * + * If not provided, a random UUID will be generated. + */ threadId?: string; + /** + * How to handle dplicate creation. + * + * @default "raise" + */ ifExists?: OnConflictBehavior; + /** + * Graph ID to associate with the thread. + */ + graphId?: string; + /** + * Apply a list of supersteps when creating a thread, each containing a sequence of updates. + * + * Used for copying a thread between deployments. + */ + fromSupersteps?: Array<{ + updates: Array<{ values: unknown; command?: Command; asNode: string }>; + }>; }): Promise> { - return this.fetch>(`/threads`, { - method: "POST", - json: { - metadata: payload?.metadata, - thread_id: payload?.threadId, - if_exists: payload?.ifExists, - }, - }); + const json: Record = { + metadata: payload?.metadata, + thread_id: payload?.threadId, + if_exists: payload?.ifExists, + }; + + if (payload?.fromSupersteps) { + json.supersteps = { + supersteps: payload.fromSupersteps.map((s) => ({ + updates: s.updates.map((u) => ({ + values: u.values, + command: u.command, + as_node: u.asNode, + })), + })), + }; + + return this.fetch>(`/threads/state/bulk`, { + method: "POST", + json, + }); + } + + return this.fetch>(`/threads`, { method: "POST", json }); } /** @@ -639,44 +677,6 @@ export class ThreadsClient< ); } - /** - * Create a new thread from a batch states. - * - * @param supersteps An array of supersteps. - * @param options Additional options. - * @returns The created thread. - */ - async bulkUpdateState( - supersteps: Array<{ - updates: Array<{ values: unknown; command?: Command; asNode: string }>; - }>, - options?: { - graphId?: string; - threadId?: string; - metadata?: Metadata; - ifExists?: OnConflictBehavior; - }, - ): Promise> { - return this.fetch>("/threads/state/bulk", { - method: "POST", - json: { - supersteps: supersteps.map((s) => ({ - updates: s.updates.map((u) => ({ - values: u.values, - command: u.command, - as_node: u.asNode, - })), - })), - thread_id: options?.threadId, - metadata: { - ...options?.metadata, - graph_id: options?.graphId, - }, - if_exists: options?.ifExists, - }, - }); - } - /** * Patch the metadata of a thread. * From 1f7a380548360b22ebcf01f79e8371fd166ccedf Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 20:54:15 +0100 Subject: [PATCH 06/10] Fix typo --- libs/sdk-js/src/client.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index 433834229..1821ef322 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -514,15 +514,13 @@ export class ThreadsClient< }; if (payload?.fromSupersteps) { - json.supersteps = { - supersteps: payload.fromSupersteps.map((s) => ({ - updates: s.updates.map((u) => ({ - values: u.values, - command: u.command, - as_node: u.asNode, - })), + json.supersteps = payload.fromSupersteps.map((s) => ({ + updates: s.updates.map((u) => ({ + values: u.values, + command: u.command, + as_node: u.asNode, })), - }; + })); return this.fetch>(`/threads/state/bulk`, { method: "POST", From 442ef0788e1205cb5e30ab4f39ca34eb346e9978 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 21:05:43 +0100 Subject: [PATCH 07/10] Add graph_id back --- libs/sdk-js/src/client.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index 1821ef322..6c654350d 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -508,7 +508,10 @@ export class ThreadsClient< }>; }): Promise> { const json: Record = { - metadata: payload?.metadata, + metadata: { + ...payload?.metadata, + graph_id: payload?.graphId, + }, thread_id: payload?.threadId, if_exists: payload?.ifExists, }; From 1f0348a5ca522d63e589d2837b65cdc61673b86f Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 21:07:07 +0100 Subject: [PATCH 08/10] Fix docstring --- libs/sdk-py/langgraph_sdk/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index 4dcb6eee3..f51477acb 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -859,7 +859,7 @@ class ThreadsClient: Example Usage: - thread = client.threads.create( + thread = await client.threads.create( metadata={"number":1}, thread_id="my-thread-id", if_exists="raise" From 6dfed31a5e3f31164fe8e4a184679f5244c5dabb Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 21:39:35 +0100 Subject: [PATCH 09/10] Update parameters --- libs/sdk-js/src/client.ts | 43 ++++++++--------- libs/sdk-py/langgraph_sdk/client.py | 72 +++++++++++++---------------- 2 files changed, 50 insertions(+), 65 deletions(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index 6c654350d..f349a6587 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -503,35 +503,28 @@ export class ThreadsClient< * * Used for copying a thread between deployments. */ - fromSupersteps?: Array<{ + supersteps?: Array<{ updates: Array<{ values: unknown; command?: Command; asNode: string }>; }>; }): Promise> { - const json: Record = { - metadata: { - ...payload?.metadata, - graph_id: payload?.graphId, - }, - thread_id: payload?.threadId, - if_exists: payload?.ifExists, - }; - - if (payload?.fromSupersteps) { - json.supersteps = payload.fromSupersteps.map((s) => ({ - updates: s.updates.map((u) => ({ - values: u.values, - command: u.command, - as_node: u.asNode, + return this.fetch>(`/threads`, { + method: "POST", + json: { + metadata: { + ...payload?.metadata, + graph_id: payload?.graphId, + }, + thread_id: payload?.threadId, + if_exists: payload?.ifExists, + supersteps: payload?.supersteps?.map((s) => ({ + updates: s.updates.map((u) => ({ + values: u.values, + command: u.command, + as_node: u.asNode, + })), })), - })); - - return this.fetch>(`/threads/state/bulk`, { - method: "POST", - json, - }); - } - - return this.fetch>(`/threads`, { method: "POST", json }); + }, + }); } /** diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index f51477acb..4418e66de 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -839,7 +839,7 @@ class ThreadsClient: metadata: Json = None, thread_id: Optional[str] = None, if_exists: Optional[OnConflictBehavior] = None, - from_supersteps: Optional[Sequence[dict[str, Sequence[dict[str, Any]]]]] = None, + supersteps: Optional[Sequence[dict[str, Sequence[dict[str, Any]]]]] = None, graph_id: Optional[str] = None, ) -> Thread: """Create a new thread. @@ -850,7 +850,7 @@ class ThreadsClient: If None, ID will be a randomly generated UUID. if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood. Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread). - from_supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates. + supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates. Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments. graph_id: Optional graph ID to associate with the thread. @@ -875,25 +875,21 @@ class ThreadsClient: } if if_exists: payload["if_exists"] = if_exists - if from_supersteps: - payload["supersteps"] = { - "supersteps": [ - { - "updates": [ - { - "values": u["values"], - "command": u.get("command"), - "as_node": u["as_node"], - } - for u in s["updates"] - ] - } - for s in from_supersteps - ], - } + if supersteps: + payload["supersteps"] = [ + { + "updates": [ + { + "values": u["values"], + "command": u.get("command"), + "as_node": u["as_node"], + } + for u in s["updates"] + ] + } + for s in supersteps + ] - if payload.get("supersteps") is not None: - return self.http.post("/threads/state/bulk", json=payload) return await self.http.post("/threads", json=payload) async def update(self, thread_id: str, *, metadata: dict[str, Any]) -> Thread: @@ -3063,7 +3059,7 @@ class SyncThreadsClient: metadata: Json = None, thread_id: Optional[str] = None, if_exists: Optional[OnConflictBehavior] = None, - from_supersteps: Optional[Sequence[dict[str, Sequence[dict[str, Any]]]]] = None, + supersteps: Optional[Sequence[dict[str, Sequence[dict[str, Any]]]]] = None, graph_id: Optional[str] = None, ) -> Thread: """Create a new thread. @@ -3074,7 +3070,7 @@ class SyncThreadsClient: If None, ID will be a randomly generated UUID. if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood. Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread). - from_supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates. + supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates. Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments. graph_id: Optional graph ID to associate with the thread. @@ -3099,25 +3095,21 @@ class SyncThreadsClient: } if if_exists: payload["if_exists"] = if_exists - if from_supersteps: - payload["supersteps"] = { - "supersteps": [ - { - "updates": [ - { - "values": u["values"], - "command": u.get("command"), - "as_node": u["as_node"], - } - for u in s["updates"] - ] - } - for s in from_supersteps - ], - } + if supersteps: + payload["supersteps"] = [ + { + "updates": [ + { + "values": u["values"], + "command": u.get("command"), + "as_node": u["as_node"], + } + for u in s["updates"] + ] + } + for s in supersteps + ] - if payload.get("supersteps") is not None: - return self.http.post("/threads/state/bulk", json=payload) return self.http.post("/threads", json=payload) def update(self, thread_id: str, *, metadata: dict[str, Any]) -> Thread: From ef345aac5ffbddce9d5fe4d7cfe1d516bbf960d5 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 19 Mar 2025 22:02:55 +0100 Subject: [PATCH 10/10] Fix typo --- libs/sdk-js/src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index f349a6587..54acd5232 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -489,7 +489,7 @@ export class ThreadsClient< */ threadId?: string; /** - * How to handle dplicate creation. + * How to handle duplicate creation. * * @default "raise" */