langgraph-api 0.4.24__tar.gz → 0.5.35__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.
Files changed (188) hide show
  1. langgraph_api-0.5.35/Makefile +256 -0
  2. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/PKG-INFO +13 -6
  3. langgraph_api-0.5.35/benchmark/Makefile +52 -0
  4. langgraph_api-0.5.35/benchmark/benchmark-runners/assistant.js +88 -0
  5. langgraph_api-0.5.35/benchmark/benchmark-runners/benchmark-runner.js +34 -0
  6. langgraph_api-0.5.35/benchmark/benchmark-runners/benchmarks.js +21 -0
  7. langgraph_api-0.5.35/benchmark/benchmark-runners/stream_write.js +98 -0
  8. langgraph_api-0.5.35/benchmark/benchmark-runners/thread.js +87 -0
  9. langgraph_api-0.5.35/benchmark/benchmark-runners/wait_write.js +65 -0
  10. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/burst.js +1 -1
  11. langgraph_api-0.5.35/benchmark/capacity_k6.js +218 -0
  12. langgraph_api-0.5.35/benchmark/capacity_runner.mjs +317 -0
  13. langgraph_api-0.5.35/benchmark/capacity_urls.mjs +8 -0
  14. langgraph_api-0.5.35/benchmark/clean.js +150 -0
  15. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/graphs.js +16 -14
  16. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/package.json +1 -1
  17. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/ramp.js +80 -86
  18. langgraph_api-0.5.35/benchmark/reporting/dd_reporting.py +88 -0
  19. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/update-revision.js +19 -7
  20. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/constraints.txt +5 -2
  21. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/healthcheck.py +2 -1
  22. langgraph_api-0.5.35/langgraph_api/__init__.py +1 -0
  23. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/__init__.py +38 -29
  24. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/a2a.py +36 -17
  25. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/assistants.py +180 -87
  26. langgraph_api-0.5.35/langgraph_api/api/encryption_middleware.py +403 -0
  27. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/mcp.py +3 -3
  28. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/meta.py +9 -4
  29. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/openapi.py +6 -1
  30. langgraph_api-0.5.35/langgraph_api/api/profile.py +108 -0
  31. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/runs.py +113 -15
  32. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/threads.py +68 -13
  33. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/asgi_transport.py +14 -9
  34. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/custom.py +30 -25
  35. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/langsmith/backend.py +3 -2
  36. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/langsmith/client.py +13 -8
  37. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/cli.py +87 -91
  38. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/command.py +2 -2
  39. langgraph_api-0.4.24/langgraph_api/config.py → langgraph_api-0.5.35/langgraph_api/config/__init__.py +190 -166
  40. langgraph_api-0.5.35/langgraph_api/config/_parse.py +39 -0
  41. langgraph_api-0.5.35/langgraph_api/config/schemas.py +245 -0
  42. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/cron_scheduler.py +17 -0
  43. langgraph_api-0.5.35/langgraph_api/encryption/__init__.py +9 -0
  44. langgraph_api-0.5.35/langgraph_api/encryption/context.py +35 -0
  45. langgraph_api-0.5.35/langgraph_api/encryption/custom.py +147 -0
  46. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/executor_entrypoint.py +11 -6
  47. langgraph_api-0.5.35/langgraph_api/feature_flags.py +32 -0
  48. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/graph.py +21 -20
  49. langgraph_api-0.5.35/langgraph_api/grpc/client.py +190 -0
  50. langgraph_api-0.5.35/langgraph_api/grpc/config_conversion.py +228 -0
  51. langgraph_api-0.5.35/langgraph_api/grpc/generated/__init__.py +23 -0
  52. langgraph_api-0.5.35/langgraph_api/grpc/generated/core_api_pb2.py +285 -0
  53. langgraph_api-0.5.35/langgraph_api/grpc/generated/core_api_pb2.pyi +982 -0
  54. langgraph_api-0.5.35/langgraph_api/grpc/generated/core_api_pb2_grpc.py +1488 -0
  55. langgraph_api-0.5.35/langgraph_api/grpc/generated/engine_common_pb2.py +211 -0
  56. langgraph_api-0.5.35/langgraph_api/grpc/generated/engine_common_pb2.pyi +685 -0
  57. langgraph_api-0.5.35/langgraph_api/grpc/generated/engine_common_pb2_grpc.py +24 -0
  58. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_cancel_run_action_pb2.py +37 -0
  59. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_cancel_run_action_pb2.pyi +12 -0
  60. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_cancel_run_action_pb2_grpc.py +24 -0
  61. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_durability_pb2.py +37 -0
  62. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_durability_pb2.pyi +16 -0
  63. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_durability_pb2_grpc.py +24 -0
  64. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_multitask_strategy_pb2.py +37 -0
  65. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_multitask_strategy_pb2.pyi +16 -0
  66. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_multitask_strategy_pb2_grpc.py +24 -0
  67. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_run_status_pb2.py +37 -0
  68. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_run_status_pb2.pyi +22 -0
  69. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_run_status_pb2_grpc.py +24 -0
  70. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_stream_mode_pb2.py +37 -0
  71. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_stream_mode_pb2.pyi +28 -0
  72. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_stream_mode_pb2_grpc.py +24 -0
  73. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_thread_status_pb2.py +37 -0
  74. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_thread_status_pb2.pyi +16 -0
  75. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_thread_status_pb2_grpc.py +24 -0
  76. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_thread_stream_mode_pb2.py +37 -0
  77. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_thread_stream_mode_pb2.pyi +16 -0
  78. langgraph_api-0.5.35/langgraph_api/grpc/generated/enum_thread_stream_mode_pb2_grpc.py +24 -0
  79. langgraph_api-0.5.35/langgraph_api/grpc/generated/errors_pb2.py +39 -0
  80. langgraph_api-0.5.35/langgraph_api/grpc/generated/errors_pb2.pyi +21 -0
  81. langgraph_api-0.5.35/langgraph_api/grpc/generated/errors_pb2_grpc.py +24 -0
  82. langgraph_api-0.5.35/langgraph_api/grpc/ops/__init__.py +181 -0
  83. langgraph_api-0.5.35/langgraph_api/grpc/ops/assistants.py +419 -0
  84. langgraph_api-0.5.35/langgraph_api/grpc/ops/threads.py +502 -0
  85. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/http_metrics.py +15 -35
  86. langgraph_api-0.5.35/langgraph_api/http_metrics_utils.py +38 -0
  87. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/build.mts +1 -1
  88. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/client.http.mts +13 -7
  89. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/client.mts +2 -5
  90. langgraph_api-0.5.35/langgraph_api/js/package.json +47 -0
  91. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/remote.py +39 -17
  92. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/src/graph.mts +20 -0
  93. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/sse.py +2 -2
  94. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/ui.py +1 -1
  95. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/yarn.lock +272 -329
  96. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/logging.py +24 -0
  97. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/metadata.py +34 -26
  98. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/middleware/http_logger.py +1 -1
  99. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/middleware/private_network.py +7 -7
  100. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/models/run.py +12 -17
  101. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/patch.py +2 -2
  102. langgraph_api-0.5.35/langgraph_api/queue_entrypoint.py +259 -0
  103. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/route.py +47 -5
  104. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/schema.py +24 -6
  105. langgraph_api-0.5.35/langgraph_api/self_hosted_logs.py +124 -0
  106. langgraph_api-0.5.35/langgraph_api/self_hosted_metrics.py +426 -0
  107. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/serde.py +74 -18
  108. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/server.py +116 -41
  109. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/state.py +3 -2
  110. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/stream.py +21 -25
  111. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/thread_ttl.py +1 -1
  112. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/utils/__init__.py +17 -5
  113. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/utils/config.py +2 -1
  114. langgraph_api-0.5.35/langgraph_api/utils/errors.py +77 -0
  115. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/utils/future.py +10 -6
  116. langgraph_api-0.5.35/langgraph_api/utils/uuids.py +54 -0
  117. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/validation.py +6 -0
  118. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/webhook.py +5 -2
  119. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/worker.py +28 -5
  120. langgraph_api-0.5.35/langgraph_license/__init__.py +0 -0
  121. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/logging.json +1 -3
  122. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/openapi.json +297 -487
  123. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/pyproject.toml +24 -8
  124. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/scripts/create_license.py +1 -0
  125. langgraph_api-0.5.35/uv.lock +1991 -0
  126. langgraph_api-0.4.24/Makefile +0 -123
  127. langgraph_api-0.4.24/benchmark/Makefile +0 -24
  128. langgraph_api-0.4.24/benchmark/clean.js +0 -87
  129. langgraph_api-0.4.24/langgraph_api/__init__.py +0 -1
  130. langgraph_api-0.4.24/langgraph_api/feature_flags.py +0 -9
  131. langgraph_api-0.4.24/langgraph_api/js/package.json +0 -47
  132. langgraph_api-0.4.24/langgraph_api/queue_entrypoint.py +0 -178
  133. langgraph_api-0.4.24/langgraph_api/utils/uuids.py +0 -87
  134. langgraph_api-0.4.24/uv.lock +0 -1451
  135. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/.gitignore +0 -0
  136. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/LICENSE +0 -0
  137. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/README.md +0 -0
  138. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/.gitignore +0 -0
  139. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/README.md +0 -0
  140. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/benchmark/weather.js +0 -0
  141. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/forbidden.txt +0 -0
  142. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/store.py +0 -0
  143. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/api/ui.py +0 -0
  144. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/asyncio.py +0 -0
  145. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/__init__.py +0 -0
  146. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/langsmith/__init__.py +0 -0
  147. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/middleware.py +0 -0
  148. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/noop.py +0 -0
  149. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/auth/studio_user.py +0 -0
  150. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/errors.py +0 -0
  151. {langgraph_api-0.4.24/langgraph_api/js → langgraph_api-0.5.35/langgraph_api/grpc}/__init__.py +0 -0
  152. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/http.py +0 -0
  153. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/.gitignore +0 -0
  154. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/.prettierrc +0 -0
  155. {langgraph_api-0.4.24/langgraph_api/middleware → langgraph_api-0.5.35/langgraph_api/js}/__init__.py +0 -0
  156. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/base.py +0 -0
  157. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/errors.py +0 -0
  158. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/global.d.ts +0 -0
  159. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/schema.py +0 -0
  160. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/src/load.hooks.mjs +0 -0
  161. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/src/preload.mjs +0 -0
  162. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/src/utils/files.mts +0 -0
  163. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/src/utils/importMap.mts +0 -0
  164. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  165. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/src/utils/serde.mts +0 -0
  166. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/traceblock.mts +0 -0
  167. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/js/tsconfig.json +0 -0
  168. {langgraph_api-0.4.24/langgraph_api/models → langgraph_api-0.5.35/langgraph_api/middleware}/__init__.py +0 -0
  169. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/middleware/request_id.py +0 -0
  170. {langgraph_api-0.4.24/langgraph_license → langgraph_api-0.5.35/langgraph_api/models}/__init__.py +0 -0
  171. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/sse.py +0 -0
  172. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/store.py +0 -0
  173. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/traceblock.py +0 -0
  174. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/tunneling/cloudflare.py +0 -0
  175. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/utils/cache.py +0 -0
  176. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/utils/headers.py +0 -0
  177. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/utils/retriable_client.py +0 -0
  178. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_api/utils/stream_codec.py +0 -0
  179. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_license/validation.py +0 -0
  180. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/__init__.py +0 -0
  181. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/checkpoint.py +0 -0
  182. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/database.py +0 -0
  183. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/lifespan.py +0 -0
  184. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/metrics.py +0 -0
  185. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/ops.py +0 -0
  186. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/queue.py +0 -0
  187. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/retry.py +0 -0
  188. {langgraph_api-0.4.24 → langgraph_api-0.5.35}/langgraph_runtime/store.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"}'
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 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,34 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.4.24
4
- Author-email: Nuno Campos <nuno@langchain.dev>, Will Fu-Hinthorn <will@langchain.dev>
3
+ Version: 0.5.35
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
9
  Requires-Dist: cryptography<45.0,>=42.0.0
10
+ Requires-Dist: grpcio-tools==1.75.1
11
+ Requires-Dist: grpcio<2.0.0,>=1.75.0
10
12
  Requires-Dist: httpx>=0.25.0
11
13
  Requires-Dist: jsonschema-rs<0.30,>=0.20.0
12
14
  Requires-Dist: langchain-core>=0.3.64
13
- Requires-Dist: langgraph-checkpoint>=2.0.23
14
- Requires-Dist: langgraph-runtime-inmem<0.15.0,>=0.14.0
15
- Requires-Dist: langgraph-sdk>=0.2.0
16
- Requires-Dist: langgraph>=0.4.0
15
+ Requires-Dist: langgraph-checkpoint<4,>=3.0.1
16
+ Requires-Dist: langgraph-runtime-inmem<0.20.0,>=0.19.0
17
+ Requires-Dist: langgraph-sdk>=0.2.10
18
+ Requires-Dist: langgraph<2,>=0.4.10
17
19
  Requires-Dist: langsmith>=0.3.45
20
+ Requires-Dist: opentelemetry-api>=1.37.0
21
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.37.0
22
+ Requires-Dist: opentelemetry-sdk>=1.37.0
18
23
  Requires-Dist: orjson>=3.9.7
24
+ Requires-Dist: protobuf<7.0.0,>=6.32.1
19
25
  Requires-Dist: pyjwt>=2.9.0
20
26
  Requires-Dist: sse-starlette<2.2.0,>=2.1.0
21
27
  Requires-Dist: starlette>=0.38.6
22
28
  Requires-Dist: structlog<26,>=24.1.0
23
29
  Requires-Dist: tenacity>=8.0.0
24
30
  Requires-Dist: truststore>=0.1
31
+ Requires-Dist: uuid-utils>=0.12.0
25
32
  Requires-Dist: uvicorn>=0.26.0
26
33
  Requires-Dist: watchfiles>=0.13
27
34
  Description-Content-Type: text/markdown
@@ -0,0 +1,52 @@
1
+ # Benchmark commands
2
+ BASE_URL ?= https://benchmark-dr-s-2799835ad04b501a95044223ae72ced7.staging.langgraph.app
3
+ RAMP_START ?= 40
4
+ RAMP_END ?= 1000
5
+ RAMP_MULTIPLIER ?= 2
6
+ WAIT_SECONDS ?= 60
7
+ CLEAR_BETWEEN_STEPS ?= true
8
+ CLEAR_DELAY_SECONDS ?= 5
9
+ DATA_SIZE ?= 1000
10
+ DELAY ?= 0
11
+ EXPAND ?= 1
12
+ STEPS ?= 100
13
+
14
+ benchmark-burst:
15
+ make benchmark-reset
16
+ k6 run burst.js
17
+
18
+ benchmark-ramp:
19
+ make benchmark-reset
20
+ k6 run --out json=raw_data_$(shell date +%Y-%m-%dT%H-%M-%S).json --system-tags=[] ramp.js
21
+
22
+ benchmark-capacity:
23
+ rm -f capacity_summary_t*.json capacity_raw_t*.json capacity_histogram_*.json
24
+ npm install
25
+ BASE_URL=$(BASE_URL) \
26
+ RAMP_START=$(RAMP_START) \
27
+ RAMP_END=$(RAMP_END) \
28
+ RAMP_MULTIPLIER=$(RAMP_MULTIPLIER) \
29
+ WAIT_SECONDS=$(WAIT_SECONDS) \
30
+ CLEAR_BETWEEN_STEPS=$(CLEAR_BETWEEN_STEPS) \
31
+ CLEAR_DELAY_SECONDS=$(CLEAR_DELAY_SECONDS) \
32
+ DATA_SIZE=$(DATA_SIZE) \
33
+ DELAY=$(DELAY) \
34
+ EXPAND=$(EXPAND) \
35
+ STEPS=$(STEPS) \
36
+ node capacity_runner.mjs
37
+
38
+ benchmark-charts:
39
+ npm install
40
+ node graphs.js $(shell ls -t raw_data_*.json | head -1) true
41
+
42
+ benchmark-reset:
43
+ node clean.js
44
+
45
+ benchmark-new-revision:
46
+ node update-revision.js
47
+
48
+ benchmark-clean:
49
+ rm -f results_*.json summary_*.json raw_data_*.json *_chart_*.png
50
+
51
+ benchmark-clean-charts:
52
+ rm -f *_chart_*.png
@@ -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
+ }