langgraph-api 0.18.0.dev6__tar.gz → 0.18.0.dev7__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 (332) hide show
  1. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/PKG-INFO +1 -1
  2. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/package.json +1 -1
  3. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/yarn.lock +7 -7
  4. langgraph_api-0.18.0.dev7/langgraph_api/__init__.py +1 -0
  5. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/threads.py +68 -20
  6. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/config/__init__.py +19 -0
  7. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/errors.py +16 -0
  8. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/runs.py +21 -0
  9. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/threads.py +33 -16
  10. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/package.json +1 -1
  11. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/yarn.lock +10 -10
  12. langgraph_api-0.18.0.dev7/langgraph_api/operator_routes.py +223 -0
  13. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/schema.py +9 -0
  14. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/server.py +7 -20
  15. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/state.py +41 -0
  16. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2.py +99 -95
  17. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2.pyi +58 -0
  18. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +44 -0
  19. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +12 -0
  20. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/openapi.json +2 -2
  21. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/uv.lock +9 -9
  22. langgraph_api-0.18.0.dev6/langgraph_api/__init__.py +0 -1
  23. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/.gitignore +0 -0
  24. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/LICENSE +0 -0
  25. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/Makefile +0 -0
  26. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/README.md +0 -0
  27. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/.gitignore +0 -0
  28. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/Makefile +0 -0
  29. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/README.md +0 -0
  30. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/REPORTS.md +0 -0
  31. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/assistant.ts +0 -0
  32. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
  33. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
  34. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/benchmarks.ts +0 -0
  35. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
  36. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/classify-error.test.js +0 -0
  37. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/classify-error.ts +0 -0
  38. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/delta-turns-lib.test.js +0 -0
  39. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/delta-turns-lib.ts +0 -0
  40. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/delta_turns.ts +0 -0
  41. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
  42. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
  43. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/log-failure.ts +0 -0
  44. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/meta_workload.ts +0 -0
  45. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/store.ts +0 -0
  46. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/stream_write.ts +0 -0
  47. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/thread.ts +0 -0
  48. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
  49. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
  50. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/types.ts +0 -0
  51. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/benchmark-runners/wait_write.ts +0 -0
  52. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/capacity-ci.js +0 -0
  53. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/capacity-ci.test.js +0 -0
  54. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/clean-cli.js +0 -0
  55. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/clean.js +0 -0
  56. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/continuous/README.md +0 -0
  57. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/continuous/pyproject.toml +0 -0
  58. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/continuous/runner.py +0 -0
  59. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/continuous/uv.lock +0 -0
  60. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/daily-report.js +0 -0
  61. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/daily-report.test.js +0 -0
  62. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/delta-report.js +0 -0
  63. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/delta-report.test.js +0 -0
  64. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/graphs.js +0 -0
  65. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/history.js +0 -0
  66. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/history.test.js +0 -0
  67. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/host-v2.js +0 -0
  68. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/host-v2.test.js +0 -0
  69. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/multer.test.js +0 -0
  70. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/ramp.js +0 -0
  71. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/reporting/dd_reporting.py +0 -0
  72. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/runner-descriptions.js +0 -0
  73. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/server-metrics.js +0 -0
  74. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/server-metrics.test.js +0 -0
  75. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/slack.js +0 -0
  76. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/staircase.py +0 -0
  77. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/staircase_step_k6.js +0 -0
  78. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/tsconfig.json +0 -0
  79. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/update-revision.js +0 -0
  80. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/benchmark/weather.js +0 -0
  81. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/constraints.txt +0 -0
  82. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/custom_store.sql +0 -0
  83. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/forbidden.txt +0 -0
  84. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/hatch_build.py +0 -0
  85. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/healthcheck.py +0 -0
  86. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph-cloud-debugging-20260210132856.zip +0 -0
  87. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/_checkpointer/__init__.py +0 -0
  88. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/_checkpointer/_adapter.py +0 -0
  89. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/_checkpointer/protocol.py +0 -0
  90. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/_factory_utils.py +0 -0
  91. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/__init__.py +0 -0
  92. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2a.py +0 -0
  93. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui.py +0 -0
  94. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/README.md +0 -0
  95. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
  96. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
  97. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
  98. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
  99. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/assistants.py +0 -0
  100. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/event_streaming.py +0 -0
  101. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/__init__.py +0 -0
  102. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_calls.py +0 -0
  103. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_constants.py +0 -0
  104. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_handlers.py +0 -0
  105. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_models.py +0 -0
  106. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_outcome.py +0 -0
  107. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_protocol.py +0 -0
  108. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_routes.py +0 -0
  109. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/mcp/_sanitizers.py +0 -0
  110. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/meta.py +0 -0
  111. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/openapi.py +0 -0
  112. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/profile.py +0 -0
  113. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/runs.py +0 -0
  114. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/store.py +0 -0
  115. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/api/ui.py +0 -0
  116. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/asgi_transport.py +0 -0
  117. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/asyncio.py +0 -0
  118. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/__init__.py +0 -0
  119. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/custom.py +0 -0
  120. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/errors.py +0 -0
  121. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/langsmith/__init__.py +0 -0
  122. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/langsmith/backend.py +0 -0
  123. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/langsmith/client.py +0 -0
  124. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/middleware.py +0 -0
  125. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/noop.py +0 -0
  126. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/auth/studio_user.py +0 -0
  127. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
  128. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/cache.py +0 -0
  129. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/cli.py +0 -0
  130. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/command.py +0 -0
  131. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/config/_parse.py +0 -0
  132. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/config/schemas.py +0 -0
  133. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/cron_scheduler.py +0 -0
  134. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/drain.py +0 -0
  135. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/__init__.py +0 -0
  136. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/aes_json.py +0 -0
  137. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/context.py +0 -0
  138. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/custom.py +0 -0
  139. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/middleware.py +0 -0
  140. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/encryption/shared.py +0 -0
  141. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/__init__.py +0 -0
  142. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/capabilities.py +0 -0
  143. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/constants.py +0 -0
  144. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/event_normalizers.py +0 -0
  145. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/namespace.py +0 -0
  146. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/service.py +0 -0
  147. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/session.py +0 -0
  148. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/state_normalizers.py +0 -0
  149. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/event_streaming/types.py +0 -0
  150. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/executor/__init__.py +0 -0
  151. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/executor/__main__.py +0 -0
  152. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/feature_flags.py +0 -0
  153. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/graph.py +0 -0
  154. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/__init__.py +0 -0
  155. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/client.py +0 -0
  156. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
  157. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/__init__.py +0 -0
  158. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/assistants.py +0 -0
  159. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/cache.py +0 -0
  160. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/ops/crons.py +0 -0
  161. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/server.py +0 -0
  162. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/servicers/__init__.py +0 -0
  163. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
  164. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/grpc/servicers/encryption.py +0 -0
  165. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/http.py +0 -0
  166. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/http_metrics.py +0 -0
  167. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/http_metrics_utils.py +0 -0
  168. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/.gitignore +0 -0
  169. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/.prettierrc +0 -0
  170. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/.yarnclean +0 -0
  171. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/__init__.py +0 -0
  172. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/base.py +0 -0
  173. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/build.mts +0 -0
  174. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/client.http.mts +0 -0
  175. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/client.mts +0 -0
  176. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/errors.py +0 -0
  177. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/global.d.ts +0 -0
  178. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/remote.py +0 -0
  179. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/schema.py +0 -0
  180. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/auth-mutations.mts +0 -0
  181. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/graph.mts +0 -0
  182. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/load.hooks.mjs +0 -0
  183. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/preload.mjs +0 -0
  184. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
  185. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/files.mts +0 -0
  186. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/importMap.mts +0 -0
  187. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  188. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/src/utils/serde.mts +0 -0
  189. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/sse.py +0 -0
  190. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/traceblock.mts +0 -0
  191. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/tsconfig.json +0 -0
  192. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/js/ui.py +0 -0
  193. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/__init__.py +0 -0
  194. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/exceptions.py +0 -0
  195. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/policy.py +0 -0
  196. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/lc_security/transport.py +0 -0
  197. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/logging.py +0 -0
  198. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/metadata.py +0 -0
  199. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/metrics_collector.py +0 -0
  200. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/metrics_otlp.py +0 -0
  201. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/__init__.py +0 -0
  202. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/ensure_store.py +0 -0
  203. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/http_logger.py +0 -0
  204. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/private_network.py +0 -0
  205. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/middleware/request_id.py +0 -0
  206. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/models/__init__.py +0 -0
  207. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/models/run.py +0 -0
  208. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/otel_context.py +0 -0
  209. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/patch.py +0 -0
  210. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/queue_entrypoint.py +0 -0
  211. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/release_tags.py +0 -0
  212. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/route.py +0 -0
  213. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/self_hosted_logs.py +0 -0
  214. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/self_hosted_metrics.py +0 -0
  215. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/serde.py +0 -0
  216. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/sse.py +0 -0
  217. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/store.py +0 -0
  218. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/stream.py +0 -0
  219. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/stream_v2.py +0 -0
  220. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/__init__.py +0 -0
  221. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/profiler.py +0 -0
  222. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/startup.py +0 -0
  223. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/timing/timer.py +0 -0
  224. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/traceblock.py +0 -0
  225. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/tracing_session.py +0 -0
  226. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/tunneling/cloudflare.py +0 -0
  227. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/__init__.py +0 -0
  228. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/cache.py +0 -0
  229. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/config.py +0 -0
  230. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/errors.py +0 -0
  231. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/extract.py +0 -0
  232. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/future.py +0 -0
  233. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/headers.py +0 -0
  234. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/network.py +0 -0
  235. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/retriable_client.py +0 -0
  236. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/stream_codec.py +0 -0
  237. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/utils/uuids.py +0 -0
  238. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/validation.py +0 -0
  239. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/webhook.py +0 -0
  240. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/worker.py +0 -0
  241. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_api/worker_runtime.py +0 -0
  242. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/__init__.py +0 -0
  243. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/checkpointer.py +0 -0
  244. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/__init__.py +0 -0
  245. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/_compat.py +0 -0
  246. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
  247. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/config.py +0 -0
  248. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/durability.py +0 -0
  249. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/store.py +0 -0
  250. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/struct.py +0 -0
  251. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/conversion/value.py +0 -0
  252. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/__init__.py +0 -0
  253. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
  254. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
  255. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
  256. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
  257. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
  258. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
  259. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
  260. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
  261. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
  262. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
  263. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
  264. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
  265. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
  266. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
  267. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
  268. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
  269. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
  270. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
  271. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
  272. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
  273. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
  274. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
  275. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
  276. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
  277. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
  278. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
  279. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
  280. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
  281. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
  282. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
  283. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
  284. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
  285. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
  286. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
  287. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
  288. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
  289. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
  290. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
  291. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
  292. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
  293. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
  294. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
  295. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
  296. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
  297. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
  298. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
  299. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
  300. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
  301. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
  302. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
  303. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
  304. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
  305. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2.py +0 -0
  306. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2.pyi +0 -0
  307. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.py +0 -0
  308. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.pyi +0 -0
  309. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2.py +0 -0
  310. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
  311. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
  312. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
  313. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/serde.py +0 -0
  314. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_grpc_common/store.py +0 -0
  315. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_license/__init__.py +0 -0
  316. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_license/validation.py +0 -0
  317. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/__init__.py +0 -0
  318. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/checkpoint.py +0 -0
  319. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/database.py +0 -0
  320. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/encryption.py +0 -0
  321. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/lifespan.py +0 -0
  322. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/metrics.py +0 -0
  323. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/ops.py +0 -0
  324. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/queue.py +0 -0
  325. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/retry.py +0 -0
  326. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/routes.py +0 -0
  327. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/langgraph_runtime/store.py +0 -0
  328. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/logging.json +0 -0
  329. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/pyproject.toml +0 -0
  330. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/scripts/build_wheel.py +0 -0
  331. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/scripts/create_license.py +0 -0
  332. {langgraph_api-0.18.0.dev6 → langgraph_api-0.18.0.dev7}/scripts/run_a2a_tck.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.18.0.dev6
3
+ Version: 0.18.0.dev7
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
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "devDependencies": {
17
17
  "@types/k6": "^2.0.0",
18
- "typescript": "^5.9.3"
18
+ "typescript": "^6.0.3"
19
19
  },
20
20
  "overrides": {
21
21
  "body-parser": "1.20.8",
@@ -493,9 +493,9 @@ path-to-regexp@~0.1.13:
493
493
  integrity sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==
494
494
 
495
495
  proxy-addr@~2.0.7:
496
- version "2.0.7"
497
- resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
498
- integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
496
+ version "2.0.8"
497
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.8.tgz#624e760fd8ab06b1b8320c2f8506d4422cf8e932"
498
+ integrity sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==
499
499
  dependencies:
500
500
  forwarded "0.2.0"
501
501
  ipaddr.js "1.9.1"
@@ -670,10 +670,10 @@ type-is@^1.6.18, type-is@~1.6.18:
670
670
  media-typer "0.3.0"
671
671
  mime-types "~2.1.24"
672
672
 
673
- typescript@^5.9.3:
674
- version "5.9.3"
675
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
676
- integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
673
+ typescript@^6.0.3:
674
+ version "6.0.3"
675
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.3.tgz#90251dc007916e972786cb94d74d15b185577d21"
676
+ integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==
677
677
 
678
678
  undici-types@~8.3.0:
679
679
  version "8.3.0"
@@ -0,0 +1 @@
1
+ __version__ = "0.18.0.dev7"
@@ -1,9 +1,11 @@
1
- from typing import get_args
1
+ from contextlib import aclosing
2
+ from typing import TYPE_CHECKING, Any, get_args
2
3
 
3
4
  from starlette.exceptions import HTTPException
4
5
  from starlette.responses import Response
5
6
  from starlette.routing import BaseRoute
6
7
 
8
+ from langgraph_api import config as lg_api_config
7
9
  from langgraph_api.config import USE_CUSTOM_CHECKPOINTER
8
10
  from langgraph_api.encryption.shared import (
9
11
  using_encryption,
@@ -14,6 +16,7 @@ from langgraph_api.feature_flags import (
14
16
  )
15
17
  from langgraph_api.route import ApiRequest, ApiResponse, ApiRoute
16
18
  from langgraph_api.schema import THREAD_FIELDS, ThreadStreamMode
19
+ from langgraph_api.serde import Fragment, json_dumpb
17
20
  from langgraph_api.sse import EventSourceResponse
18
21
  from langgraph_api.state import state_snapshot_to_thread_state
19
22
  from langgraph_api.utils import (
@@ -44,6 +47,11 @@ if IS_POSTGRES_OR_GRPC_BACKEND:
44
47
  else:
45
48
  from langgraph_runtime.ops import Threads
46
49
 
50
+ if TYPE_CHECKING:
51
+ from collections.abc import AsyncIterator
52
+
53
+ from langgraph.types import StateSnapshot
54
+
47
55
 
48
56
  @retry_db
49
57
  async def create_thread(
@@ -320,14 +328,7 @@ async def get_thread_history(
320
328
  **get_configurable_headers(request.headers),
321
329
  }
322
330
  }
323
- async with connect(supports_core_api=PREFER_GRPC_CHECKPOINTER) as conn:
324
- states = [
325
- state_snapshot_to_thread_state(c)
326
- for c in await Threads.State.list(
327
- conn, config=config, limit=limit, before=before
328
- )
329
- ]
330
- return ApiResponse(states)
331
+ return await _history_response(config=config, limit=limit, before=before)
331
332
 
332
333
 
333
334
  @retry_db
@@ -342,18 +343,65 @@ async def get_thread_history_post(
342
343
  config["configurable"].update(payload.get("checkpoint", {}))
343
344
  config["configurable"].update(get_configurable_headers(request.headers))
344
345
  config["configurable"]["thread_id"] = thread_id
346
+ return await _history_response(
347
+ config=config,
348
+ limit=int(payload.get("limit") or 1),
349
+ before=payload.get("before"),
350
+ metadata=payload.get("metadata"),
351
+ )
352
+
353
+
354
+ async def _history_response(**kwargs: Any) -> ApiResponse:
355
+ budget = lg_api_config.THREAD_HISTORY_MAX_STATE_BYTES
345
356
  async with connect(supports_core_api=PREFER_GRPC_CHECKPOINTER) as conn:
346
- states = [
347
- state_snapshot_to_thread_state(c)
348
- for c in await Threads.State.list(
349
- conn,
350
- config=config,
351
- limit=int(payload.get("limit") or 1),
352
- before=payload.get("before"),
353
- metadata=payload.get("metadata"),
354
- )
355
- ]
356
- return ApiResponse(states)
357
+ entries = await _serialize_history(
358
+ _history_states(conn, incremental=bool(budget), **kwargs),
359
+ budget=budget,
360
+ )
361
+ return ApiResponse(entries)
362
+
363
+
364
+ def _history_states(
365
+ conn: Any, *, incremental: bool, **kwargs: Any
366
+ ) -> "AsyncIterator[StateSnapshot]":
367
+ if hasattr(Threads.State, "iterate"):
368
+ return Threads.State.iterate(conn, incremental=incremental, **kwargs)
369
+ # langgraph-runtime-inmem releases before ``iterate`` only have ``list``.
370
+ return _listed_history_states(conn, **kwargs)
371
+
372
+
373
+ async def _listed_history_states(
374
+ conn: Any, **kwargs: Any
375
+ ) -> "AsyncIterator[StateSnapshot]":
376
+ for state in await Threads.State.list(conn, **kwargs):
377
+ yield state
378
+
379
+
380
+ async def _serialize_history(
381
+ states: "AsyncIterator[StateSnapshot]", *, budget: int
382
+ ) -> list[Fragment]:
383
+ """Serialize history entries until they reach ``budget`` bytes (0: no limit).
384
+
385
+ The newest entry is always returned. Each later entry is returned only if
386
+ the response stays within the budget, and history stops at the first one
387
+ that does not.
388
+ """
389
+ entries: list[Fragment] = []
390
+ total_bytes = 1 # the response array's opening bracket
391
+ async with aclosing(states):
392
+ async for state in states:
393
+ entry = json_dumpb(state_snapshot_to_thread_state(state))
394
+ # Drop the decoded state before the next checkpoint loads.
395
+ del state
396
+ # Each entry also adds a comma or the closing bracket.
397
+ total_bytes += len(entry) + 1
398
+ if budget and entries and total_bytes > budget:
399
+ break
400
+ entries.append(Fragment(entry))
401
+ if budget and total_bytes >= budget:
402
+ # Nothing more can fit, so don't load another checkpoint.
403
+ break
404
+ return entries
357
405
 
358
406
 
359
407
  @retry_db
@@ -240,6 +240,23 @@ HTTP_MAX_REQUEST_BODY_BYTES = env(
240
240
  "HTTP_MAX_REQUEST_BODY_BYTES", cast=int, default=300 * 1024 * 1024
241
241
  )
242
242
 
243
+
244
+ def _validate_thread_history_budget(budget: int) -> int:
245
+ if budget < 0:
246
+ raise ValueError(
247
+ "LANGGRAPH_THREAD_HISTORY_MAX_STATE_BYTES must be 0 (disabled) or a "
248
+ f"positive number of bytes, got {budget}."
249
+ )
250
+ return budget
251
+
252
+
253
+ # Byte budget for one history response, counted as the serialized size of its
254
+ # entries; every entry carries the full thread state. History stops before the
255
+ # entry that would cross it but always returns the newest. 0 disables it.
256
+ THREAD_HISTORY_MAX_STATE_BYTES = _validate_thread_history_budget(
257
+ env("LANGGRAPH_THREAD_HISTORY_MAX_STATE_BYTES", cast=int, default=0)
258
+ )
259
+
243
260
  # gRPC message size limits (300MB default)
244
261
  # Not in public docs: infrastructure, set by platform
245
262
  LSD_GRPC_SERVER_MAX_RECV_MSG_BYTES = env(
@@ -565,6 +582,7 @@ LANGGRAPH_ENCRYPTION = env(
565
582
  )
566
583
  # Not in public docs: set by SaaS control plane, not user-configurable
567
584
  LANGSMITH_TENANT_ID = env("LANGSMITH_TENANT_ID", cast=str, default=None)
585
+ LANGSMITH_HOST_PROJECT_ID = env("LANGSMITH_HOST_PROJECT_ID", cast=str, default=None)
568
586
  LANGSMITH_AUTH_VERIFY_TENANT_ID = env(
569
587
  "LANGSMITH_AUTH_VERIFY_TENANT_ID",
570
588
  cast=bool,
@@ -870,6 +888,7 @@ __all__ = [
870
888
  "STREAM_PUBLISH_RETRY_JITTER",
871
889
  "STREAM_PUBLISH_RETRY_MAX_DURATION_SECS",
872
890
  "STREAM_PUBLISH_RETRY_MAX_INTERVAL_SECS",
891
+ "THREAD_HISTORY_MAX_STATE_BYTES",
873
892
  "THREAD_TTL",
874
893
  "TRACING",
875
894
  "UI_USE_BUNDLER",
@@ -1,5 +1,6 @@
1
1
  import jsonschema_rs
2
2
  import structlog
3
+ from langgraph.errors import EmptyInputError, InvalidUpdateError
3
4
  from starlette.exceptions import HTTPException
4
5
  from starlette.requests import Request
5
6
  from starlette.responses import JSONResponse, Response
@@ -63,6 +64,21 @@ async def overloaded_error_handler(request, exc: ValueError):
63
64
  )
64
65
 
65
66
 
67
+ def app_exception_handlers() -> dict:
68
+ """The exception handlers shared by the server app and the operator routes."""
69
+ # Imported here because the runtime imports this module while it loads.
70
+ from langgraph_runtime.retry import OVERLOADED_EXCEPTIONS # noqa: PLC0415
71
+
72
+ return {
73
+ HTTPException: http_exception_handler,
74
+ ValueError: value_error_handler,
75
+ InvalidUpdateError: value_error_handler,
76
+ EmptyInputError: value_error_handler,
77
+ jsonschema_rs.ValidationError: validation_error_handler,
78
+ RemoteException: remote_exception_handler,
79
+ } | {exc: overloaded_error_handler for exc in OVERLOADED_EXCEPTIONS}
80
+
81
+
66
82
  class UserInterrupt(Exception):
67
83
  def __init__(self, message="User interrupted the run"):
68
84
  super().__init__(message)
@@ -71,6 +71,7 @@ from langgraph_api.utils import get_auth_ctx
71
71
 
72
72
  if TYPE_CHECKING:
73
73
  from collections.abc import AsyncIterator, Sequence
74
+ from datetime import datetime
74
75
 
75
76
  from langgraph_api.schema import (
76
77
  IfNotExists,
@@ -79,6 +80,7 @@ if TYPE_CHECKING:
79
80
  PoolStats,
80
81
  QueueStats,
81
82
  Run,
83
+ RunCancelProgress,
82
84
  RunSelectField,
83
85
  RunStatus,
84
86
  )
@@ -755,6 +757,25 @@ class Runs(Authenticated):
755
757
  client = await get_shared_client()
756
758
  await client.runs.Cancel(pb.CancelRunRequest(**request_kwargs))
757
759
 
760
+ @staticmethod
761
+ async def cancel_accepted_before(
762
+ conn,
763
+ accepted_before: datetime,
764
+ *,
765
+ reason: str,
766
+ ) -> RunCancelProgress:
767
+ """Applies no auth filters, so only the operator route may call it."""
768
+ client = await get_shared_client()
769
+ response = await client.runs.CancelAcceptedBefore(
770
+ pb.CancelAcceptedBeforeRequest(
771
+ accepted_before=accepted_before, reason=reason
772
+ )
773
+ )
774
+ return {
775
+ "not_yet_reached": response.not_yet_reached,
776
+ "finishing": response.finishing,
777
+ }
778
+
758
779
  @staticmethod
759
780
  async def stats(conn) -> QueueStats:
760
781
  """Get queue statistics (not exposed via API, no auth)."""
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
- from contextlib import AsyncExitStack
6
+ from contextlib import AsyncExitStack, aclosing
7
7
  from datetime import UTC
8
8
  from http import HTTPStatus
9
9
  from typing import TYPE_CHECKING, Any, Literal
@@ -46,7 +46,11 @@ from langgraph_api.grpc.ops import (
46
46
  from langgraph_api.grpc.ops.runs import Runs
47
47
  from langgraph_api.schema import ThreadUpdateResponse
48
48
  from langgraph_api.serde import json_dumpb, json_dumpb_optional, json_loads
49
- from langgraph_api.state import patch_interrupt, state_snapshot_to_thread_state
49
+ from langgraph_api.state import (
50
+ iter_state_history,
51
+ patch_interrupt,
52
+ state_snapshot_to_thread_state,
53
+ )
50
54
  from langgraph_api.utils import fetchone
51
55
 
52
56
  if TYPE_CHECKING:
@@ -1330,7 +1334,7 @@ class Threads(Authenticated):
1330
1334
  )
1331
1335
 
1332
1336
  @staticmethod
1333
- async def list(
1337
+ async def iterate(
1334
1338
  conn, # Still needed for checkpointer
1335
1339
  *,
1336
1340
  config: dict[str, Any],
@@ -1338,8 +1342,13 @@ class Threads(Authenticated):
1338
1342
  before: Any = None,
1339
1343
  metadata: Any = None,
1340
1344
  ctx: Any = None,
1341
- ) -> list[StateSnapshot]:
1342
- """Get the history of a thread."""
1345
+ incremental: bool = False,
1346
+ ) -> AsyncIterator[StateSnapshot]:
1347
+ """Yield the history of a thread.
1348
+
1349
+ With ``incremental``, checkpoints load in growing pages, so a
1350
+ caller that stops early does not load the rest of ``limit``.
1351
+ """
1343
1352
  async with conn.pipeline():
1344
1353
  thread, graph_id = await asyncio.gather(
1345
1354
  Threads.get(
@@ -1372,18 +1381,26 @@ class Threads(Authenticated):
1372
1381
  store=(await api_store.get_store()),
1373
1382
  access_context="threads.read",
1374
1383
  ) as graph:
1375
- return [
1376
- c
1377
- async for c in graph.aget_state_history(
1384
+ before_config = (
1385
+ {"configurable": {"checkpoint_id": before}}
1386
+ if isinstance(before, str)
1387
+ else before
1388
+ )
1389
+ history = (
1390
+ iter_state_history(
1391
+ graph,
1378
1392
  config,
1379
1393
  limit=limit,
1380
1394
  filter=metadata,
1381
- before=(
1382
- {"configurable": {"checkpoint_id": before}}
1383
- if isinstance(before, str)
1384
- else before
1385
- ),
1395
+ before=before_config,
1386
1396
  )
1387
- ]
1388
- else:
1389
- return []
1397
+ if incremental
1398
+ else graph.aget_state_history(
1399
+ config, limit=limit, filter=metadata, before=before_config
1400
+ )
1401
+ )
1402
+ async with aclosing(history) as states:
1403
+ async for c in states:
1404
+ yield c
1405
+ # Drop the entry before the next page loads.
1406
+ del c
@@ -20,7 +20,7 @@
20
20
  "hono": "^4.13.7",
21
21
  "p-queue": "^9.3.1",
22
22
  "p-retry": "^7.1.1",
23
- "typescript": "^5.9.3",
23
+ "typescript": "^6.0.3",
24
24
  "undici": "^7.29.1",
25
25
  "uuid": "^14.0.1",
26
26
  "winston": "^3.19.0",
@@ -1506,9 +1506,9 @@ postcss-modules@^6.0.1:
1506
1506
  string-hash "^1.1.3"
1507
1507
 
1508
1508
  postcss-selector-parser@^7.0.0:
1509
- version "7.1.5"
1510
- resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz#ee7b090724eb60739b530660e5b402200e694a97"
1511
- integrity sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==
1509
+ version "7.1.6"
1510
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.6.tgz#45e970f2d93d4547d6754167ed1132f43012c4bf"
1511
+ integrity sha512-7qASPzhKF2l2KLboRZux8CCTRMdGiV08vWmyKzPz22qZ7ZjQBOeY7rNzNoCLSUiftJ7HUq0GERHmxw/t0dCdMw==
1512
1512
  dependencies:
1513
1513
  cssesc "^3.0.0"
1514
1514
  util-deprecate "^1.0.2"
@@ -1630,9 +1630,9 @@ siginfo@^2.0.0:
1630
1630
  integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==
1631
1631
 
1632
1632
  source-map-js@^1.2.1:
1633
- version "1.2.1"
1634
- resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
1635
- integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
1633
+ version "1.2.2"
1634
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.2.tgz#79fb88d97535a21cb27162cb05d211b67acea4ab"
1635
+ integrity sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==
1636
1636
 
1637
1637
  stack-trace@0.0.x:
1638
1638
  version "0.0.10"
@@ -1732,10 +1732,10 @@ type-fest@^0.7.1:
1732
1732
  resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz"
1733
1733
  integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==
1734
1734
 
1735
- typescript@^5.9.3:
1736
- version "5.9.3"
1737
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
1738
- integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
1735
+ typescript@^6.0.3:
1736
+ version "6.0.3"
1737
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.3.tgz#90251dc007916e972786cb94d74d15b185577d21"
1738
+ integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==
1739
1739
 
1740
1740
  undici-types@~8.3.0:
1741
1741
  version "8.3.0"
@@ -0,0 +1,223 @@
1
+ """Operator routes: deployment-wide actions a LangSmith admin can take on a deployment.
2
+
3
+ They are served before every other middleware, so customer middleware and custom
4
+ auth handlers can't block or filter them. Instead, host-backend checks the admin's
5
+ permission and calls them with a short-lived service token scoped to one operation on
6
+ this deployment, which LangSmith verifies. See THREAT_MODEL.md.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import contextlib
12
+ from dataclasses import dataclass
13
+ from datetime import UTC, datetime, timedelta
14
+ from typing import TYPE_CHECKING, Any
15
+ from uuid import UUID
16
+
17
+ import httpx
18
+ import structlog
19
+ from starlette.applications import Starlette
20
+ from starlette.exceptions import HTTPException
21
+ from starlette.responses import JSONResponse, Response
22
+ from starlette.routing import Route
23
+
24
+ from langgraph_api import config
25
+ from langgraph_api.auth.langsmith.client import create_client
26
+ from langgraph_api.errors import app_exception_handlers
27
+ from langgraph_api.feature_flags import IS_POSTGRES_OR_GRPC_BACKEND
28
+ from langgraph_runtime.database import connect
29
+
30
+ if IS_POSTGRES_OR_GRPC_BACKEND:
31
+ from langgraph_api.grpc.ops import Runs
32
+ else:
33
+ from langgraph_runtime.ops import Runs
34
+
35
+ if TYPE_CHECKING:
36
+ from starlette.requests import Request
37
+ from starlette.types import ASGIApp, Message, Receive, Scope, Send
38
+
39
+ logger = structlog.stdlib.get_logger(__name__)
40
+
41
+ CANCEL_RUNS_PATH = "/operator/runs/cancel"
42
+
43
+ _OPERATOR_TOKEN_PATH = "/auth/operator-token"
44
+ _INTERRUPT = "interrupt"
45
+
46
+ # host-backend fixes the boundary at the press and mints every token after it, so a
47
+ # boundary later than the token's issue time would cancel runs accepted after the
48
+ # press. The allowance only covers clock differences between host-backend replicas.
49
+ _BOUNDARY_SKEW = timedelta(seconds=5)
50
+
51
+ # The route's refusal for each LangSmith answer other than 200. Anything not listed
52
+ # means LangSmith couldn't answer.
53
+ _LANGSMITH_REFUSALS = {
54
+ 401: (401, "invalid_token"),
55
+ # A LangSmith release without operator tokens can't authorize this route.
56
+ 404: (503, "langsmith_upgrade_required"),
57
+ 405: (503, "langsmith_upgrade_required"),
58
+ }
59
+
60
+
61
+ @dataclass(frozen=True)
62
+ class _OperatorToken:
63
+ """The cancellation a verified operator token authorizes."""
64
+
65
+ operation_id: UUID
66
+ user_id: UUID
67
+ accepted_before: datetime
68
+
69
+
70
+ class OperatorRoutesMiddleware:
71
+ """Serves the operator routes and passes every other request through."""
72
+
73
+ def __init__(self, app: ASGIApp, mount_prefix: str | None = None) -> None:
74
+ self.app = app
75
+ self.cancel_runs_paths = {CANCEL_RUNS_PATH}
76
+ if mount_prefix:
77
+ self.cancel_runs_paths.add(mount_prefix + CANCEL_RUNS_PATH)
78
+ # Its own small app with the server's error handlers, since these requests
79
+ # never reach the main app.
80
+ self.operator_app = Starlette(
81
+ routes=[
82
+ Route(path, cancel_runs, methods=["POST"])
83
+ for path in self.cancel_runs_paths
84
+ ],
85
+ exception_handlers=app_exception_handlers(),
86
+ )
87
+
88
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
89
+ if scope["type"] != "http" or scope["path"] not in self.cancel_runs_paths:
90
+ await self.app(scope, receive, send)
91
+ return
92
+ status = None
93
+
94
+ async def send_recording_status(message: Message) -> None:
95
+ nonlocal status
96
+ if message["type"] == "http.response.start":
97
+ status = message["status"]
98
+ await send(message)
99
+
100
+ # Every operator request gets exactly one log line, including ones that fail
101
+ # unexpectedly; customer request logging never sees them.
102
+ try:
103
+ await self.operator_app(scope, receive, send_recording_status)
104
+ except Exception:
105
+ await logger.aexception("Operator request", **_log_fields(scope, status))
106
+ raise
107
+ await logger.ainfo("Operator request", **_log_fields(scope, status))
108
+
109
+
110
+ def _log_fields(scope: Scope, status: int | None) -> dict[str, Any]:
111
+ # cancel_runs records the verified operation and the progress on the request state.
112
+ learned = scope.get("state", {}).get("operator_log_fields", {})
113
+ return {
114
+ "path": scope["path"],
115
+ "method": scope["method"],
116
+ "status": status,
117
+ } | learned
118
+
119
+
120
+ async def cancel_runs(request: Request) -> Response:
121
+ """Interrupt every in-flight run accepted at or before the token's boundary.
122
+
123
+ The operation, boundary and user all come from the verified token; the request
124
+ body is ignored. One call cancels a bounded amount of work and returns how many
125
+ targets are still in flight, and the caller repeats it until both counts are zero.
126
+ """
127
+ token = await _verify_token(request)
128
+ log_fields = {
129
+ "operation_id": str(token.operation_id),
130
+ "user_id": str(token.user_id),
131
+ }
132
+ request.state.operator_log_fields = log_fields
133
+
134
+ # Built only from fixed text and UUIDs, never from text in the request.
135
+ reason = (
136
+ f"cancelled by kill switch (operation {token.operation_id}, "
137
+ f"requested by LangSmith user {token.user_id})"
138
+ )
139
+ async with connect() as conn:
140
+ progress = await Runs.cancel_accepted_before(
141
+ conn, token.accepted_before, reason=reason
142
+ )
143
+ log_fields.update(progress)
144
+ return JSONResponse(progress)
145
+
146
+
147
+ async def _verify_token(request: Request) -> _OperatorToken:
148
+ """Return the cancellation the request's operator token authorizes here.
149
+
150
+ LangSmith checks the token's signature, audience, subject and expiry on every
151
+ call, with no cache. This route checks that the token names this deployment and
152
+ an interrupt. Anything short of that is a refusal.
153
+ """
154
+ tenant_id = _as_uuid(config.LANGSMITH_TENANT_ID)
155
+ deployment_id = _as_uuid(config.LANGSMITH_HOST_PROJECT_ID)
156
+ if tenant_id is None or deployment_id is None:
157
+ # Only a deployment LangSmith manages is sent operator tokens.
158
+ raise HTTPException(404)
159
+ token = request.headers.get("x-service-key")
160
+ if not token:
161
+ raise HTTPException(401, "missing_token")
162
+ # A client per call, so nothing one verification leaves behind (such as a
163
+ # cookie) reaches the next.
164
+ auth = create_client()
165
+ try:
166
+ response = await auth.get(
167
+ _OPERATOR_TOKEN_PATH, headers={"X-Service-Key": token}
168
+ )
169
+ except httpx.HTTPError as exc:
170
+ raise HTTPException(503, "langsmith_unavailable") from exc
171
+ finally:
172
+ await auth.client.aclose()
173
+ if response.status_code != 200:
174
+ status, detail = _LANGSMITH_REFUSALS.get(
175
+ response.status_code, (503, "langsmith_unavailable")
176
+ )
177
+ raise HTTPException(status, detail)
178
+ try:
179
+ claims = response.json()
180
+ except ValueError as exc:
181
+ raise HTTPException(503, "langsmith_unavailable") from exc
182
+ if not isinstance(claims, dict):
183
+ raise HTTPException(503, "langsmith_unavailable")
184
+
185
+ operation_id = _as_uuid(claims.get("operation_id"))
186
+ user_id = _as_uuid(claims.get("user_id"))
187
+ accepted_before = _as_datetime(claims.get("accepted_before"))
188
+ issued_at = _as_timestamp(claims.get("issued_at"))
189
+ if (
190
+ _as_uuid(claims.get("tenant_id")) != tenant_id
191
+ or _as_uuid(claims.get("deployment_id")) != deployment_id
192
+ or claims.get("action") != _INTERRUPT
193
+ or operation_id is None
194
+ or user_id is None
195
+ or accepted_before is None
196
+ or issued_at is None
197
+ or accepted_before > issued_at + _BOUNDARY_SKEW
198
+ ):
199
+ raise HTTPException(403, "forbidden")
200
+ return _OperatorToken(operation_id, user_id, accepted_before)
201
+
202
+
203
+ def _as_uuid(value: Any) -> UUID | None:
204
+ if isinstance(value, str):
205
+ with contextlib.suppress(ValueError):
206
+ return UUID(value)
207
+ return None
208
+
209
+
210
+ def _as_timestamp(value: Any) -> datetime | None:
211
+ if isinstance(value, int | float) and not isinstance(value, bool):
212
+ with contextlib.suppress(OverflowError, OSError, ValueError):
213
+ return datetime.fromtimestamp(value, UTC)
214
+ return None
215
+
216
+
217
+ def _as_datetime(value: Any) -> datetime | None:
218
+ if isinstance(value, str):
219
+ with contextlib.suppress(ValueError):
220
+ parsed = datetime.fromisoformat(value)
221
+ if parsed.tzinfo is not None:
222
+ return parsed
223
+ return None
@@ -325,6 +325,15 @@ class QueueStats(TypedDict):
325
325
  pending_unblocked_runs_wait_time_max_secs: float | None
326
326
 
327
327
 
328
+ class RunCancelProgress(TypedDict):
329
+ """Targets of a cancel-by-boundary still in flight."""
330
+
331
+ not_yet_reached: int
332
+ """Targets with no cancel intent yet."""
333
+ finishing: int
334
+ """Targets that have a cancel intent and haven't stopped yet."""
335
+
336
+
328
337
  # Canonical field sets for select= validation and type aliases for ops
329
338
 
330
339
  # Assistant select fields (intentionally excludes 'context')