langgraph-api 0.7.31__tar.gz → 0.7.33__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/PKG-INFO +1 -1
  2. langgraph_api-0.7.33/langgraph_api/__init__.py +1 -0
  3. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/_checkpointer/__init__.py +8 -0
  4. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/_checkpointer/_adapter.py +105 -41
  5. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/_checkpointer/protocol.py +5 -0
  6. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/a2a.py +12 -12
  7. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/runs.py +50 -4
  8. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/store.py +1 -1
  9. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/ui.py +2 -1
  10. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/auth/custom.py +16 -4
  11. langgraph_api-0.7.33/langgraph_api/auth/noop.py +53 -0
  12. langgraph_api-0.7.33/langgraph_api/auth/studio_user.py +39 -0
  13. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/cli.py +4 -0
  14. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/cron_scheduler.py +12 -0
  15. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/encryption/shared.py +8 -1
  16. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/graph.py +2 -0
  17. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/ops/runs.py +44 -18
  18. langgraph_api-0.7.33/langgraph_api/grpc/servicers/checkpointer.py +262 -0
  19. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/servicers/encryption.py +30 -5
  20. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/models/run.py +6 -2
  21. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/schema.py +3 -0
  22. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/serde.py +30 -1
  23. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/sse.py +6 -2
  24. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/worker.py +9 -3
  25. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/checkpoint.py +42 -2
  26. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/config.py +18 -1
  27. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/messages.py +10 -6
  28. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/struct.py +7 -1
  29. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/__init__.py +2 -0
  30. langgraph_api-0.7.33/langgraph_grpc_common/proto/core_api_pb2.py +259 -0
  31. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/core_api_pb2.pyi +555 -0
  32. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +330 -0
  33. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +76 -0
  34. langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +37 -0
  35. langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +32 -0
  36. langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +24 -0
  37. langgraph_api-0.7.33/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +20 -0
  38. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/serde.py +4 -0
  39. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/scripts/run_a2a_tck.py +15 -5
  40. langgraph_api-0.7.31/langgraph_api/__init__.py +0 -1
  41. langgraph_api-0.7.31/langgraph_api/auth/noop.py +0 -22
  42. langgraph_api-0.7.31/langgraph_api/auth/studio_user.py +0 -15
  43. langgraph_api-0.7.31/langgraph_api/grpc/servicers/checkpointer.py +0 -118
  44. langgraph_api-0.7.31/langgraph_grpc_common/proto/core_api_pb2.py +0 -228
  45. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/.gitignore +0 -0
  46. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/LICENSE +0 -0
  47. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/Makefile +0 -0
  48. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/README.md +0 -0
  49. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/.gitignore +0 -0
  50. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/Makefile +0 -0
  51. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/README.md +0 -0
  52. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/benchmark-runners/assistant.js +0 -0
  53. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/benchmark-runners/benchmark-runner.js +0 -0
  54. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/benchmark-runners/benchmarks.js +0 -0
  55. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/benchmark-runners/stream_write.js +0 -0
  56. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/benchmark-runners/thread.js +0 -0
  57. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/benchmark-runners/wait_write.js +0 -0
  58. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/burst.js +0 -0
  59. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/capacity_dd_report.py +0 -0
  60. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/capacity_k6.js +0 -0
  61. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/capacity_runner.mjs +0 -0
  62. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/capacity_slack_report.py +0 -0
  63. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/capacity_urls.mjs +0 -0
  64. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/clean-cli.js +0 -0
  65. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/clean.js +0 -0
  66. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/continuous/README.md +0 -0
  67. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/continuous/pyproject.toml +0 -0
  68. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/continuous/runner.py +0 -0
  69. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/continuous/uv.lock +0 -0
  70. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/graphs.js +0 -0
  71. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/mixed_workload_k6.js +0 -0
  72. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/mixed_workload_runner.mjs +0 -0
  73. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/package.json +0 -0
  74. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/ramp.js +0 -0
  75. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/reporting/dd_reporting.py +0 -0
  76. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/reporting/slack_slowest_runs.py +0 -0
  77. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/reporting/slack_summary.py +0 -0
  78. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/run_local.sh +0 -0
  79. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/update-revision.js +0 -0
  80. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/benchmark/weather.js +0 -0
  81. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/constraints.txt +0 -0
  82. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/custom_store.sql +0 -0
  83. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/forbidden.txt +0 -0
  84. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/hatch_build.py +0 -0
  85. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/healthcheck.py +0 -0
  86. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph-cloud-debugging-20260210132856.zip +0 -0
  87. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/_factory_utils.py +0 -0
  88. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/__init__.py +0 -0
  89. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/assistants.py +0 -0
  90. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/mcp/__init__.py +0 -0
  91. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/mcp/_constants.py +0 -0
  92. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/mcp/_handlers.py +0 -0
  93. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/mcp/_models.py +0 -0
  94. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/mcp/_routes.py +0 -0
  95. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/mcp/_sanitizers.py +0 -0
  96. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/meta.py +0 -0
  97. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/openapi.py +0 -0
  98. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/profile.py +0 -0
  99. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/api/threads.py +0 -0
  100. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/asgi_transport.py +0 -0
  101. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/asyncio.py +0 -0
  102. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/auth/__init__.py +0 -0
  103. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/auth/langsmith/__init__.py +0 -0
  104. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/auth/langsmith/backend.py +0 -0
  105. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/auth/langsmith/client.py +0 -0
  106. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/auth/middleware.py +0 -0
  107. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/cache.py +0 -0
  108. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/command.py +0 -0
  109. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/config/__init__.py +0 -0
  110. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/config/_parse.py +0 -0
  111. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/config/schemas.py +0 -0
  112. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/encryption/__init__.py +0 -0
  113. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/encryption/aes_json.py +0 -0
  114. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/encryption/context.py +0 -0
  115. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/encryption/custom.py +0 -0
  116. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/encryption/middleware.py +0 -0
  117. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/errors.py +0 -0
  118. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/executor_entrypoint.py +0 -0
  119. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/feature_flags.py +0 -0
  120. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/__init__.py +0 -0
  121. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/client.py +0 -0
  122. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
  123. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/ops/__init__.py +0 -0
  124. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/ops/assistants.py +0 -0
  125. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/ops/cache.py +0 -0
  126. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/ops/threads.py +0 -0
  127. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/server.py +0 -0
  128. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/grpc/servicers/__init__.py +0 -0
  129. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/http.py +0 -0
  130. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/http_metrics.py +0 -0
  131. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/http_metrics_utils.py +0 -0
  132. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/.gitignore +0 -0
  133. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/.prettierrc +0 -0
  134. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/__init__.py +0 -0
  135. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/base.py +0 -0
  136. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/build.mts +0 -0
  137. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/client.http.mts +0 -0
  138. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/client.mts +0 -0
  139. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/errors.py +0 -0
  140. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/global.d.ts +0 -0
  141. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/package.json +0 -0
  142. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/remote.py +0 -0
  143. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/schema.py +0 -0
  144. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/src/graph.mts +0 -0
  145. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/src/load.hooks.mjs +0 -0
  146. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/src/preload.mjs +0 -0
  147. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/src/utils/files.mts +0 -0
  148. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/src/utils/importMap.mts +0 -0
  149. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  150. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/src/utils/serde.mts +0 -0
  151. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/sse.py +0 -0
  152. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/traceblock.mts +0 -0
  153. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/tsconfig.json +0 -0
  154. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/ui.py +0 -0
  155. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/js/yarn.lock +0 -0
  156. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/logging.py +0 -0
  157. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/metadata.py +0 -0
  158. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/middleware/__init__.py +0 -0
  159. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/middleware/ensure_store.py +0 -0
  160. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/middleware/http_logger.py +0 -0
  161. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/middleware/private_network.py +0 -0
  162. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/middleware/request_id.py +0 -0
  163. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/models/__init__.py +0 -0
  164. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/otel_context.py +0 -0
  165. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/patch.py +0 -0
  166. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/queue_entrypoint.py +0 -0
  167. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/route.py +0 -0
  168. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/self_hosted_logs.py +0 -0
  169. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/self_hosted_metrics.py +0 -0
  170. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/server.py +0 -0
  171. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/state.py +0 -0
  172. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/store.py +0 -0
  173. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/stream.py +0 -0
  174. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/timing/__init__.py +0 -0
  175. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/timing/profiler.py +0 -0
  176. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/timing/timer.py +0 -0
  177. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/traceblock.py +0 -0
  178. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/tunneling/cloudflare.py +0 -0
  179. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/__init__.py +0 -0
  180. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/cache.py +0 -0
  181. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/config.py +0 -0
  182. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/errors.py +0 -0
  183. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/future.py +0 -0
  184. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/headers.py +0 -0
  185. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/retriable_client.py +0 -0
  186. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/stream_codec.py +0 -0
  187. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/utils/uuids.py +0 -0
  188. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/validation.py +0 -0
  189. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_api/webhook.py +0 -0
  190. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/__init__.py +0 -0
  191. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/__init__.py +0 -0
  192. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/_compat.py +0 -0
  193. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/channel.py +0 -0
  194. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/durability.py +0 -0
  195. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/exception.py +0 -0
  196. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/graph.py +0 -0
  197. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/interrupt.py +0 -0
  198. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/orchestrator_response.py +0 -0
  199. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/runopts.py +0 -0
  200. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/stream_mode.py +0 -0
  201. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/task.py +0 -0
  202. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/conversion/value.py +0 -0
  203. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
  204. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
  205. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
  206. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
  207. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
  208. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
  209. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
  210. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
  211. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_api_pb2.py +0 -0
  212. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_api_pb2.pyi +0 -0
  213. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_api_pb2_grpc.py +0 -0
  214. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_api_pb2_grpc.pyi +0 -0
  215. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
  216. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
  217. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
  218. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
  219. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
  220. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
  221. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
  222. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
  223. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
  224. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
  225. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
  226. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
  227. /langgraph_api-0.7.31/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
  228. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
  229. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
  230. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
  231. /langgraph_api-0.7.31/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
  232. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
  233. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
  234. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
  235. /langgraph_api-0.7.31/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
  236. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
  237. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
  238. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
  239. /langgraph_api-0.7.31/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
  240. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2.py +0 -0
  241. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2.pyi +0 -0
  242. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2_grpc.py +0 -0
  243. /langgraph_api-0.7.31/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_store_operation_entry_type_pb2_grpc.pyi +0 -0
  244. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
  245. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
  246. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
  247. /langgraph_api-0.7.31/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
  248. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
  249. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
  250. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
  251. /langgraph_api-0.7.31/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
  252. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
  253. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
  254. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
  255. /langgraph_api-0.7.31/langgraph_grpc_common/proto/errors_pb2_grpc.pyi → /langgraph_api-0.7.33/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
  256. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
  257. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
  258. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
  259. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/executor_api_pb2.py +0 -0
  260. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/executor_api_pb2.pyi +0 -0
  261. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/executor_api_pb2_grpc.py +0 -0
  262. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/proto/executor_api_pb2_grpc.pyi +0 -0
  263. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_grpc_common/sanitize.py +0 -0
  264. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_license/__init__.py +0 -0
  265. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_license/validation.py +0 -0
  266. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/__init__.py +0 -0
  267. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/checkpoint.py +0 -0
  268. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/database.py +0 -0
  269. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/lifespan.py +0 -0
  270. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/metrics.py +0 -0
  271. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/ops.py +0 -0
  272. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/queue.py +0 -0
  273. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/retry.py +0 -0
  274. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/routes.py +0 -0
  275. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/langgraph_runtime/store.py +0 -0
  276. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/logging.json +0 -0
  277. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/openapi.json +0 -0
  278. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/pyproject.toml +0 -0
  279. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/scripts/build_wheel.py +0 -0
  280. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/scripts/create_license.py +0 -0
  281. {langgraph_api-0.7.31 → langgraph_api-0.7.33}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.7.31
3
+ Version: 0.7.33
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.7.33"
@@ -25,6 +25,8 @@ async def get_checkpointer(
25
25
 
26
26
  async def start_checkpointer() -> None:
27
27
  """Start the checkpointer resources."""
28
+ # Load the custom checkpointer from LANGGRAPH_CHECKPOINTER env var, if configured.
29
+ await _adapter.collect_checkpointer_from_env()
28
30
  # If the custom checkpointer is provided, it will be started here / enter the stack.
29
31
  checkpointer = await get_checkpointer()
30
32
  if not isinstance(checkpointer, (BaseCheckpointSaver, CheckpointerProtocol)):
@@ -44,8 +46,14 @@ async def exit_checkpointer() -> None:
44
46
  await _adapter.exit_checkpointer()
45
47
 
46
48
 
49
+ def get_checkpointer_capabilities() -> _adapter.CheckpointerCapabilities | None:
50
+ """Return the capabilities of the custom checkpointer, or None if not configured."""
51
+ return _adapter.get_checkpointer_capabilities()
52
+
53
+
47
54
  __all__ = [
48
55
  "exit_checkpointer",
49
56
  "get_checkpointer",
57
+ "get_checkpointer_capabilities",
50
58
  "start_checkpointer",
51
59
  ]
@@ -5,7 +5,7 @@ import importlib.util
5
5
  import random
6
6
  import sys
7
7
  import threading
8
- from collections.abc import AsyncIterator, Callable, Sequence
8
+ from collections.abc import AsyncIterator, Callable
9
9
  from contextlib import AsyncExitStack, asynccontextmanager
10
10
  from dataclasses import dataclass
11
11
  from typing import TYPE_CHECKING, Any, Self, cast
@@ -25,7 +25,7 @@ from langgraph_api.timing import profiled_import
25
25
  from langgraph_api.utils.config import run_in_executor
26
26
 
27
27
  if TYPE_CHECKING:
28
- from collections.abc import AsyncIterator, Callable, Sequence
28
+ from collections.abc import AsyncIterator, Callable, Iterable, Sequence
29
29
 
30
30
  from langchain_core.runnables import RunnableConfig
31
31
  from langgraph.checkpoint.base import (
@@ -63,6 +63,9 @@ class CheckpointerCapabilities:
63
63
 
64
64
  has_aget_iter: bool
65
65
  has_adelete_thread: bool
66
+ has_adelete_for_runs: bool
67
+ has_acopy_thread: bool
68
+ has_aprune: bool
66
69
 
67
70
  @classmethod
68
71
  def from_type(cls: type[Self], inner_type: type) -> Self:
@@ -70,6 +73,9 @@ class CheckpointerCapabilities:
70
73
  return cls(
71
74
  has_aget_iter=_is_overridden(inner_type, "aget_iter"),
72
75
  has_adelete_thread=_is_overridden(inner_type, "adelete_thread"),
76
+ has_adelete_for_runs=_has_method(inner_type, "adelete_for_runs"),
77
+ has_acopy_thread=_has_method(inner_type, "acopy_thread"),
78
+ has_aprune=_has_method(inner_type, "aprune"),
73
79
  )
74
80
 
75
81
 
@@ -80,7 +86,6 @@ class _CustomCheckpointerAdapter(BaseCheckpointSaver):
80
86
  _validate_required_methods(inner)
81
87
  self._inner = inner
82
88
  self._capabilities = capabilities
83
- self.latest_iter: AsyncIterator[CheckpointTuple] | None = None
84
89
  super().__init__(serde=getattr(inner, "serde", None))
85
90
 
86
91
  def __getattr__(self, name: str) -> Any:
@@ -106,7 +111,7 @@ class _CustomCheckpointerAdapter(BaseCheckpointSaver):
106
111
  metadata: CheckpointMetadata,
107
112
  new_versions: ChannelVersions,
108
113
  ) -> RunnableConfig:
109
- metadata = _ensure_run_id(metadata, config)
114
+ metadata = _enrich_metadata(metadata, config)
110
115
  return await self._inner.aput(config, checkpoint, metadata, new_versions)
111
116
 
112
117
  async def aput_writes(
@@ -142,23 +147,36 @@ class _CustomCheckpointerAdapter(BaseCheckpointSaver):
142
147
  "Please implement adelete_thread in your custom checkpointer to support thread deletion."
143
148
  )
144
149
 
145
- async def aget_tuple(self, config: RunnableConfig) -> CheckpointTuple | None:
146
- # Use cached latest_iter if available and matches
147
- if self.latest_iter is not None:
148
- try:
149
- item = await anext(self.latest_iter, None)
150
- if item is not None:
151
- item_config = item.config.get("configurable", {})
152
- requested = config.get("configurable", {})
153
- if item_config.get("thread_id") == requested.get(
154
- "thread_id"
155
- ) and item_config.get("checkpoint_ns", "") == requested.get(
156
- "checkpoint_ns", ""
157
- ):
158
- return item
159
- finally:
160
- self.latest_iter = None
150
+ async def adelete_for_runs(self, run_ids: Iterable[str]) -> None:
151
+ if self._capabilities.has_adelete_for_runs:
152
+ await self._inner.adelete_for_runs(run_ids)
153
+ return
154
+ raise RuntimeError(
155
+ "Please implement adelete_for_runs in your custom checkpointer "
156
+ "to support run deletion/rollback."
157
+ )
158
+
159
+ async def acopy_thread(self, source_thread_id: str, target_thread_id: str) -> None:
160
+ if self._capabilities.has_acopy_thread:
161
+ await self._inner.acopy_thread(source_thread_id, target_thread_id)
162
+ return
163
+ raise RuntimeError(
164
+ "Please implement acopy_thread in your custom checkpointer "
165
+ "to support thread copy."
166
+ )
167
+
168
+ async def aprune(
169
+ self, thread_ids: Sequence[str], *, strategy: str = "keep_latest"
170
+ ) -> None:
171
+ if self._capabilities.has_aprune:
172
+ await self._inner.aprune(thread_ids, strategy=strategy)
173
+ return
174
+ raise RuntimeError(
175
+ "Please implement aprune in your custom checkpointer "
176
+ "to support thread pruning."
177
+ )
161
178
 
179
+ async def aget_tuple(self, config: RunnableConfig) -> CheckpointTuple | None:
162
180
  return await self._inner.aget_tuple(config)
163
181
 
164
182
  def get_next_version(self, current: str | None, channel: None) -> str:
@@ -180,7 +198,7 @@ async def get_checkpointer(
180
198
  use_direct_connection: bool = False,
181
199
  ) -> CheckpointerProtocol:
182
200
  global _CHECKPOINTER_CAPABILITIES
183
- if CUSTOM_CHECKPOINTER:
201
+ if CUSTOM_CHECKPOINTER is not None:
184
202
  # Get or create the inner checkpointer (cached per-thread)
185
203
  if not hasattr(CHECKPOINTER_STACK, "inner"):
186
204
  stack = AsyncExitStack()
@@ -198,7 +216,7 @@ async def get_checkpointer(
198
216
  f"Using custom checkpointer: {inner}",
199
217
  kind=str(type(inner)),
200
218
  )
201
- # Create fresh adapter each time (not cached) - each gets own latest_iter
219
+ # Create a fresh adapter each time (not cached) - each gets own latest_iter
202
220
  if _CHECKPOINTER_CAPABILITIES is None:
203
221
  raise RuntimeError("Capabilities not initialized")
204
222
  return _CustomCheckpointerAdapter(
@@ -212,8 +230,13 @@ async def get_checkpointer(
212
230
  )
213
231
 
214
232
 
233
+ def get_checkpointer_capabilities() -> CheckpointerCapabilities | None:
234
+ """Return the capabilities of the custom checkpointer, or None if not configured."""
235
+ return _CHECKPOINTER_CAPABILITIES
236
+
237
+
215
238
  async def exit_checkpointer() -> None:
216
- if not CUSTOM_CHECKPOINTER:
239
+ if CUSTOM_CHECKPOINTER is None:
217
240
  return
218
241
  stack = cast("AsyncExitStack|None", getattr(CHECKPOINTER_STACK, "stack", None))
219
242
  if stack is None:
@@ -231,8 +254,8 @@ async def collect_checkpointer_from_env() -> None:
231
254
 
232
255
  await logger.ainfo(
233
256
  f"Heads up! You are configuring a custom checkpointer at {checkpointer_path}\n\n"
234
- "This checkpointer will be used IN STEAD OF the default persistence backend."
235
- "The availability of some functionality, such as TTLs and pruning, may depend on the completion of your implementation."
257
+ "This checkpointer will be used INSTEAD OF the default persistence backend.\n"
258
+ "The availability of some functionality, such as TTLs and pruning, may depend on the completion of your implementation.\n"
236
259
  "Performance & feature support will depend on the quality of your implementation."
237
260
  )
238
261
 
@@ -252,7 +275,7 @@ async def collect_checkpointer_from_env() -> None:
252
275
  async def _yield_checkpointer(value: Any):
253
276
  if isinstance(value, BaseCheckpointSaver):
254
277
  yield value
255
- # Async ontext manager
278
+ # Async context manager
256
279
  elif hasattr(value, "__aenter__") and hasattr(value, "__aexit__"):
257
280
  async with value as ctx_value:
258
281
  yield ctx_value
@@ -338,28 +361,64 @@ def _load_checkpointer(checkpointer_path: str) -> Any:
338
361
  raise ValueError(
339
362
  f"Could not find checkpointer '{checkpointer_path}'. "
340
363
  f"Please check that:\n"
341
- f"1. The file exports a variable named '{checkpointer_path}'\n"
364
+ f"1. The file exports a variable named '{function}'\n"
342
365
  f"2. The variable name in your config matches the export name{suggestion}"
343
366
  ) from e
344
367
  return checkpointer
345
368
 
346
369
 
347
- def _ensure_run_id(
370
+ # Keys from config["configurable"] that should NOT be copied into checkpoint metadata.
371
+ _EXCLUDED_CONFIGURABLE_KEYS = frozenset({"checkpoint_ns", "checkpoint_id"})
372
+ # Keys that are request-scoped and must not be persisted in checkpoints.
373
+ _TRANSIENT_CONFIGURABLE_KEYS = frozenset(
374
+ {
375
+ "langgraph_request_id",
376
+ "langgraph_auth_user",
377
+ "langgraph_auth_user_id",
378
+ "langgraph_auth_permissions",
379
+ }
380
+ )
381
+
382
+
383
+ def _enrich_metadata(
348
384
  metadata: CheckpointMetadata, config: RunnableConfig
349
385
  ) -> CheckpointMetadata:
350
- run_id = metadata.get("run_id")
351
- if run_id:
352
- return metadata
353
- run_id = config.get("run_id")
354
- if run_id:
355
- return {**metadata, "run_id": run_id}
356
- run_id = config.get("metadata", {}).get("run_id")
357
- if run_id:
358
- return {**metadata, "run_id": run_id}
359
- run_id = config["configurable"].get("run_id")
360
- if run_id:
361
- return {**metadata, "run_id": run_id}
362
- raise RuntimeError("Could not find run_id in config")
386
+ """Enrich checkpoint metadata with config fields.
387
+
388
+ Mirrors the metadata enrichment performed by the built-in checkpointers
389
+ so that downstream consumers (API, state endpoints, copy) see a
390
+ consistent metadata shape regardless of checkpointer implementation.
391
+ """
392
+ configurable = config.get("configurable", {})
393
+ config_metadata = config.get("metadata", {})
394
+ enriched: dict = {
395
+ # 1. Non-internal configurable keys (thread_id, graph_id, etc.)
396
+ **{
397
+ k: v
398
+ for k, v in configurable.items()
399
+ if not k.startswith("__")
400
+ and k not in _EXCLUDED_CONFIGURABLE_KEYS
401
+ and k not in _TRANSIENT_CONFIGURABLE_KEYS
402
+ },
403
+ # 2. Config metadata (assistant_id, model_name, etc.)
404
+ **{
405
+ k: v
406
+ for k, v in config_metadata.items()
407
+ if k not in _TRANSIENT_CONFIGURABLE_KEYS
408
+ },
409
+ # 3. Original metadata on top (source, step, parents, etc.)
410
+ **{k: v for k, v in metadata.items() if k not in _TRANSIENT_CONFIGURABLE_KEYS},
411
+ }
412
+ # Ensure run_id is present when available (not always set, e.g. state updates)
413
+ if not enriched.get("run_id"):
414
+ run_id = (
415
+ config.get("run_id")
416
+ or config_metadata.get("run_id")
417
+ or configurable.get("run_id")
418
+ )
419
+ if run_id:
420
+ enriched["run_id"] = run_id
421
+ return enriched
363
422
 
364
423
 
365
424
  def _validate_required_methods(inner: BaseCheckpointSaver):
@@ -381,3 +440,8 @@ def _is_overridden(inner_type: type, method: str) -> bool:
381
440
  if base is None or impl is None:
382
441
  return impl is not None
383
442
  return impl is not base
443
+
444
+
445
+ def _has_method(inner_type: type, method: str) -> bool:
446
+ """Check if a type has a callable method (for methods not on BaseCheckpointSaver)."""
447
+ return callable(getattr(inner_type, method, None))
@@ -83,6 +83,11 @@ class CheckpointerProtocol(Protocol):
83
83
  ) -> None: ...
84
84
 
85
85
  async def adelete_thread(self, thread_id: str) -> None: ...
86
+
87
+ # NOTE: adelete_for_runs, acopy_thread, and aprune are optional extended
88
+ # capabilities checked at runtime via CheckpointerCapabilities. They are
89
+ # NOT part of this protocol to avoid breaking isinstance checks.
90
+
86
91
  async def aget_iter(
87
92
  self, config: RunnableConfig
88
93
  ) -> AsyncIterator[CheckpointTuple]: ...
@@ -661,7 +661,7 @@ def _map_runs_create_error_to_rpc(
661
661
  return {
662
662
  "error": {
663
663
  "code": ERROR_CODE_INTERNAL_ERROR,
664
- "message": f"Internal server error: {exception!s}",
664
+ "message": "Internal server error",
665
665
  }
666
666
  }
667
667
 
@@ -717,7 +717,7 @@ def _map_runs_get_error_to_rpc(
717
717
  return {
718
718
  "error": {
719
719
  "code": ERROR_CODE_INTERNAL_ERROR,
720
- "message": f"Internal server error: {exception!s}",
720
+ "message": "Internal server error",
721
721
  }
722
722
  }
723
723
 
@@ -1287,12 +1287,12 @@ async def handle_message_send(
1287
1287
  assistant_id=assistant_id,
1288
1288
  )
1289
1289
 
1290
- except Exception as e:
1290
+ except Exception:
1291
1291
  logger.exception(f"Error in message/send for assistant {assistant_id}")
1292
1292
  return {
1293
1293
  "error": {
1294
1294
  "code": ERROR_CODE_INTERNAL_ERROR,
1295
- "message": f"Internal server error: {e!s}",
1295
+ "message": "Internal server error",
1296
1296
  }
1297
1297
  }
1298
1298
 
@@ -1488,7 +1488,7 @@ async def handle_tasks_get(
1488
1488
  return {
1489
1489
  "error": {
1490
1490
  "code": ERROR_CODE_INTERNAL_ERROR,
1491
- "message": f"Internal server error: {e!s}",
1491
+ "message": "Internal server error",
1492
1492
  }
1493
1493
  }
1494
1494
 
@@ -1654,12 +1654,12 @@ async def handle_get_extended_card(
1654
1654
  "message": str(e),
1655
1655
  }
1656
1656
  }
1657
- except Exception as e:
1657
+ except Exception:
1658
1658
  logger.exception(f"Error generating extended agent card for {assistant_id}")
1659
1659
  return {
1660
1660
  "error": {
1661
1661
  "code": ERROR_CODE_INTERNAL_ERROR,
1662
- "message": f"Internal server error: {e!s}",
1662
+ "message": "Internal server error",
1663
1663
  }
1664
1664
  }
1665
1665
 
@@ -1806,12 +1806,12 @@ async def handle_agent_card_endpoint(request: ApiRequest) -> Response:
1806
1806
  status_code=400,
1807
1807
  media_type="application/json",
1808
1808
  )
1809
- except Exception as e:
1809
+ except Exception:
1810
1810
  logger.exception("Failed to generate agent card")
1811
1811
  error_response = {
1812
1812
  "error": {
1813
1813
  "code": ERROR_CODE_INTERNAL_ERROR,
1814
- "message": f"Internal server error: {e!s}",
1814
+ "message": "Internal server error",
1815
1815
  }
1816
1816
  }
1817
1817
  return Response(
@@ -2209,7 +2209,7 @@ async def handle_message_stream(
2209
2209
  "id": rpc_id,
2210
2210
  "error": {
2211
2211
  "code": ERROR_CODE_INTERNAL_ERROR,
2212
- "message": f"Internal server error: {e!s}",
2212
+ "message": "Internal server error",
2213
2213
  },
2214
2214
  },
2215
2215
  )
@@ -2300,12 +2300,12 @@ async def handle_assistant_agent_card_endpoint(request: ApiRequest) -> Response:
2300
2300
  status_code=400,
2301
2301
  media_type="application/json",
2302
2302
  )
2303
- except Exception as e:
2303
+ except Exception:
2304
2304
  logger.exception("Failed to generate agent card")
2305
2305
  error_response = {
2306
2306
  "error": {
2307
2307
  "code": ERROR_CODE_INTERNAL_ERROR,
2308
- "message": f"Internal server error: {e!s}",
2308
+ "message": "Internal server error",
2309
2309
  }
2310
2310
  }
2311
2311
  return Response(
@@ -10,12 +10,16 @@ from starlette.responses import Response, StreamingResponse
10
10
 
11
11
  from langgraph_api import config
12
12
  from langgraph_api.asyncio import ValueEvent
13
+ from langgraph_api.encryption.context import get_encryption_context
13
14
  from langgraph_api.encryption.middleware import (
14
15
  decrypt_response,
15
16
  decrypt_responses,
16
17
  encrypt_request,
17
18
  )
18
- from langgraph_api.encryption.shared import using_aes_encryption
19
+ from langgraph_api.encryption.shared import (
20
+ BLOB_ENCRYPTION_CONTEXT_KEY,
21
+ using_aes_encryption,
22
+ )
19
23
  from langgraph_api.feature_flags import IS_POSTGRES_OR_GRPC_BACKEND
20
24
  from langgraph_api.graph import _validate_assistant_id
21
25
  from langgraph_api.models.run import create_valid_run
@@ -62,6 +66,29 @@ else:
62
66
  logger = structlog.stdlib.get_logger(__name__)
63
67
 
64
68
 
69
+ def parse_stream_mode_param(stream_mode_param: str | None) -> list[str]:
70
+ """Parse stream_mode query parameter. We use this to support the query param format used by the SDK.
71
+
72
+ Supports:
73
+ - Single values: "values" -> ["values"]
74
+ - JSON arrays: '["values","messages-tuple","updates"]' -> ["values", "messages-tuple", "updates"]
75
+ - Empty/None: None -> []
76
+ """
77
+ if not stream_mode_param:
78
+ return []
79
+
80
+ # Try to parse as JSON array first
81
+ if stream_mode_param.startswith("["):
82
+ try:
83
+ parsed = orjson.loads(stream_mode_param)
84
+ if isinstance(parsed, list):
85
+ return parsed
86
+ except (orjson.JSONDecodeError, ValueError):
87
+ pass
88
+ # Single value
89
+ return [stream_mode_param]
90
+
91
+
65
92
  # Type alias for stream handlers (GrpcStreamHandler or ContextQueue).
66
93
  # Runs is selected at runtime, and the implementations have different
67
94
  # type signatures, so we use Any for compatibility.
@@ -539,7 +566,10 @@ async def join_run_stream(request: ApiRequest):
539
566
  cancel_on_disconnect = cancel_on_disconnect_str.lower() in {"true", "yes", "1"}
540
567
  validate_uuid(thread_id, "Invalid thread ID: must be a UUID")
541
568
  validate_uuid(run_id, "Invalid run ID: must be a UUID")
542
- stream_mode = request.query_params.get("stream_mode") or []
569
+
570
+ stream_mode_param = request.query_params.get("stream_mode")
571
+ stream_mode = parse_stream_mode_param(stream_mode_param)
572
+
543
573
  last_event_id = request.headers.get("last-event-id") or None
544
574
 
545
575
  async def body():
@@ -688,8 +718,16 @@ async def create_cron(request: ApiRequest):
688
718
  await validate_webhook_url_or_raise(str(webhook))
689
719
  _validate_assistant_id(payload.get("assistant_id"))
690
720
 
721
+ # Store encryption context at payload root so cron scheduler can extract it
722
+ # regardless of which fields (metadata, input, config, context) are present.
723
+ # Use a separate variable to avoid shadowing the typed payload.
724
+ enc_ctx = get_encryption_context()
725
+ payload_for_encryption: dict = (
726
+ {**payload, BLOB_ENCRYPTION_CONTEXT_KEY: enc_ctx} if enc_ctx else payload
727
+ )
728
+
691
729
  encrypted_payload = await encrypt_request(
692
- payload,
730
+ payload_for_encryption,
693
731
  "cron",
694
732
  CRON_PAYLOAD_ENCRYPTION_SUBFIELDS,
695
733
  )
@@ -724,8 +762,16 @@ async def create_thread_cron(request: ApiRequest):
724
762
  await validate_webhook_url_or_raise(str(webhook))
725
763
  _validate_assistant_id(payload.get("assistant_id"))
726
764
 
765
+ # Store encryption context at payload root so cron scheduler can extract it
766
+ # regardless of which fields (metadata, input, config, context) are present.
767
+ # Use a separate variable to avoid shadowing the typed payload.
768
+ enc_ctx = get_encryption_context()
769
+ payload_for_encryption: dict = (
770
+ {**payload, BLOB_ENCRYPTION_CONTEXT_KEY: enc_ctx} if enc_ctx else payload
771
+ )
772
+
727
773
  encrypted_payload = await encrypt_request(
728
- payload,
774
+ payload_for_encryption,
729
775
  "cron",
730
776
  CRON_PAYLOAD_ENCRYPTION_SUBFIELDS,
731
777
  )
@@ -65,7 +65,7 @@ async def put_item(request: ApiRequest):
65
65
  }
66
66
  await handle_event("put", handler_payload)
67
67
  await (await get_store()).aput(
68
- namespace, handler_payload["key"], handler_payload["value"]
68
+ handler_payload["namespace"], handler_payload["key"], handler_payload["value"]
69
69
  )
70
70
  return Response(status_code=204)
71
71
 
@@ -68,9 +68,10 @@ async def handle_ui(request: ApiRequest) -> Response:
68
68
  f'<link rel="stylesheet" href="{protocol}//{host}/ui/{graph_id}/{basename}" />'
69
69
  )
70
70
  elif ext == ".js":
71
+ safe_name = json.dumps(message["name"]).replace("'", "&#39;")
71
72
  result.append(
72
73
  f'<script src="{protocol}//{host}/ui/{graph_id}/{basename}" '
73
- f"onload='__LGUI_{valid_js_name}.render({json.dumps(message['name'])}, \"{{{{shadowRootId}}}}\")'>"
74
+ f"onload='__LGUI_{valid_js_name}.render({safe_name}, \"{{{{shadowRootId}}}}\")'>"
74
75
  "</script>"
75
76
  )
76
77
 
@@ -517,10 +517,10 @@ class ProxyUser(BaseUser):
517
517
  }
518
518
 
519
519
  def __contains__(self, key: str) -> bool:
520
- return key in self._user
520
+ return key in self.dict()
521
521
 
522
522
  def __getitem__(self, key):
523
- return self._user[key]
523
+ return self.dict()[key]
524
524
 
525
525
  def __setitem__(self, key, value):
526
526
  self._user[key] = value
@@ -530,10 +530,22 @@ class ProxyUser(BaseUser):
530
530
  return getattr(self._user, name)
531
531
 
532
532
  def __iter__(self):
533
- return iter(self._user)
533
+ return iter(self.dict())
534
534
 
535
535
  def __len__(self):
536
- return len(self._user)
536
+ return len(self.dict())
537
+
538
+ def get(self, key, /, default=None):
539
+ return self.dict().get(key, default)
540
+
541
+ def keys(self):
542
+ return self.dict().keys()
543
+
544
+ def values(self):
545
+ return self.dict().values()
546
+
547
+ def items(self):
548
+ return self.dict().items()
537
549
 
538
550
  def __str__(self) -> str:
539
551
  return f"{self._user}"
@@ -0,0 +1,53 @@
1
+ from starlette.authentication import (
2
+ AuthCredentials,
3
+ AuthenticationBackend,
4
+ BaseUser,
5
+ )
6
+ from starlette.authentication import (
7
+ UnauthenticatedUser as StarletteUnauthenticatedUser,
8
+ )
9
+ from starlette.requests import HTTPConnection
10
+
11
+
12
+ class UnauthenticatedUser(StarletteUnauthenticatedUser):
13
+ @property
14
+ def identity(self) -> str:
15
+ return ""
16
+
17
+ def dict(self):
18
+ return {
19
+ "identity": self.identity,
20
+ "is_authenticated": self.is_authenticated,
21
+ "display_name": self.display_name,
22
+ }
23
+
24
+ def __getitem__(self, key):
25
+ return self.dict()[key]
26
+
27
+ def __contains__(self, key):
28
+ return key in self.dict()
29
+
30
+ def __iter__(self):
31
+ return iter(self.dict())
32
+
33
+ def __len__(self):
34
+ return len(self.dict())
35
+
36
+ def get(self, key, /, default=None):
37
+ return self.dict().get(key, default)
38
+
39
+ def keys(self):
40
+ return self.dict().keys()
41
+
42
+ def values(self):
43
+ return self.dict().values()
44
+
45
+ def items(self):
46
+ return self.dict().items()
47
+
48
+
49
+ class NoopAuthBackend(AuthenticationBackend):
50
+ async def authenticate(
51
+ self, conn: HTTPConnection
52
+ ) -> tuple[AuthCredentials, BaseUser] | None:
53
+ return AuthCredentials(), UnauthenticatedUser()
@@ -0,0 +1,39 @@
1
+ from langgraph_sdk.auth.types import StudioUser as StudioUserBase
2
+ from starlette.authentication import BaseUser
3
+
4
+
5
+ class StudioUser(StudioUserBase, BaseUser):
6
+ """StudioUser class."""
7
+
8
+ def dict(self):
9
+ return {
10
+ "kind": "StudioUser",
11
+ "is_authenticated": self.is_authenticated,
12
+ "display_name": self.display_name,
13
+ "identity": self.identity,
14
+ "permissions": self.permissions,
15
+ }
16
+
17
+ def __getitem__(self, key):
18
+ return self.dict()[key]
19
+
20
+ def __contains__(self, key):
21
+ return key in self.dict()
22
+
23
+ def __iter__(self):
24
+ return iter(self.dict())
25
+
26
+ def __len__(self):
27
+ return len(self.dict())
28
+
29
+ def get(self, key, /, default=None):
30
+ return self.dict().get(key, default)
31
+
32
+ def keys(self):
33
+ return self.dict().keys()
34
+
35
+ def values(self):
36
+ return self.dict().values()
37
+
38
+ def items(self):
39
+ return self.dict().items()
@@ -107,6 +107,7 @@ def run_server(
107
107
  ui: dict | None = None,
108
108
  webhooks: dict | None = None,
109
109
  ui_config: dict | None = None,
110
+ checkpointer: dict | None = None,
110
111
  studio_url: str | None = None,
111
112
  disable_persistence: bool = False,
112
113
  allow_blocking: bool = False,
@@ -209,6 +210,7 @@ def run_server(
209
210
  LANGGRAPH_UI=json.dumps(ui) if ui else None,
210
211
  LANGGRAPH_WEBHOOKS=json.dumps(webhooks) if webhooks else None,
211
212
  LANGGRAPH_UI_CONFIG=json.dumps(ui_config) if ui_config else None,
213
+ LANGGRAPH_CHECKPOINTER=json.dumps(checkpointer) if checkpointer else None,
212
214
  LANGGRAPH_UI_BUNDLER="true",
213
215
  LANGGRAPH_API_URL=local_url,
214
216
  LANGGRAPH_DISABLE_FILE_PERSISTENCE=str(disable_persistence).lower(),
@@ -411,6 +413,7 @@ def main():
411
413
  ui = config_data.get("ui")
412
414
  webhooks = config_data.get("webhooks")
413
415
  ui_config = config_data.get("ui_config")
416
+ checkpointer = config_data.get("checkpointer")
414
417
  kwargs = {}
415
418
  if args.runtime_edition == "postgres":
416
419
  kwargs["__redis_uri__"] = os.getenv("REDIS_URI")
@@ -433,6 +436,7 @@ def main():
433
436
  ui=ui,
434
437
  webhooks=webhooks,
435
438
  ui_config=ui_config,
439
+ checkpointer=checkpointer,
436
440
  runtime_edition=args.runtime_edition,
437
441
  **kwargs,
438
442
  )