langgraph-api 0.14.0.dev8__tar.gz → 0.14.0.dev9__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 (298) hide show
  1. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/PKG-INFO +1 -1
  2. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/benchmark-runner.ts +1 -0
  3. langgraph_api-0.14.0.dev9/benchmark/benchmark-runners/classify-error.test.js +116 -0
  4. langgraph_api-0.14.0.dev9/benchmark/benchmark-runners/classify-error.ts +86 -0
  5. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/log-failure.ts +33 -0
  6. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/stream_write.ts +18 -13
  7. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/threads_search_metadata.ts +45 -22
  8. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/wait_write.ts +19 -12
  9. langgraph_api-0.14.0.dev9/benchmark/capacity-ci.js +658 -0
  10. langgraph_api-0.14.0.dev9/benchmark/capacity-ci.test.js +138 -0
  11. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/clean.js +61 -21
  12. langgraph_api-0.14.0.dev9/benchmark/daily-report.js +263 -0
  13. langgraph_api-0.14.0.dev9/benchmark/daily-report.test.js +242 -0
  14. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/host-v2.js +80 -10
  15. langgraph_api-0.14.0.dev9/benchmark/host-v2.test.js +108 -0
  16. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/package.json +2 -1
  17. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/ramp.js +86 -23
  18. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/staircase.py +137 -15
  19. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/staircase_step_k6.js +77 -4
  20. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/healthcheck.py +1 -1
  21. langgraph_api-0.14.0.dev9/langgraph_api/__init__.py +1 -0
  22. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/config/schemas.py +1 -1
  23. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/queue_entrypoint.py +5 -2
  24. langgraph_api-0.14.0.dev8/benchmark/capacity-ci.js +0 -332
  25. langgraph_api-0.14.0.dev8/langgraph_api/__init__.py +0 -1
  26. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/.gitignore +0 -0
  27. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/LICENSE +0 -0
  28. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/Makefile +0 -0
  29. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/README.md +0 -0
  30. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/.gitignore +0 -0
  31. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/Makefile +0 -0
  32. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/README.md +0 -0
  33. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/assistant.ts +0 -0
  34. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
  35. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/benchmarks.ts +0 -0
  36. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
  37. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
  38. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/meta_workload.ts +0 -0
  39. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/store.ts +0 -0
  40. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/thread.ts +0 -0
  41. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
  42. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/benchmark-runners/types.ts +0 -0
  43. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/clean-cli.js +0 -0
  44. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/continuous/README.md +0 -0
  45. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/continuous/pyproject.toml +0 -0
  46. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/continuous/runner.py +0 -0
  47. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/continuous/uv.lock +0 -0
  48. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/graphs.js +0 -0
  49. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/reporting/dd_reporting.py +0 -0
  50. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/tsconfig.json +0 -0
  51. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/update-revision.js +0 -0
  52. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/weather.js +0 -0
  53. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/benchmark/yarn.lock +0 -0
  54. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/constraints.txt +0 -0
  55. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/custom_store.sql +0 -0
  56. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/forbidden.txt +0 -0
  57. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/hatch_build.py +0 -0
  58. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph-cloud-debugging-20260210132856.zip +0 -0
  59. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/_checkpointer/__init__.py +0 -0
  60. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/_checkpointer/_adapter.py +0 -0
  61. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/_checkpointer/protocol.py +0 -0
  62. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/_factory_utils.py +0 -0
  63. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/__init__.py +0 -0
  64. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/a2a.py +0 -0
  65. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/assistants.py +0 -0
  66. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/event_streaming.py +0 -0
  67. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/mcp/__init__.py +0 -0
  68. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/mcp/_constants.py +0 -0
  69. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/mcp/_handlers.py +0 -0
  70. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/mcp/_models.py +0 -0
  71. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/mcp/_routes.py +0 -0
  72. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/mcp/_sanitizers.py +0 -0
  73. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/meta.py +0 -0
  74. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/openapi.py +0 -0
  75. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/profile.py +0 -0
  76. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/runs.py +0 -0
  77. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/store.py +0 -0
  78. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/threads.py +0 -0
  79. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/api/ui.py +0 -0
  80. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/asgi_transport.py +0 -0
  81. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/asyncio.py +0 -0
  82. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/__init__.py +0 -0
  83. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/custom.py +0 -0
  84. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/errors.py +0 -0
  85. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/langsmith/__init__.py +0 -0
  86. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/langsmith/backend.py +0 -0
  87. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/langsmith/client.py +0 -0
  88. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/middleware.py +0 -0
  89. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/noop.py +0 -0
  90. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/auth/studio_user.py +0 -0
  91. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
  92. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/cache.py +0 -0
  93. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/cli.py +0 -0
  94. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/command.py +0 -0
  95. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/config/__init__.py +0 -0
  96. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/config/_parse.py +0 -0
  97. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/cron_scheduler.py +0 -0
  98. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/encryption/__init__.py +0 -0
  99. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/encryption/aes_json.py +0 -0
  100. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/encryption/context.py +0 -0
  101. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/encryption/custom.py +0 -0
  102. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/encryption/middleware.py +0 -0
  103. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/encryption/shared.py +0 -0
  104. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/errors.py +0 -0
  105. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/__init__.py +0 -0
  106. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/capabilities.py +0 -0
  107. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/constants.py +0 -0
  108. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/event_normalizers.py +0 -0
  109. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/namespace.py +0 -0
  110. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/service.py +0 -0
  111. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/session.py +0 -0
  112. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/state_normalizers.py +0 -0
  113. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/event_streaming/types.py +0 -0
  114. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/feature_flags.py +0 -0
  115. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/graph.py +0 -0
  116. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/__init__.py +0 -0
  117. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/client.py +0 -0
  118. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
  119. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/ops/__init__.py +0 -0
  120. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/ops/assistants.py +0 -0
  121. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/ops/cache.py +0 -0
  122. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/ops/crons.py +0 -0
  123. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/ops/runs.py +0 -0
  124. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/ops/threads.py +0 -0
  125. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/server.py +0 -0
  126. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/servicers/__init__.py +0 -0
  127. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
  128. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/grpc/servicers/encryption.py +0 -0
  129. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/http.py +0 -0
  130. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/http_metrics.py +0 -0
  131. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/http_metrics_utils.py +0 -0
  132. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/.gitignore +0 -0
  133. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/.prettierrc +0 -0
  134. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/.yarnclean +0 -0
  135. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/__init__.py +0 -0
  136. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/base.py +0 -0
  137. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/build.mts +0 -0
  138. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/client.http.mts +0 -0
  139. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/client.mts +0 -0
  140. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/errors.py +0 -0
  141. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/global.d.ts +0 -0
  142. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/package.json +0 -0
  143. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/remote.py +0 -0
  144. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/schema.py +0 -0
  145. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/graph.mts +0 -0
  146. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/load.hooks.mjs +0 -0
  147. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/preload.mjs +0 -0
  148. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
  149. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/utils/files.mts +0 -0
  150. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/utils/importMap.mts +0 -0
  151. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  152. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/src/utils/serde.mts +0 -0
  153. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/sse.py +0 -0
  154. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/traceblock.mts +0 -0
  155. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/tsconfig.json +0 -0
  156. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/ui.py +0 -0
  157. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/js/yarn.lock +0 -0
  158. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/lc_security/__init__.py +0 -0
  159. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/lc_security/exceptions.py +0 -0
  160. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/lc_security/policy.py +0 -0
  161. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/lc_security/transport.py +0 -0
  162. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/logging.py +0 -0
  163. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/metadata.py +0 -0
  164. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/metrics_collector.py +0 -0
  165. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/metrics_otlp.py +0 -0
  166. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/middleware/__init__.py +0 -0
  167. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/middleware/ensure_store.py +0 -0
  168. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/middleware/http_logger.py +0 -0
  169. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/middleware/private_network.py +0 -0
  170. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/middleware/request_id.py +0 -0
  171. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/models/__init__.py +0 -0
  172. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/models/run.py +0 -0
  173. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/otel_context.py +0 -0
  174. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/patch.py +0 -0
  175. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/release_tags.py +0 -0
  176. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/route.py +0 -0
  177. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/schema.py +0 -0
  178. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/self_hosted_logs.py +0 -0
  179. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/self_hosted_metrics.py +0 -0
  180. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/serde.py +0 -0
  181. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/server.py +0 -0
  182. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/sse.py +0 -0
  183. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/state.py +0 -0
  184. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/store.py +0 -0
  185. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/stream.py +0 -0
  186. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/stream_v2.py +0 -0
  187. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/timing/__init__.py +0 -0
  188. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/timing/profiler.py +0 -0
  189. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/timing/timer.py +0 -0
  190. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/traceblock.py +0 -0
  191. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/tracing_session.py +0 -0
  192. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/tunneling/cloudflare.py +0 -0
  193. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/__init__.py +0 -0
  194. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/cache.py +0 -0
  195. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/config.py +0 -0
  196. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/errors.py +0 -0
  197. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/extract.py +0 -0
  198. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/future.py +0 -0
  199. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/headers.py +0 -0
  200. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/network.py +0 -0
  201. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/retriable_client.py +0 -0
  202. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/stream_codec.py +0 -0
  203. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/utils/uuids.py +0 -0
  204. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/validation.py +0 -0
  205. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/webhook.py +0 -0
  206. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_api/worker.py +0 -0
  207. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/__init__.py +0 -0
  208. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/checkpointer.py +0 -0
  209. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/__init__.py +0 -0
  210. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/_compat.py +0 -0
  211. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
  212. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/config.py +0 -0
  213. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/durability.py +0 -0
  214. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/store.py +0 -0
  215. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/struct.py +0 -0
  216. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/conversion/value.py +0 -0
  217. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/__init__.py +0 -0
  218. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
  219. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
  220. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
  221. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
  222. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/core_api_pb2.py +0 -0
  223. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/core_api_pb2.pyi +0 -0
  224. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
  225. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
  226. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
  227. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
  228. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
  229. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
  230. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
  231. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
  232. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
  233. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
  234. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
  235. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
  236. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
  237. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
  238. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
  239. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
  240. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
  241. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
  242. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
  243. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
  244. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
  245. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
  246. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
  247. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
  248. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
  249. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
  250. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
  251. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
  252. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
  253. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
  254. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
  255. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
  256. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
  257. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
  258. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
  259. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
  260. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
  261. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
  262. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
  263. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
  264. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
  265. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
  266. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
  267. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
  268. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
  269. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
  270. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
  271. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
  272. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
  273. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
  274. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/store_pb2.py +0 -0
  275. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
  276. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
  277. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
  278. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/serde.py +0 -0
  279. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_grpc_common/store.py +0 -0
  280. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_license/__init__.py +0 -0
  281. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_license/validation.py +0 -0
  282. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/__init__.py +0 -0
  283. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/checkpoint.py +0 -0
  284. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/database.py +0 -0
  285. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/lifespan.py +0 -0
  286. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/metrics.py +0 -0
  287. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/ops.py +0 -0
  288. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/queue.py +0 -0
  289. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/retry.py +0 -0
  290. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/routes.py +0 -0
  291. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/langgraph_runtime/store.py +0 -0
  292. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/logging.json +0 -0
  293. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/openapi.json +0 -0
  294. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/pyproject.toml +0 -0
  295. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/scripts/build_wheel.py +0 -0
  296. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/scripts/create_license.py +0 -0
  297. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/scripts/run_a2a_tck.py +0 -0
  298. {langgraph_api-0.14.0.dev8 → langgraph_api-0.14.0.dev9}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.14.0.dev8
3
+ Version: 0.14.0.dev9
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
@@ -3,6 +3,7 @@ import type { BenchmarkResult, BenchmarkGraphOptions } from './types.js';
3
3
  export interface ErrorMetrics {
4
4
  server_errors: { add(n: number): void };
5
5
  timeout_errors: { add(n: number): void };
6
+ connection_errors?: { add(n: number): void };
6
7
  api_errors?: { add(n: number): void };
7
8
  missing_message_errors?: { add(n: number): void };
8
9
  other_errors: { add(n: number): void };
@@ -0,0 +1,116 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ // Compiled output: the source is TypeScript, and `npm test` runs after
4
+ // `npm run build` both locally and in CI.
5
+ import { classifyError, recordError } from './dist/classify-error.js';
6
+
7
+ test('5xx is a server error', () => {
8
+ assert.equal(classifyError({ response: { status: 500 } }), 'server');
9
+ assert.equal(classifyError({ response: { status: 503 } }), 'server');
10
+ });
11
+
12
+ test('408 and timeout error strings are timeouts', () => {
13
+ assert.equal(classifyError({ response: { status: 408 } }), 'timeout');
14
+ assert.equal(
15
+ classifyError({ response: { status: 0, error: 'request timeout' } }),
16
+ 'timeout'
17
+ );
18
+ });
19
+
20
+ // The bucket that had never once been written to. A refused connection has no
21
+ // HTTP status, so every runner used to file it under something else.
22
+ test('an unreachable deployment is a connection error', () => {
23
+ assert.equal(
24
+ classifyError({ response: { status: 0, error: 'dial: connection refused' } }),
25
+ 'connection'
26
+ );
27
+ assert.equal(classifyError({ response: { status: 0 } }), 'connection');
28
+ });
29
+
30
+ test('connection beats the runner-specific fallbacks', () => {
31
+ // Before this classifier, stream_write reported exactly this case as
32
+ // missing_message and wait_write as other.
33
+ const unreachable = { status: 0, error: 'dial: connection refused' };
34
+ assert.equal(
35
+ classifyError({ response: unreachable, missingMessage: true }),
36
+ 'connection'
37
+ );
38
+ assert.equal(
39
+ classifyError({ response: unreachable, hasApiError: true }),
40
+ 'connection'
41
+ );
42
+ });
43
+
44
+ test('a 200 that came back wrong falls to the runner-specific buckets', () => {
45
+ const ok = { status: 200 };
46
+ assert.equal(classifyError({ response: ok, hasApiError: true }), 'api');
47
+ assert.equal(classifyError({ response: ok, missingMessage: true }), 'missing_message');
48
+ assert.equal(classifyError({ response: ok }), 'other');
49
+ });
50
+
51
+ test('4xx that is not 408 is not mistaken for anything else', () => {
52
+ assert.equal(classifyError({ response: { status: 422 } }), 'other');
53
+ assert.equal(classifyError({ response: { status: 404 } }), 'other');
54
+ });
55
+
56
+ test('a missing response is not reported as unreachable', () => {
57
+ // No response object at all means the runner never got that far; that is not
58
+ // evidence about the network, so it must not claim `connection`.
59
+ assert.equal(classifyError({}), 'other');
60
+ assert.equal(classifyError({ response: null, missingMessage: true }), 'missing_message');
61
+ });
62
+
63
+ // classifyError picks the bucket; recordError is what actually increments a
64
+ // counter, and it was previously untested. A mutation that unwired
65
+ // connection_errors passed the whole suite.
66
+ function spyMetrics(omit = []) {
67
+ const names = [
68
+ 'server_errors',
69
+ 'timeout_errors',
70
+ 'connection_errors',
71
+ 'api_errors',
72
+ 'missing_message_errors',
73
+ 'other_errors',
74
+ ];
75
+ const counts = {};
76
+ const metrics = {};
77
+ for (const name of names) {
78
+ counts[name] = 0;
79
+ if (!omit.includes(name)) metrics[name] = { add: (n) => (counts[name] += n) };
80
+ }
81
+ return { metrics, counts };
82
+ }
83
+
84
+ test('recordError increments the counter the bucket names', async (t) => {
85
+ const cases = [
86
+ ['server', 'server_errors'],
87
+ ['timeout', 'timeout_errors'],
88
+ ['connection', 'connection_errors'],
89
+ ['api', 'api_errors'],
90
+ ['missing_message', 'missing_message_errors'],
91
+ ['other', 'other_errors'],
92
+ ];
93
+ for (const [bucket, counter] of cases) {
94
+ await t.test(`${bucket} -> ${counter}`, () => {
95
+ const { metrics, counts } = spyMetrics();
96
+ recordError(bucket, metrics);
97
+ assert.equal(counts[counter], 1, `${bucket} did not increment ${counter}`);
98
+ const strays = Object.entries(counts).filter(([k, v]) => k !== counter && v !== 0);
99
+ assert.deepEqual(strays, [], `${bucket} also incremented ${strays.map(([k]) => k)}`);
100
+ });
101
+ }
102
+ });
103
+
104
+ test('recordError falls back to other_errors for counters the entrypoint omits', () => {
105
+ // Preserves what the runners open-coded for api_errors and
106
+ // missing_message_errors, and covers older entrypoints without connection.
107
+ for (const [bucket, counter] of [
108
+ ['connection', 'connection_errors'],
109
+ ['api', 'api_errors'],
110
+ ['missing_message', 'missing_message_errors'],
111
+ ]) {
112
+ const { metrics, counts } = spyMetrics([counter]);
113
+ recordError(bucket, metrics);
114
+ assert.equal(counts.other_errors, 1, `${bucket} did not fall back to other_errors`);
115
+ }
116
+ });
@@ -0,0 +1,86 @@
1
+ import type { ErrorMetrics } from './benchmark-runner.js';
2
+
3
+ /**
4
+ * Which error counter a failed run belongs in.
5
+ *
6
+ * `wait_write` and `stream_write` each grew their own copy of this ladder, and
7
+ * both had the same hole: neither could ever produce `connection`. That bucket
8
+ * is declared in ramp.js and staircase_step_k6.js, wired into the metrics map,
9
+ * and printed in every report - but no runner has ever written to it, so it has
10
+ * read 0 in all 32 scheduled runs on record. A refused connection has no HTTP
11
+ * status, so it fell through to `missing_message` (stream) or `other` (wait):
12
+ * "the server answered but left something out" when the truth was "the server
13
+ * never answered".
14
+ */
15
+ export type ErrorBucket =
16
+ | 'connection'
17
+ | 'timeout'
18
+ | 'server'
19
+ | 'api'
20
+ | 'missing_message'
21
+ | 'other';
22
+
23
+ /**
24
+ * Only the two fields the ladder reads. Structurally satisfied by both k6's
25
+ * RefinedResponse and our normalized HttpResponse, so runners can pass either
26
+ * without converting.
27
+ */
28
+ export interface ClassifiableResponse {
29
+ status?: number;
30
+ error?: string;
31
+ }
32
+
33
+ export interface ClassifyInput {
34
+ /** The response the run hinges on, if there was one. */
35
+ response?: ClassifiableResponse | null;
36
+ /** Runner-specific: the response body carried an `__error__` key. */
37
+ hasApiError?: boolean;
38
+ /** Runner-specific: the expected message/counter never arrived. */
39
+ missingMessage?: boolean;
40
+ }
41
+
42
+ /** k6 reports a status of 0 when no HTTP response was received at all. */
43
+ function isUnreachable(response?: ClassifiableResponse | null): boolean {
44
+ if (response == null) return false;
45
+ const status = response.status;
46
+ if (status != null && status > 0) return false;
47
+ return status === 0 || (response.error ?? '') !== '';
48
+ }
49
+
50
+ function isTimeout(response?: ClassifiableResponse | null): boolean {
51
+ if (response?.status === 408) return true;
52
+ return (response?.error ?? '').includes('timeout');
53
+ }
54
+
55
+ /**
56
+ * Order matters: a timeout is reported by k6 as an error string on a status-0
57
+ * response, so it has to be tested before the general unreachable case.
58
+ */
59
+ export function classifyError(input: ClassifyInput): ErrorBucket {
60
+ const { response, hasApiError, missingMessage } = input;
61
+ const status = response?.status;
62
+
63
+ if (status != null && status >= 500) return 'server';
64
+ if (isTimeout(response)) return 'timeout';
65
+ if (isUnreachable(response)) return 'connection';
66
+ if (hasApiError) return 'api';
67
+ if (missingMessage) return 'missing_message';
68
+ return 'other';
69
+ }
70
+
71
+ /**
72
+ * Add one to the counter for `bucket`, falling back to `other_errors` when the
73
+ * entrypoint did not supply that counter. Preserves the behaviour the runners
74
+ * open-coded for `api_errors` and `missing_message_errors`.
75
+ */
76
+ export function recordError(bucket: ErrorBucket, errorMetrics: ErrorMetrics): void {
77
+ const counters: Record<ErrorBucket, { add(n: number): void } | undefined> = {
78
+ server: errorMetrics.server_errors,
79
+ timeout: errorMetrics.timeout_errors,
80
+ connection: errorMetrics.connection_errors,
81
+ api: errorMetrics.api_errors,
82
+ missing_message: errorMetrics.missing_message_errors,
83
+ other: errorMetrics.other_errors,
84
+ };
85
+ (counters[bucket] ?? errorMetrics.other_errors).add(1);
86
+ }
@@ -4,6 +4,37 @@ export interface LogFailureOptions {
4
4
  extra?: string;
5
5
  }
6
6
 
7
+ /**
8
+ * k6's console.log is synchronous, so logging every failure throttles the load
9
+ * generator exactly when the server starts failing.
10
+ *
11
+ * Sampling is keyed on the VU rather than a counter because every k6 VU runs in
12
+ * its own JavaScript runtime, so a "first N" counter would emit N lines per VU.
13
+ * Only VU 1 logs, capped at MAX_LOGGED_SAMPLES; the error counters already
14
+ * carry the volume. BENCHMARK_VERBOSE_FAILURES=1 restores full logging.
15
+ */
16
+ const VERBOSE = __ENV.BENCHMARK_VERBOSE_FAILURES === '1';
17
+ const MAX_LOGGED_SAMPLES = Number(__ENV.BENCHMARK_FAILURE_SAMPLES || '5');
18
+ let logged = 0;
19
+ let suppressed = 0;
20
+
21
+ function shouldLog(): boolean {
22
+ if (VERBOSE) return true;
23
+ // Only VU 1 narrates. Every other VU counts silently.
24
+ if (__VU !== 1) return false;
25
+ if (logged < MAX_LOGGED_SAMPLES) {
26
+ logged++;
27
+ return true;
28
+ }
29
+ suppressed++;
30
+ if (suppressed === 1) {
31
+ console.log(
32
+ `[benchmark] further failures suppressed after ${MAX_LOGGED_SAMPLES} samples; see error counters for totals`
33
+ );
34
+ }
35
+ return false;
36
+ }
37
+
7
38
  /**
8
39
  * Log useful information when a benchmark run or validation fails.
9
40
  * Uses the consistent BenchmarkResult shape: ok, step, responses.
@@ -13,6 +44,8 @@ export function logFailure(
13
44
  result: Partial<BenchmarkResult<unknown>> | null | undefined,
14
45
  options: LogFailureOptions = {}
15
46
  ): void {
47
+ if (!shouldLog()) return;
48
+
16
49
  const parts: string[] = [`[${benchmarkType}] FAIL`];
17
50
  if (result?.ok === false) {
18
51
  parts.push('result.ok=false');
@@ -4,7 +4,8 @@ import { check } from 'k6';
4
4
  import http from 'k6/http';
5
5
  import type { BenchmarkResult, BenchmarkGraphOptions } from './types.js';
6
6
  import { parseSSE } from './types.js';
7
- import { addResponse, okResult } from './types.js';
7
+ import { addResponse, okResult, failResult } from './types.js';
8
+ import { classifyError, recordError } from './classify-error.js';
8
9
  import { logFailure } from './log-failure.js';
9
10
  import { getExpectedEvents } from './benchmark_profiles.js';
10
11
 
@@ -36,13 +37,21 @@ export class StreamWrite extends BenchmarkRunner {
36
37
  if (benchmarkGraphOptions.stateful) {
37
38
  const thread = http.post(`${baseUrl}/threads`, '{}', requestParams);
38
39
  addResponse(responses, 'create_thread', thread);
40
+ // Check before parsing. `thread.json()` on a failed create throws, and the
41
+ // throw surfaced as a generic other_error instead of the real cause.
42
+ if (thread.status !== 200) {
43
+ return failResult('create_thread', responses) as BenchmarkResult<StreamWriteData>;
44
+ }
39
45
  const threadId = (thread.json() as { thread_id: string }).thread_id;
40
46
  url = `${baseUrl}/threads/${threadId}/runs/stream`;
41
47
  }
42
48
 
43
49
  const response = http.post(url, payload, requestParams);
44
50
  addResponse(responses, 'stream', response);
45
- const events = parseSSE(response.body as string);
51
+ // Guarded: on a connection failure k6 returns a response whose body is null,
52
+ // and parseSSE would throw out of run(), discarding the responses map that
53
+ // the error classifier needs to see the failure for what it was.
54
+ const events = typeof response.body === 'string' ? parseSSE(response.body) : [];
46
55
  return okResult(responses, { events, rawResponse: response });
47
56
  }
48
57
 
@@ -75,17 +84,13 @@ export class StreamWrite extends BenchmarkRunner {
75
84
  logFailure(StreamWrite.toString(), result, {
76
85
  extra: `events.length=${events.length} expected_events=${expected_events} expected_steps=${expected_steps} hasExpectedCounter=${hasExpectedCounter}`,
77
86
  });
78
- const status = result.data?.rawResponse?.status;
79
- if (status != null && status >= 500) {
80
- errorMetrics.server_errors.add(1);
81
- } else if (status === 408) {
82
- errorMetrics.timeout_errors.add(1);
83
- } else if (!hasExpectedCounter) {
84
- if (errorMetrics.missing_message_errors) errorMetrics.missing_message_errors.add(1);
85
- else errorMetrics.other_errors.add(1);
86
- } else {
87
- errorMetrics.other_errors.add(1);
88
- }
87
+ recordError(
88
+ classifyError({
89
+ response: result.responses?.stream ?? result.responses?.create_thread ?? null,
90
+ missingMessage: !hasExpectedCounter,
91
+ }),
92
+ errorMetrics
93
+ );
89
94
  }
90
95
  return success;
91
96
  }
@@ -12,6 +12,18 @@ interface ThreadsSearchMetadataData {
12
12
  found: Array<{ thread_id: string; metadata?: { scenario?: string; tag?: string } }>;
13
13
  }
14
14
 
15
+ /**
16
+ * Delete the threads each iteration creates, or leave them to accumulate.
17
+ *
18
+ * Off by default: letting the table grow is how this benchmark shows whether
19
+ * search degrades as thread count rises, and it is the realistic case since
20
+ * deployments do not delete threads per request.
21
+ *
22
+ * The capacity staircase turns it on, because there the table grows *while*
23
+ * load is ramping, so a slower step cannot be attributed to load or to size.
24
+ */
25
+ const DELETE_THREADS = __ENV.DELETE_THREADS === '1';
26
+
15
27
  export class ThreadsSearchMetadata extends BenchmarkRunner {
16
28
  static run(
17
29
  baseUrl: string,
@@ -23,33 +35,44 @@ export class ThreadsSearchMetadata extends BenchmarkRunner {
23
35
  const responses: Record<string, import('./types.js').HttpResponse> = {};
24
36
 
25
37
  const threadIds: string[] = [];
26
- for (let i = 0; i < 2; i++) {
27
- const createRes = http.post(`${baseUrl}/threads`, '{}', requestParams);
28
- addResponse(responses, `create_thread_${i}`, createRes);
29
- if (createRes.status !== 200) {
30
- return failResult(`create_thread_${i}`, responses) as BenchmarkResult<ThreadsSearchMetadataData>;
38
+ try {
39
+ for (let i = 0; i < 2; i++) {
40
+ const createRes = http.post(`${baseUrl}/threads`, '{}', requestParams);
41
+ addResponse(responses, `create_thread_${i}`, createRes);
42
+ if (createRes.status !== 200) {
43
+ return failResult(`create_thread_${i}`, responses) as BenchmarkResult<ThreadsSearchMetadataData>;
44
+ }
45
+ threadIds.push((createRes.json() as { thread_id: string }).thread_id);
31
46
  }
32
- threadIds.push((createRes.json() as { thread_id: string }).thread_id);
33
- }
34
47
 
35
- for (let i = 0; i < 2; i++) {
36
- const patchPayload = JSON.stringify({ metadata: { ...searchMetadata, index: i } });
37
- const patchRes = http.patch(`${baseUrl}/threads/${threadIds[i]}`, patchPayload, requestParams);
38
- addResponse(responses, `patch_thread_${i}`, patchRes);
39
- if (patchRes.status !== 200) {
40
- return failResult(`patch_thread_${i}`, responses) as BenchmarkResult<ThreadsSearchMetadataData>;
48
+ for (let i = 0; i < 2; i++) {
49
+ const patchPayload = JSON.stringify({ metadata: { ...searchMetadata, index: i } });
50
+ const patchRes = http.patch(`${baseUrl}/threads/${threadIds[i]}`, patchPayload, requestParams);
51
+ addResponse(responses, `patch_thread_${i}`, patchRes);
52
+ if (patchRes.status !== 200) {
53
+ return failResult(`patch_thread_${i}`, responses) as BenchmarkResult<ThreadsSearchMetadataData>;
54
+ }
41
55
  }
42
- }
43
56
 
44
- const searchPayload = JSON.stringify({ metadata: searchMetadata, limit: 10 });
45
- const searchRes = http.post(`${baseUrl}/threads/search`, searchPayload, requestParams);
46
- addResponse(responses, 'search', searchRes);
47
- if (searchRes.status !== 200) {
48
- return failResult(undefined, responses) as BenchmarkResult<ThreadsSearchMetadataData>;
49
- }
50
- const found = searchRes.json() as ThreadsSearchMetadataData['found'];
57
+ const searchPayload = JSON.stringify({ metadata: searchMetadata, limit: 10 });
58
+ const searchRes = http.post(`${baseUrl}/threads/search`, searchPayload, requestParams);
59
+ addResponse(responses, 'search', searchRes);
60
+ if (searchRes.status !== 200) {
61
+ return failResult(undefined, responses) as BenchmarkResult<ThreadsSearchMetadataData>;
62
+ }
63
+ const found = searchRes.json() as ThreadsSearchMetadataData['found'];
51
64
 
52
- return okResult(responses, { threadIds, searchMetadata, found });
65
+ return okResult(responses, { threadIds, searchMetadata, found });
66
+ } finally {
67
+ // Best effort: a failed delete leaks one thread, which the inter-cell
68
+ // reset and the deployment's thread TTL both clean up behind us. Failing
69
+ // the iteration over cleanup would misreport the workload under test.
70
+ if (DELETE_THREADS) {
71
+ for (const threadId of threadIds) {
72
+ http.del(`${baseUrl}/threads/${threadId}`, null, requestParams);
73
+ }
74
+ }
75
+ }
53
76
  }
54
77
 
55
78
  static validate(
@@ -3,7 +3,8 @@ import type { ErrorMetrics } from './benchmark-runner.js';
3
3
  import { check } from 'k6';
4
4
  import http from 'k6/http';
5
5
  import type { BenchmarkResult, BenchmarkGraphOptions } from './types.js';
6
- import { addResponse, okResult } from './types.js';
6
+ import { addResponse, okResult, failResult } from './types.js';
7
+ import { classifyError, recordError } from './classify-error.js';
7
8
  import { logFailure } from './log-failure.js';
8
9
 
9
10
  interface WaitWriteData {
@@ -19,6 +20,7 @@ export class WaitWrite extends BenchmarkRunner {
19
20
  const context = benchmarkGraphOptions.context;
20
21
  const expand = context.expand;
21
22
  const steps = context.steps;
23
+ const responses: Record<string, import('./types.js').HttpResponse> = {};
22
24
  let url = `${baseUrl}/runs/wait`;
23
25
  const payload = JSON.stringify({
24
26
  assistant_id: benchmarkGraphOptions.graph_id,
@@ -29,12 +31,17 @@ export class WaitWrite extends BenchmarkRunner {
29
31
 
30
32
  if (benchmarkGraphOptions.stateful) {
31
33
  const thread = http.post(`${baseUrl}/threads`, '{}', requestParams);
34
+ addResponse(responses, 'create_thread', thread);
35
+ // Check before parsing. `thread.json()` on a failed create throws, and the
36
+ // throw surfaced as a generic other_error instead of the real cause.
37
+ if (thread.status !== 200) {
38
+ return failResult('create_thread', responses) as BenchmarkResult<WaitWriteData>;
39
+ }
32
40
  const threadId = (thread.json() as { thread_id: string }).thread_id;
33
41
  url = `${baseUrl}/threads/${threadId}/runs/wait`;
34
42
  }
35
43
 
36
44
  const response = http.post(url, payload, requestParams);
37
- const responses: Record<string, import('./types.js').HttpResponse> = {};
38
45
  addResponse(responses, 'wait', response);
39
46
  return okResult(responses, { rawResponse: response });
40
47
  }
@@ -76,16 +83,16 @@ export class WaitWrite extends BenchmarkRunner {
76
83
 
77
84
  if (!success) {
78
85
  logFailure(WaitWrite.toString(), result, { extra: `status=${res?.status}` });
79
- if (res?.status != null && res.status >= 500) {
80
- errorMetrics.server_errors.add(1);
81
- } else if (res?.status === 408 || (res as { error?: string }).error?.includes('timeout')) {
82
- errorMetrics.timeout_errors.add(1);
83
- } else if (json && typeof json === 'object' && (json as Record<string, unknown>).__error__) {
84
- if (errorMetrics.api_errors) errorMetrics.api_errors.add(1);
85
- else errorMetrics.other_errors.add(1);
86
- } else {
87
- errorMetrics.other_errors.add(1);
88
- }
86
+ recordError(
87
+ classifyError({
88
+ response: res ?? result.responses?.create_thread ?? null,
89
+ hasApiError:
90
+ !!json &&
91
+ typeof json === 'object' &&
92
+ (json as Record<string, unknown>).__error__ !== undefined,
93
+ }),
94
+ errorMetrics
95
+ );
89
96
  }
90
97
  return success;
91
98
  }