langgraph-api 0.14.0.dev10__tar.gz → 0.15.0.dev1__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 (300) hide show
  1. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/Makefile +1 -1
  2. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/PKG-INFO +2 -2
  3. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/README.md +49 -0
  4. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/benchmark_profiles.ts +20 -0
  5. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/benchmarks.ts +3 -0
  6. langgraph_api-0.15.0.dev1/benchmark/benchmark-runners/delta-turns-lib.test.js +169 -0
  7. langgraph_api-0.15.0.dev1/benchmark/benchmark-runners/delta-turns-lib.ts +102 -0
  8. langgraph_api-0.15.0.dev1/benchmark/benchmark-runners/delta_turns.ts +169 -0
  9. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/ramp.js +1 -1
  10. langgraph_api-0.15.0.dev1/langgraph_api/__init__.py +1 -0
  11. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/queue_entrypoint.py +0 -1
  12. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/pyproject.toml +1 -1
  13. langgraph_api-0.14.0.dev10/langgraph_api/__init__.py +0 -1
  14. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/.gitignore +0 -0
  15. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/LICENSE +0 -0
  16. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/README.md +0 -0
  17. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/.gitignore +0 -0
  18. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/Makefile +0 -0
  19. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/assistant.ts +0 -0
  20. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
  21. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
  22. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/classify-error.test.js +0 -0
  23. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/classify-error.ts +0 -0
  24. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
  25. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/log-failure.ts +0 -0
  26. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/meta_workload.ts +0 -0
  27. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/store.ts +0 -0
  28. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/stream_write.ts +0 -0
  29. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/thread.ts +0 -0
  30. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
  31. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
  32. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/types.ts +0 -0
  33. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/benchmark-runners/wait_write.ts +0 -0
  34. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/capacity-ci.js +0 -0
  35. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/capacity-ci.test.js +0 -0
  36. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/clean-cli.js +0 -0
  37. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/clean.js +0 -0
  38. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/continuous/README.md +0 -0
  39. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/continuous/pyproject.toml +0 -0
  40. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/continuous/runner.py +0 -0
  41. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/continuous/uv.lock +0 -0
  42. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/daily-report.js +0 -0
  43. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/daily-report.test.js +0 -0
  44. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/graphs.js +0 -0
  45. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/host-v2.js +0 -0
  46. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/host-v2.test.js +0 -0
  47. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/package.json +0 -0
  48. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/reporting/dd_reporting.py +0 -0
  49. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/staircase.py +0 -0
  50. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/staircase_step_k6.js +0 -0
  51. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/tsconfig.json +0 -0
  52. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/update-revision.js +0 -0
  53. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/weather.js +0 -0
  54. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/benchmark/yarn.lock +0 -0
  55. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/constraints.txt +0 -0
  56. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/custom_store.sql +0 -0
  57. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/forbidden.txt +0 -0
  58. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/hatch_build.py +0 -0
  59. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/healthcheck.py +0 -0
  60. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph-cloud-debugging-20260210132856.zip +0 -0
  61. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/_checkpointer/__init__.py +0 -0
  62. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/_checkpointer/_adapter.py +0 -0
  63. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/_checkpointer/protocol.py +0 -0
  64. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/_factory_utils.py +0 -0
  65. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/__init__.py +0 -0
  66. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/a2a.py +0 -0
  67. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/assistants.py +0 -0
  68. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/event_streaming.py +0 -0
  69. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/mcp/__init__.py +0 -0
  70. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/mcp/_constants.py +0 -0
  71. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/mcp/_handlers.py +0 -0
  72. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/mcp/_models.py +0 -0
  73. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/mcp/_routes.py +0 -0
  74. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/mcp/_sanitizers.py +0 -0
  75. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/meta.py +0 -0
  76. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/openapi.py +0 -0
  77. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/profile.py +0 -0
  78. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/runs.py +0 -0
  79. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/store.py +0 -0
  80. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/threads.py +0 -0
  81. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/api/ui.py +0 -0
  82. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/asgi_transport.py +0 -0
  83. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/asyncio.py +0 -0
  84. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/__init__.py +0 -0
  85. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/custom.py +0 -0
  86. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/errors.py +0 -0
  87. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/langsmith/__init__.py +0 -0
  88. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/langsmith/backend.py +0 -0
  89. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/langsmith/client.py +0 -0
  90. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/middleware.py +0 -0
  91. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/noop.py +0 -0
  92. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/auth/studio_user.py +0 -0
  93. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
  94. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/cache.py +0 -0
  95. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/cli.py +0 -0
  96. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/command.py +0 -0
  97. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/config/__init__.py +0 -0
  98. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/config/_parse.py +0 -0
  99. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/config/schemas.py +0 -0
  100. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/cron_scheduler.py +0 -0
  101. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/encryption/__init__.py +0 -0
  102. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/encryption/aes_json.py +0 -0
  103. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/encryption/context.py +0 -0
  104. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/encryption/custom.py +0 -0
  105. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/encryption/middleware.py +0 -0
  106. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/encryption/shared.py +0 -0
  107. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/errors.py +0 -0
  108. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/__init__.py +0 -0
  109. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/capabilities.py +0 -0
  110. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/constants.py +0 -0
  111. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/event_normalizers.py +0 -0
  112. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/namespace.py +0 -0
  113. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/service.py +0 -0
  114. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/session.py +0 -0
  115. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/state_normalizers.py +0 -0
  116. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/event_streaming/types.py +0 -0
  117. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/feature_flags.py +0 -0
  118. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/graph.py +0 -0
  119. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/__init__.py +0 -0
  120. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/client.py +0 -0
  121. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
  122. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/ops/__init__.py +0 -0
  123. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/ops/assistants.py +0 -0
  124. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/ops/cache.py +0 -0
  125. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/ops/crons.py +0 -0
  126. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/ops/runs.py +0 -0
  127. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/ops/threads.py +0 -0
  128. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/server.py +0 -0
  129. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/servicers/__init__.py +0 -0
  130. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
  131. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/grpc/servicers/encryption.py +0 -0
  132. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/http.py +0 -0
  133. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/http_metrics.py +0 -0
  134. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/http_metrics_utils.py +0 -0
  135. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/.gitignore +0 -0
  136. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/.prettierrc +0 -0
  137. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/.yarnclean +0 -0
  138. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/__init__.py +0 -0
  139. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/base.py +0 -0
  140. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/build.mts +0 -0
  141. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/client.http.mts +0 -0
  142. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/client.mts +0 -0
  143. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/errors.py +0 -0
  144. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/global.d.ts +0 -0
  145. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/package.json +0 -0
  146. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/remote.py +0 -0
  147. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/schema.py +0 -0
  148. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/graph.mts +0 -0
  149. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/load.hooks.mjs +0 -0
  150. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/preload.mjs +0 -0
  151. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
  152. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/utils/files.mts +0 -0
  153. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/utils/importMap.mts +0 -0
  154. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  155. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/src/utils/serde.mts +0 -0
  156. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/sse.py +0 -0
  157. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/traceblock.mts +0 -0
  158. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/tsconfig.json +0 -0
  159. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/ui.py +0 -0
  160. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/js/yarn.lock +0 -0
  161. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/lc_security/__init__.py +0 -0
  162. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/lc_security/exceptions.py +0 -0
  163. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/lc_security/policy.py +0 -0
  164. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/lc_security/transport.py +0 -0
  165. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/logging.py +0 -0
  166. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/metadata.py +0 -0
  167. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/metrics_collector.py +0 -0
  168. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/metrics_otlp.py +0 -0
  169. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/middleware/__init__.py +0 -0
  170. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/middleware/ensure_store.py +0 -0
  171. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/middleware/http_logger.py +0 -0
  172. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/middleware/private_network.py +0 -0
  173. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/middleware/request_id.py +0 -0
  174. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/models/__init__.py +0 -0
  175. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/models/run.py +0 -0
  176. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/otel_context.py +0 -0
  177. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/patch.py +0 -0
  178. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/release_tags.py +0 -0
  179. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/route.py +0 -0
  180. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/schema.py +0 -0
  181. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/self_hosted_logs.py +0 -0
  182. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/self_hosted_metrics.py +0 -0
  183. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/serde.py +0 -0
  184. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/server.py +0 -0
  185. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/sse.py +0 -0
  186. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/state.py +0 -0
  187. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/store.py +0 -0
  188. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/stream.py +0 -0
  189. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/stream_v2.py +0 -0
  190. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/timing/__init__.py +0 -0
  191. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/timing/profiler.py +0 -0
  192. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/timing/timer.py +0 -0
  193. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/traceblock.py +0 -0
  194. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/tracing_session.py +0 -0
  195. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/tunneling/cloudflare.py +0 -0
  196. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/__init__.py +0 -0
  197. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/cache.py +0 -0
  198. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/config.py +0 -0
  199. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/errors.py +0 -0
  200. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/extract.py +0 -0
  201. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/future.py +0 -0
  202. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/headers.py +0 -0
  203. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/network.py +0 -0
  204. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/retriable_client.py +0 -0
  205. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/stream_codec.py +0 -0
  206. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/utils/uuids.py +0 -0
  207. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/validation.py +0 -0
  208. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/webhook.py +0 -0
  209. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_api/worker.py +0 -0
  210. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/__init__.py +0 -0
  211. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/checkpointer.py +0 -0
  212. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/__init__.py +0 -0
  213. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/_compat.py +0 -0
  214. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
  215. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/config.py +0 -0
  216. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/durability.py +0 -0
  217. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/store.py +0 -0
  218. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/struct.py +0 -0
  219. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/conversion/value.py +0 -0
  220. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/__init__.py +0 -0
  221. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
  222. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
  223. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
  224. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
  225. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/core_api_pb2.py +0 -0
  226. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/core_api_pb2.pyi +0 -0
  227. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
  228. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
  229. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
  230. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
  231. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
  232. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
  233. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
  234. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
  235. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
  236. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
  237. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
  238. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
  239. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
  240. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
  241. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
  242. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
  243. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
  244. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
  245. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
  246. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
  247. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
  248. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
  249. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
  250. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
  251. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
  252. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
  253. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
  254. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
  255. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
  256. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
  257. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
  258. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
  259. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
  260. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
  261. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
  262. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
  263. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
  264. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
  265. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
  266. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
  267. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
  268. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
  269. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
  270. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
  271. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
  272. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
  273. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
  274. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
  275. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
  276. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
  277. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/store_pb2.py +0 -0
  278. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
  279. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
  280. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
  281. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/serde.py +0 -0
  282. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_grpc_common/store.py +0 -0
  283. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_license/__init__.py +0 -0
  284. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_license/validation.py +0 -0
  285. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/__init__.py +0 -0
  286. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/checkpoint.py +0 -0
  287. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/database.py +0 -0
  288. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/lifespan.py +0 -0
  289. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/metrics.py +0 -0
  290. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/ops.py +0 -0
  291. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/queue.py +0 -0
  292. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/retry.py +0 -0
  293. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/routes.py +0 -0
  294. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/langgraph_runtime/store.py +0 -0
  295. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/logging.json +0 -0
  296. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/openapi.json +0 -0
  297. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/scripts/build_wheel.py +0 -0
  298. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/scripts/create_license.py +0 -0
  299. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/scripts/run_a2a_tck.py +0 -0
  300. {langgraph_api-0.14.0.dev10 → langgraph_api-0.15.0.dev1}/uv.lock +0 -0
@@ -1,7 +1,7 @@
1
1
  .PHONY: build release lint format test test_watch start start-inmem start-inmem-license-oss start build-go-server start-go-server stop-go-server check-version check-base-imports test-a2a-tck test-a2a-tck-mandatory start-test-a2a-tck start-test-a2a-tck-mandatory start-test-a2a-tck-watch test-mcp-conformance start-test-mcp-conformance list-mcp-scenarios test-auth-read-only-assistant
2
2
 
3
3
  # Environment variables
4
- LANGSERVE_GRAPHS_ALL = '{"agent": {"path": "./tests/graphs/agent.py:graph", "description": "agent"}, "assistant_id_runtime": "./tests/graphs/assistant_id_runtime.py:graph", "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", "agent_parallel_interrupt": "./tests/graphs/agent_parallel_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", "unserializable_subgraph": "./tests/graphs/unserializable_subgraph.py:graph", "agent_interrupt_text": "./tests/graphs/agent_interrupt_text.py:graph", "agent_echo_stream": "./tests/graphs/agent_echo_stream.py:graph", "agent_tool_stream": "./tests/graphs/agent_tool_stream.py:graph", "runtime_graph": "./tests/graphs/runtime_graph.py:graph", "tool_call_chunk_stream": "./tests/graphs/tool_call_chunk_stream.py:graph", "ui_tool_call_stream": "./tests/graphs/ui_tool_call_stream.py:graph", "agent_metrics_stream": "./tests/graphs/agent_metrics_stream.py:graph", "agent_multimodal_stream": "./tests/graphs/agent_multimodal_stream.py:graph", "agent_bedtime_story": "./tests/graphs/agent_bedtime_story.py:graph", "delta_channel": "./tests/graphs/delta_channel.py:graph", "delta_channel_freq": "./tests/graphs/delta_channel_freq.py:graph", "delta_channel_files": "./tests/graphs/delta_channel_files.py:graph", "delta_channel_files_freq": "./tests/graphs/delta_channel_files_freq.py:graph", "delta_channel_legacy": "./tests/graphs/delta_channel_migration.py:graph_legacy", "delta_channel_delta": "./tests/graphs/delta_channel_migration.py:graph_delta", "delta_channel_delta_filter": "./tests/graphs/delta_channel_migration.py:graph_delta_filter", "delta_channel_messages_freq": "./tests/graphs/delta_channel_messages.py:graph_freq", "delta_channel_messages": "./tests/graphs/delta_channel_messages.py:graph", "delta_channel_messages_legacy": "./tests/graphs/delta_channel_messages.py:graph_legacy", "delta_channel_messages_remove": "./tests/graphs/delta_channel_messages.py:graph_remove", "delta_channel_messages_update": "./tests/graphs/delta_channel_messages.py:graph_update", "delta_channel_messages_delta": "./tests/graphs/delta_channel_messages.py:graph_delta", "store_e2e_async": "./tests/graphs/store_e2e.py:graph_async", "store_e2e_sync": "./tests/graphs/store_e2e.py:graph_sync"}'
4
+ LANGSERVE_GRAPHS_ALL = '{"agent": {"path": "./tests/graphs/agent.py:graph", "description": "agent"}, "assistant_id_runtime": "./tests/graphs/assistant_id_runtime.py:graph", "custom_lifespan": "./tests/graphs/my_router.py:graph", "single_node": "./tests/graphs/single_node.py:graph", "benchmark": "./tests/graphs/benchmark.py:graph", "benchmark_delta": "./tests/graphs/benchmark.py:graph_delta", "benchmark_delta_freq": "./tests/graphs/benchmark.py:graph_delta_freq", "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", "agent_parallel_interrupt": "./tests/graphs/agent_parallel_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", "unserializable_subgraph": "./tests/graphs/unserializable_subgraph.py:graph", "agent_interrupt_text": "./tests/graphs/agent_interrupt_text.py:graph", "agent_echo_stream": "./tests/graphs/agent_echo_stream.py:graph", "agent_tool_stream": "./tests/graphs/agent_tool_stream.py:graph", "runtime_graph": "./tests/graphs/runtime_graph.py:graph", "tool_call_chunk_stream": "./tests/graphs/tool_call_chunk_stream.py:graph", "ui_tool_call_stream": "./tests/graphs/ui_tool_call_stream.py:graph", "agent_metrics_stream": "./tests/graphs/agent_metrics_stream.py:graph", "agent_multimodal_stream": "./tests/graphs/agent_multimodal_stream.py:graph", "agent_bedtime_story": "./tests/graphs/agent_bedtime_story.py:graph", "delta_channel": "./tests/graphs/delta_channel.py:graph", "delta_channel_freq": "./tests/graphs/delta_channel_freq.py:graph", "delta_channel_files": "./tests/graphs/delta_channel_files.py:graph", "delta_channel_files_freq": "./tests/graphs/delta_channel_files_freq.py:graph", "delta_channel_legacy": "./tests/graphs/delta_channel_migration.py:graph_legacy", "delta_channel_delta": "./tests/graphs/delta_channel_migration.py:graph_delta", "delta_channel_delta_filter": "./tests/graphs/delta_channel_migration.py:graph_delta_filter", "delta_channel_messages_freq": "./tests/graphs/delta_channel_messages.py:graph_freq", "delta_channel_messages": "./tests/graphs/delta_channel_messages.py:graph", "delta_channel_messages_legacy": "./tests/graphs/delta_channel_messages.py:graph_legacy", "delta_channel_messages_remove": "./tests/graphs/delta_channel_messages.py:graph_remove", "delta_channel_messages_update": "./tests/graphs/delta_channel_messages.py:graph_update", "delta_channel_messages_delta": "./tests/graphs/delta_channel_messages.py:graph_delta", "store_e2e_async": "./tests/graphs/store_e2e.py:graph_async", "store_e2e_sync": "./tests/graphs/store_e2e.py:graph_sync"}'
5
5
  LANGSERVE_GRAPHS_AUTH = '{"agent": {"path": "./tests/graphs/agent.py:graph", "description": "agent"}, "assistant_id_runtime": "./tests/graphs/assistant_id_runtime.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_parallel_interrupt": "./tests/graphs/agent_parallel_interrupt.py:graph", "functional_fibonacci": "./tests/graphs/functional_fibonacci.py:fibonacci", "state_graph_fibonacci": "./tests/graphs/state_graph_fibonacci.py:fibonacci", "runtime_graph": "./tests/graphs/runtime_graph.py:graph"}'
6
6
 
7
7
  # Go server management
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.14.0.dev10
3
+ Version: 0.15.0.dev1
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
@@ -16,7 +16,7 @@ Requires-Dist: jsonschema-rs<0.45,>=0.20.0
16
16
  Requires-Dist: langchain-core>=0.3.64
17
17
  Requires-Dist: langchain-protocol<0.1,>=0.0.18
18
18
  Requires-Dist: langgraph-checkpoint<5,>=3.0.1
19
- Requires-Dist: langgraph-runtime-inmem<0.35.0.dev0,>=0.34.0.dev0
19
+ Requires-Dist: langgraph-runtime-inmem<0.36.0.dev0,>=0.35.0.dev0
20
20
  Requires-Dist: langgraph-sdk>=0.3.5
21
21
  Requires-Dist: langgraph<2,>=0.4.10
22
22
  Requires-Dist: langsmith[otel]>=0.6.3
@@ -47,6 +47,7 @@ The runner contains the actual logic each virtual user will execute during the b
47
47
  - `threads_search_metadata` - Validates thread metadata search/filter behavior.
48
48
  - `store` - Writes, reads, validates, and deletes a Store item with a configurable payload size.
49
49
  - `meta_workload` (randomly delegates to one of the others)
50
+ - `delta_turns` - Keeps one thread per VU and adds a turn to it every iteration, so latency can be read against thread depth. Built for the delta-channel cells; see below.
50
51
 
51
52
  ## Profiles (`BENCHMARK_PROFILE`)
52
53
 
@@ -58,6 +59,7 @@ Profiles are quick ways to configure the benchmark graph for any run depending o
58
59
  - `stateless-parallel-medium` - Stateless high-fanout profile with medium checkpoint payloads.
59
60
  - `parallel-small` - Stateful high-fanout profile with small checkpoint payloads.
60
61
  - `parallel-medium` - Stateful high-fanout profile with medium checkpoint payloads.
62
+ - `delta-turns` - Cheap turns for the delta-channel cells, so a VU reaches the depth where a `snapshot_frequency` of 1000 fires.
61
63
 
62
64
  Each profile defines:
63
65
 
@@ -113,6 +115,53 @@ make benchmark-charts
113
115
  make benchmark-clean
114
116
  ```
115
117
 
118
+ ## Delta-channel cells
119
+
120
+ A `DeltaChannel` stores changes rather than the value, and rebuilds the value on read
121
+ by replaying them. That moves cost from write to read, and the read cost grows with
122
+ thread depth. `delta_turns` measures it: one thread per VU, one turn per iteration,
123
+ `turn_duration` tagged by depth bucket.
124
+
125
+ Run the cells one at a time and compare `turn_duration` by depth. Both sides get slower
126
+ with depth for different reasons, the control by re-writing a growing value and delta by
127
+ replaying more writes, so the deliverable is which curve is worse and where they cross.
128
+
129
+ | Cell | Env |
130
+ |---|---|
131
+ | control | `GRAPH_ID=benchmark EXPECT_DELTA=false` |
132
+ | delta, snapshot every 1000 | `GRAPH_ID=benchmark_delta` |
133
+ | delta, snapshot every 50 | `GRAPH_ID=benchmark_delta_freq` |
134
+ | migration | `GRAPH_ID=benchmark_delta MIGRATE_FROM_GRAPH_ID=benchmark MIGRATE_AFTER=200` |
135
+
136
+ ```bash
137
+ BASE_URL=... BENCHMARK_TYPE=delta_turns BENCHMARK_PROFILE=delta-turns \
138
+ GRAPH_ID=benchmark_delta LOAD_SIZE=25 LEVELS=1 PLATEAU_DURATION=300 \
139
+ P95_RUN_DURATION=... AVERAGE_RUN_DURATION=... k6 run --system-tags='[]' ramp.js
140
+ ```
141
+
142
+ Knobs beyond the common ones:
143
+
144
+ - `GRAPH_ID` - graph under test (any runner; defaults to `benchmark`).
145
+ - `EXPECT_DELTA` - whether `GRAPH_ID` is delta-backed. Default `true`.
146
+ - `MIGRATE_FROM_GRAPH_ID` / `MIGRATE_AFTER` - run the first N turns on another graph, then
147
+ switch on the same thread.
148
+ - `VERIFY_EVERY` - cold re-read cadence in turns. Default 50, `0` disables.
149
+ - `DEPTH_BUCKET` - width of a depth bucket. Default 100.
150
+
151
+ Two things to know before reading any result:
152
+
153
+ - **Run at low `LOAD_SIZE`.** Depth and load fight each other: saturate the deployment and
154
+ turn time measures queueing, not reconstruction. Verify the control curve is flat before
155
+ trusting the delta one.
156
+ - **`successful_runs` will fail its threshold.** The count is derived from a duration table
157
+ that assumes the existing workload. Pass `P95_RUN_DURATION` and `AVERAGE_RUN_DURATION`,
158
+ and treat these cells as report-only until the numbers settle.
159
+
160
+ The runner fails a turn rather than reporting a false pass when delta is not actually on:
161
+ the `DeltaChannel` import is version-guarded, and its stub degrades to a plain channel.
162
+ Storage savings, the reason the feature exists, are not measured here; that needs a query
163
+ against the deployment database, which CI cannot reach.
164
+
116
165
  ## Outputs
117
166
 
118
167
  - Ramp:
@@ -68,6 +68,26 @@ export const BENCHMARK_PROFILES: Record<string, BenchmarkProfile> = {
68
68
  burst_size: 0,
69
69
  },
70
70
  },
71
+ // Delta-channel cells: cheap turns, so a VU reaches the depth where a
72
+ // snapshot_frequency of 1000 finally fires. Run these at a low LOAD_SIZE;
73
+ // saturation turns the measurement into queue time.
74
+ 'delta-turns': {
75
+ resumable: false,
76
+ runMode: 'stateful',
77
+ context: {
78
+ delay: 0,
79
+ delay_jitter_ratio: 0,
80
+ expand: 1,
81
+ steps: 1,
82
+ checkpoint_size: 256,
83
+ llm_enabled: false,
84
+ stream_size: 0,
85
+ chunk_size: 1,
86
+ burst_mode: false,
87
+ burst_probability: 0,
88
+ burst_size: 0,
89
+ },
90
+ },
71
91
  'streaming-long': {
72
92
  resumable: true,
73
93
  runMode: 'stateful',
@@ -8,6 +8,7 @@ import { ThreadRunsMetadataSearch } from './thread_runs_metadata_search.js';
8
8
  import { ThreadsSearchMetadata } from './threads_search_metadata.js';
9
9
  import { Store } from './store.js';
10
10
  import { MetaWorkload } from './meta_workload.js';
11
+ import { DeltaTurns } from './delta_turns.js';
11
12
  import type { BenchmarkRunner } from './benchmark-runner.js';
12
13
 
13
14
  export class Benchmarks {
@@ -33,6 +34,8 @@ export class Benchmarks {
33
34
  return Store;
34
35
  case MetaWorkload.toString():
35
36
  return MetaWorkload;
37
+ case DeltaTurns.toString():
38
+ return DeltaTurns;
36
39
  default:
37
40
  throw new Error(`Unknown benchmark type: ${type}`);
38
41
  }
@@ -0,0 +1,169 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {
4
+ planTurn,
5
+ deltaGuardFailure,
6
+ stateDrift,
7
+ unusableCheckpointSize,
8
+ } from './dist/delta-turns-lib.js';
9
+ import { getBenchmarkProfile } from './dist/benchmark_profiles.js';
10
+
11
+ const BASE = {
12
+ graphId: 'benchmark_delta',
13
+ migrateFromGraphId: '',
14
+ migrateAfter: 0,
15
+ expectDelta: true,
16
+ verifyEvery: 50,
17
+ bucketSize: 100,
18
+ };
19
+
20
+ const MIGRATING = {
21
+ ...BASE,
22
+ migrateFromGraphId: 'benchmark',
23
+ migrateAfter: 200,
24
+ };
25
+
26
+ test('steps equals the turn number, because steps is cumulative on a reused thread', () => {
27
+ assert.equal(planTurn(1, BASE).steps, 1);
28
+ assert.equal(planTurn(937, BASE).steps, 937);
29
+ });
30
+
31
+ test('without migration every turn uses the same graph', () => {
32
+ assert.equal(planTurn(1, BASE).graphId, 'benchmark_delta');
33
+ assert.equal(planTurn(500, BASE).graphId, 'benchmark_delta');
34
+ assert.equal(planTurn(500, BASE).expectDelta, true);
35
+ });
36
+
37
+ test('migration switches graph and delta expectation at the boundary', () => {
38
+ assert.equal(planTurn(200, MIGRATING).graphId, 'benchmark');
39
+ assert.equal(planTurn(200, MIGRATING).expectDelta, false);
40
+ assert.equal(planTurn(201, MIGRATING).graphId, 'benchmark_delta');
41
+ assert.equal(planTurn(201, MIGRATING).expectDelta, true);
42
+ });
43
+
44
+ test('migrateAfter is ignored without a graph to migrate from', () => {
45
+ const plan = planTurn(1, { ...BASE, migrateAfter: 200 });
46
+ assert.equal(plan.graphId, 'benchmark_delta');
47
+ assert.equal(plan.expectDelta, true);
48
+ });
49
+
50
+ test('the guard runs on turn 2, never on turn 1', () => {
51
+ assert.equal(planTurn(1, BASE).guard, false);
52
+ assert.equal(planTurn(2, BASE).guard, true);
53
+ assert.equal(planTurn(3, BASE).guard, false);
54
+ });
55
+
56
+ test('migration guards again two turns after the switch', () => {
57
+ assert.equal(planTurn(201, MIGRATING).guard, false);
58
+ assert.equal(planTurn(202, MIGRATING).guard, true);
59
+ });
60
+
61
+ test('the guard never lands on a snapshot boundary, where absent counters are correct', () => {
62
+ const guarded = [];
63
+ for (let turn = 1; turn <= 1000; turn += 1) {
64
+ if (planTurn(turn, MIGRATING).guard) guarded.push(turn);
65
+ }
66
+ assert.deepEqual(guarded, [2, 202]);
67
+ for (const turn of guarded) {
68
+ assert.notEqual(turn % 50, 0);
69
+ assert.notEqual(turn % 1000, 0);
70
+ }
71
+ });
72
+
73
+ test('cold re-read runs on the configured cadence and can be disabled', () => {
74
+ assert.equal(planTurn(50, BASE).verify, true);
75
+ assert.equal(planTurn(51, BASE).verify, false);
76
+ assert.equal(planTurn(50, { ...BASE, verifyEvery: 0 }).verify, false);
77
+ });
78
+
79
+ test('depth buckets group turns and stay stable at the edges', () => {
80
+ assert.equal(planTurn(1, BASE).depthBucket, '1-100');
81
+ assert.equal(planTurn(100, BASE).depthBucket, '1-100');
82
+ assert.equal(planTurn(101, BASE).depthBucket, '101-200');
83
+ assert.equal(planTurn(7, { ...BASE, bucketSize: 0 }).depthBucket, '7');
84
+ });
85
+
86
+ test('a delta graph without counters is a silent fallback to a plain channel', () => {
87
+ assert.equal(deltaGuardFailure({ counters_since_delta_snapshot: { c: [3, 3] } }, true), null);
88
+ assert.equal(deltaGuardFailure({ step: 4 }, true), 'delta_off_on_delta_graph');
89
+ assert.equal(deltaGuardFailure(null, true), 'delta_off_on_delta_graph');
90
+ });
91
+
92
+ test('empty counters read as absent, matching Pregel filtering out zero entries', () => {
93
+ assert.equal(deltaGuardFailure({ counters_since_delta_snapshot: {} }, true), 'delta_off_on_delta_graph');
94
+ assert.equal(deltaGuardFailure({ counters_since_delta_snapshot: {} }, false), null);
95
+ });
96
+
97
+ test('counters on the control graph mean the wrong graph is under test', () => {
98
+ assert.equal(deltaGuardFailure({ counters_since_delta_snapshot: { c: [1, 1] } }, false), 'delta_on_on_plain_graph');
99
+ assert.equal(deltaGuardFailure({ step: 4 }, false), null);
100
+ });
101
+
102
+ test('matching live and stored state is no drift', () => {
103
+ const values = { counter: 12, cumulative_checkpoint: 'abcd' };
104
+ assert.equal(stateDrift(values, { ...values }, 'cumulative_checkpoint'), null);
105
+ });
106
+
107
+ test('a lost write shows up as a shorter stored channel', () => {
108
+ const live = { counter: 12, cumulative_checkpoint: 'abcd' };
109
+ const cold = { counter: 12, cumulative_checkpoint: 'ab' };
110
+ assert.equal(stateDrift(live, cold, 'cumulative_checkpoint'), 'channel_drift:abcd!=ab');
111
+ });
112
+
113
+ test('same-length channel corruption is still drift', () => {
114
+ const live = { counter: 12, cumulative_checkpoint: 'abcd' };
115
+ const cold = { counter: 12, cumulative_checkpoint: 'abce' };
116
+ assert.equal(stateDrift(live, cold, 'cumulative_checkpoint'), 'channel_drift:abcd!=abce');
117
+ });
118
+
119
+ test('a counter that does not survive the read is drift', () => {
120
+ const live = { counter: 12, cumulative_checkpoint: 'ab' };
121
+ const cold = { counter: 11, cumulative_checkpoint: 'ab' };
122
+ assert.equal(stateDrift(live, cold, 'cumulative_checkpoint'), 'counter_drift:12!=11');
123
+ });
124
+
125
+ test('missing values are reported rather than passing silently', () => {
126
+ assert.equal(stateDrift(null, {}, 'cumulative_checkpoint'), 'run_values_missing');
127
+ assert.equal(stateDrift({}, null, 'cumulative_checkpoint'), 'cold_values_missing');
128
+ });
129
+
130
+ test('a non-string channel encoding is still comparable', () => {
131
+ const live = { counter: 1, cumulative_checkpoint: { data: [1, 2, 3] } };
132
+ const cold = { counter: 1, cumulative_checkpoint: { data: [1, 2] } };
133
+ assert.equal(
134
+ stateDrift(live, cold, 'cumulative_checkpoint'),
135
+ 'channel_drift:{"data":[1,2,3]}!={"data":[1,2]}'
136
+ );
137
+ });
138
+
139
+ test('the first turn of a migration runs on the graph being migrated from', () => {
140
+ assert.equal(planTurn(1, MIGRATING).graphId, 'benchmark');
141
+ assert.equal(planTurn(1, MIGRATING).expectDelta, false);
142
+ });
143
+
144
+ test('adjacent guard turns do not collapse when the switch is early', () => {
145
+ const early = { ...MIGRATING, migrateAfter: 1 };
146
+ assert.equal(planTurn(2, early).guard, true);
147
+ assert.equal(planTurn(3, early).guard, true);
148
+ assert.equal(planTurn(2, early).expectDelta, true);
149
+ });
150
+
151
+ test('a channel absent from both sides compares equal, which is why checkpoint_size must be > 0', () => {
152
+ const drift = stateDrift({ counter: 1 }, { counter: 1 }, 'cumulative_checkpoint');
153
+ assert.equal(drift, null);
154
+ });
155
+
156
+ test('a checkpoint size of zero makes the run meaningless and is rejected', () => {
157
+ assert.equal(unusableCheckpointSize(0), true);
158
+ assert.equal(unusableCheckpointSize(undefined), true);
159
+ assert.equal(unusableCheckpointSize(-1), true);
160
+ assert.equal(unusableCheckpointSize(256), false);
161
+ });
162
+
163
+ test('the delta-turns profile is wired and writes a growing channel', () => {
164
+ const { profile } = getBenchmarkProfile('delta-turns');
165
+ assert.equal(profile.runMode, 'stateful');
166
+ assert.equal(unusableCheckpointSize(profile.context.checkpoint_size), false);
167
+ assert.equal(profile.context.delay, 0);
168
+ assert.equal(profile.context.steps, 1);
169
+ });
@@ -0,0 +1,102 @@
1
+ // No k6 imports here, so `node --test` can import the compiled output.
2
+
3
+ export interface DeltaTurnsOptions {
4
+ graphId: string;
5
+ /** Drives the first `migrateAfter` turns. Empty disables migration. */
6
+ migrateFromGraphId: string;
7
+ migrateAfter: number;
8
+ /** Whether `graphId` is delta-backed. */
9
+ expectDelta: boolean;
10
+ /** Cold re-read cadence, in turns. 0 disables. */
11
+ verifyEvery: number;
12
+ bucketSize: number;
13
+ }
14
+
15
+ export interface TurnPlan {
16
+ graphId: string;
17
+ /** Cumulative on a reused thread, so turn N asks for N. */
18
+ steps: number;
19
+ expectDelta: boolean;
20
+ guard: boolean;
21
+ verify: boolean;
22
+ depthBucket: string;
23
+ }
24
+
25
+ const DELTA_COUNTERS_KEY = 'counters_since_delta_snapshot';
26
+
27
+ /** At size 0 the thread deepens but the channel stays empty, measuring nothing. */
28
+ export function unusableCheckpointSize(checkpointSize: number | undefined): boolean {
29
+ return !(typeof checkpointSize === 'number' && checkpointSize > 0);
30
+ }
31
+
32
+ export function planTurn(turn: number, options: DeltaTurnsOptions): TurnPlan {
33
+ const migrating = options.migrateFromGraphId !== '' && options.migrateAfter > 0;
34
+ const beforeSwitch = migrating && turn <= options.migrateAfter;
35
+ return {
36
+ graphId: beforeSwitch ? options.migrateFromGraphId : options.graphId,
37
+ steps: turn,
38
+ expectDelta: beforeSwitch ? false : options.expectDelta,
39
+ guard: isGuardTurn(turn, options, migrating),
40
+ verify: options.verifyEvery > 0 && turn % options.verifyEvery === 0,
41
+ depthBucket: depthBucket(turn, options.bucketSize),
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Turn 1 has no counters yet, and on a snapshot point Pregel drops the counters
47
+ * entry, so its absence there is correct rather than a fallback.
48
+ */
49
+ function isGuardTurn(turn: number, options: DeltaTurnsOptions, migrating: boolean): boolean {
50
+ if (turn === 2) return true;
51
+ return migrating && turn === options.migrateAfter + 2;
52
+ }
53
+
54
+ function depthBucket(turn: number, bucketSize: number): string {
55
+ if (bucketSize <= 0) return String(turn);
56
+ const floor = Math.floor((turn - 1) / bucketSize) * bucketSize;
57
+ return `${floor + 1}-${floor + bucketSize}`;
58
+ }
59
+
60
+ /**
61
+ * The delta import is version-guarded and its stub degrades to a plain channel,
62
+ * so without this a delta cell can silently measure the control graph.
63
+ */
64
+ export function deltaGuardFailure(metadata: unknown, expectDelta: boolean): string | null {
65
+ const counters =
66
+ metadata != null && typeof metadata === 'object'
67
+ ? (metadata as Record<string, unknown>)[DELTA_COUNTERS_KEY]
68
+ : undefined;
69
+ const present = counters != null && Object.keys(counters as object).length > 0;
70
+ if (expectDelta && !present) return 'delta_off_on_delta_graph';
71
+ if (!expectDelta && present) return 'delta_on_on_plain_graph';
72
+ return null;
73
+ }
74
+
75
+ /**
76
+ * Delta bugs return the right answer live and lose it on the next read, so the
77
+ * run's own output is the reference and the stored value is under test.
78
+ */
79
+ export function stateDrift(
80
+ runValues: unknown,
81
+ coldValues: unknown,
82
+ channel: string
83
+ ): string | null {
84
+ if (runValues == null || typeof runValues !== 'object') return 'run_values_missing';
85
+ if (coldValues == null || typeof coldValues !== 'object') return 'cold_values_missing';
86
+ const live = runValues as Record<string, unknown>;
87
+ const cold = coldValues as Record<string, unknown>;
88
+
89
+ if (live.counter !== cold.counter) {
90
+ return `counter_drift:${String(live.counter)}!=${String(cold.counter)}`;
91
+ }
92
+ const liveEnc = encodeChannel(live[channel]);
93
+ const coldEnc = encodeChannel(cold[channel]);
94
+ if (liveEnc !== coldEnc) return `channel_drift:${liveEnc}!=${coldEnc}`;
95
+ return null;
96
+ }
97
+
98
+ /** Bytes arrive as a string, other channels as objects. */
99
+ function encodeChannel(value: unknown): string {
100
+ if (value == null) return '';
101
+ return typeof value === 'string' ? value : JSON.stringify(value);
102
+ }
@@ -0,0 +1,169 @@
1
+ import { BenchmarkRunner } from './benchmark-runner.js';
2
+ import type { ErrorMetrics } from './benchmark-runner.js';
3
+ import { check } from 'k6';
4
+ import http from 'k6/http';
5
+ import { Trend } from 'k6/metrics';
6
+ import type { BenchmarkResult, BenchmarkGraphOptions, HttpResponse } from './types.js';
7
+ import { addResponse, okResult, failResult } from './types.js';
8
+ import { classifyError, recordError } from './classify-error.js';
9
+ import { logFailure } from './log-failure.js';
10
+ import {
11
+ planTurn,
12
+ deltaGuardFailure,
13
+ stateDrift,
14
+ unusableCheckpointSize,
15
+ } from './delta-turns-lib.js';
16
+ import type { DeltaTurnsOptions, TurnPlan } from './delta-turns-lib.js';
17
+
18
+ const CHANNEL = 'cumulative_checkpoint';
19
+
20
+ /** Tagged by depth: VUs ramp in, so clock time is not thread length. */
21
+ const turnDuration = new Trend('turn_duration', true);
22
+
23
+ const TURN_CONFIG: Omit<DeltaTurnsOptions, 'graphId'> = {
24
+ migrateFromGraphId: __ENV.MIGRATE_FROM_GRAPH_ID || '',
25
+ migrateAfter: parseInt(__ENV.MIGRATE_AFTER || '0', 10),
26
+ expectDelta: (__ENV.EXPECT_DELTA || 'true') === 'true',
27
+ verifyEvery: parseInt(__ENV.VERIFY_EVERY || '50', 10),
28
+ bucketSize: parseInt(__ENV.DEPTH_BUCKET || '100', 10),
29
+ };
30
+
31
+ // Each k6 VU runs this module in its own context, so these are per VU.
32
+ let threadId: string | null = null;
33
+ let turn = 0;
34
+
35
+ interface DeltaTurnsData {
36
+ rawResponse: ReturnType<typeof http.post>;
37
+ plan: TurnPlan;
38
+ guardFailure: string | null;
39
+ drift: string | null;
40
+ }
41
+
42
+ export class DeltaTurns extends BenchmarkRunner {
43
+ static run(
44
+ baseUrl: string,
45
+ requestParams: Record<string, unknown>,
46
+ benchmarkGraphOptions: BenchmarkGraphOptions
47
+ ): BenchmarkResult<DeltaTurnsData> {
48
+ const responses: Record<string, HttpResponse> = {};
49
+
50
+ if (unusableCheckpointSize(benchmarkGraphOptions.context.checkpoint_size)) {
51
+ return failResult('checkpoint_size', responses) as BenchmarkResult<DeltaTurnsData>;
52
+ }
53
+
54
+ if (threadId === null) {
55
+ const thread = http.post(`${baseUrl}/threads`, '{}', requestParams);
56
+ addResponse(responses, 'create_thread', thread);
57
+ if (thread.status !== 200) {
58
+ return failResult('create_thread', responses) as BenchmarkResult<DeltaTurnsData>;
59
+ }
60
+ threadId = (thread.json() as { thread_id: string }).thread_id;
61
+ turn = 0;
62
+ }
63
+
64
+ turn += 1;
65
+ const plan = planTurn(turn, { ...TURN_CONFIG, graphId: benchmarkGraphOptions.graph_id });
66
+ const payload = JSON.stringify({
67
+ assistant_id: plan.graphId,
68
+ input: {},
69
+ context: { ...benchmarkGraphOptions.context, steps: plan.steps },
70
+ config: { recursion_limit: plan.steps + 2 },
71
+ });
72
+
73
+ const startedAt = Date.now();
74
+ const response = http.post(
75
+ `${baseUrl}/threads/${threadId}/runs/wait`,
76
+ payload,
77
+ requestParams
78
+ );
79
+ turnDuration.add(Date.now() - startedAt, { depth: plan.depthBucket });
80
+ addResponse(responses, 'wait', response);
81
+
82
+ let guardFailure: string | null = null;
83
+ let drift: string | null = null;
84
+ // A failed body is not state, and comparing against it would report drift
85
+ // on top of the failure that caused it.
86
+ if (response.status === 200 && (plan.guard || plan.verify)) {
87
+ const state = http.get(`${baseUrl}/threads/${threadId}/state`, requestParams);
88
+ addResponse(responses, 'state', state);
89
+ const body = state.status === 200 ? safeJson(state.body) : null;
90
+ if (body === null) {
91
+ guardFailure = plan.guard ? 'state_unreadable' : guardFailure;
92
+ drift = plan.verify ? 'state_unreadable' : drift;
93
+ } else {
94
+ if (plan.guard) {
95
+ guardFailure = deltaGuardFailure(body.metadata, plan.expectDelta);
96
+ }
97
+ if (plan.verify) {
98
+ // `/runs/wait` returns the state values themselves; `/state` nests them.
99
+ drift = stateDrift(safeJson(response.body), body.values, CHANNEL);
100
+ }
101
+ }
102
+ }
103
+
104
+ return okResult(responses, { rawResponse: response, plan, guardFailure, drift });
105
+ }
106
+
107
+ static validate(
108
+ result: BenchmarkResult<DeltaTurnsData>,
109
+ errorMetrics: ErrorMetrics
110
+ ): boolean {
111
+ const res = result.data?.rawResponse;
112
+ const plan = result.data?.plan;
113
+ const json = res?.status === 200 ? safeJson(res.body) : null;
114
+ let success = false;
115
+
116
+ try {
117
+ success = check(result, {
118
+ 'Run completed successfully': () => (res?.status ?? 0) === 200,
119
+ 'Response contains valid JSON': () => json != null,
120
+ 'Response does not contain __error__': () => json?.__error__ === undefined,
121
+ 'Run advanced the thread by one turn': () =>
122
+ json == null || plan == null || json.counter === plan.steps,
123
+ 'Delta storage is as expected': () => result.data?.guardFailure == null,
124
+ 'Cold re-read matches the run': () => result.data?.drift == null,
125
+ });
126
+ } catch (error) {
127
+ console.log(`Unknown error checking result: ${(error as Error).message}`);
128
+ }
129
+
130
+ if (!success) {
131
+ const detail = [
132
+ plan ? `turn=${plan.steps} graph=${plan.graphId}` : '',
133
+ res ? `status=${res.status}` : '',
134
+ result.data?.guardFailure ? `guard=${result.data.guardFailure}` : '',
135
+ result.data?.drift ? `drift=${result.data.drift}` : '',
136
+ ]
137
+ .filter(Boolean)
138
+ .join(' ');
139
+ logFailure(DeltaTurns.toString(), result, { extra: detail });
140
+ recordError(
141
+ classifyError({
142
+ response: res ?? result.responses?.create_thread ?? null,
143
+ hasApiError: json?.__error__ !== undefined,
144
+ missingMessage: result.data?.drift != null || result.data?.guardFailure != null,
145
+ }),
146
+ errorMetrics
147
+ );
148
+ // The thread is now at an unknown depth, so later turns would be tagged
149
+ // with a depth they do not have.
150
+ threadId = null;
151
+ }
152
+ return success;
153
+ }
154
+
155
+ static toString(): string {
156
+ return 'delta_turns';
157
+ }
158
+ }
159
+
160
+ /** k6 returns a null body on a connection failure. */
161
+ function safeJson(body: string | null | ArrayBuffer): Record<string, any> | null {
162
+ if (typeof body !== 'string') return null;
163
+ try {
164
+ const parsed = JSON.parse(body);
165
+ return parsed != null && typeof parsed === 'object' ? parsed : null;
166
+ } catch {
167
+ return null;
168
+ }
169
+ }
@@ -123,7 +123,7 @@ export let options = {
123
123
  const runner = Benchmarks.getRunner(BENCHMARK_TYPE);
124
124
 
125
125
  const benchmarkGraphOptions = {
126
- graph_id: "benchmark",
126
+ graph_id: __ENV.GRAPH_ID || "benchmark",
127
127
  input: {},
128
128
  context: EFFECTIVE_CONTEXT,
129
129
  stateful: STATEFUL,
@@ -0,0 +1 @@
1
+ __version__ = "0.15.0.dev1"
@@ -75,7 +75,6 @@ async def health_and_metrics_server():
75
75
  from langgraph_api.api.meta import METRICS_FORMATS, meta_pool_stats # noqa: PLC0415
76
76
 
77
77
  port = int(os.getenv("PORT", "8080"))
78
- # Not in public docs: LANGGRAPH_SERVER_HOST is internal
79
78
  # Empty means every interface: asyncio then opens one socket per address
80
79
  # family, so the server answers on IPv4 and IPv6.
81
80
  host = normalize_host(os.getenv("LANGGRAPH_SERVER_HOST", ""))
@@ -39,7 +39,7 @@ dependencies = [
39
39
  "cryptography>=50.0.0",
40
40
  "langgraph-sdk>=0.3.5",
41
41
  "cloudpickle>=3.0.0",
42
- "langgraph-runtime-inmem>=0.34.0.dev0,<0.35.0.dev0",
42
+ "langgraph-runtime-inmem>=0.35.0.dev0,<0.36.0.dev0",
43
43
  "truststore>=0.1",
44
44
  "protobuf>=6.32.1,<7.0.0",
45
45
  "grpcio>=1.81.0,<1.82.0",
@@ -1 +0,0 @@
1
- __version__ = "0.14.0.dev10"