langgraph-api 0.9.0.dev6__tar.gz → 0.10.0rc1__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.10.0rc1}/PKG-INFO +3 -3
- langgraph_api-0.10.0rc1/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/custom.py +115 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/service.py +251 -66
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/types.py +6 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/pyproject.toml +2 -2
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/uv.lock +4 -4
- langgraph_api-0.9.0.dev6/langgraph_api/__init__.py +0 -1
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/.gitignore +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/LICENSE +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/Makefile +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/README.md +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/.gitignore +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/Makefile +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/README.md +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/capacity_dd_report.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/capacity_k6.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/capacity_runner.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/capacity_slack_report.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/capacity_urls.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/clean.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/continuous/uv.lock +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/graphs.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/mixed_workload_k6.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/mixed_workload_runner.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/package.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/ramp.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/reporting/slack_slowest_runs.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/reporting/slack_summary.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/run_local.sh +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/staircase.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/benchmark/weather.js +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/constraints.txt +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/custom_store.sql +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/forbidden.txt +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/hatch_build.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/healthcheck.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/event_streaming.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/threads.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/command.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/config/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/config/schemas.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/ops/runs.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/ops/threads.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/http.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/package.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/js/yarn.lock +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/metrics_datadog.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/route.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/schema.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/server.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/state.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/core_api_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/core_api_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/logging.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/openapi.json +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/scripts/create_license.py +0 -0
- {langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/scripts/run_a2a_tck.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0rc1
|
|
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
|
|
@@ -14,9 +14,9 @@ Requires-Dist: httptools>=0.5.0; platform_system != 'Windows'
|
|
|
14
14
|
Requires-Dist: httpx>=0.25.0
|
|
15
15
|
Requires-Dist: jsonschema-rs<0.45,>=0.20.0
|
|
16
16
|
Requires-Dist: langchain-core>=0.3.64
|
|
17
|
-
Requires-Dist: langchain-protocol<0.1,>=0.0.
|
|
17
|
+
Requires-Dist: langchain-protocol<0.1,>=0.0.16
|
|
18
18
|
Requires-Dist: langgraph-checkpoint<5,>=3.0.1
|
|
19
|
-
Requires-Dist: langgraph-runtime-inmem<0.
|
|
19
|
+
Requires-Dist: langgraph-runtime-inmem<0.31.0.dev0,>=0.30.0.dev0
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.10.0rc1"
|
|
@@ -250,6 +250,12 @@ def _get_custom_auth_middleware(
|
|
|
250
250
|
' return "my-user-id"'
|
|
251
251
|
)
|
|
252
252
|
|
|
253
|
+
# We are wiring custom auth into the server middleware stack — emit the
|
|
254
|
+
# missing-handler warning here (once at startup) rather than inside
|
|
255
|
+
# `_get_auth_instance`, which is also reached from per-request dispatch
|
|
256
|
+
# and from telemetry helpers that have no opinion about coverage.
|
|
257
|
+
_warn_on_missing_handlers(auth_instance)
|
|
258
|
+
|
|
253
259
|
result = CustomAuthBackend(
|
|
254
260
|
auth_instance._authenticate_handler,
|
|
255
261
|
disable_studio_auth,
|
|
@@ -276,6 +282,115 @@ def _get_auth_instance(path: str | None = None) -> Auth | Literal["js"] | None:
|
|
|
276
282
|
return auth_instance
|
|
277
283
|
|
|
278
284
|
|
|
285
|
+
def _derive_known_resource_actions(auth: Auth) -> dict[str, frozenset[str]]:
|
|
286
|
+
"""Walk an ``Auth.on`` namespace to discover every (resource, action) pair
|
|
287
|
+
the SDK supports for handler registration.
|
|
288
|
+
|
|
289
|
+
The SDK's ``_On`` class declares ``__slots__`` listing top-level resource
|
|
290
|
+
namespaces (``assistants``, ``threads``, ``crons``, ``store``). Inside
|
|
291
|
+
each namespace, the SDK installs one ``_ResourceActionOn`` /
|
|
292
|
+
``_StoreActionOn`` instance per supported action, each carrying a
|
|
293
|
+
``.action`` string attribute (and a ``.resource`` for the non-store ones).
|
|
294
|
+
Duck-typing on those attributes avoids a hand-maintained list and keeps
|
|
295
|
+
this in sync as the SDK adds resources/actions.
|
|
296
|
+
"""
|
|
297
|
+
on = auth.on
|
|
298
|
+
matrix: dict[str, set[str]] = {}
|
|
299
|
+
for slot in getattr(type(on), "__slots__", ()) or ():
|
|
300
|
+
if slot.startswith("_") or slot == "value":
|
|
301
|
+
continue
|
|
302
|
+
namespace = getattr(on, slot, None)
|
|
303
|
+
if namespace is None:
|
|
304
|
+
continue
|
|
305
|
+
for attr_name in dir(namespace):
|
|
306
|
+
if attr_name.startswith("_"):
|
|
307
|
+
continue
|
|
308
|
+
attr = getattr(namespace, attr_name, None)
|
|
309
|
+
action = getattr(attr, "action", None)
|
|
310
|
+
if not isinstance(action, str):
|
|
311
|
+
continue
|
|
312
|
+
# `_StoreActionOn` doesn't carry `.resource` (it's always
|
|
313
|
+
# "store"); fall back to the outer namespace name.
|
|
314
|
+
resource = getattr(attr, "resource", slot)
|
|
315
|
+
if not isinstance(resource, str):
|
|
316
|
+
continue
|
|
317
|
+
matrix.setdefault(resource, set()).add(action)
|
|
318
|
+
return {resource: frozenset(actions) for resource, actions in matrix.items()}
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def _missing_handler_paths(auth: Auth) -> list[tuple[str, str]]:
|
|
322
|
+
"""Return ``(resource, action)`` pairs with no matching authorization handler.
|
|
323
|
+
|
|
324
|
+
Mirrors the dispatch precedence in :func:`_get_handler`:
|
|
325
|
+
- specific ``(resource, action)``
|
|
326
|
+
- resource wildcard ``(resource, "*")``
|
|
327
|
+
- action wildcard ``("*", action)``
|
|
328
|
+
- full wildcard ``("*", "*")`` registered via ``auth.on(resources=["*"], actions=["*"])``
|
|
329
|
+
- global ``@auth.on``
|
|
330
|
+
|
|
331
|
+
Either of the last two covers everything, so an empty list is returned
|
|
332
|
+
in those cases. Otherwise the returned list enumerates every
|
|
333
|
+
resource/action pair the server may dispatch which would currently fall
|
|
334
|
+
through to "allow".
|
|
335
|
+
"""
|
|
336
|
+
if auth._global_handlers:
|
|
337
|
+
return []
|
|
338
|
+
handlers = auth._handlers
|
|
339
|
+
# `auth.on(resources=["*"], actions=["*"])` stores under ("*", "*") in
|
|
340
|
+
# `_handlers` (not `_global_handlers`) and `_get_handler` matches it as
|
|
341
|
+
# the final fallback before `_global_handlers`. Treat it as full coverage.
|
|
342
|
+
if ("*", "*") in handlers:
|
|
343
|
+
return []
|
|
344
|
+
missing: list[tuple[str, str]] = []
|
|
345
|
+
for resource, actions in _derive_known_resource_actions(auth).items():
|
|
346
|
+
for action in actions:
|
|
347
|
+
if (resource, action) in handlers:
|
|
348
|
+
continue
|
|
349
|
+
if (resource, "*") in handlers:
|
|
350
|
+
continue
|
|
351
|
+
if ("*", action) in handlers:
|
|
352
|
+
continue
|
|
353
|
+
missing.append((resource, action))
|
|
354
|
+
return missing
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def _warn_on_missing_handlers(auth: Auth) -> None:
|
|
358
|
+
"""Log a warning when the user has registered some auth handlers but
|
|
359
|
+
left other dispatch paths uncovered.
|
|
360
|
+
|
|
361
|
+
Custom auth currently fails open: a request whose ``(resource, action)``
|
|
362
|
+
has no matching handler is allowed without filtering. This is a common
|
|
363
|
+
source of cross-user authorization bugs (see GHSA-38q2-qc5v-fccw and
|
|
364
|
+
related issues), so we surface a warning at startup listing every
|
|
365
|
+
uncovered path and a suggested default-deny snippet.
|
|
366
|
+
|
|
367
|
+
"""
|
|
368
|
+
if not auth._handlers and not auth._global_handlers:
|
|
369
|
+
# Auth instance with only an `@auth.authenticate` handler — the user
|
|
370
|
+
# hasn't opted into resource-level authorization at all, so warning
|
|
371
|
+
# about every path would be too noisy. The auth dispatch is a no-op
|
|
372
|
+
# in this case.
|
|
373
|
+
return
|
|
374
|
+
missing = _missing_handler_paths(auth)
|
|
375
|
+
if not missing:
|
|
376
|
+
return
|
|
377
|
+
paths = sorted(f"{resource}.{action}" for resource, action in missing)
|
|
378
|
+
logger.warning(
|
|
379
|
+
"Custom auth has no handler registered for some dispatch paths. "
|
|
380
|
+
"Authentication (@auth.authenticate) still applies, but requests "
|
|
381
|
+
"to these paths will be allowed without resource-level authorization "
|
|
382
|
+
"checks (a common source of cross-user data leaks).",
|
|
383
|
+
missing_paths=paths,
|
|
384
|
+
suggestion=(
|
|
385
|
+
"Add a default-deny global handler and override per-resource "
|
|
386
|
+
"as needed:\n"
|
|
387
|
+
" @auth.on\n"
|
|
388
|
+
" async def deny_all(ctx, value):\n"
|
|
389
|
+
" return False"
|
|
390
|
+
),
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
|
|
279
394
|
def _extract_arguments_from_scope(
|
|
280
395
|
scope: Mapping[str, Any],
|
|
281
396
|
param_names: set[str],
|
{langgraph_api-0.9.0.dev6 → langgraph_api-0.10.0rc1}/langgraph_api/event_streaming/service.py
RENAMED
|
@@ -22,8 +22,8 @@ import asyncio
|
|
|
22
22
|
import contextlib
|
|
23
23
|
import inspect
|
|
24
24
|
from collections.abc import Awaitable, Callable
|
|
25
|
-
from typing import Any, cast
|
|
26
|
-
from uuid import uuid4
|
|
25
|
+
from typing import Any, cast, get_args
|
|
26
|
+
from uuid import UUID, uuid4
|
|
27
27
|
|
|
28
28
|
import orjson
|
|
29
29
|
import structlog
|
|
@@ -43,6 +43,7 @@ from langgraph_api.event_streaming.session import (
|
|
|
43
43
|
)
|
|
44
44
|
from langgraph_api.event_streaming.types import Subscription
|
|
45
45
|
from langgraph_api.feature_flags import FF_V2_EVENT_STREAMING
|
|
46
|
+
from langgraph_api.schema import MultitaskStrategy
|
|
46
47
|
|
|
47
48
|
logger = structlog.stdlib.get_logger(__name__)
|
|
48
49
|
|
|
@@ -51,6 +52,75 @@ def _is_record(value: Any) -> bool:
|
|
|
51
52
|
return isinstance(value, dict)
|
|
52
53
|
|
|
53
54
|
|
|
55
|
+
def _checkpoint_id_from_run_start_config(params: dict[str, Any]) -> str | None:
|
|
56
|
+
"""Extract ``config.configurable.checkpoint_id`` from ``run.start`` params.
|
|
57
|
+
|
|
58
|
+
Protocol v2 clients pass fork/time-travel targets via RunnableConfig::
|
|
59
|
+
|
|
60
|
+
{
|
|
61
|
+
"input": null,
|
|
62
|
+
"config": { "configurable": { "checkpoint_id": "<uuid>" } },
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Returns the checkpoint id (validated as a non-empty string) or ``None``
|
|
66
|
+
when no fork target is present.
|
|
67
|
+
"""
|
|
68
|
+
config = params.get("config")
|
|
69
|
+
if not _is_record(config):
|
|
70
|
+
return None
|
|
71
|
+
configurable = config.get("configurable")
|
|
72
|
+
if not _is_record(configurable):
|
|
73
|
+
return None
|
|
74
|
+
checkpoint_id = configurable.get("checkpoint_id")
|
|
75
|
+
if checkpoint_id is None:
|
|
76
|
+
return None
|
|
77
|
+
if not isinstance(checkpoint_id, str) or not checkpoint_id.strip():
|
|
78
|
+
raise ValueError(
|
|
79
|
+
"config.configurable.checkpoint_id must be a non-empty string."
|
|
80
|
+
)
|
|
81
|
+
return checkpoint_id
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def validate_checkpoint_id_from_runnable_config(params: dict[str, Any]) -> str | None:
|
|
85
|
+
"""Return a client-facing validation message, or ``None`` if valid/absent."""
|
|
86
|
+
try:
|
|
87
|
+
checkpoint_id = _checkpoint_id_from_run_start_config(params)
|
|
88
|
+
except ValueError as exc:
|
|
89
|
+
return str(exc)
|
|
90
|
+
if checkpoint_id is None:
|
|
91
|
+
return None
|
|
92
|
+
try:
|
|
93
|
+
UUID(checkpoint_id)
|
|
94
|
+
except ValueError:
|
|
95
|
+
return f"Invalid config.configurable.checkpoint_id: {checkpoint_id!r}."
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Concurrency strategies accepted on ``run.start`` — the four values the
|
|
100
|
+
# SDK's ``multitaskStrategy`` option can take, derived from the canonical
|
|
101
|
+
# ``MultitaskStrategy`` literal so the two never drift.
|
|
102
|
+
VALID_MULTITASK_STRATEGIES: tuple[str, ...] = get_args(MultitaskStrategy)
|
|
103
|
+
# Legacy stream-endpoint default: queue new runs behind active ones instead
|
|
104
|
+
# of interrupting. Used when the caller omits ``multitaskStrategy``.
|
|
105
|
+
DEFAULT_MULTITASK_STRATEGY = "enqueue"
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _multitask_strategy_from_run_start(params: dict[str, Any]) -> str:
|
|
109
|
+
"""Resolve the per-run ``multitaskStrategy`` from ``run.start`` params.
|
|
110
|
+
|
|
111
|
+
The SDK forwards the caller's ``multitaskStrategy`` on every
|
|
112
|
+
``run.start`` (one of ``reject`` | ``rollback`` | ``interrupt`` |
|
|
113
|
+
``enqueue``). Honor it when it is one of the recognized strategies,
|
|
114
|
+
otherwise fall back to ``DEFAULT_MULTITASK_STRATEGY`` (the legacy
|
|
115
|
+
stream-endpoint default). This mirrors the JS reference server's
|
|
116
|
+
lenient normalization so both behave identically.
|
|
117
|
+
"""
|
|
118
|
+
strategy = params.get("multitaskStrategy")
|
|
119
|
+
if isinstance(strategy, str) and strategy in VALID_MULTITASK_STRATEGIES:
|
|
120
|
+
return strategy
|
|
121
|
+
return DEFAULT_MULTITASK_STRATEGY
|
|
122
|
+
|
|
123
|
+
|
|
54
124
|
EventSink = Callable[[dict[str, Any]], Awaitable[None] | None]
|
|
55
125
|
|
|
56
126
|
|
|
@@ -401,6 +471,10 @@ class ThreadRunManager:
|
|
|
401
471
|
"run.start requires an assistant_id.",
|
|
402
472
|
)
|
|
403
473
|
|
|
474
|
+
checkpoint_error = validate_checkpoint_id_from_runnable_config(params)
|
|
475
|
+
if checkpoint_error is not None:
|
|
476
|
+
return self._error(command.get("id"), "invalid_argument", checkpoint_error)
|
|
477
|
+
|
|
404
478
|
try:
|
|
405
479
|
run = await self._create_or_resume_run(assistant_id, params)
|
|
406
480
|
except ProtocolV2UnsupportedError as exc:
|
|
@@ -419,69 +493,150 @@ class ThreadRunManager:
|
|
|
419
493
|
"meta": self._meta(),
|
|
420
494
|
}
|
|
421
495
|
|
|
422
|
-
|
|
423
|
-
|
|
496
|
+
@staticmethod
|
|
497
|
+
def _coerce_respond_namespace(raw: Any) -> list[str] | None:
|
|
498
|
+
"""Validate an ``input.respond`` namespace.
|
|
499
|
+
|
|
500
|
+
CDDL ``InputRespondParams`` marks ``namespace`` as required, but an
|
|
501
|
+
omitted value is treated as the root namespace (``[]``). Returns the
|
|
502
|
+
coerced list, or ``None`` when the value is not a list of strings.
|
|
503
|
+
"""
|
|
504
|
+
if not isinstance(raw, list) or not all(isinstance(seg, str) for seg in raw):
|
|
505
|
+
return None
|
|
506
|
+
return list(raw)
|
|
507
|
+
|
|
508
|
+
def _normalize_respond_entries(
|
|
509
|
+
self, cmd_id: int | None, params: dict[str, Any]
|
|
510
|
+
) -> tuple[list[tuple[str, list[str], Any]] | None, dict[str, Any] | None]:
|
|
511
|
+
"""Normalize ``input.respond`` params into resume entries.
|
|
512
|
+
|
|
513
|
+
Clients send either a single ``interrupt_id`` / ``response`` (with an
|
|
514
|
+
optional ``namespace``) or a ``responses`` batch — a list of
|
|
515
|
+
``{interrupt_id, response, namespace?}`` objects. The batch form
|
|
516
|
+
resumes several interrupts pending at the same checkpoint (e.g.
|
|
517
|
+
parallel tool-authorization prompts) in one command; sequential
|
|
518
|
+
single resumes cannot, since the first resume starts a run, leaving
|
|
519
|
+
the rest with no interrupted run to respond to. Both forms are part
|
|
520
|
+
of the streaming protocol (``InputRespondParams`` =
|
|
521
|
+
``InputRespondOne / InputRespondMany``); the batch entries are read
|
|
522
|
+
leniently to tolerate clients pinned to older bindings.
|
|
523
|
+
|
|
524
|
+
Returns ``(entries, None)`` on success or ``(None, error)`` with a
|
|
525
|
+
protocol error envelope. Each entry is
|
|
526
|
+
``(interrupt_id, namespace, response)``.
|
|
527
|
+
"""
|
|
528
|
+
raw_responses = params.get("responses")
|
|
529
|
+
if isinstance(raw_responses, list):
|
|
530
|
+
if not raw_responses:
|
|
531
|
+
return None, self._error(
|
|
532
|
+
cmd_id,
|
|
533
|
+
"invalid_argument",
|
|
534
|
+
"input.respond requires at least one response.",
|
|
535
|
+
)
|
|
536
|
+
entries: list[tuple[str, list[str], Any]] = []
|
|
537
|
+
for entry in raw_responses:
|
|
538
|
+
if not _is_record(entry):
|
|
539
|
+
return None, self._error(
|
|
540
|
+
cmd_id,
|
|
541
|
+
"invalid_argument",
|
|
542
|
+
"input.respond responses entries must be objects.",
|
|
543
|
+
)
|
|
544
|
+
entry_id = entry.get("interrupt_id")
|
|
545
|
+
if not isinstance(entry_id, str):
|
|
546
|
+
return None, self._error(
|
|
547
|
+
cmd_id,
|
|
548
|
+
"invalid_argument",
|
|
549
|
+
"input.respond responses entries require an interrupt_id.",
|
|
550
|
+
)
|
|
551
|
+
namespace = self._coerce_respond_namespace(entry.get("namespace", []))
|
|
552
|
+
if namespace is None:
|
|
553
|
+
return None, self._error(
|
|
554
|
+
cmd_id,
|
|
555
|
+
"invalid_argument",
|
|
556
|
+
"input.respond requires namespace to be a list of strings.",
|
|
557
|
+
)
|
|
558
|
+
entries.append((entry_id, namespace, entry.get("response")))
|
|
559
|
+
return entries, None
|
|
560
|
+
|
|
424
561
|
interrupt_id = params.get("interrupt_id")
|
|
425
562
|
if not isinstance(interrupt_id, str):
|
|
426
|
-
return self._error(
|
|
427
|
-
|
|
563
|
+
return None, self._error(
|
|
564
|
+
cmd_id,
|
|
428
565
|
"invalid_argument",
|
|
429
566
|
"input.respond requires an interrupt_id.",
|
|
430
567
|
)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if not isinstance(raw_namespace, list) or not all(
|
|
436
|
-
isinstance(seg, str) for seg in raw_namespace
|
|
437
|
-
):
|
|
438
|
-
return self._error(
|
|
439
|
-
command.get("id"),
|
|
568
|
+
namespace = self._coerce_respond_namespace(params.get("namespace", []))
|
|
569
|
+
if namespace is None:
|
|
570
|
+
return None, self._error(
|
|
571
|
+
cmd_id,
|
|
440
572
|
"invalid_argument",
|
|
441
573
|
"input.respond requires namespace to be a list of strings.",
|
|
442
574
|
)
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
# is still empty. In that case, fall back to the thread-state
|
|
451
|
-
# check so we don't reject legitimate resumes with a fresh
|
|
452
|
-
# handle. The WebSocket path (long-lived session) hits the
|
|
453
|
-
# in-memory check and skips the DB round-trip.
|
|
454
|
-
pending_namespace = (
|
|
455
|
-
self._session.lookup_pending_interrupt(interrupt_id)
|
|
456
|
-
if self._session is not None
|
|
457
|
-
else None
|
|
575
|
+
return [(interrupt_id, namespace, params.get("response"))], None
|
|
576
|
+
|
|
577
|
+
async def _handle_input_respond(self, command: dict[str, Any]) -> dict[str, Any]:
|
|
578
|
+
params = command.get("params", {}) if _is_record(command.get("params")) else {}
|
|
579
|
+
|
|
580
|
+
entries, normalize_error = self._normalize_respond_entries(
|
|
581
|
+
command.get("id"), params
|
|
458
582
|
)
|
|
459
|
-
if
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
583
|
+
if normalize_error is not None:
|
|
584
|
+
return normalize_error
|
|
585
|
+
if entries is None: # narrowed by the error branch above
|
|
586
|
+
return self._error(
|
|
587
|
+
command.get("id"), "unknown_error", "No entries to respond to."
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
# Cross-check every targeted interrupt against the session's pending
|
|
591
|
+
# interrupts so we can return ``no_such_interrupt`` for
|
|
592
|
+
# unknown/mismatched pairs. When the session was attached fresh by
|
|
593
|
+
# this HTTP request (the stateless ``POST /commands`` transport) its
|
|
594
|
+
# source task hasn't had a chance to emit ``input.requested`` yet —
|
|
595
|
+
# ``_pending_interrupts`` is still empty. In that case, fall back to
|
|
596
|
+
# the thread-state check so we don't reject legitimate resumes with a
|
|
597
|
+
# fresh handle. The WebSocket path (long-lived session) hits the
|
|
598
|
+
# in-memory check and skips the DB round-trip.
|
|
599
|
+
#
|
|
600
|
+
# The thread-state fallback is fetched at most once per batch and
|
|
601
|
+
# cached in ``thread_state_ids``: a batch of N entries that all miss
|
|
602
|
+
# the session would otherwise issue N identical ``State.get`` calls.
|
|
603
|
+
thread_state_ids: set[str] | None = None
|
|
604
|
+
thread_state_fetched = False
|
|
605
|
+
for interrupt_id, claimed_namespace, _ in entries:
|
|
606
|
+
pending_namespace = (
|
|
607
|
+
self._session.lookup_pending_interrupt(interrupt_id)
|
|
608
|
+
if self._session is not None
|
|
609
|
+
else None
|
|
610
|
+
)
|
|
611
|
+
if pending_namespace is not None:
|
|
612
|
+
# Authoritative: the session observed the ``input.requested``
|
|
613
|
+
# event and recorded the exact subgraph namespace. Enforce
|
|
614
|
+
# strict comparison.
|
|
615
|
+
if pending_namespace != claimed_namespace:
|
|
616
|
+
return self._error(
|
|
617
|
+
command.get("id"),
|
|
618
|
+
"no_such_interrupt",
|
|
619
|
+
"Interrupt namespace does not match the pending interrupt.",
|
|
620
|
+
)
|
|
621
|
+
continue
|
|
622
|
+
# HTTP fallback: the bulk thread-state lookup only walks root
|
|
623
|
+
# tasks and surfaces interrupts by id (not namespace), so it
|
|
472
624
|
# cannot validate subgraph namespaces. Verify the interrupt
|
|
473
625
|
# exists on persisted state and trust the client-claimed
|
|
474
|
-
# namespace — the interrupt_id is a UUID, so the existence
|
|
475
|
-
#
|
|
476
|
-
#
|
|
477
|
-
if
|
|
626
|
+
# namespace — the interrupt_id is a UUID, so the existence check
|
|
627
|
+
# alone is sufficient. (Without this, every HTTP ``input.respond``
|
|
628
|
+
# for a subgraph interrupt would 404.)
|
|
629
|
+
if not thread_state_fetched:
|
|
630
|
+
thread_state_ids = await self._collect_thread_state_interrupt_ids()
|
|
631
|
+
thread_state_fetched = True
|
|
632
|
+
if thread_state_ids is None or interrupt_id not in thread_state_ids:
|
|
478
633
|
return self._error(
|
|
479
634
|
command.get("id"),
|
|
480
635
|
"no_such_interrupt",
|
|
481
636
|
f"Unknown or already-consumed interrupt: {interrupt_id}",
|
|
482
637
|
)
|
|
483
638
|
|
|
484
|
-
# At this point we've confirmed
|
|
639
|
+
# At this point we've confirmed every interrupt exists on the
|
|
485
640
|
# thread state (or was surfaced via the session). No need for a
|
|
486
641
|
# second ``_has_pending_interrupts`` round-trip.
|
|
487
642
|
|
|
@@ -496,12 +651,17 @@ class ThreadRunManager:
|
|
|
496
651
|
"No interrupted run is bound to this thread.",
|
|
497
652
|
)
|
|
498
653
|
|
|
654
|
+
# Merge every entry into a single ``{interrupt_id: response}`` resume
|
|
655
|
+
# map. ``_create_or_resume_run`` forwards it verbatim as
|
|
656
|
+
# ``Command(resume=...)``, which resumes all targeted interrupts in
|
|
657
|
+
# one run.
|
|
658
|
+
resume_input = {interrupt_id: response for interrupt_id, _, response in entries}
|
|
499
659
|
try:
|
|
500
660
|
await self._create_or_resume_run(
|
|
501
661
|
assistant_id,
|
|
502
662
|
{
|
|
503
663
|
"assistant_id": assistant_id,
|
|
504
|
-
"input":
|
|
664
|
+
"input": resume_input,
|
|
505
665
|
"config": params.get("config"),
|
|
506
666
|
"metadata": params.get("metadata"),
|
|
507
667
|
},
|
|
@@ -512,7 +672,8 @@ class ThreadRunManager:
|
|
|
512
672
|
return self._error(command.get("id"), "unknown_error", str(exc))
|
|
513
673
|
|
|
514
674
|
if self._session is not None:
|
|
515
|
-
|
|
675
|
+
for interrupt_id, _, _ in entries:
|
|
676
|
+
self._session.clear_pending_interrupt(interrupt_id)
|
|
516
677
|
|
|
517
678
|
return {
|
|
518
679
|
"type": "success",
|
|
@@ -575,13 +736,26 @@ class ThreadRunManager:
|
|
|
575
736
|
},
|
|
576
737
|
}
|
|
577
738
|
|
|
739
|
+
# The fork target arrives only via ``config.configurable.checkpoint_id``
|
|
740
|
+
# (the SDK folds its ergonomic ``forkFrom`` option into this field
|
|
741
|
+
# client-side, so there is a single way to provide it). Extract it
|
|
742
|
+
# here and map it onto the top-level ``checkpoint_id`` / ``checkpoint``
|
|
743
|
+
# fields of ``run_payload`` below: ``create_valid_run`` — the shared
|
|
744
|
+
# run-creation path also used by the legacy REST run-create endpoints —
|
|
745
|
+
# reads the fork target from those fields (UUID-validating it and
|
|
746
|
+
# injecting it back into ``config.configurable``), so populating them is
|
|
747
|
+
# what makes the run replay from the requested checkpoint rather than
|
|
748
|
+
# the thread's latest state.
|
|
749
|
+
checkpoint_id = _checkpoint_id_from_run_start_config(params)
|
|
750
|
+
|
|
578
751
|
run_payload: dict[str, Any] = {
|
|
579
752
|
"assistant_id": assistant_id,
|
|
580
753
|
"input": None if is_resume else params.get("input"),
|
|
581
754
|
"command": {"resume": params["input"]} if is_resume else None,
|
|
582
755
|
"config": run_config,
|
|
583
756
|
"metadata": params.get("metadata"),
|
|
584
|
-
"checkpoint_id":
|
|
757
|
+
"checkpoint_id": checkpoint_id,
|
|
758
|
+
"checkpoint": {"checkpoint_id": checkpoint_id} if checkpoint_id else None,
|
|
585
759
|
"context": None,
|
|
586
760
|
"webhook": None,
|
|
587
761
|
"stream_mode": list(DEFAULT_RUN_STREAM_MODES),
|
|
@@ -596,11 +770,10 @@ class ThreadRunManager:
|
|
|
596
770
|
# chokes on None. Zero means "start immediately".
|
|
597
771
|
"after_seconds": 0,
|
|
598
772
|
"if_not_exists": "create",
|
|
599
|
-
#
|
|
600
|
-
#
|
|
601
|
-
#
|
|
602
|
-
|
|
603
|
-
"multitask_strategy": "enqueue",
|
|
773
|
+
# Honor the caller's ``multitaskStrategy`` (the SDK sends it on
|
|
774
|
+
# every run.start), falling back to ``enqueue`` — the legacy
|
|
775
|
+
# stream-endpoint default — when omitted.
|
|
776
|
+
"multitask_strategy": _multitask_strategy_from_run_start(params),
|
|
604
777
|
"langsmith_tracer": None,
|
|
605
778
|
"durability": None,
|
|
606
779
|
}
|
|
@@ -862,6 +1035,24 @@ class ThreadRunManager:
|
|
|
862
1035
|
treat ``[]`` as "interrupt found, namespace unknown" and trust
|
|
863
1036
|
the client-claimed namespace.
|
|
864
1037
|
"""
|
|
1038
|
+
found = await self._collect_thread_state_interrupt_ids()
|
|
1039
|
+
if found is None:
|
|
1040
|
+
return None
|
|
1041
|
+
return [] if interrupt_id in found else None
|
|
1042
|
+
|
|
1043
|
+
async def _collect_thread_state_interrupt_ids(self) -> set[str] | None:
|
|
1044
|
+
"""Fetch persisted thread state once and collect all interrupt ids.
|
|
1045
|
+
|
|
1046
|
+
Bulk counterpart to ``_lookup_interrupt_in_thread_state`` for the
|
|
1047
|
+
``input.respond`` batch path: a single ``State.get`` round-trip is
|
|
1048
|
+
shared across every entry in the batch instead of one DB call per
|
|
1049
|
+
interrupt. Returns the set of interrupt ids present on the thread's
|
|
1050
|
+
root tasks, or ``None`` if the state fetch failed (callers treat a
|
|
1051
|
+
``None`` result as "lookup unavailable", not "no interrupts").
|
|
1052
|
+
|
|
1053
|
+
Like the single lookup, this only walks root-level tasks — subgraph
|
|
1054
|
+
interrupts surface by id but not by namespace.
|
|
1055
|
+
"""
|
|
865
1056
|
from langgraph_runtime.database import connect # noqa: PLC0415
|
|
866
1057
|
|
|
867
1058
|
# ``supports_core_api=False`` so the postgres backend yields a
|
|
@@ -879,7 +1070,6 @@ class ThreadRunManager:
|
|
|
879
1070
|
logger.warning(
|
|
880
1071
|
"interrupt_lookup_failed",
|
|
881
1072
|
thread_id=self._thread_id,
|
|
882
|
-
interrupt_id=interrupt_id,
|
|
883
1073
|
error=str(exc),
|
|
884
1074
|
error_type=type(exc).__name__,
|
|
885
1075
|
)
|
|
@@ -888,6 +1078,7 @@ class ThreadRunManager:
|
|
|
888
1078
|
tasks = (
|
|
889
1079
|
state.get("tasks") if _is_record(state) else getattr(state, "tasks", None)
|
|
890
1080
|
) or ()
|
|
1081
|
+
found: set[str] = set()
|
|
891
1082
|
for task in tasks:
|
|
892
1083
|
interrupts = (
|
|
893
1084
|
task.get("interrupts")
|
|
@@ -900,15 +1091,9 @@ class ThreadRunManager:
|
|
|
900
1091
|
entry_id = (
|
|
901
1092
|
entry.get("id") if _is_record(entry) else getattr(entry, "id", None)
|
|
902
1093
|
)
|
|
903
|
-
if entry_id
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
# (subgraph tasks aren't always materialized in
|
|
907
|
-
# ``state.tasks``), so we return ``[]`` as an
|
|
908
|
-
# "interrupt found" sentinel. The caller knows not
|
|
909
|
-
# to use this for namespace comparison.
|
|
910
|
-
return []
|
|
911
|
-
return None
|
|
1094
|
+
if isinstance(entry_id, str):
|
|
1095
|
+
found.add(entry_id)
|
|
1096
|
+
return found
|
|
912
1097
|
|
|
913
1098
|
async def _has_pending_interrupts(self) -> bool:
|
|
914
1099
|
# Prefer the session's locally-tracked pending interrupts when
|
|
@@ -28,6 +28,9 @@ from langchain_protocol import (
|
|
|
28
28
|
FinalizedContentBlock,
|
|
29
29
|
ImageContentBlock,
|
|
30
30
|
InputRequestedData,
|
|
31
|
+
InputRespondEntry,
|
|
32
|
+
InputRespondMany,
|
|
33
|
+
InputRespondOne,
|
|
31
34
|
InputRespondParams,
|
|
32
35
|
LifecycleCause,
|
|
33
36
|
LifecycleCauseEdge,
|
|
@@ -90,6 +93,9 @@ __all__ = [
|
|
|
90
93
|
"FinalizedContentBlock",
|
|
91
94
|
"ImageContentBlock",
|
|
92
95
|
"InputRequestedData",
|
|
96
|
+
"InputRespondEntry",
|
|
97
|
+
"InputRespondMany",
|
|
98
|
+
"InputRespondOne",
|
|
93
99
|
"InputRespondParams",
|
|
94
100
|
"LifecycleCause",
|
|
95
101
|
"LifecycleCauseEdge",
|
|
@@ -39,7 +39,7 @@ dependencies = [
|
|
|
39
39
|
"cryptography>=42.0.0",
|
|
40
40
|
"langgraph-sdk>=0.3.5",
|
|
41
41
|
"cloudpickle>=3.0.0",
|
|
42
|
-
"langgraph-runtime-inmem>=0.
|
|
42
|
+
"langgraph-runtime-inmem>=0.30.0.dev0,<0.31.0.dev0",
|
|
43
43
|
"truststore>=0.1",
|
|
44
44
|
"protobuf>=6.32.1,<7.0.0",
|
|
45
45
|
"grpcio>=1.80.0,<1.81.0",
|
|
@@ -50,7 +50,7 @@ dependencies = [
|
|
|
50
50
|
"opentelemetry-exporter-otlp-proto-http>=0.0.1",
|
|
51
51
|
"uuid-utils>=0.12.0",
|
|
52
52
|
"zstandard>=0.23.0",
|
|
53
|
-
"langchain-protocol>=0.0.
|
|
53
|
+
"langchain-protocol>=0.0.16,<0.1",
|
|
54
54
|
]
|
|
55
55
|
|
|
56
56
|
[project.scripts]
|
|
@@ -684,14 +684,14 @@ wheels = [
|
|
|
684
684
|
|
|
685
685
|
[[package]]
|
|
686
686
|
name = "langchain-protocol"
|
|
687
|
-
version = "0.0.
|
|
687
|
+
version = "0.0.16"
|
|
688
688
|
source = { registry = "https://pypi.org/simple" }
|
|
689
689
|
dependencies = [
|
|
690
690
|
{ name = "typing-extensions" },
|
|
691
691
|
]
|
|
692
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
692
|
+
sdist = { url = "https://files.pythonhosted.org/packages/36/e7/8300ba22d968653051fd06e3117d783872dddf3dcebdd6b1d386836eb43c/langchain_protocol-0.0.16.tar.gz", hash = "sha256:806c7cdd951b1c4f692fa40fce60821ff0f221d4360e27673ddf2c2b99c2b7ff", size = 5969, upload-time = "2026-05-28T23:05:11.121Z" }
|
|
693
693
|
wheels = [
|
|
694
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
694
|
+
{ url = "https://files.pythonhosted.org/packages/1f/9c/06dfcc88d02a6364e8d864c421ddd3736305cb0a6c853f75c302c80fe17c/langchain_protocol-0.0.16-py3-none-any.whl", hash = "sha256:3658c142c5d0fb3a023a4be442ce4c15c6d626aab6135eb79a76dc64ad19c3c3", size = 7037, upload-time = "2026-05-28T23:05:10.163Z" },
|
|
695
695
|
]
|
|
696
696
|
|
|
697
697
|
[[package]]
|
|
@@ -785,7 +785,7 @@ requires-dist = [
|
|
|
785
785
|
{ name = "httpx", specifier = ">=0.25.0" },
|
|
786
786
|
{ name = "jsonschema-rs", specifier = ">=0.20.0,<0.45" },
|
|
787
787
|
{ name = "langchain-core", specifier = ">=0.3.64" },
|
|
788
|
-
{ name = "langchain-protocol", specifier = ">=0.0.
|
|
788
|
+
{ name = "langchain-protocol", specifier = ">=0.0.16,<0.1" },
|
|
789
789
|
{ name = "langgraph", specifier = ">=0.4.10,<2" },
|
|
790
790
|
{ name = "langgraph-checkpoint", specifier = ">=3.0.1,<5" },
|
|
791
791
|
{ name = "langgraph-runtime-inmem", editable = "../runtime_inmem" },
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.9.0.dev6"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|