langgraph-api 0.2.132__tar.gz → 0.2.135__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.132 → langgraph_api-0.2.135}/Makefile +2 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/PKG-INFO +2 -2
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/Makefile +8 -0
- langgraph_api-0.2.135/benchmark/clean.js +87 -0
- langgraph_api-0.2.135/benchmark/update-revision.js +148 -0
- langgraph_api-0.2.135/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/assistants.py +26 -1
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/runs.py +38 -1
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/threads.py +27 -1
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/package.json +2 -2
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/yarn.lock +9 -9
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/route.py +2 -1
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/schema.py +70 -5
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/utils/__init__.py +19 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/validation.py +9 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/openapi.json +331 -1
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/pyproject.toml +1 -1
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/uv.lock +76 -61
- langgraph_api-0.2.132/langgraph_api/__init__.py +0 -1
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/.gitignore +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/LICENSE +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/README.md +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/.gitignore +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/README.md +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/burst.js +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/graphs.js +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/package.json +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/ramp.js +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/benchmark/weather.js +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/constraints.txt +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/forbidden.txt +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/healthcheck.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/mcp.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/command.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/config.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/executor_entrypoint.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/http.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/server.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/state.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/store.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/thread_ttl.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/utils.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/logging.json +0 -0
- {langgraph_api-0.2.132 → langgraph_api-0.2.135}/scripts/create_license.py +0 -0
|
@@ -41,6 +41,8 @@ test-watch-oss:
|
|
|
41
41
|
|
|
42
42
|
test: test-license-oss
|
|
43
43
|
test-watch: test-watch-oss
|
|
44
|
+
unit-test:
|
|
45
|
+
DATABASE_URI="test" REDIS_URI="test" uv run pytest tests/unit_tests
|
|
44
46
|
|
|
45
47
|
test-auth:
|
|
46
48
|
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_AUTH='{"path": "./tests/graphs/fastapi_jwt_auth.py:get_current_active_user"}' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run pytest -v $(AUTH_TEST)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.135
|
|
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.3.64
|
|
13
13
|
Requires-Dist: langgraph-checkpoint>=2.0.23
|
|
14
|
-
Requires-Dist: langgraph-runtime-inmem<0.
|
|
14
|
+
Requires-Dist: langgraph-runtime-inmem<0.9.0,>=0.8.0
|
|
15
15
|
Requires-Dist: langgraph-sdk>=0.2.0
|
|
16
16
|
Requires-Dist: langgraph>=0.4.0
|
|
17
17
|
Requires-Dist: langsmith>=0.3.45
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
# Benchmark commands
|
|
2
2
|
benchmark-burst:
|
|
3
|
+
make benchmark-reset
|
|
3
4
|
k6 run burst.js
|
|
4
5
|
|
|
5
6
|
benchmark-ramp:
|
|
7
|
+
make benchmark-reset
|
|
6
8
|
k6 run --out json=raw_data_$(shell date +%Y-%m-%dT%H-%M-%S).json ramp.js
|
|
7
9
|
|
|
8
10
|
benchmark-charts:
|
|
9
11
|
npm install
|
|
10
12
|
node graphs.js $(shell ls -t raw_data_*.json | head -1) true
|
|
11
13
|
|
|
14
|
+
benchmark-reset:
|
|
15
|
+
node clean.js
|
|
16
|
+
|
|
17
|
+
benchmark-new-revision:
|
|
18
|
+
node update-revision.js
|
|
19
|
+
|
|
12
20
|
benchmark-clean:
|
|
13
21
|
rm -f results_*.json summary_*.json raw_data_*.json *_chart_*.png
|
|
14
22
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Delete all threads and runs from the last benchmark run for consistent tests
|
|
3
|
+
* The default benchmark server has a thread TTL of one hour that should clean things up too so this doesn't run too long.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// URL of your LangGraph server
|
|
7
|
+
const BASE_URL = process.env.BASE_URL || 'http://localhost:9123';
|
|
8
|
+
// LangSmith API key only needed with a custom server endpoint
|
|
9
|
+
const LANGSMITH_API_KEY = process.env.LANGSMITH_API_KEY;
|
|
10
|
+
|
|
11
|
+
async function clean() {
|
|
12
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
13
|
+
if (LANGSMITH_API_KEY) {
|
|
14
|
+
headers['x-api-key'] = LANGSMITH_API_KEY;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const searchUrl = `${BASE_URL}/threads/search`;
|
|
18
|
+
let totalDeleted = 0;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
console.log('Starting thread cleanup...');
|
|
22
|
+
|
|
23
|
+
while (true) {
|
|
24
|
+
try {
|
|
25
|
+
// Get the next page of threads
|
|
26
|
+
console.log('Searching for threads...');
|
|
27
|
+
const searchResponse = await fetch(searchUrl, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers,
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
limit: 1000
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (!searchResponse.ok) {
|
|
36
|
+
throw new Error(`Search request failed: ${searchResponse.status} ${searchResponse.statusText}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const threads = await searchResponse.json();
|
|
40
|
+
|
|
41
|
+
// If no threads found, we're done
|
|
42
|
+
if (!threads || threads.length === 0) {
|
|
43
|
+
console.log('No more threads found.');
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(`Found ${threads.length} threads to delete`);
|
|
48
|
+
|
|
49
|
+
// Delete each thread
|
|
50
|
+
for (const thread of threads) {
|
|
51
|
+
try {
|
|
52
|
+
const deleteUrl = `${BASE_URL}/threads/${thread.thread_id}`;
|
|
53
|
+
const deleteResponse = await fetch(deleteUrl, {
|
|
54
|
+
method: 'DELETE',
|
|
55
|
+
headers
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (!deleteResponse.ok) {
|
|
59
|
+
console.error(`Failed to delete thread ${thread.thread_id}: ${deleteResponse.status} ${deleteResponse.statusText}`);
|
|
60
|
+
} else {
|
|
61
|
+
totalDeleted++;
|
|
62
|
+
}
|
|
63
|
+
} catch (deleteError) {
|
|
64
|
+
console.error(`Error deleting thread ${thread.thread_id}:`, deleteError.message);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log(`Deleted ${threads.length} threads in this batch`);
|
|
69
|
+
|
|
70
|
+
} catch (batchError) {
|
|
71
|
+
console.error('Error in batch processing:', batchError.message);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(`Cleanup completed. Total threads deleted: ${totalDeleted}`);
|
|
77
|
+
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error('Fatal error during cleanup:', error.message);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
clean().catch(error => {
|
|
85
|
+
console.error('Unhandled error:', error.message);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Trigger a new revision deployment and wait for it to complete
|
|
3
|
+
* This ensures the benchmark instance is running the latest code
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// LangSmith API endpoints and credentials
|
|
7
|
+
const DEPLOYMENT_ID = process.env.DEPLOYMENT_ID || 'a23f03ff-6d4d-4efd-8149-bb5a7f3b95cf'; // jdr-benchmark deployment id
|
|
8
|
+
const LANGSMITH_API_KEY = process.env.LANGSMITH_API_KEY;
|
|
9
|
+
const API_BASE = 'https://api.host.langchain.com/v1';
|
|
10
|
+
|
|
11
|
+
// Deployment configuration
|
|
12
|
+
const REVISION_CONFIG = {
|
|
13
|
+
repo_path: "langgraph.json",
|
|
14
|
+
env_vars: [
|
|
15
|
+
{
|
|
16
|
+
name: "N_JOBS_PER_WORKER",
|
|
17
|
+
value: "100",
|
|
18
|
+
value_from: "secret",
|
|
19
|
+
type: "secret"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
shareable: false,
|
|
23
|
+
container_spec: {
|
|
24
|
+
cpu: null,
|
|
25
|
+
memory_mb: null,
|
|
26
|
+
min_scale: 10,
|
|
27
|
+
max_scale: null
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Expected deployment statuses in order
|
|
32
|
+
const EXPECTED_STATUSES = ['CREATED', 'AWAITING_BUILD', 'BUILDING', 'AWAITING_DEPLOY', 'DEPLOYING', 'DEPLOYED', 'QUEUED'];
|
|
33
|
+
const FINAL_STATUS = 'DEPLOYED';
|
|
34
|
+
const POLL_INTERVAL = 10000; // 10 seconds
|
|
35
|
+
const MAX_WAIT_TIME = 30 * 60 * 1000; // 30 minutes
|
|
36
|
+
|
|
37
|
+
async function updateRevision() {
|
|
38
|
+
if (!LANGSMITH_API_KEY) {
|
|
39
|
+
console.error('LANGSMITH_API_KEY environment variable is required');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const headers = {
|
|
44
|
+
'Content-Type': 'application/json',
|
|
45
|
+
'x-api-key': LANGSMITH_API_KEY
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const createUrl = `${API_BASE}/projects/${DEPLOYMENT_ID}/revisions`;
|
|
49
|
+
const pollUrl = `${API_BASE}/projects/${DEPLOYMENT_ID}/revisions?limit=1&offset=0`;
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
console.log('Triggering new revision deployment...');
|
|
53
|
+
|
|
54
|
+
// Step 1: Create new revision
|
|
55
|
+
const createResponse = await fetch(createUrl, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers,
|
|
58
|
+
body: JSON.stringify(REVISION_CONFIG)
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (createResponse.status === 409) {
|
|
62
|
+
console.log('⚠️ A new revision is already in progress. Continuing to poll existing deployment...');
|
|
63
|
+
} else if (!createResponse.ok) {
|
|
64
|
+
throw new Error(`Failed to create revision: ${createResponse.status} ${createResponse.statusText}`);
|
|
65
|
+
} else {
|
|
66
|
+
const newRevision = await createResponse.json();
|
|
67
|
+
const revisionId = newRevision.resource.latest_revision.hosted_langserve_revision_id;
|
|
68
|
+
console.log(`✓ New revision created: ${revisionId}`);
|
|
69
|
+
console.log(`Initial status: ${newRevision.status}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Step 2: Poll until deployment is complete
|
|
73
|
+
console.log('\nPolling deployment status...');
|
|
74
|
+
const startTime = Date.now();
|
|
75
|
+
let lastStatus = null;
|
|
76
|
+
|
|
77
|
+
while (true) {
|
|
78
|
+
let pollResponse;
|
|
79
|
+
try {
|
|
80
|
+
pollResponse = await fetch(pollUrl, {
|
|
81
|
+
method: 'GET',
|
|
82
|
+
headers
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (!pollResponse.ok) {
|
|
86
|
+
throw new Error(`Failed to poll revisions: ${pollResponse.status} ${pollResponse.statusText}`);
|
|
87
|
+
}
|
|
88
|
+
} catch (pollError) {
|
|
89
|
+
console.error('Error calling poll endpoint (will retry):', pollError.message);
|
|
90
|
+
// Wait before next poll and continue
|
|
91
|
+
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL));
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Parse response and handle deployment logic (these errors should still be thrown)
|
|
96
|
+
const revisions = await pollResponse.json();
|
|
97
|
+
|
|
98
|
+
if (!revisions || revisions.length === 0) {
|
|
99
|
+
throw new Error('No revisions found');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const latestRevision = revisions[0];
|
|
103
|
+
const currentStatus = latestRevision.status;
|
|
104
|
+
|
|
105
|
+
// Log status changes
|
|
106
|
+
if (currentStatus !== lastStatus) {
|
|
107
|
+
const timestamp = new Date().toISOString();
|
|
108
|
+
console.log(`[${timestamp}] Status: ${currentStatus}`);
|
|
109
|
+
|
|
110
|
+
if (latestRevision.status_message) {
|
|
111
|
+
console.log(` Message: ${latestRevision.status_message}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
lastStatus = currentStatus;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Check if deployment is complete
|
|
118
|
+
if (currentStatus === FINAL_STATUS) {
|
|
119
|
+
console.log(`\n✓ Deployment completed successfully!`);
|
|
120
|
+
console.log(`Revision ID: ${latestRevision.id}`);
|
|
121
|
+
console.log(`Total time: ${Math.round((Date.now() - startTime) / 1000)}s`);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Check for failure statuses
|
|
126
|
+
if (!EXPECTED_STATUSES.includes(currentStatus)) {
|
|
127
|
+
throw new Error(`Deployment failed with status: ${currentStatus}${latestRevision.status_message ? ` - ${latestRevision.status_message}` : ''}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Check timeout
|
|
131
|
+
if (Date.now() - startTime > MAX_WAIT_TIME) {
|
|
132
|
+
throw new Error(`Deployment timeout after ${MAX_WAIT_TIME / 60000} minutes. Last status: ${currentStatus}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Wait before next poll
|
|
136
|
+
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error('Fatal error during revision update:', error.message);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
updateRevision().catch(error => {
|
|
146
|
+
console.error('Unhandled error:', error.message);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.135"
|
|
@@ -16,9 +16,16 @@ from langgraph_api.feature_flags import USE_RUNTIME_CONTEXT_API
|
|
|
16
16
|
from langgraph_api.graph import get_assistant_id, get_graph
|
|
17
17
|
from langgraph_api.js.base import BaseRemotePregel
|
|
18
18
|
from langgraph_api.route import ApiRequest, ApiResponse, ApiRoute
|
|
19
|
+
from langgraph_api.schema import ASSISTANT_FIELDS
|
|
19
20
|
from langgraph_api.serde import ajson_loads
|
|
20
|
-
from langgraph_api.utils import
|
|
21
|
+
from langgraph_api.utils import (
|
|
22
|
+
fetchone,
|
|
23
|
+
get_pagination_headers,
|
|
24
|
+
validate_select_columns,
|
|
25
|
+
validate_uuid,
|
|
26
|
+
)
|
|
21
27
|
from langgraph_api.validation import (
|
|
28
|
+
AssistantCountRequest,
|
|
22
29
|
AssistantCreate,
|
|
23
30
|
AssistantPatch,
|
|
24
31
|
AssistantSearchRequest,
|
|
@@ -173,6 +180,7 @@ async def search_assistants(
|
|
|
173
180
|
) -> ApiResponse:
|
|
174
181
|
"""List assistants."""
|
|
175
182
|
payload = await request.json(AssistantSearchRequest)
|
|
183
|
+
select = validate_select_columns(payload.get("select") or None, ASSISTANT_FIELDS)
|
|
176
184
|
offset = int(payload.get("offset") or 0)
|
|
177
185
|
async with connect() as conn:
|
|
178
186
|
assistants_iter, next_offset = await Assistants.search(
|
|
@@ -183,6 +191,7 @@ async def search_assistants(
|
|
|
183
191
|
offset=offset,
|
|
184
192
|
sort_by=payload.get("sort_by"),
|
|
185
193
|
sort_order=payload.get("sort_order"),
|
|
194
|
+
select=select,
|
|
186
195
|
)
|
|
187
196
|
assistants, response_headers = await get_pagination_headers(
|
|
188
197
|
assistants_iter, next_offset, offset
|
|
@@ -190,6 +199,21 @@ async def search_assistants(
|
|
|
190
199
|
return ApiResponse(assistants, headers=response_headers)
|
|
191
200
|
|
|
192
201
|
|
|
202
|
+
@retry_db
|
|
203
|
+
async def count_assistants(
|
|
204
|
+
request: ApiRequest,
|
|
205
|
+
) -> ApiResponse:
|
|
206
|
+
"""Count assistants."""
|
|
207
|
+
payload = await request.json(AssistantCountRequest)
|
|
208
|
+
async with connect() as conn:
|
|
209
|
+
count = await Assistants.count(
|
|
210
|
+
conn,
|
|
211
|
+
graph_id=payload.get("graph_id"),
|
|
212
|
+
metadata=payload.get("metadata"),
|
|
213
|
+
)
|
|
214
|
+
return ApiResponse(count)
|
|
215
|
+
|
|
216
|
+
|
|
193
217
|
@retry_db
|
|
194
218
|
async def get_assistant(
|
|
195
219
|
request: ApiRequest,
|
|
@@ -415,6 +439,7 @@ async def set_latest_assistant_version(request: ApiRequest) -> ApiResponse:
|
|
|
415
439
|
assistants_routes: list[BaseRoute] = [
|
|
416
440
|
ApiRoute("/assistants", create_assistant, methods=["POST"]),
|
|
417
441
|
ApiRoute("/assistants/search", search_assistants, methods=["POST"]),
|
|
442
|
+
ApiRoute("/assistants/count", count_assistants, methods=["POST"]),
|
|
418
443
|
ApiRoute(
|
|
419
444
|
"/assistants/{assistant_id}/latest",
|
|
420
445
|
set_latest_assistant_version,
|
|
@@ -10,9 +10,17 @@ from langgraph_api import config
|
|
|
10
10
|
from langgraph_api.asyncio import ValueEvent, aclosing
|
|
11
11
|
from langgraph_api.models.run import create_valid_run
|
|
12
12
|
from langgraph_api.route import ApiRequest, ApiResponse, ApiRoute
|
|
13
|
+
from langgraph_api.schema import CRON_FIELDS, RUN_FIELDS
|
|
13
14
|
from langgraph_api.sse import EventSourceResponse
|
|
14
|
-
from langgraph_api.utils import
|
|
15
|
+
from langgraph_api.utils import (
|
|
16
|
+
fetchone,
|
|
17
|
+
get_pagination_headers,
|
|
18
|
+
uuid7,
|
|
19
|
+
validate_select_columns,
|
|
20
|
+
validate_uuid,
|
|
21
|
+
)
|
|
15
22
|
from langgraph_api.validation import (
|
|
23
|
+
CronCountRequest,
|
|
16
24
|
CronCreate,
|
|
17
25
|
CronSearch,
|
|
18
26
|
RunBatchCreate,
|
|
@@ -337,6 +345,9 @@ async def list_runs(
|
|
|
337
345
|
limit = int(request.query_params.get("limit", 10))
|
|
338
346
|
offset = int(request.query_params.get("offset", 0))
|
|
339
347
|
status = request.query_params.get("status")
|
|
348
|
+
select = validate_select_columns(
|
|
349
|
+
request.query_params.getlist("select") or None, RUN_FIELDS
|
|
350
|
+
)
|
|
340
351
|
|
|
341
352
|
async with connect() as conn, conn.pipeline():
|
|
342
353
|
thread, runs = await asyncio.gather(
|
|
@@ -347,6 +358,7 @@ async def list_runs(
|
|
|
347
358
|
limit=limit,
|
|
348
359
|
offset=offset,
|
|
349
360
|
status=status,
|
|
361
|
+
select=select,
|
|
350
362
|
),
|
|
351
363
|
)
|
|
352
364
|
await fetchone(thread)
|
|
@@ -560,6 +572,7 @@ async def delete_cron(request: ApiRequest):
|
|
|
560
572
|
async def search_crons(request: ApiRequest):
|
|
561
573
|
"""List all cron jobs for an assistant"""
|
|
562
574
|
payload = await request.json(CronSearch)
|
|
575
|
+
select = validate_select_columns(payload.get("select") or None, CRON_FIELDS)
|
|
563
576
|
if assistant_id := payload.get("assistant_id"):
|
|
564
577
|
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
565
578
|
if thread_id := payload.get("thread_id"):
|
|
@@ -575,6 +588,7 @@ async def search_crons(request: ApiRequest):
|
|
|
575
588
|
offset=offset,
|
|
576
589
|
sort_by=payload.get("sort_by"),
|
|
577
590
|
sort_order=payload.get("sort_order"),
|
|
591
|
+
select=select,
|
|
578
592
|
)
|
|
579
593
|
crons, response_headers = await get_pagination_headers(
|
|
580
594
|
crons_iter, next_offset, offset
|
|
@@ -582,6 +596,24 @@ async def search_crons(request: ApiRequest):
|
|
|
582
596
|
return ApiResponse(crons, headers=response_headers)
|
|
583
597
|
|
|
584
598
|
|
|
599
|
+
@retry_db
|
|
600
|
+
async def count_crons(request: ApiRequest):
|
|
601
|
+
"""Count cron jobs."""
|
|
602
|
+
payload = await request.json(CronCountRequest)
|
|
603
|
+
if assistant_id := payload.get("assistant_id"):
|
|
604
|
+
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
605
|
+
if thread_id := payload.get("thread_id"):
|
|
606
|
+
validate_uuid(thread_id, "Invalid thread ID: must be a UUID")
|
|
607
|
+
|
|
608
|
+
async with connect() as conn:
|
|
609
|
+
count = await Crons.count(
|
|
610
|
+
conn,
|
|
611
|
+
assistant_id=assistant_id,
|
|
612
|
+
thread_id=thread_id,
|
|
613
|
+
)
|
|
614
|
+
return ApiResponse(count)
|
|
615
|
+
|
|
616
|
+
|
|
585
617
|
runs_routes = [
|
|
586
618
|
ApiRoute("/runs/stream", stream_run_stateless, methods=["POST"]),
|
|
587
619
|
ApiRoute("/runs/wait", wait_run_stateless, methods=["POST"]),
|
|
@@ -598,6 +630,11 @@ runs_routes = [
|
|
|
598
630
|
if config.FF_CRONS_ENABLED and plus_features_enabled()
|
|
599
631
|
else None
|
|
600
632
|
),
|
|
633
|
+
(
|
|
634
|
+
ApiRoute("/runs/crons/count", count_crons, methods=["POST"])
|
|
635
|
+
if config.FF_CRONS_ENABLED and plus_features_enabled()
|
|
636
|
+
else None
|
|
637
|
+
),
|
|
601
638
|
ApiRoute("/threads/{thread_id}/runs/{run_id}/join", join_run, methods=["GET"]),
|
|
602
639
|
ApiRoute(
|
|
603
640
|
"/threads/{thread_id}/runs/{run_id}/stream",
|
|
@@ -5,9 +5,16 @@ from starlette.responses import Response
|
|
|
5
5
|
from starlette.routing import BaseRoute
|
|
6
6
|
|
|
7
7
|
from langgraph_api.route import ApiRequest, ApiResponse, ApiRoute
|
|
8
|
+
from langgraph_api.schema import THREAD_FIELDS
|
|
8
9
|
from langgraph_api.state import state_snapshot_to_thread_state
|
|
9
|
-
from langgraph_api.utils import
|
|
10
|
+
from langgraph_api.utils import (
|
|
11
|
+
fetchone,
|
|
12
|
+
get_pagination_headers,
|
|
13
|
+
validate_select_columns,
|
|
14
|
+
validate_uuid,
|
|
15
|
+
)
|
|
10
16
|
from langgraph_api.validation import (
|
|
17
|
+
ThreadCountRequest,
|
|
11
18
|
ThreadCreate,
|
|
12
19
|
ThreadPatch,
|
|
13
20
|
ThreadSearchRequest,
|
|
@@ -58,6 +65,7 @@ async def search_threads(
|
|
|
58
65
|
):
|
|
59
66
|
"""List threads."""
|
|
60
67
|
payload = await request.json(ThreadSearchRequest)
|
|
68
|
+
select = validate_select_columns(payload.get("select") or None, THREAD_FIELDS)
|
|
61
69
|
limit = int(payload.get("limit") or 10)
|
|
62
70
|
offset = int(payload.get("offset") or 0)
|
|
63
71
|
async with connect() as conn:
|
|
@@ -70,6 +78,7 @@ async def search_threads(
|
|
|
70
78
|
offset=offset,
|
|
71
79
|
sort_by=payload.get("sort_by"),
|
|
72
80
|
sort_order=payload.get("sort_order"),
|
|
81
|
+
select=select,
|
|
73
82
|
)
|
|
74
83
|
threads, response_headers = await get_pagination_headers(
|
|
75
84
|
threads_iter, next_offset, offset
|
|
@@ -77,6 +86,22 @@ async def search_threads(
|
|
|
77
86
|
return ApiResponse(threads, headers=response_headers)
|
|
78
87
|
|
|
79
88
|
|
|
89
|
+
@retry_db
|
|
90
|
+
async def count_threads(
|
|
91
|
+
request: ApiRequest,
|
|
92
|
+
):
|
|
93
|
+
"""Count threads."""
|
|
94
|
+
payload = await request.json(ThreadCountRequest)
|
|
95
|
+
async with connect() as conn:
|
|
96
|
+
count = await Threads.count(
|
|
97
|
+
conn,
|
|
98
|
+
status=payload.get("status"),
|
|
99
|
+
values=payload.get("values"),
|
|
100
|
+
metadata=payload.get("metadata"),
|
|
101
|
+
)
|
|
102
|
+
return ApiResponse(count)
|
|
103
|
+
|
|
104
|
+
|
|
80
105
|
@retry_db
|
|
81
106
|
async def get_thread_state(
|
|
82
107
|
request: ApiRequest,
|
|
@@ -260,6 +285,7 @@ async def copy_thread(request: ApiRequest):
|
|
|
260
285
|
threads_routes: list[BaseRoute] = [
|
|
261
286
|
ApiRoute("/threads", endpoint=create_thread, methods=["POST"]),
|
|
262
287
|
ApiRoute("/threads/search", endpoint=search_threads, methods=["POST"]),
|
|
288
|
+
ApiRoute("/threads/count", endpoint=count_threads, methods=["POST"]),
|
|
263
289
|
ApiRoute("/threads/{thread_id}", endpoint=get_thread, methods=["GET"]),
|
|
264
290
|
ApiRoute("/threads/{thread_id}", endpoint=patch_thread, methods=["PATCH"]),
|
|
265
291
|
ApiRoute("/threads/{thread_id}", endpoint=delete_thread, methods=["DELETE"]),
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"@hono/zod-validator": "^0.2.2",
|
|
12
12
|
"@langchain/core": "^0.3.59",
|
|
13
13
|
"@langchain/langgraph": "^0.2.65",
|
|
14
|
-
"@langchain/langgraph-api": "~0.0.
|
|
15
|
-
"@langchain/langgraph-ui": "~0.0.
|
|
14
|
+
"@langchain/langgraph-api": "~0.0.59",
|
|
15
|
+
"@langchain/langgraph-ui": "~0.0.59",
|
|
16
16
|
"@langchain/langgraph-checkpoint": "~0.0.18",
|
|
17
17
|
"@types/json-schema": "^7.0.15",
|
|
18
18
|
"@typescript/vfs": "^1.6.0",
|
|
@@ -203,15 +203,15 @@
|
|
|
203
203
|
zod "^3.25.32"
|
|
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.59":
|
|
207
|
+
version "0.0.59"
|
|
208
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-api/-/langgraph-api-0.0.59.tgz#a3d69b8cc68ceebd8a8d86b77abd03924ddcd02c"
|
|
209
|
+
integrity sha512-pUt3yKB2z1nsXdhqpRQgVefYg5MdJVsqH64gTNzSb/JYJBPIUj2h8XttRx9+3mHtVqCzvL2bb+HVIterNFOKtw==
|
|
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.59"
|
|
215
215
|
"@types/json-schema" "^7.0.15"
|
|
216
216
|
"@typescript/vfs" "^1.6.0"
|
|
217
217
|
dedent "^1.5.3"
|
|
@@ -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.59", "@langchain/langgraph-ui@~0.0.59":
|
|
260
|
+
version "0.0.59"
|
|
261
|
+
resolved "https://registry.yarnpkg.com/@langchain/langgraph-ui/-/langgraph-ui-0.0.59.tgz#41988eae48c7520c5ebfa9bcdda65ddadfe1aab9"
|
|
262
|
+
integrity sha512-x6Jqt7TZRfHGU0MyxVbz7ugucT/oJQm9kM+DlGdmfAEm2JrNqgy1W85E589xJCJjpuRiDLpP7NiqSwnp8lCEqg==
|
|
263
263
|
dependencies:
|
|
264
264
|
"@commander-js/extra-typings" "^13.0.0"
|
|
265
265
|
commander "^13.0.0"
|
|
@@ -97,7 +97,8 @@ class ApiRoute(Route):
|
|
|
97
97
|
include_in_schema: bool = True,
|
|
98
98
|
middleware: typing.Sequence[Middleware] | None = None,
|
|
99
99
|
) -> None:
|
|
100
|
-
|
|
100
|
+
if not path.startswith("/"):
|
|
101
|
+
raise ValueError("Routed paths must start with '/'")
|
|
101
102
|
self.path = path
|
|
102
103
|
self.endpoint = endpoint
|
|
103
104
|
self.name = get_name(endpoint) if name is None else name
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Sequence
|
|
2
2
|
from datetime import datetime
|
|
3
|
-
from typing import Any, Literal, Optional, TypeAlias
|
|
3
|
+
from typing import Any, Literal, NotRequired, Optional, TypeAlias
|
|
4
4
|
from uuid import UUID
|
|
5
5
|
|
|
6
6
|
from langchain_core.runnables.config import RunnableConfig
|
|
@@ -121,6 +121,8 @@ class Thread(TypedDict):
|
|
|
121
121
|
"""The thread metadata."""
|
|
122
122
|
config: Fragment
|
|
123
123
|
"""The thread config."""
|
|
124
|
+
context: Fragment
|
|
125
|
+
"""The thread context."""
|
|
124
126
|
status: ThreadStatus
|
|
125
127
|
"""The status of the thread. One of 'idle', 'busy', 'interrupted', "error"."""
|
|
126
128
|
values: Fragment
|
|
@@ -223,16 +225,16 @@ class Cron(TypedDict):
|
|
|
223
225
|
"""The time the cron was created."""
|
|
224
226
|
updated_at: datetime
|
|
225
227
|
"""The last time the cron was updated."""
|
|
226
|
-
user_id:
|
|
227
|
-
"""The ID of the user."""
|
|
228
|
+
user_id: str | None
|
|
229
|
+
"""The ID of the user (string identity)."""
|
|
228
230
|
payload: Fragment
|
|
229
231
|
"""The run payload to use for creating new run."""
|
|
230
232
|
next_run_date: datetime
|
|
231
233
|
"""The next run date of the cron."""
|
|
232
234
|
metadata: Fragment
|
|
233
235
|
"""The cron metadata."""
|
|
234
|
-
now: datetime
|
|
235
|
-
"""The current time."""
|
|
236
|
+
now: NotRequired[datetime]
|
|
237
|
+
"""The current time (present in internal next() only)."""
|
|
236
238
|
|
|
237
239
|
|
|
238
240
|
class ThreadUpdateResponse(TypedDict):
|
|
@@ -246,3 +248,66 @@ class QueueStats(TypedDict):
|
|
|
246
248
|
n_running: int
|
|
247
249
|
max_age_secs: datetime | None
|
|
248
250
|
med_age_secs: datetime | None
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# Canonical field sets for select= validation and type aliases for ops
|
|
254
|
+
|
|
255
|
+
# Assistant select fields (intentionally excludes 'context')
|
|
256
|
+
AssistantSelectField = Literal[
|
|
257
|
+
"assistant_id",
|
|
258
|
+
"graph_id",
|
|
259
|
+
"name",
|
|
260
|
+
"description",
|
|
261
|
+
"config",
|
|
262
|
+
"context",
|
|
263
|
+
"created_at",
|
|
264
|
+
"updated_at",
|
|
265
|
+
"metadata",
|
|
266
|
+
"version",
|
|
267
|
+
]
|
|
268
|
+
ASSISTANT_FIELDS: set[str] = set(AssistantSelectField.__args__) # type: ignore[attr-defined]
|
|
269
|
+
|
|
270
|
+
# Thread select fields
|
|
271
|
+
ThreadSelectField = Literal[
|
|
272
|
+
"thread_id",
|
|
273
|
+
"created_at",
|
|
274
|
+
"updated_at",
|
|
275
|
+
"metadata",
|
|
276
|
+
"config",
|
|
277
|
+
"context",
|
|
278
|
+
"status",
|
|
279
|
+
"values",
|
|
280
|
+
"interrupts",
|
|
281
|
+
]
|
|
282
|
+
THREAD_FIELDS: set[str] = set(ThreadSelectField.__args__) # type: ignore[attr-defined]
|
|
283
|
+
|
|
284
|
+
# Run select fields
|
|
285
|
+
RunSelectField = Literal[
|
|
286
|
+
"run_id",
|
|
287
|
+
"thread_id",
|
|
288
|
+
"assistant_id",
|
|
289
|
+
"created_at",
|
|
290
|
+
"updated_at",
|
|
291
|
+
"status",
|
|
292
|
+
"metadata",
|
|
293
|
+
"kwargs",
|
|
294
|
+
"multitask_strategy",
|
|
295
|
+
]
|
|
296
|
+
RUN_FIELDS: set[str] = set(RunSelectField.__args__) # type: ignore[attr-defined]
|
|
297
|
+
|
|
298
|
+
# Cron select fields
|
|
299
|
+
CronSelectField = Literal[
|
|
300
|
+
"cron_id",
|
|
301
|
+
"assistant_id",
|
|
302
|
+
"thread_id",
|
|
303
|
+
"end_time",
|
|
304
|
+
"schedule",
|
|
305
|
+
"created_at",
|
|
306
|
+
"updated_at",
|
|
307
|
+
"user_id",
|
|
308
|
+
"payload",
|
|
309
|
+
"next_run_date",
|
|
310
|
+
"metadata",
|
|
311
|
+
"now",
|
|
312
|
+
]
|
|
313
|
+
CRON_FIELDS: set[str] = set(CronSelectField.__args__) # type: ignore[attr-defined]
|