langgraph-api 0.16.9__tar.gz → 0.17.0__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.16.9 → langgraph_api-0.17.0}/LICENSE +1 -1
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/Makefile +8 -2
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/PKG-INFO +2 -2
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/README.md +11 -20
- langgraph_api-0.17.0/benchmark/REPORTS.md +174 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/delta-turns-lib.test.js +33 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/delta-turns-lib.ts +41 -1
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/delta_turns.ts +47 -20
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/threads_search_metadata.ts +5 -4
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/capacity-ci.js +88 -133
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/capacity-ci.test.js +72 -34
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/clean.js +0 -1
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/continuous/uv.lock +7 -7
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/daily-report.js +77 -99
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/daily-report.test.js +111 -56
- langgraph_api-0.17.0/benchmark/delta-report.js +396 -0
- langgraph_api-0.17.0/benchmark/delta-report.test.js +196 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/history.js +55 -12
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/history.test.js +34 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/multer.test.js +2 -2
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/ramp.js +5 -6
- langgraph_api-0.17.0/benchmark/runner-descriptions.js +21 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/slack.js +21 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/update-revision.js +4 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/yarn.lock +3 -3
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/custom_store.sql +0 -0
- langgraph_api-0.17.0/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/__init__.py +1 -1
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/assistants.py +30 -75
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/event_streaming.py +103 -19
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/runs.py +9 -132
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/store.py +17 -35
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/threads.py +153 -95
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/asyncio.py +6 -1
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/cache.py +86 -26
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/config/__init__.py +99 -5
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/config/schemas.py +12 -12
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/cron_scheduler.py +1 -27
- langgraph_api-0.17.0/langgraph_api/drain.py +164 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/encryption/aes_json.py +47 -6
- langgraph_api-0.17.0/langgraph_api/encryption/context.py +95 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/encryption/custom.py +14 -10
- langgraph_api-0.17.0/langgraph_api/encryption/middleware.py +350 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/encryption/shared.py +3 -30
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/service.py +110 -31
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/session.py +9 -6
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/feature_flags.py +41 -4
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/graph.py +29 -6
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/ops/__init__.py +3 -4
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/ops/runs.py +44 -5
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/ops/threads.py +159 -72
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/servicers/checkpointer.py +3 -2
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/servicers/encryption.py +22 -172
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/package.json +5 -5
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/yarn.lock +79 -80
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/metrics_otlp.py +8 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/models/run.py +6 -28
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/schema.py +16 -110
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/state.py +91 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/store.py +72 -1
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/stream.py +50 -3
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/cache.py +22 -10
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/worker.py +150 -31
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/worker_runtime.py +123 -3
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/checkpointer.py +26 -3
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/store.py +8 -6
- langgraph_api-0.17.0/langgraph_grpc_common/proto/checkpointer_pb2.py +99 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +85 -6
- langgraph_api-0.17.0/langgraph_grpc_common/proto/core_api_pb2.py +288 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/core_api_pb2.pyi +197 -7
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +89 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +30 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/store_pb2.py +25 -25
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/store_pb2.pyi +6 -1
- langgraph_api-0.17.0/langgraph_license/__init__.py +0 -0
- langgraph_api-0.17.0/langgraph_runtime/encryption.py +15 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/openapi.json +124 -4
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/pyproject.toml +1 -1
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/uv.lock +13 -13
- langgraph_api-0.16.9/benchmark/delta-report.js +0 -599
- langgraph_api-0.16.9/benchmark/delta-report.test.js +0 -191
- langgraph_api-0.16.9/benchmark/runner-descriptions.js +0 -58
- langgraph_api-0.16.9/langgraph_api/__init__.py +0 -1
- langgraph_api-0.16.9/langgraph_api/encryption/context.py +0 -35
- langgraph_api-0.16.9/langgraph_api/encryption/middleware.py +0 -766
- langgraph_api-0.16.9/langgraph_api/event_streaming/__init__.py +0 -1
- langgraph_api-0.16.9/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -87
- langgraph_api-0.16.9/langgraph_grpc_common/proto/core_api_pb2.py +0 -276
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/.gitignore +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/README.md +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/.gitignore +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/Makefile +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/classify-error.test.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/classify-error.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/store.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/graphs.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/host-v2.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/host-v2.test.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/package.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/server-metrics.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/server-metrics.test.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/staircase.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/weather.js +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/constraints.txt +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/forbidden.txt +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/hatch_build.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/healthcheck.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/a2ui.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/a2ui_schemas/README.md +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/command.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.16.9/langgraph_api/grpc → langgraph_api-0.17.0/langgraph_api/event_streaming}/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.16.9/langgraph_api/js → langgraph_api-0.17.0/langgraph_api/grpc}/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/http.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/.yarnclean +0 -0
- {langgraph_api-0.16.9/langgraph_api/middleware → langgraph_api-0.17.0/langgraph_api/js}/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/auth-mutations.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/metrics_collector.py +0 -0
- {langgraph_api-0.16.9/langgraph_api/models → langgraph_api-0.17.0/langgraph_api/middleware}/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.16.9/langgraph_license → langgraph_api-0.17.0/langgraph_api/models}/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/route.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/runner/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/runner/__main__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/server.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/tracing_session.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/runner_pb2.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/runner_pb2.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/runner_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/runner_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_grpc_common/store.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/logging.json +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/scripts/create_license.py +0 -0
- {langgraph_api-0.16.9 → langgraph_api-0.17.0}/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.
|
|
3
|
+
Version: 0.17.0
|
|
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
|
|
@@ -17,7 +17,7 @@ Requires-Dist: jsonschema-rs<0.45,>=0.20.0
|
|
|
17
17
|
Requires-Dist: langchain-core>=0.3.64
|
|
18
18
|
Requires-Dist: langchain-protocol<0.1,>=0.0.18
|
|
19
19
|
Requires-Dist: langgraph-checkpoint<5,>=3.0.1
|
|
20
|
-
Requires-Dist: langgraph-runtime-inmem<0.
|
|
20
|
+
Requires-Dist: langgraph-runtime-inmem<0.38.0.dev0,>=0.37.0.dev0
|
|
21
21
|
Requires-Dist: langgraph-sdk>=0.4.4
|
|
22
22
|
Requires-Dist: langgraph<2,>=0.4.10
|
|
23
23
|
Requires-Dist: langsmith[otel]>=0.6.3
|
|
@@ -129,13 +129,11 @@ by replaying them. That moves cost from write to read, and the read cost grows w
|
|
|
129
129
|
thread depth. `delta_turns` measures it: one thread per VU, one turn per iteration,
|
|
130
130
|
`turn_duration` tagged by depth bucket.
|
|
131
131
|
|
|
132
|
-
`benchmark-delta.yml` runs
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
with depth for different reasons, the control by re-writing a growing value and delta by
|
|
138
|
-
replaying more writes, so the deliverable is which curve is worse and where they cross.
|
|
132
|
+
`benchmark-delta.yml` runs two cells nightly in one k6 run (`DELTA_CELLS`): every VU turns a
|
|
133
|
+
plain-channel thread and a `benchmark_delta_messages` thread (a message list, snapshot every 50,
|
|
134
|
+
the deepagents setting) in rotation, `ITERATIONS` fixed so both reach 1,400 turns.
|
|
135
|
+
`delta-report.js` posts turn, write, read and data at the last turn and puts the by-depth tables
|
|
136
|
+
in the thread; `REPORTS.md` explains the post. The cells below stay available for manual runs.
|
|
139
137
|
|
|
140
138
|
| Cell | Env |
|
|
141
139
|
|---|---|
|
|
@@ -143,7 +141,7 @@ replaying more writes, so the deliverable is which curve is worse and where they
|
|
|
143
141
|
| delta, snapshot every 1000 | `GRAPH_ID=benchmark_delta` |
|
|
144
142
|
| delta, snapshot every 50 | `GRAPH_ID=benchmark_delta_freq` |
|
|
145
143
|
| delta, snapshot every 500 | `GRAPH_ID=benchmark_delta_500` |
|
|
146
|
-
| delta on a message list | `GRAPH_ID=benchmark_delta_messages PAYLOAD=messages` |
|
|
144
|
+
| delta on a message list, snapshot every 50 | `GRAPH_ID=benchmark_delta_messages PAYLOAD=messages` |
|
|
147
145
|
| migration | `GRAPH_ID=benchmark_delta MIGRATE_FROM_GRAPH_ID=benchmark MIGRATE_AFTER=200` |
|
|
148
146
|
|
|
149
147
|
```bash
|
|
@@ -175,7 +173,7 @@ At every `VERIFY_EVERY` turn it also times the cold `GET /threads/{thread_id}/st
|
|
|
175
173
|
`state_read_duration` (the read path alone; a turn is one save plus the read before it), and
|
|
176
174
|
reads `GET /threads/{thread_id}/storage` and records
|
|
177
175
|
`thread_storage_bytes` tagged by depth bucket and graph, so the control and delta cells can
|
|
178
|
-
be compared on the bytes they
|
|
176
|
+
be compared on the bytes they store, which is what the feature exists to reduce.
|
|
179
177
|
|
|
180
178
|
## Outputs
|
|
181
179
|
|
|
@@ -190,9 +188,9 @@ be compared on the bytes they occupy, which is what the feature exists to reduce
|
|
|
190
188
|
|
|
191
189
|
## CI workflows
|
|
192
190
|
|
|
193
|
-
- Daily ramp benchmark: `.github/workflows/benchmark.yml`
|
|
194
|
-
- Daily capacity matrix: `.github/workflows/benchmark-capacity-matrix.yml`
|
|
195
|
-
- Daily delta-channel cells: `.github/workflows/benchmark-delta.yml`, reported by `delta-report.js`
|
|
191
|
+
- Daily ramp benchmark: `.github/workflows/langgraph-api-benchmark.yml`
|
|
192
|
+
- Daily capacity matrix: `.github/workflows/langgraph-api-benchmark-capacity-matrix.yml`
|
|
193
|
+
- Daily delta-channel cells: `.github/workflows/langgraph-api-benchmark-delta.yml`, reported by `delta-report.js`
|
|
196
194
|
|
|
197
195
|
The staging deployments build their graphs from
|
|
198
196
|
[langgraph-server-benchmarks](https://github.com/langchain-ai/langgraph-server-benchmarks), not
|
|
@@ -209,14 +207,7 @@ Each cell also records the deployment's own view of its window (queue and API po
|
|
|
209
207
|
|
|
210
208
|
### Slack reports
|
|
211
209
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
- The first line is the verdict: a dot (green quiet, yellow something regressed or a bottleneck or errors, red something failed), the report name and date, `manual run` when dispatched by hand, the API version, and a clause saying what needs attention. The second line says what the benchmark is, for a reader outside the team.
|
|
215
|
-
- Then `Failed`, `Regressed`, `Improved` and `Bottlenecks` or `Errors` lines, worst first. `Regressed` prints `none` rather than going quiet.
|
|
216
|
-
- One table per deployment, about 40 characters wide so it fits a phone, with `▲ better` / `▼ worse` markers on cells that left their usual range.
|
|
217
|
-
- One legend line (pass rule, arrows, dot colors), then a link to the thread, which holds the per-cell or per-run numbers and the longer *How to read*, and to the run's artifacts.
|
|
218
|
-
|
|
219
|
-
Both reports compare tonight with the previous scheduled nights (`history.js`, artifacts fetched with `gh`). A figure is flagged only when it leaves that cell's own observed range, and only once five same-kind nights exist; before that the table says how many nights it has. The daily benchmark posts one digest per workflow once its last runner finishes (`daily-report.js`, fed by each runner's artifact), not one message per runner. The delta-channel report (`delta-report.js`) keeps the plain-vs-delta table in the channel and puts the snapshot-frequency sweep in the thread.
|
|
210
|
+
What each post means, for a reader outside the team, is in [REPORTS.md](REPORTS.md); every post links to its section. The channel message carries only the verdict, the lines that need attention and a small table per deployment (with a p95 trend on the daily ones), each fitting a phone; the numbers behind it go to the thread.
|
|
220
211
|
|
|
221
212
|
Local commands:
|
|
222
213
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Reading the benchmark reports
|
|
2
|
+
|
|
3
|
+
The LGP Benchmark Reporter posts four benchmark reports to #test-reports-lsd.
|
|
4
|
+
Each post keeps to the numbers; this page explains what they mean. Every post
|
|
5
|
+
links to its own section below with "What is this?". The weekly image-pull post
|
|
6
|
+
in the same channel is separate and not covered here.
|
|
7
|
+
|
|
8
|
+
## Reading any report
|
|
9
|
+
|
|
10
|
+
- **The dot.** 🟢 nothing to look at. 🟡 look at it: a regression, 10 or more
|
|
11
|
+
failed requests, a bottleneck, a correctness check or a warning line. 🔴 something failed: a
|
|
12
|
+
run crossed its pass bar, or never produced results.
|
|
13
|
+
- **The first line** is the verdict: report, date, `manual run` when someone
|
|
14
|
+
dispatched it by hand, the API version that was tested, and what needs
|
|
15
|
+
attention.
|
|
16
|
+
- **Failed / Errors / Regressed / Bottlenecks** lines only appear when there is
|
|
17
|
+
something to say, worst first.
|
|
18
|
+
- **Regressed / Improved.** A figure is flagged only when it leaves its own
|
|
19
|
+
usual range over the recent nights: the 9 before tonight for the daily and
|
|
20
|
+
delta reports, the last 7 for capacity, where ▲ better and ▼ worse also
|
|
21
|
+
mark the cell in the table. The usual range is half the spread
|
|
22
|
+
between the best and worst of those nights, and never less than 10%, so a
|
|
23
|
+
series that swings 40% night to night is not flagged for moving 15%.
|
|
24
|
+
Flags start once five nights of history exist; until then the post says how
|
|
25
|
+
many it has.
|
|
26
|
+
- **The thread** holds the full numbers: per-run or per-cell detail and
|
|
27
|
+
improvements with before and after values; the daily threads also give the
|
|
28
|
+
load that ran.
|
|
29
|
+
- **Run** opens the GitHub Actions run, with the raw k6 summaries and charts.
|
|
30
|
+
- `-` in a cell means there is no number: the run produced no results, nothing
|
|
31
|
+
succeeded, or no thread reached that depth.
|
|
32
|
+
|
|
33
|
+
## Daily benchmark
|
|
34
|
+
|
|
35
|
+
**Question it answers:** did latency or errors change for the three core
|
|
36
|
+
request paths, compared with the recent nights?
|
|
37
|
+
|
|
38
|
+
**How it runs.** [k6](https://k6.io/docs/) starts virtual users (simulated
|
|
39
|
+
clients). Each one repeats one request path as fast as the server answers: it
|
|
40
|
+
sends a request, waits for the response, then sends the next (a "closed
|
|
41
|
+
model"). Users are added in two steps of 60 s, then held for 5 minutes. Each
|
|
42
|
+
path runs as its own k6 run against the benchmark staging deployment. Every
|
|
43
|
+
scheduled night starts from a fresh revision of that deployment; it runs the
|
|
44
|
+
server version staging is on, which is the API version in the first line.
|
|
45
|
+
|
|
46
|
+
| Row | Runner | What one iteration does | Users |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| `wait` | `wait_write` | start a run and wait for its result (`POST /runs/wait`): run execution and checkpointing | 1,000 |
|
|
49
|
+
| `stream` | `stream_write` | start a run and read its event stream to the end (`POST /runs/stream`) | 1,000 |
|
|
50
|
+
| `search` | `threads_search` | create two threads, set their metadata, then search for them by it: database and metadata search | 300 |
|
|
51
|
+
|
|
52
|
+
Tables use the one-word row names so they fit a phone; the lines above the
|
|
53
|
+
table use the runner names.
|
|
54
|
+
|
|
55
|
+
`threads_search` does not delete the threads it creates; the deployment's
|
|
56
|
+
60-minute thread TTL removes them, so each night searches a table of about
|
|
57
|
+
that run's threads, not a growing history.
|
|
58
|
+
|
|
59
|
+
**The table.**
|
|
60
|
+
|
|
61
|
+
- `p95 s`: 95% of iterations finished within this many seconds tonight. When
|
|
62
|
+
it left its usual range, the Regressed or Improved line says so, with the
|
|
63
|
+
before and after.
|
|
64
|
+
- `last 10`: p95 over the same 10 nights the flags use, oldest on the left,
|
|
65
|
+
tonight on the right. Taller is slower. Each row has its own scale, so a full
|
|
66
|
+
bar means that runner's slowest night of the ten, not a number of seconds:
|
|
67
|
+
compare a row with itself, not with the row below. The bars never stretch
|
|
68
|
+
small noise to full height, so a real step stands out.
|
|
69
|
+
|
|
70
|
+
**Pass bar.** Request errors under 1%, p95 under 13 s, and more than 99% of
|
|
71
|
+
iterations succeeding. Missing any of them fails the run and turns the dot red.
|
|
72
|
+
|
|
73
|
+
**Errors line.** Failed requests by HTTP status, and how many nights in a row
|
|
74
|
+
that runner has had any, as `N+` when every fetched night had them, since the
|
|
75
|
+
streak then started before the history does. 10 or more in one night turn the dot yellow even when
|
|
76
|
+
the run passes.
|
|
77
|
+
|
|
78
|
+
**Thread.** Average, p95 and p95 of successful iterations only; run and
|
|
79
|
+
failure counts; every figure against the 9 nights before tonight, including average
|
|
80
|
+
latency and run count (run count follows latency under a fixed user count, so
|
|
81
|
+
it is shown but never flagged).
|
|
82
|
+
|
|
83
|
+
## Scale to zero
|
|
84
|
+
|
|
85
|
+
The daily benchmark against a second deployment that scales to zero when
|
|
86
|
+
idle. Scheduled runs redeploy it first, so the first minute includes the cold
|
|
87
|
+
start; a manual run skips the redeploy unless it is asked for. 200 users per
|
|
88
|
+
path instead of the daily's 1,000 (300 for search), and the pass bar is p95
|
|
89
|
+
under 25 s to allow for the cold start. Read it like the [daily benchmark](#daily-benchmark).
|
|
90
|
+
|
|
91
|
+
## Capacity
|
|
92
|
+
|
|
93
|
+
**Question it answers:** how much traffic can each deployment size handle
|
|
94
|
+
before it breaks its latency target, and what runs out first?
|
|
95
|
+
|
|
96
|
+
**How it runs.** Two staging deployments, one dedicated and one serverless,
|
|
97
|
+
are resized to each tier (L, M, S) in turn. For each tier and path, k6 sends a
|
|
98
|
+
fixed request rate regardless of how fast the server answers (an "open
|
|
99
|
+
model", the way real traffic arrives), and raises it every 60 s: dedicated by
|
|
100
|
+
50 req/s starting at 50, serverless by 5 starting at 10.
|
|
101
|
+
|
|
102
|
+
**The table.** Each cell is the highest request rate the tier held for two
|
|
103
|
+
steps while staying on target: at least 99% success, p50 at most 3 s, p95 at
|
|
104
|
+
most 10 s. `70+` means the tier passed the last step, so its real ceiling is
|
|
105
|
+
higher than the test goes. `0` means no step met the target, `ERR` means the cell crashed,
|
|
106
|
+
`-` means it never ran. A crashed cell's error is on the `Why:` line, once per
|
|
107
|
+
distinct error.
|
|
108
|
+
|
|
109
|
+
**Bottlenecks.** A component (queue, api, database, redis) running at or over
|
|
110
|
+
95% of its CPU request during the steps the tier passed. That is what stops
|
|
111
|
+
the tier going higher. Over 100% means it is bursting above its request.
|
|
112
|
+
|
|
113
|
+
**Keep in mind.** The graph is one step with no LLM call, so this measures the
|
|
114
|
+
server's own ceiling, not a customer workload. Every tier starts at one queue
|
|
115
|
+
pod and autoscales during a cell, so a capacity number is partly a pod-count
|
|
116
|
+
number.
|
|
117
|
+
|
|
118
|
+
**Thread.** Improvements with before and after values, then per deployment
|
|
119
|
+
two small tables grouped by tier: peak CPU as % of the pod's request, and pods
|
|
120
|
+
at the start and end of the cell. Both cover the whole cell, including steps
|
|
121
|
+
that failed. Last, the request rate actually served at the top step.
|
|
122
|
+
|
|
123
|
+
## Delta channel
|
|
124
|
+
|
|
125
|
+
**Question it answers:** on a long thread, does `DeltaChannel` at the
|
|
126
|
+
deepagents setting (a message list, snapshot every 50 turns) save faster and
|
|
127
|
+
store less than a plain channel, without making reads slower?
|
|
128
|
+
|
|
129
|
+
**Background.** A plain channel saves the whole value at every checkpoint. A
|
|
130
|
+
`DeltaChannel` saves only what changed, plus a full snapshot every N turns,
|
|
131
|
+
and rebuilds the value on read by replaying the changes since the last
|
|
132
|
+
snapshot. That moves cost from write to read, and read cost grows with the
|
|
133
|
+
distance to the last snapshot.
|
|
134
|
+
|
|
135
|
+
**How it runs.** One k6 run of 20 users. Each user owns two threads, one plain
|
|
136
|
+
(`base`) and one delta, and takes a turn on each in rotation until both reach
|
|
137
|
+
1,400 turns, so the two are always measured at the same depth seconds apart.
|
|
138
|
+
A turn (`POST /runs/wait`) appends one 1 KB chat message of varied text; text
|
|
139
|
+
repeated every turn would compress away in Postgres and make storage measure
|
|
140
|
+
row overhead. Each user also does a cold state read (`GET /threads/{id}/state`)
|
|
141
|
+
once every 50 turns, at its own offset in that interval, so the reads cover
|
|
142
|
+
the whole climb between two snapshots instead of the moment right after one.
|
|
143
|
+
Storage (`GET /threads/{id}/storage`) is read at turns 350, 700, 1050 and 1400.
|
|
144
|
+
|
|
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.
|
|
156
|
+
|
|
157
|
+
**Pass bar.** Request errors under 1% and success over 99%. Two correctness
|
|
158
|
+
checks turn the dot yellow on any failure: at turn 2 each thread confirms
|
|
159
|
+
delta is on (or off, for `base`), because a too-old langgraph silently
|
|
160
|
+
degrades a `DeltaChannel` to a plain one; and every cold read is compared with
|
|
161
|
+
what the run returned.
|
|
162
|
+
|
|
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.
|
|
166
|
+
|
|
167
|
+
## Changing a report
|
|
168
|
+
|
|
169
|
+
The builders are `daily-report.js` (daily and scale to zero),
|
|
170
|
+
`capacity-ci.js --aggregate` and `delta-report.js`, all posting through
|
|
171
|
+
`slack.js`. The daily workflows post one digest after their last runner finishes, built from each runner's artifact. History comes from previous scheduled runs' artifacts via
|
|
172
|
+
`history.js`. Each has a `*.test.js` beside it (`npm test`). A dispatch of the
|
|
173
|
+
workflow with `post_to_slack` reproduces a post: about 30 minutes for the
|
|
174
|
+
daily reports, about 2 hours for delta and capacity.
|
{langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/delta-turns-lib.test.js
RENAMED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import test from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import {
|
|
4
|
+
parseCells,
|
|
4
5
|
planTurn,
|
|
6
|
+
readOffset,
|
|
5
7
|
deltaGuardFailure,
|
|
6
8
|
digestDrift,
|
|
7
9
|
stateDrift,
|
|
@@ -15,6 +17,8 @@ const BASE = {
|
|
|
15
17
|
migrateAfter: 0,
|
|
16
18
|
expectDelta: true,
|
|
17
19
|
verifyEvery: 50,
|
|
20
|
+
readOffset: 0,
|
|
21
|
+
storageEvery: 0,
|
|
18
22
|
bucketSize: 100,
|
|
19
23
|
};
|
|
20
24
|
|
|
@@ -180,3 +184,32 @@ test('a missing digest on either side is reported, not passed', () => {
|
|
|
180
184
|
assert.equal(digestDrift('', 'a'.repeat(64)), 'run_digest_missing');
|
|
181
185
|
assert.equal(digestDrift('a'.repeat(64), null), 'cold_digest_missing');
|
|
182
186
|
});
|
|
187
|
+
|
|
188
|
+
test('cold reads spread across the snapshot interval instead of all landing on it', () => {
|
|
189
|
+
const offsets = Array.from({ length: 20 }, (_, i) => readOffset(i + 1, 20, 50));
|
|
190
|
+
assert.equal(offsets[0], 0);
|
|
191
|
+
assert.equal(offsets.at(-1), 47);
|
|
192
|
+
assert.equal(new Set(offsets).size, 20, 'every VU reads at its own point');
|
|
193
|
+
assert.equal(planTurn(47, { ...BASE, readOffset: 3 }).verify, true);
|
|
194
|
+
assert.equal(planTurn(50, { ...BASE, readOffset: 3 }).verify, false);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test('storage is read on the cold-read turn of each bucket that ends a table row', () => {
|
|
198
|
+
const options = { ...BASE, bucketSize: 50, readOffset: 10, storageEvery: 350 };
|
|
199
|
+
assert.equal(planTurn(340, options).storage, true, 'bucket 301-350 ends on 350');
|
|
200
|
+
assert.equal(planTurn(290, options).storage, false, 'a cold read, but bucket 251-300 is not a row');
|
|
201
|
+
assert.equal(planTurn(341, options).storage, false, 'not a cold-read turn');
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('without a storage interval, storage is read on every cold read', () => {
|
|
205
|
+
assert.equal(planTurn(50, { ...BASE, storageEvery: 0 }).storage, true);
|
|
206
|
+
assert.equal(planTurn(51, { ...BASE, storageEvery: 0 }).storage, false);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test('cells parse from name:graph:expectDelta', () => {
|
|
210
|
+
assert.deepEqual(parseCells('control:benchmark:false, delta_50:benchmark_delta_messages:true'), [
|
|
211
|
+
{ name: 'control', graphId: 'benchmark', expectDelta: false },
|
|
212
|
+
{ name: 'delta_50', graphId: 'benchmark_delta_messages', expectDelta: true },
|
|
213
|
+
]);
|
|
214
|
+
assert.deepEqual(parseCells(''), []);
|
|
215
|
+
});
|
{langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/delta-turns-lib.ts
RENAMED
|
@@ -9,9 +9,20 @@ export interface DeltaTurnsOptions {
|
|
|
9
9
|
expectDelta: boolean;
|
|
10
10
|
/** Cold re-read cadence, in turns. 0 disables. */
|
|
11
11
|
verifyEvery: number;
|
|
12
|
+
/** Shifts this VU's cold reads off the multiples of `verifyEvery`; see readOffset. */
|
|
13
|
+
readOffset: number;
|
|
14
|
+
/** Storage is read on the cold-read turn of every bucket ending on a multiple of this. 0 reads it on every cold read. */
|
|
15
|
+
storageEvery: number;
|
|
12
16
|
bucketSize: number;
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
/** One setup the VU turns in rotation, on a thread of its own. */
|
|
20
|
+
export interface DeltaCell {
|
|
21
|
+
name: string;
|
|
22
|
+
graphId: string;
|
|
23
|
+
expectDelta: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
export interface TurnPlan {
|
|
16
27
|
graphId: string;
|
|
17
28
|
/** Cumulative on a reused thread, so turn N asks for N. */
|
|
@@ -19,6 +30,7 @@ export interface TurnPlan {
|
|
|
19
30
|
expectDelta: boolean;
|
|
20
31
|
guard: boolean;
|
|
21
32
|
verify: boolean;
|
|
33
|
+
storage: boolean;
|
|
22
34
|
depthBucket: string;
|
|
23
35
|
}
|
|
24
36
|
|
|
@@ -32,16 +44,40 @@ export function unusableCheckpointSize(checkpointSize: number | undefined): bool
|
|
|
32
44
|
export function planTurn(turn: number, options: DeltaTurnsOptions): TurnPlan {
|
|
33
45
|
const migrating = options.migrateFromGraphId !== '' && options.migrateAfter > 0;
|
|
34
46
|
const beforeSwitch = migrating && turn <= options.migrateAfter;
|
|
47
|
+
const verify = options.verifyEvery > 0 && (turn + options.readOffset) % options.verifyEvery === 0;
|
|
35
48
|
return {
|
|
36
49
|
graphId: beforeSwitch ? options.migrateFromGraphId : options.graphId,
|
|
37
50
|
steps: turn,
|
|
38
51
|
expectDelta: beforeSwitch ? false : options.expectDelta,
|
|
39
52
|
guard: isGuardTurn(turn, options, migrating),
|
|
40
|
-
verify
|
|
53
|
+
verify,
|
|
54
|
+
storage: verify && (options.storageEvery <= 0 || bucketEnd(turn, options.bucketSize) % options.storageEvery === 0),
|
|
41
55
|
depthBucket: depthBucket(turn, options.bucketSize),
|
|
42
56
|
};
|
|
43
57
|
}
|
|
44
58
|
|
|
59
|
+
/** `name:graph:expectDelta`, comma-separated. */
|
|
60
|
+
export function parseCells(spec: string): DeltaCell[] {
|
|
61
|
+
return spec
|
|
62
|
+
.split(',')
|
|
63
|
+
.map((part) => part.trim())
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.map((part) => {
|
|
66
|
+
const [name, graphId, expectDelta] = part.split(':');
|
|
67
|
+
return { name, graphId, expectDelta: expectDelta === 'true' };
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A delta snapshot lands on every multiple of its frequency, so reading every
|
|
73
|
+
* VU on those turns only ever measures the read right after one. Spreading the
|
|
74
|
+
* VUs across the interval samples the whole climb between snapshots.
|
|
75
|
+
*/
|
|
76
|
+
export function readOffset(vu: number, vus: number, verifyEvery: number): number {
|
|
77
|
+
if (verifyEvery <= 0 || vus <= 0) return 0;
|
|
78
|
+
return Math.floor(((vu - 1) * verifyEvery) / vus) % verifyEvery;
|
|
79
|
+
}
|
|
80
|
+
|
|
45
81
|
/**
|
|
46
82
|
* Turn 1 has no counters yet, and on a snapshot point Pregel drops the counters
|
|
47
83
|
* entry, so its absence there is correct rather than a fallback.
|
|
@@ -51,6 +87,10 @@ function isGuardTurn(turn: number, options: DeltaTurnsOptions, migrating: boolea
|
|
|
51
87
|
return migrating && turn === options.migrateAfter + 2;
|
|
52
88
|
}
|
|
53
89
|
|
|
90
|
+
function bucketEnd(turn: number, bucketSize: number): number {
|
|
91
|
+
return bucketSize <= 0 ? turn : Math.ceil(turn / bucketSize) * bucketSize;
|
|
92
|
+
}
|
|
93
|
+
|
|
54
94
|
function depthBucket(turn: number, bucketSize: number): string {
|
|
55
95
|
if (bucketSize <= 0) return String(turn);
|
|
56
96
|
const floor = Math.floor((turn - 1) / bucketSize) * bucketSize;
|
|
@@ -13,9 +13,11 @@ import {
|
|
|
13
13
|
planTurn,
|
|
14
14
|
deltaGuardFailure,
|
|
15
15
|
digestDrift,
|
|
16
|
+
parseCells,
|
|
17
|
+
readOffset,
|
|
16
18
|
unusableCheckpointSize,
|
|
17
19
|
} from './delta-turns-lib.js';
|
|
18
|
-
import type { DeltaTurnsOptions, TurnPlan } from './delta-turns-lib.js';
|
|
20
|
+
import type { DeltaCell, DeltaTurnsOptions, TurnPlan } from './delta-turns-lib.js';
|
|
19
21
|
|
|
20
22
|
const PAYLOAD_CHANNELS = [
|
|
21
23
|
'cumulative_checkpoint',
|
|
@@ -35,20 +37,30 @@ const stateReadDuration = new Trend('state_read_duration', true);
|
|
|
35
37
|
const checkpointSaveDuration = new Trend('checkpoint_save', true);
|
|
36
38
|
const threadStorageBytes = new Trend('thread_storage_bytes', false);
|
|
37
39
|
|
|
38
|
-
const TURN_CONFIG: Omit<DeltaTurnsOptions, 'graphId'> = {
|
|
40
|
+
const TURN_CONFIG: Omit<DeltaTurnsOptions, 'graphId' | 'readOffset'> = {
|
|
39
41
|
migrateFromGraphId: __ENV.MIGRATE_FROM_GRAPH_ID || '',
|
|
40
42
|
migrateAfter: parseInt(__ENV.MIGRATE_AFTER || '0', 10),
|
|
41
43
|
expectDelta: (__ENV.EXPECT_DELTA || 'true') === 'true',
|
|
42
44
|
verifyEvery: parseInt(__ENV.VERIFY_EVERY || '50', 10),
|
|
45
|
+
storageEvery: parseInt(__ENV.STORAGE_EVERY || '0', 10),
|
|
43
46
|
// One bucket per cold read, so every row of the report is one sample per thread.
|
|
44
47
|
bucketSize: parseInt(__ENV.DEPTH_BUCKET || __ENV.VERIFY_EVERY || '50', 10),
|
|
45
48
|
};
|
|
46
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Every VU turns these in rotation, one thread each, so the cells are measured
|
|
52
|
+
* at the same depth seconds apart. Empty runs GRAPH_ID alone.
|
|
53
|
+
*/
|
|
54
|
+
const CELLS = parseCells(__ENV.DELTA_CELLS || '');
|
|
55
|
+
|
|
47
56
|
// Each k6 VU runs this module in its own context, so these are per VU.
|
|
48
|
-
|
|
49
|
-
let
|
|
57
|
+
const threads: Record<string, { threadId: string | null; turn: number }> = {};
|
|
58
|
+
let iteration = 0;
|
|
50
59
|
|
|
51
60
|
interface DeltaTurnsData {
|
|
61
|
+
cell: string;
|
|
62
|
+
turnMs: number;
|
|
63
|
+
tags: { depth: string; cell: string };
|
|
52
64
|
rawResponse: ReturnType<typeof http.post>;
|
|
53
65
|
plan: TurnPlan;
|
|
54
66
|
guardFailure: string | null;
|
|
@@ -69,18 +81,31 @@ export class DeltaTurns extends BenchmarkRunner {
|
|
|
69
81
|
return failResult('checkpoint_size', responses) as BenchmarkResult<DeltaTurnsData>;
|
|
70
82
|
}
|
|
71
83
|
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
const cell: DeltaCell = CELLS.length > 0
|
|
85
|
+
? CELLS[iteration++ % CELLS.length]
|
|
86
|
+
: { name: benchmarkGraphOptions.graph_id, graphId: benchmarkGraphOptions.graph_id, expectDelta: TURN_CONFIG.expectDelta };
|
|
87
|
+
const own = (threads[cell.name] ??= { threadId: null, turn: 0 });
|
|
88
|
+
if (own.threadId === null) {
|
|
89
|
+
const ttlMinutes = parseInt(__ENV.THREAD_TTL_MINUTES || '0', 10);
|
|
90
|
+
const body = ttlMinutes > 0 ? { ttl: { strategy: 'delete', ttl: ttlMinutes } } : {};
|
|
91
|
+
const thread = http.post(`${baseUrl}/threads`, JSON.stringify(body), requestParams);
|
|
74
92
|
addResponse(responses, 'create_thread', thread);
|
|
75
93
|
if (thread.status !== 200) {
|
|
76
94
|
return failResult('create_thread', responses) as BenchmarkResult<DeltaTurnsData>;
|
|
77
95
|
}
|
|
78
|
-
threadId = (thread.json() as { thread_id: string }).thread_id;
|
|
79
|
-
turn = 0;
|
|
96
|
+
own.threadId = (thread.json() as { thread_id: string }).thread_id;
|
|
97
|
+
own.turn = 0;
|
|
80
98
|
}
|
|
99
|
+
const threadId = own.threadId;
|
|
81
100
|
|
|
82
|
-
turn += 1;
|
|
83
|
-
const plan = planTurn(turn, {
|
|
101
|
+
own.turn += 1;
|
|
102
|
+
const plan = planTurn(own.turn, {
|
|
103
|
+
...TURN_CONFIG,
|
|
104
|
+
graphId: cell.graphId,
|
|
105
|
+
expectDelta: cell.expectDelta,
|
|
106
|
+
readOffset: readOffset(__VU, parseInt(__ENV.LOAD_SIZE || '1', 10), TURN_CONFIG.verifyEvery),
|
|
107
|
+
});
|
|
108
|
+
const tags = { depth: plan.depthBucket, cell: cell.name };
|
|
84
109
|
const payload = JSON.stringify({
|
|
85
110
|
assistant_id: plan.graphId,
|
|
86
111
|
input: {},
|
|
@@ -97,14 +122,11 @@ export class DeltaTurns extends BenchmarkRunner {
|
|
|
97
122
|
payload,
|
|
98
123
|
requestParams
|
|
99
124
|
);
|
|
100
|
-
|
|
125
|
+
const turnMs = Date.now() - startedAt;
|
|
101
126
|
addResponse(responses, 'wait', response);
|
|
102
127
|
const saveMs = response.status === 200 ? safeJson(response.body)?.save_ms : null;
|
|
103
128
|
if (typeof saveMs === 'number' && saveMs > 0) {
|
|
104
|
-
|
|
105
|
-
// turn is where a snapshot save shows; a percentile over the bucket hides it.
|
|
106
|
-
const rowTurn = plan.steps % TURN_CONFIG.bucketSize === 0 ? '1' : '0';
|
|
107
|
-
checkpointSaveDuration.add(saveMs, { depth: plan.depthBucket, row_turn: rowTurn });
|
|
129
|
+
checkpointSaveDuration.add(saveMs, tags);
|
|
108
130
|
}
|
|
109
131
|
|
|
110
132
|
let guardFailure: string | null = null;
|
|
@@ -120,7 +142,7 @@ export class DeltaTurns extends BenchmarkRunner {
|
|
|
120
142
|
// a plain-channel read cost as much as a whole turn. The turn-2 guard
|
|
121
143
|
// read is at depth 2, not the bucket's end, so it is not timed.
|
|
122
144
|
if (state.status === 200 && plan.verify) {
|
|
123
|
-
stateReadDuration.add(state.timings.waiting,
|
|
145
|
+
stateReadDuration.add(state.timings.waiting, tags);
|
|
124
146
|
}
|
|
125
147
|
addResponse(responses, 'state', state);
|
|
126
148
|
const body = state.status === 200 ? safeJson(state.body) : null;
|
|
@@ -137,7 +159,7 @@ export class DeltaTurns extends BenchmarkRunner {
|
|
|
137
159
|
drift = digestDrift(safeJson(response.body)?.payload_sha256, coldDigest(body.values));
|
|
138
160
|
}
|
|
139
161
|
}
|
|
140
|
-
if (plan.
|
|
162
|
+
if (plan.storage) {
|
|
141
163
|
// Servers before 0.16 have no storage endpoint. A 404 there is a missing
|
|
142
164
|
// sample, not a failed request: without this, one 404 per 50 turns is
|
|
143
165
|
// about 2% and trips the 1% error budget on every cell.
|
|
@@ -148,12 +170,12 @@ export class DeltaTurns extends BenchmarkRunner {
|
|
|
148
170
|
addResponse(responses, 'storage', storage);
|
|
149
171
|
const total = storage.status === 200 ? safeJson(storage.body)?.total_bytes : null;
|
|
150
172
|
if (typeof total === 'number') {
|
|
151
|
-
threadStorageBytes.add(total, {
|
|
173
|
+
threadStorageBytes.add(total, { ...tags, graph: plan.graphId });
|
|
152
174
|
}
|
|
153
175
|
}
|
|
154
176
|
}
|
|
155
177
|
|
|
156
|
-
return okResult(responses, { rawResponse: response, plan, guardFailure, drift, stateStatus });
|
|
178
|
+
return okResult(responses, { cell: cell.name, turnMs, tags, rawResponse: response, plan, guardFailure, drift, stateStatus });
|
|
157
179
|
}
|
|
158
180
|
|
|
159
181
|
static validate(
|
|
@@ -203,7 +225,12 @@ export class DeltaTurns extends BenchmarkRunner {
|
|
|
203
225
|
);
|
|
204
226
|
// The thread is now at an unknown depth, so later turns would be tagged
|
|
205
227
|
// with a depth they do not have.
|
|
206
|
-
|
|
228
|
+
const cell = result.data?.cell;
|
|
229
|
+
if (cell && threads[cell]) threads[cell].threadId = null;
|
|
230
|
+
} else if (result.data) {
|
|
231
|
+
// The report counts these per bucket to tell which depth every user
|
|
232
|
+
// finished, so only a turn that passed every check counts.
|
|
233
|
+
turnDuration.add(result.data.turnMs, result.data.tags);
|
|
207
234
|
}
|
|
208
235
|
return success;
|
|
209
236
|
}
|
{langgraph_api-0.16.9 → langgraph_api-0.17.0}/benchmark/benchmark-runners/threads_search_metadata.ts
RENAMED
|
@@ -13,11 +13,12 @@ interface ThreadsSearchMetadataData {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Delete the threads each iteration creates, or leave them to
|
|
16
|
+
* Delete the threads each iteration creates, or leave them to the deployment.
|
|
17
17
|
*
|
|
18
|
-
* Off by default
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Off by default, since deployments do not delete threads per request. The
|
|
19
|
+
* nightly deployments' 60-minute thread TTL (langgraph.json in
|
|
20
|
+
* langgraph-server-benchmarks) removes them after the run, so the table holds
|
|
21
|
+
* about one run's threads rather than growing night over night.
|
|
21
22
|
*
|
|
22
23
|
* The capacity staircase turns it on, because there the table grows *while*
|
|
23
24
|
* load is ramping, so a slower step cannot be attributed to load or to size.
|