From 51be5b6ac3e52a4ad0f3707bcf8e62c5d2c87154 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Fri, 27 Sep 2024 13:24:46 +0200 Subject: [PATCH 1/5] feat(sdk-js): add support for subgraphs, match schema --- libs/sdk-js/src/client.ts | 65 ++++++++++++++++++++++++++++++++++----- libs/sdk-js/src/schema.ts | 2 ++ libs/sdk-js/src/types.ts | 5 +++ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index be3c2c991..bc3a22e0d 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -10,6 +10,8 @@ import { ThreadState, Cron, AssistantVersion, + Subgraphs, + Checkpoint, } from "./schema.js"; import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js"; import { @@ -234,6 +236,31 @@ export class AssistantsClient extends BaseClient { return this.fetch(`/assistants/${assistantId}/schemas`); } + /** + * Get the schemas of an assistant by ID. + * + * @param assistantId The ID of the assistant to get the schema of. + * @param options Additional options for getting subgraphs, such as namespace or recursion extraction. + * @returns The subgraphs of the assistant. + */ + async getSubgraphs( + assistantId: string, + options?: { + namespace?: string; + recurse?: boolean; + }, + ): Promise { + if (options?.namespace) { + return this.fetch( + `/assistants/${assistantId}/subgraphs/${options.namespace}`, + { params: { recurse: options?.recurse } }, + ); + } + return this.fetch(`/assistants/${assistantId}/subgraphs`, { + params: { recurse: options?.recurse }, + }); + } + /** * Create a new assistant. * @param payload Payload for creating an assistant. @@ -479,13 +506,30 @@ export class ThreadsClient extends BaseClient { */ async getState( threadId: string, - checkpointId?: string, + checkpoint?: Checkpoint | string, + options?: { subgraphs?: boolean }, ): Promise> { - return this.fetch>( - checkpointId != null - ? `/threads/${threadId}/state/${checkpointId}` - : `/threads/${threadId}/state`, - ); + if (checkpoint != null) { + if (typeof checkpoint !== "string") { + return this.fetch>( + `/threads/${threadId}/state/checkpoint`, + { + method: "POST", + json: { checkpoint, subgraphs: options?.subgraphs }, + }, + ); + } + + // deprecated + return this.fetch>( + `/threads/${threadId}/state/${checkpoint}`, + { params: { subgraphs: options?.subgraphs } }, + ); + } + + return this.fetch>(`/threads/${threadId}/state`, { + params: { subgraphs: options?.subgraphs }, + }); } /** @@ -496,7 +540,12 @@ export class ThreadsClient extends BaseClient { */ async updateState( threadId: string, - options: { values: ValuesType; checkpointId?: string; asNode?: string }, + options: { + values: ValuesType; + checkpoint?: Checkpoint; + checkpointId?: string; + asNode?: string; + }, ): Promise> { return this.fetch>( `/threads/${threadId}/state`, @@ -505,6 +554,7 @@ export class ThreadsClient extends BaseClient { json: { values: options.values, checkpoint_id: options.checkpointId, + checkpoint: options.checkpoint, as_node: options?.asNode, }, }, @@ -608,6 +658,7 @@ export class RunsClient extends BaseClient { config: payload?.config, metadata: payload?.metadata, stream_mode: payload?.streamMode, + stream_subgraphs: payload?.streamSubgraphs, feedback_keys: payload?.feedbackKeys, assistant_id: assistantId, interrupt_before: payload?.interruptBefore, diff --git a/libs/sdk-js/src/schema.ts b/libs/sdk-js/src/schema.ts index b016cea9b..aa398df3c 100644 --- a/libs/sdk-js/src/schema.ts +++ b/libs/sdk-js/src/schema.ts @@ -75,6 +75,8 @@ export interface GraphSchema { config_schema?: JSONSchema7; } +export type Subgraphs = Record; + export type Metadata = Optional>; export interface AssistantBase { diff --git a/libs/sdk-js/src/types.ts b/libs/sdk-js/src/types.ts index 2a5d6c4f1..b044d57bd 100644 --- a/libs/sdk-js/src/types.ts +++ b/libs/sdk-js/src/types.ts @@ -98,6 +98,11 @@ export interface RunsStreamPayload extends RunsInvokePayload { */ streamMode?: StreamMode | Array; + /** + * Stream output from subgraphs. By default, streams only the top graph. + */ + streamSubgraphs?: boolean; + /** * Pass one or more feedbackKeys if you want to request short-lived signed URLs * for submitting feedback to LangSmith with this key for this run. From f1c6e13e960fa7907cddf7047f865384f54dd523 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Fri, 27 Sep 2024 13:26:58 +0200 Subject: [PATCH 2/5] Ignore tgz and tar files --- libs/sdk-js/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/sdk-js/.gitignore b/libs/sdk-js/.gitignore index 4b85d8c2a..af019c1c6 100644 --- a/libs/sdk-js/.gitignore +++ b/libs/sdk-js/.gitignore @@ -1,4 +1,6 @@ /docs +/*.tgz +/*.tar ## GENERATED create-entrypoints.js /client.cjs /client.js From e4a4889b6d2190a4320ffb02daee4832152fd344 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Fri, 27 Sep 2024 13:30:47 +0200 Subject: [PATCH 3/5] Add .prettierrc file to make vscode prettier work --- libs/sdk-js/.prettierrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 libs/sdk-js/.prettierrc diff --git a/libs/sdk-js/.prettierrc b/libs/sdk-js/.prettierrc new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/libs/sdk-js/.prettierrc @@ -0,0 +1 @@ +{} From be44d0cfb6a1745281e0cbaab6ccb1cc2294e27e Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Fri, 27 Sep 2024 15:15:56 +0200 Subject: [PATCH 4/5] feat(sdk): expose xray kwarg to get_graph/getGraph --- libs/sdk-js/src/client.ts | 9 +++++++-- libs/sdk-py/langgraph_sdk/client.py | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts index bc3a22e0d..b2cddc8a3 100644 --- a/libs/sdk-js/src/client.ts +++ b/libs/sdk-js/src/client.ts @@ -223,8 +223,13 @@ export class AssistantsClient extends BaseClient { * @param assistantId The ID of the assistant. * @returns Serialized graph */ - async getGraph(assistantId: string): Promise { - return this.fetch(`/assistants/${assistantId}/graph`); + async getGraph( + assistantId: string, + options?: { xray?: boolean }, + ): Promise { + return this.fetch(`/assistants/${assistantId}/graph`, { + params: { xray: options?.xray }, + }); } /** diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index 9125f8bb1..9adb40aed 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -304,11 +304,14 @@ class AssistantsClient: """ # noqa: E501 return await self.http.get(f"/assistants/{assistant_id}") - async def get_graph(self, assistant_id: str) -> dict[str, list[dict[str, Any]]]: + async def get_graph( + self, assistant_id: str, *, xray: bool = False + ) -> dict[str, list[dict[str, Any]]]: """Get the graph of an assistant by ID. Args: assistant_id: The ID of the assistant to get the graph of. + xray: Include graph representation of subgraphs. Returns: Graph: The graph information for the assistant in JSON format. @@ -338,7 +341,9 @@ class AssistantsClient: """ # noqa: E501 - return await self.http.get(f"/assistants/{assistant_id}/graph") + return await self.http.get( + f"/assistants/{assistant_id}/graph", params={"xray": xray} + ) async def get_schemas(self, assistant_id: str) -> GraphSchema: """Get the schemas of an assistant by ID. From 80f12c8f5c8c3b8d7d54463c4d691af65c6e84ca Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Fri, 27 Sep 2024 16:43:41 +0200 Subject: [PATCH 5/5] Update sync client --- libs/sdk-py/langgraph_sdk/client.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index 9adb40aed..a466c4dc8 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -2073,11 +2073,14 @@ class SyncAssistantsClient: """ # noqa: E501 return self.http.get(f"/assistants/{assistant_id}") - def get_graph(self, assistant_id: str) -> dict[str, list[dict[str, Any]]]: + def get_graph( + self, assistant_id: str, *, xray: bool = False + ) -> dict[str, list[dict[str, Any]]]: """Get the graph of an assistant by ID. Args: assistant_id: The ID of the assistant to get the graph of. + xray: Include graph representation of subgraphs. Returns: Graph: The graph information for the assistant in JSON format. @@ -2107,7 +2110,7 @@ class SyncAssistantsClient: """ # noqa: E501 - return self.http.get(f"/assistants/{assistant_id}/graph") + return self.http.get(f"/assistants/{assistant_id}/graph", params={"xray": xray}) def get_schemas(self, assistant_id: str) -> GraphSchema: """Get the schemas of an assistant by ID.