langgraph-api 0.4.28__tar.gz → 0.4.29__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.4.28 → langgraph_api-0.4.29}/Makefile +48 -8
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/PKG-INFO +4 -1
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/constraints.txt +3 -0
- langgraph_api-0.4.29/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/assistants.py +12 -9
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/feature_flags.py +9 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/graph.py +11 -12
- langgraph_api-0.4.29/langgraph_api/grpc_ops/client.py +80 -0
- langgraph_api-0.4.29/langgraph_api/grpc_ops/generated/__init__.py +5 -0
- langgraph_api-0.4.29/langgraph_api/grpc_ops/generated/core_api_pb2.py +274 -0
- langgraph_api-0.4.29/langgraph_api/grpc_ops/generated/core_api_pb2.pyi +988 -0
- langgraph_api-0.4.29/langgraph_api/grpc_ops/generated/core_api_pb2_grpc.py +1400 -0
- langgraph_api-0.4.29/langgraph_api/grpc_ops/ops.py +540 -0
- langgraph_api-0.4.29/langgraph_api/grpc_ops/scripts/generate_protos.sh +47 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/schema.py +2 -1
- langgraph_api-0.4.29/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/pyproject.toml +6 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/uv.lock +144 -31
- langgraph_api-0.4.28/langgraph_api/__init__.py +0 -1
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/.gitignore +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/LICENSE +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/README.md +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/.gitignore +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/Makefile +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/README.md +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/burst.js +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/clean.js +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/graphs.js +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/package.json +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/ramp.js +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/benchmark/weather.js +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/forbidden.txt +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/healthcheck.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/mcp.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/threads.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/command.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/config.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/executor_entrypoint.py +0 -0
- {langgraph_api-0.4.28/langgraph_api/js → langgraph_api-0.4.29/langgraph_api/grpc_ops}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/http.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.4.28/langgraph_api/middleware → langgraph_api-0.4.29/langgraph_api/js}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/package.json +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/js/yarn.lock +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.4.28/langgraph_api/models → langgraph_api-0.4.29/langgraph_api/middleware}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.4.28/langgraph_license → langgraph_api-0.4.29/langgraph_api/models}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/route.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/server.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/state.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/store.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/thread_ttl.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/logging.json +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/openapi.json +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.4.29}/scripts/create_license.py +0 -0
|
@@ -1,22 +1,39 @@
|
|
|
1
|
-
.PHONY: build release lint format test test_watch start start-inmem start-inmem-license-oss start check-version check-base-imports
|
|
1
|
+
.PHONY: build release lint format test test_watch start start-inmem start-inmem-license-oss start start-js-server build-go-server start-go-server stop-go-server check-version check-base-imports
|
|
2
|
+
|
|
3
|
+
# Environment variables
|
|
4
|
+
FF_USE_CORE_API ?= false
|
|
5
|
+
CORE_API_LANGSERVE_GRAPHS = '{"agent": "./tests/graphs/agent.py:graph", "custom_lifespan": "./tests/graphs/my_router.py:graph", "single_node": "./tests/graphs/single_node.py:graph", "benchmark": "./tests/graphs/benchmark.py:graph", "config_graph": "./tests/graphs/config_graph.py:graph", "other": "./tests/graphs/other.py:make_graph", "weather": "./tests/graphs/weather.py:mk_weather_graph", "searchy": "./tests/graphs/searchy.py:graph", "agent_simple": "./tests/graphs/agent_simple.py:graph", "simple_runtime": "./tests/graphs/simple_runtime.py:graph", "agent_interrupt": "./tests/graphs/agent_interrupt.py:graph", "message_type_test": "./tests/graphs/message_type_test.py:graph", "remote_subgraph_parent": "./tests/graphs/remote_subgraph_parent.py:graph", "simple_remote": "./tests/graphs/simple_remote.py:graph"}'
|
|
6
|
+
# Go server management
|
|
7
|
+
build-go-server:
|
|
8
|
+
@echo "Building Go gRPC server..."
|
|
9
|
+
cd ../core/core-api/cmd/sqlite-test-server && go build -o cmd main.go
|
|
10
|
+
|
|
11
|
+
start-go-server:
|
|
12
|
+
@echo "Starting Go gRPC server on port 50051..."
|
|
13
|
+
cd ../core/core-api/cmd/sqlite-test-server && LANGSERVE_GRAPHS=$(CORE_API_LANGSERVE_GRAPHS) ./cmd &
|
|
14
|
+
@sleep 2
|
|
15
|
+
|
|
16
|
+
stop-go-server:
|
|
17
|
+
@echo "Stopping Go gRPC server on port 50051..."
|
|
18
|
+
@lsof -ti:50051 | xargs -r kill -9 || echo "No process found on port 50051"
|
|
2
19
|
|
|
3
20
|
# lint commands
|
|
4
21
|
|
|
5
22
|
lint:
|
|
6
|
-
uv run ruff check .
|
|
7
|
-
uv run ruff format . --diff
|
|
8
|
-
uvx ty check --exclude "**/pb/**" --exclude "**/*_test.py" --exclude "**/test_*.py" --exclude "**/tests/**" --exclude "venv/**" --exclude ".venv/**" --exclude "build/**" --exclude "dist/**" .
|
|
23
|
+
uv run ruff check . --exclude "**/generated/**"
|
|
24
|
+
uv run ruff format . --diff --exclude "**/generated/**"
|
|
25
|
+
uvx ty check --exclude "**/pb/**" --exclude "**/*_test.py" --exclude "**/test_*.py" --exclude "**/tests/**" --exclude "venv/**" --exclude ".venv/**" --exclude "build/**" --exclude "dist/**" --exclude "**/generated/**" .
|
|
9
26
|
|
|
10
27
|
format:
|
|
11
|
-
uv run ruff check --fix .
|
|
12
|
-
uv run ruff format .
|
|
28
|
+
uv run ruff check --fix . --exclude "**/generated/**"
|
|
29
|
+
uv run ruff format . --exclude "**/generated/**"
|
|
13
30
|
|
|
14
31
|
check-base-imports:
|
|
15
32
|
LANGGRAPH_RUNTIME_EDITION=inmem DATABASE_URI=:memory: REDIS_URI=_FAKE uv run python -c "from langgraph_api.config import *; from langgraph_runtime import *"
|
|
16
33
|
|
|
17
34
|
# test commands
|
|
18
35
|
|
|
19
|
-
TEST ?= tests/
|
|
36
|
+
TEST ?= tests/ ../runtime_inmem/tests/
|
|
20
37
|
AUTH_TEST ?= "tests/integration_tests/test_custom_auth.py"
|
|
21
38
|
LANGGRAPH_HTTP ?= {"disable_mcp": false, "disable_a2a": false}
|
|
22
39
|
LANGGRAPH_AES_KEY ?= '1234567890123456'
|
|
@@ -37,7 +54,11 @@ endif
|
|
|
37
54
|
REVISION ?= $(shell git rev-parse --short HEAD)
|
|
38
55
|
|
|
39
56
|
test-license-oss:
|
|
40
|
-
|
|
57
|
+
@if [ "$(FF_USE_CORE_API)" = "true" ]; then \
|
|
58
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' LANGGRAPH_STORE='$(STORE_CONFIG)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ FF_USE_CORE_API=true uv run pytest -m grpc -v $(TEST); \
|
|
59
|
+
else \
|
|
60
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' LANGGRAPH_STORE='$(STORE_CONFIG)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run pytest -v $(TEST); \
|
|
61
|
+
fi
|
|
41
62
|
|
|
42
63
|
test-watch-oss:
|
|
43
64
|
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run --no-sync ptw . -- -x -vv --ff --capture=no $(TEST)
|
|
@@ -56,6 +77,10 @@ test-auth-watch:
|
|
|
56
77
|
# dev commands
|
|
57
78
|
|
|
58
79
|
start:
|
|
80
|
+
@if [ "$(FF_USE_CORE_API)" = "true" ]; then \
|
|
81
|
+
$(MAKE) build-go-server && $(MAKE) start-go-server; \
|
|
82
|
+
trap '$(MAKE) stop-go-server' INT TERM EXIT; \
|
|
83
|
+
fi; \
|
|
59
84
|
sleep 3 && \
|
|
60
85
|
LANGGRAPH_HTTP='$(HTTP_CONFIG)' \
|
|
61
86
|
LANGGRAPH_RUNTIME_EDITION=inmem \
|
|
@@ -65,6 +90,7 @@ start:
|
|
|
65
90
|
LANGGRAPH_STORE='$(STORE_CONFIG)' \
|
|
66
91
|
LANGGRAPH_CONFIG='{"agent": {"configurable": {"model_name": "openai"}}}' \
|
|
67
92
|
LANGSMITH_LANGGRAPH_API_VARIANT=test \
|
|
93
|
+
FF_USE_CORE_API=$(FF_USE_CORE_API) \
|
|
68
94
|
REDIS_URI=fake \
|
|
69
95
|
DATABASE_URI=:memory: \
|
|
70
96
|
MIGRATIONS_PATH=__inmem \
|
|
@@ -117,6 +143,20 @@ start-auth-fastapi-jwt:
|
|
|
117
143
|
--reload-dir ../runtime_inmem \
|
|
118
144
|
--no-access-log
|
|
119
145
|
|
|
146
|
+
start-js-server:
|
|
147
|
+
@echo "Building and starting Go gRPC server..."
|
|
148
|
+
$(MAKE) build-go-server
|
|
149
|
+
$(MAKE) start-go-server
|
|
150
|
+
@trap '$(MAKE) -C $(CURDIR) stop-go-server' INT TERM EXIT; \
|
|
151
|
+
echo "Installing JS server dependencies..."; \
|
|
152
|
+
cd ../public-api-server-js && npm install; \
|
|
153
|
+
echo "Building JS server..."; \
|
|
154
|
+
cd ../public-api-server-js && npm run build; \
|
|
155
|
+
echo "Starting JS server on port 9123..."; \
|
|
156
|
+
cd ../public-api-server-js && FF_USE_CORE_API=true \
|
|
157
|
+
LANGSERVE_GRAPHS=$(CORE_API_LANGSERVE_GRAPHS) \
|
|
158
|
+
PORT=9123 npm start
|
|
159
|
+
|
|
120
160
|
VERSION_KIND ?= patch
|
|
121
161
|
|
|
122
162
|
bump-version:
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.29
|
|
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
|
|
7
7
|
Requires-Python: >=3.11
|
|
8
8
|
Requires-Dist: cloudpickle>=3.0.0
|
|
9
9
|
Requires-Dist: cryptography<45.0,>=42.0.0
|
|
10
|
+
Requires-Dist: grpcio-tools<2.0.0,>=1.75.0
|
|
11
|
+
Requires-Dist: grpcio<2.0.0,>=1.75.0
|
|
10
12
|
Requires-Dist: httpx>=0.25.0
|
|
11
13
|
Requires-Dist: jsonschema-rs<0.30,>=0.20.0
|
|
12
14
|
Requires-Dist: langchain-core>=0.3.64
|
|
@@ -16,6 +18,7 @@ Requires-Dist: langgraph-sdk>=0.2.0
|
|
|
16
18
|
Requires-Dist: langgraph>=0.4.0
|
|
17
19
|
Requires-Dist: langsmith>=0.3.45
|
|
18
20
|
Requires-Dist: orjson>=3.9.7
|
|
21
|
+
Requires-Dist: protobuf<7.0.0,>=6.32.1
|
|
19
22
|
Requires-Dist: pyjwt>=2.9.0
|
|
20
23
|
Requires-Dist: sse-starlette<2.2.0,>=2.1.0
|
|
21
24
|
Requires-Dist: starlette>=0.38.6
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.29"
|
|
@@ -12,8 +12,9 @@ from starlette.responses import Response
|
|
|
12
12
|
from starlette.routing import BaseRoute
|
|
13
13
|
|
|
14
14
|
from langgraph_api import store as api_store
|
|
15
|
-
from langgraph_api.feature_flags import USE_RUNTIME_CONTEXT_API
|
|
15
|
+
from langgraph_api.feature_flags import FF_USE_CORE_API, USE_RUNTIME_CONTEXT_API
|
|
16
16
|
from langgraph_api.graph import get_assistant_id, get_graph
|
|
17
|
+
from langgraph_api.grpc_ops.ops import Assistants as GrpcAssistants
|
|
17
18
|
from langgraph_api.js.base import BaseRemotePregel
|
|
18
19
|
from langgraph_api.route import ApiRequest, ApiResponse, ApiRoute
|
|
19
20
|
from langgraph_api.schema import ASSISTANT_FIELDS
|
|
@@ -40,6 +41,7 @@ from langgraph_runtime.retry import retry_db
|
|
|
40
41
|
|
|
41
42
|
logger = structlog.stdlib.get_logger(__name__)
|
|
42
43
|
|
|
44
|
+
CrudAssistants = GrpcAssistants if FF_USE_CORE_API else Assistants
|
|
43
45
|
|
|
44
46
|
EXCLUDED_CONFIG_SCHEMA = (
|
|
45
47
|
"__pregel_checkpointer",
|
|
@@ -164,7 +166,7 @@ async def create_assistant(request: ApiRequest) -> ApiResponse:
|
|
|
164
166
|
if assistant_id := payload.get("assistant_id"):
|
|
165
167
|
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
166
168
|
async with connect() as conn:
|
|
167
|
-
assistant = await
|
|
169
|
+
assistant = await CrudAssistants.put(
|
|
168
170
|
conn,
|
|
169
171
|
assistant_id or str(uuid4()),
|
|
170
172
|
config=payload.get("config") or {},
|
|
@@ -175,6 +177,7 @@ async def create_assistant(request: ApiRequest) -> ApiResponse:
|
|
|
175
177
|
name=payload.get("name") or "Untitled",
|
|
176
178
|
description=payload.get("description"),
|
|
177
179
|
)
|
|
180
|
+
|
|
178
181
|
return ApiResponse(await fetchone(assistant, not_found_code=409))
|
|
179
182
|
|
|
180
183
|
|
|
@@ -187,7 +190,7 @@ async def search_assistants(
|
|
|
187
190
|
select = validate_select_columns(payload.get("select") or None, ASSISTANT_FIELDS)
|
|
188
191
|
offset = int(payload.get("offset") or 0)
|
|
189
192
|
async with connect() as conn:
|
|
190
|
-
assistants_iter, next_offset = await
|
|
193
|
+
assistants_iter, next_offset = await CrudAssistants.search(
|
|
191
194
|
conn,
|
|
192
195
|
graph_id=payload.get("graph_id"),
|
|
193
196
|
metadata=payload.get("metadata"),
|
|
@@ -210,7 +213,7 @@ async def count_assistants(
|
|
|
210
213
|
"""Count assistants."""
|
|
211
214
|
payload = await request.json(AssistantCountRequest)
|
|
212
215
|
async with connect() as conn:
|
|
213
|
-
count = await
|
|
216
|
+
count = await CrudAssistants.count(
|
|
214
217
|
conn,
|
|
215
218
|
graph_id=payload.get("graph_id"),
|
|
216
219
|
metadata=payload.get("metadata"),
|
|
@@ -226,7 +229,7 @@ async def get_assistant(
|
|
|
226
229
|
"""Get an assistant by ID."""
|
|
227
230
|
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
228
231
|
async with connect() as conn:
|
|
229
|
-
assistant = await
|
|
232
|
+
assistant = await CrudAssistants.get(conn, assistant_id)
|
|
230
233
|
return ApiResponse(await fetchone(assistant))
|
|
231
234
|
|
|
232
235
|
|
|
@@ -386,7 +389,7 @@ async def patch_assistant(
|
|
|
386
389
|
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
387
390
|
payload = await request.json(AssistantPatch)
|
|
388
391
|
async with connect() as conn:
|
|
389
|
-
assistant = await
|
|
392
|
+
assistant = await CrudAssistants.patch(
|
|
390
393
|
conn,
|
|
391
394
|
assistant_id,
|
|
392
395
|
config=payload.get("config"),
|
|
@@ -405,7 +408,7 @@ async def delete_assistant(request: ApiRequest) -> Response:
|
|
|
405
408
|
assistant_id = request.path_params["assistant_id"]
|
|
406
409
|
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
407
410
|
async with connect() as conn:
|
|
408
|
-
aid = await
|
|
411
|
+
aid = await CrudAssistants.delete(conn, assistant_id)
|
|
409
412
|
await fetchone(aid)
|
|
410
413
|
return Response(status_code=204)
|
|
411
414
|
|
|
@@ -417,7 +420,7 @@ async def get_assistant_versions(request: ApiRequest) -> ApiResponse:
|
|
|
417
420
|
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
418
421
|
payload = await request.json(AssistantVersionsSearchRequest)
|
|
419
422
|
async with connect() as conn:
|
|
420
|
-
assistants_iter = await
|
|
423
|
+
assistants_iter = await CrudAssistants.get_versions(
|
|
421
424
|
conn,
|
|
422
425
|
assistant_id,
|
|
423
426
|
metadata=payload.get("metadata") or {},
|
|
@@ -439,7 +442,7 @@ async def set_latest_assistant_version(request: ApiRequest) -> ApiResponse:
|
|
|
439
442
|
payload = await request.json(AssistantVersionChange)
|
|
440
443
|
validate_uuid(assistant_id, "Invalid assistant ID: must be a UUID")
|
|
441
444
|
async with connect() as conn:
|
|
442
|
-
assistant = await
|
|
445
|
+
assistant = await CrudAssistants.set_latest(
|
|
443
446
|
conn, assistant_id, payload.get("version")
|
|
444
447
|
)
|
|
445
448
|
return ApiResponse(await fetchone(assistant, not_found_code=404))
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
from langgraph.version import __version__
|
|
2
4
|
|
|
3
5
|
# Only gate features on the major.minor version; Lets you ignore the rc/alpha/etc. releases anyway
|
|
@@ -7,3 +9,10 @@ OMIT_PENDING_SENDS = LANGGRAPH_PY_MINOR >= (0, 5)
|
|
|
7
9
|
USE_RUNTIME_CONTEXT_API = LANGGRAPH_PY_MINOR >= (0, 6)
|
|
8
10
|
USE_NEW_INTERRUPTS = LANGGRAPH_PY_MINOR >= (0, 6)
|
|
9
11
|
USE_DURABILITY = LANGGRAPH_PY_MINOR >= (0, 6)
|
|
12
|
+
|
|
13
|
+
# Feature flag for new gRPC-based persistence layer
|
|
14
|
+
FF_USE_CORE_API = os.getenv("FF_USE_CORE_API", "false").lower() in (
|
|
15
|
+
"true",
|
|
16
|
+
"1",
|
|
17
|
+
"yes",
|
|
18
|
+
)
|
|
@@ -21,9 +21,8 @@ from langgraph.pregel import Pregel
|
|
|
21
21
|
from langgraph.store.base import BaseStore
|
|
22
22
|
from starlette.exceptions import HTTPException
|
|
23
23
|
|
|
24
|
-
from langgraph_api import asyncio as lg_asyncio
|
|
25
24
|
from langgraph_api import config
|
|
26
|
-
from langgraph_api.feature_flags import USE_RUNTIME_CONTEXT_API
|
|
25
|
+
from langgraph_api.feature_flags import FF_USE_CORE_API, USE_RUNTIME_CONTEXT_API
|
|
27
26
|
from langgraph_api.js.base import BaseRemotePregel, is_js_path
|
|
28
27
|
from langgraph_api.schema import Config
|
|
29
28
|
from langgraph_api.utils.config import run_in_executor, var_child_runnable_config
|
|
@@ -51,13 +50,19 @@ async def register_graph(
|
|
|
51
50
|
description: str | None = None,
|
|
52
51
|
) -> None:
|
|
53
52
|
"""Register a graph."""
|
|
53
|
+
from langgraph_api.grpc_ops.ops import Assistants as AssistantsGrpc
|
|
54
54
|
from langgraph_runtime.database import connect
|
|
55
|
-
from langgraph_runtime.ops import Assistants
|
|
55
|
+
from langgraph_runtime.ops import Assistants as AssistantsRuntime
|
|
56
|
+
|
|
57
|
+
Assistants = AssistantsGrpc if FF_USE_CORE_API else AssistantsRuntime
|
|
56
58
|
|
|
57
59
|
await logger.ainfo(f"Registering graph with id '{graph_id}'", graph_id=graph_id)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
if not FF_USE_CORE_API:
|
|
61
|
+
GRAPHS[graph_id] = graph
|
|
62
|
+
if callable(graph):
|
|
63
|
+
FACTORY_ACCEPTS_CONFIG[graph_id] = (
|
|
64
|
+
len(inspect.signature(graph).parameters) > 0
|
|
65
|
+
)
|
|
61
66
|
|
|
62
67
|
from langgraph_runtime.retry import retry_db
|
|
63
68
|
|
|
@@ -87,12 +92,6 @@ async def register_graph(
|
|
|
87
92
|
await register_graph_db()
|
|
88
93
|
|
|
89
94
|
|
|
90
|
-
def register_graph_sync(
|
|
91
|
-
graph_id: str, graph: GraphValue, config: dict | None = None
|
|
92
|
-
) -> None:
|
|
93
|
-
lg_asyncio.run_coroutine_threadsafe(register_graph(graph_id, graph, config))
|
|
94
|
-
|
|
95
|
-
|
|
96
95
|
@asynccontextmanager
|
|
97
96
|
async def _generate_graph(value: Any) -> AsyncIterator[Any]:
|
|
98
97
|
"""Yield a graph object regardless of its type."""
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""gRPC client wrapper for LangGraph persistence services."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
from grpc import aio # type: ignore[import]
|
|
7
|
+
|
|
8
|
+
from .generated.core_api_pb2_grpc import AdminStub, AssistantsStub
|
|
9
|
+
|
|
10
|
+
logger = structlog.stdlib.get_logger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GrpcClient:
|
|
14
|
+
"""gRPC client for LangGraph persistence services."""
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
server_address: str | None = None,
|
|
19
|
+
):
|
|
20
|
+
"""Initialize the gRPC client.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
server_address: The gRPC server address (default: localhost:50051)
|
|
24
|
+
"""
|
|
25
|
+
self.server_address = server_address or os.getenv(
|
|
26
|
+
"GRPC_SERVER_ADDRESS", "localhost:50051"
|
|
27
|
+
)
|
|
28
|
+
self._channel: aio.Channel | None = None
|
|
29
|
+
self._assistants_stub: AssistantsStub | None = None
|
|
30
|
+
self._admin_stub: AdminStub | None = None
|
|
31
|
+
|
|
32
|
+
async def __aenter__(self):
|
|
33
|
+
"""Async context manager entry."""
|
|
34
|
+
await self.connect()
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
38
|
+
"""Async context manager exit."""
|
|
39
|
+
await self.close()
|
|
40
|
+
|
|
41
|
+
async def connect(self):
|
|
42
|
+
"""Connect to the gRPC server."""
|
|
43
|
+
if self._channel is not None:
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
self._channel = aio.insecure_channel(self.server_address)
|
|
47
|
+
|
|
48
|
+
self._assistants_stub = AssistantsStub(self._channel)
|
|
49
|
+
self._admin_stub = AdminStub(self._channel)
|
|
50
|
+
|
|
51
|
+
await logger.adebug(
|
|
52
|
+
"Connected to gRPC server", server_address=self.server_address
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
async def close(self):
|
|
56
|
+
"""Close the gRPC connection."""
|
|
57
|
+
if self._channel is not None:
|
|
58
|
+
await self._channel.close()
|
|
59
|
+
self._channel = None
|
|
60
|
+
self._assistants_stub = None
|
|
61
|
+
self._admin_stub = None
|
|
62
|
+
await logger.adebug("Closed gRPC connection")
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def assistants(self) -> AssistantsStub:
|
|
66
|
+
"""Get the assistants service stub."""
|
|
67
|
+
if self._assistants_stub is None:
|
|
68
|
+
raise RuntimeError(
|
|
69
|
+
"Client not connected. Use async context manager or call connect() first."
|
|
70
|
+
)
|
|
71
|
+
return self._assistants_stub
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def admin(self) -> AdminStub:
|
|
75
|
+
"""Get the admin service stub."""
|
|
76
|
+
if self._admin_stub is None:
|
|
77
|
+
raise RuntimeError(
|
|
78
|
+
"Client not connected. Use async context manager or call connect() first."
|
|
79
|
+
)
|
|
80
|
+
return self._admin_stub
|