langgraph-api 0.18.0.dev5__tar.gz → 0.18.0.dev7__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.18.0.dev5 → langgraph_api-0.18.0.dev7}/PKG-INFO +1 -1
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/package.json +1 -1
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/yarn.lock +7 -7
- langgraph_api-0.18.0.dev7/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/threads.py +68 -20
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/config/__init__.py +19 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/errors.py +16 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/runs.py +21 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/threads.py +33 -16
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/package.json +1 -1
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/yarn.lock +10 -10
- langgraph_api-0.18.0.dev7/langgraph_api/operator_routes.py +223 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/schema.py +9 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/server.py +7 -20
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/state.py +41 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2.py +99 -95
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2.pyi +58 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +44 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +12 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/openapi.json +2 -2
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/uv.lock +9 -9
- langgraph_api-0.18.0.dev5/langgraph_api/__init__.py +0 -1
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/.gitignore +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/LICENSE +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/Makefile +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/README.md +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/.gitignore +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/Makefile +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/README.md +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/REPORTS.md +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/classify-error.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/classify-error.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/delta-turns-lib.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/delta-turns-lib.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/delta_turns.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/store.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/capacity-ci.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/capacity-ci.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/clean.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/continuous/uv.lock +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/daily-report.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/daily-report.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/delta-report.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/delta-report.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/graphs.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/history.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/history.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/host-v2.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/host-v2.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/multer.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/ramp.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/runner-descriptions.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/server-metrics.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/server-metrics.test.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/slack.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/staircase.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/benchmark/weather.js +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/constraints.txt +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/custom_store.sql +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/forbidden.txt +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/hatch_build.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/healthcheck.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/README.md +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/event_streaming.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_calls.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_outcome.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_protocol.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/command.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/config/schemas.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/drain.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/service.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/executor/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/executor/__main__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/http.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/.yarnclean +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/auth-mutations.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/metrics_collector.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/metrics_otlp.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/route.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/store.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/startup.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/tracing_session.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_api/worker_runtime.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/store.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/store.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/encryption.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/logging.json +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/pyproject.toml +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/scripts/create_license.py +0 -0
- {langgraph_api-0.18.0.dev5 → langgraph_api-0.18.0.dev7}/scripts/run_a2a_tck.py +0 -0
|
@@ -493,9 +493,9 @@ path-to-regexp@~0.1.13:
|
|
|
493
493
|
integrity sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==
|
|
494
494
|
|
|
495
495
|
proxy-addr@~2.0.7:
|
|
496
|
-
version "2.0.
|
|
497
|
-
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.
|
|
498
|
-
integrity sha512-
|
|
496
|
+
version "2.0.8"
|
|
497
|
+
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.8.tgz#624e760fd8ab06b1b8320c2f8506d4422cf8e932"
|
|
498
|
+
integrity sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==
|
|
499
499
|
dependencies:
|
|
500
500
|
forwarded "0.2.0"
|
|
501
501
|
ipaddr.js "1.9.1"
|
|
@@ -670,10 +670,10 @@ type-is@^1.6.18, type-is@~1.6.18:
|
|
|
670
670
|
media-typer "0.3.0"
|
|
671
671
|
mime-types "~2.1.24"
|
|
672
672
|
|
|
673
|
-
typescript@^
|
|
674
|
-
version "
|
|
675
|
-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-
|
|
676
|
-
integrity sha512-
|
|
673
|
+
typescript@^6.0.3:
|
|
674
|
+
version "6.0.3"
|
|
675
|
+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.3.tgz#90251dc007916e972786cb94d74d15b185577d21"
|
|
676
|
+
integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==
|
|
677
677
|
|
|
678
678
|
undici-types@~8.3.0:
|
|
679
679
|
version "8.3.0"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.18.0.dev7"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
from
|
|
1
|
+
from contextlib import aclosing
|
|
2
|
+
from typing import TYPE_CHECKING, Any, get_args
|
|
2
3
|
|
|
3
4
|
from starlette.exceptions import HTTPException
|
|
4
5
|
from starlette.responses import Response
|
|
5
6
|
from starlette.routing import BaseRoute
|
|
6
7
|
|
|
8
|
+
from langgraph_api import config as lg_api_config
|
|
7
9
|
from langgraph_api.config import USE_CUSTOM_CHECKPOINTER
|
|
8
10
|
from langgraph_api.encryption.shared import (
|
|
9
11
|
using_encryption,
|
|
@@ -14,6 +16,7 @@ from langgraph_api.feature_flags import (
|
|
|
14
16
|
)
|
|
15
17
|
from langgraph_api.route import ApiRequest, ApiResponse, ApiRoute
|
|
16
18
|
from langgraph_api.schema import THREAD_FIELDS, ThreadStreamMode
|
|
19
|
+
from langgraph_api.serde import Fragment, json_dumpb
|
|
17
20
|
from langgraph_api.sse import EventSourceResponse
|
|
18
21
|
from langgraph_api.state import state_snapshot_to_thread_state
|
|
19
22
|
from langgraph_api.utils import (
|
|
@@ -44,6 +47,11 @@ if IS_POSTGRES_OR_GRPC_BACKEND:
|
|
|
44
47
|
else:
|
|
45
48
|
from langgraph_runtime.ops import Threads
|
|
46
49
|
|
|
50
|
+
if TYPE_CHECKING:
|
|
51
|
+
from collections.abc import AsyncIterator
|
|
52
|
+
|
|
53
|
+
from langgraph.types import StateSnapshot
|
|
54
|
+
|
|
47
55
|
|
|
48
56
|
@retry_db
|
|
49
57
|
async def create_thread(
|
|
@@ -320,14 +328,7 @@ async def get_thread_history(
|
|
|
320
328
|
**get_configurable_headers(request.headers),
|
|
321
329
|
}
|
|
322
330
|
}
|
|
323
|
-
|
|
324
|
-
states = [
|
|
325
|
-
state_snapshot_to_thread_state(c)
|
|
326
|
-
for c in await Threads.State.list(
|
|
327
|
-
conn, config=config, limit=limit, before=before
|
|
328
|
-
)
|
|
329
|
-
]
|
|
330
|
-
return ApiResponse(states)
|
|
331
|
+
return await _history_response(config=config, limit=limit, before=before)
|
|
331
332
|
|
|
332
333
|
|
|
333
334
|
@retry_db
|
|
@@ -342,18 +343,65 @@ async def get_thread_history_post(
|
|
|
342
343
|
config["configurable"].update(payload.get("checkpoint", {}))
|
|
343
344
|
config["configurable"].update(get_configurable_headers(request.headers))
|
|
344
345
|
config["configurable"]["thread_id"] = thread_id
|
|
346
|
+
return await _history_response(
|
|
347
|
+
config=config,
|
|
348
|
+
limit=int(payload.get("limit") or 1),
|
|
349
|
+
before=payload.get("before"),
|
|
350
|
+
metadata=payload.get("metadata"),
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
async def _history_response(**kwargs: Any) -> ApiResponse:
|
|
355
|
+
budget = lg_api_config.THREAD_HISTORY_MAX_STATE_BYTES
|
|
345
356
|
async with connect(supports_core_api=PREFER_GRPC_CHECKPOINTER) as conn:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
+
entries = await _serialize_history(
|
|
358
|
+
_history_states(conn, incremental=bool(budget), **kwargs),
|
|
359
|
+
budget=budget,
|
|
360
|
+
)
|
|
361
|
+
return ApiResponse(entries)
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def _history_states(
|
|
365
|
+
conn: Any, *, incremental: bool, **kwargs: Any
|
|
366
|
+
) -> "AsyncIterator[StateSnapshot]":
|
|
367
|
+
if hasattr(Threads.State, "iterate"):
|
|
368
|
+
return Threads.State.iterate(conn, incremental=incremental, **kwargs)
|
|
369
|
+
# langgraph-runtime-inmem releases before ``iterate`` only have ``list``.
|
|
370
|
+
return _listed_history_states(conn, **kwargs)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
async def _listed_history_states(
|
|
374
|
+
conn: Any, **kwargs: Any
|
|
375
|
+
) -> "AsyncIterator[StateSnapshot]":
|
|
376
|
+
for state in await Threads.State.list(conn, **kwargs):
|
|
377
|
+
yield state
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
async def _serialize_history(
|
|
381
|
+
states: "AsyncIterator[StateSnapshot]", *, budget: int
|
|
382
|
+
) -> list[Fragment]:
|
|
383
|
+
"""Serialize history entries until they reach ``budget`` bytes (0: no limit).
|
|
384
|
+
|
|
385
|
+
The newest entry is always returned. Each later entry is returned only if
|
|
386
|
+
the response stays within the budget, and history stops at the first one
|
|
387
|
+
that does not.
|
|
388
|
+
"""
|
|
389
|
+
entries: list[Fragment] = []
|
|
390
|
+
total_bytes = 1 # the response array's opening bracket
|
|
391
|
+
async with aclosing(states):
|
|
392
|
+
async for state in states:
|
|
393
|
+
entry = json_dumpb(state_snapshot_to_thread_state(state))
|
|
394
|
+
# Drop the decoded state before the next checkpoint loads.
|
|
395
|
+
del state
|
|
396
|
+
# Each entry also adds a comma or the closing bracket.
|
|
397
|
+
total_bytes += len(entry) + 1
|
|
398
|
+
if budget and entries and total_bytes > budget:
|
|
399
|
+
break
|
|
400
|
+
entries.append(Fragment(entry))
|
|
401
|
+
if budget and total_bytes >= budget:
|
|
402
|
+
# Nothing more can fit, so don't load another checkpoint.
|
|
403
|
+
break
|
|
404
|
+
return entries
|
|
357
405
|
|
|
358
406
|
|
|
359
407
|
@retry_db
|
|
@@ -240,6 +240,23 @@ HTTP_MAX_REQUEST_BODY_BYTES = env(
|
|
|
240
240
|
"HTTP_MAX_REQUEST_BODY_BYTES", cast=int, default=300 * 1024 * 1024
|
|
241
241
|
)
|
|
242
242
|
|
|
243
|
+
|
|
244
|
+
def _validate_thread_history_budget(budget: int) -> int:
|
|
245
|
+
if budget < 0:
|
|
246
|
+
raise ValueError(
|
|
247
|
+
"LANGGRAPH_THREAD_HISTORY_MAX_STATE_BYTES must be 0 (disabled) or a "
|
|
248
|
+
f"positive number of bytes, got {budget}."
|
|
249
|
+
)
|
|
250
|
+
return budget
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# Byte budget for one history response, counted as the serialized size of its
|
|
254
|
+
# entries; every entry carries the full thread state. History stops before the
|
|
255
|
+
# entry that would cross it but always returns the newest. 0 disables it.
|
|
256
|
+
THREAD_HISTORY_MAX_STATE_BYTES = _validate_thread_history_budget(
|
|
257
|
+
env("LANGGRAPH_THREAD_HISTORY_MAX_STATE_BYTES", cast=int, default=0)
|
|
258
|
+
)
|
|
259
|
+
|
|
243
260
|
# gRPC message size limits (300MB default)
|
|
244
261
|
# Not in public docs: infrastructure, set by platform
|
|
245
262
|
LSD_GRPC_SERVER_MAX_RECV_MSG_BYTES = env(
|
|
@@ -565,6 +582,7 @@ LANGGRAPH_ENCRYPTION = env(
|
|
|
565
582
|
)
|
|
566
583
|
# Not in public docs: set by SaaS control plane, not user-configurable
|
|
567
584
|
LANGSMITH_TENANT_ID = env("LANGSMITH_TENANT_ID", cast=str, default=None)
|
|
585
|
+
LANGSMITH_HOST_PROJECT_ID = env("LANGSMITH_HOST_PROJECT_ID", cast=str, default=None)
|
|
568
586
|
LANGSMITH_AUTH_VERIFY_TENANT_ID = env(
|
|
569
587
|
"LANGSMITH_AUTH_VERIFY_TENANT_ID",
|
|
570
588
|
cast=bool,
|
|
@@ -870,6 +888,7 @@ __all__ = [
|
|
|
870
888
|
"STREAM_PUBLISH_RETRY_JITTER",
|
|
871
889
|
"STREAM_PUBLISH_RETRY_MAX_DURATION_SECS",
|
|
872
890
|
"STREAM_PUBLISH_RETRY_MAX_INTERVAL_SECS",
|
|
891
|
+
"THREAD_HISTORY_MAX_STATE_BYTES",
|
|
873
892
|
"THREAD_TTL",
|
|
874
893
|
"TRACING",
|
|
875
894
|
"UI_USE_BUNDLER",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import jsonschema_rs
|
|
2
2
|
import structlog
|
|
3
|
+
from langgraph.errors import EmptyInputError, InvalidUpdateError
|
|
3
4
|
from starlette.exceptions import HTTPException
|
|
4
5
|
from starlette.requests import Request
|
|
5
6
|
from starlette.responses import JSONResponse, Response
|
|
@@ -63,6 +64,21 @@ async def overloaded_error_handler(request, exc: ValueError):
|
|
|
63
64
|
)
|
|
64
65
|
|
|
65
66
|
|
|
67
|
+
def app_exception_handlers() -> dict:
|
|
68
|
+
"""The exception handlers shared by the server app and the operator routes."""
|
|
69
|
+
# Imported here because the runtime imports this module while it loads.
|
|
70
|
+
from langgraph_runtime.retry import OVERLOADED_EXCEPTIONS # noqa: PLC0415
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
HTTPException: http_exception_handler,
|
|
74
|
+
ValueError: value_error_handler,
|
|
75
|
+
InvalidUpdateError: value_error_handler,
|
|
76
|
+
EmptyInputError: value_error_handler,
|
|
77
|
+
jsonschema_rs.ValidationError: validation_error_handler,
|
|
78
|
+
RemoteException: remote_exception_handler,
|
|
79
|
+
} | {exc: overloaded_error_handler for exc in OVERLOADED_EXCEPTIONS}
|
|
80
|
+
|
|
81
|
+
|
|
66
82
|
class UserInterrupt(Exception):
|
|
67
83
|
def __init__(self, message="User interrupted the run"):
|
|
68
84
|
super().__init__(message)
|
|
@@ -71,6 +71,7 @@ from langgraph_api.utils import get_auth_ctx
|
|
|
71
71
|
|
|
72
72
|
if TYPE_CHECKING:
|
|
73
73
|
from collections.abc import AsyncIterator, Sequence
|
|
74
|
+
from datetime import datetime
|
|
74
75
|
|
|
75
76
|
from langgraph_api.schema import (
|
|
76
77
|
IfNotExists,
|
|
@@ -79,6 +80,7 @@ if TYPE_CHECKING:
|
|
|
79
80
|
PoolStats,
|
|
80
81
|
QueueStats,
|
|
81
82
|
Run,
|
|
83
|
+
RunCancelProgress,
|
|
82
84
|
RunSelectField,
|
|
83
85
|
RunStatus,
|
|
84
86
|
)
|
|
@@ -755,6 +757,25 @@ class Runs(Authenticated):
|
|
|
755
757
|
client = await get_shared_client()
|
|
756
758
|
await client.runs.Cancel(pb.CancelRunRequest(**request_kwargs))
|
|
757
759
|
|
|
760
|
+
@staticmethod
|
|
761
|
+
async def cancel_accepted_before(
|
|
762
|
+
conn,
|
|
763
|
+
accepted_before: datetime,
|
|
764
|
+
*,
|
|
765
|
+
reason: str,
|
|
766
|
+
) -> RunCancelProgress:
|
|
767
|
+
"""Applies no auth filters, so only the operator route may call it."""
|
|
768
|
+
client = await get_shared_client()
|
|
769
|
+
response = await client.runs.CancelAcceptedBefore(
|
|
770
|
+
pb.CancelAcceptedBeforeRequest(
|
|
771
|
+
accepted_before=accepted_before, reason=reason
|
|
772
|
+
)
|
|
773
|
+
)
|
|
774
|
+
return {
|
|
775
|
+
"not_yet_reached": response.not_yet_reached,
|
|
776
|
+
"finishing": response.finishing,
|
|
777
|
+
}
|
|
778
|
+
|
|
758
779
|
@staticmethod
|
|
759
780
|
async def stats(conn) -> QueueStats:
|
|
760
781
|
"""Get queue statistics (not exposed via API, no auth)."""
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
-
from contextlib import AsyncExitStack
|
|
6
|
+
from contextlib import AsyncExitStack, aclosing
|
|
7
7
|
from datetime import UTC
|
|
8
8
|
from http import HTTPStatus
|
|
9
9
|
from typing import TYPE_CHECKING, Any, Literal
|
|
@@ -46,7 +46,11 @@ from langgraph_api.grpc.ops import (
|
|
|
46
46
|
from langgraph_api.grpc.ops.runs import Runs
|
|
47
47
|
from langgraph_api.schema import ThreadUpdateResponse
|
|
48
48
|
from langgraph_api.serde import json_dumpb, json_dumpb_optional, json_loads
|
|
49
|
-
from langgraph_api.state import
|
|
49
|
+
from langgraph_api.state import (
|
|
50
|
+
iter_state_history,
|
|
51
|
+
patch_interrupt,
|
|
52
|
+
state_snapshot_to_thread_state,
|
|
53
|
+
)
|
|
50
54
|
from langgraph_api.utils import fetchone
|
|
51
55
|
|
|
52
56
|
if TYPE_CHECKING:
|
|
@@ -1330,7 +1334,7 @@ class Threads(Authenticated):
|
|
|
1330
1334
|
)
|
|
1331
1335
|
|
|
1332
1336
|
@staticmethod
|
|
1333
|
-
async def
|
|
1337
|
+
async def iterate(
|
|
1334
1338
|
conn, # Still needed for checkpointer
|
|
1335
1339
|
*,
|
|
1336
1340
|
config: dict[str, Any],
|
|
@@ -1338,8 +1342,13 @@ class Threads(Authenticated):
|
|
|
1338
1342
|
before: Any = None,
|
|
1339
1343
|
metadata: Any = None,
|
|
1340
1344
|
ctx: Any = None,
|
|
1341
|
-
|
|
1342
|
-
|
|
1345
|
+
incremental: bool = False,
|
|
1346
|
+
) -> AsyncIterator[StateSnapshot]:
|
|
1347
|
+
"""Yield the history of a thread.
|
|
1348
|
+
|
|
1349
|
+
With ``incremental``, checkpoints load in growing pages, so a
|
|
1350
|
+
caller that stops early does not load the rest of ``limit``.
|
|
1351
|
+
"""
|
|
1343
1352
|
async with conn.pipeline():
|
|
1344
1353
|
thread, graph_id = await asyncio.gather(
|
|
1345
1354
|
Threads.get(
|
|
@@ -1372,18 +1381,26 @@ class Threads(Authenticated):
|
|
|
1372
1381
|
store=(await api_store.get_store()),
|
|
1373
1382
|
access_context="threads.read",
|
|
1374
1383
|
) as graph:
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1384
|
+
before_config = (
|
|
1385
|
+
{"configurable": {"checkpoint_id": before}}
|
|
1386
|
+
if isinstance(before, str)
|
|
1387
|
+
else before
|
|
1388
|
+
)
|
|
1389
|
+
history = (
|
|
1390
|
+
iter_state_history(
|
|
1391
|
+
graph,
|
|
1378
1392
|
config,
|
|
1379
1393
|
limit=limit,
|
|
1380
1394
|
filter=metadata,
|
|
1381
|
-
before=
|
|
1382
|
-
{"configurable": {"checkpoint_id": before}}
|
|
1383
|
-
if isinstance(before, str)
|
|
1384
|
-
else before
|
|
1385
|
-
),
|
|
1395
|
+
before=before_config,
|
|
1386
1396
|
)
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1397
|
+
if incremental
|
|
1398
|
+
else graph.aget_state_history(
|
|
1399
|
+
config, limit=limit, filter=metadata, before=before_config
|
|
1400
|
+
)
|
|
1401
|
+
)
|
|
1402
|
+
async with aclosing(history) as states:
|
|
1403
|
+
async for c in states:
|
|
1404
|
+
yield c
|
|
1405
|
+
# Drop the entry before the next page loads.
|
|
1406
|
+
del c
|
|
@@ -1506,9 +1506,9 @@ postcss-modules@^6.0.1:
|
|
|
1506
1506
|
string-hash "^1.1.3"
|
|
1507
1507
|
|
|
1508
1508
|
postcss-selector-parser@^7.0.0:
|
|
1509
|
-
version "7.1.
|
|
1510
|
-
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.
|
|
1511
|
-
integrity sha512-
|
|
1509
|
+
version "7.1.6"
|
|
1510
|
+
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.6.tgz#45e970f2d93d4547d6754167ed1132f43012c4bf"
|
|
1511
|
+
integrity sha512-7qASPzhKF2l2KLboRZux8CCTRMdGiV08vWmyKzPz22qZ7ZjQBOeY7rNzNoCLSUiftJ7HUq0GERHmxw/t0dCdMw==
|
|
1512
1512
|
dependencies:
|
|
1513
1513
|
cssesc "^3.0.0"
|
|
1514
1514
|
util-deprecate "^1.0.2"
|
|
@@ -1630,9 +1630,9 @@ siginfo@^2.0.0:
|
|
|
1630
1630
|
integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==
|
|
1631
1631
|
|
|
1632
1632
|
source-map-js@^1.2.1:
|
|
1633
|
-
version "1.2.
|
|
1634
|
-
resolved "https://registry.
|
|
1635
|
-
integrity sha512-
|
|
1633
|
+
version "1.2.2"
|
|
1634
|
+
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.2.tgz#79fb88d97535a21cb27162cb05d211b67acea4ab"
|
|
1635
|
+
integrity sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==
|
|
1636
1636
|
|
|
1637
1637
|
stack-trace@0.0.x:
|
|
1638
1638
|
version "0.0.10"
|
|
@@ -1732,10 +1732,10 @@ type-fest@^0.7.1:
|
|
|
1732
1732
|
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz"
|
|
1733
1733
|
integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==
|
|
1734
1734
|
|
|
1735
|
-
typescript@^
|
|
1736
|
-
version "
|
|
1737
|
-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-
|
|
1738
|
-
integrity sha512-
|
|
1735
|
+
typescript@^6.0.3:
|
|
1736
|
+
version "6.0.3"
|
|
1737
|
+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.3.tgz#90251dc007916e972786cb94d74d15b185577d21"
|
|
1738
|
+
integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==
|
|
1739
1739
|
|
|
1740
1740
|
undici-types@~8.3.0:
|
|
1741
1741
|
version "8.3.0"
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""Operator routes: deployment-wide actions a LangSmith admin can take on a deployment.
|
|
2
|
+
|
|
3
|
+
They are served before every other middleware, so customer middleware and custom
|
|
4
|
+
auth handlers can't block or filter them. Instead, host-backend checks the admin's
|
|
5
|
+
permission and calls them with a short-lived service token scoped to one operation on
|
|
6
|
+
this deployment, which LangSmith verifies. See THREAT_MODEL.md.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import contextlib
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from datetime import UTC, datetime, timedelta
|
|
14
|
+
from typing import TYPE_CHECKING, Any
|
|
15
|
+
from uuid import UUID
|
|
16
|
+
|
|
17
|
+
import httpx
|
|
18
|
+
import structlog
|
|
19
|
+
from starlette.applications import Starlette
|
|
20
|
+
from starlette.exceptions import HTTPException
|
|
21
|
+
from starlette.responses import JSONResponse, Response
|
|
22
|
+
from starlette.routing import Route
|
|
23
|
+
|
|
24
|
+
from langgraph_api import config
|
|
25
|
+
from langgraph_api.auth.langsmith.client import create_client
|
|
26
|
+
from langgraph_api.errors import app_exception_handlers
|
|
27
|
+
from langgraph_api.feature_flags import IS_POSTGRES_OR_GRPC_BACKEND
|
|
28
|
+
from langgraph_runtime.database import connect
|
|
29
|
+
|
|
30
|
+
if IS_POSTGRES_OR_GRPC_BACKEND:
|
|
31
|
+
from langgraph_api.grpc.ops import Runs
|
|
32
|
+
else:
|
|
33
|
+
from langgraph_runtime.ops import Runs
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from starlette.requests import Request
|
|
37
|
+
from starlette.types import ASGIApp, Message, Receive, Scope, Send
|
|
38
|
+
|
|
39
|
+
logger = structlog.stdlib.get_logger(__name__)
|
|
40
|
+
|
|
41
|
+
CANCEL_RUNS_PATH = "/operator/runs/cancel"
|
|
42
|
+
|
|
43
|
+
_OPERATOR_TOKEN_PATH = "/auth/operator-token"
|
|
44
|
+
_INTERRUPT = "interrupt"
|
|
45
|
+
|
|
46
|
+
# host-backend fixes the boundary at the press and mints every token after it, so a
|
|
47
|
+
# boundary later than the token's issue time would cancel runs accepted after the
|
|
48
|
+
# press. The allowance only covers clock differences between host-backend replicas.
|
|
49
|
+
_BOUNDARY_SKEW = timedelta(seconds=5)
|
|
50
|
+
|
|
51
|
+
# The route's refusal for each LangSmith answer other than 200. Anything not listed
|
|
52
|
+
# means LangSmith couldn't answer.
|
|
53
|
+
_LANGSMITH_REFUSALS = {
|
|
54
|
+
401: (401, "invalid_token"),
|
|
55
|
+
# A LangSmith release without operator tokens can't authorize this route.
|
|
56
|
+
404: (503, "langsmith_upgrade_required"),
|
|
57
|
+
405: (503, "langsmith_upgrade_required"),
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class _OperatorToken:
|
|
63
|
+
"""The cancellation a verified operator token authorizes."""
|
|
64
|
+
|
|
65
|
+
operation_id: UUID
|
|
66
|
+
user_id: UUID
|
|
67
|
+
accepted_before: datetime
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class OperatorRoutesMiddleware:
|
|
71
|
+
"""Serves the operator routes and passes every other request through."""
|
|
72
|
+
|
|
73
|
+
def __init__(self, app: ASGIApp, mount_prefix: str | None = None) -> None:
|
|
74
|
+
self.app = app
|
|
75
|
+
self.cancel_runs_paths = {CANCEL_RUNS_PATH}
|
|
76
|
+
if mount_prefix:
|
|
77
|
+
self.cancel_runs_paths.add(mount_prefix + CANCEL_RUNS_PATH)
|
|
78
|
+
# Its own small app with the server's error handlers, since these requests
|
|
79
|
+
# never reach the main app.
|
|
80
|
+
self.operator_app = Starlette(
|
|
81
|
+
routes=[
|
|
82
|
+
Route(path, cancel_runs, methods=["POST"])
|
|
83
|
+
for path in self.cancel_runs_paths
|
|
84
|
+
],
|
|
85
|
+
exception_handlers=app_exception_handlers(),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
|
89
|
+
if scope["type"] != "http" or scope["path"] not in self.cancel_runs_paths:
|
|
90
|
+
await self.app(scope, receive, send)
|
|
91
|
+
return
|
|
92
|
+
status = None
|
|
93
|
+
|
|
94
|
+
async def send_recording_status(message: Message) -> None:
|
|
95
|
+
nonlocal status
|
|
96
|
+
if message["type"] == "http.response.start":
|
|
97
|
+
status = message["status"]
|
|
98
|
+
await send(message)
|
|
99
|
+
|
|
100
|
+
# Every operator request gets exactly one log line, including ones that fail
|
|
101
|
+
# unexpectedly; customer request logging never sees them.
|
|
102
|
+
try:
|
|
103
|
+
await self.operator_app(scope, receive, send_recording_status)
|
|
104
|
+
except Exception:
|
|
105
|
+
await logger.aexception("Operator request", **_log_fields(scope, status))
|
|
106
|
+
raise
|
|
107
|
+
await logger.ainfo("Operator request", **_log_fields(scope, status))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _log_fields(scope: Scope, status: int | None) -> dict[str, Any]:
|
|
111
|
+
# cancel_runs records the verified operation and the progress on the request state.
|
|
112
|
+
learned = scope.get("state", {}).get("operator_log_fields", {})
|
|
113
|
+
return {
|
|
114
|
+
"path": scope["path"],
|
|
115
|
+
"method": scope["method"],
|
|
116
|
+
"status": status,
|
|
117
|
+
} | learned
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
async def cancel_runs(request: Request) -> Response:
|
|
121
|
+
"""Interrupt every in-flight run accepted at or before the token's boundary.
|
|
122
|
+
|
|
123
|
+
The operation, boundary and user all come from the verified token; the request
|
|
124
|
+
body is ignored. One call cancels a bounded amount of work and returns how many
|
|
125
|
+
targets are still in flight, and the caller repeats it until both counts are zero.
|
|
126
|
+
"""
|
|
127
|
+
token = await _verify_token(request)
|
|
128
|
+
log_fields = {
|
|
129
|
+
"operation_id": str(token.operation_id),
|
|
130
|
+
"user_id": str(token.user_id),
|
|
131
|
+
}
|
|
132
|
+
request.state.operator_log_fields = log_fields
|
|
133
|
+
|
|
134
|
+
# Built only from fixed text and UUIDs, never from text in the request.
|
|
135
|
+
reason = (
|
|
136
|
+
f"cancelled by kill switch (operation {token.operation_id}, "
|
|
137
|
+
f"requested by LangSmith user {token.user_id})"
|
|
138
|
+
)
|
|
139
|
+
async with connect() as conn:
|
|
140
|
+
progress = await Runs.cancel_accepted_before(
|
|
141
|
+
conn, token.accepted_before, reason=reason
|
|
142
|
+
)
|
|
143
|
+
log_fields.update(progress)
|
|
144
|
+
return JSONResponse(progress)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async def _verify_token(request: Request) -> _OperatorToken:
|
|
148
|
+
"""Return the cancellation the request's operator token authorizes here.
|
|
149
|
+
|
|
150
|
+
LangSmith checks the token's signature, audience, subject and expiry on every
|
|
151
|
+
call, with no cache. This route checks that the token names this deployment and
|
|
152
|
+
an interrupt. Anything short of that is a refusal.
|
|
153
|
+
"""
|
|
154
|
+
tenant_id = _as_uuid(config.LANGSMITH_TENANT_ID)
|
|
155
|
+
deployment_id = _as_uuid(config.LANGSMITH_HOST_PROJECT_ID)
|
|
156
|
+
if tenant_id is None or deployment_id is None:
|
|
157
|
+
# Only a deployment LangSmith manages is sent operator tokens.
|
|
158
|
+
raise HTTPException(404)
|
|
159
|
+
token = request.headers.get("x-service-key")
|
|
160
|
+
if not token:
|
|
161
|
+
raise HTTPException(401, "missing_token")
|
|
162
|
+
# A client per call, so nothing one verification leaves behind (such as a
|
|
163
|
+
# cookie) reaches the next.
|
|
164
|
+
auth = create_client()
|
|
165
|
+
try:
|
|
166
|
+
response = await auth.get(
|
|
167
|
+
_OPERATOR_TOKEN_PATH, headers={"X-Service-Key": token}
|
|
168
|
+
)
|
|
169
|
+
except httpx.HTTPError as exc:
|
|
170
|
+
raise HTTPException(503, "langsmith_unavailable") from exc
|
|
171
|
+
finally:
|
|
172
|
+
await auth.client.aclose()
|
|
173
|
+
if response.status_code != 200:
|
|
174
|
+
status, detail = _LANGSMITH_REFUSALS.get(
|
|
175
|
+
response.status_code, (503, "langsmith_unavailable")
|
|
176
|
+
)
|
|
177
|
+
raise HTTPException(status, detail)
|
|
178
|
+
try:
|
|
179
|
+
claims = response.json()
|
|
180
|
+
except ValueError as exc:
|
|
181
|
+
raise HTTPException(503, "langsmith_unavailable") from exc
|
|
182
|
+
if not isinstance(claims, dict):
|
|
183
|
+
raise HTTPException(503, "langsmith_unavailable")
|
|
184
|
+
|
|
185
|
+
operation_id = _as_uuid(claims.get("operation_id"))
|
|
186
|
+
user_id = _as_uuid(claims.get("user_id"))
|
|
187
|
+
accepted_before = _as_datetime(claims.get("accepted_before"))
|
|
188
|
+
issued_at = _as_timestamp(claims.get("issued_at"))
|
|
189
|
+
if (
|
|
190
|
+
_as_uuid(claims.get("tenant_id")) != tenant_id
|
|
191
|
+
or _as_uuid(claims.get("deployment_id")) != deployment_id
|
|
192
|
+
or claims.get("action") != _INTERRUPT
|
|
193
|
+
or operation_id is None
|
|
194
|
+
or user_id is None
|
|
195
|
+
or accepted_before is None
|
|
196
|
+
or issued_at is None
|
|
197
|
+
or accepted_before > issued_at + _BOUNDARY_SKEW
|
|
198
|
+
):
|
|
199
|
+
raise HTTPException(403, "forbidden")
|
|
200
|
+
return _OperatorToken(operation_id, user_id, accepted_before)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _as_uuid(value: Any) -> UUID | None:
|
|
204
|
+
if isinstance(value, str):
|
|
205
|
+
with contextlib.suppress(ValueError):
|
|
206
|
+
return UUID(value)
|
|
207
|
+
return None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _as_timestamp(value: Any) -> datetime | None:
|
|
211
|
+
if isinstance(value, int | float) and not isinstance(value, bool):
|
|
212
|
+
with contextlib.suppress(OverflowError, OSError, ValueError):
|
|
213
|
+
return datetime.fromtimestamp(value, UTC)
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _as_datetime(value: Any) -> datetime | None:
|
|
218
|
+
if isinstance(value, str):
|
|
219
|
+
with contextlib.suppress(ValueError):
|
|
220
|
+
parsed = datetime.fromisoformat(value)
|
|
221
|
+
if parsed.tzinfo is not None:
|
|
222
|
+
return parsed
|
|
223
|
+
return None
|
|
@@ -325,6 +325,15 @@ class QueueStats(TypedDict):
|
|
|
325
325
|
pending_unblocked_runs_wait_time_max_secs: float | None
|
|
326
326
|
|
|
327
327
|
|
|
328
|
+
class RunCancelProgress(TypedDict):
|
|
329
|
+
"""Targets of a cancel-by-boundary still in flight."""
|
|
330
|
+
|
|
331
|
+
not_yet_reached: int
|
|
332
|
+
"""Targets with no cancel intent yet."""
|
|
333
|
+
finishing: int
|
|
334
|
+
"""Targets that have a cancel intent and haven't stopped yet."""
|
|
335
|
+
|
|
336
|
+
|
|
328
337
|
# Canonical field sets for select= validation and type aliases for ops
|
|
329
338
|
|
|
330
339
|
# Assistant select fields (intentionally excludes 'context')
|