langgraph-api 0.8.5__tar.gz → 0.8.7__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 (281) hide show
  1. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/PKG-INFO +1 -1
  2. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/continuous/pyproject.toml +2 -2
  3. langgraph_api-0.8.7/langgraph_api/__init__.py +1 -0
  4. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/a2a.py +31 -1
  5. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/meta.py +31 -19
  6. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/cli.py +6 -11
  7. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/http_metrics.py +5 -4
  8. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/client.mts +15 -0
  9. langgraph_api-0.8.7/langgraph_api/js/src/utils/experiment-tracing.mts +51 -0
  10. langgraph_api-0.8.7/langgraph_api/js/yarn.lock +1321 -0
  11. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/metadata.py +1 -0
  12. langgraph_api-0.8.7/langgraph_api/release_tags.py +206 -0
  13. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/pyproject.toml +3 -3
  14. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/uv.lock +30 -30
  15. langgraph_api-0.8.5/langgraph_api/__init__.py +0 -1
  16. langgraph_api-0.8.5/langgraph_api/js/yarn.lock +0 -1894
  17. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/.gitignore +0 -0
  18. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/LICENSE +0 -0
  19. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/Makefile +0 -0
  20. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/README.md +0 -0
  21. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/.gitignore +0 -0
  22. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/Makefile +0 -0
  23. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/README.md +0 -0
  24. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/assistant.ts +0 -0
  25. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
  26. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
  27. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/benchmarks.ts +0 -0
  28. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
  29. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
  30. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/log-failure.ts +0 -0
  31. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/meta_workload.ts +0 -0
  32. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/stream_write.ts +0 -0
  33. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/thread.ts +0 -0
  34. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
  35. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
  36. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/types.ts +0 -0
  37. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/benchmark-runners/wait_write.ts +0 -0
  38. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/capacity_dd_report.py +0 -0
  39. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/capacity_k6.js +0 -0
  40. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/capacity_runner.mjs +0 -0
  41. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/capacity_slack_report.py +0 -0
  42. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/capacity_urls.mjs +0 -0
  43. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/clean-cli.js +0 -0
  44. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/clean.js +0 -0
  45. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/continuous/README.md +0 -0
  46. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/continuous/runner.py +0 -0
  47. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/continuous/uv.lock +0 -0
  48. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/graphs.js +0 -0
  49. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/mixed_workload_k6.js +0 -0
  50. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/mixed_workload_runner.mjs +0 -0
  51. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/package.json +0 -0
  52. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/ramp.js +0 -0
  53. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/reporting/dd_reporting.py +0 -0
  54. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/reporting/slack_slowest_runs.py +0 -0
  55. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/reporting/slack_summary.py +0 -0
  56. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/run_local.sh +0 -0
  57. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/staircase.py +0 -0
  58. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/staircase_step_k6.js +0 -0
  59. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/tsconfig.json +0 -0
  60. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/update-revision.js +0 -0
  61. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/benchmark/weather.js +0 -0
  62. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/constraints.txt +0 -0
  63. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/custom_store.sql +0 -0
  64. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/forbidden.txt +0 -0
  65. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/hatch_build.py +0 -0
  66. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/healthcheck.py +0 -0
  67. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph-cloud-debugging-20260210132856.zip +0 -0
  68. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/_checkpointer/__init__.py +0 -0
  69. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/_checkpointer/_adapter.py +0 -0
  70. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/_checkpointer/protocol.py +0 -0
  71. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/_factory_utils.py +0 -0
  72. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/__init__.py +0 -0
  73. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/assistants.py +0 -0
  74. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/mcp/__init__.py +0 -0
  75. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/mcp/_constants.py +0 -0
  76. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/mcp/_handlers.py +0 -0
  77. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/mcp/_models.py +0 -0
  78. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/mcp/_routes.py +0 -0
  79. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/mcp/_sanitizers.py +0 -0
  80. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/openapi.py +0 -0
  81. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/profile.py +0 -0
  82. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/runs.py +0 -0
  83. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/store.py +0 -0
  84. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/threads.py +0 -0
  85. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/api/ui.py +0 -0
  86. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/asgi_transport.py +0 -0
  87. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/asyncio.py +0 -0
  88. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/__init__.py +0 -0
  89. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/custom.py +0 -0
  90. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/errors.py +0 -0
  91. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/langsmith/__init__.py +0 -0
  92. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/langsmith/backend.py +0 -0
  93. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/langsmith/client.py +0 -0
  94. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/middleware.py +0 -0
  95. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/noop.py +0 -0
  96. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/auth/studio_user.py +0 -0
  97. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/cache.py +0 -0
  98. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/command.py +0 -0
  99. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/config/__init__.py +0 -0
  100. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/config/_parse.py +0 -0
  101. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/config/schemas.py +0 -0
  102. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/cron_scheduler.py +0 -0
  103. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/encryption/__init__.py +0 -0
  104. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/encryption/aes_json.py +0 -0
  105. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/encryption/context.py +0 -0
  106. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/encryption/custom.py +0 -0
  107. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/encryption/middleware.py +0 -0
  108. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/encryption/shared.py +0 -0
  109. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/errors.py +0 -0
  110. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/feature_flags.py +0 -0
  111. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/graph.py +0 -0
  112. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/__init__.py +0 -0
  113. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/client.py +0 -0
  114. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
  115. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/ops/__init__.py +0 -0
  116. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/ops/assistants.py +0 -0
  117. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/ops/cache.py +0 -0
  118. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/ops/crons.py +0 -0
  119. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/ops/runs.py +0 -0
  120. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/ops/threads.py +0 -0
  121. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/server.py +0 -0
  122. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/servicers/__init__.py +0 -0
  123. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
  124. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/grpc/servicers/encryption.py +0 -0
  125. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/http.py +0 -0
  126. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/http_metrics_utils.py +0 -0
  127. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/.gitignore +0 -0
  128. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/.prettierrc +0 -0
  129. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/__init__.py +0 -0
  130. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/base.py +0 -0
  131. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/build.mts +0 -0
  132. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/client.http.mts +0 -0
  133. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/errors.py +0 -0
  134. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/global.d.ts +0 -0
  135. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/package.json +0 -0
  136. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/remote.py +0 -0
  137. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/schema.py +0 -0
  138. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/src/graph.mts +0 -0
  139. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/src/load.hooks.mjs +0 -0
  140. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/src/preload.mjs +0 -0
  141. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/src/utils/files.mts +0 -0
  142. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/src/utils/importMap.mts +0 -0
  143. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  144. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/src/utils/serde.mts +0 -0
  145. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/sse.py +0 -0
  146. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/traceblock.mts +0 -0
  147. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/tsconfig.json +0 -0
  148. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/js/ui.py +0 -0
  149. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/lc_security/__init__.py +0 -0
  150. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/lc_security/exceptions.py +0 -0
  151. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/lc_security/policy.py +0 -0
  152. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/lc_security/transport.py +0 -0
  153. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/logging.py +0 -0
  154. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/metrics_datadog.py +0 -0
  155. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/middleware/__init__.py +0 -0
  156. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/middleware/ensure_store.py +0 -0
  157. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/middleware/http_logger.py +0 -0
  158. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/middleware/private_network.py +0 -0
  159. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/middleware/request_id.py +0 -0
  160. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/models/__init__.py +0 -0
  161. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/models/run.py +0 -0
  162. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/otel_context.py +0 -0
  163. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/patch.py +0 -0
  164. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/queue_entrypoint.py +0 -0
  165. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/route.py +0 -0
  166. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/schema.py +0 -0
  167. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/self_hosted_logs.py +0 -0
  168. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/self_hosted_metrics.py +0 -0
  169. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/serde.py +0 -0
  170. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/server.py +0 -0
  171. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/sse.py +0 -0
  172. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/state.py +0 -0
  173. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/store.py +0 -0
  174. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/stream.py +0 -0
  175. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/timing/__init__.py +0 -0
  176. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/timing/profiler.py +0 -0
  177. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/timing/timer.py +0 -0
  178. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/traceblock.py +0 -0
  179. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/tunneling/cloudflare.py +0 -0
  180. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/__init__.py +0 -0
  181. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/cache.py +0 -0
  182. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/config.py +0 -0
  183. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/errors.py +0 -0
  184. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/extract.py +0 -0
  185. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/future.py +0 -0
  186. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/headers.py +0 -0
  187. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/network.py +0 -0
  188. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/retriable_client.py +0 -0
  189. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/stream_codec.py +0 -0
  190. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/utils/uuids.py +0 -0
  191. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/validation.py +0 -0
  192. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/webhook.py +0 -0
  193. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_api/worker.py +0 -0
  194. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/__init__.py +0 -0
  195. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/checkpointer.py +0 -0
  196. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/conversion/__init__.py +0 -0
  197. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/conversion/_compat.py +0 -0
  198. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
  199. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/conversion/config.py +0 -0
  200. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/conversion/durability.py +0 -0
  201. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/conversion/struct.py +0 -0
  202. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/conversion/value.py +0 -0
  203. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/__init__.py +0 -0
  204. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
  205. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
  206. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
  207. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
  208. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/core_api_pb2.py +0 -0
  209. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/core_api_pb2.pyi +0 -0
  210. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
  211. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
  212. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
  213. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
  214. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
  215. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
  216. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
  217. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
  218. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
  219. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
  220. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
  221. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
  222. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
  223. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
  224. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
  225. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
  226. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
  227. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
  228. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
  229. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
  230. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
  231. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
  232. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
  233. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
  234. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
  235. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
  236. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
  237. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
  238. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
  239. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
  240. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
  241. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
  242. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
  243. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
  244. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2.py +0 -0
  245. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2.pyi +0 -0
  246. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2_grpc.py +0 -0
  247. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2_grpc.pyi +0 -0
  248. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
  249. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
  250. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
  251. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
  252. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
  253. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
  254. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
  255. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
  256. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
  257. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
  258. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
  259. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
  260. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
  261. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
  262. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
  263. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
  264. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_grpc_common/serde.py +0 -0
  265. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_license/__init__.py +0 -0
  266. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_license/validation.py +0 -0
  267. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/__init__.py +0 -0
  268. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/checkpoint.py +0 -0
  269. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/database.py +0 -0
  270. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/lifespan.py +0 -0
  271. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/metrics.py +0 -0
  272. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/ops.py +0 -0
  273. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/queue.py +0 -0
  274. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/retry.py +0 -0
  275. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/routes.py +0 -0
  276. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/langgraph_runtime/store.py +0 -0
  277. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/logging.json +0 -0
  278. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/openapi.json +0 -0
  279. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/scripts/build_wheel.py +0 -0
  280. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/scripts/create_license.py +0 -0
  281. {langgraph_api-0.8.5 → langgraph_api-0.8.7}/scripts/run_a2a_tck.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.8.5
3
+ Version: 0.8.7
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
@@ -4,8 +4,8 @@ version = "0.1.0"
4
4
  description = "Continuous stress test for Agent Server"
5
5
  requires-python = ">=3.13"
6
6
  dependencies = [
7
- "langgraph-sdk>=0.2.10",
8
- "click>=8.3.2",
7
+ "langgraph-sdk>=0.3.13",
8
+ "click>=8.3.3",
9
9
  "structlog>=24.1.0",
10
10
  "datadog-api-client>=2.0.0",
11
11
  "python-dateutil>=2.8.0",
@@ -0,0 +1 @@
1
+ __version__ = "0.8.7"
@@ -552,6 +552,22 @@ def _create_interrupt_artifact(interrupts: list[dict[str, Any]]) -> dict[str, An
552
552
  }
553
553
 
554
554
 
555
+ def _tool_result_data(it: dict[str, Any]) -> dict[str, Any] | None:
556
+ tool_call_id = it.get("tool_call_id")
557
+ if not isinstance(tool_call_id, str) or not tool_call_id:
558
+ return None
559
+
560
+ result: dict[str, Any] = {"toolCallId": tool_call_id}
561
+ content = it.get("content")
562
+ if content not in (None, ""):
563
+ result["content"] = content
564
+ for key in ("name", "status"):
565
+ value = it.get(key)
566
+ if isinstance(value, str) and value:
567
+ result[key] = value
568
+ return result
569
+
570
+
555
571
  def _lc_stream_items_to_a2a_message(
556
572
  items: list[dict[str, Any]],
557
573
  *,
@@ -604,6 +620,9 @@ def _lc_stream_items_to_a2a_message(
604
620
  tc = it.get("tool_calls")
605
621
  if isinstance(tc, list) and tc:
606
622
  extra_data.setdefault("tool_calls", tc)
623
+ tool_result = _tool_result_data(it)
624
+ if tool_result is not None:
625
+ extra_data.setdefault("tool_results", []).append(tool_result)
607
626
 
608
627
  parts: list[dict[str, Any]] = []
609
628
  if text_parts:
@@ -809,10 +828,21 @@ def _convert_messages_to_a2a_format(
809
828
  else "ROLE_AGENT"
810
829
  )
811
830
 
831
+ parts: list[dict[str, Any]] = [{"kind": "text", "text": str(content)}]
832
+ extra_data: dict[str, Any] = {}
833
+ tc = msg.get("tool_calls")
834
+ if isinstance(tc, list) and tc:
835
+ extra_data["tool_calls"] = tc
836
+ tool_result = _tool_result_data(msg)
837
+ if tool_result is not None:
838
+ extra_data["tool_results"] = [tool_result]
839
+ if extra_data:
840
+ parts.append({"kind": "data", "data": extra_data})
841
+
812
842
  a2a_message = {
813
843
  "kind": "message",
814
844
  "role": a2a_role,
815
- "parts": [{"kind": "text", "text": str(content)}],
845
+ "parts": parts,
816
846
  "messageId": id,
817
847
  "taskId": task_id,
818
848
  "contextId": context_id,
@@ -47,9 +47,13 @@ def _merge_pool_stats(local: PoolStats, remote: PoolStats) -> PoolStats:
47
47
 
48
48
 
49
49
  def _pool_stats_to_prometheus_lines(
50
- stats: PoolStats, project_id: str | None, revision_id: str | None
50
+ stats: PoolStats,
51
+ project_id: str | None,
52
+ revision_id: str | None,
53
+ deployment_type: str = "",
51
54
  ) -> list[str]:
52
55
  """Format merged pool stats as Prometheus text lines (same format as langgraph_runtime.database.pool_stats)."""
56
+ labels = f'project_id="{project_id}", revision_id="{revision_id}", deployment_type="{deployment_type}"'
53
57
  lines = []
54
58
  if "postgres" in stats:
55
59
  pg = stats["postgres"]
@@ -57,19 +61,19 @@ def _pool_stats_to_prometheus_lines(
57
61
  [
58
62
  "# HELP lg_api_pg_pool_max The maximum size of the postgres connection pool.",
59
63
  "# TYPE lg_api_pg_pool_max gauge",
60
- f'lg_api_pg_pool_max{{project_id="{project_id}", revision_id="{revision_id}"}} {pg.get("pool_max", 0)}',
64
+ f"lg_api_pg_pool_max{{{labels}}} {pg.get('pool_max', 0)}",
61
65
  "# HELP lg_api_pg_pool_size Number of connections currently managed by the postgres connection pool (in the pool, given to clients, being prepared)",
62
66
  "# TYPE lg_api_pg_pool_size gauge",
63
- f'lg_api_pg_pool_size{{project_id="{project_id}", revision_id="{revision_id}"}} {pg.get("pool_size", 0)}',
67
+ f"lg_api_pg_pool_size{{{labels}}} {pg.get('pool_size', 0)}",
64
68
  "# HELP lg_api_pg_pool_available Number of connections currently idle in the postgres connection pool",
65
69
  "# TYPE lg_api_pg_pool_available gauge",
66
- f'lg_api_pg_pool_available{{project_id="{project_id}", revision_id="{revision_id}"}} {pg.get("pool_available", 0)}',
70
+ f"lg_api_pg_pool_available{{{labels}}} {pg.get('pool_available', 0)}",
67
71
  "# HELP lg_api_pg_pool_requests_queued Number of postgres connection requests queued because a postgres connection wasn't immediately available in the pool",
68
72
  "# TYPE lg_api_pg_pool_requests_queued counter",
69
- f'lg_api_pg_pool_requests_queued{{project_id="{project_id}", revision_id="{revision_id}"}} {pg.get("requests_queued", 0)}',
73
+ f"lg_api_pg_pool_requests_queued{{{labels}}} {pg.get('requests_queued', 0)}",
70
74
  "# HELP lg_api_pg_pool_requests_errors Number of postgres connection requests resulting in an error (timeouts, queue full...)",
71
75
  "# TYPE lg_api_pg_pool_requests_errors counter",
72
- f'lg_api_pg_pool_requests_errors{{project_id="{project_id}", revision_id="{revision_id}"}} {pg.get("requests_errors", 0)}',
76
+ f"lg_api_pg_pool_requests_errors{{{labels}}} {pg.get('requests_errors', 0)}",
73
77
  ]
74
78
  )
75
79
  if "redis" in stats:
@@ -78,13 +82,13 @@ def _pool_stats_to_prometheus_lines(
78
82
  [
79
83
  "# HELP lg_api_redis_pool_available Number of connections currently idle in the redis connection pool",
80
84
  "# TYPE lg_api_redis_pool_available gauge",
81
- f'lg_api_redis_pool_available{{project_id="{project_id}", revision_id="{revision_id}"}} {rd.get("idle_connections", 0)}',
85
+ f"lg_api_redis_pool_available{{{labels}}} {rd.get('idle_connections', 0)}",
82
86
  "# HELP lg_api_redis_pool_size Number of connections currently in use in the redis connection pool",
83
87
  "# TYPE lg_api_redis_pool_size gauge",
84
- f'lg_api_redis_pool_size{{project_id="{project_id}", revision_id="{revision_id}"}} {rd.get("in_use_connections", 0)}',
88
+ f"lg_api_redis_pool_size{{{labels}}} {rd.get('in_use_connections', 0)}",
85
89
  "# HELP lg_api_redis_pool_max The maximum size of the redis connection pool.",
86
90
  "# TYPE lg_api_redis_pool_max gauge",
87
- f'lg_api_redis_pool_max{{project_id="{project_id}", revision_id="{revision_id}"}} {rd.get("max_connections", 0)}',
91
+ f"lg_api_redis_pool_max{{{labels}}} {rd.get('max_connections', 0)}",
88
92
  ]
89
93
  )
90
94
  return lines
@@ -111,7 +115,10 @@ async def meta_pool_stats(metrics_format: str) -> PoolStats | list[str]:
111
115
  merged_pool_stats = _merge_pool_stats(local_pool_stats, grpc_pool_stats)
112
116
  if metrics_format == "prometheus":
113
117
  return _pool_stats_to_prometheus_lines(
114
- merged_pool_stats, metadata.PROJECT_ID, metadata.HOST_REVISION_ID
118
+ merged_pool_stats,
119
+ metadata.PROJECT_ID,
120
+ metadata.HOST_REVISION_ID,
121
+ metadata.DEPLOYMENT_TYPE,
115
122
  )
116
123
  else:
117
124
  return merged_pool_stats
@@ -154,7 +161,10 @@ async def meta_metrics(request: ApiRequest):
154
161
  workers_available = worker_metrics["available"]
155
162
 
156
163
  http_metrics = HTTP_METRICS_COLLECTOR.get_metrics(
157
- metadata.PROJECT_ID, metadata.HOST_REVISION_ID, metrics_format
164
+ metadata.PROJECT_ID,
165
+ metadata.HOST_REVISION_ID,
166
+ metrics_format,
167
+ metadata.DEPLOYMENT_TYPE,
158
168
  )
159
169
 
160
170
  merged_pool_stats = await meta_pool_stats(metrics_format)
@@ -175,23 +185,24 @@ async def meta_metrics(request: ApiRequest):
175
185
  async with connect() as conn:
176
186
  queue_stats = await Runs.stats(conn)
177
187
 
188
+ labels = f'project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}", deployment_type="{metadata.DEPLOYMENT_TYPE}"'
178
189
  metrics.extend(
179
190
  [
180
191
  "# HELP lg_api_num_pending_runs The number of runs currently pending.",
181
192
  "# TYPE lg_api_num_pending_runs gauge",
182
- f'lg_api_num_pending_runs{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {queue_stats["n_pending"]}',
193
+ f"lg_api_num_pending_runs{{{labels}}} {queue_stats['n_pending']}",
183
194
  "# HELP lg_api_num_running_runs The number of runs currently running.",
184
195
  "# TYPE lg_api_num_running_runs gauge",
185
- f'lg_api_num_running_runs{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {queue_stats["n_running"]}',
196
+ f"lg_api_num_running_runs{{{labels}}} {queue_stats['n_running']}",
186
197
  "# HELP lg_api_pending_runs_wait_time_max The maximum time a run has been pending, in seconds.",
187
198
  "# TYPE lg_api_pending_runs_wait_time_max gauge",
188
- f'lg_api_pending_runs_wait_time_max{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {queue_stats.get("pending_runs_wait_time_max_secs") or 0}',
199
+ f"lg_api_pending_runs_wait_time_max{{{labels}}} {queue_stats.get('pending_runs_wait_time_max_secs') or 0}",
189
200
  "# HELP lg_api_pending_runs_wait_time_med The median pending wait time across runs, in seconds.",
190
201
  "# TYPE lg_api_pending_runs_wait_time_med gauge",
191
- f'lg_api_pending_runs_wait_time_med{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {queue_stats.get("pending_runs_wait_time_med_secs") or 0}',
202
+ f"lg_api_pending_runs_wait_time_med{{{labels}}} {queue_stats.get('pending_runs_wait_time_med_secs') or 0}",
192
203
  "# HELP lg_api_pending_unblocked_runs_wait_time_max The maximum time a run has been pending excluding runs blocked by another run on the same thread, in seconds.",
193
204
  "# TYPE lg_api_pending_unblocked_runs_wait_time_max gauge",
194
- f'lg_api_pending_unblocked_runs_wait_time_max{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {queue_stats.get("pending_unblocked_runs_wait_time_max_secs") or 0}',
205
+ f"lg_api_pending_unblocked_runs_wait_time_max{{{labels}}} {queue_stats.get('pending_unblocked_runs_wait_time_max_secs') or 0}",
195
206
  ]
196
207
  )
197
208
  except Exception as e:
@@ -200,17 +211,18 @@ async def meta_metrics(request: ApiRequest):
200
211
  )
201
212
 
202
213
  if config.N_JOBS_PER_WORKER > 0:
214
+ worker_labels = f'project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}", deployment_type="{metadata.DEPLOYMENT_TYPE}"'
203
215
  metrics.extend(
204
216
  [
205
217
  "# HELP lg_api_workers_max The maximum number of workers available.",
206
218
  "# TYPE lg_api_workers_max gauge",
207
- f'lg_api_workers_max{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {workers_max}',
219
+ f"lg_api_workers_max{{{worker_labels}}} {workers_max}",
208
220
  "# HELP lg_api_workers_active The number of currently active workers.",
209
221
  "# TYPE lg_api_workers_active gauge",
210
- f'lg_api_workers_active{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {workers_active}',
222
+ f"lg_api_workers_active{{{worker_labels}}} {workers_active}",
211
223
  "# HELP lg_api_workers_available The number of available (idle) workers.",
212
224
  "# TYPE lg_api_workers_available gauge",
213
- f'lg_api_workers_available{{project_id="{metadata.PROJECT_ID}", revision_id="{metadata.HOST_REVISION_ID}"}} {workers_available}',
225
+ f"lg_api_workers_available{{{worker_labels}}} {workers_available}",
214
226
  ]
215
227
  )
216
228
 
@@ -94,6 +94,7 @@ def _is_port_available(host: str, port: int) -> bool:
94
94
  """Check if a port is available for binding."""
95
95
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
96
96
  try:
97
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
97
98
  s.bind((host, port))
98
99
  return True
99
100
  except OSError:
@@ -150,17 +151,11 @@ def _resolve_server_url(
150
151
 
151
152
  def _resolve_port(host: str, port: int | None) -> int:
152
153
  """Resolve the port to use for the server."""
153
- if port is not None:
154
- if not _is_port_available(host, port):
155
- raise OSError(
156
- f"Port {port} is already in use. Please specify a different port "
157
- f"or omit the port argument to auto-discover an available one."
158
- )
159
- return port
160
- if _is_port_available(host, DEFAULT_PORT):
161
- return DEFAULT_PORT
154
+ requested = port if port is not None else DEFAULT_PORT
155
+ if _is_port_available(host, requested):
156
+ return requested
162
157
  found = _find_open_port(host)
163
- logger.info(f"Default port {DEFAULT_PORT} is in use, using port {found} instead.")
158
+ logger.warning(f"Port {requested} is already in use, using port {found} instead.")
164
159
  return found
165
160
 
166
161
 
@@ -416,7 +411,7 @@ def main():
416
411
  "--port",
417
412
  type=int,
418
413
  default=None,
419
- help="Port to bind the server to (default: 2024, auto-discovers if in use)",
414
+ help="Port to bind the server to (default: 2024; auto-discovers another port if the requested one is in use)",
420
415
  )
421
416
  parser.add_argument("--no-reload", action="store_true", help="Disable auto-reload")
422
417
  parser.add_argument(
@@ -84,6 +84,7 @@ class HTTPMetricsCollector:
84
84
  project_id: str | None,
85
85
  revision_id: str | None,
86
86
  format: str = "prometheus",
87
+ deployment_type: str = "",
87
88
  ) -> dict | list[str]:
88
89
  if format == "json":
89
90
  return {
@@ -117,7 +118,7 @@ class HTTPMetricsCollector:
117
118
 
118
119
  for (method, path, status), count in self._request_counts.items():
119
120
  metrics.append(
120
- f'lg_api_http_requests_total{{project_id="{project_id}", revision_id="{revision_id}", method="{method}", path="{path}", status="{status}"}} {count}'
121
+ f'lg_api_http_requests_total{{project_id="{project_id}", revision_id="{revision_id}", deployment_type="{deployment_type}", method="{method}", path="{path}", status="{status}"}} {count}'
121
122
  )
122
123
 
123
124
  # Histogram metrics
@@ -135,13 +136,13 @@ class HTTPMetricsCollector:
135
136
  acc += bucket_count
136
137
  bucket_label = self._histogram_bucket_labels[i]
137
138
  metrics.append(
138
- f'lg_api_http_requests_latency_seconds_bucket{{project_id="{project_id}", revision_id="{revision_id}", method="{method}", path="{path}", le="{bucket_label}"}} {acc}'
139
+ f'lg_api_http_requests_latency_seconds_bucket{{project_id="{project_id}", revision_id="{revision_id}", deployment_type="{deployment_type}", method="{method}", path="{path}", le="{bucket_label}"}} {acc}'
139
140
  )
140
141
 
141
142
  metrics.extend(
142
143
  [
143
- f'lg_api_http_requests_latency_seconds_sum{{project_id="{project_id}", revision_id="{revision_id}", method="{method}", path="{path}"}} {hist_data["sum"]:.6f}',
144
- f'lg_api_http_requests_latency_seconds_count{{project_id="{project_id}", revision_id="{revision_id}", method="{method}", path="{path}"}} {hist_data["count"]}',
144
+ f'lg_api_http_requests_latency_seconds_sum{{project_id="{project_id}", revision_id="{revision_id}", deployment_type="{deployment_type}", method="{method}", path="{path}"}} {hist_data["sum"]:.6f}',
145
+ f'lg_api_http_requests_latency_seconds_count{{project_id="{project_id}", revision_id="{revision_id}", deployment_type="{deployment_type}", method="{method}", path="{path}"}} {hist_data["count"]}',
145
146
  ]
146
147
  )
147
148
 
@@ -30,6 +30,7 @@ import * as fs from "node:fs/promises";
30
30
  import * as path from "node:path";
31
31
  import { serialiseAsDict, serializeError } from "./src/utils/serde.mjs";
32
32
  import * as importMap from "./src/utils/importMap.mjs";
33
+ import { buildExperimentReplicas } from "./src/utils/experiment-tracing.mjs";
33
34
 
34
35
  import { createLogger, format, transports } from "winston";
35
36
 
@@ -45,6 +46,8 @@ import {
45
46
  } from "./src/graph.mts";
46
47
  import { asyncExitHook, gracefulExit } from "exit-hook";
47
48
  import { awaitAllCallbacks } from "@langchain/core/callbacks/promises";
49
+ import { LangChainTracer } from "@langchain/core/tracers/tracer_langchain";
50
+ import type { BaseCallbackHandler } from "@langchain/core/callbacks/base";
48
51
  import { StatusCode } from "hono/utils/http-status";
49
52
  import {
50
53
  authenticate,
@@ -714,6 +717,17 @@ async function* streamEventsRequest(
714
717
  config.metadata.langgraph_version = version;
715
718
  }
716
719
 
720
+ // Mirror the Python worker's experiment-routing setup for JS graphs. The
721
+ // Python `tracing_context(replicas=...)` cannot cross the sidecar boundary,
722
+ // so build replicas from the same reserved configurable keys and attach a
723
+ // LangChainTracer carrying them. The framework skips its default tracer
724
+ // when one with name "langchain_tracer" is already present in
725
+ // config.callbacks (see @langchain/core callbacks/manager.js).
726
+ const replicas = buildExperimentReplicas(config.configurable);
727
+ const callbacks: BaseCallbackHandler[] | undefined = replicas
728
+ ? [new LangChainTracer({ replicas })]
729
+ : undefined;
730
+
717
731
  for await (const data of graph.streamEvents(input, {
718
732
  ...config,
719
733
  version: "v2",
@@ -721,6 +735,7 @@ async function* streamEventsRequest(
721
735
  subgraphs: payload.subgraphs,
722
736
  interruptBefore,
723
737
  interruptAfter,
738
+ ...(callbacks ? { callbacks } : {}),
724
739
  })) {
725
740
  // TODO: upstream this fix to LangGraphJS
726
741
  if (streamMode.length === 1 && !Array.isArray(data.data.chunk)) {
@@ -0,0 +1,51 @@
1
+ // Helpers for routing studio-experiment runs to a separate LangSmith project
2
+ // when a JS graph is invoked via the Node sidecar.
3
+ //
4
+ // The Python worker (api/langgraph_api/stream.py) reads the run-creation
5
+ // payload's `langsmith_tracer` field and stores it under the reserved
6
+ // configurable keys `__langsmith_project__` / `__langsmith_example_id__`
7
+ // (see api/langgraph_api/models/run.py). For Python graphs it then wraps
8
+ // execution in `langsmith.tracing_context(replicas=[...])`. Python contextvars
9
+ // don't cross the HTTP boundary into the JS sidecar, so we read the same
10
+ // reserved keys here and produce an equivalent replica list that the JS
11
+ // sidecar can pass to a `LangChainTracer`.
12
+
13
+ export interface ExperimentReplica {
14
+ projectName: string;
15
+ updates?: { reference_example_id: string };
16
+ }
17
+
18
+ /**
19
+ * Build the LangSmith tracing replicas for a JS streamEvents call.
20
+ *
21
+ * Returns `undefined` when the run was not dispatched as part of a studio
22
+ * experiment (i.e. `__langsmith_project__` is not set). When set, returns
23
+ * two replicas mirroring the Python worker:
24
+ * 1. the experiment project (carrying `reference_example_id` when an
25
+ * example_id is present) — links runs to dataset rows in the experiment
26
+ * view.
27
+ * 2. the deployment's env-default project (`LANGSMITH_PROJECT` /
28
+ * `LANGCHAIN_PROJECT`) — keeps the deployment-level trace stream
29
+ * unchanged for non-experiment observability.
30
+ */
31
+ export function buildExperimentReplicas(
32
+ configurable: Record<string, unknown> | undefined,
33
+ env: NodeJS.ProcessEnv = process.env,
34
+ ): ExperimentReplica[] | undefined {
35
+ const lsProject = configurable?.["__langsmith_project__"];
36
+ if (typeof lsProject !== "string" || lsProject.length === 0) return undefined;
37
+
38
+ const lsExampleId = configurable?.["__langsmith_example_id__"];
39
+ const envProject =
40
+ env.LANGSMITH_PROJECT ?? env.LANGCHAIN_PROJECT ?? "default";
41
+
42
+ return [
43
+ {
44
+ projectName: lsProject,
45
+ ...(typeof lsExampleId === "string" && lsExampleId.length > 0
46
+ ? { updates: { reference_example_id: lsExampleId } }
47
+ : {}),
48
+ },
49
+ { projectName: envProject },
50
+ ];
51
+ }