langgraph-api 0.2.30__tar.gz → 0.2.34__tar.gz
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-0.2.30 → langgraph_api-0.2.34}/Makefile +3 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/PKG-INFO +2 -2
- langgraph_api-0.2.34/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/runs.py +29 -9
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/build.mts +36 -19
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/package.json +3 -3
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/yarn.lock +13 -13
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/metadata.py +16 -28
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/models/run.py +3 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/sse.py +12 -4
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/stream.py +15 -18
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/worker.py +6 -3
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/openapi.json +129 -59
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/pyproject.toml +1 -1
- langgraph_api-0.2.30/langgraph_api/__init__.py +0 -1
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/.gitignore +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/LICENSE +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/README.md +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/benchmark/weather.js +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/constraints.txt +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/forbidden.txt +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/healthcheck.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/mcp.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/threads.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/command.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/config.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/http.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/route.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/schema.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/server.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/state.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/store.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/thread_ttl.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/utils.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/logging.json +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/scripts/create_license.py +0 -0
- {langgraph_api-0.2.30 → langgraph_api-0.2.34}/uv.lock +0 -0
|
@@ -67,6 +67,7 @@ start:
|
|
|
67
67
|
--reload \
|
|
68
68
|
--port 9123 \
|
|
69
69
|
--reload-dir langgraph_api \
|
|
70
|
+
--reload-dir ../runtime_inmem \
|
|
70
71
|
--no-access-log
|
|
71
72
|
|
|
72
73
|
|
|
@@ -89,6 +90,7 @@ start-auth-jwt:
|
|
|
89
90
|
--reload \
|
|
90
91
|
--port 9123 \
|
|
91
92
|
--reload-dir langgraph_api \
|
|
93
|
+
--reload-dir ../runtime_inmem \
|
|
92
94
|
--no-access-log
|
|
93
95
|
|
|
94
96
|
start-auth-fastapi-jwt:
|
|
@@ -106,6 +108,7 @@ start-auth-fastapi-jwt:
|
|
|
106
108
|
--reload \
|
|
107
109
|
--port 9123 \
|
|
108
110
|
--reload-dir langgraph_api \
|
|
111
|
+
--reload-dir ../runtime_inmem \
|
|
109
112
|
--no-access-log
|
|
110
113
|
|
|
111
114
|
VERSION_KIND ?= patch
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.34
|
|
4
4
|
Author-email: Nuno Campos <nuno@langchain.dev>, Will Fu-Hinthorn <will@langchain.dev>
|
|
5
5
|
License: Elastic-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -11,7 +11,7 @@ Requires-Dist: httpx>=0.25.0
|
|
|
11
11
|
Requires-Dist: jsonschema-rs<0.30,>=0.20.0
|
|
12
12
|
Requires-Dist: langchain-core>=0.2.38
|
|
13
13
|
Requires-Dist: langgraph-checkpoint>=2.0.23
|
|
14
|
-
Requires-Dist: langgraph-runtime-inmem<0.
|
|
14
|
+
Requires-Dist: langgraph-runtime-inmem<0.3,>=0.2.0
|
|
15
15
|
Requires-Dist: langgraph-sdk>=0.1.66
|
|
16
16
|
Requires-Dist: langgraph>=0.3.27
|
|
17
17
|
Requires-Dist: langsmith>=0.1.112
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.34"
|
|
@@ -39,7 +39,10 @@ async def create_run(request: ApiRequest):
|
|
|
39
39
|
payload,
|
|
40
40
|
request.headers,
|
|
41
41
|
)
|
|
42
|
-
return ApiResponse(
|
|
42
|
+
return ApiResponse(
|
|
43
|
+
run,
|
|
44
|
+
headers={"Content-Location": f"/threads/{thread_id}/runs/{run['run_id']}"},
|
|
45
|
+
)
|
|
43
46
|
|
|
44
47
|
|
|
45
48
|
@retry_db
|
|
@@ -53,7 +56,10 @@ async def create_stateless_run(request: ApiRequest):
|
|
|
53
56
|
payload,
|
|
54
57
|
request.headers,
|
|
55
58
|
)
|
|
56
|
-
return ApiResponse(
|
|
59
|
+
return ApiResponse(
|
|
60
|
+
run,
|
|
61
|
+
headers={"Content-Location": f"/runs/{run['run_id']}"},
|
|
62
|
+
)
|
|
57
63
|
|
|
58
64
|
|
|
59
65
|
async def create_stateless_run_batch(request: ApiRequest):
|
|
@@ -107,8 +113,12 @@ async def stream_run(
|
|
|
107
113
|
thread_id=thread_id,
|
|
108
114
|
cancel_on_disconnect=on_disconnect == "cancel",
|
|
109
115
|
stream_mode=await sub,
|
|
116
|
+
last_event_id=None,
|
|
110
117
|
),
|
|
111
|
-
headers={
|
|
118
|
+
headers={
|
|
119
|
+
"Location": f"/threads/{thread_id}/runs/{run['run_id']}/stream",
|
|
120
|
+
"Content-Location": f"/threads/{thread_id}/runs/{run['run_id']}",
|
|
121
|
+
},
|
|
112
122
|
)
|
|
113
123
|
|
|
114
124
|
|
|
@@ -143,9 +153,11 @@ async def stream_run_stateless(
|
|
|
143
153
|
ignore_404=True,
|
|
144
154
|
cancel_on_disconnect=on_disconnect == "cancel",
|
|
145
155
|
stream_mode=await sub,
|
|
156
|
+
last_event_id=None,
|
|
146
157
|
),
|
|
147
158
|
headers={
|
|
148
|
-
"Location": f"/
|
|
159
|
+
"Location": f"/runs/{run['run_id']}/stream",
|
|
160
|
+
"Content-Location": f"/runs/{run['run_id']}",
|
|
149
161
|
},
|
|
150
162
|
)
|
|
151
163
|
|
|
@@ -182,7 +194,7 @@ async def wait_run(request: ApiRequest):
|
|
|
182
194
|
run["run_id"], thread_id=run["thread_id"], stream_mode=await sub
|
|
183
195
|
)
|
|
184
196
|
) as stream:
|
|
185
|
-
async for mode, chunk in stream:
|
|
197
|
+
async for mode, chunk, _ in stream:
|
|
186
198
|
if mode == b"values":
|
|
187
199
|
vchunk = chunk
|
|
188
200
|
elif mode == b"error":
|
|
@@ -216,7 +228,10 @@ async def wait_run(request: ApiRequest):
|
|
|
216
228
|
return StreamingResponse(
|
|
217
229
|
body(),
|
|
218
230
|
media_type="application/json",
|
|
219
|
-
headers={
|
|
231
|
+
headers={
|
|
232
|
+
"Location": f"/threads/{thread_id}/runs/{run['run_id']}/join",
|
|
233
|
+
"Content-Location": f"/threads/{thread_id}/runs/{run['run_id']}",
|
|
234
|
+
},
|
|
220
235
|
)
|
|
221
236
|
|
|
222
237
|
|
|
@@ -251,7 +266,7 @@ async def wait_run_stateless(request: ApiRequest):
|
|
|
251
266
|
run["run_id"], thread_id=run["thread_id"], stream_mode=await sub
|
|
252
267
|
)
|
|
253
268
|
) as stream:
|
|
254
|
-
async for mode, chunk in stream:
|
|
269
|
+
async for mode, chunk, _ in stream:
|
|
255
270
|
if mode == b"values":
|
|
256
271
|
vchunk = chunk
|
|
257
272
|
elif mode == b"error":
|
|
@@ -280,7 +295,10 @@ async def wait_run_stateless(request: ApiRequest):
|
|
|
280
295
|
return StreamingResponse(
|
|
281
296
|
body(),
|
|
282
297
|
media_type="application/json",
|
|
283
|
-
headers={
|
|
298
|
+
headers={
|
|
299
|
+
"Location": f"/threads/{run['thread_id']}/runs/{run['run_id']}/join",
|
|
300
|
+
"Content-Location": f"/threads/{run['thread_id']}/runs/{run['run_id']}",
|
|
301
|
+
},
|
|
284
302
|
)
|
|
285
303
|
|
|
286
304
|
|
|
@@ -358,13 +376,15 @@ async def join_run_stream(request: ApiRequest):
|
|
|
358
376
|
validate_uuid(thread_id, "Invalid thread ID: must be a UUID")
|
|
359
377
|
validate_uuid(run_id, "Invalid run ID: must be a UUID")
|
|
360
378
|
stream_mode = request.query_params.get("stream_mode") or None
|
|
379
|
+
last_event_id = request.headers.get("last-event-id") or None
|
|
361
380
|
return EventSourceResponse(
|
|
362
381
|
Runs.Stream.join(
|
|
363
382
|
run_id,
|
|
364
383
|
thread_id=thread_id,
|
|
365
384
|
cancel_on_disconnect=cancel_on_disconnect,
|
|
366
385
|
stream_mode=stream_mode,
|
|
367
|
-
|
|
386
|
+
last_event_id=last_event_id,
|
|
387
|
+
),
|
|
368
388
|
)
|
|
369
389
|
|
|
370
390
|
|
|
@@ -7,7 +7,10 @@ import * as path from "node:path";
|
|
|
7
7
|
import { type GraphSchema, resolveGraph } from "./src/graph.mts";
|
|
8
8
|
import { build } from "@langchain/langgraph-ui";
|
|
9
9
|
import { checkLangGraphSemver } from "@langchain/langgraph-api/semver";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
getStaticGraphSchema,
|
|
12
|
+
GraphSpec,
|
|
13
|
+
} from "@langchain/langgraph-api/schema";
|
|
11
14
|
import { filterValidExportPath } from "./src/utils/files.mts";
|
|
12
15
|
|
|
13
16
|
const __dirname = new URL(".", import.meta.url).pathname;
|
|
@@ -17,7 +20,7 @@ async function main() {
|
|
|
17
20
|
z.record(z.string()).parse(JSON.parse(process.env.LANGSERVE_GRAPHS)),
|
|
18
21
|
).filter(([_, spec]) => filterValidExportPath(spec));
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
let GRAPH_SCHEMAS: Record<string, Record<string, GraphSchema> | false> = {};
|
|
21
24
|
|
|
22
25
|
const semver = await checkLangGraphSemver();
|
|
23
26
|
const invalidPackages = semver.filter(
|
|
@@ -42,28 +45,42 @@ async function main() {
|
|
|
42
45
|
|
|
43
46
|
let failed = false;
|
|
44
47
|
try {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
console.info(`[${graphId}]: Extracting schema`);
|
|
54
|
-
GRAPH_SCHEMAS[graphId] = await getStaticGraphSchema(spec, {
|
|
55
|
-
timeoutMs: 120_000,
|
|
48
|
+
const resolveSpecs = Object.fromEntries<GraphSpec>(
|
|
49
|
+
await Promise.all(
|
|
50
|
+
specs.map(async ([graphId, rawSpec]) => {
|
|
51
|
+
console.info(`[${graphId}]: Checking for source file existence`);
|
|
52
|
+
const { resolved, ...spec } = await resolveGraph(rawSpec, {
|
|
53
|
+
onlyFilePresence: true,
|
|
56
54
|
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}),
|
|
55
|
+
|
|
56
|
+
return [graphId, spec] as [string, GraphSpec];
|
|
57
|
+
}),
|
|
58
|
+
),
|
|
62
59
|
);
|
|
63
60
|
|
|
61
|
+
try {
|
|
62
|
+
console.info("Extracting schemas");
|
|
63
|
+
GRAPH_SCHEMAS = await getStaticGraphSchema(resolveSpecs, {
|
|
64
|
+
timeoutMs: 120_000,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error(`Error extracting schema: ${error}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
64
70
|
await fs.writeFile(
|
|
65
71
|
path.resolve(__dirname, "client.schemas.json"),
|
|
66
|
-
JSON.stringify(
|
|
72
|
+
JSON.stringify(
|
|
73
|
+
Object.fromEntries(
|
|
74
|
+
specs.map(([graphId]) => {
|
|
75
|
+
const valid = GRAPH_SCHEMAS[graphId];
|
|
76
|
+
if (valid == null || Object.values(valid).every((x) => x == null)) {
|
|
77
|
+
return [graphId, false];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return [graphId, valid];
|
|
81
|
+
}),
|
|
82
|
+
),
|
|
83
|
+
),
|
|
67
84
|
{ encoding: "utf-8" },
|
|
68
85
|
);
|
|
69
86
|
} catch (error) {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"undici": "^6.21.1",
|
|
25
25
|
"uuid": "^10.0.0",
|
|
26
26
|
"winston": "^3.17.0",
|
|
27
|
-
"@langchain/langgraph-api": "~0.0.
|
|
28
|
-
"@langchain/langgraph-ui": "~0.0.
|
|
27
|
+
"@langchain/langgraph-api": "~0.0.37",
|
|
28
|
+
"@langchain/langgraph-ui": "~0.0.37",
|
|
29
29
|
"zod": "^3.23.8"
|
|
30
30
|
},
|
|
31
31
|
"resolutions": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"jose": "^6.0.10",
|
|
36
|
-
"@langchain/langgraph-sdk": "^0.0.
|
|
36
|
+
"@langchain/langgraph-sdk": "^0.0.77",
|
|
37
37
|
"@types/react": "^19.0.8",
|
|
38
38
|
"@types/react-dom": "^19.0.3",
|
|
39
39
|
"@types/node": "^22.2.0",
|
|
@@ -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.37":
|
|
207
|
+
version "0.0.37"
|
|
208
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-api/-/langgraph-api-0.0.37.tgz#52b3a62ac56dc56e239b76953ccc5b42a5aa1396"
|
|
209
|
+
integrity sha512-0mMmjA0KSYx/oKm6a+KSjWj7hneWsGlTDuwIaEnpauFLo5FCx3bZ8yQSPNFprvgHgJkxYWLjnVuXS+y/V1kLqg==
|
|
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.37"
|
|
215
215
|
"@types/json-schema" "^7.0.15"
|
|
216
216
|
"@typescript/vfs" "^1.6.0"
|
|
217
217
|
dedent "^1.5.3"
|
|
@@ -236,10 +236,10 @@
|
|
|
236
236
|
dependencies:
|
|
237
237
|
uuid "^10.0.0"
|
|
238
238
|
|
|
239
|
-
"@langchain/langgraph-sdk@^0.0.
|
|
240
|
-
version "0.0.
|
|
241
|
-
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.
|
|
242
|
-
integrity sha512-
|
|
239
|
+
"@langchain/langgraph-sdk@^0.0.77":
|
|
240
|
+
version "0.0.77"
|
|
241
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.77.tgz#adcd978843e61bbf09b9625d519dda16d27cec09"
|
|
242
|
+
integrity sha512-DMCONENhhaMS+Buw8s2UkKjAa9I6cT1aVJEDOmTO2lpon4Dqz/jiYUVJK7pTlNVSNvSx0E8aOmtT7NgGBcWflg==
|
|
243
243
|
dependencies:
|
|
244
244
|
"@types/json-schema" "^7.0.15"
|
|
245
245
|
p-queue "^6.6.2"
|
|
@@ -256,10 +256,10 @@
|
|
|
256
256
|
p-retry "4"
|
|
257
257
|
uuid "^9.0.0"
|
|
258
258
|
|
|
259
|
-
"@langchain/langgraph-ui@0.0.
|
|
260
|
-
version "0.0.
|
|
261
|
-
resolved "https://registry.yarnpkg.com/@langchain/langgraph-ui/-/langgraph-ui-0.0.
|
|
262
|
-
integrity sha512-
|
|
259
|
+
"@langchain/langgraph-ui@0.0.37", "@langchain/langgraph-ui@~0.0.37":
|
|
260
|
+
version "0.0.37"
|
|
261
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-ui/-/langgraph-ui-0.0.37.tgz#02bfdcc6ef1f518d3810afe298d6862d82100c58"
|
|
262
|
+
integrity sha512-eHsm+bjxXYzHsWa3WjlYiHd7a5PMaLgH1U0B5Ox+p43QnCE+mUCm82dWvvvXQ+FO/RktPk8kjbswwK/y/0Zk5A==
|
|
263
263
|
dependencies:
|
|
264
264
|
"@commander-js/extra-typings" "^13.0.0"
|
|
265
265
|
commander "^13.0.0"
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import os
|
|
3
|
-
from collections import defaultdict
|
|
4
3
|
from datetime import UTC, datetime
|
|
5
4
|
|
|
6
5
|
import langgraph.version
|
|
@@ -37,8 +36,8 @@ PLAN = "enterprise" if plus_features_enabled() else "developer"
|
|
|
37
36
|
USER_API_URL = os.getenv("LANGGRAPH_API_URL", None)
|
|
38
37
|
|
|
39
38
|
LOGS: list[dict] = []
|
|
40
|
-
RUN_COUNTER =
|
|
41
|
-
NODE_COUNTER =
|
|
39
|
+
RUN_COUNTER = 0
|
|
40
|
+
NODE_COUNTER = 0
|
|
42
41
|
FROM_TIMESTAMP = datetime.now(UTC).isoformat()
|
|
43
42
|
|
|
44
43
|
if (
|
|
@@ -50,12 +49,14 @@ else:
|
|
|
50
49
|
METADATA_ENDPOINT = "https://api.smith.langchain.com/v1/metadata/submit"
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
def incr_runs(*,
|
|
54
|
-
RUN_COUNTER
|
|
52
|
+
def incr_runs(*, incr: int = 1) -> None:
|
|
53
|
+
global RUN_COUNTER
|
|
54
|
+
RUN_COUNTER += incr
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def incr_nodes(
|
|
58
|
-
NODE_COUNTER
|
|
57
|
+
def incr_nodes(_, *, incr: int = 1) -> None:
|
|
58
|
+
global NODE_COUNTER
|
|
59
|
+
NODE_COUNTER += incr
|
|
59
60
|
|
|
60
61
|
|
|
61
62
|
def append_log(log: dict) -> None:
|
|
@@ -88,23 +89,13 @@ async def metadata_loop() -> None:
|
|
|
88
89
|
# we don't need a lock as long as there's no awaits in this block
|
|
89
90
|
from_timestamp = FROM_TIMESTAMP
|
|
90
91
|
to_timestamp = datetime.now(UTC).isoformat()
|
|
91
|
-
nodes = NODE_COUNTER
|
|
92
|
-
runs = RUN_COUNTER
|
|
92
|
+
nodes = NODE_COUNTER
|
|
93
|
+
runs = RUN_COUNTER
|
|
93
94
|
logs = LOGS.copy()
|
|
94
95
|
LOGS.clear()
|
|
95
|
-
RUN_COUNTER
|
|
96
|
-
NODE_COUNTER
|
|
96
|
+
RUN_COUNTER = 0
|
|
97
|
+
NODE_COUNTER = 0
|
|
97
98
|
FROM_TIMESTAMP = to_timestamp
|
|
98
|
-
graph_measures = {
|
|
99
|
-
f"langgraph.platform.graph_runs.{graph_id}": runs.get(graph_id, 0)
|
|
100
|
-
for graph_id in runs
|
|
101
|
-
}
|
|
102
|
-
graph_measures.update(
|
|
103
|
-
{
|
|
104
|
-
f"langgraph.platform.graph_nodes.{graph_id}": nodes.get(graph_id, 0)
|
|
105
|
-
for graph_id in nodes
|
|
106
|
-
}
|
|
107
|
-
)
|
|
108
99
|
|
|
109
100
|
payload = {
|
|
110
101
|
"license_key": LANGGRAPH_CLOUD_LICENSE_KEY,
|
|
@@ -129,9 +120,8 @@ async def metadata_loop() -> None:
|
|
|
129
120
|
"user_app.uses_store_ttl": str(USES_STORE_TTL),
|
|
130
121
|
},
|
|
131
122
|
"measures": {
|
|
132
|
-
"langgraph.platform.runs":
|
|
133
|
-
"langgraph.platform.nodes":
|
|
134
|
-
**graph_measures,
|
|
123
|
+
"langgraph.platform.runs": runs,
|
|
124
|
+
"langgraph.platform.nodes": nodes,
|
|
135
125
|
},
|
|
136
126
|
"logs": logs,
|
|
137
127
|
}
|
|
@@ -144,10 +134,8 @@ async def metadata_loop() -> None:
|
|
|
144
134
|
)
|
|
145
135
|
except Exception as e:
|
|
146
136
|
# retry on next iteration
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
for graph_id, incr in nodes.items():
|
|
150
|
-
incr_nodes(graph_id=graph_id, incr=incr)
|
|
137
|
+
incr_runs(incr=runs)
|
|
138
|
+
incr_nodes("", incr=nodes)
|
|
151
139
|
FROM_TIMESTAMP = from_timestamp
|
|
152
140
|
await logger.ainfo("Metadata submission skipped.", error=str(e))
|
|
153
141
|
await asyncio.sleep(INTERVAL)
|
|
@@ -77,6 +77,8 @@ class RunCreateDict(TypedDict):
|
|
|
77
77
|
"""
|
|
78
78
|
stream_subgraphs: bool | None
|
|
79
79
|
"""Stream output from subgraphs. By default, streams only the top graph."""
|
|
80
|
+
stream_resumable: bool | None
|
|
81
|
+
"""Whether to persist the stream chunks in order to resume the stream later."""
|
|
80
82
|
feedback_keys: list[str] | None
|
|
81
83
|
"""Pass one or more feedback_keys if you want to request short-lived signed URLs
|
|
82
84
|
for submitting feedback to LangSmith with this key for this run."""
|
|
@@ -305,6 +307,7 @@ async def create_valid_run(
|
|
|
305
307
|
"feedback_keys": payload.get("feedback_keys"),
|
|
306
308
|
"temporary": temporary,
|
|
307
309
|
"subgraphs": payload.get("stream_subgraphs", False),
|
|
310
|
+
"resumable": payload.get("stream_resumable", False),
|
|
308
311
|
"checkpoint_during": payload.get("checkpoint_during", True),
|
|
309
312
|
},
|
|
310
313
|
metadata=payload.get("metadata"),
|
|
@@ -18,7 +18,9 @@ logger = structlog.stdlib.get_logger(__name__)
|
|
|
18
18
|
class EventSourceResponse(sse_starlette.EventSourceResponse):
|
|
19
19
|
def __init__(
|
|
20
20
|
self,
|
|
21
|
-
content: AsyncIterator[
|
|
21
|
+
content: AsyncIterator[
|
|
22
|
+
bytes | tuple[bytes, Any | bytes] | tuple[bytes, Any | bytes, bytes | None]
|
|
23
|
+
],
|
|
22
24
|
status_code: int = 200,
|
|
23
25
|
headers: Mapping[str, str] | None = None,
|
|
24
26
|
) -> None:
|
|
@@ -101,11 +103,12 @@ async def sse_heartbeat(send: Send) -> None:
|
|
|
101
103
|
SEP = b"\r\n"
|
|
102
104
|
EVENT = b"event: "
|
|
103
105
|
DATA = b"data: "
|
|
106
|
+
ID = b"id: "
|
|
104
107
|
BYTES_LIKE = (bytes, bytearray, memoryview)
|
|
105
108
|
|
|
106
109
|
|
|
107
|
-
def json_to_sse(event: bytes, data: Any | bytes) -> bytes:
|
|
108
|
-
|
|
110
|
+
def json_to_sse(event: bytes, data: Any | bytes, id: bytes | None = None) -> bytes:
|
|
111
|
+
result = b"".join(
|
|
109
112
|
(
|
|
110
113
|
EVENT,
|
|
111
114
|
event,
|
|
@@ -113,6 +116,11 @@ def json_to_sse(event: bytes, data: Any | bytes) -> bytes:
|
|
|
113
116
|
DATA,
|
|
114
117
|
data if isinstance(data, BYTES_LIKE) else json_dumpb(data),
|
|
115
118
|
SEP,
|
|
116
|
-
SEP,
|
|
117
119
|
)
|
|
118
120
|
)
|
|
121
|
+
|
|
122
|
+
if id is not None:
|
|
123
|
+
result += b"".join((ID, id, SEP))
|
|
124
|
+
|
|
125
|
+
result += SEP
|
|
126
|
+
return result
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import functools
|
|
2
1
|
from collections.abc import AsyncIterator, Callable
|
|
3
2
|
from contextlib import AsyncExitStack, aclosing
|
|
3
|
+
from functools import lru_cache
|
|
4
4
|
from typing import Any, cast
|
|
5
5
|
|
|
6
6
|
import langgraph.version
|
|
@@ -87,6 +87,7 @@ async def astream_state(
|
|
|
87
87
|
# extract args from run
|
|
88
88
|
kwargs = run["kwargs"].copy()
|
|
89
89
|
kwargs.pop("webhook", None)
|
|
90
|
+
kwargs.pop("resumable", False)
|
|
90
91
|
subgraphs = kwargs.get("subgraphs", False)
|
|
91
92
|
temporary = kwargs.pop("temporary", False)
|
|
92
93
|
config = kwargs.pop("config")
|
|
@@ -119,9 +120,7 @@ async def astream_state(
|
|
|
119
120
|
# attach node counter
|
|
120
121
|
is_remote_pregel = isinstance(graph, BaseRemotePregel)
|
|
121
122
|
if not is_remote_pregel:
|
|
122
|
-
config["configurable"]["__pregel_node_finished"] =
|
|
123
|
-
incr_nodes, graph_id=_get_graph_id(run)
|
|
124
|
-
)
|
|
123
|
+
config["configurable"]["__pregel_node_finished"] = incr_nodes
|
|
125
124
|
|
|
126
125
|
# attach run_id to config
|
|
127
126
|
# for attempts beyond the first, use a fresh, unique run_id
|
|
@@ -265,10 +264,10 @@ async def astream_state(
|
|
|
265
264
|
yield mode, chunk
|
|
266
265
|
# --- end shared logic with astream_events ---
|
|
267
266
|
if is_remote_pregel:
|
|
268
|
-
#
|
|
267
|
+
# increament the remote runs
|
|
269
268
|
try:
|
|
270
269
|
nodes_executed = await graph.fetch_nodes_executed()
|
|
271
|
-
incr_nodes(
|
|
270
|
+
incr_nodes(None, incr=nodes_executed)
|
|
272
271
|
except Exception as e:
|
|
273
272
|
logger.warning(f"Failed to fetch nodes executed for {graph.graph_id}: {e}")
|
|
274
273
|
|
|
@@ -280,19 +279,25 @@ async def astream_state(
|
|
|
280
279
|
yield "feedback", feedback_urls
|
|
281
280
|
|
|
282
281
|
|
|
283
|
-
async def consume(stream: AnyStream, run_id: str) -> None:
|
|
282
|
+
async def consume(stream: AnyStream, run_id: str, resumable: bool = False) -> None:
|
|
284
283
|
async with aclosing(stream):
|
|
285
284
|
try:
|
|
286
285
|
async for mode, payload in stream:
|
|
287
286
|
await Runs.Stream.publish(
|
|
288
|
-
run_id,
|
|
287
|
+
run_id,
|
|
288
|
+
mode,
|
|
289
|
+
await run_in_executor(None, json_dumpb, payload),
|
|
290
|
+
resumable=resumable,
|
|
289
291
|
)
|
|
290
292
|
except Exception as e:
|
|
291
293
|
g = e
|
|
292
294
|
if isinstance(e, ExceptionGroup):
|
|
293
295
|
e = e.exceptions[0]
|
|
294
296
|
await Runs.Stream.publish(
|
|
295
|
-
run_id,
|
|
297
|
+
run_id,
|
|
298
|
+
"error",
|
|
299
|
+
await run_in_executor(None, json_dumpb, e),
|
|
300
|
+
resumable=resumable,
|
|
296
301
|
)
|
|
297
302
|
raise e from g
|
|
298
303
|
|
|
@@ -303,7 +308,7 @@ def get_feedback_urls(run_id: str, feedback_keys: list[str]) -> dict[str, str]:
|
|
|
303
308
|
return {key: token.url for key, token in zip(feedback_keys, tokens, strict=False)}
|
|
304
309
|
|
|
305
310
|
|
|
306
|
-
@
|
|
311
|
+
@lru_cache(maxsize=1)
|
|
307
312
|
def get_langsmith_client() -> langsmith.Client:
|
|
308
313
|
return langsmith.Client()
|
|
309
314
|
|
|
@@ -317,11 +322,3 @@ EXPECTED_ERRORS = (
|
|
|
317
322
|
ValidationError,
|
|
318
323
|
ValidationErrorLegacy,
|
|
319
324
|
)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
def _get_graph_id(run: Run) -> str | None:
|
|
323
|
-
try:
|
|
324
|
-
return run["kwargs"]["config"]["configurable"]["graph_id"]
|
|
325
|
-
except Exception:
|
|
326
|
-
logger.info(f"Failed to get graph_id from run {run['run_id']}")
|
|
327
|
-
return "Unknown"
|
|
@@ -69,7 +69,7 @@ async def worker(
|
|
|
69
69
|
) -> WorkerResult:
|
|
70
70
|
run_id = run["run_id"]
|
|
71
71
|
if attempt == 1:
|
|
72
|
-
incr_runs(
|
|
72
|
+
incr_runs()
|
|
73
73
|
checkpoint: CheckpointPayload | None = None
|
|
74
74
|
exception: Exception | None = None
|
|
75
75
|
status: str | None = None
|
|
@@ -83,8 +83,8 @@ async def worker(
|
|
|
83
83
|
Runs.enter(run_id, main_loop) as done,
|
|
84
84
|
):
|
|
85
85
|
temporary = run["kwargs"].get("temporary", False)
|
|
86
|
+
resumable = run["kwargs"].get("resumable", False)
|
|
86
87
|
run_created_at = run["created_at"].isoformat()
|
|
87
|
-
run["kwargs"]
|
|
88
88
|
lg_logging.set_logging_context(
|
|
89
89
|
{
|
|
90
90
|
"run_id": str(run_id),
|
|
@@ -145,7 +145,10 @@ async def worker(
|
|
|
145
145
|
on_checkpoint=on_checkpoint,
|
|
146
146
|
on_task_result=on_task_result,
|
|
147
147
|
)
|
|
148
|
-
await asyncio.wait_for(
|
|
148
|
+
await asyncio.wait_for(
|
|
149
|
+
consume(stream, run_id, resumable),
|
|
150
|
+
BG_JOB_TIMEOUT_SECS,
|
|
151
|
+
)
|
|
149
152
|
run_ended_at = datetime.now(UTC).isoformat()
|
|
150
153
|
await logger.ainfo(
|
|
151
154
|
"Background run succeeded",
|
|
@@ -886,73 +886,73 @@
|
|
|
886
886
|
}
|
|
887
887
|
}
|
|
888
888
|
},
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
},
|
|
908
|
-
{
|
|
909
|
-
"description": "The ID of the checkpoint.",
|
|
910
|
-
"required": true,
|
|
911
|
-
"schema": {
|
|
912
|
-
"type": "string",
|
|
913
|
-
"format": "uuid",
|
|
914
|
-
"title": "Checkpoint Id",
|
|
915
|
-
"description": "The ID of the checkpoint."
|
|
889
|
+
"/threads/{thread_id}/state/{checkpoint_id}": {
|
|
890
|
+
"get": {
|
|
891
|
+
"tags": ["Threads"],
|
|
892
|
+
"summary": "Get Thread State At Checkpoint",
|
|
893
|
+
"description": "Get state for a thread at a specific checkpoint.",
|
|
894
|
+
"operationId": "get_thread_state_at_checkpoint_threads__thread_id__state__checkpoint_id__get",
|
|
895
|
+
"parameters": [
|
|
896
|
+
{
|
|
897
|
+
"description": "The ID of the thread.",
|
|
898
|
+
"required": true,
|
|
899
|
+
"schema": {
|
|
900
|
+
"type": "string",
|
|
901
|
+
"format": "uuid",
|
|
902
|
+
"title": "Thread Id",
|
|
903
|
+
"description": "The ID of the thread."
|
|
904
|
+
},
|
|
905
|
+
"name": "thread_id",
|
|
906
|
+
"in": "path"
|
|
916
907
|
},
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
"
|
|
908
|
+
{
|
|
909
|
+
"description": "The ID of the checkpoint.",
|
|
910
|
+
"required": true,
|
|
911
|
+
"schema": {
|
|
912
|
+
"type": "string",
|
|
913
|
+
"format": "uuid",
|
|
914
|
+
"title": "Checkpoint Id",
|
|
915
|
+
"description": "The ID of the checkpoint."
|
|
916
|
+
},
|
|
917
|
+
"name": "checkpoint_id",
|
|
918
|
+
"in": "path"
|
|
927
919
|
},
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
"
|
|
937
|
-
|
|
938
|
-
|
|
920
|
+
{
|
|
921
|
+
"description": "Whether to include subgraphs in the response.",
|
|
922
|
+
"required": false,
|
|
923
|
+
"schema": {
|
|
924
|
+
"type": "boolean",
|
|
925
|
+
"title": "Subgraphs",
|
|
926
|
+
"description": "Whether to include subgraphs in the response."
|
|
927
|
+
},
|
|
928
|
+
"name": "subgraphs",
|
|
929
|
+
"in": "query"
|
|
930
|
+
}
|
|
931
|
+
],
|
|
932
|
+
"responses": {
|
|
933
|
+
"200": {
|
|
934
|
+
"description": "Success",
|
|
935
|
+
"content": {
|
|
936
|
+
"application/json": {
|
|
937
|
+
"schema": {
|
|
938
|
+
"$ref": "#/components/schemas/ThreadState"
|
|
939
|
+
}
|
|
939
940
|
}
|
|
940
941
|
}
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
942
|
+
},
|
|
943
|
+
"422": {
|
|
944
|
+
"description": "Validation Error",
|
|
945
|
+
"content": {
|
|
946
|
+
"application/json": {
|
|
947
|
+
"schema": {
|
|
948
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
949
|
+
}
|
|
949
950
|
}
|
|
950
951
|
}
|
|
951
952
|
}
|
|
952
953
|
}
|
|
953
954
|
}
|
|
954
|
-
}
|
|
955
|
-
},
|
|
955
|
+
},
|
|
956
956
|
"/threads/{thread_id}/state/checkpoint": {
|
|
957
957
|
"post": {
|
|
958
958
|
"tags": ["Threads"],
|
|
@@ -1483,6 +1483,14 @@
|
|
|
1483
1483
|
"$ref": "#/components/schemas/Run"
|
|
1484
1484
|
}
|
|
1485
1485
|
}
|
|
1486
|
+
},
|
|
1487
|
+
"headers": {
|
|
1488
|
+
"Content-Location": {
|
|
1489
|
+
"description": "The URL of the run that was created. Can be used to later join the stream.",
|
|
1490
|
+
"schema": {
|
|
1491
|
+
"type": "string"
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1486
1494
|
}
|
|
1487
1495
|
},
|
|
1488
1496
|
"404": {
|
|
@@ -1622,6 +1630,14 @@
|
|
|
1622
1630
|
"description": "The server will send a stream of events in SSE format.\n\n**Example event**:\n\nid: 1\n\nevent: message\n\ndata: {}"
|
|
1623
1631
|
}
|
|
1624
1632
|
}
|
|
1633
|
+
},
|
|
1634
|
+
"headers": {
|
|
1635
|
+
"Content-Location": {
|
|
1636
|
+
"description": "The URL of the run that was created. Can be used to later join the stream.",
|
|
1637
|
+
"schema": {
|
|
1638
|
+
"type": "string"
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1625
1641
|
}
|
|
1626
1642
|
},
|
|
1627
1643
|
"404": {
|
|
@@ -1694,6 +1710,14 @@
|
|
|
1694
1710
|
"application/json": {
|
|
1695
1711
|
"schema": {}
|
|
1696
1712
|
}
|
|
1713
|
+
},
|
|
1714
|
+
"headers": {
|
|
1715
|
+
"Content-Location": {
|
|
1716
|
+
"description": "The URL of the run that was created. Can be used to later join the stream.",
|
|
1717
|
+
"schema": {
|
|
1718
|
+
"type": "string"
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1697
1721
|
}
|
|
1698
1722
|
},
|
|
1699
1723
|
"404": {
|
|
@@ -1936,7 +1960,7 @@
|
|
|
1936
1960
|
"get": {
|
|
1937
1961
|
"tags": ["Thread Runs"],
|
|
1938
1962
|
"summary": "Join Run Stream",
|
|
1939
|
-
"description": "Join a run stream. This endpoint streams output in real-time from a run similar to the /threads/__THREAD_ID__/runs/stream endpoint.
|
|
1963
|
+
"description": "Join a run stream. This endpoint streams output in real-time from a run similar to the /threads/__THREAD_ID__/runs/stream endpoint. If the run has been created with `stream_resumable=true`, the stream can be resumed from the last seen event ID.",
|
|
1940
1964
|
"operationId": "stream_run_http_threads__thread_id__runs__run_id__join_get",
|
|
1941
1965
|
"parameters": [
|
|
1942
1966
|
{
|
|
@@ -1962,6 +1986,16 @@
|
|
|
1962
1986
|
},
|
|
1963
1987
|
"name": "run_id",
|
|
1964
1988
|
"in": "path"
|
|
1989
|
+
},
|
|
1990
|
+
{
|
|
1991
|
+
"required": false,
|
|
1992
|
+
"schema": {
|
|
1993
|
+
"type": "string",
|
|
1994
|
+
"title": "Last Event ID",
|
|
1995
|
+
"description": "The ID of the last event received. Set to -1 if you want to stream all events. Requires `stream_resumable=true` to be set when creating the run."
|
|
1996
|
+
},
|
|
1997
|
+
"name": "Last-Event-ID",
|
|
1998
|
+
"in": "header"
|
|
1965
1999
|
}
|
|
1966
2000
|
],
|
|
1967
2001
|
"responses": {
|
|
@@ -2204,6 +2238,14 @@
|
|
|
2204
2238
|
"description": "The server will send a stream of events in SSE format.\n\n**Example event**:\n\nid: 1\n\nevent: message\n\ndata: {}"
|
|
2205
2239
|
}
|
|
2206
2240
|
}
|
|
2241
|
+
},
|
|
2242
|
+
"headers": {
|
|
2243
|
+
"Content-Location": {
|
|
2244
|
+
"description": "The URL of the run that was created. Can be used to later join the stream.",
|
|
2245
|
+
"schema": {
|
|
2246
|
+
"type": "string"
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2207
2249
|
}
|
|
2208
2250
|
},
|
|
2209
2251
|
"404": {
|
|
@@ -2319,6 +2361,14 @@
|
|
|
2319
2361
|
"application/json": {
|
|
2320
2362
|
"schema": {}
|
|
2321
2363
|
}
|
|
2364
|
+
},
|
|
2365
|
+
"headers": {
|
|
2366
|
+
"Content-Location": {
|
|
2367
|
+
"description": "The URL of the run that was created. Can be used to later join the stream.",
|
|
2368
|
+
"schema": {
|
|
2369
|
+
"type": "string"
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2322
2372
|
}
|
|
2323
2373
|
},
|
|
2324
2374
|
"404": {
|
|
@@ -2377,6 +2427,14 @@
|
|
|
2377
2427
|
"application/json": {
|
|
2378
2428
|
"schema": {}
|
|
2379
2429
|
}
|
|
2430
|
+
},
|
|
2431
|
+
"headers": {
|
|
2432
|
+
"Content-Location": {
|
|
2433
|
+
"description": "The URL of the run that was created. Can be used to later join the stream.",
|
|
2434
|
+
"schema": {
|
|
2435
|
+
"type": "string"
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2380
2438
|
}
|
|
2381
2439
|
},
|
|
2382
2440
|
"404": {
|
|
@@ -3569,6 +3627,12 @@
|
|
|
3569
3627
|
"description": "Whether to stream output from subgraphs.",
|
|
3570
3628
|
"default": false
|
|
3571
3629
|
},
|
|
3630
|
+
"stream_resumable": {
|
|
3631
|
+
"type": "boolean",
|
|
3632
|
+
"title": "Stream Resumable",
|
|
3633
|
+
"description": "Whether to persist the stream chunks in order to resume the stream later.",
|
|
3634
|
+
"default": false
|
|
3635
|
+
},
|
|
3572
3636
|
"on_disconnect": {
|
|
3573
3637
|
"type": "string",
|
|
3574
3638
|
"enum": ["cancel", "continue"],
|
|
@@ -3791,6 +3855,12 @@
|
|
|
3791
3855
|
"description": "Whether to stream output from subgraphs.",
|
|
3792
3856
|
"default": false
|
|
3793
3857
|
},
|
|
3858
|
+
"stream_resumable": {
|
|
3859
|
+
"type": "boolean",
|
|
3860
|
+
"title": "Stream Resumable",
|
|
3861
|
+
"description": "Whether to persist the stream chunks in order to resume the stream later.",
|
|
3862
|
+
"default": false
|
|
3863
|
+
},
|
|
3794
3864
|
"on_completion": {
|
|
3795
3865
|
"type": "string",
|
|
3796
3866
|
"enum": ["delete", "keep"],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.30"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|