langgraph-api 0.12.0.dev15__tar.gz → 0.12.0.dev17__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.
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/PKG-INFO +1 -1
- langgraph_api-0.12.0.dev17/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/meta.py +1 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/ops/runs.py +7 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/models/run.py +7 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/schema.py +3 -0
- langgraph_api-0.12.0.dev17/langgraph_api/tracing_session.py +22 -0
- langgraph_api-0.12.0.dev17/langgraph_grpc_common/conversion/store.py +442 -0
- langgraph_api-0.12.0.dev17/langgraph_grpc_common/proto/core_api_pb2.py +274 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/core_api_pb2.pyi +17 -5
- langgraph_api-0.12.0.dev17/langgraph_grpc_common/proto/store_pb2.py +82 -0
- langgraph_api-0.12.0.dev17/langgraph_grpc_common/proto/store_pb2.pyi +652 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/store.py +16 -16
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/openapi.json +8 -1
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/uv.lock +4 -4
- langgraph_api-0.12.0.dev15/langgraph_api/__init__.py +0 -1
- langgraph_api-0.12.0.dev15/langgraph_grpc_common/conversion/store.py +0 -208
- langgraph_api-0.12.0.dev15/langgraph_grpc_common/proto/core_api_pb2.py +0 -274
- langgraph_api-0.12.0.dev15/langgraph_grpc_common/proto/store_pb2.py +0 -54
- langgraph_api-0.12.0.dev15/langgraph_grpc_common/proto/store_pb2.pyi +0 -246
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/.gitignore +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/LICENSE +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/Makefile +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/README.md +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/.gitignore +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/Makefile +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/README.md +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/clean.js +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/continuous/uv.lock +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/graphs.js +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/package.json +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/ramp.js +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/staircase.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/benchmark/weather.js +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/constraints.txt +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/custom_store.sql +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/forbidden.txt +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/hatch_build.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/healthcheck.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/event_streaming.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/threads.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/command.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/config/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/config/schemas.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/service.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/ops/threads.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/http.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/package.json +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/js/yarn.lock +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/metrics_collector.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/metrics_otlp.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/route.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/server.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/state.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/store.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/logging.json +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/pyproject.toml +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/scripts/create_license.py +0 -0
- {langgraph_api-0.12.0.dev15 → langgraph_api-0.12.0.dev17}/scripts/run_a2a_tck.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.12.0.dev17"
|
|
@@ -383,6 +383,9 @@ def proto_to_run(proto_run: pb.Run) -> Run:
|
|
|
383
383
|
"multitask_strategy": MULTITASK_STRATEGY_FROM_PB.get(
|
|
384
384
|
proto_run.multitask_strategy
|
|
385
385
|
),
|
|
386
|
+
"langsmith_session_name": proto_run.langsmith_session_name
|
|
387
|
+
if proto_run.HasField("langsmith_session_name")
|
|
388
|
+
else None,
|
|
386
389
|
}
|
|
387
390
|
|
|
388
391
|
|
|
@@ -588,6 +591,7 @@ class Runs(Authenticated):
|
|
|
588
591
|
if_not_exists: IfNotExists = "reject",
|
|
589
592
|
after_seconds: int = 0,
|
|
590
593
|
ctx: Any = None,
|
|
594
|
+
langsmith_session_name: str | None = None,
|
|
591
595
|
) -> AsyncIterator[Run]:
|
|
592
596
|
"""Create a run."""
|
|
593
597
|
metadata = metadata or {}
|
|
@@ -662,6 +666,9 @@ class Runs(Authenticated):
|
|
|
662
666
|
if after_seconds > 0:
|
|
663
667
|
request_kwargs["after_seconds"] = int(after_seconds)
|
|
664
668
|
|
|
669
|
+
if langsmith_session_name is not None:
|
|
670
|
+
request_kwargs["langsmith_session_name"] = langsmith_session_name
|
|
671
|
+
|
|
665
672
|
# Build encryption context for Go layer
|
|
666
673
|
enc_ctx = build_encryption_context("run")
|
|
667
674
|
if enc_ctx is not None:
|
|
@@ -10,6 +10,7 @@ import structlog
|
|
|
10
10
|
from starlette.exceptions import HTTPException
|
|
11
11
|
from typing_extensions import TypedDict
|
|
12
12
|
|
|
13
|
+
from langgraph_api import config as api_config
|
|
13
14
|
from langgraph_api.auth.noop import UnauthenticatedUser
|
|
14
15
|
from langgraph_api.encryption.middleware import encrypt_request
|
|
15
16
|
from langgraph_api.encryption.shared import (
|
|
@@ -35,6 +36,7 @@ from langgraph_api.schema import (
|
|
|
35
36
|
RunCommand,
|
|
36
37
|
StreamMode,
|
|
37
38
|
)
|
|
39
|
+
from langgraph_api.tracing_session import resolve_tracing_session_name
|
|
38
40
|
from langgraph_api.utils import AsyncConnectionProto, get_auth_ctx, get_user_id
|
|
39
41
|
from langgraph_api.utils.headers import get_configurable_headers
|
|
40
42
|
from langgraph_api.utils.uuids import uuid7
|
|
@@ -300,6 +302,10 @@ async def create_valid_run(
|
|
|
300
302
|
if webhook := payload.get("webhook"):
|
|
301
303
|
await validate_webhook_url_or_raise(str(webhook))
|
|
302
304
|
|
|
305
|
+
langsmith_session_name = (
|
|
306
|
+
resolve_tracing_session_name(payload) if api_config.TRACING else None
|
|
307
|
+
)
|
|
308
|
+
|
|
303
309
|
# We can't pass payload directly because config and context have
|
|
304
310
|
# been modified above (with auth context, checkpoint info, etc.)
|
|
305
311
|
fields_to_encrypt = {
|
|
@@ -346,6 +352,7 @@ async def create_valid_run(
|
|
|
346
352
|
prevent_insert_if_inflight=prevent_insert_if_inflight,
|
|
347
353
|
after_seconds=after_seconds,
|
|
348
354
|
if_not_exists=if_not_exists,
|
|
355
|
+
langsmith_session_name=langsmith_session_name,
|
|
349
356
|
)
|
|
350
357
|
run_ = await run_coro
|
|
351
358
|
|
|
@@ -255,6 +255,8 @@ class Run(TypedDict):
|
|
|
255
255
|
"""The run kwargs."""
|
|
256
256
|
multitask_strategy: MultitaskStrategy
|
|
257
257
|
"""Strategy to handle concurrent runs on the same thread."""
|
|
258
|
+
langsmith_session_name: str | None
|
|
259
|
+
"""LangSmith tracing session (project) name for this run, if tracing is enabled."""
|
|
258
260
|
|
|
259
261
|
|
|
260
262
|
class RunSend(TypedDict):
|
|
@@ -359,6 +361,7 @@ RunSelectField = Literal[
|
|
|
359
361
|
"metadata",
|
|
360
362
|
"kwargs",
|
|
361
363
|
"multitask_strategy",
|
|
364
|
+
"langsmith_session_name",
|
|
362
365
|
]
|
|
363
366
|
RUN_FIELDS: set[str] = set(RunSelectField.__args__)
|
|
364
367
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""LangSmith tracing session helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from langsmith.utils import get_tracer_project
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def resolve_tracing_session_name(payload: Mapping[str, Any]) -> str:
|
|
12
|
+
"""Return the LangSmith session (project) name for a run.
|
|
13
|
+
|
|
14
|
+
Per-run ``langsmith_tracer.project_name`` overrides the deployment default
|
|
15
|
+
from ``LANGSMITH_PROJECT`` / ``LANGCHAIN_PROJECT``.
|
|
16
|
+
"""
|
|
17
|
+
ls_tracing = payload.get("langsmith_tracer")
|
|
18
|
+
if isinstance(ls_tracing, Mapping):
|
|
19
|
+
project_name = ls_tracing.get("project_name")
|
|
20
|
+
if isinstance(project_name, str) and project_name:
|
|
21
|
+
return project_name
|
|
22
|
+
return get_tracer_project()
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
"""Marshal langgraph.store.base GetOp/PutOp/Item/Result to and from store.proto."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
7
|
+
|
|
8
|
+
import orjson
|
|
9
|
+
from google.protobuf import empty_pb2
|
|
10
|
+
from langgraph.store.base import (
|
|
11
|
+
GetOp,
|
|
12
|
+
IndexConfig,
|
|
13
|
+
Item,
|
|
14
|
+
ListNamespacesOp,
|
|
15
|
+
MatchCondition,
|
|
16
|
+
Op,
|
|
17
|
+
PutOp,
|
|
18
|
+
Result,
|
|
19
|
+
SearchItem,
|
|
20
|
+
SearchOp,
|
|
21
|
+
ensure_embeddings,
|
|
22
|
+
get_text_at_path,
|
|
23
|
+
tokenize_path,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from langgraph_grpc_common.proto import store_pb2
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from collections.abc import Sequence
|
|
30
|
+
|
|
31
|
+
from langchain_core.embeddings import Embeddings
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _ensure_index_config(
|
|
35
|
+
index_config: IndexConfig,
|
|
36
|
+
) -> tuple[Embeddings | None, IndexConfig]:
|
|
37
|
+
# Vendored from langgraph.store.postgres.base so grpc_common_py stays
|
|
38
|
+
# backend-agnostic (no langgraph-checkpoint-postgres / psycopg dependency).
|
|
39
|
+
index_config = index_config.copy()
|
|
40
|
+
tokenized: list[tuple[str, str | list[str]]] = []
|
|
41
|
+
tot = 0
|
|
42
|
+
fields = index_config.get("fields") or ["$"]
|
|
43
|
+
if isinstance(fields, str):
|
|
44
|
+
fields = [fields]
|
|
45
|
+
if not isinstance(fields, list):
|
|
46
|
+
raise ValueError(f"Text fields must be a list or a string. Got {fields}")
|
|
47
|
+
for p in fields:
|
|
48
|
+
if p == "$":
|
|
49
|
+
tokenized.append((p, "$"))
|
|
50
|
+
tot += 1
|
|
51
|
+
else:
|
|
52
|
+
toks = tokenize_path(p)
|
|
53
|
+
tokenized.append((p, toks))
|
|
54
|
+
tot += len(toks)
|
|
55
|
+
index_config["__tokenized_fields"] = tokenized # ty: ignore[invalid-key]
|
|
56
|
+
index_config["__estimated_num_vectors"] = tot # ty: ignore[invalid-key]
|
|
57
|
+
embeddings = ensure_embeddings(index_config.get("embed"))
|
|
58
|
+
return embeddings, index_config
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _ttl_to_proto_minutes(ttl: float | None) -> int:
|
|
62
|
+
if ttl is None:
|
|
63
|
+
return 0
|
|
64
|
+
if ttl != int(ttl):
|
|
65
|
+
raise ValueError(
|
|
66
|
+
f"gRPC store only supports integer-minute TTL; got fractional ttl={ttl}"
|
|
67
|
+
)
|
|
68
|
+
return int(ttl)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# Ordered comparisons compare the *text* form of the field (value->>key); $eq/$ne
|
|
72
|
+
# are handled separately as jsonb comparisons.
|
|
73
|
+
_FILTER_OP_BY_NAME = {
|
|
74
|
+
"$gt": store_pb2.FILTER_OP_GT,
|
|
75
|
+
"$gte": store_pb2.FILTER_OP_GTE,
|
|
76
|
+
"$lt": store_pb2.FILTER_OP_LT,
|
|
77
|
+
"$lte": store_pb2.FILTER_OP_LTE,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# pgvector distance / column types come from the index config as strings; map
|
|
81
|
+
# them to the wire enums (see store.proto DistanceType / VectorType).
|
|
82
|
+
_DISTANCE_TYPE_BY_NAME = {
|
|
83
|
+
"cosine": store_pb2.DISTANCE_TYPE_COSINE,
|
|
84
|
+
"l2": store_pb2.DISTANCE_TYPE_L2,
|
|
85
|
+
"inner_product": store_pb2.DISTANCE_TYPE_INNER_PRODUCT,
|
|
86
|
+
}
|
|
87
|
+
_VECTOR_TYPE_BY_NAME = {
|
|
88
|
+
"vector": store_pb2.VECTOR_TYPE_VECTOR,
|
|
89
|
+
"halfvec": store_pb2.VECTOR_TYPE_HALFVEC,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# ListNamespaces match type: langgraph uses the strings "prefix"/"suffix".
|
|
93
|
+
_MATCH_TYPE_BY_NAME = {
|
|
94
|
+
"prefix": store_pb2.MATCH_TYPE_PREFIX,
|
|
95
|
+
"suffix": store_pb2.MATCH_TYPE_SUFFIX,
|
|
96
|
+
}
|
|
97
|
+
_MATCH_TYPE_TO_NAME = {op: name for name, op in _MATCH_TYPE_BY_NAME.items()}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _match_type_to_proto(match_type: str) -> int:
|
|
101
|
+
proto = _MATCH_TYPE_BY_NAME.get(match_type)
|
|
102
|
+
if proto is None:
|
|
103
|
+
raise ValueError(f"Unsupported list_namespaces match_type: {match_type!r}")
|
|
104
|
+
return proto
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _filter_to_conditions(
|
|
108
|
+
filter_dict: dict[str, Any],
|
|
109
|
+
) -> list[store_pb2.FilterCondition]:
|
|
110
|
+
"""Flatten a langgraph filter dict into typed FilterConditions.
|
|
111
|
+
|
|
112
|
+
A plain value is an equality match; a dict is a set of operator comparisons.
|
|
113
|
+
$eq/$ne compare as jsonb; $gt/$gte/$lt/$lte compare on the text form of the
|
|
114
|
+
value (str(value), produced here so the store never re-derives it). Mirrors
|
|
115
|
+
OSS PostgresStore._get_filter_condition, done in Python where the DSL is
|
|
116
|
+
native so the store only maps op -> SQL.
|
|
117
|
+
"""
|
|
118
|
+
conditions: list[store_pb2.FilterCondition] = []
|
|
119
|
+
for key, value in filter_dict.items():
|
|
120
|
+
if isinstance(value, dict):
|
|
121
|
+
for op_name, op_val in value.items():
|
|
122
|
+
if op_name in ("$eq", "$ne"):
|
|
123
|
+
op = (
|
|
124
|
+
store_pb2.FILTER_OP_EQ
|
|
125
|
+
if op_name == "$eq"
|
|
126
|
+
else store_pb2.FILTER_OP_NE
|
|
127
|
+
)
|
|
128
|
+
conditions.append(
|
|
129
|
+
store_pb2.FilterCondition(
|
|
130
|
+
key=key, op=op, operand=orjson.dumps(op_val).decode()
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
elif op_name in _FILTER_OP_BY_NAME:
|
|
134
|
+
conditions.append(
|
|
135
|
+
store_pb2.FilterCondition(
|
|
136
|
+
key=key, op=_FILTER_OP_BY_NAME[op_name], operand=str(op_val)
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
else:
|
|
140
|
+
raise ValueError(f"Unsupported filter operator: {op_name}")
|
|
141
|
+
else:
|
|
142
|
+
conditions.append(
|
|
143
|
+
store_pb2.FilterCondition(
|
|
144
|
+
key=key,
|
|
145
|
+
op=store_pb2.FILTER_OP_EQ,
|
|
146
|
+
operand=orjson.dumps(value).decode(),
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
return conditions
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def op_to_proto(
|
|
153
|
+
op: Op,
|
|
154
|
+
*,
|
|
155
|
+
vectors: Sequence[store_pb2.VectorValue] | None = None,
|
|
156
|
+
search_vector: store_pb2.VectorSearch | None = None,
|
|
157
|
+
) -> store_pb2.Op:
|
|
158
|
+
if isinstance(op, GetOp):
|
|
159
|
+
return store_pb2.Op(
|
|
160
|
+
get=store_pb2.GetOp(
|
|
161
|
+
namespace=list(op.namespace),
|
|
162
|
+
key=str(op.key),
|
|
163
|
+
refreshTTL=op.refresh_ttl,
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
if isinstance(op, PutOp):
|
|
167
|
+
# A PutOp with value=None is a delete in OSS; on the gRPC path it maps to
|
|
168
|
+
# an explicit DeleteOp so an empty value can't be mistaken for a delete.
|
|
169
|
+
if op.value is None:
|
|
170
|
+
return store_pb2.Op(
|
|
171
|
+
delete=store_pb2.DeleteOp(
|
|
172
|
+
namespace=list(op.namespace),
|
|
173
|
+
key=str(op.key),
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
put_kwargs: dict[str, Any] = {
|
|
177
|
+
"namespace": list(op.namespace),
|
|
178
|
+
"key": str(op.key),
|
|
179
|
+
"value_json": orjson.dumps(op.value),
|
|
180
|
+
"ttlMinutes": _ttl_to_proto_minutes(op.ttl),
|
|
181
|
+
}
|
|
182
|
+
if vectors is not None:
|
|
183
|
+
put_kwargs["vectors"] = list(vectors)
|
|
184
|
+
return store_pb2.Op(put=store_pb2.PutOp(**put_kwargs))
|
|
185
|
+
if isinstance(op, SearchOp):
|
|
186
|
+
# The natural-language query itself is not sent: Python embeds it into
|
|
187
|
+
# `search_vector`, which is the only semantic-search signal the store needs.
|
|
188
|
+
search_kwargs: dict[str, Any] = {
|
|
189
|
+
"namespace_prefix": list(op.namespace_prefix),
|
|
190
|
+
"limit": op.limit,
|
|
191
|
+
"offset": op.offset,
|
|
192
|
+
"refreshTTL": op.refresh_ttl,
|
|
193
|
+
}
|
|
194
|
+
if op.filter:
|
|
195
|
+
search_kwargs["filter"] = _filter_to_conditions(op.filter)
|
|
196
|
+
if search_vector is not None:
|
|
197
|
+
search_kwargs["vector"] = search_vector
|
|
198
|
+
return store_pb2.Op(search=store_pb2.SearchOp(**search_kwargs))
|
|
199
|
+
if isinstance(op, ListNamespacesOp):
|
|
200
|
+
list_kwargs: dict[str, Any] = {
|
|
201
|
+
"limit": op.limit,
|
|
202
|
+
"offset": op.offset,
|
|
203
|
+
}
|
|
204
|
+
if op.match_conditions:
|
|
205
|
+
list_kwargs["match_conditions"] = [
|
|
206
|
+
store_pb2.MatchCondition(
|
|
207
|
+
match_type=_match_type_to_proto(mc.match_type),
|
|
208
|
+
path=list(mc.path),
|
|
209
|
+
)
|
|
210
|
+
for mc in op.match_conditions
|
|
211
|
+
]
|
|
212
|
+
if op.max_depth is not None:
|
|
213
|
+
list_kwargs["max_depth"] = op.max_depth
|
|
214
|
+
return store_pb2.Op(list_namespaces=store_pb2.ListNamespacesOp(**list_kwargs))
|
|
215
|
+
raise TypeError(f"unsupported op: {type(op).__name__}")
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def op_from_proto(msg: store_pb2.Op) -> Op:
|
|
219
|
+
kind = msg.WhichOneof("op")
|
|
220
|
+
if kind == "get":
|
|
221
|
+
g = msg.get
|
|
222
|
+
return GetOp(
|
|
223
|
+
namespace=tuple(g.namespace),
|
|
224
|
+
key=g.key,
|
|
225
|
+
refresh_ttl=g.refreshTTL,
|
|
226
|
+
)
|
|
227
|
+
if kind == "put":
|
|
228
|
+
p = msg.put
|
|
229
|
+
ttl: float | None = None
|
|
230
|
+
if p.ttlMinutes:
|
|
231
|
+
ttl = float(p.ttlMinutes)
|
|
232
|
+
return PutOp(
|
|
233
|
+
namespace=tuple(p.namespace),
|
|
234
|
+
key=p.key,
|
|
235
|
+
value=orjson.loads(p.value_json),
|
|
236
|
+
ttl=ttl,
|
|
237
|
+
)
|
|
238
|
+
if kind == "delete":
|
|
239
|
+
d = msg.delete
|
|
240
|
+
return PutOp(namespace=tuple(d.namespace), key=d.key, value=None)
|
|
241
|
+
if kind == "search":
|
|
242
|
+
s = msg.search
|
|
243
|
+
# `query` (embedded into `vector`) and `filter` (flattened to typed
|
|
244
|
+
# conditions) are one-directional encodings, not reconstructed here; the
|
|
245
|
+
# store consumes them and Python never decodes a SearchOp in production.
|
|
246
|
+
return SearchOp(
|
|
247
|
+
namespace_prefix=tuple(s.namespace_prefix),
|
|
248
|
+
limit=s.limit,
|
|
249
|
+
offset=s.offset,
|
|
250
|
+
refresh_ttl=s.refreshTTL,
|
|
251
|
+
)
|
|
252
|
+
if kind == "list_namespaces":
|
|
253
|
+
ln = msg.list_namespaces
|
|
254
|
+
return ListNamespacesOp(
|
|
255
|
+
match_conditions=tuple(
|
|
256
|
+
MatchCondition(
|
|
257
|
+
match_type=_MATCH_TYPE_TO_NAME[mc.match_type],
|
|
258
|
+
path=tuple(mc.path),
|
|
259
|
+
)
|
|
260
|
+
for mc in ln.match_conditions
|
|
261
|
+
)
|
|
262
|
+
or None,
|
|
263
|
+
max_depth=ln.max_depth if ln.HasField("max_depth") else None,
|
|
264
|
+
limit=ln.limit,
|
|
265
|
+
offset=ln.offset,
|
|
266
|
+
)
|
|
267
|
+
raise ValueError("empty Op message (no oneof set)")
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def result_to_proto(result: Result, op: Op) -> store_pb2.OpResult:
|
|
271
|
+
if isinstance(op, GetOp):
|
|
272
|
+
if result is None:
|
|
273
|
+
return store_pb2.OpResult(none=empty_pb2.Empty())
|
|
274
|
+
if not isinstance(result, Item):
|
|
275
|
+
raise TypeError(
|
|
276
|
+
f"expected Item for GetOp result, got {type(result).__name__}"
|
|
277
|
+
)
|
|
278
|
+
return store_pb2.OpResult(item=_item_to_proto(result))
|
|
279
|
+
if isinstance(op, PutOp):
|
|
280
|
+
return store_pb2.OpResult(none=empty_pb2.Empty())
|
|
281
|
+
if isinstance(op, SearchOp):
|
|
282
|
+
items = cast("list[SearchItem]", result or [])
|
|
283
|
+
return store_pb2.OpResult(
|
|
284
|
+
search=store_pb2.SearchResult(
|
|
285
|
+
items=[_search_item_to_proto(item) for item in items]
|
|
286
|
+
)
|
|
287
|
+
)
|
|
288
|
+
if isinstance(op, ListNamespacesOp):
|
|
289
|
+
namespaces = cast("list[tuple[str, ...]]", result or [])
|
|
290
|
+
return store_pb2.OpResult(
|
|
291
|
+
list_namespaces=store_pb2.ListNamespacesResult(
|
|
292
|
+
namespaces=[store_pb2.Namespace(parts=list(ns)) for ns in namespaces]
|
|
293
|
+
)
|
|
294
|
+
)
|
|
295
|
+
raise TypeError(f"unsupported op for result encoding: {type(op).__name__}")
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def result_from_proto(msg: store_pb2.OpResult) -> Result:
|
|
299
|
+
kind = msg.WhichOneof("result")
|
|
300
|
+
if kind == "none":
|
|
301
|
+
return None
|
|
302
|
+
if kind == "item":
|
|
303
|
+
return _item_from_proto(msg.item)
|
|
304
|
+
if kind == "search":
|
|
305
|
+
return [_search_item_from_proto(item) for item in msg.search.items]
|
|
306
|
+
if kind == "list_namespaces":
|
|
307
|
+
return [tuple(ns.parts) for ns in msg.list_namespaces.namespaces]
|
|
308
|
+
raise ValueError("empty OpResult message (no oneof set)")
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def _item_to_proto(item: Item) -> store_pb2.Item:
|
|
312
|
+
return store_pb2.Item(
|
|
313
|
+
namespace=list(item.namespace),
|
|
314
|
+
key=item.key,
|
|
315
|
+
value_json=orjson.dumps(item.value),
|
|
316
|
+
created_at=_format_dt(item.created_at),
|
|
317
|
+
updated_at=_format_dt(item.updated_at),
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def _item_from_proto(msg: store_pb2.Item) -> Item:
|
|
322
|
+
return Item(
|
|
323
|
+
namespace=tuple(msg.namespace),
|
|
324
|
+
key=msg.key,
|
|
325
|
+
value=orjson.loads(msg.value_json),
|
|
326
|
+
created_at=datetime.fromisoformat(msg.created_at),
|
|
327
|
+
updated_at=datetime.fromisoformat(msg.updated_at),
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def _search_item_to_proto(item: SearchItem) -> store_pb2.SearchItem:
|
|
332
|
+
kwargs: dict[str, Any] = {
|
|
333
|
+
"namespace": list(item.namespace),
|
|
334
|
+
"key": item.key,
|
|
335
|
+
"value_json": orjson.dumps(item.value),
|
|
336
|
+
"created_at": _format_dt(item.created_at),
|
|
337
|
+
"updated_at": _format_dt(item.updated_at),
|
|
338
|
+
}
|
|
339
|
+
if item.score is not None:
|
|
340
|
+
kwargs["score"] = item.score
|
|
341
|
+
return store_pb2.SearchItem(**kwargs)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def _search_item_from_proto(msg: store_pb2.SearchItem) -> SearchItem:
|
|
345
|
+
return SearchItem(
|
|
346
|
+
namespace=tuple(msg.namespace),
|
|
347
|
+
key=msg.key,
|
|
348
|
+
value=orjson.loads(msg.value_json),
|
|
349
|
+
created_at=datetime.fromisoformat(msg.created_at),
|
|
350
|
+
updated_at=datetime.fromisoformat(msg.updated_at),
|
|
351
|
+
score=msg.score if msg.HasField("score") else None,
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _format_dt(dt: datetime) -> str:
|
|
356
|
+
return dt.isoformat()
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
async def vectors_for_put_op(
|
|
360
|
+
op: PutOp,
|
|
361
|
+
index_config: IndexConfig,
|
|
362
|
+
embeddings: Embeddings,
|
|
363
|
+
) -> list[store_pb2.VectorValue]:
|
|
364
|
+
if op.index is False or op.value is None:
|
|
365
|
+
return []
|
|
366
|
+
|
|
367
|
+
value = op.value
|
|
368
|
+
if op.index is None:
|
|
369
|
+
paths = cast(
|
|
370
|
+
"list[tuple[str, str | list[str]]]",
|
|
371
|
+
index_config["__tokenized_fields"], # ty: ignore[invalid-key]
|
|
372
|
+
)
|
|
373
|
+
else:
|
|
374
|
+
paths = [(ix, tokenize_path(ix)) for ix in op.index]
|
|
375
|
+
|
|
376
|
+
texts: list[str] = []
|
|
377
|
+
pathnames: list[str] = []
|
|
378
|
+
for path, tokenized_path in paths:
|
|
379
|
+
extracted = get_text_at_path(value, tokenized_path)
|
|
380
|
+
for i, text in enumerate(extracted):
|
|
381
|
+
pathname = f"{path}.{i}" if len(extracted) > 1 else path
|
|
382
|
+
pathnames.append(pathname)
|
|
383
|
+
texts.append(text)
|
|
384
|
+
|
|
385
|
+
if not texts:
|
|
386
|
+
return []
|
|
387
|
+
|
|
388
|
+
vectors = await embeddings.aembed_documents(texts)
|
|
389
|
+
return [
|
|
390
|
+
store_pb2.VectorValue(valuePath=pathname, embedding=vector)
|
|
391
|
+
for pathname, vector in zip(pathnames, vectors, strict=False)
|
|
392
|
+
]
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
async def query_embedding_for_search_op(
|
|
396
|
+
op: SearchOp,
|
|
397
|
+
index_config: IndexConfig,
|
|
398
|
+
embeddings: Embeddings,
|
|
399
|
+
) -> store_pb2.VectorSearch | None:
|
|
400
|
+
"""Embed a SearchOp's natural-language query for semantic search.
|
|
401
|
+
|
|
402
|
+
Returns None when the op has no query (a plain filter/pagination search).
|
|
403
|
+
Distance params are read from the index config and sent alongside the
|
|
404
|
+
embedding so the Go store stays stateless.
|
|
405
|
+
"""
|
|
406
|
+
if not op.query:
|
|
407
|
+
return None
|
|
408
|
+
|
|
409
|
+
vectors = await embeddings.aembed_documents([op.query])
|
|
410
|
+
if not vectors:
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
cfg = cast("dict[str, Any]", index_config)
|
|
414
|
+
distance_type = cfg.get("distance_type", "cosine")
|
|
415
|
+
vectors_per_doc = cfg.get("__estimated_num_vectors", 1)
|
|
416
|
+
vector_type = cfg.get("ann_index_config", {}).get("vector_type", "vector")
|
|
417
|
+
|
|
418
|
+
if distance_type not in _DISTANCE_TYPE_BY_NAME:
|
|
419
|
+
raise ValueError(
|
|
420
|
+
f"gRPC store semantic search does not support distance_type={distance_type!r} "
|
|
421
|
+
"(only 'cosine', 'l2', 'inner_product')"
|
|
422
|
+
)
|
|
423
|
+
if vector_type not in _VECTOR_TYPE_BY_NAME:
|
|
424
|
+
raise NotImplementedError(
|
|
425
|
+
f"gRPC store semantic search does not support vector_type={vector_type!r} "
|
|
426
|
+
"(only 'vector' and 'halfvec')"
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
return store_pb2.VectorSearch(
|
|
430
|
+
query_embedding=vectors[0],
|
|
431
|
+
distance_type=_DISTANCE_TYPE_BY_NAME[distance_type],
|
|
432
|
+
vectors_per_doc=vectors_per_doc,
|
|
433
|
+
vector_type=_VECTOR_TYPE_BY_NAME[vector_type],
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def normalize_index_config(
|
|
438
|
+
index: IndexConfig | None,
|
|
439
|
+
) -> tuple[Embeddings | None, IndexConfig | None]:
|
|
440
|
+
if not index:
|
|
441
|
+
return None, None
|
|
442
|
+
return _ensure_index_config(index)
|