langgraph-api 0.1.0__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of langgraph-api might be problematic. Click here for more details.
- langgraph_api/__init__.py +1 -1
- langgraph_api/auth/custom.py +25 -4
- langgraph_api/auth/middleware.py +1 -2
- langgraph_api/config.py +10 -4
- langgraph_api/graph.py +4 -12
- langgraph_api/js/__init__.py +0 -0
- langgraph_api/js/base.py +17 -0
- langgraph_api/js/build.mts +3 -3
- langgraph_api/js/client.mts +64 -3
- langgraph_api/js/global.d.ts +1 -0
- langgraph_api/js/package.json +4 -3
- langgraph_api/js/remote.py +93 -2
- langgraph_api/js/src/graph.mts +0 -6
- langgraph_api/js/src/utils/files.mts +4 -0
- langgraph_api/js/tests/api.test.mts +83 -83
- langgraph_api/js/tests/auth.test.mts +648 -0
- langgraph_api/js/tests/compose-postgres.auth.yml +59 -0
- langgraph_api/js/tests/graphs/agent_simple.mts +79 -0
- langgraph_api/js/tests/graphs/auth.mts +106 -0
- langgraph_api/js/tests/graphs/package.json +3 -1
- langgraph_api/js/tests/graphs/yarn.lock +9 -4
- langgraph_api/js/yarn.lock +18 -23
- langgraph_api/metadata.py +6 -0
- langgraph_api/serde.py +1 -1
- langgraph_api/server.py +38 -0
- langgraph_api/stream.py +2 -1
- langgraph_api/worker.py +1 -22
- {langgraph_api-0.1.0.dist-info → langgraph_api-0.1.3.dist-info}/METADATA +1 -2
- {langgraph_api-0.1.0.dist-info → langgraph_api-0.1.3.dist-info}/RECORD +32 -26
- {langgraph_api-0.1.0.dist-info → langgraph_api-0.1.3.dist-info}/LICENSE +0 -0
- {langgraph_api-0.1.0.dist-info → langgraph_api-0.1.3.dist-info}/WHEEL +0 -0
- {langgraph_api-0.1.0.dist-info → langgraph_api-0.1.3.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StateGraph,
|
|
3
|
+
END,
|
|
4
|
+
Send,
|
|
5
|
+
MessagesAnnotation,
|
|
6
|
+
Annotation,
|
|
7
|
+
START,
|
|
8
|
+
LangGraphRunnableConfig,
|
|
9
|
+
} from "@langchain/langgraph";
|
|
10
|
+
import { BaseMessage, ToolMessage } from "@langchain/core/messages";
|
|
11
|
+
import { FakeListChatModel } from "@langchain/core/utils/testing";
|
|
12
|
+
|
|
13
|
+
const getStableModel = (() => {
|
|
14
|
+
const cached: Record<string, FakeListChatModel> = {};
|
|
15
|
+
return (threadId: string) => {
|
|
16
|
+
cached[threadId] ??= new FakeListChatModel({
|
|
17
|
+
responses: ["begin", "end\u2028"],
|
|
18
|
+
});
|
|
19
|
+
return cached[threadId];
|
|
20
|
+
};
|
|
21
|
+
})();
|
|
22
|
+
|
|
23
|
+
const AgentState = Annotation.Root({
|
|
24
|
+
key_one: Annotation<string>(),
|
|
25
|
+
key_two: Annotation<string>(),
|
|
26
|
+
sleep: Annotation<number>(),
|
|
27
|
+
messages: MessagesAnnotation.spec.messages,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
async function callModel(
|
|
31
|
+
state: typeof AgentState.State,
|
|
32
|
+
config: LangGraphRunnableConfig
|
|
33
|
+
): Promise<typeof AgentState.Update> {
|
|
34
|
+
let userId: string | undefined;
|
|
35
|
+
|
|
36
|
+
if (config.configurable?.langgraph_auth_user != null) {
|
|
37
|
+
const user = config.configurable?.langgraph_auth_user as
|
|
38
|
+
| { identity: string }
|
|
39
|
+
| undefined;
|
|
40
|
+
|
|
41
|
+
userId = user?.identity;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const model = getStableModel(config.configurable?.thread_id ?? "$");
|
|
45
|
+
const existing = await config.store?.get([userId ?? "ALL"], "key_one");
|
|
46
|
+
if (!existing) {
|
|
47
|
+
const text = state.messages.at(-1)?.content;
|
|
48
|
+
await config.store?.put([userId ?? "ALL"], "key_one", { text });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const response = await model.invoke(state.messages);
|
|
52
|
+
const result: typeof AgentState.Update = { messages: [response] };
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function callTool(
|
|
57
|
+
message: BaseMessage
|
|
58
|
+
): Promise<typeof AgentState.Update> {
|
|
59
|
+
const response = new ToolMessage(
|
|
60
|
+
`tool_call__${message.content}`,
|
|
61
|
+
"tool_call_id"
|
|
62
|
+
);
|
|
63
|
+
return { messages: [response] };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function shouldContinue(state: typeof AgentState.State): typeof END | Send {
|
|
67
|
+
const lastMessage = state.messages.at(-1);
|
|
68
|
+
if ((lastMessage?.content as string).startsWith("end")) return END;
|
|
69
|
+
return new Send("tool", lastMessage);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const workflow = new StateGraph(AgentState)
|
|
73
|
+
.addNode("agent", callModel)
|
|
74
|
+
.addNode("tool", callTool)
|
|
75
|
+
.addEdge(START, "agent")
|
|
76
|
+
.addConditionalEdges("agent", shouldContinue)
|
|
77
|
+
.addEdge("tool", "agent");
|
|
78
|
+
|
|
79
|
+
export const graph = workflow.compile();
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";
|
|
2
|
+
import { JWTPayload, jwtVerify } from "jose";
|
|
3
|
+
|
|
4
|
+
const SECRET_KEY = new TextEncoder().encode(
|
|
5
|
+
"09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
|
|
6
|
+
);
|
|
7
|
+
const ALGORITHM = "HS256";
|
|
8
|
+
|
|
9
|
+
const USERS_DB: Record<
|
|
10
|
+
string,
|
|
11
|
+
{
|
|
12
|
+
username: string;
|
|
13
|
+
identity: string;
|
|
14
|
+
full_name: string;
|
|
15
|
+
email: string;
|
|
16
|
+
permissions: string[];
|
|
17
|
+
hashed_password: string;
|
|
18
|
+
disabled: boolean;
|
|
19
|
+
}
|
|
20
|
+
> = {
|
|
21
|
+
johndoe: {
|
|
22
|
+
username: "johndoe",
|
|
23
|
+
identity: "johndoe",
|
|
24
|
+
full_name: "John Doe",
|
|
25
|
+
email: "johndoe@example.com",
|
|
26
|
+
permissions: ["read", "write", "assistants:write", "me"],
|
|
27
|
+
hashed_password:
|
|
28
|
+
"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
|
|
29
|
+
disabled: false,
|
|
30
|
+
},
|
|
31
|
+
alice: {
|
|
32
|
+
username: "alice",
|
|
33
|
+
identity: "alice",
|
|
34
|
+
full_name: "Alice Chains",
|
|
35
|
+
email: "alicechains@example.com",
|
|
36
|
+
permissions: ["read", "write", "assistants:write", "me"],
|
|
37
|
+
hashed_password:
|
|
38
|
+
"$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm",
|
|
39
|
+
disabled: true,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
export const auth = new Auth()
|
|
43
|
+
.authenticate(async (request) => {
|
|
44
|
+
const authorization = request.headers.get("Authorization");
|
|
45
|
+
|
|
46
|
+
const exc = new HTTPException(401, {
|
|
47
|
+
message: "Could not validate credentials",
|
|
48
|
+
headers: { "WWW-Authenticate": "Bearer" },
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (!authorization?.toLocaleLowerCase().startsWith("bearer ")) {
|
|
52
|
+
throw exc;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let payload: JWTPayload | undefined;
|
|
56
|
+
try {
|
|
57
|
+
const token = authorization.split(" ")[1];
|
|
58
|
+
const result = await jwtVerify(token, SECRET_KEY, {
|
|
59
|
+
algorithms: [ALGORITHM],
|
|
60
|
+
});
|
|
61
|
+
payload = result.payload;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
throw new HTTPException(401, {
|
|
64
|
+
message: "Failed to verify JWT token",
|
|
65
|
+
cause: error,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const scopes = (payload["scopes"] ?? []) as string[];
|
|
70
|
+
const username = payload["sub"] as string | undefined;
|
|
71
|
+
const user = username ? USERS_DB[username] : null;
|
|
72
|
+
if (!user) throw exc;
|
|
73
|
+
|
|
74
|
+
let permissions = user.permissions ?? [];
|
|
75
|
+
permissions = scopes.filter((scope) => permissions.includes(scope));
|
|
76
|
+
|
|
77
|
+
return { ...user, permissions };
|
|
78
|
+
})
|
|
79
|
+
.on("*", ({ permissions }) => {
|
|
80
|
+
if (!permissions?.length) {
|
|
81
|
+
throw new HTTPException(403, { message: "Not authorized" });
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
.on("assistants:create", ({ value, user, permissions }) => {
|
|
85
|
+
if (!permissions?.includes("assistants:write")) {
|
|
86
|
+
throw new HTTPException(403, { message: "Not authorized" });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
value.metadata ??= {};
|
|
90
|
+
value.metadata["owner"] = user.identity;
|
|
91
|
+
})
|
|
92
|
+
.on("assistants:search", (params) => ({ owner: params.user.identity }))
|
|
93
|
+
.on(["threads", "assistants"], ({ action, value, user }) => {
|
|
94
|
+
const filters = { owner: user.identity };
|
|
95
|
+
if (action === "create" || action === "update" || action === "create_run") {
|
|
96
|
+
value.metadata ??= {};
|
|
97
|
+
value.metadata["owner"] = user.identity;
|
|
98
|
+
}
|
|
99
|
+
return filters;
|
|
100
|
+
})
|
|
101
|
+
.on("store", ({ value, user }) => {
|
|
102
|
+
const identity = user.identity;
|
|
103
|
+
if (!identity || !value.namespace?.includes(identity)) {
|
|
104
|
+
throw new HTTPException(403, { message: "Not authorized" });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
dependencies:
|
|
33
33
|
uuid "^10.0.0"
|
|
34
34
|
|
|
35
|
-
"@langchain/langgraph-sdk@~0.0.32":
|
|
36
|
-
version "0.0.
|
|
37
|
-
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.
|
|
38
|
-
integrity sha512-
|
|
35
|
+
"@langchain/langgraph-sdk@^0.0.66", "@langchain/langgraph-sdk@~0.0.32":
|
|
36
|
+
version "0.0.66"
|
|
37
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.66.tgz#1a31c3b30d9cffff59910d95c77832e4606b7c3b"
|
|
38
|
+
integrity sha512-l0V4yfKXhHaTRK/1bKMfZ14k3wWZu27DWTlCUnbYJvdo7os5srhONgPCOqQgpazhi5EhXbW2EVgeu/wLW2zH6Q==
|
|
39
39
|
dependencies:
|
|
40
40
|
"@types/json-schema" "^7.0.15"
|
|
41
41
|
p-queue "^6.6.2"
|
|
@@ -131,6 +131,11 @@ has-flag@^4.0.0:
|
|
|
131
131
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
|
132
132
|
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
|
133
133
|
|
|
134
|
+
jose@^6.0.10:
|
|
135
|
+
version "6.0.10"
|
|
136
|
+
resolved "https://registry.yarnpkg.com/jose/-/jose-6.0.10.tgz#52d96e1a671b4c02e13b71e0d35abea2e774712b"
|
|
137
|
+
integrity sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw==
|
|
138
|
+
|
|
134
139
|
js-tiktoken@^1.0.12:
|
|
135
140
|
version "1.0.12"
|
|
136
141
|
resolved "https://registry.yarnpkg.com/js-tiktoken/-/js-tiktoken-1.0.12.tgz#af0f5cf58e5e7318240d050c8413234019424211"
|
langgraph_api/js/yarn.lock
CHANGED
|
@@ -203,15 +203,15 @@
|
|
|
203
203
|
zod "^3.22.4"
|
|
204
204
|
zod-to-json-schema "^3.22.3"
|
|
205
205
|
|
|
206
|
-
"@langchain/langgraph-api@~0.0.
|
|
207
|
-
version "0.0.
|
|
208
|
-
resolved "https://registry.yarnpkg.com/@langchain/langgraph-api/-/langgraph-api-0.0.
|
|
209
|
-
integrity sha512-
|
|
206
|
+
"@langchain/langgraph-api@~0.0.21":
|
|
207
|
+
version "0.0.21"
|
|
208
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-api/-/langgraph-api-0.0.21.tgz#95e84d941298e3b6bcaa749d6cdb030d9bdaa5a3"
|
|
209
|
+
integrity sha512-vQLxvYf3opVBdg5ZosObfwqJgfpLu729+Fz2sq9k+8tIMI0XKFnQw+UKTKyQYOUnsyDjRfZFr64AX2vRkWgF1w==
|
|
210
210
|
dependencies:
|
|
211
211
|
"@babel/code-frame" "^7.26.2"
|
|
212
212
|
"@hono/node-server" "^1.12.0"
|
|
213
213
|
"@hono/zod-validator" "^0.2.2"
|
|
214
|
-
"@langchain/langgraph-ui" "0.0.
|
|
214
|
+
"@langchain/langgraph-ui" "0.0.21"
|
|
215
215
|
"@types/json-schema" "^7.0.15"
|
|
216
216
|
"@typescript/vfs" "^1.6.0"
|
|
217
217
|
dedent "^1.5.3"
|
|
@@ -242,30 +242,20 @@
|
|
|
242
242
|
dependencies:
|
|
243
243
|
uuid "^10.0.0"
|
|
244
244
|
|
|
245
|
-
"@langchain/langgraph-sdk@^0.0.
|
|
246
|
-
version "0.0.
|
|
247
|
-
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.
|
|
248
|
-
integrity sha512-
|
|
245
|
+
"@langchain/langgraph-sdk@^0.0.66", "@langchain/langgraph-sdk@~0.0.32":
|
|
246
|
+
version "0.0.66"
|
|
247
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.66.tgz#1a31c3b30d9cffff59910d95c77832e4606b7c3b"
|
|
248
|
+
integrity sha512-l0V4yfKXhHaTRK/1bKMfZ14k3wWZu27DWTlCUnbYJvdo7os5srhONgPCOqQgpazhi5EhXbW2EVgeu/wLW2zH6Q==
|
|
249
249
|
dependencies:
|
|
250
250
|
"@types/json-schema" "^7.0.15"
|
|
251
251
|
p-queue "^6.6.2"
|
|
252
252
|
p-retry "4"
|
|
253
253
|
uuid "^9.0.0"
|
|
254
254
|
|
|
255
|
-
"@langchain/langgraph-
|
|
256
|
-
version "0.0.
|
|
257
|
-
resolved "https://registry.yarnpkg.com/@langchain/langgraph-
|
|
258
|
-
integrity sha512-
|
|
259
|
-
dependencies:
|
|
260
|
-
"@types/json-schema" "^7.0.15"
|
|
261
|
-
p-queue "^6.6.2"
|
|
262
|
-
p-retry "4"
|
|
263
|
-
uuid "^9.0.0"
|
|
264
|
-
|
|
265
|
-
"@langchain/langgraph-ui@0.0.20", "@langchain/langgraph-ui@~0.0.20":
|
|
266
|
-
version "0.0.20"
|
|
267
|
-
resolved "https://registry.yarnpkg.com/@langchain/langgraph-ui/-/langgraph-ui-0.0.20.tgz#9075acef91c287cfafa81d4eef34a6a51ba1a4d1"
|
|
268
|
-
integrity sha512-x6fF6STKx0gsCAtEqEwyIib6klwLboqvpXsobHVeFOx6qGqOGsVKbq6rgCIKxQz8tZeSQVXslas4/20SFUjwKA==
|
|
255
|
+
"@langchain/langgraph-ui@0.0.21", "@langchain/langgraph-ui@~0.0.21":
|
|
256
|
+
version "0.0.21"
|
|
257
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-ui/-/langgraph-ui-0.0.21.tgz#522c87f602954b8bcb75f63b983ec2de18c14b3f"
|
|
258
|
+
integrity sha512-9XauIpo6KkztOmp4ayR+2gzCPHsGIZJl2x5EwPwCnipzsLo0zbm6Frc8fLZyZtaZrU3sIhVpguLB8ORYPKsB3g==
|
|
269
259
|
dependencies:
|
|
270
260
|
"@commander-js/extra-typings" "^13.0.0"
|
|
271
261
|
commander "^13.0.0"
|
|
@@ -1034,6 +1024,11 @@ jiti@^2.4.2:
|
|
|
1034
1024
|
resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560"
|
|
1035
1025
|
integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==
|
|
1036
1026
|
|
|
1027
|
+
jose@^6.0.10:
|
|
1028
|
+
version "6.0.10"
|
|
1029
|
+
resolved "https://registry.yarnpkg.com/jose/-/jose-6.0.10.tgz#52d96e1a671b4c02e13b71e0d35abea2e774712b"
|
|
1030
|
+
integrity sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw==
|
|
1031
|
+
|
|
1037
1032
|
js-tiktoken@^1.0.12:
|
|
1038
1033
|
version "1.0.15"
|
|
1039
1034
|
resolved "https://registry.yarnpkg.com/js-tiktoken/-/js-tiktoken-1.0.15.tgz#92a7d829f6950c2cfb35cc52555502e3d6e2ebac"
|
langgraph_api/metadata.py
CHANGED
|
@@ -70,6 +70,12 @@ async def metadata_loop() -> None:
|
|
|
70
70
|
if not LANGGRAPH_CLOUD_LICENSE_KEY and not LANGSMITH_API_KEY:
|
|
71
71
|
return
|
|
72
72
|
|
|
73
|
+
if LANGGRAPH_CLOUD_LICENSE_KEY and not LANGGRAPH_CLOUD_LICENSE_KEY.startswith(
|
|
74
|
+
"lcl_"
|
|
75
|
+
):
|
|
76
|
+
logger.info("Running in air-gapped mode, skipping metadata loop")
|
|
77
|
+
return
|
|
78
|
+
|
|
73
79
|
logger.info("Starting metadata loop")
|
|
74
80
|
|
|
75
81
|
global RUN_COUNTER, NODE_COUNTER, FROM_TIMESTAMP
|
langgraph_api/serde.py
CHANGED
|
@@ -104,7 +104,7 @@ _option = orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_NON_STR_KEYS
|
|
|
104
104
|
|
|
105
105
|
def json_dumpb(obj) -> bytes:
|
|
106
106
|
return orjson.dumps(obj, default=default, option=_option).replace(
|
|
107
|
-
|
|
107
|
+
rb"\u0000", b""
|
|
108
108
|
) # null unicode char not allowed in json
|
|
109
109
|
|
|
110
110
|
|
langgraph_api/server.py
CHANGED
|
@@ -5,6 +5,7 @@ import sys
|
|
|
5
5
|
# WARNING: Keep the import above before other code runs as it
|
|
6
6
|
# patches an error in the Starlette library.
|
|
7
7
|
import logging
|
|
8
|
+
import typing
|
|
8
9
|
|
|
9
10
|
import jsonschema_rs
|
|
10
11
|
import structlog
|
|
@@ -13,10 +14,13 @@ from langgraph.errors import EmptyInputError, InvalidUpdateError
|
|
|
13
14
|
from starlette.applications import Starlette
|
|
14
15
|
from starlette.middleware import Middleware
|
|
15
16
|
from starlette.middleware.cors import CORSMiddleware
|
|
17
|
+
|
|
16
18
|
from langgraph_api.api.openapi import set_custom_spec
|
|
19
|
+
from starlette.types import Receive, Scope, Send
|
|
17
20
|
|
|
18
21
|
import langgraph_api.config as config
|
|
19
22
|
from langgraph_api.api import routes, meta_routes, user_router
|
|
23
|
+
from starlette.routing import Mount
|
|
20
24
|
from langgraph_api.errors import (
|
|
21
25
|
overloaded_error_handler,
|
|
22
26
|
validation_error_handler,
|
|
@@ -149,3 +153,37 @@ else:
|
|
|
149
153
|
middleware=middleware,
|
|
150
154
|
exception_handlers=exception_handlers,
|
|
151
155
|
)
|
|
156
|
+
|
|
157
|
+
if config.MOUNT_PREFIX:
|
|
158
|
+
prefix = config.MOUNT_PREFIX
|
|
159
|
+
if not prefix.startswith("/") or prefix.endswith("/"):
|
|
160
|
+
raise ValueError(
|
|
161
|
+
f"Invalid mount_prefix '{prefix}': Must start with '/' and must not end with '/'. "
|
|
162
|
+
f"Valid examples: '/my-api', '/v1', '/api/v1'.\nInvalid examples: 'api/', '/api/'"
|
|
163
|
+
)
|
|
164
|
+
logger.info(f"Mounting routes at prefix: {prefix}")
|
|
165
|
+
plen = len(prefix)
|
|
166
|
+
rplen = len(prefix.encode("utf-8"))
|
|
167
|
+
|
|
168
|
+
class ASGIBypassMiddleware:
|
|
169
|
+
def __init__(self, app: typing.Any, **kwargs):
|
|
170
|
+
self.app = app
|
|
171
|
+
|
|
172
|
+
async def __call__(
|
|
173
|
+
self, scope: Scope, receive: Receive, send: Send
|
|
174
|
+
) -> typing.Any:
|
|
175
|
+
if (root_path := scope.get("root_path")) and root_path == "/noauth":
|
|
176
|
+
# The SDK initialized with None is trying to connect via
|
|
177
|
+
# ASGITransport. Ensure that it has the correct subpath prefixes
|
|
178
|
+
# so the regular router can handle it.
|
|
179
|
+
scope["path"] = f'/noauth{prefix}{scope["path"]}'
|
|
180
|
+
scope["raw_path"] = scope["path"].encode("utf-8")
|
|
181
|
+
|
|
182
|
+
return await self.app(scope, receive, send)
|
|
183
|
+
|
|
184
|
+
app = Starlette(
|
|
185
|
+
routes=[Mount(prefix, app=app)],
|
|
186
|
+
lifespan=app.router.lifespan_context,
|
|
187
|
+
middleware=[Middleware(ASGIBypassMiddleware)] + app.user_middleware,
|
|
188
|
+
exception_handlers=app.exception_handlers,
|
|
189
|
+
)
|
langgraph_api/stream.py
CHANGED
|
@@ -260,12 +260,13 @@ async def consume(stream: AnyStream, run_id: str) -> None:
|
|
|
260
260
|
run_id, mode, await run_in_executor(None, json_dumpb, payload)
|
|
261
261
|
)
|
|
262
262
|
except Exception as e:
|
|
263
|
+
g = e
|
|
263
264
|
if isinstance(e, ExceptionGroup):
|
|
264
265
|
e = e.exceptions[0]
|
|
265
266
|
await Runs.Stream.publish(
|
|
266
267
|
run_id, "error", await run_in_executor(None, json_dumpb, e)
|
|
267
268
|
)
|
|
268
|
-
raise e from
|
|
269
|
+
raise e from g
|
|
269
270
|
|
|
270
271
|
|
|
271
272
|
def get_feedback_urls(run_id: str, feedback_keys: list[str]) -> dict[str, str]:
|
langgraph_api/worker.py
CHANGED
|
@@ -35,11 +35,6 @@ try:
|
|
|
35
35
|
except ImportError:
|
|
36
36
|
InFailedSqlTransaction = ()
|
|
37
37
|
|
|
38
|
-
try:
|
|
39
|
-
from blockbuster import BlockingError
|
|
40
|
-
except ImportError:
|
|
41
|
-
BlockingError = ()
|
|
42
|
-
|
|
43
38
|
logger = structlog.stdlib.get_logger(__name__)
|
|
44
39
|
|
|
45
40
|
|
|
@@ -247,23 +242,6 @@ async def worker(
|
|
|
247
242
|
await Runs.set_status(conn, run_id, "pending")
|
|
248
243
|
raise
|
|
249
244
|
except Exception as exc:
|
|
250
|
-
if isinstance(exc, BlockingError):
|
|
251
|
-
# Only occurs in the dev server
|
|
252
|
-
exc.add_note(
|
|
253
|
-
"Heads up! LangGraph identified a synchronous blocking call in your code. "
|
|
254
|
-
"When running in an ASGI web server, blocking calls can degrade performance for everyone since they tie up the event loop.\n\n"
|
|
255
|
-
"Here are your options to fix this:\n\n"
|
|
256
|
-
"1. Best approach: Convert any blocking code to use async/await patterns\n"
|
|
257
|
-
" For example, use 'await aiohttp.get()' instead of 'requests.get()'\n\n"
|
|
258
|
-
"2. Quick fix: Move blocking operations to a separate thread\n"
|
|
259
|
-
" Example: 'await asyncio.to_thread(your_blocking_function)'\n\n"
|
|
260
|
-
"3. Override (if you can't change the code):\n"
|
|
261
|
-
" - For development: Run 'langgraph dev --allow-blocking'\n"
|
|
262
|
-
" - For deployment: Set 'BG_JOB_ISOLATED_LOOPS=true' environment variable\n\n"
|
|
263
|
-
"These blocking operations can prevent health checks and slow down other runs in your deployment. "
|
|
264
|
-
"Following these recommendations will help keep your LangGraph application running smoothly!"
|
|
265
|
-
)
|
|
266
|
-
|
|
267
245
|
exception = exc
|
|
268
246
|
status = "error"
|
|
269
247
|
run_ended_at = datetime.now(UTC).isoformat()
|
|
@@ -296,6 +274,7 @@ async def worker(
|
|
|
296
274
|
# Note we don't handle asyncio.CancelledError here, as we want to
|
|
297
275
|
# let it bubble up and rollback db transaction, thus marking the run
|
|
298
276
|
# as available to be picked up by another worker
|
|
277
|
+
|
|
299
278
|
return {
|
|
300
279
|
"checkpoint": checkpoint,
|
|
301
280
|
"status": status,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary:
|
|
5
5
|
License: Elastic-2.0
|
|
6
6
|
Author: Nuno Campos
|
|
@@ -11,7 +11,6 @@ Classifier: Programming Language :: Python :: 3
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
-
Requires-Dist: blockbuster (>=1.5.24,<2.0.0)
|
|
15
14
|
Requires-Dist: cloudpickle (>=3.0.0,<4.0.0)
|
|
16
15
|
Requires-Dist: cryptography (>=42.0.0,<45.0)
|
|
17
16
|
Requires-Dist: httpx (>=0.25.0)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
2
|
-
langgraph_api/__init__.py,sha256=
|
|
2
|
+
langgraph_api/__init__.py,sha256=XEqb2aiIn8fzGE68Mph4ck1FtQqsR_am0wRWvrYPffQ,22
|
|
3
3
|
langgraph_api/api/__init__.py,sha256=ohkuKTIYaWMAnr2pck2XAMrg4srA418VM76GQWRf5tU,5493
|
|
4
4
|
langgraph_api/api/assistants.py,sha256=i-nxkScUB2g8bTVGtQIp1psABXlaY1aVx9pkB_UiRH8,14353
|
|
5
5
|
langgraph_api/api/mcp.py,sha256=KbR19dtFCpJEiKYj3IfepAuJij8YZVELuVp7JY_yu_o,13754
|
|
@@ -11,60 +11,66 @@ langgraph_api/api/threads.py,sha256=EvKJDnZDWutKoB5KoTP40NPEqG5LJ-Iw97TLYHkhLbw,
|
|
|
11
11
|
langgraph_api/api/ui.py,sha256=kdCQ-p0voxAqIFc72aqqzdPGH2v-yEBKzjRE6cUPvpU,2201
|
|
12
12
|
langgraph_api/asyncio.py,sha256=h0eZ7aoDGnJpoxnHLZABVlj1jQ78UxjgiHntTmAEWek,8613
|
|
13
13
|
langgraph_api/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
langgraph_api/auth/custom.py,sha256=
|
|
14
|
+
langgraph_api/auth/custom.py,sha256=QR49PnIfPPQZ6ygWmnMkSuAzgOpBBUbbz5kJ2yVwGmQ,21934
|
|
15
15
|
langgraph_api/auth/langsmith/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
langgraph_api/auth/langsmith/backend.py,sha256=InScaL-HYCnxYEauhxU198gRZV9pJn9SzzBoR9Edn7g,2654
|
|
17
17
|
langgraph_api/auth/langsmith/client.py,sha256=eKchvAom7hdkUXauD8vHNceBDDUijrFgdTV8bKd7x4Q,3998
|
|
18
|
-
langgraph_api/auth/middleware.py,sha256=
|
|
18
|
+
langgraph_api/auth/middleware.py,sha256=jDA4t41DUoAArEY_PNoXesIUBJ0nGhh85QzRdn5EPD0,1916
|
|
19
19
|
langgraph_api/auth/noop.py,sha256=Bk6Nf3p8D_iMVy_OyfPlyiJp_aEwzL-sHrbxoXpCbac,586
|
|
20
20
|
langgraph_api/auth/studio_user.py,sha256=FzFQRROKDlA9JjtBuwyZvk6Mbwno5M9RVYjDO6FU3F8,186
|
|
21
21
|
langgraph_api/cli.py,sha256=eVX8zGeQAoVMotib2s-QhIQWQX1JInpVMItkTTgG_dU,12833
|
|
22
22
|
langgraph_api/command.py,sha256=3O9v3i0OPa96ARyJ_oJbLXkfO8rPgDhLCswgO9koTFA,768
|
|
23
|
-
langgraph_api/config.py,sha256=
|
|
23
|
+
langgraph_api/config.py,sha256=uvw51OP8VApy54DbqZIShNoaCJeM7M83mR-8hDgMLY8,10553
|
|
24
24
|
langgraph_api/cron_scheduler.py,sha256=i87j4pJrcsmsqMKeKUs69gaAjrGaSM3pM3jnXdN5JDQ,2630
|
|
25
25
|
langgraph_api/errors.py,sha256=Bu_i5drgNTyJcLiyrwVE_6-XrSU50BHf9TDpttki9wQ,1690
|
|
26
|
-
langgraph_api/graph.py,sha256=
|
|
26
|
+
langgraph_api/graph.py,sha256=GZtVXyP1l-nKlcRmB9s_m0U9UnifPUzIBBjDXmT11oo,20959
|
|
27
27
|
langgraph_api/http.py,sha256=gYbxxjY8aLnsXeJymcJ7G7Nj_yToOGpPYQqmZ1_ggfA,5240
|
|
28
28
|
langgraph_api/js/.gitignore,sha256=l5yI6G_V6F1600I1IjiUKn87f4uYIrBAYU1MOyBBhg4,59
|
|
29
|
-
langgraph_api/js/
|
|
30
|
-
langgraph_api/js/
|
|
31
|
-
langgraph_api/js/
|
|
29
|
+
langgraph_api/js/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
+
langgraph_api/js/base.py,sha256=udYS5_OmmJI_d7kEUv0H4FINprZOW6tdXRkKDEdzNvc,469
|
|
31
|
+
langgraph_api/js/build.mts,sha256=4xcjo9rufSPUnnihdYp1EnDPSoaDQDV6aN8_UMjKp-g,1916
|
|
32
|
+
langgraph_api/js/client.mts,sha256=7v5BcWsR5w6wGCsxhm6xryBgI-5vfu2Or1YmT-GdKyY,28766
|
|
32
33
|
langgraph_api/js/errors.py,sha256=Cm1TKWlUCwZReDC5AQ6SgNIVGD27Qov2xcgHyf8-GXo,361
|
|
33
|
-
langgraph_api/js/global.d.ts,sha256=
|
|
34
|
-
langgraph_api/js/package.json,sha256=
|
|
35
|
-
langgraph_api/js/remote.py,sha256
|
|
34
|
+
langgraph_api/js/global.d.ts,sha256=j4GhgtQSZ5_cHzjSPcHgMJ8tfBThxrH-pUOrrJGteOU,196
|
|
35
|
+
langgraph_api/js/package.json,sha256=7lAok4cUtnfbE2E2P1FQDZgwmsZSQSl5O6eDoh1va-I,1289
|
|
36
|
+
langgraph_api/js/remote.py,sha256=OHxjncX1AAahUurlntkcgMYl852XgT19OxJeuvfEFsc,27959
|
|
36
37
|
langgraph_api/js/schema.py,sha256=7idnv7URlYUdSNMBXQcw7E4SxaPxCq_Oxwnlml8q5ik,408
|
|
37
|
-
langgraph_api/js/src/graph.mts,sha256=
|
|
38
|
+
langgraph_api/js/src/graph.mts,sha256=g86jOvbHj1B0o1jatBc2X5_JEZW2DSNwgUJ_kw1k8Cw,3569
|
|
38
39
|
langgraph_api/js/src/hooks.mjs,sha256=XtktgmIHlls_DsknAuwib-z7TqCm0haRoTXvnkgzMuo,601
|
|
39
40
|
langgraph_api/js/src/parser/parser.mts,sha256=c7WLEtMMwtVzir9O8VpJFVHKuLjtI86rde-In2lvaM0,13217
|
|
40
41
|
langgraph_api/js/src/parser/parser.worker.mjs,sha256=2K6D0GlUmkk7LE39I8mryB8VZVE3-N9Cblji-ArPhFo,386
|
|
41
42
|
langgraph_api/js/src/schema/types.mts,sha256=SRCYZTWjxyc7528DaapR_DCm3G5bfDSh4vf-JsYpk0w,62633
|
|
42
43
|
langgraph_api/js/src/schema/types.template.mts,sha256=Dbjj_8d-OubqH4QY_OaxSu8ocZ4dVjI94oncL20fqtk,2235
|
|
44
|
+
langgraph_api/js/src/utils/files.mts,sha256=MXC-3gy0pkS82AjPBoUN83jY_qg37WSAPHOA7DwfB4M,141
|
|
43
45
|
langgraph_api/js/src/utils/importMap.mts,sha256=pX4TGOyUpuuWF82kXcxcv3-8mgusRezOGe6Uklm2O5A,1644
|
|
44
46
|
langgraph_api/js/src/utils/pythonSchemas.mts,sha256=98IW7Z_VP7L_CHNRMb3_MsiV3BgLE2JsWQY_PQcRR3o,685
|
|
45
47
|
langgraph_api/js/src/utils/serde.mts,sha256=OuyyO9btvwWd55rU_H4x91dFEJiaPxL-lL9O6Zgo908,742
|
|
46
48
|
langgraph_api/js/sse.py,sha256=lsfp4nyJyA1COmlKG9e2gJnTttf_HGCB5wyH8OZBER8,4105
|
|
47
|
-
langgraph_api/js/tests/api.test.mts,sha256=
|
|
49
|
+
langgraph_api/js/tests/api.test.mts,sha256=CJ4q0HmutNRLMFhEkOZ4w3UJxgEG9FYLDVFCB8WirGQ,62987
|
|
50
|
+
langgraph_api/js/tests/auth.test.mts,sha256=A8JXfEep6S4jzduoSZeRQkqq9WsFbVE8Bvi3Hj_zx2w,21600
|
|
51
|
+
langgraph_api/js/tests/compose-postgres.auth.yml,sha256=iPfJbCeYZdV6GiRLiDn_f7qgpG4TyyGaQ4lV-ZXr6Qk,1768
|
|
48
52
|
langgraph_api/js/tests/compose-postgres.yml,sha256=yz99nUy4Gm8vXuE5cnp2ekPzv7x5XWdwFPB9muAqeGE,1861
|
|
49
53
|
langgraph_api/js/tests/graphs/.gitignore,sha256=26J8MarZNXh7snXD5eTpV3CPFTht5Znv8dtHYCLNfkw,12
|
|
50
54
|
langgraph_api/js/tests/graphs/agent.css,sha256=QgcOC0W7IBsrg4pSqqpull-WTgtULZfx_lF_5ZxLdag,23
|
|
51
55
|
langgraph_api/js/tests/graphs/agent.mts,sha256=E9WMv0alMv0njUEECqEsqoRk9NXJUgXW7SyQJ3GOZ8k,5396
|
|
52
56
|
langgraph_api/js/tests/graphs/agent.ui.tsx,sha256=JDFJdpdIS6rglkXTaROSb1Is0j1kt5wN9ML8W4cuht8,175
|
|
57
|
+
langgraph_api/js/tests/graphs/agent_simple.mts,sha256=Ge7jzkV-DsSmJM9RBFrfMIONCtvU-_Ci2PqS9GaYf6w,2231
|
|
58
|
+
langgraph_api/js/tests/graphs/auth.mts,sha256=kF2TZP3n_urWigf0qgejZqTe93-341_Mhqe_qnBO_Io,3195
|
|
53
59
|
langgraph_api/js/tests/graphs/command.mts,sha256=YO1_cEs_n9VsH_-IediLnI4Yc8KRlp4qrprUZXpAlwM,1163
|
|
54
60
|
langgraph_api/js/tests/graphs/delay.mts,sha256=CFneKxqI4bGGK0lYjSbe80QirowPQlsRSuhDUKfydhk,703
|
|
55
61
|
langgraph_api/js/tests/graphs/dynamic.mts,sha256=Wf_-keF7lkEfp_iyI45nlFGCeU8ARLQ8axc0LXh7TyE,659
|
|
56
62
|
langgraph_api/js/tests/graphs/error.mts,sha256=l4tk89449dj1BnEF_0ZcfPt0Ikk1gl8L1RaSnRfr3xo,487
|
|
57
63
|
langgraph_api/js/tests/graphs/langgraph.json,sha256=h6hV1wkNEUIpLBX9JOUKqtIBvbhvzyLEuWtBIHteseg,265
|
|
58
64
|
langgraph_api/js/tests/graphs/nested.mts,sha256=4G7jSOSaFVQAza-_ARbK-Iai1biLlF2DIPDZXf7PLIY,1245
|
|
59
|
-
langgraph_api/js/tests/graphs/package.json,sha256=
|
|
65
|
+
langgraph_api/js/tests/graphs/package.json,sha256=xVclKB1ofQDeTocnu8gvxghPZg2llsIOcn47RuuIOHs,240
|
|
60
66
|
langgraph_api/js/tests/graphs/weather.mts,sha256=A7mLK3xW8h5B-ZyJNAyX2M2fJJwzPJzXs4DYesJwreQ,1655
|
|
61
|
-
langgraph_api/js/tests/graphs/yarn.lock,sha256=
|
|
67
|
+
langgraph_api/js/tests/graphs/yarn.lock,sha256=JP_za1t56zCne5O8QOc-kLrGrUDwSnBZ25F8tVObUuU,10957
|
|
62
68
|
langgraph_api/js/tests/parser.test.mts,sha256=dEC8KTqKygeb1u39ZvpPqCT4HtfPD947nLmITt2buxA,27883
|
|
63
69
|
langgraph_api/js/tests/utils.mts,sha256=q1V9gvT63v95onlfK9W4iv3n9ZJO3h-0RD9TdDYuRyY,439
|
|
64
70
|
langgraph_api/js/ui.py,sha256=XNT8iBcyT8XmbIqSQUWd-j_00HsaWB2vRTVabwFBkik,2439
|
|
65
|
-
langgraph_api/js/yarn.lock,sha256=
|
|
71
|
+
langgraph_api/js/yarn.lock,sha256=A4b9TS9cljYvyc-7RF9QY0zcP_NFJMe2-RVeTSlX2DY,83691
|
|
66
72
|
langgraph_api/logging.py,sha256=JJIzbNIgLCN6ClQ3tA-Mm5ffuBGvpRDSZsEvnIlsuu4,3693
|
|
67
|
-
langgraph_api/metadata.py,sha256=
|
|
73
|
+
langgraph_api/metadata.py,sha256=RUDDgxlrmf7zDFT_kI587JZboD0IdmlBwwkLA0Fxm00,4132
|
|
68
74
|
langgraph_api/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
75
|
langgraph_api/middleware/http_logger.py,sha256=aj4mdisRobFePkD3Iy6-w_Mujwx4TQRaEhPvSd6HgLk,3284
|
|
70
76
|
langgraph_api/middleware/private_network.py,sha256=eYgdyU8AzU2XJu362i1L8aSFoQRiV7_aLBPw7_EgeqI,2111
|
|
@@ -74,24 +80,24 @@ langgraph_api/patch.py,sha256=Dgs0PXHytekX4SUL6KsjjN0hHcOtGLvv1GRGbh6PswU,1408
|
|
|
74
80
|
langgraph_api/queue_entrypoint.py,sha256=gjtajZfnDXhsi7JElfmkY-p0ENBiKBDJ4Ugiw-exapw,1839
|
|
75
81
|
langgraph_api/route.py,sha256=fM4qYCGbmH0a3_cV8uKocb1sLklehxO6HhdRXqLK6OM,4421
|
|
76
82
|
langgraph_api/schema.py,sha256=Frh_YOC3S1cDAMPUVanNi78ooSXK2WFpu9YkIVz5h14,5433
|
|
77
|
-
langgraph_api/serde.py,sha256=
|
|
78
|
-
langgraph_api/server.py,sha256=
|
|
83
|
+
langgraph_api/serde.py,sha256=TVsx2QQtepf8Wsgsabcku1NV4Vbugu4Oujmdnq4qMS0,3964
|
|
84
|
+
langgraph_api/server.py,sha256=d1OeDY7zvw16mX_NWAi9PbFbpFygFlM0clJXRoooPig,6368
|
|
79
85
|
langgraph_api/sse.py,sha256=2wNodCOP2eg7a9mpSu0S3FQ0CHk2BBV_vv0UtIgJIcc,4034
|
|
80
86
|
langgraph_api/state.py,sha256=8jx4IoTCOjTJuwzuXJKKFwo1VseHjNnw_CCq4x1SW14,2284
|
|
81
|
-
langgraph_api/stream.py,sha256=
|
|
87
|
+
langgraph_api/stream.py,sha256=SN96CLJ5QnSQ2YWRrkQb4K8XkdoSbloyFRj8N1vKcs8,11369
|
|
82
88
|
langgraph_api/thread_ttl.py,sha256=4vch4nu1UOiYcqYRd7bTHsfs0Ei_lXuy9nBQ0uVJLyo,1765
|
|
83
89
|
langgraph_api/utils.py,sha256=92mSti9GfGdMRRWyESKQW5yV-75Z9icGHnIrBYvdypU,3619
|
|
84
90
|
langgraph_api/validation.py,sha256=Qo3EkSRXzIRe3GRuqRWbElTcUXRMXMyA1w0VbMvdwME,4934
|
|
85
91
|
langgraph_api/webhook.py,sha256=1ncwO0rIZcj-Df9sxSnFEzd1gP1bfS4okeZQS8NSRoE,1382
|
|
86
|
-
langgraph_api/worker.py,sha256=
|
|
92
|
+
langgraph_api/worker.py,sha256=DX_EZZs47cfb4_1owBkjiq-Mrr2vUoeGjotWvKY21uc,11290
|
|
87
93
|
langgraph_license/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
94
|
langgraph_license/middleware.py,sha256=_ODIYzQkymr6W9_Fp9wtf1kAQspnpsmr53xuzyF2GA0,612
|
|
89
95
|
langgraph_license/validation.py,sha256=Uu_G8UGO_WTlLsBEY0gTVWjRR4czYGfw5YAD3HLZoj0,203
|
|
90
96
|
langgraph_runtime/__init__.py,sha256=3stEi5ECApK7l0Y7q4vN-fQQz8cgJ9lyqAyhqDBqags,1075
|
|
91
97
|
logging.json,sha256=3RNjSADZmDq38eHePMm1CbP6qZ71AmpBtLwCmKU9Zgo,379
|
|
92
98
|
openapi.json,sha256=YW4ND-N3adriEoNwxw7UD9endO2xUZoodCtwVIfa2dU,132261
|
|
93
|
-
langgraph_api-0.1.
|
|
94
|
-
langgraph_api-0.1.
|
|
95
|
-
langgraph_api-0.1.
|
|
96
|
-
langgraph_api-0.1.
|
|
97
|
-
langgraph_api-0.1.
|
|
99
|
+
langgraph_api-0.1.3.dist-info/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
100
|
+
langgraph_api-0.1.3.dist-info/METADATA,sha256=AM0f6xyGMvefzzmkHsD37dNq8Qyq4BAb6wBwswBjLMg,4119
|
|
101
|
+
langgraph_api-0.1.3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
102
|
+
langgraph_api-0.1.3.dist-info/entry_points.txt,sha256=3EYLgj89DfzqJHHYGxPH4A_fEtClvlRbWRUHaXO7hj4,77
|
|
103
|
+
langgraph_api-0.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|