langgraph-api 0.17.0.dev4__tar.gz → 0.17.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.17.0.dev4 → langgraph_api-0.17.0rc1}/Makefile +8 -2
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/PKG-INFO +2 -2
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/README.md +2 -2
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/REPORTS.md +14 -9
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/delta-report.js +26 -14
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/delta-report.test.js +35 -24
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/constraints.txt +1 -1
- langgraph_api-0.17.0rc1/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/event_streaming.py +31 -11
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/threads.py +13 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/asyncio.py +29 -2
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/service.py +22 -4
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/graph.py +3 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/ops/threads.py +6 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/client.mts +2 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/remote.py +17 -7
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/metrics_otlp.py +9 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/queue_entrypoint.py +3 -6
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/stream.py +1 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/worker.py +2 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/checkpoint.py +19 -14
- langgraph_api-0.17.0rc1/langgraph_grpc_common/proto/core_api_pb2.py +288 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/core_api_pb2.pyi +54 -5
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +45 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +18 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/openapi.json +37 -1
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/pyproject.toml +1 -1
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/uv.lock +4 -4
- langgraph_api-0.17.0.dev4/langgraph_api/__init__.py +0 -1
- langgraph_api-0.17.0.dev4/langgraph_grpc_common/proto/core_api_pb2.py +0 -286
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/.gitignore +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/LICENSE +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/README.md +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/.gitignore +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/Makefile +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/classify-error.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/classify-error.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/delta-turns-lib.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/delta-turns-lib.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/delta_turns.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/store.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/capacity-ci.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/capacity-ci.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/clean.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/continuous/uv.lock +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/daily-report.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/daily-report.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/graphs.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/history.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/history.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/host-v2.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/host-v2.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/multer.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/package.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/ramp.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/runner-descriptions.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/server-metrics.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/server-metrics.test.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/slack.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/staircase.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/weather.js +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/benchmark/yarn.lock +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/custom_store.sql +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/forbidden.txt +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/hatch_build.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/healthcheck.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/a2ui.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/a2ui_schemas/README.md +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/command.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/config/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/config/schemas.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/ops/runs.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/http.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/.yarnclean +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/package.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/auth-mutations.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/js/yarn.lock +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/metrics_collector.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/route.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/runner/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/runner/__main__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/schema.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/server.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/state.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/store.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/tracing_session.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/worker_runtime.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/store.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/runner_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/runner_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/runner_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/runner_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/store_pb2.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_grpc_common/store.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/encryption.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/logging.json +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/scripts/create_license.py +0 -0
- {langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/scripts/run_a2a_tck.py +0 -0
|
@@ -43,7 +43,7 @@ TEST ?= tests/ ../runtime_inmem/tests/
|
|
|
43
43
|
# has no [tool.pytest] — dropping pythonpath (e.g. apply_prerelease_version).
|
|
44
44
|
PYTEST_ROOT_ARGS := --rootdir=. -c pyproject.toml
|
|
45
45
|
PYTEST_WORKERS ?= 0
|
|
46
|
-
AUTH_TEST ?=
|
|
46
|
+
AUTH_TEST ?= tests/integration_tests/test_custom_auth.py tests/integration_tests/test_auth_mcp.py
|
|
47
47
|
LANGGRAPH_HTTP ?= {"disable_mcp": false, "disable_a2a": false}
|
|
48
48
|
LANGGRAPH_AES_KEY ?= '1234567890123456'
|
|
49
49
|
BG_JOB_TIMEOUT_SECS ?= 86400
|
|
@@ -128,7 +128,13 @@ test-auth:
|
|
|
128
128
|
test-with-server:
|
|
129
129
|
@bash -euo pipefail -c '$(MAKE) $(START_TARGET) LANGGRAPH_HTTP='\''$(LANGGRAPH_HTTP)'\'' & \
|
|
130
130
|
pid=$$!; \
|
|
131
|
-
cleanup() {
|
|
131
|
+
cleanup() { \
|
|
132
|
+
if [ -r /proc/$$pid/winpid ]; then \
|
|
133
|
+
taskkill //F //T //PID "$$(cat /proc/$$pid/winpid)" >/dev/null 2>&1 || true; \
|
|
134
|
+
else \
|
|
135
|
+
kill $$pid >/dev/null 2>&1 || true; \
|
|
136
|
+
fi; \
|
|
137
|
+
}; \
|
|
132
138
|
trap cleanup EXIT; \
|
|
133
139
|
for i in $$(seq 1 $(SERVER_START_TIMEOUT_SECS)); do \
|
|
134
140
|
if curl -sf "$(SERVER_HEALTH_URL)" >/dev/null; then \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.17.
|
|
3
|
+
Version: 0.17.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
|
|
@@ -35,7 +35,7 @@ Requires-Dist: structlog<26,>=24.1.0
|
|
|
35
35
|
Requires-Dist: tenacity>=8.0.0
|
|
36
36
|
Requires-Dist: truststore>=0.1
|
|
37
37
|
Requires-Dist: uuid-utils>=0.16.2
|
|
38
|
-
Requires-Dist: uvicorn>=0.
|
|
38
|
+
Requires-Dist: uvicorn>=0.29.0
|
|
39
39
|
Requires-Dist: uvloop>=0.18.0; platform_system != 'Windows'
|
|
40
40
|
Requires-Dist: watchfiles>=0.13
|
|
41
41
|
Requires-Dist: websockets>=13.0
|
|
@@ -132,7 +132,7 @@ thread depth. `delta_turns` measures it: one thread per VU, one turn per iterati
|
|
|
132
132
|
`benchmark-delta.yml` runs two cells nightly in one k6 run (`DELTA_CELLS`): every VU turns a
|
|
133
133
|
plain-channel thread and a `benchmark_delta_messages` thread (a message list, snapshot every 50,
|
|
134
134
|
the deepagents setting) in rotation, `ITERATIONS` fixed so both reach 1,400 turns.
|
|
135
|
-
`delta-report.js` posts write, read and
|
|
135
|
+
`delta-report.js` posts turn, write, read and data at the last turn and puts the by-depth tables
|
|
136
136
|
in the thread; `REPORTS.md` explains the post. The cells below stay available for manual runs.
|
|
137
137
|
|
|
138
138
|
| Cell | Env |
|
|
@@ -173,7 +173,7 @@ At every `VERIFY_EVERY` turn it also times the cold `GET /threads/{thread_id}/st
|
|
|
173
173
|
`state_read_duration` (the read path alone; a turn is one save plus the read before it), and
|
|
174
174
|
reads `GET /threads/{thread_id}/storage` and records
|
|
175
175
|
`thread_storage_bytes` tagged by depth bucket and graph, so the control and delta cells can
|
|
176
|
-
be compared on the bytes they
|
|
176
|
+
be compared on the bytes they store, which is what the feature exists to reduce.
|
|
177
177
|
|
|
178
178
|
## Outputs
|
|
179
179
|
|
|
@@ -142,12 +142,17 @@ once every 50 turns, at its own offset in that interval, so the reads cover
|
|
|
142
142
|
the whole climb between two snapshots instead of the moment right after one.
|
|
143
143
|
Storage (`GET /threads/{id}/storage`) is read at turns 350, 700, 1050 and 1400.
|
|
144
144
|
|
|
145
|
-
**The table.** Both setups at turn 1400: `
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
**The table.** Both setups at turn 1400: `turn` is the average successful
|
|
146
|
+
turn (`POST /runs/wait`), what a user waits for; `write` is the average
|
|
147
|
+
checkpoint save, timed by the worker between the graph's two steps. Both are
|
|
148
|
+
averages so that a delta thread's snapshot, written on one turn in 50, counts:
|
|
149
|
+
a median never sees it. `read` is the median cold read, timed to the server's
|
|
150
|
+
first byte. `data` is the thread's stored data in MB as
|
|
151
|
+
`GET /threads/{id}/storage` reports it: the stored size of the checkpoint,
|
|
152
|
+
metadata and blob values (`pg_column_size`), without keys, row headers or
|
|
153
|
+
indexes, so not disk use. Lower is better for every row. `last 10` is the
|
|
154
|
+
delta value over tonight and the nine nights before it. A metric outside its
|
|
155
|
+
usual range over five or more nights gets a ⚠️ line above the table.
|
|
151
156
|
|
|
152
157
|
**Pass bar.** Request errors under 1% and success over 99%. Two correctness
|
|
153
158
|
checks turn the dot yellow on any failure: at turn 2 each thread confirms
|
|
@@ -155,9 +160,9 @@ delta is on (or off, for `base`), because a too-old langgraph silently
|
|
|
155
160
|
degrades a `DeltaChannel` to a plain one; and every cold read is compared with
|
|
156
161
|
what the run returned.
|
|
157
162
|
|
|
158
|
-
**Thread.**
|
|
159
|
-
how many times better delta is (`same` within 15%, below `1.0x` when
|
|
160
|
-
worse). Then the run's size, failures and correctness checks.
|
|
163
|
+
**Thread.** Turn, write, read and data at turns 350, 700, 1050 and 1400, with
|
|
164
|
+
`gain`: how many times better delta is (`same` within 15%, below `1.0x` when
|
|
165
|
+
delta is worse). Then the run's size, failures and correctness checks.
|
|
161
166
|
|
|
162
167
|
## Changing a report
|
|
163
168
|
|
|
@@ -21,8 +21,8 @@ export const CELLS = [
|
|
|
21
21
|
{ cell: 'delta_50', label: 'delta' },
|
|
22
22
|
];
|
|
23
23
|
|
|
24
|
-
/** Nights measured another way (one cell per job, a bytes channel) do not compare with these. */
|
|
25
|
-
export const DESIGN = 'paired-messages';
|
|
24
|
+
/** Nights measured another way (one cell per job, a bytes channel, a median write) do not compare with these. */
|
|
25
|
+
export const DESIGN = 'paired-messages-mean';
|
|
26
26
|
|
|
27
27
|
/** Tonight plus the nine nights before it, as in the daily report. */
|
|
28
28
|
const NIGHTS = 10;
|
|
@@ -30,13 +30,19 @@ const NIGHTS = 10;
|
|
|
30
30
|
/** The thread's growth tables, one row per this many turns. Matches STORAGE_EVERY in the workflow. */
|
|
31
31
|
export const ROW_EVERY = 350;
|
|
32
32
|
|
|
33
|
-
/** Metric key, label, printer. All
|
|
33
|
+
/** Metric key, label, printer, unit. All are lower-is-better. */
|
|
34
34
|
const METRICS = [
|
|
35
|
-
['
|
|
36
|
-
['
|
|
37
|
-
['
|
|
35
|
+
['turnMeanMs', 'turn', formatSeconds, 's'],
|
|
36
|
+
['saveMeanMs', 'write', formatSeconds, 's'],
|
|
37
|
+
['readP50Ms', 'read', formatSeconds, 's'],
|
|
38
|
+
['bytes', 'data', formatMb, 'MB'],
|
|
38
39
|
];
|
|
39
40
|
|
|
41
|
+
/** From 10 s on, one decimal: five characters would fill the column and touch the one before it. */
|
|
42
|
+
function formatSeconds(v) {
|
|
43
|
+
return isNumber(v) ? (v / 1000).toFixed(v >= 10_000 ? 1 : 2) : '-';
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
function formatMb(v) {
|
|
41
47
|
if (!isNumber(v)) return '-';
|
|
42
48
|
const mb = v / 1024 / 1024;
|
|
@@ -56,6 +62,10 @@ function percentile(sorted, p) {
|
|
|
56
62
|
return sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil(sorted.length * p) - 1))];
|
|
57
63
|
}
|
|
58
64
|
|
|
65
|
+
function mean(values) {
|
|
66
|
+
return values.length > 0 ? values.reduce((sum, v) => sum + v, 0) / values.length : null;
|
|
67
|
+
}
|
|
68
|
+
|
|
59
69
|
export function bucketStart(bucket) {
|
|
60
70
|
const n = parseInt(String(bucket).split('-')[0], 10);
|
|
61
71
|
return Number.isFinite(n) ? n : Number.MAX_SAFE_INTEGER;
|
|
@@ -91,9 +101,12 @@ export function aggregateSamples(points) {
|
|
|
91
101
|
for (const depth of new Set([...Object.keys(turns), ...Object.keys(reads), ...Object.keys(saves), ...Object.keys(bytes)])) {
|
|
92
102
|
buckets[depth] = {
|
|
93
103
|
turns: (turns[depth] ?? []).length,
|
|
104
|
+
// Averages, so a delta thread's snapshot turn counts: one write in 50
|
|
105
|
+
// saves the whole value, and a median never sees it.
|
|
106
|
+
turnMeanMs: mean(turns[depth] ?? []),
|
|
107
|
+
saveMeanMs: mean(saves[depth] ?? []),
|
|
94
108
|
// One cold read per thread per bucket is few samples, so the median only.
|
|
95
109
|
readP50Ms: percentile((reads[depth] ?? []).sort((a, b) => a - b), 0.5),
|
|
96
|
-
saveMs: percentile((saves[depth] ?? []).sort((a, b) => a - b), 0.5),
|
|
97
110
|
bytes: bytes[depth] ?? null,
|
|
98
111
|
};
|
|
99
112
|
}
|
|
@@ -228,11 +241,11 @@ function failureReason(run) {
|
|
|
228
241
|
export function cellChanges(cell, depth, history) {
|
|
229
242
|
const tonight = cell.buckets?.[depth];
|
|
230
243
|
const changes = [];
|
|
231
|
-
for (const [key, label, format] of METRICS) {
|
|
244
|
+
for (const [key, label, format, unit] of METRICS) {
|
|
232
245
|
const past = history.map((night) => night[cell.cell]?.buckets?.[depth]?.[key]).filter(isNumber);
|
|
233
246
|
const flagged = flaggedChange(tonight?.[key], past, { higherIsBetter: false });
|
|
234
247
|
if (!flagged) continue;
|
|
235
|
-
changes.push({ key, better: flagged.better, text: `${cell.label} ${label} ${formatMove(format(flagged.median), format(tonight[key]), flagged.deltaPct,
|
|
248
|
+
changes.push({ key, better: flagged.better, text: `${cell.label} ${label} ${formatMove(format(flagged.median), format(tonight[key]), flagged.deltaPct, unit)}` });
|
|
236
249
|
}
|
|
237
250
|
return changes;
|
|
238
251
|
}
|
|
@@ -241,7 +254,7 @@ export function cellChanges(cell, depth, history) {
|
|
|
241
254
|
export function gain(base, cell) {
|
|
242
255
|
if (!isNumber(base) || !isNumber(cell) || base <= 0 || cell <= 0) return '-';
|
|
243
256
|
const ratio = base / cell;
|
|
244
|
-
// About the night-to-night noise on these
|
|
257
|
+
// About the night-to-night noise on these numbers; closer reads as a tie.
|
|
245
258
|
if (ratio > 0.85 && ratio < 1.15) return 'same';
|
|
246
259
|
return ratio >= 10 ? `${Math.round(ratio)}x` : `${ratio.toFixed(1)}x`;
|
|
247
260
|
}
|
|
@@ -266,9 +279,8 @@ export function growthTables(cells) {
|
|
|
266
279
|
const depths = Object.keys(base.buckets)
|
|
267
280
|
.filter((d) => bucketEnd(d) % ROW_EVERY === 0 && delta.buckets[d])
|
|
268
281
|
.sort(byDepth);
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const lines = ['```', titles[key], `${'turn'.padEnd(5)}${'base'.padStart(6)}${'delta'.padStart(6)}${'gain'.padStart(6)}`];
|
|
282
|
+
return METRICS.filter(([key]) => depths.some((d) => isNumber(base.buckets[d][key]))).map(([key, label, format, unit]) => {
|
|
283
|
+
const lines = ['```', `${label} ${unit}`, `${'turn'.padEnd(5)}${'base'.padStart(6)}${'delta'.padStart(6)}${'gain'.padStart(6)}`];
|
|
272
284
|
for (const d of depths) {
|
|
273
285
|
const [b, x] = [base.buckets[d][key], delta.buckets[d][key]];
|
|
274
286
|
lines.push(`${depthLabel(d).padEnd(5)}${format(b).padStart(6)}${format(x).padStart(6)}${gain(b, x).padStart(6)}`);
|
|
@@ -321,7 +333,7 @@ export function buildReport(run, context = {}) {
|
|
|
321
333
|
lines.push('*No turn was finished by every user on both cells.*');
|
|
322
334
|
}
|
|
323
335
|
if (depth && !anyBytes(run.cells[0])) {
|
|
324
|
-
lines.push('_No
|
|
336
|
+
lines.push('_No data row: the deployment runs an API without `GET /threads/{id}/storage` yet._');
|
|
325
337
|
}
|
|
326
338
|
if (history.length < MIN_HISTORY_NIGHTS) lines.push(`_${history.length} of ${MIN_HISTORY_NIGHTS} nights of history, no change flags yet_`);
|
|
327
339
|
lines.push(footer('delta-channel', artifactUrl));
|
|
@@ -9,19 +9,21 @@ import { PHONE_WIDTH, footer, widestCodeLine } from './slack.js';
|
|
|
9
9
|
const MB = 1024 * 1024;
|
|
10
10
|
const point = (metric, depth, value, cell) => ({ metric, value, tags: { depth, ...(cell ? { cell } : {}) } });
|
|
11
11
|
|
|
12
|
-
test('
|
|
12
|
+
test('turn and write are averages so a snapshot write counts, read is the median, bytes the largest reading', () => {
|
|
13
13
|
const buckets = aggregateSamples([
|
|
14
14
|
point('turn_duration', '1-50', 100),
|
|
15
15
|
point('turn_duration', '1-50', 300),
|
|
16
16
|
point('checkpoint_save', '1-50', 30),
|
|
17
|
+
point('checkpoint_save', '1-50', 30),
|
|
18
|
+
point('checkpoint_save', '1-50', 600),
|
|
17
19
|
point('thread_storage_bytes', '1-50', 1024),
|
|
18
20
|
point('thread_storage_bytes', '1-50', 4096),
|
|
19
21
|
point('state_read_duration', '1-50', 50),
|
|
20
22
|
point('state_read_duration', '1-50', 70),
|
|
21
23
|
point('turn_duration', '51-100', 900),
|
|
22
24
|
]);
|
|
23
|
-
assert.deepEqual(buckets['1-50'], { turns: 2,
|
|
24
|
-
assert.deepEqual(buckets['51-100'], { turns: 1,
|
|
25
|
+
assert.deepEqual(buckets['1-50'], { turns: 2, turnMeanMs: 200, saveMeanMs: 220, readP50Ms: 50, bytes: 4096 });
|
|
26
|
+
assert.deepEqual(buckets['51-100'], { turns: 1, turnMeanMs: 900, saveMeanMs: null, readP50Ms: null, bytes: null });
|
|
25
27
|
});
|
|
26
28
|
|
|
27
29
|
test('samples from one run split by the cell the runner tagged them with', () => {
|
|
@@ -31,21 +33,21 @@ test('samples from one run split by the cell the runner tagged them with', () =>
|
|
|
31
33
|
point('checkpoint_save', '1-50', 999),
|
|
32
34
|
]);
|
|
33
35
|
assert.deepEqual(Object.keys(byCell).sort(), ['control', 'delta_50']);
|
|
34
|
-
assert.equal(byCell.control['1-50'].
|
|
35
|
-
assert.equal(byCell.delta_50['1-50'].
|
|
36
|
+
assert.equal(byCell.control['1-50'].saveMeanMs, 300);
|
|
37
|
+
assert.equal(byCell.delta_50['1-50'].saveMeanMs, 60);
|
|
36
38
|
});
|
|
37
39
|
|
|
38
|
-
const bucket = (
|
|
40
|
+
const bucket = (turnMeanMs, saveMeanMs, readP50Ms, bytes) => ({ turns: 1000, turnMeanMs, saveMeanMs, readP50Ms, bytes });
|
|
39
41
|
|
|
40
42
|
function run({ base = {}, delta = {}, summary, stepOutcome = 'success' } = {}) {
|
|
41
|
-
const b = { save: 310, read: 110, bytes: 980 * MB, ...base };
|
|
42
|
-
const d = { save: 60, read: 100, bytes: 22 * MB, ...delta };
|
|
43
|
-
const rows = (s, r, bytes) => ({
|
|
44
|
-
'301-350': bucket(s / 4, r * 0.6, bytes / 16),
|
|
45
|
-
'651-700': bucket(s / 2, r * 0.7, bytes / 4),
|
|
46
|
-
'1001-1050': bucket(s * 0.75, r * 0.9, bytes / 2),
|
|
47
|
-
'1301-1350': bucket(s, r, null),
|
|
48
|
-
'1351-1400': bucket(s, r, bytes),
|
|
43
|
+
const b = { turn: 1600, save: 310, read: 110, bytes: 980 * MB, ...base };
|
|
44
|
+
const d = { turn: 1400, save: 60, read: 100, bytes: 22 * MB, ...delta };
|
|
45
|
+
const rows = (t, s, r, bytes) => ({
|
|
46
|
+
'301-350': bucket(t / 4, s / 4, r * 0.6, bytes / 16),
|
|
47
|
+
'651-700': bucket(t / 2, s / 2, r * 0.7, bytes / 4),
|
|
48
|
+
'1001-1050': bucket(t * 0.75, s * 0.75, r * 0.9, bytes / 2),
|
|
49
|
+
'1301-1350': bucket(t, s, r, null),
|
|
50
|
+
'1351-1400': bucket(t, s, r, bytes),
|
|
49
51
|
});
|
|
50
52
|
return {
|
|
51
53
|
stepOutcome,
|
|
@@ -58,8 +60,8 @@ function run({ base = {}, delta = {}, summary, stepOutcome = 'success' } = {}) {
|
|
|
58
60
|
thresholds: { http_req_failed: { 'rate<0.01': { ok: true } } },
|
|
59
61
|
},
|
|
60
62
|
cells: [
|
|
61
|
-
{ cell: 'control', label: 'base', buckets: rows(b.save, b.read, b.bytes) },
|
|
62
|
-
{ cell: 'delta_50', label: 'delta', buckets: rows(d.save, d.read, d.bytes) },
|
|
63
|
+
{ cell: 'control', label: 'base', buckets: rows(b.turn, b.save, b.read, b.bytes) },
|
|
64
|
+
{ cell: 'delta_50', label: 'delta', buckets: rows(d.turn, d.save, d.read, d.bytes) },
|
|
63
65
|
],
|
|
64
66
|
};
|
|
65
67
|
}
|
|
@@ -75,19 +77,27 @@ test('a clean night is the verdict, one table at the last turn, and a footer', (
|
|
|
75
77
|
'_at turn 1400_',
|
|
76
78
|
'```',
|
|
77
79
|
' base delta last 10',
|
|
80
|
+
'turn 1.60 1.40 ▄▄▄▄▄▄▄▄▄▄',
|
|
78
81
|
'write 0.31 0.06 ▄▄▄▄▄▄▄▄▄▄',
|
|
79
82
|
'read 0.11 0.10 ▄▄▄▄▄▄▄▄▄▄',
|
|
80
|
-
'
|
|
83
|
+
'data 980 22.0 ▄▄▄▄▄▄▄▄▄▄',
|
|
81
84
|
'```',
|
|
82
85
|
footer('delta-channel', 'https://github.com/x/y/actions/runs/1'),
|
|
83
86
|
]);
|
|
84
87
|
assert.ok(widestCodeLine(text) <= PHONE_WIDTH, 'the table fits a phone');
|
|
85
88
|
});
|
|
86
89
|
|
|
90
|
+
test('a turn of ten seconds or more keeps a space before it', () => {
|
|
91
|
+
const { text } = buildReport(run({ delta: { turn: 10500 } }), base);
|
|
92
|
+
assert.match(text, /^turn 1\.60 10\.5 /m);
|
|
93
|
+
});
|
|
94
|
+
|
|
87
95
|
test('the thread shows each metric as the threads grow, with the gain at every row', () => {
|
|
88
96
|
const { thread } = buildReport(run(), base);
|
|
89
97
|
assert.match(thread[0], /^\*As the thread grows\*$/m);
|
|
98
|
+
assert.match(thread[0], /^turn s\nturn\s+base\s+delta\s+gain\n350\s+0\.40\s+0\.35\s+same$/m, 'a whole turn gains less than its write');
|
|
90
99
|
assert.match(thread[0], /^write s\nturn\s+base\s+delta\s+gain\n350\s+0\.08\s+0\.01\s+5\.2x$/m);
|
|
100
|
+
assert.match(thread[0], /^data MB$/m);
|
|
91
101
|
assert.match(thread[0], /^1400\s+0\.11\s+0\.10\s+same$/m, 'read within 15% is a tie');
|
|
92
102
|
assert.match(thread[0], /^1400\s+980\s+22\.0\s+45x$/m);
|
|
93
103
|
assert.doesNotMatch(thread[0], /^1350/m, 'rows are every 350 turns only');
|
|
@@ -120,15 +130,16 @@ test('history keeps only nights measured with this design, newest first', () =>
|
|
|
120
130
|
write('100', { design: DESIGN, cells: { control: { tag: 'older' } } });
|
|
121
131
|
write('300', { design: DESIGN, cells: { control: { tag: 'newer' } } });
|
|
122
132
|
write('200', { cells: { control: { tag: 'one job per cell' } } });
|
|
133
|
+
write('250', { design: 'paired-messages', cells: { control: { tag: 'median write' } } });
|
|
123
134
|
assert.deepEqual(loadDeltaHistory(dir).map((night) => night.control.tag), ['newer', 'older']);
|
|
124
135
|
});
|
|
125
136
|
|
|
126
|
-
test('without storage readings the
|
|
137
|
+
test('without storage readings the data row is left out and the post says why', () => {
|
|
127
138
|
const r = run();
|
|
128
139
|
for (const c of r.cells) for (const b of Object.values(c.buckets)) b.bytes = null;
|
|
129
140
|
const { text } = buildReport(r, base);
|
|
130
|
-
assert.doesNotMatch(text, /^
|
|
131
|
-
assert.match(text, /^_No
|
|
141
|
+
assert.doesNotMatch(text, /^data/m);
|
|
142
|
+
assert.match(text, /^_No data row: the deployment runs an API without `GET \/threads\/\{id\}\/storage` yet\._$/m);
|
|
132
143
|
});
|
|
133
144
|
|
|
134
145
|
test('a run with no results is red and says why', () => {
|
|
@@ -156,8 +167,8 @@ test('storage missing at the compared turn shows as a dash, not as an API withou
|
|
|
156
167
|
const r = run();
|
|
157
168
|
for (const c of r.cells) c.buckets['1351-1400'].bytes = null;
|
|
158
169
|
const { text } = buildReport(r, base);
|
|
159
|
-
assert.match(text, /^
|
|
160
|
-
assert.doesNotMatch(text, /No
|
|
170
|
+
assert.match(text, /^data\s+-\s+- /m);
|
|
171
|
+
assert.doesNotMatch(text, /No data row/);
|
|
161
172
|
});
|
|
162
173
|
|
|
163
174
|
test('gain says how many times better delta is, and a tie as same', () => {
|
|
@@ -171,7 +182,7 @@ test('gain says how many times better delta is, and a tie as same', () => {
|
|
|
171
182
|
test('growth tables skip a metric no row measured', () => {
|
|
172
183
|
const r = run();
|
|
173
184
|
for (const c of r.cells) for (const b of Object.values(c.buckets)) b.bytes = null;
|
|
174
|
-
assert.equal(growthTables(r.cells).length,
|
|
185
|
+
assert.equal(growthTables(r.cells).length, 3);
|
|
175
186
|
});
|
|
176
187
|
|
|
177
188
|
test('a single downloaded artifact is read from the results directory itself', async () => {
|
|
@@ -181,5 +192,5 @@ test('a single downloaded artifact is read from the results directory itself', a
|
|
|
181
192
|
writeFileSync(path.join(dir, 'raw_data_1.json'), `${JSON.stringify(sample)}\n`);
|
|
182
193
|
const run = await collectRun(dir);
|
|
183
194
|
assert.equal(run.stepOutcome, 'success');
|
|
184
|
-
assert.equal(run.cells.find((c) => c.cell === 'delta_50').buckets['1-50'].
|
|
195
|
+
assert.equal(run.cells.find((c) => c.cell === 'delta_50').buckets['1-50'].saveMeanMs, 30);
|
|
185
196
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.17.0rc1"
|
|
@@ -33,7 +33,7 @@ from starlette.websockets import WebSocketDisconnect
|
|
|
33
33
|
|
|
34
34
|
from langgraph_api.event_streaming.service import ThreadRunManager
|
|
35
35
|
from langgraph_api.event_streaming.session import _is_supported_channel
|
|
36
|
-
from langgraph_api.event_streaming.types import Subscription
|
|
36
|
+
from langgraph_api.event_streaming.types import ErrorResponse, Subscription
|
|
37
37
|
from langgraph_api.feature_flags import IS_POSTGRES_OR_GRPC_BACKEND
|
|
38
38
|
from langgraph_api.route import ApiRoute, ApiWebSocketRoute
|
|
39
39
|
from langgraph_api.serde import json_dumpb
|
|
@@ -61,6 +61,19 @@ logger = structlog.stdlib.get_logger(__name__)
|
|
|
61
61
|
# connection, vs. the unbounded set this replaces.
|
|
62
62
|
_DELIVERED_DEDUP_WINDOW = 2048
|
|
63
63
|
|
|
64
|
+
# Final frame on SSE and WebSocket when the thread-stream consumer stops
|
|
65
|
+
# without being cancelled. A thread stream has no natural end, so that always
|
|
66
|
+
# means the read failed. The message is fixed because the exception text can
|
|
67
|
+
# carry raw backend errors; the consumer has already logged it.
|
|
68
|
+
_THREAD_STREAM_FAILED_DATA = json_dumpb(
|
|
69
|
+
ErrorResponse(
|
|
70
|
+
type="error",
|
|
71
|
+
id=None,
|
|
72
|
+
error="unknown_error",
|
|
73
|
+
message="Thread event stream failed.",
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
|
|
64
77
|
|
|
65
78
|
def _json_response(content: Any, *, status_code: int = 200) -> Response:
|
|
66
79
|
"""JSON response backed by the repo's orjson helper.
|
|
@@ -118,6 +131,10 @@ async def _thread_events(request: Request) -> Response:
|
|
|
118
131
|
The filter applies for the lifetime of the connection; closing the
|
|
119
132
|
connection unsubscribes. No state is persisted server-side beyond the
|
|
120
133
|
connection.
|
|
134
|
+
|
|
135
|
+
If reading the thread's event stream fails, the server ends the
|
|
136
|
+
stream with a final ``event: error`` frame carrying a protocol error
|
|
137
|
+
(``"type": "error"``, ``"id": null``, ``"error": "unknown_error"``).
|
|
121
138
|
"""
|
|
122
139
|
thread_id = request.path_params["thread_id"]
|
|
123
140
|
try:
|
|
@@ -245,10 +262,9 @@ async def _thread_events(request: Request) -> Response:
|
|
|
245
262
|
try:
|
|
246
263
|
while True:
|
|
247
264
|
# Race ``flush_pending`` against the thread-stream consumer
|
|
248
|
-
# ending. If the consumer
|
|
249
|
-
#
|
|
250
|
-
#
|
|
251
|
-
# never arrive.
|
|
265
|
+
# ending. If the consumer stops (its read failed or its
|
|
266
|
+
# source ended), we want this loop to exit rather than
|
|
267
|
+
# wedge forever waiting for events that will never arrive.
|
|
252
268
|
flush_task = asyncio.create_task(flush_pending.wait())
|
|
253
269
|
done_task = asyncio.create_task(manager.wait_for_thread_stream_end())
|
|
254
270
|
try:
|
|
@@ -285,6 +301,8 @@ async def _thread_events(request: Request) -> Response:
|
|
|
285
301
|
str(sse_id).encode() if isinstance(sse_id, int) else None,
|
|
286
302
|
)
|
|
287
303
|
if stream_finished:
|
|
304
|
+
if manager.thread_stream_failed:
|
|
305
|
+
yield (b"error", _THREAD_STREAM_FAILED_DATA)
|
|
288
306
|
break
|
|
289
307
|
finally:
|
|
290
308
|
await manager.close()
|
|
@@ -366,14 +384,16 @@ async def _thread_websocket(websocket: WebSocket) -> None:
|
|
|
366
384
|
manager = _make_manager(thread_id, send_event=ws_send_event)
|
|
367
385
|
manager.start_thread_stream()
|
|
368
386
|
|
|
369
|
-
# Watchdog: when the thread-stream consumer
|
|
370
|
-
#
|
|
371
|
-
#
|
|
372
|
-
#
|
|
373
|
-
#
|
|
374
|
-
# loop through its existing handler.
|
|
387
|
+
# Watchdog: when the thread-stream consumer stops, send the error frame
|
|
388
|
+
# (if it wasn't cancelled) and close the socket, instead of leaving the
|
|
389
|
+
# client on an open connection that will never deliver another event.
|
|
390
|
+
# ``receive_text`` below raises ``WebSocketDisconnect`` once the close
|
|
391
|
+
# lands, exiting the loop through its existing handler.
|
|
375
392
|
async def _stream_watchdog() -> None:
|
|
376
393
|
await manager.wait_for_thread_stream_end()
|
|
394
|
+
if manager.thread_stream_failed:
|
|
395
|
+
with contextlib.suppress(Exception):
|
|
396
|
+
await websocket.send_text(_THREAD_STREAM_FAILED_DATA.decode())
|
|
377
397
|
with contextlib.suppress(Exception):
|
|
378
398
|
await websocket.close(code=1011, reason="thread stream ended")
|
|
379
399
|
|
|
@@ -96,6 +96,16 @@ async def create_thread(
|
|
|
96
96
|
return ApiResponse(thread)
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
def _exclude_metadata_kwargs(payload: dict) -> dict:
|
|
100
|
+
"""Normalize `exclude_metadata` (object or list of objects) into ops kwargs."""
|
|
101
|
+
exclude_metadata = payload.get("exclude_metadata")
|
|
102
|
+
if exclude_metadata is None:
|
|
103
|
+
return {}
|
|
104
|
+
if isinstance(exclude_metadata, dict):
|
|
105
|
+
exclude_metadata = [exclude_metadata]
|
|
106
|
+
return {"exclude_metadata": exclude_metadata}
|
|
107
|
+
|
|
108
|
+
|
|
99
109
|
@retry_db
|
|
100
110
|
async def search_threads(
|
|
101
111
|
request: ApiRequest,
|
|
@@ -133,6 +143,7 @@ async def search_threads(
|
|
|
133
143
|
# it would extract from ciphertext (wrong) and we'll redo it anyway.
|
|
134
144
|
storage_extract = None if needs_python_extract else extract
|
|
135
145
|
|
|
146
|
+
exclude_kwargs = _exclude_metadata_kwargs(payload)
|
|
136
147
|
async with connect() as conn:
|
|
137
148
|
threads_iter, next_offset = await Threads.search(
|
|
138
149
|
conn,
|
|
@@ -146,6 +157,7 @@ async def search_threads(
|
|
|
146
157
|
sort_order=payload.get("sort_order"),
|
|
147
158
|
select=storage_select,
|
|
148
159
|
extract=storage_extract,
|
|
160
|
+
**exclude_kwargs,
|
|
149
161
|
)
|
|
150
162
|
threads, response_headers = await get_pagination_headers(
|
|
151
163
|
threads_iter, next_offset, offset
|
|
@@ -180,6 +192,7 @@ async def count_threads(
|
|
|
180
192
|
status=payload.get("status"),
|
|
181
193
|
values=payload.get("values"),
|
|
182
194
|
metadata=payload.get("metadata"),
|
|
195
|
+
**_exclude_metadata_kwargs(payload),
|
|
183
196
|
)
|
|
184
197
|
return ApiResponse(count)
|
|
185
198
|
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import concurrent.futures
|
|
3
|
-
from collections.abc import AsyncIterator, Coroutine
|
|
4
|
-
from contextlib import
|
|
3
|
+
from collections.abc import AsyncIterator, Coroutine, Generator
|
|
4
|
+
from contextlib import (
|
|
5
|
+
AbstractAsyncContextManager,
|
|
6
|
+
asynccontextmanager,
|
|
7
|
+
contextmanager,
|
|
8
|
+
suppress,
|
|
9
|
+
)
|
|
5
10
|
from functools import partial
|
|
6
11
|
from typing import Any, Generic, TypeVar
|
|
7
12
|
|
|
8
13
|
import structlog
|
|
14
|
+
import uvicorn
|
|
9
15
|
|
|
10
16
|
T = TypeVar("T")
|
|
11
17
|
|
|
@@ -343,3 +349,24 @@ class AsyncQueue(Generic[T], asyncio.Queue[T]):
|
|
|
343
349
|
# the call. Wake up the next in line.
|
|
344
350
|
self._wakeup_next(self._getters)
|
|
345
351
|
raise
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
class NoSignalServer(uvicorn.Server):
|
|
355
|
+
"""uvicorn server that leaves the process signal handlers alone.
|
|
356
|
+
|
|
357
|
+
uvicorn's own SIGTERM handler exits on the first signal, which would
|
|
358
|
+
short-circuit the queue's graceful shutdown. This server runs until the
|
|
359
|
+
task awaiting ``serve()`` is cancelled.
|
|
360
|
+
"""
|
|
361
|
+
|
|
362
|
+
@contextmanager
|
|
363
|
+
def capture_signals(self) -> Generator[None, None, None]:
|
|
364
|
+
yield
|
|
365
|
+
|
|
366
|
+
async def serve(self, sockets: list | None = None) -> None:
|
|
367
|
+
try:
|
|
368
|
+
await super().serve(sockets)
|
|
369
|
+
except asyncio.CancelledError:
|
|
370
|
+
if self.started:
|
|
371
|
+
await self.shutdown(sockets)
|
|
372
|
+
raise
|
{langgraph_api-0.17.0.dev4 → langgraph_api-0.17.0rc1}/langgraph_api/event_streaming/service.py
RENAMED
|
@@ -194,11 +194,13 @@ class ThreadRunManager:
|
|
|
194
194
|
self._seq: int = 0
|
|
195
195
|
self._thread_source_task: asyncio.Task[None] | None = None
|
|
196
196
|
# Set by ``_consume_thread_stream`` when the background task
|
|
197
|
-
# exits
|
|
198
|
-
#
|
|
199
|
-
#
|
|
200
|
-
#
|
|
197
|
+
# exits for any reason, including cancellation. Route handlers
|
|
198
|
+
# (SSE body_iter, WS watchdog) await this so a transient
|
|
199
|
+
# ``join_event_streaming`` failure can no longer leave the
|
|
200
|
+
# connection wedged with no events flowing.
|
|
201
201
|
self._thread_stream_done: asyncio.Event = asyncio.Event()
|
|
202
|
+
# Set when the consumer stops for any reason other than cancellation.
|
|
203
|
+
self._thread_stream_failed: bool = False
|
|
202
204
|
# WebSocket clients typically call ``subscription.subscribe``
|
|
203
205
|
# before ``run.start`` — natural ordering since they want to
|
|
204
206
|
# observe before firing. Buffer those subscriptions here and
|
|
@@ -224,6 +226,15 @@ class ThreadRunManager:
|
|
|
224
226
|
def seq(self) -> int:
|
|
225
227
|
return self._seq
|
|
226
228
|
|
|
229
|
+
@property
|
|
230
|
+
def thread_stream_failed(self) -> bool:
|
|
231
|
+
"""Whether the thread-stream consumer stopped without being cancelled.
|
|
232
|
+
|
|
233
|
+
A thread stream has no natural end, so the consumer stopping on its
|
|
234
|
+
own, by raising or by its source finishing, means the read failed.
|
|
235
|
+
"""
|
|
236
|
+
return self._thread_stream_failed
|
|
237
|
+
|
|
227
238
|
async def attach_event_sink(self, send_event: EventSink) -> None:
|
|
228
239
|
"""Attach a live transport consumer and flush buffered events."""
|
|
229
240
|
self._send_event = send_event
|
|
@@ -307,12 +318,19 @@ class ThreadRunManager:
|
|
|
307
318
|
except asyncio.CancelledError:
|
|
308
319
|
raise
|
|
309
320
|
except Exception as exc:
|
|
321
|
+
self._thread_stream_failed = True
|
|
310
322
|
await logger.aexception(
|
|
311
323
|
"protocol thread stream failed",
|
|
312
324
|
thread_id=str(self._thread_id),
|
|
313
325
|
error=str(exc),
|
|
314
326
|
error_type=type(exc).__name__,
|
|
315
327
|
)
|
|
328
|
+
else:
|
|
329
|
+
self._thread_stream_failed = True
|
|
330
|
+
await logger.awarning(
|
|
331
|
+
"protocol thread stream ended unexpectedly",
|
|
332
|
+
thread_id=str(self._thread_id),
|
|
333
|
+
)
|
|
316
334
|
finally:
|
|
317
335
|
# Wake up SSE body_iter / WS watchdog so the connection can
|
|
318
336
|
# be torn down. Without this, a transient ``join_event_streaming``
|
|
@@ -676,6 +676,9 @@ async def collect_graphs_from_env(
|
|
|
676
676
|
|
|
677
677
|
|
|
678
678
|
def _handle_exception(task: asyncio.Task) -> None:
|
|
679
|
+
if task.cancelled():
|
|
680
|
+
# Intentional stop (stop_remote_graphs); let lifespan teardown finish.
|
|
681
|
+
return
|
|
679
682
|
try:
|
|
680
683
|
task.result()
|
|
681
684
|
except (asyncio.CancelledError, SystemExit):
|
|
@@ -334,6 +334,7 @@ class Threads(Authenticated):
|
|
|
334
334
|
sort_order: str | None = None,
|
|
335
335
|
select: list[ThreadSelectField] | None = None,
|
|
336
336
|
extract: dict[str, str] | None = None,
|
|
337
|
+
exclude_metadata: list[dict[str, Any]] | None = None,
|
|
337
338
|
ctx: Any = None,
|
|
338
339
|
) -> tuple[AsyncIterator[Thread], int | None]:
|
|
339
340
|
metadata = metadata or {}
|
|
@@ -360,6 +361,8 @@ class Threads(Authenticated):
|
|
|
360
361
|
"sort_by": _map_threads_sort_by(sort_by),
|
|
361
362
|
"sort_order": _map_sort_order(sort_order),
|
|
362
363
|
}
|
|
364
|
+
if exclude_metadata:
|
|
365
|
+
request_kwargs["exclude_metadata_json"] = json_dumpb(exclude_metadata)
|
|
363
366
|
|
|
364
367
|
if status:
|
|
365
368
|
mapped_status = _map_thread_status(status)
|
|
@@ -402,6 +405,7 @@ class Threads(Authenticated):
|
|
|
402
405
|
metadata: MetadataInput,
|
|
403
406
|
values: MetadataInput,
|
|
404
407
|
status: ThreadStatus | None,
|
|
408
|
+
exclude_metadata: list[dict[str, Any]] | None = None,
|
|
405
409
|
ctx: Any = None,
|
|
406
410
|
) -> int:
|
|
407
411
|
metadata = metadata or {}
|
|
@@ -422,6 +426,8 @@ class Threads(Authenticated):
|
|
|
422
426
|
"metadata_json": json_dumpb_optional(metadata),
|
|
423
427
|
"values_json": json_dumpb_optional(values),
|
|
424
428
|
}
|
|
429
|
+
if exclude_metadata:
|
|
430
|
+
request_kwargs["exclude_metadata_json"] = json_dumpb(exclude_metadata)
|
|
425
431
|
if status:
|
|
426
432
|
mapped_status = _map_thread_status(status)
|
|
427
433
|
if mapped_status is None:
|
|
@@ -475,11 +475,13 @@ class RemoteCheckpointer extends BaseCheckpointSaver<number | string> {
|
|
|
475
475
|
config: RunnableConfig,
|
|
476
476
|
writes: [string, unknown][],
|
|
477
477
|
taskId: string,
|
|
478
|
+
taskPath?: string,
|
|
478
479
|
): Promise<void> {
|
|
479
480
|
await sendRecv("checkpointer_put_writes", {
|
|
480
481
|
config: stripConfigCallbacks(config),
|
|
481
482
|
writes,
|
|
482
483
|
taskId,
|
|
484
|
+
taskPath,
|
|
483
485
|
});
|
|
484
486
|
}
|
|
485
487
|
|