langgraph-api 0.18.0.dev3__tar.gz → 0.18.0.dev4__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 (331) hide show
  1. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/PKG-INFO +1 -1
  2. langgraph_api-0.18.0.dev4/langgraph_api/__init__.py +1 -0
  3. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/event_streaming.py +71 -7
  4. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/config/__init__.py +2 -4
  5. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/drain.py +64 -2
  6. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/service.py +75 -129
  7. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/session.py +11 -6
  8. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/ops/threads.py +54 -6
  9. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/models/run.py +7 -0
  10. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/headers.py +5 -0
  11. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/validation.py +6 -6
  12. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/openapi.json +20 -0
  13. langgraph_api-0.18.0.dev3/langgraph_api/__init__.py +0 -1
  14. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/.gitignore +0 -0
  15. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/LICENSE +0 -0
  16. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/Makefile +0 -0
  17. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/README.md +0 -0
  18. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/.gitignore +0 -0
  19. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/Makefile +0 -0
  20. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/README.md +0 -0
  21. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/REPORTS.md +0 -0
  22. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/assistant.ts +0 -0
  23. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
  24. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
  25. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/benchmarks.ts +0 -0
  26. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
  27. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/classify-error.test.js +0 -0
  28. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/classify-error.ts +0 -0
  29. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/delta-turns-lib.test.js +0 -0
  30. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/delta-turns-lib.ts +0 -0
  31. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/delta_turns.ts +0 -0
  32. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
  33. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
  34. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/log-failure.ts +0 -0
  35. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/meta_workload.ts +0 -0
  36. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/store.ts +0 -0
  37. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/stream_write.ts +0 -0
  38. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/thread.ts +0 -0
  39. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
  40. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
  41. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/types.ts +0 -0
  42. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/benchmark-runners/wait_write.ts +0 -0
  43. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/capacity-ci.js +0 -0
  44. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/capacity-ci.test.js +0 -0
  45. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/clean-cli.js +0 -0
  46. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/clean.js +0 -0
  47. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/continuous/README.md +0 -0
  48. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/continuous/pyproject.toml +0 -0
  49. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/continuous/runner.py +0 -0
  50. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/continuous/uv.lock +0 -0
  51. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/daily-report.js +0 -0
  52. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/daily-report.test.js +0 -0
  53. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/delta-report.js +0 -0
  54. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/delta-report.test.js +0 -0
  55. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/graphs.js +0 -0
  56. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/history.js +0 -0
  57. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/history.test.js +0 -0
  58. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/host-v2.js +0 -0
  59. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/host-v2.test.js +0 -0
  60. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/multer.test.js +0 -0
  61. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/package.json +0 -0
  62. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/ramp.js +0 -0
  63. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/reporting/dd_reporting.py +0 -0
  64. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/runner-descriptions.js +0 -0
  65. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/server-metrics.js +0 -0
  66. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/server-metrics.test.js +0 -0
  67. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/slack.js +0 -0
  68. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/staircase.py +0 -0
  69. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/staircase_step_k6.js +0 -0
  70. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/tsconfig.json +0 -0
  71. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/update-revision.js +0 -0
  72. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/weather.js +0 -0
  73. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/benchmark/yarn.lock +0 -0
  74. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/constraints.txt +0 -0
  75. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/custom_store.sql +0 -0
  76. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/forbidden.txt +0 -0
  77. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/hatch_build.py +0 -0
  78. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/healthcheck.py +0 -0
  79. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph-cloud-debugging-20260210132856.zip +0 -0
  80. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/_checkpointer/__init__.py +0 -0
  81. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/_checkpointer/_adapter.py +0 -0
  82. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/_checkpointer/protocol.py +0 -0
  83. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/_factory_utils.py +0 -0
  84. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/__init__.py +0 -0
  85. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/a2a.py +0 -0
  86. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/a2ui.py +0 -0
  87. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/a2ui_schemas/README.md +0 -0
  88. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
  89. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
  90. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
  91. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
  92. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/assistants.py +0 -0
  93. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/__init__.py +0 -0
  94. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_calls.py +0 -0
  95. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_constants.py +0 -0
  96. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_handlers.py +0 -0
  97. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_models.py +0 -0
  98. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_outcome.py +0 -0
  99. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_protocol.py +0 -0
  100. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_routes.py +0 -0
  101. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/mcp/_sanitizers.py +0 -0
  102. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/meta.py +0 -0
  103. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/openapi.py +0 -0
  104. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/profile.py +0 -0
  105. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/runs.py +0 -0
  106. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/store.py +0 -0
  107. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/threads.py +0 -0
  108. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/api/ui.py +0 -0
  109. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/asgi_transport.py +0 -0
  110. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/asyncio.py +0 -0
  111. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/__init__.py +0 -0
  112. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/custom.py +0 -0
  113. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/errors.py +0 -0
  114. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/langsmith/__init__.py +0 -0
  115. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/langsmith/backend.py +0 -0
  116. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/langsmith/client.py +0 -0
  117. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/middleware.py +0 -0
  118. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/noop.py +0 -0
  119. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/auth/studio_user.py +0 -0
  120. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
  121. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/cache.py +0 -0
  122. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/cli.py +0 -0
  123. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/command.py +0 -0
  124. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/config/_parse.py +0 -0
  125. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/config/schemas.py +0 -0
  126. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/cron_scheduler.py +0 -0
  127. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/encryption/__init__.py +0 -0
  128. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/encryption/aes_json.py +0 -0
  129. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/encryption/context.py +0 -0
  130. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/encryption/custom.py +0 -0
  131. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/encryption/middleware.py +0 -0
  132. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/encryption/shared.py +0 -0
  133. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/errors.py +0 -0
  134. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/__init__.py +0 -0
  135. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/capabilities.py +0 -0
  136. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/constants.py +0 -0
  137. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/event_normalizers.py +0 -0
  138. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/namespace.py +0 -0
  139. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/state_normalizers.py +0 -0
  140. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/event_streaming/types.py +0 -0
  141. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/executor/__init__.py +0 -0
  142. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/executor/__main__.py +0 -0
  143. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/feature_flags.py +0 -0
  144. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/graph.py +0 -0
  145. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/__init__.py +0 -0
  146. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/client.py +0 -0
  147. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
  148. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/ops/__init__.py +0 -0
  149. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/ops/assistants.py +0 -0
  150. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/ops/cache.py +0 -0
  151. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/ops/crons.py +0 -0
  152. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/ops/runs.py +0 -0
  153. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/server.py +0 -0
  154. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/servicers/__init__.py +0 -0
  155. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
  156. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/grpc/servicers/encryption.py +0 -0
  157. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/http.py +0 -0
  158. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/http_metrics.py +0 -0
  159. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/http_metrics_utils.py +0 -0
  160. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/.gitignore +0 -0
  161. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/.prettierrc +0 -0
  162. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/.yarnclean +0 -0
  163. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/__init__.py +0 -0
  164. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/base.py +0 -0
  165. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/build.mts +0 -0
  166. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/client.http.mts +0 -0
  167. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/client.mts +0 -0
  168. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/errors.py +0 -0
  169. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/global.d.ts +0 -0
  170. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/package.json +0 -0
  171. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/remote.py +0 -0
  172. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/schema.py +0 -0
  173. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/auth-mutations.mts +0 -0
  174. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/graph.mts +0 -0
  175. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/load.hooks.mjs +0 -0
  176. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/preload.mjs +0 -0
  177. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
  178. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/utils/files.mts +0 -0
  179. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/utils/importMap.mts +0 -0
  180. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  181. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/src/utils/serde.mts +0 -0
  182. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/sse.py +0 -0
  183. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/traceblock.mts +0 -0
  184. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/tsconfig.json +0 -0
  185. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/ui.py +0 -0
  186. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/js/yarn.lock +0 -0
  187. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/lc_security/__init__.py +0 -0
  188. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/lc_security/exceptions.py +0 -0
  189. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/lc_security/policy.py +0 -0
  190. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/lc_security/transport.py +0 -0
  191. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/logging.py +0 -0
  192. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/metadata.py +0 -0
  193. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/metrics_collector.py +0 -0
  194. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/metrics_otlp.py +0 -0
  195. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/middleware/__init__.py +0 -0
  196. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/middleware/ensure_store.py +0 -0
  197. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/middleware/http_logger.py +0 -0
  198. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/middleware/private_network.py +0 -0
  199. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/middleware/request_id.py +0 -0
  200. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/models/__init__.py +0 -0
  201. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/otel_context.py +0 -0
  202. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/patch.py +0 -0
  203. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/queue_entrypoint.py +0 -0
  204. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/release_tags.py +0 -0
  205. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/route.py +0 -0
  206. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/schema.py +0 -0
  207. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/self_hosted_logs.py +0 -0
  208. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/self_hosted_metrics.py +0 -0
  209. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/serde.py +0 -0
  210. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/server.py +0 -0
  211. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/sse.py +0 -0
  212. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/state.py +0 -0
  213. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/store.py +0 -0
  214. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/stream.py +0 -0
  215. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/stream_v2.py +0 -0
  216. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/timing/__init__.py +0 -0
  217. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/timing/profiler.py +0 -0
  218. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/timing/startup.py +0 -0
  219. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/timing/timer.py +0 -0
  220. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/traceblock.py +0 -0
  221. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/tracing_session.py +0 -0
  222. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/tunneling/cloudflare.py +0 -0
  223. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/__init__.py +0 -0
  224. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/cache.py +0 -0
  225. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/config.py +0 -0
  226. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/errors.py +0 -0
  227. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/extract.py +0 -0
  228. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/future.py +0 -0
  229. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/network.py +0 -0
  230. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/retriable_client.py +0 -0
  231. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/stream_codec.py +0 -0
  232. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/utils/uuids.py +0 -0
  233. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/webhook.py +0 -0
  234. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/worker.py +0 -0
  235. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_api/worker_runtime.py +0 -0
  236. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/__init__.py +0 -0
  237. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/checkpointer.py +0 -0
  238. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/__init__.py +0 -0
  239. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/_compat.py +0 -0
  240. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
  241. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/config.py +0 -0
  242. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/durability.py +0 -0
  243. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/store.py +0 -0
  244. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/struct.py +0 -0
  245. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/conversion/value.py +0 -0
  246. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/__init__.py +0 -0
  247. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
  248. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
  249. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
  250. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
  251. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/core_api_pb2.py +0 -0
  252. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/core_api_pb2.pyi +0 -0
  253. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
  254. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
  255. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
  256. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
  257. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
  258. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
  259. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
  260. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
  261. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
  262. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
  263. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
  264. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
  265. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
  266. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
  267. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
  268. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
  269. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
  270. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
  271. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
  272. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
  273. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
  274. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
  275. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
  276. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
  277. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
  278. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
  279. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
  280. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
  281. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
  282. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
  283. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
  284. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
  285. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
  286. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
  287. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
  288. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
  289. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
  290. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
  291. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
  292. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
  293. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
  294. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
  295. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
  296. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
  297. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
  298. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
  299. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
  300. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
  301. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
  302. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
  303. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/orchestrator_pb2.py +0 -0
  304. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/orchestrator_pb2.pyi +0 -0
  305. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.py +0 -0
  306. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.pyi +0 -0
  307. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/store_pb2.py +0 -0
  308. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
  309. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
  310. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
  311. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/serde.py +0 -0
  312. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_grpc_common/store.py +0 -0
  313. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_license/__init__.py +0 -0
  314. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_license/validation.py +0 -0
  315. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/__init__.py +0 -0
  316. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/checkpoint.py +0 -0
  317. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/database.py +0 -0
  318. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/encryption.py +0 -0
  319. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/lifespan.py +0 -0
  320. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/metrics.py +0 -0
  321. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/ops.py +0 -0
  322. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/queue.py +0 -0
  323. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/retry.py +0 -0
  324. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/routes.py +0 -0
  325. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/langgraph_runtime/store.py +0 -0
  326. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/logging.json +0 -0
  327. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/pyproject.toml +0 -0
  328. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/scripts/build_wheel.py +0 -0
  329. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/scripts/create_license.py +0 -0
  330. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/scripts/run_a2a_tck.py +0 -0
  331. {langgraph_api-0.18.0.dev3 → langgraph_api-0.18.0.dev4}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.18.0.dev3
3
+ Version: 0.18.0.dev4
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
@@ -0,0 +1 @@
1
+ __version__ = "0.18.0.dev4"
@@ -28,6 +28,7 @@ from uuid import uuid4
28
28
 
29
29
  import orjson
30
30
  import structlog
31
+ from starlette.exceptions import HTTPException
31
32
  from starlette.responses import Response
32
33
  from starlette.websockets import WebSocketDisconnect
33
34
 
@@ -38,6 +39,7 @@ from langgraph_api.feature_flags import IS_POSTGRES_OR_GRPC_BACKEND
38
39
  from langgraph_api.route import ApiRoute, ApiWebSocketRoute
39
40
  from langgraph_api.serde import json_dumpb
40
41
  from langgraph_api.sse import EventSourceResponse
42
+ from langgraph_api.utils import validate_uuid
41
43
 
42
44
  if TYPE_CHECKING:
43
45
  from collections.abc import Mapping
@@ -98,6 +100,7 @@ def _make_manager(
98
100
  send_event: Any = None,
99
101
  *,
100
102
  headers: Mapping[str, str] | None = None,
103
+ replay_buffer: bool = True,
101
104
  ) -> ThreadRunManager:
102
105
  # Auth context is propagated via ``ApiRoute``'s ``with_user`` wrapper
103
106
  # — ops reads it off the context var, so we don't thread it through
@@ -108,6 +111,7 @@ def _make_manager(
108
111
  threads=Threads,
109
112
  send_event=send_event,
110
113
  headers=headers,
114
+ replay_buffer=replay_buffer,
111
115
  )
112
116
 
113
117
 
@@ -143,8 +147,12 @@ async def _thread_events(request: Request) -> Response:
143
147
  If reading the thread's event stream fails, the server ends the
144
148
  stream with a final ``event: error`` frame carrying a protocol error
145
149
  (``"type": "error"``, ``"id": null``, ``"error": "unknown_error"``).
150
+
151
+ A thread the caller isn't allowed to read returns 403 or 404 before
152
+ the stream starts, and a malformed thread ID returns 422.
146
153
  """
147
154
  thread_id = request.path_params["thread_id"]
155
+ thread_uuid = validate_uuid(thread_id, "Invalid thread ID: must be a UUID")
148
156
  try:
149
157
  body = orjson.loads(await request.body())
150
158
  except Exception:
@@ -217,6 +225,10 @@ async def _thread_events(request: Request) -> Response:
217
225
  else None
218
226
  )
219
227
 
228
+ # Checked here, before the 200, because clients retry a 200 that ends in
229
+ # an error instead of giving up.
230
+ auth_filters = await Threads.Stream.check_thread_stream_auth(thread_uuid)
231
+
220
232
  # Bounded LRU dedup: ``recent_eids`` is the eviction order, ``delivered``
221
233
  # is the O(1) membership view. When the deque hits its cap, the oldest
222
234
  # entry rolls off; we mirror that on ``delivered`` to keep them in sync.
@@ -241,7 +253,10 @@ async def _thread_events(request: Request) -> Response:
241
253
  pending_events.append(event)
242
254
  flush_pending.set()
243
255
 
244
- manager = _make_manager(thread_id, send_event=on_event)
256
+ # SSE never replays from the session's buffer: it has no subscribe or
257
+ # reconnect commands, and ``start_thread_stream`` replays from the
258
+ # thread's event stream.
259
+ manager = _make_manager(thread_id, send_event=on_event, replay_buffer=False)
245
260
 
246
261
  filter_sub = Subscription(
247
262
  id=str(uuid4()),
@@ -264,7 +279,7 @@ async def _thread_events(request: Request) -> Response:
264
279
  # outbound events; the thread-level reader always replays from the
265
280
  # beginning so namespace-scoped projections see history. See
266
281
  # ``ThreadRunManager.start_thread_stream`` for the rationale.
267
- manager.start_thread_stream()
282
+ manager.start_thread_stream(auth_filters=auth_filters)
268
283
 
269
284
  async def body_iter():
270
285
  try:
@@ -377,20 +392,51 @@ async def _thread_command(request: Request) -> Response:
377
392
  # ---------------------------------------------------------------------------
378
393
 
379
394
 
395
+ async def _close_for_failed_access_check(websocket: WebSocket, exc: Exception) -> None:
396
+ if isinstance(exc, HTTPException) and exc.status_code < 500:
397
+ await websocket.close(code=4000 + exc.status_code)
398
+ return
399
+ logger.exception("Thread stream access check failed")
400
+ await websocket.send_text(_THREAD_STREAM_FAILED_DATA.decode())
401
+ await websocket.close(code=1011, reason="thread stream ended")
402
+
403
+
380
404
  async def _thread_websocket(websocket: WebSocket) -> None:
381
405
  """Full-duplex protocol connection scoped to a thread.
382
406
 
383
407
  Supports ``run.start``, ``input.respond``, ``subscription.subscribe``,
384
408
  ``subscription.unsubscribe``, ``agent.getTree``.
409
+
410
+ A 4xx from the thread's access check closes the socket with 4000 plus the
411
+ status (4403, 4422). A 404 can be a thread the client minted and has yet
412
+ to create, so the socket then waits for a ``run.start``, which checks
413
+ access like any run start, and closes with 4404 if another command comes
414
+ first. Any other failure of the check, a 5xx included, gets the stream
415
+ error frame and a 1011 close, as when the stream fails later.
385
416
  """
386
417
  thread_id = websocket.path_params["thread_id"]
418
+ # Browsers report a refused upgrade only as a 1006 close, so accept first
419
+ # to make the close code readable.
387
420
  await websocket.accept()
421
+ try:
422
+ thread_uuid = validate_uuid(thread_id, "Invalid thread ID: must be a UUID")
423
+ except HTTPException as exc:
424
+ await _close_for_failed_access_check(websocket, exc)
425
+ return
426
+ awaiting_thread = False
427
+ auth_filters: Any = None
428
+ try:
429
+ auth_filters = await Threads.Stream.check_thread_stream_auth(thread_uuid)
430
+ except Exception as exc:
431
+ if not (isinstance(exc, HTTPException) and exc.status_code == 404):
432
+ await _close_for_failed_access_check(websocket, exc)
433
+ return
434
+ awaiting_thread = True
388
435
 
389
436
  async def ws_send_event(event: dict[str, Any]) -> None:
390
437
  await websocket.send_text(orjson.dumps(event).decode("utf-8"))
391
438
 
392
439
  manager = _make_manager(thread_id, send_event=ws_send_event)
393
- manager.start_thread_stream()
394
440
 
395
441
  # Watchdog: when the thread-stream consumer stops, send the error frame
396
442
  # (if it wasn't cancelled) and close the socket, instead of leaving the
@@ -405,7 +451,11 @@ async def _thread_websocket(websocket: WebSocket) -> None:
405
451
  with contextlib.suppress(Exception):
406
452
  await websocket.close(code=1011, reason="thread stream ended")
407
453
 
408
- watchdog = asyncio.create_task(_stream_watchdog())
454
+ def start_stream(filters: Any) -> asyncio.Task[None]:
455
+ manager.start_thread_stream(auth_filters=filters)
456
+ return asyncio.create_task(_stream_watchdog())
457
+
458
+ watchdog = None if awaiting_thread else start_stream(auth_filters)
409
459
 
410
460
  try:
411
461
  while True:
@@ -438,16 +488,30 @@ async def _thread_websocket(websocket: WebSocket) -> None:
438
488
  )
439
489
  continue
440
490
 
491
+ if awaiting_thread and payload["method"] != "run.start":
492
+ await websocket.close(code=4404)
493
+ return
441
494
  response = await manager.handle_command(payload)
442
495
  await websocket.send_text(orjson.dumps(response).decode("utf-8"))
496
+ if awaiting_thread and response.get("type") == "success":
497
+ try:
498
+ auth_filters = await Threads.Stream.check_thread_stream_auth(
499
+ thread_uuid
500
+ )
501
+ except Exception as exc:
502
+ await _close_for_failed_access_check(websocket, exc)
503
+ return
504
+ watchdog = start_stream(auth_filters)
505
+ awaiting_thread = False
443
506
  except WebSocketDisconnect:
444
507
  pass
445
508
  except Exception:
446
509
  logger.exception("Protocol WebSocket error")
447
510
  finally:
448
- watchdog.cancel()
449
- with contextlib.suppress(asyncio.CancelledError, Exception):
450
- await watchdog
511
+ if watchdog is not None:
512
+ watchdog.cancel()
513
+ with contextlib.suppress(asyncio.CancelledError, Exception):
514
+ await watchdog
451
515
  await manager.close()
452
516
 
453
517
 
@@ -507,7 +507,8 @@ FF_CRONS_ENABLED = env("FF_CRONS_ENABLED", cast=bool, default=True)
507
507
  FF_LOG_DROPPED_EVENTS = env("FF_LOG_DROPPED_EVENTS", cast=bool, default=False)
508
508
  FF_LOG_QUERY_AND_PARAMS = env("FF_LOG_QUERY_AND_PARAMS", cast=bool, default=False)
509
509
  # Opt-in handling of drained runs: the server's control signalling to the
510
- # graph and its handling of drained runs, together.
510
+ # graph and its handling of drained runs, together. On, a Postgres-backed
511
+ # replica that is shutting down also drains its in-flight runs.
511
512
  # Off: no control is created or seeded, and GraphDrained lands in the
512
513
  # catch-all error branch.
513
514
  FF_RESUME_DRAINED_RUNS = env("FF_RESUME_DRAINED_RUNS", cast=bool, default=False)
@@ -535,8 +536,6 @@ RESUME_DRAINED_RUNS = _resolve_resume_drained_runs(
535
536
  is_postgres=IS_POSTGRES_BACKEND,
536
537
  langgraph_supported=DRAIN_RESUME_SUPPORT,
537
538
  )
538
- # Not in public docs: internal feature flag
539
- FF_USE_REDIS_QUEUE = env("FF_USE_REDIS_QUEUE", cast=bool, default=True)
540
539
 
541
540
 
542
541
  # Internal flag intended for testing only
@@ -811,7 +810,6 @@ __all__ = [
811
810
  "FF_PYSPY_PROFILING_ENABLED",
812
811
  "FF_PYSPY_PROFILING_MAX_DURATION_SECS",
813
812
  "FF_RESUME_DRAINED_RUNS",
814
- "FF_USE_REDIS_QUEUE",
815
813
  "GRPC_CLIENT_HTTP2_INITIAL_WINDOW_SIZE",
816
814
  "GRPC_CLIENT_MAX_RECV_MSG_BYTES",
817
815
  "GRPC_CLIENT_MAX_SEND_MSG_BYTES",
@@ -10,6 +10,7 @@ guarded and the placeholders below never match or instantiate anything.
10
10
  from __future__ import annotations
11
11
 
12
12
  import contextvars
13
+ import threading
13
14
  from typing import Any
14
15
 
15
16
  # The control of the run whose top-level graph this context is executing. The
@@ -47,17 +48,35 @@ try:
47
48
  The request is visible only where this is provably the run's top-level
48
49
  loop: in a context the server marked for this control (see
49
50
  mark_top_level) and outside any graph node. So the run drains only at
50
- a top-level step boundary, after that step's subgraphs have finished.
51
+ a top-level step boundary, after that step's subgraphs have finished,
52
+ and never before its first step.
51
53
  Graph code inside a node, and threads a node starts, see no drain
52
54
  (drain_requested False, drain_reason None).
53
55
  """
54
56
 
57
+ __slots__ = ("_first_check_done",)
58
+
59
+ def __init__(self) -> None:
60
+ super().__init__()
61
+ self._first_check_done = False
62
+
55
63
  def _visible(self) -> bool:
56
64
  return _TOP_LEVEL_CONTROL.get() is self and not _in_graph_node()
57
65
 
58
66
  @property
59
67
  def drain_requested(self) -> bool:
60
- return self._visible() and RunControl.drain_requested.fget(self)
68
+ if not self._visible():
69
+ return False
70
+ # LangGraph checks once per top-level step boundary, before the
71
+ # step. Only a server drain can be pending at the first check. A
72
+ # run started with a Command has no checkpoint of its own until its
73
+ # first step ends, so if it drained there, its next claim would
74
+ # re-send the Command and LangGraph would apply it again. So a run
75
+ # always completes a step before it drains.
76
+ if not self._first_check_done:
77
+ self._first_check_done = True
78
+ return False
79
+ return RunControl.drain_requested.fget(self)
61
80
 
62
81
  @property
63
82
  def drain_reason(self) -> str | None:
@@ -79,6 +98,11 @@ except ImportError:
79
98
 
80
99
  DRAIN_SUPPORT = False
81
100
 
101
+ # Reason the server passes to request_drain() when its pod is shutting down.
102
+ # Graph code can pass any reason (request_drain() defaults to "shutdown"), so
103
+ # this distinct value is what tells server drains from graph drains in logs.
104
+ SERVER_SHUTDOWN_DRAIN_REASON = "server_shutdown"
105
+
82
106
 
83
107
  def mark_top_level(control: ServerRunControl | None) -> None:
84
108
  """Mark the current context as running ``control``'s top-level graph."""
@@ -92,10 +116,48 @@ def new_run_control() -> ServerRunControl | None:
92
116
  return None
93
117
 
94
118
 
119
+ class RunControlRegistry:
120
+ """Controls of the runs a queue drains at shutdown, keyed by run ID.
121
+
122
+ Workers can finish on background threads (isolated loops), so every access
123
+ takes a lock and ``drain_all`` works on a snapshot. Controls are registered
124
+ before the run starts, and removed only by the claim that registered them,
125
+ so a fast-finishing or superseded claim can't leave or remove the wrong
126
+ entry.
127
+ """
128
+
129
+ def __init__(self) -> None:
130
+ self._lock = threading.Lock()
131
+ self._controls: dict[str, ServerRunControl] = {}
132
+
133
+ def add(self, run_id: Any, control: ServerRunControl) -> None:
134
+ """Register a run's control before the run starts."""
135
+ with self._lock:
136
+ self._controls[str(run_id)] = control
137
+
138
+ def release(self, run_id: Any, control: ServerRunControl | None) -> None:
139
+ """Remove a run's control if it is still the one this claim registered."""
140
+ if control is None:
141
+ return
142
+ with self._lock:
143
+ if self._controls.get(str(run_id)) is control:
144
+ del self._controls[str(run_id)]
145
+
146
+ def drain_all(self, reason: str) -> int:
147
+ """Request a drain from every registered run; return how many."""
148
+ with self._lock:
149
+ controls = list(self._controls.values())
150
+ for control in controls:
151
+ control.request_drain(reason)
152
+ return len(controls)
153
+
154
+
95
155
  __all__ = [
96
156
  "DRAIN_SUPPORT",
157
+ "SERVER_SHUTDOWN_DRAIN_REASON",
97
158
  "GraphDrained",
98
159
  "RunControl",
160
+ "RunControlRegistry",
99
161
  "ServerRunControl",
100
162
  "mark_top_level",
101
163
  "new_run_control",
@@ -22,7 +22,6 @@ import asyncio
22
22
  import contextlib
23
23
  import inspect
24
24
  import re
25
- import time
26
25
  from collections.abc import Awaitable, Callable, Mapping
27
26
  from typing import Any, cast, get_args
28
27
  from uuid import UUID, uuid4
@@ -46,6 +45,7 @@ from langgraph_api.event_streaming.session import (
46
45
  from langgraph_api.event_streaming.types import Subscription
47
46
  from langgraph_api.feature_flags import FF_V2_EVENT_STREAMING, PREFER_GRPC_CHECKPOINTER
48
47
  from langgraph_api.schema import MultitaskStrategy
48
+ from langgraph_api.validation import sanitize_reserved_keys
49
49
 
50
50
  logger = structlog.stdlib.get_logger(__name__)
51
51
 
@@ -145,10 +145,7 @@ def _multitask_strategy_from_run_start(params: dict[str, Any]) -> str:
145
145
  EventSink = Callable[[dict[str, Any]], Awaitable[None] | None]
146
146
 
147
147
 
148
- # ``set_joint_status`` commits interrupts after the stream event; gRPC can lag.
149
148
  _IN_FLIGHT_THREAD_STATUS = "busy"
150
- _INTERRUPT_SETTLE_TIMEOUT_SECONDS = 5.0
151
- _INTERRUPT_SETTLE_POLL_INTERVAL_SECONDS = 0.05
152
149
  # langgraph resumes interrupts by id only when every key of the resume map has
153
150
  # this shape; any other key turns the whole map into one value for whichever
154
151
  # interrupt is pending.
@@ -192,6 +189,9 @@ class ThreadRunManager:
192
189
  One ``ThreadRunManager`` is created per connection (HTTP SSE stream or
193
190
  WebSocket). It is not shared across connections — each observer owns
194
191
  its own view of the thread's run stream.
192
+
193
+ ``replay_buffer=False`` keeps no per-run replay buffer, for connections
194
+ that never replay from it.
195
195
  """
196
196
 
197
197
  def __init__(
@@ -202,12 +202,14 @@ class ThreadRunManager:
202
202
  threads: Any,
203
203
  send_event: EventSink | None = None,
204
204
  headers: Mapping[str, str] | None = None,
205
+ replay_buffer: bool = True,
205
206
  ) -> None:
206
207
  self._thread_id = thread_id
207
208
  self._runs = runs
208
209
  self._threads = threads
209
210
  self._send_event = send_event
210
211
  self._headers = headers if headers is not None else {}
212
+ self._replay_buffer = replay_buffer
211
213
  self._session: EventStreamingSession | None = None
212
214
  self._current_run_id: str | None = None
213
215
  self._queued_events: list[dict[str, Any]] = []
@@ -291,7 +293,7 @@ class ThreadRunManager:
291
293
  active=True,
292
294
  )
293
295
 
294
- def start_thread_stream(self) -> None:
296
+ def start_thread_stream(self, *, auth_filters: Any = None) -> None:
295
297
  """Start consuming the thread-level stream for this connection.
296
298
 
297
299
  Always start from the beginning of the thread's event stream
@@ -306,14 +308,19 @@ class ThreadRunManager:
306
308
  produce output…". The SSE/WS sink applies the caller's ``since``
307
309
  as a seq filter on outbound events, and the SDK dedups by
308
310
  ``event_id``, so repeat observers don't see duplicates.
311
+
312
+ ``auth_filters`` is what the route's ``check_thread_stream_auth``
313
+ returned, passed on so the stream doesn't run the read handler again.
309
314
  """
310
315
  if self._thread_source_task is not None:
311
316
  return
312
317
  self._thread_source_task = asyncio.create_task(
313
- self._consume_thread_stream(last_event_id="-")
318
+ self._consume_thread_stream(last_event_id="-", auth_filters=auth_filters)
314
319
  )
315
320
 
316
- async def _consume_thread_stream(self, *, last_event_id: str | None) -> None:
321
+ async def _consume_thread_stream(
322
+ self, *, last_event_id: str | None, auth_filters: Any
323
+ ) -> None:
317
324
  try:
318
325
  async for (
319
326
  event,
@@ -324,6 +331,7 @@ class ThreadRunManager:
324
331
  self._thread_id,
325
332
  stream_modes=["run_modes", "lifecycle"],
326
333
  last_event_id=last_event_id,
334
+ auth_filters=auth_filters,
327
335
  ):
328
336
  if not run_id or run_id == "*":
329
337
  continue
@@ -781,40 +789,15 @@ class ThreadRunManager:
781
789
  if not capabilities.ok:
782
790
  raise ProtocolV2UnsupportedError(capabilities)
783
791
 
792
+ # Drop server-owned configurable and metadata keys before the run
793
+ # config is built, as the REST request parser does for its bodies.
794
+ sanitize_reserved_keys(params)
784
795
  config = params.get("config") if _is_record(params.get("config")) else {}
785
796
 
786
- # ``input.respond`` checked its interrupts already and always resumes;
787
- # the lookups below can wait seconds on a busy thread.
788
- force_resume = params.get("force_resume")
789
- current_run = None if force_resume else await self._fetch_current_run()
790
-
791
- current_status = None
792
- if current_run is not None:
793
- current_status = (
794
- current_run["status"]
795
- if _is_record(current_run)
796
- else getattr(current_run, "status", None)
797
- )
798
-
799
- has_interrupts = False
800
- if params.get("input") is not None and not force_resume:
801
- has_interrupts = await self._has_pending_interrupts()
802
- if has_interrupts and not _keyed_by_interrupt_id(params["input"]):
803
- # One answer can't say which of several pending interrupts it is
804
- # for: langgraph fails the run, or picks one when they share a
805
- # subgraph task. Only a paused thread's row is current, so a run in
806
- # flight keeps resuming as before.
807
- paused_on = await self._collect_interrupt_ids_unless_busy()
808
- if paused_on is not None and len(paused_on) > 1:
809
- raise _AmbiguousResumeError(
810
- f"run.start input can't say which of the {len(paused_on)} "
811
- "pending interrupts it answers; answer them with input.respond."
812
- )
813
-
797
+ # ``input.respond`` checked its interrupts already and always resumes.
814
798
  is_resume = params.get("input") is not None and (
815
- force_resume
816
- or (current_run is not None and current_status == "interrupted")
817
- or has_interrupts
799
+ bool(params.get("force_resume"))
800
+ or await self._run_start_resumes(params["input"])
818
801
  )
819
802
 
820
803
  run_config: dict[str, Any] = {
@@ -903,6 +886,16 @@ class ThreadRunManager:
903
886
  except Exception:
904
887
  raise
905
888
 
889
+ # ``input.respond`` clears the interrupts it answered itself.
890
+ if is_resume and not params.get("force_resume") and self._session is not None:
891
+ # Until the stream rebinds to the resumed run, input sent next must
892
+ # not answer these interrupts a second time.
893
+ answered = params["input"]
894
+ if _keyed_by_interrupt_id(answered):
895
+ for interrupt_id in answered:
896
+ self._session.clear_pending_interrupt(interrupt_id)
897
+ else:
898
+ self._session._pending_interrupts.clear()
906
899
  return run
907
900
 
908
901
  async def _ensure_run_session(
@@ -959,6 +952,7 @@ class ThreadRunManager:
959
952
  get_thread_state=self._make_get_thread_state(thread_id),
960
953
  source=None,
961
954
  send=self._make_send(),
955
+ max_buffer_size=None if self._replay_buffer else 0,
962
956
  )
963
957
 
964
958
  self._session = session
@@ -1086,19 +1080,6 @@ class ThreadRunManager:
1086
1080
  # Run lookup
1087
1081
  # ------------------------------------------------------------------
1088
1082
 
1089
- async def _fetch_current_run(self) -> dict[str, Any] | None:
1090
- """Fetch the currently-bound run from storage.
1091
-
1092
- ``Runs.get`` uses keyword-only ``thread_id`` / ``ctx`` args so we
1093
- cannot call it positionally. We also rely on ``ApiRoute``'s
1094
- ``with_user`` to populate the auth context var instead of
1095
- passing ``ctx=self._auth`` (which is a starlette
1096
- ``AuthCredentials``, not a ``BaseAuthContext``).
1097
- """
1098
- if self._current_run_id is None:
1099
- return None
1100
- return await self._fetch_run_by_id(self._current_run_id)
1101
-
1102
1083
  async def _fetch_run_by_id(self, run_id: str) -> dict[str, Any] | None:
1103
1084
  """Fetch a run by id without searching for the latest run."""
1104
1085
  from langgraph_runtime.database import connect # noqa: PLC0415
@@ -1127,41 +1108,6 @@ class ThreadRunManager:
1127
1108
  # Interrupt detection
1128
1109
  # ------------------------------------------------------------------
1129
1110
 
1130
- async def _lookup_interrupt_in_thread_state(
1131
- self, interrupt_id: str
1132
- ) -> list[str] | None:
1133
- """Existence check for ``interrupt_id`` against persisted thread state.
1134
-
1135
- Fallback for ``input.respond`` on stateless HTTP transports, where the
1136
- fresh session hasn't observed ``input.requested`` yet. Backed by the
1137
- durable thread-row map (see :meth:`_collect_persisted_interrupt_ids`).
1138
-
1139
- Returns ``[]`` if the interrupt exists, else ``None``. The ``[]`` is a
1140
- sentinel, not a namespace — the map carries no namespace, so callers
1141
- must treat it as "found, namespace unknown" and trust the client claim.
1142
- """
1143
- found = await self._collect_persisted_interrupt_ids()
1144
- if found is None:
1145
- return None
1146
- return [] if interrupt_id in found else None
1147
-
1148
- async def _collect_persisted_interrupt_ids(self) -> set[str] | None:
1149
- """Collect interrupt ids from the durable thread-row ``interrupts`` map.
1150
-
1151
- ``Threads.set_status`` writes ``{task_id: [{id, value}, ...]}`` onto the
1152
- thread row atomically with the status whenever a run pauses. Reading it
1153
- is a plain row fetch (same ``connect()`` + ``Threads.get`` path as
1154
- :meth:`_get_thread_assistant_id`) — unlike ``Threads.State.get`` it does
1155
- not rebuild the graph, so it can't spuriously raise and reject a
1156
- legitimate resume, and it survives reconnects/redeploys.
1157
-
1158
- Returns the set of interrupt ids (empty when none are pending), or
1159
- ``None`` if the fetch failed — callers treat ``None`` as "unavailable"
1160
- and fall open rather than fabricating ``no_such_interrupt``.
1161
- """
1162
- thread = await self._fetch_thread_row()
1163
- return None if thread is None else self._interrupt_ids(thread)
1164
-
1165
1111
  async def _fetch_thread_row(self) -> dict[str, Any] | None:
1166
1112
  """Return the durable thread row, or ``None`` if the fetch failed."""
1167
1113
  from langgraph_runtime.database import connect # noqa: PLC0415
@@ -1182,6 +1128,11 @@ class ThreadRunManager:
1182
1128
 
1183
1129
  @staticmethod
1184
1130
  def _interrupt_ids(thread: dict[str, Any]) -> set[str]:
1131
+ """Ids in the row's ``interrupts`` map, written with the status when a run ends.
1132
+
1133
+ Read instead of ``Threads.State.get``, which rebuilds the graph and can
1134
+ raise, turning a valid answer into ``no_such_interrupt``.
1135
+ """
1185
1136
  interrupts_map = thread.get("interrupts")
1186
1137
  if not _is_record(interrupts_map):
1187
1138
  return set()
@@ -1197,40 +1148,6 @@ class ThreadRunManager:
1197
1148
  found.add(entry_id)
1198
1149
  return found
1199
1150
 
1200
- async def _fetch_thread_status(self) -> str | None:
1201
- """Return durable thread status, or ``None`` if unreadable."""
1202
- from langgraph_runtime.database import connect # noqa: PLC0415
1203
-
1204
- try:
1205
- async with connect() as conn:
1206
- result = await self._threads.get(conn, self._thread_id)
1207
- thread = await anext(result) if hasattr(result, "__anext__") else result
1208
- except Exception:
1209
- return None
1210
- status = thread.get("status") if _is_record(thread) else None
1211
- return status if isinstance(status, str) else None
1212
-
1213
- async def _collect_settled_interrupt_ids(self) -> set[str] | None:
1214
- """Persisted interrupt ids, polling while the thread is still ``busy``."""
1215
- ids = await self._collect_persisted_interrupt_ids()
1216
- if ids is None:
1217
- return None
1218
- if ids:
1219
- return ids
1220
- deadline = time.monotonic() + _INTERRUPT_SETTLE_TIMEOUT_SECONDS
1221
- while True:
1222
- status = await self._fetch_thread_status()
1223
- if status != _IN_FLIGHT_THREAD_STATUS:
1224
- return await self._collect_persisted_interrupt_ids()
1225
- if time.monotonic() >= deadline:
1226
- return set()
1227
- await asyncio.sleep(_INTERRUPT_SETTLE_POLL_INTERVAL_SECONDS)
1228
- ids = await self._collect_persisted_interrupt_ids()
1229
- if ids is None:
1230
- return None
1231
- if ids:
1232
- return ids
1233
-
1234
1151
  async def _collect_interrupt_ids_unless_busy(self) -> set[str] | None:
1235
1152
  """Persisted interrupt ids, or ``None`` while a run is in flight.
1236
1153
 
@@ -1247,16 +1164,45 @@ class ThreadRunManager:
1247
1164
  return None
1248
1165
  return self._interrupt_ids(thread)
1249
1166
 
1250
- async def _has_pending_interrupts(self) -> bool:
1251
- # Prefer the session's in-memory pending interrupts (populated the
1252
- # instant ``input.requested`` surfaces) to skip a DB round-trip;
1253
- # otherwise consult the durable thread-row map. A lookup failure
1254
- # (``None``) reads as "none pending" — ``run.start`` then falls back to
1255
- # the ``current_status == "interrupted"`` signal for resume-vs-start.
1256
- if self._session is not None and self._session._pending_interrupts:
1167
+ async def _run_start_resumes(self, value: Any) -> bool:
1168
+ """Whether ``run.start`` input answers the interrupts the thread is paused on.
1169
+
1170
+ Decided without waiting, from one read of the thread row. Interrupts
1171
+ reach the row only when their run ends, so while a run is in flight the
1172
+ input is a new run for the multitask strategy (``enqueue``, the default,
1173
+ queues it behind the running one), never an answer for whichever
1174
+ interrupt is open when that run pauses. The exception is the run this
1175
+ connection streams: the session reports it ``interrupted`` as soon as it
1176
+ raises an interrupt, so input sent after that answers the streamed
1177
+ interrupts, until this connection resumes them or that run ends. When
1178
+ the row can't be read, the streamed interrupts decide. The last run's
1179
+ status isn't consulted: a run that pauses on an interrupt ends
1180
+ ``success``, and ``interrupted`` means it was cancelled; any interrupt it
1181
+ left open is in the row.
1182
+
1183
+ Raises ``_AmbiguousResumeError`` when the input would answer several
1184
+ interrupts and isn't keyed by interrupt id.
1185
+ """
1186
+ if _keyed_by_interrupt_id(value):
1257
1187
  return True
1258
- found = await self._collect_settled_interrupt_ids()
1259
- return bool(found)
1188
+ session = self._session
1189
+ streamed = set(session._pending_interrupts) if session is not None else set()
1190
+ thread = await self._fetch_thread_row()
1191
+ if thread is None:
1192
+ paused_on = streamed
1193
+ elif thread.get("status") == _IN_FLIGHT_THREAD_STATUS:
1194
+ paused_on = set() if session is None or session.run_done else streamed
1195
+ else:
1196
+ paused_on = self._interrupt_ids(thread)
1197
+ if len(paused_on) > 1:
1198
+ # One answer can't say which of several pending interrupts it is
1199
+ # for: langgraph fails the run, or picks one when they share a
1200
+ # subgraph task.
1201
+ raise _AmbiguousResumeError(
1202
+ f"run.start input can't say which of the {len(paused_on)} "
1203
+ "pending interrupts it answers; answer them with input.respond."
1204
+ )
1205
+ return bool(paused_on)
1260
1206
 
1261
1207
  # ------------------------------------------------------------------
1262
1208
  # Command forwarding