langgraph-api 0.4.28__tar.gz → 0.6.25__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.6.25/Makefile +256 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/PKG-INFO +15 -7
- langgraph_api-0.6.25/benchmark/Makefile +89 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/README.md +2 -2
- langgraph_api-0.6.25/benchmark/benchmark-runners/assistant.js +88 -0
- langgraph_api-0.6.25/benchmark/benchmark-runners/benchmark-runner.js +34 -0
- langgraph_api-0.6.25/benchmark/benchmark-runners/benchmarks.js +21 -0
- langgraph_api-0.6.25/benchmark/benchmark-runners/stream_write.js +98 -0
- langgraph_api-0.6.25/benchmark/benchmark-runners/thread.js +87 -0
- langgraph_api-0.6.25/benchmark/benchmark-runners/wait_write.js +65 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/burst.js +1 -1
- langgraph_api-0.6.25/benchmark/capacity_k6.js +220 -0
- langgraph_api-0.6.25/benchmark/capacity_runner.mjs +371 -0
- langgraph_api-0.6.25/benchmark/capacity_urls.mjs +8 -0
- langgraph_api-0.6.25/benchmark/clean.js +151 -0
- langgraph_api-0.6.25/benchmark/continuous/README.md +38 -0
- langgraph_api-0.6.25/benchmark/continuous/pyproject.toml +13 -0
- langgraph_api-0.6.25/benchmark/continuous/runner.py +699 -0
- langgraph_api-0.6.25/benchmark/continuous/uv.lock +228 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/graphs.js +16 -14
- langgraph_api-0.6.25/benchmark/mixed_workload_k6.js +290 -0
- langgraph_api-0.6.25/benchmark/mixed_workload_runner.mjs +171 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/package.json +1 -1
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/ramp.js +80 -86
- langgraph_api-0.6.25/benchmark/reporting/dd_reporting.py +88 -0
- langgraph_api-0.6.25/benchmark/reporting/slack_slowest_runs.py +244 -0
- langgraph_api-0.6.25/benchmark/reporting/slack_summary.py +311 -0
- langgraph_api-0.6.25/benchmark/run_local.sh +27 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/update-revision.js +9 -7
- langgraph_api-0.6.25/constraints.txt +23 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/healthcheck.py +2 -1
- langgraph_api-0.6.25/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/__init__.py +106 -51
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/a2a.py +14 -15
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/assistants.py +186 -88
- langgraph_api-0.6.25/langgraph_api/api/encryption_middleware.py +626 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/mcp.py +3 -3
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/meta.py +18 -6
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/openapi.py +6 -1
- langgraph_api-0.6.25/langgraph_api/api/profile.py +108 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/runs.py +111 -57
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/store.py +19 -2
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/threads.py +142 -15
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/asgi_transport.py +14 -9
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/custom.py +52 -37
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/langsmith/backend.py +3 -2
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/langsmith/client.py +13 -8
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/cli.py +89 -91
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/command.py +2 -2
- langgraph_api-0.6.25/langgraph_api/config/__init__.py +452 -0
- langgraph_api-0.6.25/langgraph_api/config/_parse.py +58 -0
- langgraph_api-0.6.25/langgraph_api/config/schemas.py +429 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/cron_scheduler.py +15 -0
- langgraph_api-0.6.25/langgraph_api/encryption/__init__.py +13 -0
- langgraph_api-0.6.25/langgraph_api/encryption/context.py +35 -0
- langgraph_api-0.6.25/langgraph_api/encryption/custom.py +133 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/executor_entrypoint.py +11 -6
- langgraph_api-0.6.25/langgraph_api/feature_flags.py +32 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/graph.py +146 -72
- langgraph_api-0.6.25/langgraph_api/grpc/client.py +300 -0
- langgraph_api-0.6.25/langgraph_api/grpc/config_conversion.py +228 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/__init__.py +29 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/checkpointer_pb2.py +63 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/checkpointer_pb2.pyi +99 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/checkpointer_pb2_grpc.py +329 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/core_api_pb2.py +206 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/core_api_pb2.pyi +867 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/core_api_pb2_grpc.py +1533 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/engine_common_pb2.py +217 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/engine_common_pb2.pyi +716 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/engine_common_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_cancel_run_action_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_cancel_run_action_pb2.pyi +12 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_cancel_run_action_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_control_signal_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_control_signal_pb2.pyi +16 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_control_signal_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_durability_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_durability_pb2.pyi +16 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_durability_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_multitask_strategy_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_multitask_strategy_pb2.pyi +16 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_multitask_strategy_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_run_status_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_run_status_pb2.pyi +22 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_run_status_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_stream_mode_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_stream_mode_pb2.pyi +28 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_stream_mode_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_thread_status_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_thread_status_pb2.pyi +16 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_thread_status_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_thread_stream_mode_pb2.py +37 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_thread_stream_mode_pb2.pyi +16 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/enum_thread_stream_mode_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/errors_pb2.py +39 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/errors_pb2.pyi +21 -0
- langgraph_api-0.6.25/langgraph_api/grpc/generated/errors_pb2_grpc.py +24 -0
- langgraph_api-0.6.25/langgraph_api/grpc/ops/__init__.py +320 -0
- langgraph_api-0.6.25/langgraph_api/grpc/ops/assistants.py +421 -0
- langgraph_api-0.6.25/langgraph_api/grpc/ops/runs.py +487 -0
- langgraph_api-0.6.25/langgraph_api/grpc/ops/threads.py +599 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/http_metrics.py +15 -35
- langgraph_api-0.6.25/langgraph_api/http_metrics_utils.py +38 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/build.mts +1 -1
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/client.http.mts +13 -7
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/client.mts +2 -5
- langgraph_api-0.6.25/langgraph_api/js/package.json +47 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/remote.py +39 -17
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/src/graph.mts +20 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/sse.py +2 -2
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/ui.py +1 -1
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/yarn.lock +494 -519
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/logging.py +24 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/metadata.py +48 -29
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/middleware/http_logger.py +1 -1
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/middleware/private_network.py +7 -7
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/models/run.py +37 -25
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/patch.py +2 -2
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/queue_entrypoint.py +91 -36
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/route.py +47 -5
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/schema.py +86 -6
- langgraph_api-0.6.25/langgraph_api/self_hosted_logs.py +124 -0
- langgraph_api-0.6.25/langgraph_api/self_hosted_metrics.py +450 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/serde.py +74 -18
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/server.py +131 -56
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/state.py +3 -2
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/store.py +25 -16
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/stream.py +22 -16
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/thread_ttl.py +28 -13
- langgraph_api-0.6.25/langgraph_api/timing/__init__.py +25 -0
- langgraph_api-0.6.25/langgraph_api/timing/profiler.py +200 -0
- langgraph_api-0.6.25/langgraph_api/timing/timer.py +318 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/utils/__init__.py +28 -8
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/utils/config.py +2 -1
- langgraph_api-0.6.25/langgraph_api/utils/errors.py +77 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/utils/future.py +10 -6
- langgraph_api-0.6.25/langgraph_api/utils/uuids.py +54 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/validation.py +9 -0
- langgraph_api-0.6.25/langgraph_api/webhook.py +163 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/worker.py +28 -6
- langgraph_api-0.6.25/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/__init__.py +1 -0
- langgraph_api-0.6.25/langgraph_runtime/routes.py +11 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/logging.json +1 -3
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/openapi.json +415 -491
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/pyproject.toml +30 -10
- langgraph_api-0.6.25/uv.lock +2039 -0
- langgraph_api-0.4.28/Makefile +0 -123
- langgraph_api-0.4.28/benchmark/Makefile +0 -24
- langgraph_api-0.4.28/benchmark/clean.js +0 -87
- langgraph_api-0.4.28/constraints.txt +0 -19
- langgraph_api-0.4.28/langgraph_api/__init__.py +0 -1
- langgraph_api-0.4.28/langgraph_api/config.py +0 -387
- langgraph_api-0.4.28/langgraph_api/feature_flags.py +0 -9
- langgraph_api-0.4.28/langgraph_api/js/package.json +0 -47
- langgraph_api-0.4.28/langgraph_api/utils/uuids.py +0 -87
- langgraph_api-0.4.28/langgraph_api/webhook.py +0 -49
- langgraph_api-0.4.28/uv.lock +0 -1451
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/.gitignore +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/LICENSE +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/README.md +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/.gitignore +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/benchmark/weather.js +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/forbidden.txt +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.4.28/langgraph_api/js → langgraph_api-0.6.25/langgraph_api/grpc}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/http.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.4.28/langgraph_api/middleware → langgraph_api-0.6.25/langgraph_api/js}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.4.28/langgraph_api/models → langgraph_api-0.6.25/langgraph_api/middleware}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.4.28/langgraph_license → langgraph_api-0.6.25/langgraph_api/models}/__init__.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.4.28 → langgraph_api-0.6.25}/scripts/create_license.py +0 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
.PHONY: build release lint format test test_watch start start-inmem start-inmem-license-oss start start-js-server build-go-server start-go-server stop-go-server check-version check-base-imports
|
|
2
|
+
|
|
3
|
+
# Environment variables
|
|
4
|
+
FF_USE_CORE_API ?= false
|
|
5
|
+
LANGSERVE_GRAPHS_ALL = '{"agent": {"path": "./tests/graphs/agent.py:graph", "description": "agent"}, "custom_lifespan": "./tests/graphs/my_router.py:graph", "single_node": "./tests/graphs/single_node.py:graph", "benchmark": "./tests/graphs/benchmark.py:graph", "config_graph": "./tests/graphs/config_graph.py:graph", "other": "./tests/graphs/other.py:make_graph", "weather": "./tests/graphs/weather.py:mk_weather_graph", "searchy": "./tests/graphs/searchy.py:graph", "agent_simple": "./tests/graphs/agent_simple.py:graph", "simple_runtime": "./tests/graphs/simple_runtime.py:graph", "agent_interrupt": "./tests/graphs/agent_interrupt.py:graph", "message_type_test": "./tests/graphs/message_type_test.py:graph", "remote_subgraph_parent": "./tests/graphs/remote_subgraph_parent.py:graph", "simple_remote": "./tests/graphs/simple_remote.py:graph", "nested_subgraphs": "./tests/graphs/nested_subgraphs.py:graph", "functional_fibonacci": "./tests/graphs/functional_fibonacci.py:fibonacci", "state_graph_fibonacci": "./tests/graphs/state_graph_fibonacci.py:fibonacci", "max_concurrency_graph": "./tests/graphs/max_concurrency_graph.py:graph"}'
|
|
6
|
+
LANGSERVE_GRAPHS_AUTH = '{"agent": {"path": "./tests/graphs/agent.py:graph", "description": "agent"}, "config_graph": "./tests/graphs/config_graph.py:graph", "other": "./tests/graphs/other.py:make_graph", "weather": "./tests/graphs/weather.py:mk_weather_graph", "searchy": "./tests/graphs/searchy.py:graph", "agent_simple": "./tests/graphs/agent_simple.py:graph", "simple_runtime": "./tests/graphs/simple_runtime.py:graph", "functional_fibonacci": "./tests/graphs/functional_fibonacci.py:fibonacci", "state_graph_fibonacci": "./tests/graphs/state_graph_fibonacci.py:fibonacci"}'
|
|
7
|
+
|
|
8
|
+
# Go server management
|
|
9
|
+
build-go-server:
|
|
10
|
+
@echo "Building core-server..."
|
|
11
|
+
$(MAKE) -C ../core build-core-server
|
|
12
|
+
|
|
13
|
+
start-go-server: # NOTE: core server will start with sqlite if no DATABASE_URI is provided
|
|
14
|
+
@echo "Starting Core API (SQLite) gRPC server on port 50051..."
|
|
15
|
+
cd ../core && \
|
|
16
|
+
FF_USE_CORE_API=true \
|
|
17
|
+
LANGSERVE_GRAPHS=$(LANGSERVE_GRAPHS_ALL) \
|
|
18
|
+
DATABASE_URI= \
|
|
19
|
+
REDIS_URI= \
|
|
20
|
+
./bin/core-server \
|
|
21
|
+
-service core-api \
|
|
22
|
+
-apply-db-schema &
|
|
23
|
+
@sleep 2
|
|
24
|
+
|
|
25
|
+
stop-go-server:
|
|
26
|
+
@echo "Stopping Core API gRPC server on port 50051..."
|
|
27
|
+
@lsof -ti:50051 | xargs -r kill -9 || echo "No process found on port 50051"
|
|
28
|
+
|
|
29
|
+
# lint commands
|
|
30
|
+
|
|
31
|
+
lint:
|
|
32
|
+
uv run ruff check . --exclude "**/generated/**"
|
|
33
|
+
uv run ruff format . --diff --exclude "**/generated/**"
|
|
34
|
+
uv run ty check --exclude "**/pb/**" --exclude "**/*_test.py" --exclude "**/test_*.py" --exclude "**/tests/**" --exclude "venv/**" --exclude ".venv/**" --exclude "build/**" --exclude "dist/**" --exclude "**/generated/**" .
|
|
35
|
+
|
|
36
|
+
format:
|
|
37
|
+
uv run ruff check --fix . --exclude "**/generated/**"
|
|
38
|
+
uv run ruff format . --exclude "**/generated/**"
|
|
39
|
+
|
|
40
|
+
check-base-imports:
|
|
41
|
+
LANGGRAPH_RUNTIME_EDITION=inmem DATABASE_URI=:memory: REDIS_URI=_FAKE uv run python -c "from langgraph_api.config import *; from langgraph_runtime import *"
|
|
42
|
+
|
|
43
|
+
# test commands
|
|
44
|
+
|
|
45
|
+
TEST ?= tests/ ../runtime_inmem/tests/
|
|
46
|
+
AUTH_TEST ?= "tests/integration_tests/test_custom_auth.py"
|
|
47
|
+
LANGGRAPH_HTTP ?= {"disable_mcp": false, "disable_a2a": false}
|
|
48
|
+
LANGGRAPH_AES_KEY ?= '1234567890123456'
|
|
49
|
+
BG_JOB_TIMEOUT_SECS ?= 3600
|
|
50
|
+
|
|
51
|
+
ifeq ($(LANGGRAPH_HTTP),fastapi)
|
|
52
|
+
HTTP_CONFIG := {"app": "./tests/graphs/my_router.py:app", "disable_mcp": false, "disable_a2a": false, "mount_prefix": "/my-cool/api"}
|
|
53
|
+
else
|
|
54
|
+
HTTP_CONFIG := $(LANGGRAPH_HTTP)
|
|
55
|
+
endif
|
|
56
|
+
|
|
57
|
+
LANGGRAPH_STORE ?= ""
|
|
58
|
+
ifeq ($(LANGGRAPH_STORE),custom)
|
|
59
|
+
STORE_CONFIG := {"path": "./tests/graphs/custom_store.py:generate_store"}
|
|
60
|
+
else
|
|
61
|
+
STORE_CONFIG := {"index": {"dims": 500, "embed": "./tests/graphs/test_utils/embeddings.py:embeddings"}}
|
|
62
|
+
endif
|
|
63
|
+
|
|
64
|
+
REVISION ?= $(shell git rev-parse --short HEAD)
|
|
65
|
+
LANGGRAPH_ENCRYPTION ?=
|
|
66
|
+
|
|
67
|
+
test-license-oss:
|
|
68
|
+
@if [ "$(FF_USE_CORE_API)" = "true" ]; then \
|
|
69
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' LANGGRAPH_STORE='$(STORE_CONFIG)' LANGGRAPH_ENCRYPTION='$(LANGGRAPH_ENCRYPTION)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ FF_USE_CORE_API=true uv run pytest -m sqlite_grpc -v $(TEST); \
|
|
70
|
+
else \
|
|
71
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' LANGGRAPH_STORE='$(STORE_CONFIG)' LANGGRAPH_ENCRYPTION='$(LANGGRAPH_ENCRYPTION)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run pytest -v $(TEST); \
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
test-watch-oss:
|
|
75
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' LANGGRAPH_ENCRYPTION='$(LANGGRAPH_ENCRYPTION)' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run --no-sync ptw . -- -x -vv --ff --capture=no $(TEST)
|
|
76
|
+
|
|
77
|
+
test: test-license-oss
|
|
78
|
+
test-watch: test-watch-oss
|
|
79
|
+
unit-test:
|
|
80
|
+
DATABASE_URI="test" REDIS_URI="test" uv run pytest tests/unit_tests
|
|
81
|
+
|
|
82
|
+
test-auth:
|
|
83
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_AUTH='{"path": "./tests/graphs/fastapi_jwt_auth.py:get_current_active_user"}' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run pytest -v $(AUTH_TEST)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
define FASTAPI_JWT_AUTH_TEST
|
|
87
|
+
LANGGRAPH_RUNTIME_EDITION=inmem \
|
|
88
|
+
LANGGRAPH_AUTH='{"path": "./tests/graphs/fastapi_jwt_middleware_ordering.py:auth"}' \
|
|
89
|
+
REDIS_URI=_FAKE \
|
|
90
|
+
DATABASE_URI=:memory: \
|
|
91
|
+
MIGRATIONS_PATH=__inmem__ \
|
|
92
|
+
LANGGRAPH_HTTP='{"app": "./tests/graphs/fastapi_jwt_middleware_ordering.py:app", "middleware_order": "$(1)", "enable_custom_route_auth": $(2)}' \
|
|
93
|
+
uv run pytest -v $(AUTH_TEST)
|
|
94
|
+
endef
|
|
95
|
+
|
|
96
|
+
test-auth-fastapi-jwt--before-custom-middleware--no-custom-route-auth:
|
|
97
|
+
$(call FASTAPI_JWT_AUTH_TEST,auth_first,false)
|
|
98
|
+
|
|
99
|
+
test-auth-fastapi-jwt--after-custom-middleware--no-custom-route-auth:
|
|
100
|
+
$(call FASTAPI_JWT_AUTH_TEST,middleware_first,false)
|
|
101
|
+
|
|
102
|
+
test-auth-fastapi-jwt--before-custom-middleware--custom-route-auth:
|
|
103
|
+
$(call FASTAPI_JWT_AUTH_TEST,auth_first,true)
|
|
104
|
+
|
|
105
|
+
test-auth-fastapi-jwt--after-custom-middleware--custom-route-auth:
|
|
106
|
+
$(call FASTAPI_JWT_AUTH_TEST,middleware_first, true)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
test-auth-watch:
|
|
110
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_AUTH='{"path": "./tests/graphs/fastapi_jwt_auth.py:get_current_active_user"}' REDIS_URI=_FAKE DATABASE_URI=:memory: MIGRATIONS_PATH=__inmem__ uv run ptw . -- -x -vv --ff --capture=no $(AUTH_TEST)
|
|
111
|
+
|
|
112
|
+
# dev commands
|
|
113
|
+
|
|
114
|
+
start:
|
|
115
|
+
@if [ "$(FF_USE_CORE_API)" = "true" ]; then \
|
|
116
|
+
$(MAKE) build-go-server && $(MAKE) start-go-server; \
|
|
117
|
+
trap '$(MAKE) stop-go-server' INT TERM EXIT; \
|
|
118
|
+
fi; \
|
|
119
|
+
sleep 3 && \
|
|
120
|
+
LANGGRAPH_HTTP='$(HTTP_CONFIG)' \
|
|
121
|
+
LANGGRAPH_RUNTIME_EDITION=inmem \
|
|
122
|
+
LANGGRAPH_AES_KEY='$(LANGGRAPH_AES_KEY)' \
|
|
123
|
+
N_JOBS_PER_WORKER=2 \
|
|
124
|
+
LANGSERVE_GRAPHS=$(LANGSERVE_GRAPHS_ALL) \
|
|
125
|
+
LANGGRAPH_STORE='$(STORE_CONFIG)' \
|
|
126
|
+
LANGGRAPH_CONFIG='{"agent": {"configurable": {"model_name": "openai"}}}' \
|
|
127
|
+
LANGSMITH_LANGGRAPH_API_VARIANT=test \
|
|
128
|
+
FF_USE_CORE_API=$(FF_USE_CORE_API) \
|
|
129
|
+
BG_JOB_TIMEOUT_SECS=$(BG_JOB_TIMEOUT_SECS) \
|
|
130
|
+
REDIS_URI=fake \
|
|
131
|
+
DATABASE_URI=:memory: \
|
|
132
|
+
MIGRATIONS_PATH=__inmem \
|
|
133
|
+
uv run uvicorn \
|
|
134
|
+
"langgraph_api.server:app" \
|
|
135
|
+
--reload \
|
|
136
|
+
--port 9123 \
|
|
137
|
+
--reload-dir langgraph_api \
|
|
138
|
+
--reload-dir ../runtime_inmem \
|
|
139
|
+
--no-access-log
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
start-license-oss: start
|
|
143
|
+
|
|
144
|
+
start-encrypt:
|
|
145
|
+
LANGGRAPH_HTTP='$(HTTP_CONFIG)' \
|
|
146
|
+
LANGGRAPH_RUNTIME_EDITION=inmem \
|
|
147
|
+
LANGGRAPH_AES_KEY='$(LANGGRAPH_AES_KEY)' \
|
|
148
|
+
N_JOBS_PER_WORKER=2 \
|
|
149
|
+
LANGSERVE_GRAPHS=$(LANGSERVE_GRAPHS_ALL) \
|
|
150
|
+
LANGGRAPH_STORE='$(STORE_CONFIG)' \
|
|
151
|
+
LANGGRAPH_ENCRYPTION='{"path": "./tests/graphs/custom_encryption.py:encryption"}' \
|
|
152
|
+
LANGGRAPH_CONFIG='{"agent": {"configurable": {"model_name": "openai"}}}' \
|
|
153
|
+
LANGSMITH_LANGGRAPH_API_VARIANT=test \
|
|
154
|
+
BG_JOB_TIMEOUT_SECS=$(BG_JOB_TIMEOUT_SECS) \
|
|
155
|
+
REDIS_URI=fake \
|
|
156
|
+
DATABASE_URI=:memory: \
|
|
157
|
+
MIGRATIONS_PATH=__inmem \
|
|
158
|
+
uv run uvicorn \
|
|
159
|
+
"langgraph_api.server:app" \
|
|
160
|
+
--reload \
|
|
161
|
+
--port 9123 \
|
|
162
|
+
--reload-dir langgraph_api \
|
|
163
|
+
--reload-dir ../runtime_inmem \
|
|
164
|
+
--no-access-log
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
start-auth-jwt:
|
|
168
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' \
|
|
169
|
+
LANGGRAPH_AES_KEY='$(LANGGRAPH_AES_KEY)' \
|
|
170
|
+
N_JOBS_PER_WORKER=2 \
|
|
171
|
+
LANGSERVE_GRAPHS=$(LANGSERVE_GRAPHS_AUTH) \
|
|
172
|
+
LANGGRAPH_STORE='$(STORE_CONFIG)' \
|
|
173
|
+
LANGGRAPH_AUTH='{"path": "tests/graphs/jwt_auth.py:auth"}' \
|
|
174
|
+
LANGSMITH_LANGGRAPH_API_VARIANT=test \
|
|
175
|
+
REDIS_URI=fake \
|
|
176
|
+
DATABASE_URI=:memory: \
|
|
177
|
+
MIGRATIONS_PATH=__inmem \
|
|
178
|
+
uv run uvicorn \
|
|
179
|
+
"langgraph_api.server:app" \
|
|
180
|
+
--reload \
|
|
181
|
+
--port 9123 \
|
|
182
|
+
--reload-dir langgraph_api \
|
|
183
|
+
--reload-dir ../runtime_inmem \
|
|
184
|
+
--no-access-log
|
|
185
|
+
|
|
186
|
+
start-auth-fastapi-jwt:
|
|
187
|
+
LANGGRAPH_RUNTIME_EDITION=inmem LANGGRAPH_HTTP='$(HTTP_CONFIG)' \
|
|
188
|
+
N_JOBS_PER_WORKER=2 \
|
|
189
|
+
LANGSERVE_GRAPHS=$(LANGSERVE_GRAPHS_AUTH) \
|
|
190
|
+
LANGGRAPH_STORE='$(STORE_CONFIG)' \
|
|
191
|
+
LANGGRAPH_AUTH='{"path": "./tests/graphs/fastapi_jwt_auth.py:auth"}' \
|
|
192
|
+
LANGSMITH_LANGGRAPH_API_VARIANT=test \
|
|
193
|
+
REDIS_URI=fake \
|
|
194
|
+
DATABASE_URI=:memory: \
|
|
195
|
+
MIGRATIONS_PATH=__inmem \
|
|
196
|
+
uv run uvicorn \
|
|
197
|
+
"langgraph_api.server:app" \
|
|
198
|
+
--reload \
|
|
199
|
+
--port 9123 \
|
|
200
|
+
--reload-dir langgraph_api \
|
|
201
|
+
--reload-dir ../runtime_inmem \
|
|
202
|
+
--no-access-log
|
|
203
|
+
|
|
204
|
+
define RUN_FASTAPI_JWT_MW_ORDERING
|
|
205
|
+
LANGGRAPH_RUNTIME_EDITION=inmem \
|
|
206
|
+
LANGGRAPH_HTTP='{"app": "./tests/graphs/fastapi_jwt_middleware_ordering.py:app", "middleware_order": "$(1)", "enable_custom_route_auth": $(2)}' \
|
|
207
|
+
N_JOBS_PER_WORKER=2 \
|
|
208
|
+
LANGSERVE_GRAPHS=$(LANGSERVE_GRAPHS_AUTH) \
|
|
209
|
+
LANGGRAPH_STORE='$(STORE_CONFIG)' \
|
|
210
|
+
LANGGRAPH_AUTH='{"path": "./tests/graphs/fastapi_jwt_middleware_ordering.py:auth"}' \
|
|
211
|
+
LANGSMITH_LANGGRAPH_API_VARIANT=test \
|
|
212
|
+
REDIS_URI=fake \
|
|
213
|
+
DATABASE_URI=:memory: \
|
|
214
|
+
MIGRATIONS_PATH=__inmem \
|
|
215
|
+
uv run uvicorn \
|
|
216
|
+
"langgraph_api.server:app" \
|
|
217
|
+
--reload \
|
|
218
|
+
--port 9123 \
|
|
219
|
+
--reload-dir langgraph_api \
|
|
220
|
+
--reload-dir ../runtime_inmem \
|
|
221
|
+
--no-access-log
|
|
222
|
+
endef
|
|
223
|
+
|
|
224
|
+
start-auth-fastapi-jwt--before-custom-middleware--no-custom-route-auth:
|
|
225
|
+
$(call RUN_FASTAPI_JWT_MW_ORDERING,auth_first,false)
|
|
226
|
+
|
|
227
|
+
start-auth-fastapi-jwt--after-custom-middleware--no-custom-route-auth:
|
|
228
|
+
$(call RUN_FASTAPI_JWT_MW_ORDERING,middleware_first,false)
|
|
229
|
+
|
|
230
|
+
start-auth-fastapi-jwt--before-custom-middleware--custom-route-auth:
|
|
231
|
+
$(call RUN_FASTAPI_JWT_MW_ORDERING,auth_first,true)
|
|
232
|
+
|
|
233
|
+
start-auth-fastapi-jwt--after-custom-middleware--custom-route-auth:
|
|
234
|
+
$(call RUN_FASTAPI_JWT_MW_ORDERING,middleware_first,true)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
start-js-server:
|
|
238
|
+
@echo "Building and starting Go gRPC server..."
|
|
239
|
+
$(MAKE) build-go-server
|
|
240
|
+
$(MAKE) start-go-server
|
|
241
|
+
@trap '$(MAKE) -C $(CURDIR) stop-go-server' INT TERM EXIT; \
|
|
242
|
+
echo "Installing JS server dependencies..."; \
|
|
243
|
+
cd ../public-api-server-js && yarn install; \
|
|
244
|
+
echo "Building JS server..."; \
|
|
245
|
+
cd ../public-api-server-js && yarn run build; \
|
|
246
|
+
echo "Starting JS server on port 9123..."; \
|
|
247
|
+
cd ../public-api-server-js && FF_USE_CORE_API=true \
|
|
248
|
+
LANGSERVE_GRAPHS=$(LANGSERVE_GRAPHS_ALL) \
|
|
249
|
+
LANGGRAPH_CONFIG='{"agent": {"configurable": {"model_name": "openai"}}}' \
|
|
250
|
+
FF_USE_JS_API=true \
|
|
251
|
+
PORT=9123 yarn start
|
|
252
|
+
|
|
253
|
+
VERSION_KIND ?= patch
|
|
254
|
+
|
|
255
|
+
bump-version:
|
|
256
|
+
uv run --with hatch hatch version $(VERSION_KIND)
|
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.
|
|
4
|
-
Author-email:
|
|
3
|
+
Version: 0.6.25
|
|
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
|
|
7
7
|
Requires-Python: >=3.11
|
|
8
8
|
Requires-Dist: cloudpickle>=3.0.0
|
|
9
|
-
Requires-Dist: cryptography<
|
|
9
|
+
Requires-Dist: cryptography<47.0,>=42.0.0
|
|
10
|
+
Requires-Dist: grpcio-health-checking<2.0.0,>=1.75.0
|
|
11
|
+
Requires-Dist: grpcio-tools==1.75.1
|
|
12
|
+
Requires-Dist: grpcio<2.0.0,>=1.75.0
|
|
10
13
|
Requires-Dist: httpx>=0.25.0
|
|
11
14
|
Requires-Dist: jsonschema-rs<0.30,>=0.20.0
|
|
12
15
|
Requires-Dist: langchain-core>=0.3.64
|
|
13
|
-
Requires-Dist: langgraph-checkpoint
|
|
14
|
-
Requires-Dist: langgraph-runtime-inmem<0.
|
|
15
|
-
Requires-Dist: langgraph-sdk>=0.
|
|
16
|
-
Requires-Dist: langgraph
|
|
16
|
+
Requires-Dist: langgraph-checkpoint<5,>=3.0.1
|
|
17
|
+
Requires-Dist: langgraph-runtime-inmem<0.23.0,>=0.22.0
|
|
18
|
+
Requires-Dist: langgraph-sdk>=0.3.0
|
|
19
|
+
Requires-Dist: langgraph<2,>=0.4.10
|
|
17
20
|
Requires-Dist: langsmith>=0.3.45
|
|
21
|
+
Requires-Dist: opentelemetry-api>=1.37.0
|
|
22
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.37.0
|
|
23
|
+
Requires-Dist: opentelemetry-sdk>=1.37.0
|
|
18
24
|
Requires-Dist: orjson>=3.9.7
|
|
25
|
+
Requires-Dist: protobuf<7.0.0,>=6.32.1
|
|
19
26
|
Requires-Dist: pyjwt>=2.9.0
|
|
20
27
|
Requires-Dist: sse-starlette<2.2.0,>=2.1.0
|
|
21
28
|
Requires-Dist: starlette>=0.38.6
|
|
22
29
|
Requires-Dist: structlog<26,>=24.1.0
|
|
23
30
|
Requires-Dist: tenacity>=8.0.0
|
|
24
31
|
Requires-Dist: truststore>=0.1
|
|
32
|
+
Requires-Dist: uuid-utils>=0.12.0
|
|
25
33
|
Requires-Dist: uvicorn>=0.26.0
|
|
26
34
|
Requires-Dist: watchfiles>=0.13
|
|
27
35
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Benchmark commands
|
|
2
|
+
BASE_URL ?= https://benchmark-dr-s-2799835ad04b501a95044223ae72ced7.staging.langgraph.app
|
|
3
|
+
SLOWEST_N ?= 2
|
|
4
|
+
RAMP_START ?= 40
|
|
5
|
+
RAMP_END ?= 1000
|
|
6
|
+
RAMP_MULTIPLIER ?= 2
|
|
7
|
+
WAIT_SECONDS ?= 60
|
|
8
|
+
CLEAR_BETWEEN_STEPS ?= true
|
|
9
|
+
CLEAR_DELAY_SECONDS ?= 5
|
|
10
|
+
DATA_SIZE ?= 1000
|
|
11
|
+
DELAY ?= 0
|
|
12
|
+
EXPAND ?= 1
|
|
13
|
+
STEPS ?= 100
|
|
14
|
+
|
|
15
|
+
benchmark-burst:
|
|
16
|
+
make benchmark-reset
|
|
17
|
+
k6 run burst.js
|
|
18
|
+
|
|
19
|
+
benchmark-ramp:
|
|
20
|
+
make benchmark-reset
|
|
21
|
+
k6 run --out json=raw_data_$(shell date +%Y-%m-%dT%H-%M-%S).json --system-tags=[] ramp.js
|
|
22
|
+
|
|
23
|
+
benchmark-capacity:
|
|
24
|
+
rm -f capacity_summary_t*.json capacity_raw_t*.json capacity_histogram_*.json
|
|
25
|
+
npm install
|
|
26
|
+
BASE_URL=$(BASE_URL) \
|
|
27
|
+
SLOWEST_N=$(SLOWEST_N) \
|
|
28
|
+
RAMP_START=$(RAMP_START) \
|
|
29
|
+
RAMP_END=$(RAMP_END) \
|
|
30
|
+
RAMP_MULTIPLIER=$(RAMP_MULTIPLIER) \
|
|
31
|
+
WAIT_SECONDS=$(WAIT_SECONDS) \
|
|
32
|
+
CLEAR_BETWEEN_STEPS=$(CLEAR_BETWEEN_STEPS) \
|
|
33
|
+
CLEAR_DELAY_SECONDS=$(CLEAR_DELAY_SECONDS) \
|
|
34
|
+
DATA_SIZE=$(DATA_SIZE) \
|
|
35
|
+
DELAY=$(DELAY) \
|
|
36
|
+
EXPAND=$(EXPAND) \
|
|
37
|
+
STEPS=$(STEPS) \
|
|
38
|
+
node capacity_runner.mjs
|
|
39
|
+
|
|
40
|
+
benchmark-charts:
|
|
41
|
+
npm install
|
|
42
|
+
node graphs.js $(shell ls -t raw_data_*.json | head -1) true
|
|
43
|
+
|
|
44
|
+
benchmark-reset:
|
|
45
|
+
node clean.js
|
|
46
|
+
|
|
47
|
+
benchmark-new-revision:
|
|
48
|
+
node update-revision.js
|
|
49
|
+
|
|
50
|
+
benchmark-clean:
|
|
51
|
+
rm -f results_*.json summary_*.json raw_data_*.json *_chart_*.png
|
|
52
|
+
|
|
53
|
+
benchmark-clean-charts:
|
|
54
|
+
rm -f *_chart_*.png
|
|
55
|
+
|
|
56
|
+
# Mixed workload benchmark - tests quick runs competing with long runs
|
|
57
|
+
QUICK_VUS ?= 250
|
|
58
|
+
QUICK_ITERATIONS ?= 1000
|
|
59
|
+
QUICK_STEPS ?= 5
|
|
60
|
+
QUICK_DATA_SIZE ?= 100
|
|
61
|
+
QUICK_MAX_WAIT_SECONDS ?= 120
|
|
62
|
+
QUICK_POLL_INTERVAL ?= 2
|
|
63
|
+
LONG_VUS ?= 5
|
|
64
|
+
LONG_ITERATIONS ?= 10
|
|
65
|
+
LONG_STEPS ?= 50
|
|
66
|
+
LONG_DELAY ?= 1
|
|
67
|
+
LONG_DATA_SIZE ?= 10000
|
|
68
|
+
LONG_MAX_WAIT_SECONDS ?= 200
|
|
69
|
+
LONG_POLL_INTERVAL ?= 5
|
|
70
|
+
|
|
71
|
+
benchmark-mixed:
|
|
72
|
+
rm -f mixed_workload_*.json
|
|
73
|
+
npm install
|
|
74
|
+
BASE_URL=$(BASE_URL) \
|
|
75
|
+
SLOWEST_N=$(SLOWEST_N) \
|
|
76
|
+
QUICK_VUS=$(QUICK_VUS) \
|
|
77
|
+
QUICK_ITERATIONS=$(QUICK_ITERATIONS) \
|
|
78
|
+
QUICK_STEPS=$(QUICK_STEPS) \
|
|
79
|
+
QUICK_DATA_SIZE=$(QUICK_DATA_SIZE) \
|
|
80
|
+
QUICK_MAX_WAIT_SECONDS=$(QUICK_MAX_WAIT_SECONDS) \
|
|
81
|
+
QUICK_POLL_INTERVAL=$(QUICK_POLL_INTERVAL) \
|
|
82
|
+
LONG_VUS=$(LONG_VUS) \
|
|
83
|
+
LONG_ITERATIONS=$(LONG_ITERATIONS) \
|
|
84
|
+
LONG_STEPS=$(LONG_STEPS) \
|
|
85
|
+
LONG_DELAY=$(LONG_DELAY) \
|
|
86
|
+
LONG_DATA_SIZE=$(LONG_DATA_SIZE) \
|
|
87
|
+
LONG_MAX_WAIT_SECONDS=$(LONG_MAX_WAIT_SECONDS) \
|
|
88
|
+
LONG_POLL_INTERVAL=$(LONG_POLL_INTERVAL) \
|
|
89
|
+
node mixed_workload_runner.mjs
|
|
@@ -7,7 +7,7 @@ K6 is a modern load testing tool that allows you to test the performance and rel
|
|
|
7
7
|
### Available Tests
|
|
8
8
|
|
|
9
9
|
There are two modes of testing available:
|
|
10
|
-
1. `Burst` - Kick off a burst of /run/wait requests.
|
|
10
|
+
1. `Burst` - Kick off a burst of /run/wait requests.
|
|
11
11
|
Available Params:
|
|
12
12
|
BURST_SIZE - How many requests to run. Default: 100
|
|
13
13
|
2. `Ramp` - Scale up the number of /run/wait requests and then plateau.
|
|
@@ -71,4 +71,4 @@ Charts can be created from the run locally using the `make benchmark-charts` com
|
|
|
71
71
|
|
|
72
72
|
- [K6 Documentation](https://k6.io/docs/)
|
|
73
73
|
- [K6 JavaScript API](https://k6.io/docs/javascript-api/)
|
|
74
|
-
- [Performance Testing Best Practices](https://k6.io/docs/testing-guides/)
|
|
74
|
+
- [Performance Testing Best Practices](https://k6.io/docs/testing-guides/)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { BenchmarkRunner } from './benchmark-runner.js';
|
|
2
|
+
import http from 'k6/http';
|
|
3
|
+
import { check } from 'k6';
|
|
4
|
+
// Uses crypto which is globally available in k6: https://grafana.com/docs/k6/latest/javascript-api/#crypto
|
|
5
|
+
|
|
6
|
+
export class Assistant extends BenchmarkRunner {
|
|
7
|
+
/**
|
|
8
|
+
* Create an assistant, search for it, get it, patch it, get it again, count the number of assistants, delete the assistant
|
|
9
|
+
*/
|
|
10
|
+
static run(baseUrl, requestParams) {
|
|
11
|
+
const graph_id = 'benchmark';
|
|
12
|
+
let metadata = { description: `Test benchmark assistant ${crypto.randomUUID()}`, created_by: 'benchmark' };
|
|
13
|
+
|
|
14
|
+
// Create an assistant
|
|
15
|
+
const createPayload = JSON.stringify({ graph_id, metadata });
|
|
16
|
+
const createResponse = http.post(`${baseUrl}/assistants`, createPayload, requestParams);
|
|
17
|
+
const assistantId = createResponse.json().assistant_id;
|
|
18
|
+
|
|
19
|
+
// Search for the assistant
|
|
20
|
+
const searchPayload = JSON.stringify({ graph_id, metadata, limit: 1 });
|
|
21
|
+
const searchResponse = http.post(`${baseUrl}/assistants/search`, searchPayload, requestParams);
|
|
22
|
+
|
|
23
|
+
// Get the assistant
|
|
24
|
+
const getResponse = http.get(`${baseUrl}/assistants/${assistantId}`, requestParams);
|
|
25
|
+
|
|
26
|
+
// Patch the assistant
|
|
27
|
+
metadata = { description: `Test benchmark assistant ${crypto.randomUUID()}` };
|
|
28
|
+
const patchPayload = JSON.stringify({ metadata });
|
|
29
|
+
const patchResponse = http.patch(`${baseUrl}/assistants/${assistantId}`, patchPayload, requestParams);
|
|
30
|
+
|
|
31
|
+
// Get the assistant again
|
|
32
|
+
const getResponse2 = http.get(`${baseUrl}/assistants/${assistantId}`, requestParams);
|
|
33
|
+
|
|
34
|
+
// Count the number of assistants
|
|
35
|
+
const countPayload = JSON.stringify({ graph_id, metadata });
|
|
36
|
+
const countResponse = http.post(`${baseUrl}/assistants/count`, countPayload, requestParams);
|
|
37
|
+
|
|
38
|
+
// Delete the assistant
|
|
39
|
+
const deleteResponse = http.del(`${baseUrl}/assistants/${assistantId}`, "{}", requestParams);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
assistantId,
|
|
43
|
+
searchResponse,
|
|
44
|
+
getResponse,
|
|
45
|
+
patchResponse,
|
|
46
|
+
getResponse2,
|
|
47
|
+
countResponse,
|
|
48
|
+
deleteResponse,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static validate(result, errorMetrics, benchmarkGraphOptions) {
|
|
53
|
+
let success = false;
|
|
54
|
+
try {
|
|
55
|
+
success = check(result, {
|
|
56
|
+
'Search response contains a single assistant': (r) => r.searchResponse.json().length === 1,
|
|
57
|
+
'Search response contains the correct assistant': (r) => r.searchResponse.json()[0].assistant_id === result.assistantId,
|
|
58
|
+
'Get response contains the correct assistant': (r) => r.getResponse.json().assistant_id === result.assistantId,
|
|
59
|
+
'Patch response contains the correct assistant': (r) => r.patchResponse.json().assistant_id === result.assistantId,
|
|
60
|
+
'Get response 2 contains the correct assistant': (r) => r.getResponse2.json().assistant_id === result.assistantId,
|
|
61
|
+
'Get response 2 contains the new description': (r) => r.getResponse2.json().metadata.description != result.getResponse.json().metadata.description && result.getResponse2.json().metadata.description === result.patchResponse.json().metadata.description,
|
|
62
|
+
'Get response 2 contains the correct created_by': (r) => r.getResponse2.json().metadata.created_by === 'benchmark',
|
|
63
|
+
'Count response contains the correct number of assistants': (r) => parseInt(r.countResponse.json()) === 1,
|
|
64
|
+
'Delete response is successful': (r) => r.deleteResponse.status === 204,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.log(`Unknown error checking response: ${error.message}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!success) {
|
|
71
|
+
if (result.searchResponse.status == 502 || result.getResponse.status == 502 || result.patchResponse.status == 502 || result.getResponse2.status == 502 || result.countResponse.status == 502 || result.deleteResponse.status == 502) {
|
|
72
|
+
errorMetrics.server_errors.add(1);
|
|
73
|
+
console.log(`Server error: ${result.searchResponse.status}, ${result.getResponse.status}, ${result.patchResponse.status}, ${result.getResponse2.status}, ${result.countResponse.status}, ${result.deleteResponse.status}`);
|
|
74
|
+
} else if (result.searchResponse.status === 408 || result.getResponse.status === 408 || result.patchResponse.status === 408 || result.getResponse2.status === 408 || result.countResponse.status === 408 || result.deleteResponse.status === 408) {
|
|
75
|
+
errorMetrics.timeout_errors.add(1);
|
|
76
|
+
console.log(`Timeout error: ${result.searchResponse.error}, ${result.getResponse.error}, ${result.patchResponse.error}, ${result.getResponse2.error}, ${result.countResponse.error}, ${result.deleteResponse.error}`);
|
|
77
|
+
} else {
|
|
78
|
+
errorMetrics.other_errors.add(1);
|
|
79
|
+
console.log(`Other error: ${result.searchResponse.body}, ${result.getResponse.body}, ${result.patchResponse.body}, ${result.getResponse2.body}, ${result.countResponse.body}, ${result.deleteResponse.body}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return success;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static toString() {
|
|
86
|
+
return 'assistants';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract class for running a benchmark type.
|
|
3
|
+
*/
|
|
4
|
+
export class BenchmarkRunner {
|
|
5
|
+
/**
|
|
6
|
+
* Run the benchmark type.
|
|
7
|
+
* @param {string} baseUrl - The base URL of the Agent Server.
|
|
8
|
+
* @param {any} requestParams - The parameters to use for the request. Includes headers and other config like timeout.
|
|
9
|
+
* @param {any} benchmarkGraphOptions - The options for the benchmark graph.
|
|
10
|
+
* @returns {any} - The result of the benchmark type. This format will vary by benchmark type.
|
|
11
|
+
*/
|
|
12
|
+
static run(baseUrl, requestParams, benchmarkGraphOptions) {
|
|
13
|
+
throw new Error('Not implemented');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Convert the benchmark name to a string.
|
|
18
|
+
* @returns {string} - A string representation of the benchmark name.
|
|
19
|
+
*/
|
|
20
|
+
static toString() {
|
|
21
|
+
throw new Error('Not implemented');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Validate the result of the benchmark run.
|
|
26
|
+
* @param {any} result - The result of the benchmark run. This format will vary by benchmark type.
|
|
27
|
+
* @param {any} errorMetrics - A dictionary of error metrics that can be used to more granularly track errors.
|
|
28
|
+
* @param {any} benchmarkGraphOptions - The options for the benchmark graph.
|
|
29
|
+
* @returns {boolean} - True if the benchmark run was successful, false otherwise.
|
|
30
|
+
*/
|
|
31
|
+
static validate(result, errorMetrics, benchmarkGraphOptions) {
|
|
32
|
+
throw new Error('Not implemented');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WaitWrite } from './wait_write.js';
|
|
2
|
+
import { StreamWrite } from './stream_write.js';
|
|
3
|
+
import { Assistant } from './assistant.js';
|
|
4
|
+
import { Thread } from './thread.js';
|
|
5
|
+
|
|
6
|
+
export class Benchmarks {
|
|
7
|
+
static getRunner(type) {
|
|
8
|
+
switch (type) {
|
|
9
|
+
case WaitWrite.toString():
|
|
10
|
+
return WaitWrite;
|
|
11
|
+
case StreamWrite.toString():
|
|
12
|
+
return StreamWrite;
|
|
13
|
+
case Assistant.toString():
|
|
14
|
+
return Assistant;
|
|
15
|
+
case Thread.toString():
|
|
16
|
+
return Thread;
|
|
17
|
+
default:
|
|
18
|
+
throw new Error(`Unknown benchmark type: ${type}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { BenchmarkRunner } from './benchmark-runner.js';
|
|
2
|
+
import { check } from 'k6';
|
|
3
|
+
import http from 'k6/http';
|
|
4
|
+
|
|
5
|
+
function parseSSE(text) {
|
|
6
|
+
const events = [];
|
|
7
|
+
const lines = text.split('\r\n');
|
|
8
|
+
let currentEvent = { event: '', data: '' };
|
|
9
|
+
|
|
10
|
+
for (const line of lines) {
|
|
11
|
+
if (line.startsWith('event:')) {
|
|
12
|
+
currentEvent.event = line.substring(6).trim();
|
|
13
|
+
} else if (line.startsWith('data:')) {
|
|
14
|
+
const dataContent = line.substring(5).trim();
|
|
15
|
+
currentEvent.data = dataContent;
|
|
16
|
+
} else if (line === '') {
|
|
17
|
+
// Empty line marks end of event
|
|
18
|
+
if (currentEvent.data) {
|
|
19
|
+
try {
|
|
20
|
+
events.push({
|
|
21
|
+
event: currentEvent.event,
|
|
22
|
+
data: JSON.parse(currentEvent.data)
|
|
23
|
+
});
|
|
24
|
+
} catch (e) {
|
|
25
|
+
// Some events might not be JSON
|
|
26
|
+
events.push(currentEvent);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
currentEvent = { event: '', data: '' };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return events;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class StreamWrite extends BenchmarkRunner {
|
|
37
|
+
static run(baseUrl, requestParams, benchmarkGraphOptions) {
|
|
38
|
+
let url = `${baseUrl}/runs/stream`;
|
|
39
|
+
|
|
40
|
+
// Create a payload with the LangGraph agent configuration
|
|
41
|
+
const payload = JSON.stringify({
|
|
42
|
+
assistant_id: benchmarkGraphOptions.graph_id,
|
|
43
|
+
input: benchmarkGraphOptions.input,
|
|
44
|
+
config: {
|
|
45
|
+
recursion_limit: benchmarkGraphOptions.input.expand + 2,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// If the request is stateful, create a thread first and use it in the url
|
|
50
|
+
if (benchmarkGraphOptions.stateful) {
|
|
51
|
+
const thread = http.post(`${baseUrl}/threads`, "{}", requestParams);
|
|
52
|
+
const threadId = thread.json().thread_id;
|
|
53
|
+
url = `${baseUrl}/threads/${threadId}/runs/stream`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const response = http.post(url, payload, requestParams);
|
|
57
|
+
const events = parseSSE(response.body);
|
|
58
|
+
return { events, response };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static validate(result, errorMetrics, benchmarkGraphOptions) {
|
|
62
|
+
const expected_messages = benchmarkGraphOptions.input.mode === 'single' ? 1 : benchmarkGraphOptions.input.expand + 1;
|
|
63
|
+
const expected_events = expected_messages + 2; // +2 for the metadata and initial values event
|
|
64
|
+
let success = false;
|
|
65
|
+
try {
|
|
66
|
+
success = check(result, {
|
|
67
|
+
'Run completed successfully': (r) => r.response.status === 200,
|
|
68
|
+
'Response contains expected number of events': (r) => r.events.length === expected_events,
|
|
69
|
+
'Response contains metadata event': (r) => r.events[0].event === 'metadata',
|
|
70
|
+
'Response contains expected number of messages': (r) => r.events[expected_events - 1].data.messages.length === expected_messages,
|
|
71
|
+
});
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.log(`Unknown error checking result: ${error.message}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!success) {
|
|
77
|
+
// Classify error based on status code or response
|
|
78
|
+
if (result.response.status >= 500) {
|
|
79
|
+
errorMetrics.server_errors.add(1);
|
|
80
|
+
console.log(`Server error: ${result.response.status}`);
|
|
81
|
+
} else if (result.response.status === 408 || result.response.error?.includes('timeout')) {
|
|
82
|
+
errorMetrics.timeout_errors.add(1);
|
|
83
|
+
console.log(`Timeout error: ${result.response.error}`);
|
|
84
|
+
} else if (result.response.status === 200 && result.events[expected_events - 1].data.messages.length !== expected_messages) {
|
|
85
|
+
errorMetrics.missing_message_errors.add(1);
|
|
86
|
+
console.log(`Missing message error: Status ${result.response.status}, ${JSON.stringify(result.response.body)}, ${result.response.headers?.['Content-Location']}`);
|
|
87
|
+
} else {
|
|
88
|
+
errorMetrics.other_errors.add(1);
|
|
89
|
+
console.log(`Other error: Status ${result.response.status}, ${JSON.stringify(result.response.body)}, ${result.events}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return success;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static toString() {
|
|
96
|
+
return 'stream_write';
|
|
97
|
+
}
|
|
98
|
+
}
|