langgraph-api 0.16.0.dev7__tar.gz → 0.16.0.dev8__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 (325) hide show
  1. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/PKG-INFO +2 -1
  2. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/README.md +11 -2
  3. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/capacity-ci.js +359 -146
  4. langgraph_api-0.16.0.dev8/benchmark/capacity-ci.test.js +404 -0
  5. langgraph_api-0.16.0.dev8/benchmark/daily-report.js +503 -0
  6. langgraph_api-0.16.0.dev8/benchmark/daily-report.test.js +463 -0
  7. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/history.js +22 -2
  8. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/history.test.js +46 -4
  9. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/runner-descriptions.js +25 -0
  10. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/server-metrics.js +10 -0
  11. langgraph_api-0.16.0.dev8/benchmark/slack.js +49 -0
  12. langgraph_api-0.16.0.dev8/langgraph_api/__init__.py +1 -0
  13. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2a.py +8 -11
  14. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/threads.py +2 -0
  15. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/schema.py +2 -0
  16. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/state.py +11 -5
  17. langgraph_api-0.16.0.dev8/langgraph_grpc_common/proto/core_api_pb2.py +274 -0
  18. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/core_api_pb2.pyi +10 -2
  19. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/openapi.json +4 -0
  20. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/pyproject.toml +1 -0
  21. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/uv.lock +2 -0
  22. langgraph_api-0.16.0.dev7/benchmark/capacity-ci.test.js +0 -265
  23. langgraph_api-0.16.0.dev7/benchmark/daily-report.js +0 -358
  24. langgraph_api-0.16.0.dev7/benchmark/daily-report.test.js +0 -350
  25. langgraph_api-0.16.0.dev7/langgraph_api/__init__.py +0 -1
  26. langgraph_api-0.16.0.dev7/langgraph_grpc_common/proto/core_api_pb2.py +0 -274
  27. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/.gitignore +0 -0
  28. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/LICENSE +0 -0
  29. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/Makefile +0 -0
  30. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/README.md +0 -0
  31. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/.gitignore +0 -0
  32. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/Makefile +0 -0
  33. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/assistant.ts +0 -0
  34. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
  35. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
  36. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/benchmarks.ts +0 -0
  37. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
  38. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/classify-error.test.js +0 -0
  39. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/classify-error.ts +0 -0
  40. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/delta-turns-lib.test.js +0 -0
  41. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/delta-turns-lib.ts +0 -0
  42. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/delta_turns.ts +0 -0
  43. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
  44. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
  45. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/log-failure.ts +0 -0
  46. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/meta_workload.ts +0 -0
  47. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/store.ts +0 -0
  48. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/stream_write.ts +0 -0
  49. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/thread.ts +0 -0
  50. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
  51. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
  52. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/types.ts +0 -0
  53. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/wait_write.ts +0 -0
  54. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/clean-cli.js +0 -0
  55. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/clean.js +0 -0
  56. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/README.md +0 -0
  57. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/pyproject.toml +0 -0
  58. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/runner.py +0 -0
  59. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/uv.lock +0 -0
  60. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/graphs.js +0 -0
  61. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/host-v2.js +0 -0
  62. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/host-v2.test.js +0 -0
  63. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/multer.test.js +0 -0
  64. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/package.json +0 -0
  65. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/ramp.js +0 -0
  66. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/reporting/dd_reporting.py +0 -0
  67. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/server-metrics.test.js +0 -0
  68. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/staircase.py +0 -0
  69. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/staircase_step_k6.js +0 -0
  70. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/tsconfig.json +0 -0
  71. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/update-revision.js +0 -0
  72. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/weather.js +0 -0
  73. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/yarn.lock +0 -0
  74. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/constraints.txt +0 -0
  75. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/custom_store.sql +0 -0
  76. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/forbidden.txt +0 -0
  77. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/hatch_build.py +0 -0
  78. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/healthcheck.py +0 -0
  79. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph-cloud-debugging-20260210132856.zip +0 -0
  80. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_checkpointer/__init__.py +0 -0
  81. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_checkpointer/_adapter.py +0 -0
  82. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_checkpointer/protocol.py +0 -0
  83. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_factory_utils.py +0 -0
  84. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/__init__.py +0 -0
  85. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui.py +0 -0
  86. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/README.md +0 -0
  87. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
  88. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
  89. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
  90. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
  91. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/assistants.py +0 -0
  92. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/event_streaming.py +0 -0
  93. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/__init__.py +0 -0
  94. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_constants.py +0 -0
  95. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_handlers.py +0 -0
  96. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_models.py +0 -0
  97. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_routes.py +0 -0
  98. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_sanitizers.py +0 -0
  99. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/meta.py +0 -0
  100. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/openapi.py +0 -0
  101. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/profile.py +0 -0
  102. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/runs.py +0 -0
  103. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/store.py +0 -0
  104. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/threads.py +0 -0
  105. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/ui.py +0 -0
  106. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/asgi_transport.py +0 -0
  107. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/asyncio.py +0 -0
  108. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/__init__.py +0 -0
  109. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/custom.py +0 -0
  110. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/errors.py +0 -0
  111. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/langsmith/__init__.py +0 -0
  112. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/langsmith/backend.py +0 -0
  113. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/langsmith/client.py +0 -0
  114. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/middleware.py +0 -0
  115. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/noop.py +0 -0
  116. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/studio_user.py +0 -0
  117. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
  118. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/cache.py +0 -0
  119. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/cli.py +0 -0
  120. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/command.py +0 -0
  121. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/config/__init__.py +0 -0
  122. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/config/_parse.py +0 -0
  123. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/config/schemas.py +0 -0
  124. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/cron_scheduler.py +0 -0
  125. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/__init__.py +0 -0
  126. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/aes_json.py +0 -0
  127. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/context.py +0 -0
  128. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/custom.py +0 -0
  129. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/middleware.py +0 -0
  130. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/shared.py +0 -0
  131. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/errors.py +0 -0
  132. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/__init__.py +0 -0
  133. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/capabilities.py +0 -0
  134. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/constants.py +0 -0
  135. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/event_normalizers.py +0 -0
  136. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/namespace.py +0 -0
  137. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/service.py +0 -0
  138. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/session.py +0 -0
  139. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/state_normalizers.py +0 -0
  140. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/types.py +0 -0
  141. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/feature_flags.py +0 -0
  142. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/graph.py +0 -0
  143. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/__init__.py +0 -0
  144. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/client.py +0 -0
  145. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
  146. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/__init__.py +0 -0
  147. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/assistants.py +0 -0
  148. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/cache.py +0 -0
  149. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/crons.py +0 -0
  150. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/runs.py +0 -0
  151. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/server.py +0 -0
  152. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/servicers/__init__.py +0 -0
  153. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
  154. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/servicers/encryption.py +0 -0
  155. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/http.py +0 -0
  156. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/http_metrics.py +0 -0
  157. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/http_metrics_utils.py +0 -0
  158. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/.gitignore +0 -0
  159. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/.prettierrc +0 -0
  160. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/.yarnclean +0 -0
  161. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/__init__.py +0 -0
  162. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/base.py +0 -0
  163. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/build.mts +0 -0
  164. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/client.http.mts +0 -0
  165. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/client.mts +0 -0
  166. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/errors.py +0 -0
  167. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/global.d.ts +0 -0
  168. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/package.json +0 -0
  169. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/remote.py +0 -0
  170. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/schema.py +0 -0
  171. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/graph.mts +0 -0
  172. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/load.hooks.mjs +0 -0
  173. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/preload.mjs +0 -0
  174. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
  175. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/files.mts +0 -0
  176. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/importMap.mts +0 -0
  177. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  178. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/serde.mts +0 -0
  179. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/sse.py +0 -0
  180. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/traceblock.mts +0 -0
  181. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/tsconfig.json +0 -0
  182. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/ui.py +0 -0
  183. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/yarn.lock +0 -0
  184. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/__init__.py +0 -0
  185. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/exceptions.py +0 -0
  186. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/policy.py +0 -0
  187. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/transport.py +0 -0
  188. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/logging.py +0 -0
  189. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/metadata.py +0 -0
  190. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/metrics_collector.py +0 -0
  191. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/metrics_otlp.py +0 -0
  192. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/__init__.py +0 -0
  193. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/ensure_store.py +0 -0
  194. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/http_logger.py +0 -0
  195. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/private_network.py +0 -0
  196. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/request_id.py +0 -0
  197. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/models/__init__.py +0 -0
  198. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/models/run.py +0 -0
  199. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/otel_context.py +0 -0
  200. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/patch.py +0 -0
  201. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/queue_entrypoint.py +0 -0
  202. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/release_tags.py +0 -0
  203. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/route.py +0 -0
  204. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/runner/__init__.py +0 -0
  205. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/runner/__main__.py +0 -0
  206. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/self_hosted_logs.py +0 -0
  207. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/self_hosted_metrics.py +0 -0
  208. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/serde.py +0 -0
  209. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/server.py +0 -0
  210. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/sse.py +0 -0
  211. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/store.py +0 -0
  212. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/stream.py +0 -0
  213. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/stream_v2.py +0 -0
  214. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/timing/__init__.py +0 -0
  215. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/timing/profiler.py +0 -0
  216. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/timing/timer.py +0 -0
  217. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/traceblock.py +0 -0
  218. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/tracing_session.py +0 -0
  219. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/tunneling/cloudflare.py +0 -0
  220. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/__init__.py +0 -0
  221. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/cache.py +0 -0
  222. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/config.py +0 -0
  223. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/errors.py +0 -0
  224. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/extract.py +0 -0
  225. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/future.py +0 -0
  226. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/headers.py +0 -0
  227. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/network.py +0 -0
  228. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/retriable_client.py +0 -0
  229. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/stream_codec.py +0 -0
  230. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/uuids.py +0 -0
  231. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/validation.py +0 -0
  232. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/webhook.py +0 -0
  233. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/worker.py +0 -0
  234. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/worker_runtime.py +0 -0
  235. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/__init__.py +0 -0
  236. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/checkpointer.py +0 -0
  237. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/__init__.py +0 -0
  238. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/_compat.py +0 -0
  239. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
  240. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/config.py +0 -0
  241. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/durability.py +0 -0
  242. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/store.py +0 -0
  243. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/struct.py +0 -0
  244. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/value.py +0 -0
  245. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/__init__.py +0 -0
  246. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
  247. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
  248. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
  249. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
  250. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
  251. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
  252. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
  253. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
  254. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
  255. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
  256. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
  257. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
  258. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
  259. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
  260. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
  261. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
  262. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
  263. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
  264. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
  265. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
  266. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
  267. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
  268. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
  269. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
  270. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
  271. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
  272. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
  273. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
  274. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
  275. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
  276. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
  277. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
  278. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
  279. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
  280. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
  281. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
  282. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
  283. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
  284. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
  285. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
  286. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
  287. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
  288. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
  289. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
  290. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
  291. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
  292. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
  293. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
  294. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
  295. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
  296. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
  297. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
  298. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
  299. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
  300. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2.py +0 -0
  301. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2.pyi +0 -0
  302. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2_grpc.py +0 -0
  303. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2_grpc.pyi +0 -0
  304. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2.py +0 -0
  305. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
  306. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
  307. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
  308. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/serde.py +0 -0
  309. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/store.py +0 -0
  310. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_license/__init__.py +0 -0
  311. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_license/validation.py +0 -0
  312. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/__init__.py +0 -0
  313. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/checkpoint.py +0 -0
  314. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/database.py +0 -0
  315. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/lifespan.py +0 -0
  316. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/metrics.py +0 -0
  317. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/ops.py +0 -0
  318. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/queue.py +0 -0
  319. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/retry.py +0 -0
  320. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/routes.py +0 -0
  321. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/store.py +0 -0
  322. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/logging.json +0 -0
  323. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/scripts/build_wheel.py +0 -0
  324. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/scripts/create_license.py +0 -0
  325. {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/scripts/run_a2a_tck.py +0 -0
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.16.0.dev7
3
+ Version: 0.16.0.dev8
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
7
7
  Requires-Python: >=3.11
8
+ Requires-Dist: anyio>=4.14.2
8
9
  Requires-Dist: cloudpickle>=3.0.0
9
10
  Requires-Dist: cryptography>=50.0.0
10
11
  Requires-Dist: grpcio-health-checking<1.82.0,>=1.81.0
@@ -192,9 +192,18 @@ be compared on the bytes they occupy, which is what the feature exists to reduce
192
192
  2. Fill in `deploymentId` and `baseUrl` in `CAPACITY_DEPLOYMENTS` at the top of [`capacity-ci.js`](capacity-ci.js).
193
193
  3. Scheduled run: two parallel CI jobs (one per deployment), aggregate job posts Slack summary.
194
194
 
195
- Each cell also records the deployment's own view of its window (queue and API pod counts, CPU peaks) from the control plane's deployment metrics route, and the posted table lists it under each deployment. Every tier starts at one queue pod and autoscales during a cell, so a capacity number is partly a pod-count number; pinning pods at the tier maximum would need the benchmark deployments recreated as `external_docker` sources, the only kind whose `resource_spec` the API accepts.
195
+ Each cell also records the deployment's own view of its window (queue and API pod counts, CPU peaks) from the control plane's deployment metrics route. The posted message names any component at or over 95% of its CPU request as that tier's bottleneck, and the full per-cell table goes to the message's thread. Every tier starts at one queue pod and autoscales during a cell, so a capacity number is partly a pod-count number; pinning pods at the tier maximum would need the benchmark deployments recreated as `external_docker` sources, the only kind whose `resource_spec` the API accepts.
196
196
 
197
- Both the daily and the capacity reports compare tonight with the previous scheduled nights (`history.js`, artifacts fetched with `gh`), flagging a figure only when it leaves that runner's own observed range.
197
+ ### Slack reports
198
+
199
+ Every report follows one shape so the channel reads the same way each morning, on a phone as well as a desktop:
200
+
201
+ - The first line is the verdict: a dot (green quiet, yellow something regressed or a bottleneck or errors, red something failed), the report name and date, `manual run` when dispatched by hand, the API version, and a clause saying what needs attention. The second line says what the benchmark is, for a reader outside the team.
202
+ - Then `Failed`, `Regressed`, `Improved` and `Bottlenecks` or `Errors` lines, worst first. `Regressed` prints `none` rather than going quiet.
203
+ - One table per deployment, about 40 characters wide so it fits a phone, with `▲ better` / `▼ worse` markers on cells that left their usual range.
204
+ - One legend line (pass rule, arrows, dot colors), then a link to the thread, which holds the per-cell or per-run numbers and the longer *How to read*, and to the run's artifacts.
205
+
206
+ Both reports compare tonight with the previous scheduled nights (`history.js`, artifacts fetched with `gh`). A figure is flagged only when it leaves that cell's own observed range, and only once five same-kind nights exist; before that the table says how many nights it has. The daily benchmark posts one digest per workflow once its last runner finishes (`daily-report.js`, fed by each runner's artifact), not one message per runner.
198
207
 
199
208
  Local commands:
200
209
 
@@ -18,23 +18,33 @@ import {
18
18
  requireApiKey,
19
19
  setResourceTiers,
20
20
  } from "./host-v2.js";
21
- import { cellKey, compare, formatDelta, loadCapacityHistory } from "./history.js";
22
- import { describeRunner, runnerShortName } from "./runner-descriptions.js";
21
+ import { RUNNERS, readApiVersion } from "./daily-report.js";
23
22
  import {
24
- cellWindow,
25
- formatServerMetrics,
26
- summarizeServerMetrics,
27
- } from "./server-metrics.js";
23
+ MIN_HISTORY_NIGHTS,
24
+ cellKey,
25
+ flaggedChange,
26
+ formatMove,
27
+ loadCapacityHistory,
28
+ } from "./history.js";
29
+ import {
30
+ describeRunnerBriefly,
31
+ runnerColumnName,
32
+ runnerGloss,
33
+ runnerShortName,
34
+ } from "./runner-descriptions.js";
35
+ import { cellWindow, peakCpu, podRange, summarizeServerMetrics } from "./server-metrics.js";
36
+ import { dotFor, postReport } from "./slack.js";
28
37
 
29
38
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
30
39
 
31
40
  /**
32
41
  * @typedef {{startLoad?: string, stepSize?: string, numSteps?: string, warmupLoad?: string}} StaircaseGeometry
33
- * @type {Array<{slug: string, deploymentId: string, baseUrl: string, tiers: string[], staircase?: StaircaseGeometry}>}
42
+ * @type {Array<{slug: string, name: string, deploymentId: string, baseUrl: string, tiers: string[], staircase?: StaircaseGeometry}>}
34
43
  */
35
44
  const CAPACITY_DEPLOYMENTS = [
36
45
  {
37
46
  slug: "daily-cap-benchmark-dedicated",
47
+ name: "Dedicated",
38
48
  deploymentId: "22a22e9d-521e-4635-9bcb-a096a22820cc",
39
49
  baseUrl:
40
50
  "https://daily-cap-benchmark-dedicat-9669b63626045e0681f1f1fda08ef4ce.staging.langgraph.app",
@@ -45,6 +55,7 @@ const CAPACITY_DEPLOYMENTS = [
45
55
  },
46
56
  {
47
57
  slug: "daily-cap-benchmark-serverless",
58
+ name: "Serverless",
48
59
  deploymentId: "becfa8bb-e2e3-4d96-8d08-3191b17c5d4d",
49
60
  baseUrl:
50
61
  "https://daily-cap-benchmark-serverl-b5dc9d9f7fa05990b279939863ae08de.staging.langgraph.app",
@@ -56,8 +67,6 @@ const CAPACITY_DEPLOYMENTS = [
56
67
  },
57
68
  ];
58
69
 
59
- const RUNNERS = ["wait_write", "stream_write", "threads_search_metadata"];
60
-
61
70
  // Open model: a fixed arrival rate per step, so capacity reads directly as the
62
71
  // service rate. Closed-model users back off as the server slows and flatter it.
63
72
  const STAIRCASE_EXECUTOR = "constant-arrival-rate";
@@ -195,135 +204,354 @@ export function capacityVus(summary) {
195
204
  return perSec == null ? String(vus) : `${vus} (${perSec}/s)`;
196
205
  }
197
206
 
198
- export function formatAggregateTable(
199
- deployments,
200
- summaries,
201
- warnings = [],
202
- now = new Date(),
203
- history = {},
204
- ) {
207
+ const BOTTLENECK_CPU_PCT = 95;
208
+ const COMPONENTS = [
209
+ ["queue", "queue"],
210
+ ["api", "api"],
211
+ ["db", "database"],
212
+ ["redis", "redis"],
213
+ ];
214
+
215
+ function deploymentName(deployment) {
216
+ return deployment.name ?? deployment.slug;
217
+ }
218
+
219
+ function tierLabel(deployment, tier) {
220
+ const prefix = `${deploymentName(deployment).toUpperCase()}_`;
221
+ return tier.startsWith(prefix) ? tier.slice(prefix.length) : tier;
222
+ }
223
+
224
+ function cellName(deployment, tier, runner) {
225
+ return `${deploymentName(deployment)} ${tierLabel(deployment, tier)} ${runnerColumnName(runner)}`;
226
+ }
227
+
228
+ function indexCells(deployments, summaries) {
205
229
  /** @type {Record<string, Record<string, Record<string, object>>>} */
206
230
  const byDeployment = Object.fromEntries(deployments.map((d) => [d.slug, {}]));
207
-
208
231
  for (const summary of summaries) {
209
- const config = summary.config ?? {};
210
- const { deploymentSlug, computeTier, benchmarkType } = config;
232
+ const { deploymentSlug, computeTier, benchmarkType } = summary.config ?? {};
211
233
  if (deploymentSlug && computeTier && benchmarkType) {
212
234
  byDeployment[deploymentSlug] ??= {};
213
235
  byDeployment[deploymentSlug][computeTier] ??= {};
214
236
  byDeployment[deploymentSlug][computeTier][benchmarkType] = summary;
215
237
  }
216
238
  }
239
+ return byDeployment;
240
+ }
217
241
 
218
- const expected = deployments.reduce(
219
- (total, deployment) => total + deployment.tiers.length * RUNNERS.length,
220
- 0,
221
- );
222
- const failed = summaries.filter((summary) => summary.error).length;
223
- const stepSeconds = (() => {
224
- const seen = [...new Set(
225
- summaries.map((s) => s.config?.plateauDurationSeconds).filter((v) => v != null).map(String),
226
- )];
227
- if (seen.length === 0) return STAIRCASE_PLATEAU_DURATION;
228
- return seen.sort((a, b) => Number(a) - Number(b)).join("/");
229
- })();
230
- const missing = expected - summaries.length;
242
+ function pastNights(deployment, tier, runner, summary, history) {
243
+ const executor = summary?.config?.k6Executor ?? "constant-vus";
244
+ // Nights measured in users and nights measured in req/s are different
245
+ // scales; only the same executor is a baseline.
246
+ return (history[cellKey({ deploymentSlug: deployment.slug, computeTier: tier, benchmarkType: runner })] ?? [])
247
+ .filter((night) => (night.executor ?? "constant-vus") === executor)
248
+ .map((night) => night.capacityVUs);
249
+ }
250
+
251
+ function analyseDeployment(deployment, cells, history) {
252
+ const rows = [];
253
+ let nights = 0;
254
+ for (const tier of deployment.tiers) {
255
+ for (const runner of RUNNERS) {
256
+ const summary = cells[tier]?.[runner];
257
+ const past = summary && !summary.error ? pastNights(deployment, tier, runner, summary, history) : [];
258
+ nights = Math.max(nights, past.length);
259
+ const change =
260
+ summary && !summary.error
261
+ ? flaggedChange(summary.capacity?.targetVUs ?? 0, past, { higherIsBetter: true })
262
+ : null;
263
+ rows.push({
264
+ deployment,
265
+ tier,
266
+ runner,
267
+ summary,
268
+ change,
269
+ hot: hotComponents(summary),
270
+ });
271
+ }
272
+ }
273
+ return { rows, nights };
274
+ }
275
+
276
+ function hotComponents(summary) {
277
+ const groups = summary?.serverMetricsAtCapacity?.groups ?? {};
278
+ return COMPONENTS.flatMap(([label, name]) => {
279
+ const cpu = peakCpu(groups[label]);
280
+ return cpu != null && cpu >= BOTTLENECK_CPU_PCT ? [{ name, cpu: Math.round(cpu) }] : [];
281
+ });
282
+ }
283
+
284
+ function bottleneckLines(rows) {
285
+ const groups = new Map();
286
+ for (const row of rows) {
287
+ for (const { name, cpu } of row.hot) {
288
+ const key = `${row.deployment.slug}|${name}`;
289
+ const group = groups.get(key) ?? { deployment: row.deployment, name, tiers: new Set(), cpus: [] };
290
+ group.tiers.add(tierLabel(row.deployment, row.tier));
291
+ group.cpus.push(cpu);
292
+ groups.set(key, group);
293
+ }
294
+ }
295
+ const order = (group) => COMPONENTS.findIndex(([, name]) => name === group.name);
296
+ return [...groups.values()].sort((a, b) => order(a) - order(b)).map(({ deployment, name, tiers, cpus }) => {
297
+ const low = Math.min(...cpus);
298
+ const high = Math.max(...cpus);
299
+ const range = low === high ? `${high}%` : `${low} to ${high}%`;
300
+ return `${deploymentName(deployment)} ${[...tiers].join(", ")}: ${name} at ${range}`;
301
+ });
302
+ }
303
+
304
+ function crashedTiers(rows) {
305
+ const byTier = new Map();
306
+ for (const row of rows) {
307
+ if (!row.summary?.error) continue;
308
+ const key = `${row.deployment.slug}|${row.tier}`;
309
+ (byTier.get(key) ?? byTier.set(key, { row, runners: [] }).get(key)).runners.push(row.runner);
310
+ }
311
+ return [...byTier.values()].map(({ row, runners }) => {
312
+ const where = `${deploymentName(row.deployment)} ${tierLabel(row.deployment, row.tier)}`;
313
+ const detail = runners.length === RUNNERS.length
314
+ ? `${where}, all ${RUNNERS.length} tests (ERR)`
315
+ : `${where} ${runners.map(runnerColumnName).join(", ")} (ERR)`;
316
+ return { where, detail };
317
+ });
318
+ }
319
+
320
+ function moveLine(row, unit) {
321
+ const now = row.summary.capacity?.targetVUs ?? 0;
322
+ return `${cellName(row.deployment, row.tier, row.runner)} ${formatMove(Math.round(row.change.median), now, row.change.deltaPct, unit)}`;
323
+ }
324
+
325
+ export function capacityCell(summary) {
326
+ if (!summary) return "-";
327
+ if (summary.error) return "ERR";
328
+ return String(summary.capacity?.targetVUs ?? 0);
329
+ }
330
+
331
+ function plural(n, word) {
332
+ return `${n} ${word}${n === 1 ? "" : "s"}`;
333
+ }
334
+
335
+ function stepSecondsOf(summaries) {
336
+ const seen = [...new Set(
337
+ summaries.map((s) => s.config?.plateauDurationSeconds).filter((v) => v != null).map(String),
338
+ )];
339
+ if (seen.length === 0) return STAIRCASE_PLATEAU_DURATION;
340
+ return seen.sort((a, b) => Number(a) - Number(b)).join("/");
341
+ }
342
+
343
+ /** A dispatch can override the configured geometry; the report describes the run. */
344
+ function geometryOf(deployment, cells) {
345
+ const ran = ranGeometry(cells) ?? deployment.staircase ?? {};
346
+ return {
347
+ start: Number(ran.startLoad ?? STAIRCASE_START_LOAD),
348
+ step: Number(ran.stepSize ?? STAIRCASE_STEP_SIZE),
349
+ };
350
+ }
351
+
352
+ function capacityTable(deployment, rows, unit) {
353
+ const labels = deployment.tiers.map((tier) => tierLabel(deployment, tier));
354
+ const labelWidth = Math.max(2, ...labels.map((l) => l.length)) + 1;
355
+ const column = (text, arrow = " ") => `${text.padStart(6)}${arrow}`;
356
+ const lines = [
357
+ `*${deploymentName(deployment)}* · ${unit} at SLO`,
358
+ "```",
359
+ `${"".padEnd(labelWidth)}${RUNNERS.map((r) => column(runnerColumnName(r))).join("")}`,
360
+ ];
361
+ for (const tier of deployment.tiers) {
362
+ const cells = rows.filter((row) => row.tier === tier);
363
+ lines.push(
364
+ `${tierLabel(deployment, tier).padEnd(labelWidth)}${cells.map((row) => column(capacityCell(row.summary), row.change?.arrow)).join("")}`,
365
+ );
366
+ }
367
+ lines.push("```");
368
+ return lines;
369
+ }
370
+
371
+ export function formatAggregateTable(
372
+ deployments,
373
+ summaries,
374
+ warnings = [],
375
+ now = new Date(),
376
+ history = {},
377
+ apiVersion = null,
378
+ manual = false,
379
+ ) {
380
+ const byDeployment = indexCells(deployments, summaries);
381
+ const analysed = deployments.map((deployment) => ({
382
+ deployment,
383
+ ...analyseDeployment(deployment, byDeployment[deployment.slug] ?? {}, history),
384
+ }));
385
+ const rows = analysed.flatMap((a) => a.rows);
386
+
387
+ const expected = rows.length;
388
+ const failed = rows.filter((row) => row.summary?.error).length;
389
+ const missing = rows.filter((row) => !row.summary).length;
390
+ const jobFailed = process.env.CAPACITY_JOB_RESULT === "failure";
391
+ const regressed = rows.filter((row) => row.change && !row.change.better);
392
+ const improved = rows.filter((row) => row.change?.better);
393
+ const bottlenecks = bottleneckLines(rows);
394
+ const checked = analysed.some((a) => a.nights >= MIN_HISTORY_NIGHTS);
395
+ const allWarnings = [...warnings, ...toolOverheadWarnings(summaries)];
231
396
 
232
397
  const executor = executorOf(summaries);
233
- const open = executor === OPEN_MODEL;
234
398
  const unit = unitFor(executor);
399
+ const date = now.toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
400
+ const ran = failed + missing === 0 ? `all ${expected} cells ran` : `${expected - failed - missing} of ${expected} cells ran`;
401
+ const verdict = [];
402
+ const crashed = crashedTiers(rows);
403
+ if (crashed.length > 0) verdict.push(`${crashed.map((tier) => tier.where).join(", ")} crashed`);
404
+ if (missing > 0) verdict.push(`${missing} never ran`);
405
+ if (jobFailed) verdict.push("job failed");
406
+ if (regressed.length > 0) verdict.push(plural(regressed.length, "regression"));
407
+ if (improved.length > 0) verdict.push(plural(improved.length, "improvement"));
408
+ if (bottlenecks.length > 0) verdict.push(plural(bottlenecks.length, "bottleneck"));
409
+ if (verdict.length === 0) verdict.push("all quiet");
410
+
411
+ const dot = dotFor({
412
+ failed: failed + missing > 0 || jobFailed,
413
+ attention: regressed.length + bottlenecks.length + allWarnings.length > 0,
414
+ });
235
415
  const lines = [
236
- `*Daily Capacity Benchmark* · ${now.toISOString().slice(0, 10)} · ${expected - missing - failed}/${expected} cells`,
237
- "*Goal:* how much load each tier serves before it breaks the SLO, and the runs/sec it delivers there. Compares tiers; not a customer workload.",
238
- `*How:* ${open ? "the offered request rate" : "the number of users"} climbs in steps of ${stepSeconds}s. A step passes at success >= ${SLO.minSuccessRate}%, p50 <= ${SLO.maxP50Ms / 1000}s, p95 <= ${SLO.maxP95Ms / 1000}s. Capacity = the top passing step, with the step below also passing.${open ? " Requests the tool had to drop count as failures." : ""}`,
239
- "*Graph:* `default`, 1 step, no LLM, 1KB checkpoint. Server overhead, not a customer workload.",
240
- `*Tests:* ${RUNNERS.map((runner) => `${runnerShortName(runner)} = ${describeRunner(runner)}`).join(" · ")}`,
241
- `*Reading a cell:* \`400 (398/s)\` held 400 ${unit} at SLO, serving 398 runs/sec · \`0 (~46/s ceiling)\` no step met SLO, best rate any step served · \`ERR\` crashed, no data · \`-\` never ran`,
242
- "*Pods:* every tier starts at one queue pod and grows during a cell, so a low number can mean few pods rather than a slow server. Pod counts and CPU peaks are listed under each table where the control plane returned them.",
416
+ `${dot} *Capacity · ${date}*${manual ? " · manual run" : ""}${apiVersion ? ` · API ${apiVersion}` : ""} · ${ran} · ${verdict.join(", ")}`,
417
+ describeCapacity(analysed, summaries, executor),
243
418
  ];
244
419
 
245
- // Say out loud when the run was not clean. Without this a run where half the
246
- // matrix never executed posts a tidy-looking table and reads as authoritative.
247
- const problems = [];
248
- if (failed > 0) problems.push(`${failed} failed`);
249
- if (missing > 0) problems.push(`${missing} never ran`);
250
- if (process.env.CAPACITY_JOB_RESULT === "failure") {
251
- problems.push("the capacity job itself failed");
420
+ const failedParts = crashed.map((tier) => tier.detail);
421
+ for (const row of rows) {
422
+ if (!row.summary) failedParts.push(`${cellName(row.deployment, row.tier, row.runner)} never ran`);
252
423
  }
253
- if (problems.length > 0) {
254
- lines.push(
255
- `:warning: ${problems.join(", ")} of ${expected} cells - treat this table as incomplete`,
256
- );
424
+ if (jobFailed) failedParts.push("the capacity job exited with failure");
425
+ if (failedParts.length > 0) {
426
+ lines.push(`*Failed:* ${failedParts.join(" · ")} · treat the table as incomplete`);
427
+ }
428
+
429
+ if (!checked) {
430
+ const nights = Math.max(...analysed.map((a) => a.nights));
431
+ lines.push(`*Regressed:* not checked, ${nights} of ${MIN_HISTORY_NIGHTS} nights of history`);
432
+ } else {
433
+ lines.push(`*Regressed:* ${regressed.length > 0 ? regressed.map((row) => moveLine(row, unit)).join(" · ") : "none"}`);
434
+ if (improved.length > 0) lines.push(`*Improved:* ${improved.map((row) => moveLine(row, unit)).join(" · ")}`);
435
+ }
436
+ lines.push(`*Bottlenecks:* ${bottlenecks.length > 0 ? bottlenecks.join(" · ") : "none reported"}`);
437
+ for (const warning of allWarnings) lines.push(`:warning: ${warning}`);
438
+
439
+ for (const { deployment, rows: deploymentRows, nights } of analysed) {
440
+ lines.push("", ...capacityTable(deployment, deploymentRows, unitFor(executorOf(deploymentRows.map((r) => r.summary).filter(Boolean)))));
441
+ if (checked && nights < MIN_HISTORY_NIGHTS) {
442
+ lines.push(`_${nights} of ${MIN_HISTORY_NIGHTS} nights of history, no change flags yet_`);
443
+ }
444
+ }
445
+
446
+ lines.push(
447
+ "",
448
+ `▲ better ▼ worse than the last ${MIN_HISTORY_NIGHTS}+ nights · \`0\` no step passed · \`ERR\` crashed · \`-\` never ran · 🟢 quiet · 🟡 regression or bottleneck · 🔴 cells failed`,
449
+ );
450
+ return lines.join("\n");
451
+ }
452
+
453
+ function describeCapacity(analysed, summaries, executor) {
454
+ const open = executor === OPEN_MODEL;
455
+ const unit = unitFor(executor);
456
+ const climb = analysed
457
+ .map(({ deployment, rows }) => {
458
+ const cells = indexCells([deployment], rows.map((r) => r.summary).filter(Boolean))[deployment.slug] ?? {};
459
+ const { start, step } = geometryOf(deployment, cells);
460
+ return `+${step} from ${start} (${deploymentName(deployment).toLowerCase()})`;
461
+ })
462
+ .join(" or ");
463
+ const where = analysed.length === 1 ? "one staging deployment" : `${analysed.length} staging deployments`;
464
+ return (
465
+ `k6 ${open ? "open-model" : "closed-model"} staircase, ${where} resized per tier: ${open ? "request rate" : "virtual users"} ${climb} every ${stepSecondsOf(summaries)} s, per path: ${RUNNERS.map(runnerGloss).join(", ")}. ` +
466
+ `Cell = highest ${unit} where success ≥ ${SLO.minSuccessRate}%, p50 ≤ ${SLO.maxP50Ms / 1000} s, p95 ≤ ${SLO.maxP95Ms / 1000} s held for two steps. ` +
467
+ "One-step graph, no LLM: server ceiling, not customer traffic."
468
+ );
469
+ }
470
+
471
+ export function howToRead() {
472
+ return [
473
+ "*How to read*",
474
+ `• *Tests:* ${RUNNERS.map((r) => `${runnerColumnName(r)} = ${describeRunnerBriefly(r)}`).join(" · ")}.`,
475
+ `• *Regressed / Improved:* a cell outside its own usual range over the last ${MIN_HISTORY_NIGHTS}+ nights measured the same way.`,
476
+ `• *Bottleneck:* a component at or over ${BOTTLENECK_CPU_PCT}% of its CPU request while the tier held its top step. It is what stops the tier going higher.`,
477
+ "• Graph is one step, no LLM, so this is server overhead, not a customer workload.",
478
+ ].join("\n");
479
+ }
480
+
481
+ function servedRate(summary) {
482
+ const rate = summary?.capacity?.successfulRunsPerSec;
483
+ if (rate != null) return String(Math.round(rate));
484
+ const ceiling = summary?.throughputCeiling?.successfulRunsPerSec;
485
+ return ceiling != null ? `0 (ceiling ${Math.round(ceiling)})` : "-";
486
+ }
487
+
488
+ function serverColumns(summaries) {
489
+ const columns = [];
490
+ for (const [label, name] of COMPONENTS) {
491
+ const groups = summaries.map((s) => s?.serverMetrics?.groups?.[label]).filter(Boolean);
492
+ if (groups.length === 0) continue;
493
+ if (groups.some(podRange)) columns.push({ label, kind: "pods", width: 7 });
494
+ if (groups.some((g) => peakCpu(g) != null)) columns.push({ label, kind: "cpu", width: 6 });
257
495
  }
258
- for (const warning of [...warnings, ...toolOverheadWarnings(summaries)]) {
259
- lines.push(`:warning: ${warning}`);
496
+ return columns;
497
+ }
498
+
499
+ function serverCell(summary, column) {
500
+ const group = summary?.serverMetrics?.groups?.[column.label];
501
+ if (column.kind === "pods") {
502
+ const range = podRange(group);
503
+ return range ? `${range.min}→${range.max}` : "-";
260
504
  }
261
- lines.push("");
505
+ const cpu = peakCpu(group);
506
+ return cpu != null ? String(Math.round(cpu)) : "-";
507
+ }
262
508
 
509
+ export function formatServerView(deployments, summaries) {
510
+ const byDeployment = indexCells(deployments, summaries);
511
+ const blocks = [];
263
512
  for (const deployment of deployments) {
264
513
  const cells = byDeployment[deployment.slug] ?? {};
265
- const geometry = ranGeometry(cells) ?? deployment.staircase ?? {};
266
- const start = Number(geometry.startLoad ?? STAIRCASE_START_LOAD);
267
- const step = Number(geometry.stepSize ?? STAIRCASE_STEP_SIZE);
268
- const steps = Number(geometry.numSteps ?? STAIRCASE_NUM_STEPS);
269
- const dedicated = deployment.tiers.some((tier) => tier.startsWith("DEDICATED_"));
270
- const cellExecutor = executorOf(Object.values(cells).flatMap((byRunner) => Object.values(byRunner)));
271
- const mode = cellExecutor === OPEN_MODEL ? "open model, fixed request rate" : "closed model, fixed users";
272
- lines.push(
273
- `*${deployment.slug}* · ${dedicated ? "compute and database resized per tier" : "compute resized per tier, one shared database tier"} · ${start} to ${start + step * (steps - 1)} ${unitFor(cellExecutor)}, +${step} per step · ${mode}`,
274
- );
275
- lines.push("```");
276
- lines.push(
277
- `${"".padEnd(16)}${RUNNERS.map((runner) => runnerShortName(runner).padEnd(20)).join("")}`,
278
- );
279
- for (const tier of deployment.tiers) {
280
- let row = tier.padEnd(16);
281
- for (const runner of RUNNERS) {
282
- const summary = cells[tier]?.[runner];
283
- row += capacityVus(summary).padEnd(20);
284
- }
285
- lines.push(row);
514
+ const present = Object.values(cells).flatMap((byRunner) => Object.values(byRunner));
515
+ if (present.length === 0) continue;
516
+ const served = deployment.tiers
517
+ .map((tier) => `${tierLabel(deployment, tier)} ${RUNNERS.map((r) => servedRate(cells[tier]?.[r])).join(" / ")}`)
518
+ .join(" · ");
519
+ const servedLine = `Runs/sec actually served at the top step, as ${RUNNERS.map(runnerColumnName).join(" / ")}: ${served}`;
520
+ // The served rate is k6's; the pod and CPU columns are the dashboard's, which is best effort.
521
+ const columns = serverColumns(present);
522
+ if (columns.length === 0) {
523
+ blocks.push(`*${deploymentName(deployment)}*\n${servedLine}`);
524
+ continue;
525
+ }
526
+ const labelWidth = Math.max(...deployment.tiers.map((t) => tierLabel(deployment, t).length)) + 8;
527
+ const spans = [];
528
+ for (const column of columns) {
529
+ const last = spans[spans.length - 1];
530
+ if (last && last.label === column.label) last.width += column.width;
531
+ else spans.push({ label: column.label, width: column.width });
286
532
  }
287
- lines.push("```");
533
+ const lines = [
534
+ `*${deploymentName(deployment)}*`,
535
+ "```",
536
+ `${"".padEnd(labelWidth)}${spans.map((s) => s.label.padStart(s.width)).join("")}`,
537
+ `${"".padEnd(labelWidth)}${columns.map((c) => c.kind.padStart(c.width)).join("")}`,
538
+ ];
288
539
  for (const tier of deployment.tiers) {
289
540
  for (const runner of RUNNERS) {
290
- const served = formatServerMetrics(cells[tier]?.[runner]?.serverMetrics);
291
- if (served) lines.push(`\`${tier} ${runnerShortName(runner)}\`: ${served}`);
292
- }
293
- }
294
- const drift = historyLine(deployment, cells, history);
295
- if (drift) lines.push(drift);
296
- lines.push("");
297
- }
298
- return lines.join("\n").trimEnd();
299
- }
300
-
301
- function historyLine(deployment, cells, history) {
302
- const moved = [];
303
- let nights = 0;
304
- for (const tier of deployment.tiers) {
305
- for (const runner of RUNNERS) {
306
- const summary = cells[tier]?.[runner];
307
- if (!summary || summary.error) continue;
308
- const executor = summary.config?.k6Executor ?? "constant-vus";
309
- // Nights measured in users and nights measured in req/s are different
310
- // scales; only the same executor is a baseline.
311
- const past = (history[cellKey({ deploymentSlug: deployment.slug, computeTier: tier, benchmarkType: runner })] ?? [])
312
- .filter((night) => (night.executor ?? "constant-vus") === executor);
313
- const verdict = compare(summary.capacity?.targetVUs ?? 0, past.map((p) => p.capacityVUs));
314
- if (!verdict) continue;
315
- nights = Math.max(nights, verdict.nights);
316
- if (verdict.outside) {
317
- moved.push(
318
- `${tier} ${runnerShortName(runner)} ${summary.capacity?.targetVUs ?? 0} vs median ${Math.round(verdict.median)} (${formatDelta(verdict.deltaPct)}, usual ±${verdict.spreadPct.toFixed(0)}%)`,
319
- );
541
+ const summary = cells[tier]?.[runner];
542
+ if (!summary?.serverMetrics) continue;
543
+ const label = `${tierLabel(deployment, tier)} ${runnerColumnName(runner)}`;
544
+ lines.push(`${label.padEnd(labelWidth)}${columns.map((c) => serverCell(summary, c).padStart(c.width)).join("")}`);
320
545
  }
321
546
  }
547
+ lines.push("```", servedLine);
548
+ blocks.push(lines.join("\n"));
322
549
  }
323
- if (nights === 0) return null;
324
- return moved.length > 0
325
- ? `*vs last ${nights} nights:* ${moved.join(" · ")}`
326
- : `*vs last ${nights} nights:* every cell within its usual range`;
550
+ if (blocks.length === 0) return null;
551
+ return [
552
+ "*Pods and CPU per cell*, peak over the whole cell including the steps that failed. Pods are start → end. CPU is % of the pod's request, so over 100 means bursting above it.",
553
+ ...blocks,
554
+ ].join("\n\n");
327
555
  }
328
556
 
329
557
  function toolOverheadWarnings(summaries) {
@@ -651,12 +879,20 @@ async function runDeploymentMatrix(deployment, apiKey) {
651
879
  return { summaryPaths, failures, warnings };
652
880
  }
653
881
 
882
+ // The steps past capacity saturate everything, so a bottleneck read over the
883
+ // whole cell names a component the tier never hit while it was passing.
654
884
  async function attachServerMetrics(deployment, apiKey, summaryPath) {
655
885
  const summary = JSON.parse(readFileSync(summaryPath, "utf8"));
656
886
  const window = cellWindow(summary.steps);
657
887
  if (!window) throw new Error("steps carry no timestamps");
658
- const section = await getDeploymentMetrics(deployment.deploymentId, apiKey, window);
659
- summary.serverMetrics = summarizeServerMetrics(section);
888
+ summary.serverMetrics = summarizeServerMetrics(
889
+ await getDeploymentMetrics(deployment.deploymentId, apiKey, window),
890
+ );
891
+ const capacityStep = summary.capacity?.step;
892
+ const held = capacityStep ? cellWindow(summary.steps.filter((s) => s.step <= capacityStep)) : null;
893
+ summary.serverMetricsAtCapacity = held
894
+ ? summarizeServerMetrics(await getDeploymentMetrics(deployment.deploymentId, apiKey, held))
895
+ : null;
660
896
  writeFileSync(summaryPath, `${JSON.stringify(summary, null, 2)}\n`);
661
897
  }
662
898
 
@@ -675,49 +911,26 @@ function collectSummaries(directory) {
675
911
  );
676
912
  }
677
913
 
678
- async function postSlack(message) {
679
- const token = process.env.SLACK_BOT_TOKEN;
680
- const channel = process.env.SLACK_CHANNEL;
681
- if (!token || !channel) {
682
- console.log(
683
- "SLACK_BOT_TOKEN or SLACK_CHANNEL not set; skipping Slack post",
684
- );
685
- console.log(message);
686
- return;
687
- }
688
-
689
- const response = await fetch("https://slack.com/api/chat.postMessage", {
690
- method: "POST",
691
- headers: {
692
- "Content-Type": "application/json; charset=utf-8",
693
- Authorization: `Bearer ${token}`,
694
- },
695
- body: JSON.stringify({ channel, text: message }),
696
- });
697
- const result = await response.json();
698
- if (!result.ok) {
699
- throw new Error(`Slack API error: ${result.error ?? "unknown"}`);
700
- }
701
- console.log("Posted aggregate summary to Slack");
702
- }
703
-
704
914
  async function runAggregate(summariesDir, { postToSlack, historyDir }) {
705
915
  const summaries = collectSummaries(summariesDir);
706
916
  const warnings = collectWarnings(summariesDir);
707
- const message = formatAggregateTable(
917
+ const history = historyDir ? loadCapacityHistory(historyDir) : {};
918
+ let text = formatAggregateTable(
708
919
  CAPACITY_DEPLOYMENTS,
709
920
  summaries,
710
921
  warnings,
711
922
  new Date(),
712
- historyDir ? loadCapacityHistory(historyDir) : {},
923
+ history,
924
+ process.env.API_VERSION || readApiVersion(),
925
+ process.env.MANUAL === "true",
713
926
  );
714
- console.log(message);
927
+ const artifactUrl = process.env.GITHUB_RUN_URL;
928
+ text += `\n*Thread:* pods and CPU per cell, and how to read${artifactUrl ? ` · <${artifactUrl}|Artifacts:> raw k6 summaries` : ""}`;
929
+ const thread = [[formatServerView(CAPACITY_DEPLOYMENTS, summaries), howToRead()].filter(Boolean).join("\n\n")];
715
930
  if (postToSlack) {
716
- const artifactUrl = process.env.GITHUB_RUN_URL;
717
- const slackMessage = artifactUrl
718
- ? `${message}\n\n<${artifactUrl}|Download artifacts>`
719
- : message;
720
- await postSlack(slackMessage);
931
+ await postReport({ text, thread });
932
+ } else {
933
+ for (const part of [text, ...thread]) console.log(`${part}\n`);
721
934
  }
722
935
  }
723
936