langgraph-api 0.9.0.dev6__tar.gz → 0.9.1__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.
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/Makefile +3 -18
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/PKG-INFO +3 -3
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/README.md +1 -1
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/continuous/uv.lock +3 -3
- langgraph_api-0.9.1/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/runs.py +0 -14
- langgraph_api-0.9.1/langgraph_api/asgi_transport.py +173 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/config/schemas.py +2 -26
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/cron_scheduler.py +1 -1
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/service.py +6 -32
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/ops/crons.py +1 -31
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/ops/runs.py +3 -4
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/webhook.py +3 -25
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/core_api_pb2.py +51 -53
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/core_api_pb2.pyi +0 -24
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -43
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -9
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/openapi.json +0 -50
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/pyproject.toml +1 -1
- langgraph_api-0.9.0.dev6/langgraph_api/__init__.py +0 -1
- langgraph_api-0.9.0.dev6/langgraph_api/asgi_transport.py +0 -310
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/.gitignore +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/LICENSE +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/.gitignore +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/Makefile +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/README.md +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/capacity_dd_report.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/capacity_k6.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/capacity_runner.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/capacity_slack_report.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/capacity_urls.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/clean.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/graphs.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/mixed_workload_k6.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/mixed_workload_runner.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/package.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/ramp.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/reporting/slack_slowest_runs.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/reporting/slack_summary.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/run_local.sh +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/staircase.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/benchmark/weather.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/constraints.txt +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/custom_store.sql +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/forbidden.txt +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/hatch_build.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/healthcheck.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/event_streaming.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/threads.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/command.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/config/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/ops/threads.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/http.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/package.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/js/yarn.lock +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/metrics_datadog.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/route.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/schema.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/server.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/state.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/logging.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/scripts/create_license.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/scripts/run_a2a_tck.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.9.1}/uv.lock +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
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 test-a2a-tck test-a2a-tck-mandatory start-test-a2a-tck start-test-a2a-tck-mandatory start-test-a2a-tck-watch test-mcp-conformance start-test-mcp-conformance list-mcp-scenarios
|
|
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 test-a2a-tck test-a2a-tck-mandatory start-test-a2a-tck start-test-a2a-tck-mandatory start-test-a2a-tck-watch test-mcp-conformance start-test-mcp-conformance list-mcp-scenarios
|
|
2
2
|
|
|
3
3
|
# Environment variables
|
|
4
4
|
LANGSERVE_GRAPHS_ALL = '{"agent": {"path": "./tests/graphs/agent.py:graph", "description": "agent"}, "assistant_id_runtime": "./tests/graphs/assistant_id_runtime.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", "agent_parallel_interrupt": "./tests/graphs/agent_parallel_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", "nested_subgraphs": "./tests/graphs/nested_subgraphs.py:graph", "functional_fibonacci": "./tests/graphs/functional_fibonacci.py:fibonacci", "state_graph_fibonacci": "./tests/graphs/state_graph_fibonacci.py:fibonacci", "max_concurrency_graph": "./tests/graphs/max_concurrency_graph.py:graph", "unserializable_subgraph": "./tests/graphs/unserializable_subgraph.py:graph", "agent_interrupt_text": "./tests/graphs/agent_interrupt_text.py:graph", "agent_echo_stream": "./tests/graphs/agent_echo_stream.py:graph", "agent_tool_stream": "./tests/graphs/agent_tool_stream.py:graph", "runtime_graph": "./tests/graphs/runtime_graph.py:graph", "tool_call_chunk_stream": "./tests/graphs/tool_call_chunk_stream.py:graph", "ui_tool_call_stream": "./tests/graphs/ui_tool_call_stream.py:graph", "agent_metrics_stream": "./tests/graphs/agent_metrics_stream.py:graph", "agent_multimodal_stream": "./tests/graphs/agent_multimodal_stream.py:graph", "agent_bedtime_story": "./tests/graphs/agent_bedtime_story.py:graph", "delta_channel": "./tests/graphs/delta_channel.py:graph", "delta_channel_freq": "./tests/graphs/delta_channel_freq.py:graph", "delta_channel_files": "./tests/graphs/delta_channel_files.py:graph", "delta_channel_files_freq": "./tests/graphs/delta_channel_files_freq.py:graph", "delta_channel_legacy": "./tests/graphs/delta_channel_migration.py:graph_legacy", "delta_channel_delta": "./tests/graphs/delta_channel_migration.py:graph_delta", "delta_channel_messages_freq": "./tests/graphs/delta_channel_messages.py:graph_freq", "delta_channel_messages": "./tests/graphs/delta_channel_messages.py:graph", "delta_channel_messages_legacy": "./tests/graphs/delta_channel_messages.py:graph_legacy", "delta_channel_messages_remove": "./tests/graphs/delta_channel_messages.py:graph_remove", "delta_channel_messages_update": "./tests/graphs/delta_channel_messages.py:graph_update", "delta_channel_messages_delta": "./tests/graphs/delta_channel_messages.py:graph_delta"}'
|
|
@@ -71,19 +71,6 @@ else
|
|
|
71
71
|
HTTP_CONFIG := $(LANGGRAPH_HTTP)
|
|
72
72
|
endif
|
|
73
73
|
|
|
74
|
-
# Dev/test default: opt in to loopback + http webhooks.
|
|
75
|
-
# ``test_custom_route`` etc use relative URLs to dispatch to my_router.py;
|
|
76
|
-
# ``test_join_*`` / ``test_webhook_payload_on_timeouts`` / ``test_cron_*``
|
|
77
|
-
# and the shutdown suite use ``http://localhost:{port}/webhook`` to a
|
|
78
|
-
# pytest httpserver fixture — all of these are blocked by the secure
|
|
79
|
-
# ``disable_loopback`` default (GHSA-q3v5-r5ch-p57j), and
|
|
80
|
-
# ``require_https`` defaults to true once any webhooks.url block is
|
|
81
|
-
# present, so explicitly disable it for the http httpserver fixture.
|
|
82
|
-
# Production deployers don't use these Makefiles. Override with
|
|
83
|
-
# ``LANGGRAPH_WEBHOOKS=...`` on the command line to exercise the secure
|
|
84
|
-
# default during local development.
|
|
85
|
-
LANGGRAPH_WEBHOOKS ?= {"url": {"disable_loopback": false, "require_https": false}}
|
|
86
|
-
|
|
87
74
|
LANGGRAPH_STORE ?= ""
|
|
88
75
|
ifeq ($(LANGGRAPH_STORE),custom)
|
|
89
76
|
STORE_CONFIG := {"path": "./tests/graphs/custom_store.py:generate_store"}
|
|
@@ -106,10 +93,10 @@ REVISION ?= $(shell git rev-parse --short HEAD)
|
|
|
106
93
|
LANGGRAPH_ENCRYPTION ?=
|
|
107
94
|
|
|
108
95
|
test-license-oss:
|
|
109
|
-
LANGGRAPH_RUNTIME_EDITION=inmem
|
|
96
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' LANGGRAPH_STORE='$(STORE_CONFIG)' LANGGRAPH_CHECKPOINTER='$(CHECKPOINTER_CONFIG)' LANGGRAPH_ENCRYPTION='$(LANGGRAPH_ENCRYPTION)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run pytest -v $(XDIST_ARGS) $(TEST)
|
|
110
97
|
|
|
111
98
|
test-watch-oss:
|
|
112
|
-
LANGGRAPH_RUNTIME_EDITION=inmem
|
|
99
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' LANGGRAPH_ENCRYPTION='$(LANGGRAPH_ENCRYPTION)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run --no-sync ptw . -- -x -vv --ff --capture=no $(TEST)
|
|
113
100
|
|
|
114
101
|
test: test-license-oss
|
|
115
102
|
test-watch: test-watch-oss
|
|
@@ -172,7 +159,6 @@ LANGSMITH_TRACING ?= false
|
|
|
172
159
|
|
|
173
160
|
start:
|
|
174
161
|
LANGGRAPH_DISABLE_FILE_PERSISTENCE=$(LANGGRAPH_DISABLE_FILE_PERSISTENCE) \
|
|
175
|
-
LANGGRAPH_WEBHOOKS='$(LANGGRAPH_WEBHOOKS)' \
|
|
176
162
|
LANGGRAPH_HTTP='$(HTTP_CONFIG)' \
|
|
177
163
|
LANGGRAPH_RUNTIME_EDITION=inmem \
|
|
178
164
|
LANGGRAPH_AES_KEY='$(LANGGRAPH_AES_KEY)' \
|
|
@@ -200,7 +186,6 @@ start:
|
|
|
200
186
|
start-license-oss: start
|
|
201
187
|
|
|
202
188
|
start-encrypt:
|
|
203
|
-
LANGGRAPH_WEBHOOKS='$(LANGGRAPH_WEBHOOKS)' \
|
|
204
189
|
LANGGRAPH_HTTP='$(HTTP_CONFIG)' \
|
|
205
190
|
LANGGRAPH_RUNTIME_EDITION=inmem \
|
|
206
191
|
LANGGRAPH_AES_KEY='$(LANGGRAPH_AES_KEY)' \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Author-email: Will Fu-Hinthorn <will@langchain.dev>, Josh Rogers <josh@langchain.dev>, Parker Rule <parker@langchain.dev>
|
|
5
5
|
License: Elastic-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -16,7 +16,7 @@ Requires-Dist: jsonschema-rs<0.45,>=0.20.0
|
|
|
16
16
|
Requires-Dist: langchain-core>=0.3.64
|
|
17
17
|
Requires-Dist: langchain-protocol<0.1,>=0.0.15
|
|
18
18
|
Requires-Dist: langgraph-checkpoint<5,>=3.0.1
|
|
19
|
-
Requires-Dist: langgraph-runtime-inmem<0.
|
|
19
|
+
Requires-Dist: langgraph-runtime-inmem<0.30.0,>=0.29.0
|
|
20
20
|
Requires-Dist: langgraph-sdk>=0.3.5
|
|
21
21
|
Requires-Dist: langgraph<2,>=0.4.10
|
|
22
22
|
Requires-Dist: langsmith[otel]>=0.6.3
|
|
@@ -50,7 +50,7 @@ For production use, see the various [deployment options](https://langchain-ai.gi
|
|
|
50
50
|
Install the `langgraph-cli` package with the `inmem` extra. Your CLI version must be no lower than `0.1.55`.
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
pip install -U
|
|
53
|
+
pip install -U langgraph-cli[inmem]
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
## Quickstart
|
|
@@ -9,7 +9,7 @@ For production use, see the various [deployment options](https://langchain-ai.gi
|
|
|
9
9
|
Install the `langgraph-cli` package with the `inmem` extra. Your CLI version must be no lower than `0.1.55`.
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
pip install -U
|
|
12
|
+
pip install -U langgraph-cli[inmem]
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Quickstart
|
|
@@ -98,11 +98,11 @@ wheels = [
|
|
|
98
98
|
|
|
99
99
|
[[package]]
|
|
100
100
|
name = "idna"
|
|
101
|
-
version = "3.
|
|
101
|
+
version = "3.11"
|
|
102
102
|
source = { registry = "https://pypi.org/simple" }
|
|
103
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
103
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
|
|
104
104
|
wheels = [
|
|
105
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
105
|
+
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
|
106
106
|
]
|
|
107
107
|
|
|
108
108
|
[[package]]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.9.1"
|
|
@@ -853,19 +853,6 @@ async def create_thread_cron(request: ApiRequest):
|
|
|
853
853
|
return ApiResponse(cron_dict)
|
|
854
854
|
|
|
855
855
|
|
|
856
|
-
@retry_db
|
|
857
|
-
async def get_cron(request: ApiRequest) -> ApiResponse:
|
|
858
|
-
"""Get a cron by ID."""
|
|
859
|
-
cron_id = request.path_params["cron_id"]
|
|
860
|
-
validate_uuid(cron_id, "Invalid cron ID: must be a UUID")
|
|
861
|
-
async with connect() as conn:
|
|
862
|
-
cron = await Crons.get(conn, cron_id)
|
|
863
|
-
cron_dict = await fetchone(cron)
|
|
864
|
-
if not IS_POSTGRES_OR_GRPC_BACKEND or using_aes_encryption():
|
|
865
|
-
cron_dict = await decrypt_response(cron_dict, "cron", CRON_ENCRYPTION_FIELDS)
|
|
866
|
-
return ApiResponse(cron_dict)
|
|
867
|
-
|
|
868
|
-
|
|
869
856
|
@retry_db
|
|
870
857
|
async def patch_cron(request: ApiRequest):
|
|
871
858
|
"""Update a cron by ID."""
|
|
@@ -1005,7 +992,6 @@ runs_routes = [
|
|
|
1005
992
|
ApiRoute("/threads/{thread_id}/runs", create_run, methods=["POST"]),
|
|
1006
993
|
ApiRoute("/threads/{thread_id}/runs/crons", create_thread_cron, methods=["POST"]),
|
|
1007
994
|
ApiRoute("/threads/{thread_id}/runs", list_runs, methods=["GET"]),
|
|
1008
|
-
ApiRoute("/runs/crons/{cron_id}", get_cron, methods=["GET"]),
|
|
1009
995
|
ApiRoute("/runs/crons/{cron_id}", patch_cron, methods=["PATCH"]),
|
|
1010
996
|
ApiRoute("/runs/crons/{cron_id}", delete_cron, methods=["DELETE"]),
|
|
1011
997
|
]
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""ASGI transport that lets you schedule to the main loop.
|
|
2
|
+
|
|
3
|
+
Adapted from: https://github.com/encode/httpx/blob/6c7af967734bafd011164f2a1653abc87905a62b/httpx/_transports/asgi.py#L1
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import typing
|
|
10
|
+
|
|
11
|
+
from httpx import ASGITransport as ASGITransportBase
|
|
12
|
+
from httpx import AsyncByteStream, Request, Response
|
|
13
|
+
|
|
14
|
+
if typing.TYPE_CHECKING: # pragma: no cover
|
|
15
|
+
import trio # type: ignore[unresolved-import]
|
|
16
|
+
|
|
17
|
+
Event = asyncio.Event | trio.Event
|
|
18
|
+
|
|
19
|
+
__all__ = ["ASGITransport"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def is_running_trio() -> bool:
|
|
23
|
+
try:
|
|
24
|
+
# sniffio is a dependency of trio.
|
|
25
|
+
|
|
26
|
+
# See https://github.com/python-trio/trio/issues/2802
|
|
27
|
+
import sniffio # type: ignore[unresolved-import] # noqa: PLC0415
|
|
28
|
+
|
|
29
|
+
if sniffio.current_async_library() == "trio":
|
|
30
|
+
return True
|
|
31
|
+
except ImportError: # pragma: nocover
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def create_event() -> Event:
|
|
38
|
+
if is_running_trio():
|
|
39
|
+
import trio # type: ignore[unresolved-import] # noqa: PLC0415
|
|
40
|
+
|
|
41
|
+
return trio.Event()
|
|
42
|
+
|
|
43
|
+
return asyncio.Event()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ASGIResponseStream(AsyncByteStream):
|
|
47
|
+
def __init__(self, body: list[bytes]) -> None:
|
|
48
|
+
self._body = body
|
|
49
|
+
|
|
50
|
+
async def __aiter__(self) -> typing.AsyncIterator[bytes]:
|
|
51
|
+
yield b"".join(self._body)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ASGITransport(ASGITransportBase):
|
|
55
|
+
"""
|
|
56
|
+
A custom AsyncTransport that handles sending requests directly to an ASGI app.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
transport = httpx.ASGITransport(
|
|
60
|
+
app=app,
|
|
61
|
+
root_path="/submount",
|
|
62
|
+
client=("1.2.3.4", 123)
|
|
63
|
+
)
|
|
64
|
+
client = httpx.AsyncClient(transport=transport)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Arguments:
|
|
68
|
+
|
|
69
|
+
* `app` - The ASGI application.
|
|
70
|
+
* `raise_app_exceptions` - Boolean indicating if exceptions in the application
|
|
71
|
+
should be raised. Default to `True`. Can be set to `False` for use cases
|
|
72
|
+
such as testing the content of a client 500 response.
|
|
73
|
+
* `root_path` - The root path on which the ASGI application should be mounted.
|
|
74
|
+
* `client` - A two-tuple indicating the client IP and port of incoming requests.
|
|
75
|
+
```
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
async def handle_async_request(
|
|
79
|
+
self,
|
|
80
|
+
request: Request,
|
|
81
|
+
) -> Response:
|
|
82
|
+
from langgraph_api.asyncio import call_soon_in_main_loop # noqa: PLC0415
|
|
83
|
+
|
|
84
|
+
if not isinstance(request.stream, AsyncByteStream):
|
|
85
|
+
raise ValueError("Request stream must be an AsyncByteStream")
|
|
86
|
+
|
|
87
|
+
# ASGI scope.
|
|
88
|
+
scope = {
|
|
89
|
+
"type": "http",
|
|
90
|
+
"asgi": {"version": "3.0"},
|
|
91
|
+
"http_version": "1.1",
|
|
92
|
+
"method": request.method,
|
|
93
|
+
"headers": [(k.lower(), v) for (k, v) in request.headers.raw],
|
|
94
|
+
"scheme": request.url.scheme,
|
|
95
|
+
"path": request.url.path,
|
|
96
|
+
"raw_path": request.url.raw_path.split(b"?")[0],
|
|
97
|
+
"query_string": request.url.query,
|
|
98
|
+
"server": (request.url.host, request.url.port),
|
|
99
|
+
"client": self.client,
|
|
100
|
+
"root_path": self.root_path,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# Request.
|
|
104
|
+
request_body_chunks = request.stream.__aiter__()
|
|
105
|
+
request_complete = False
|
|
106
|
+
|
|
107
|
+
# Response.
|
|
108
|
+
status_code = None
|
|
109
|
+
response_headers = None
|
|
110
|
+
body_parts = []
|
|
111
|
+
response_started = False
|
|
112
|
+
response_complete = create_event()
|
|
113
|
+
|
|
114
|
+
# ASGI callables.
|
|
115
|
+
|
|
116
|
+
async def receive() -> dict[str, typing.Any]:
|
|
117
|
+
nonlocal request_complete
|
|
118
|
+
|
|
119
|
+
if request_complete:
|
|
120
|
+
await response_complete.wait()
|
|
121
|
+
return {"type": "http.disconnect"}
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
body = await request_body_chunks.__anext__()
|
|
125
|
+
except StopAsyncIteration:
|
|
126
|
+
request_complete = True
|
|
127
|
+
return {"type": "http.request", "body": b"", "more_body": False}
|
|
128
|
+
return {"type": "http.request", "body": body, "more_body": True}
|
|
129
|
+
|
|
130
|
+
async def send(message: typing.MutableMapping[str, typing.Any]) -> None:
|
|
131
|
+
nonlocal status_code, response_headers, response_started
|
|
132
|
+
|
|
133
|
+
if message["type"] == "http.response.start":
|
|
134
|
+
if response_started:
|
|
135
|
+
raise RuntimeError("Response already started")
|
|
136
|
+
status_code = message["status"]
|
|
137
|
+
response_headers = message.get("headers", [])
|
|
138
|
+
response_started = True
|
|
139
|
+
|
|
140
|
+
elif message["type"] == "http.response.body":
|
|
141
|
+
if response_complete.is_set():
|
|
142
|
+
raise RuntimeError("Response already complete")
|
|
143
|
+
body = message.get("body", b"")
|
|
144
|
+
more_body = message.get("more_body", False)
|
|
145
|
+
|
|
146
|
+
if body and request.method != "HEAD":
|
|
147
|
+
body_parts.append(body)
|
|
148
|
+
|
|
149
|
+
if not more_body:
|
|
150
|
+
response_complete.set()
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
await call_soon_in_main_loop(self.app(scope, receive, send))
|
|
154
|
+
except Exception:
|
|
155
|
+
if self.raise_app_exceptions:
|
|
156
|
+
raise
|
|
157
|
+
|
|
158
|
+
response_complete.set()
|
|
159
|
+
if status_code is None:
|
|
160
|
+
status_code = 500
|
|
161
|
+
if response_headers is None:
|
|
162
|
+
response_headers = {}
|
|
163
|
+
|
|
164
|
+
if not response_complete.is_set():
|
|
165
|
+
raise RuntimeError("Response not complete")
|
|
166
|
+
if status_code is None:
|
|
167
|
+
raise RuntimeError("Status code not set")
|
|
168
|
+
if response_headers is None:
|
|
169
|
+
raise RuntimeError("Response headers not set")
|
|
170
|
+
|
|
171
|
+
stream = ASGIResponseStream(body_parts)
|
|
172
|
+
|
|
173
|
+
return Response(status_code, headers=response_headers, stream=stream)
|
|
@@ -386,26 +386,7 @@ class WebhookUrlPolicy(TypedDict, total=False):
|
|
|
386
386
|
max_url_length: int
|
|
387
387
|
"""Maximum permitted URL length in characters; longer inputs are rejected early."""
|
|
388
388
|
disable_loopback: bool
|
|
389
|
-
"""Disallow loopback
|
|
390
|
-
|
|
391
|
-
Covers all of:
|
|
392
|
-
- Relative URLs (e.g. ``/internal/hook``) that would dispatch via the
|
|
393
|
-
in-process ASGI loopback transport at ``root_path="/noauth"``. These
|
|
394
|
-
bypass authentication and were the auth-bypass primitive behind
|
|
395
|
-
GHSA-q3v5-r5ch-p57j.
|
|
396
|
-
- Absolute URLs whose hostname is ``localhost`` / ``localhost.localdomain``
|
|
397
|
-
/ ``host.docker.internal``.
|
|
398
|
-
- Absolute URLs that DNS-resolve into the IPv4 loopback range
|
|
399
|
-
(``127.0.0.0/8``) or IPv6 loopback (``::1/128``) — including
|
|
400
|
-
DNS-rebinding-style attacks where an arbitrary hostname resolves to
|
|
401
|
-
a loopback IP.
|
|
402
|
-
|
|
403
|
-
Operators who intentionally route webhooks to in-process routes
|
|
404
|
-
(e.g. for local development with ``langgraph dev``, or single-host
|
|
405
|
-
docker-compose setups dispatching to ``host.docker.internal``) can
|
|
406
|
-
set this to ``false`` to restore the pre-GHSA behavior. Only do this
|
|
407
|
-
when you control all routes that loopback webhooks can reach.
|
|
408
|
-
"""
|
|
389
|
+
"""Disallow relative URLs (internal loopback calls) and localhost hostnames when true."""
|
|
409
390
|
disable_private_ips: bool
|
|
410
391
|
"""Block RFC 1918 / CGN private IP ranges as webhook targets when true.
|
|
411
392
|
|
|
@@ -445,12 +426,7 @@ def _validate_url_policy(
|
|
|
445
426
|
if "max_url_length" not in policy:
|
|
446
427
|
policy["max_url_length"] = 2048
|
|
447
428
|
if "disable_loopback" not in policy:
|
|
448
|
-
|
|
449
|
-
# loopback auth bypass) and the broader SSRF surface that the same
|
|
450
|
-
# flag governs via SSRFPolicy.block_localhost. Mirrored at the
|
|
451
|
-
# webhook.py read site so deployments without any webhooks block
|
|
452
|
-
# also get the safe default.
|
|
453
|
-
policy["disable_loopback"] = True
|
|
429
|
+
policy["disable_loopback"] = False
|
|
454
430
|
if "disable_private_ips" not in policy:
|
|
455
431
|
policy["disable_private_ips"] = False
|
|
456
432
|
return policy
|
|
@@ -54,7 +54,7 @@ async def cron_scheduler():
|
|
|
54
54
|
logger.info("Starting cron scheduler")
|
|
55
55
|
while True:
|
|
56
56
|
try:
|
|
57
|
-
async with connect() as conn:
|
|
57
|
+
async with connect(supports_core_api=False) as conn:
|
|
58
58
|
async for item in Crons.next(conn):
|
|
59
59
|
# gRPC path yields (cron, enc_ctx) tuples;
|
|
60
60
|
# non-gRPC path yields plain Cron dicts.
|
|
@@ -749,23 +749,14 @@ class ThreadRunManager:
|
|
|
749
749
|
async def get_thread_state() -> dict[str, Any] | None:
|
|
750
750
|
from langgraph_runtime.database import connect # noqa: PLC0415
|
|
751
751
|
|
|
752
|
-
# ``supports_core_api=False`` so the postgres backend yields a
|
|
753
|
-
# real connection. ``State.get`` uses the local checkpointer
|
|
754
|
-
# and needs a usable ``conn`` — the default flag yields None.
|
|
755
752
|
try:
|
|
756
|
-
async with connect(
|
|
753
|
+
async with connect() as conn:
|
|
757
754
|
return await self._threads.State.get(
|
|
758
755
|
conn,
|
|
759
756
|
{"configurable": {"thread_id": thread_id}},
|
|
760
757
|
subgraphs=True,
|
|
761
758
|
)
|
|
762
|
-
except Exception
|
|
763
|
-
logger.warning(
|
|
764
|
-
"terminal_thread_state_fetch_failed",
|
|
765
|
-
thread_id=thread_id,
|
|
766
|
-
error=str(exc),
|
|
767
|
-
error_type=type(exc).__name__,
|
|
768
|
-
)
|
|
759
|
+
except Exception:
|
|
769
760
|
return None
|
|
770
761
|
|
|
771
762
|
return get_thread_state
|
|
@@ -864,25 +855,14 @@ class ThreadRunManager:
|
|
|
864
855
|
"""
|
|
865
856
|
from langgraph_runtime.database import connect # noqa: PLC0415
|
|
866
857
|
|
|
867
|
-
# ``supports_core_api=False`` so the postgres backend yields a
|
|
868
|
-
# real connection. The default (``True``) yields ``None`` because
|
|
869
|
-
# data ops normally go through the gRPC server — but ``State.get``
|
|
870
|
-
# uses the local checkpointer and needs a usable ``conn``.
|
|
871
858
|
try:
|
|
872
|
-
async with connect(
|
|
859
|
+
async with connect() as conn:
|
|
873
860
|
state = await self._threads.State.get(
|
|
874
861
|
conn,
|
|
875
862
|
{"configurable": {"thread_id": self._thread_id}},
|
|
876
863
|
subgraphs=True,
|
|
877
864
|
)
|
|
878
|
-
except Exception
|
|
879
|
-
logger.warning(
|
|
880
|
-
"interrupt_lookup_failed",
|
|
881
|
-
thread_id=self._thread_id,
|
|
882
|
-
interrupt_id=interrupt_id,
|
|
883
|
-
error=str(exc),
|
|
884
|
-
error_type=type(exc).__name__,
|
|
885
|
-
)
|
|
865
|
+
except Exception:
|
|
886
866
|
return None
|
|
887
867
|
|
|
888
868
|
tasks = (
|
|
@@ -923,7 +903,7 @@ class ThreadRunManager:
|
|
|
923
903
|
from langgraph_runtime.database import connect # noqa: PLC0415
|
|
924
904
|
|
|
925
905
|
try:
|
|
926
|
-
async with connect(
|
|
906
|
+
async with connect() as conn:
|
|
927
907
|
state = await self._threads.State.get(
|
|
928
908
|
conn,
|
|
929
909
|
{"configurable": {"thread_id": self._thread_id}},
|
|
@@ -949,13 +929,7 @@ class ThreadRunManager:
|
|
|
949
929
|
if isinstance(interrupts, (list, tuple)) and len(interrupts) > 0:
|
|
950
930
|
return True
|
|
951
931
|
return False
|
|
952
|
-
except Exception
|
|
953
|
-
logger.warning(
|
|
954
|
-
"has_pending_interrupts_failed",
|
|
955
|
-
thread_id=self._thread_id,
|
|
956
|
-
error=str(exc),
|
|
957
|
-
error_type=type(exc).__name__,
|
|
958
|
-
)
|
|
932
|
+
except Exception:
|
|
959
933
|
return False
|
|
960
934
|
|
|
961
935
|
# ------------------------------------------------------------------
|
|
@@ -230,14 +230,10 @@ class Crons(Authenticated):
|
|
|
230
230
|
|
|
231
231
|
assistant_filters: list[Any] = []
|
|
232
232
|
if payload["assistant_id"] not in SYSTEM_ASSISTANT_IDS:
|
|
233
|
-
# Do not populate `metadata` on the AssistantsRead request value:
|
|
234
|
-
# client-supplied cron metadata must not influence the auth
|
|
235
|
-
# decision (defense vs. forged payloads), mirroring Runs.put.
|
|
236
|
-
# The handler is expected to return a filter that is matched
|
|
237
|
-
# against the persisted assistant metadata server-side.
|
|
238
233
|
assistant_request_data = Auth.types.AssistantsRead(
|
|
239
234
|
assistant_id=str(payload["assistant_id"])
|
|
240
235
|
)
|
|
236
|
+
assistant_request_data["metadata"] = metadata
|
|
241
237
|
assistant_filters = await Assistants.handle_event(
|
|
242
238
|
ctx, "read", assistant_request_data
|
|
243
239
|
)
|
|
@@ -278,32 +274,6 @@ class Crons(Authenticated):
|
|
|
278
274
|
|
|
279
275
|
return generate_result()
|
|
280
276
|
|
|
281
|
-
@staticmethod
|
|
282
|
-
async def get(
|
|
283
|
-
conn, # Not used in gRPC implementation
|
|
284
|
-
cron_id: UUID | str,
|
|
285
|
-
ctx: Any = None,
|
|
286
|
-
) -> AsyncIterator[Cron]:
|
|
287
|
-
"""Get cron by ID via gRPC."""
|
|
288
|
-
auth_filters = await Crons.handle_event(
|
|
289
|
-
ctx, "read", Auth.types.CronsRead(cron_id=cron_id)
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
request = pb.GetCronRequest(
|
|
293
|
-
cron_id=pb.UUID(value=str(cron_id)),
|
|
294
|
-
filters=auth_filters,
|
|
295
|
-
)
|
|
296
|
-
|
|
297
|
-
client = await get_shared_client()
|
|
298
|
-
response = await client.crons.Get(request)
|
|
299
|
-
|
|
300
|
-
cron = proto_to_cron(response)
|
|
301
|
-
|
|
302
|
-
async def generate_result():
|
|
303
|
-
yield cron
|
|
304
|
-
|
|
305
|
-
return generate_result()
|
|
306
|
-
|
|
307
277
|
@staticmethod
|
|
308
278
|
async def search(
|
|
309
279
|
conn, # Not used in gRPC implementation
|
|
@@ -610,19 +610,18 @@ class Runs(Authenticated):
|
|
|
610
610
|
create_run_value,
|
|
611
611
|
)
|
|
612
612
|
# Automatically enforce assistant ownership for non-system assistants
|
|
613
|
-
# by calling the user's assistant
|
|
613
|
+
# by calling the user's assistant search auth handler.
|
|
614
614
|
assistant_auth_filters: list[pb.AuthFilter] = []
|
|
615
615
|
if str(assistant_id) not in SYSTEM_ASSISTANT_IDS:
|
|
616
616
|
ctx_ = ctx or get_auth_ctx()
|
|
617
617
|
if ctx_ is not None:
|
|
618
618
|
auth_ctx = Auth.types.AuthContext(
|
|
619
619
|
resource="assistants",
|
|
620
|
-
action="
|
|
620
|
+
action="search",
|
|
621
621
|
user=ctx_.user,
|
|
622
622
|
permissions=ctx_.permissions,
|
|
623
623
|
)
|
|
624
|
-
|
|
625
|
-
raw = await auth_handle_event(auth_ctx, read_value)
|
|
624
|
+
raw = await auth_handle_event(auth_ctx, {"metadata": {}})
|
|
626
625
|
if raw:
|
|
627
626
|
assistant_auth_filters = _filters_to_proto(raw)
|
|
628
627
|
|
|
@@ -79,14 +79,7 @@ def _get_webhook_config() -> _WebhookConfig:
|
|
|
79
79
|
exact_allowed = frozenset(exact_hosts)
|
|
80
80
|
|
|
81
81
|
disable_private_ips = bool(policy_cfg.get("disable_private_ips", False))
|
|
82
|
-
|
|
83
|
-
# would dispatch through the in-process ASGI client at root_path=/noauth,
|
|
84
|
-
# plus localhost / 127.x / ::1 / host.docker.internal absolute URLs,
|
|
85
|
-
# plus any hostname that DNS-resolves into the loopback range). This is
|
|
86
|
-
# the fix for GHSA-q3v5-r5ch-p57j: relative-URL webhooks were the auth
|
|
87
|
-
# bypass primitive, and the localhost/loopback IP variants are the
|
|
88
|
-
# broader SSRF surface that the same flag governs via SSRFPolicy.
|
|
89
|
-
disable_loopback = bool(policy_cfg.get("disable_loopback", True))
|
|
82
|
+
disable_loopback = bool(policy_cfg.get("disable_loopback", False))
|
|
90
83
|
|
|
91
84
|
return _WebhookConfig(
|
|
92
85
|
allowed_domains=allowed_domains,
|
|
@@ -118,26 +111,11 @@ async def validate_webhook_url_or_raise(url: str) -> None:
|
|
|
118
111
|
if len(url) > wh.max_url_length:
|
|
119
112
|
raise HTTPException(status_code=422, detail="Webhook URL too long")
|
|
120
113
|
|
|
121
|
-
# Relative loopback URL (internal route) —
|
|
122
|
-
# ASGI client that mounts under root_path="/noauth", which the auth
|
|
123
|
-
# middleware treats as an auth-bypass marker. Denied by default so a
|
|
124
|
-
# user-supplied webhook URL cannot be turned into an unauthenticated
|
|
125
|
-
# call against the server's own routes (GHSA-q3v5-r5ch-p57j). Operators
|
|
126
|
-
# who intentionally route webhooks to in-process routes can opt back in
|
|
127
|
-
# by setting webhooks.url.disable_loopback to false.
|
|
114
|
+
# Relative loopback URL (internal route) — not subject to SSRF checks
|
|
128
115
|
if url.startswith("/"):
|
|
129
116
|
if wh.disable_loopback:
|
|
130
117
|
raise HTTPException(
|
|
131
|
-
status_code=422,
|
|
132
|
-
detail=(
|
|
133
|
-
"Loopback webhooks (relative URLs and localhost) are "
|
|
134
|
-
"disabled by default. They bypass authentication via the "
|
|
135
|
-
"in-process ASGI transport and can be abused to invoke "
|
|
136
|
-
"internal routes as an unauthenticated caller. Set "
|
|
137
|
-
"webhooks.url.disable_loopback to false (in langgraph.json "
|
|
138
|
-
"or via LANGGRAPH_WEBHOOKS) to opt back in — only do so "
|
|
139
|
-
"when you control the mounted routes."
|
|
140
|
-
),
|
|
118
|
+
status_code=422, detail="Loopback webhooks are disabled"
|
|
141
119
|
)
|
|
142
120
|
return
|
|
143
121
|
|