langgraph-api 0.14.0.dev1__tar.gz → 0.14.0.dev3__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.14.0.dev1 → langgraph_api-0.14.0.dev3}/PKG-INFO +2 -2
- langgraph_api-0.14.0.dev3/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/a2a.py +324 -43
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/assistants.py +39 -4
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/ops/assistants.py +4 -1
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/package.json +2 -2
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/yarn.lock +16 -16
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/metrics_otlp.py +1 -1
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/checkpoint.py +1 -2
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/value.py +1 -2
- langgraph_api-0.14.0.dev3/langgraph_grpc_common/proto/core_api_pb2.py +274 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/core_api_pb2.pyi +10 -2
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/pyproject.toml +2 -2
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/uv.lock +56 -56
- langgraph_api-0.14.0.dev1/langgraph_api/__init__.py +0 -1
- langgraph_api-0.14.0.dev1/langgraph_grpc_common/proto/core_api_pb2.py +0 -274
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/.gitignore +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/LICENSE +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/Makefile +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/README.md +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/.gitignore +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/Makefile +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/README.md +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/store.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/clean.js +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/continuous/uv.lock +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/graphs.js +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/package.json +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/ramp.js +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/staircase.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/weather.js +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/benchmark/yarn.lock +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/constraints.txt +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/custom_store.sql +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/forbidden.txt +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/hatch_build.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/healthcheck.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/event_streaming.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/threads.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/command.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/config/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/config/schemas.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/service.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/ops/runs.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/ops/threads.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/http.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/.yarnclean +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/metrics_collector.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/route.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/schema.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/server.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/state.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/store.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/tracing_session.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/store.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/store_pb2.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_grpc_common/store.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/logging.json +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/openapi.json +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/scripts/create_license.py +0 -0
- {langgraph_api-0.14.0.dev1 → langgraph_api-0.14.0.dev3}/scripts/run_a2a_tck.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.14.0.
|
|
3
|
+
Version: 0.14.0.dev3
|
|
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
|
|
7
7
|
Requires-Python: >=3.11
|
|
8
8
|
Requires-Dist: cloudpickle>=3.0.0
|
|
9
|
-
Requires-Dist: cryptography>=
|
|
9
|
+
Requires-Dist: cryptography>=50.0.0
|
|
10
10
|
Requires-Dist: grpcio-health-checking<1.82.0,>=1.81.0
|
|
11
11
|
Requires-Dist: grpcio-tools==1.81.1
|
|
12
12
|
Requires-Dist: grpcio<1.82.0,>=1.81.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.14.0.dev3"
|
|
@@ -11,6 +11,8 @@ Push notifications are not implemented.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import asyncio
|
|
14
|
+
import base64
|
|
15
|
+
import binascii
|
|
14
16
|
import functools
|
|
15
17
|
import os
|
|
16
18
|
import uuid
|
|
@@ -92,6 +94,13 @@ ERROR_CODE_INVALID_AGENT_RESPONSE = -32006
|
|
|
92
94
|
# ============================================================================
|
|
93
95
|
|
|
94
96
|
A2A_PROTOCOL_VERSION = "1.0"
|
|
97
|
+
_DEFAULT_A2A_INPUT_MODES = ("application/json", "text/plain")
|
|
98
|
+
_DEFAULT_A2A_OUTPUT_MODES = ("application/json", "text/plain")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class InvalidAgentResponseError(ValueError):
|
|
102
|
+
"""Raised when public agent output cannot be represented as an A2A part."""
|
|
103
|
+
|
|
95
104
|
|
|
96
105
|
# ============================================================================
|
|
97
106
|
# Legacy (v0.x) format helpers
|
|
@@ -592,6 +601,7 @@ _AGENT_MESSAGE_TYPES = {"ai", "aimessage", "aimessagechunk"}
|
|
|
592
601
|
_ROLE_DEFINED_MESSAGE_TYPES = {"chat", "chatmessage", "chatmessagechunk"}
|
|
593
602
|
_USER_MESSAGE_ROLES = {"human", "user"}
|
|
594
603
|
_AGENT_MESSAGE_ROLES = {"agent", "assistant"}
|
|
604
|
+
_MEDIA_CONTENT_BLOCK_TYPES = {"audio", "file", "image", "video"}
|
|
595
605
|
|
|
596
606
|
|
|
597
607
|
def _normalize_message_label(value: Any) -> str:
|
|
@@ -630,6 +640,117 @@ def _a2a_role_for_message(
|
|
|
630
640
|
return type_role or role_role
|
|
631
641
|
|
|
632
642
|
|
|
643
|
+
def _content_block_to_a2a_file_part(block: dict[str, Any]) -> dict[str, Any]:
|
|
644
|
+
"""Convert one canonical LangChain media block to an A2A FilePart."""
|
|
645
|
+
|
|
646
|
+
source = next(
|
|
647
|
+
(key for key in ("base64", "data", "url") if block.get(key) is not None),
|
|
648
|
+
None,
|
|
649
|
+
)
|
|
650
|
+
if source is None:
|
|
651
|
+
raise InvalidAgentResponseError(
|
|
652
|
+
"Media content blocks must contain 'base64', 'data', or 'url'."
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
value = block[source]
|
|
656
|
+
file_obj: dict[str, Any] = {}
|
|
657
|
+
if source == "url":
|
|
658
|
+
if not isinstance(value, str) or not value:
|
|
659
|
+
raise InvalidAgentResponseError(
|
|
660
|
+
"Media content block 'url' must be a non-empty string."
|
|
661
|
+
)
|
|
662
|
+
file_obj["uri"] = value
|
|
663
|
+
else:
|
|
664
|
+
if source == "data" and isinstance(value, (bytes, bytearray)):
|
|
665
|
+
value = base64.b64encode(value).decode("ascii")
|
|
666
|
+
if not isinstance(value, str):
|
|
667
|
+
raise InvalidAgentResponseError(
|
|
668
|
+
f"Media content block '{source}' must be base64-encoded text or bytes."
|
|
669
|
+
)
|
|
670
|
+
compact_value = "".join(value.split())
|
|
671
|
+
padded_value = compact_value + ("=" * (-len(compact_value) % 4))
|
|
672
|
+
try:
|
|
673
|
+
decoded = base64.b64decode(
|
|
674
|
+
padded_value,
|
|
675
|
+
altchars=b"-_",
|
|
676
|
+
validate=True,
|
|
677
|
+
)
|
|
678
|
+
except (binascii.Error, ValueError) as e:
|
|
679
|
+
raise InvalidAgentResponseError(
|
|
680
|
+
f"Media content block '{source}' must contain valid base64 data."
|
|
681
|
+
) from e
|
|
682
|
+
file_obj["bytes"] = base64.b64encode(decoded).decode("ascii")
|
|
683
|
+
|
|
684
|
+
mime_type = block.get("mime_type")
|
|
685
|
+
if mime_type is not None:
|
|
686
|
+
if not isinstance(mime_type, str):
|
|
687
|
+
raise InvalidAgentResponseError(
|
|
688
|
+
"Media content block 'mime_type' must be a string."
|
|
689
|
+
)
|
|
690
|
+
if mime_type:
|
|
691
|
+
file_obj["mimeType"] = mime_type
|
|
692
|
+
|
|
693
|
+
filename = block.get("filename")
|
|
694
|
+
if filename is None:
|
|
695
|
+
extras = block.get("extras")
|
|
696
|
+
if isinstance(extras, dict):
|
|
697
|
+
filename = extras.get("filename")
|
|
698
|
+
if filename is not None:
|
|
699
|
+
if not isinstance(filename, str):
|
|
700
|
+
raise InvalidAgentResponseError(
|
|
701
|
+
"Media content block filename must be a string."
|
|
702
|
+
)
|
|
703
|
+
if filename:
|
|
704
|
+
file_obj["name"] = filename
|
|
705
|
+
|
|
706
|
+
return {"kind": "file", "file": file_obj}
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
def _content_to_a2a_parts(content: Any) -> list[dict[str, Any]]:
|
|
710
|
+
"""Convert public LangChain message content to ordered A2A parts."""
|
|
711
|
+
|
|
712
|
+
if isinstance(content, str):
|
|
713
|
+
return [{"kind": "text", "text": content}]
|
|
714
|
+
if content is None:
|
|
715
|
+
return []
|
|
716
|
+
if not isinstance(content, list):
|
|
717
|
+
return [{"kind": "text", "text": str(content)}]
|
|
718
|
+
|
|
719
|
+
parts: list[dict[str, Any]] = []
|
|
720
|
+
text_parts: list[str] = []
|
|
721
|
+
|
|
722
|
+
def flush_text() -> None:
|
|
723
|
+
if text_parts:
|
|
724
|
+
parts.append({"kind": "text", "text": "".join(text_parts)})
|
|
725
|
+
text_parts.clear()
|
|
726
|
+
|
|
727
|
+
for block in content:
|
|
728
|
+
if isinstance(block, str):
|
|
729
|
+
text_parts.append(block)
|
|
730
|
+
elif isinstance(block, dict) and block.get("type") == "text":
|
|
731
|
+
text = block.get("text")
|
|
732
|
+
if isinstance(text, str):
|
|
733
|
+
text_parts.append(text)
|
|
734
|
+
elif (
|
|
735
|
+
isinstance(block, dict) and block.get("type") in _MEDIA_CONTENT_BLOCK_TYPES
|
|
736
|
+
):
|
|
737
|
+
flush_text()
|
|
738
|
+
parts.append(_content_block_to_a2a_file_part(block))
|
|
739
|
+
|
|
740
|
+
flush_text()
|
|
741
|
+
return parts
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
def _a2a_parts_have_content(parts: list[dict[str, Any]]) -> bool:
|
|
745
|
+
"""Return whether converted parts contain public text or file content."""
|
|
746
|
+
|
|
747
|
+
return any(
|
|
748
|
+
part.get("kind") == "file"
|
|
749
|
+
or (part.get("kind") == "text" and bool(part.get("text")))
|
|
750
|
+
for part in parts
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
|
|
633
754
|
def _content_to_text(content: Any) -> str:
|
|
634
755
|
"""Convert public LangChain message content to A2A text."""
|
|
635
756
|
|
|
@@ -650,41 +771,41 @@ def _content_to_text(content: Any) -> str:
|
|
|
650
771
|
return str(content)
|
|
651
772
|
|
|
652
773
|
|
|
653
|
-
def _extract_a2a_response(result: dict[str, Any]) -> str:
|
|
654
|
-
"""Extract
|
|
774
|
+
def _extract_a2a_response(result: dict[str, Any]) -> list[dict[str, Any]]:
|
|
775
|
+
"""Extract public A2A parts from the last assistant response.
|
|
655
776
|
|
|
656
777
|
Args:
|
|
657
778
|
result: Graph execution result
|
|
658
779
|
|
|
659
780
|
Returns:
|
|
660
|
-
|
|
781
|
+
Ordered public parts from the last assistant message
|
|
661
782
|
|
|
662
783
|
Raises:
|
|
663
784
|
ValueError: If result doesn't contain messages or is invalid
|
|
664
785
|
"""
|
|
665
786
|
if "__error__" in result:
|
|
666
787
|
# Let the caller handle errors
|
|
667
|
-
return str(result)
|
|
788
|
+
return [{"kind": "text", "text": str(result)}]
|
|
668
789
|
|
|
669
790
|
if "messages" not in result:
|
|
670
791
|
# Fallback to the full result if no messages schema. It is not optimal to do A2A on assistants without
|
|
671
792
|
# a messages key, but it is not a hard requirement.
|
|
672
|
-
return str(result)
|
|
793
|
+
return [{"kind": "text", "text": str(result)}]
|
|
673
794
|
|
|
674
795
|
messages = result["messages"]
|
|
675
796
|
if not isinstance(messages, list) or not messages:
|
|
676
|
-
return str(result)
|
|
797
|
+
return [{"kind": "text", "text": str(result)}]
|
|
677
798
|
|
|
678
799
|
# Find the last assistant message
|
|
679
800
|
for message in reversed(messages):
|
|
680
801
|
if not isinstance(message, dict):
|
|
681
802
|
continue
|
|
682
803
|
if _a2a_role_for_message(message) == "ROLE_AGENT" and "content" in message:
|
|
683
|
-
|
|
684
|
-
if
|
|
685
|
-
return
|
|
804
|
+
parts = _content_to_a2a_parts(message["content"])
|
|
805
|
+
if _a2a_parts_have_content(parts):
|
|
806
|
+
return parts
|
|
686
807
|
|
|
687
|
-
return ""
|
|
808
|
+
return [{"kind": "text", "text": ""}]
|
|
688
809
|
|
|
689
810
|
|
|
690
811
|
def _create_interrupt_artifact(interrupts: list[dict[str, Any]]) -> dict[str, Any]:
|
|
@@ -714,25 +835,27 @@ def _create_interrupt_artifact(interrupts: list[dict[str, Any]]) -> dict[str, An
|
|
|
714
835
|
}
|
|
715
836
|
|
|
716
837
|
|
|
717
|
-
def _create_response_artifact(
|
|
718
|
-
|
|
838
|
+
def _create_response_artifact(
|
|
839
|
+
parts: list[dict[str, Any]], assistant_id: str
|
|
840
|
+
) -> dict[str, Any]:
|
|
841
|
+
"""Create an A2A artifact carrying the agent's final response parts.
|
|
719
842
|
|
|
720
843
|
Shared by ``message/send`` and ``message/stream`` so both paths return the
|
|
721
844
|
same first-class Artifact shape. Per A2A spec section 3.7, task outputs
|
|
722
845
|
SHOULD be returned via Artifacts rather than embedded in a status Message.
|
|
723
846
|
|
|
724
847
|
Args:
|
|
725
|
-
|
|
848
|
+
parts: The final response parts (from ``_extract_a2a_response``).
|
|
726
849
|
assistant_id: The assistant ID, used only for the description.
|
|
727
850
|
|
|
728
851
|
Returns:
|
|
729
|
-
A2A artifact dict
|
|
852
|
+
A2A artifact dict containing the ordered public response parts.
|
|
730
853
|
"""
|
|
731
854
|
return {
|
|
732
855
|
"artifactId": str(uuid.uuid4()),
|
|
733
856
|
"name": "Assistant Response",
|
|
734
857
|
"description": f"Response from assistant {assistant_id}",
|
|
735
|
-
"parts":
|
|
858
|
+
"parts": parts,
|
|
736
859
|
}
|
|
737
860
|
|
|
738
861
|
|
|
@@ -740,7 +863,7 @@ def _create_response_artifact_update(
|
|
|
740
863
|
*,
|
|
741
864
|
task_id: str,
|
|
742
865
|
context_id: str,
|
|
743
|
-
|
|
866
|
+
parts: list[dict[str, Any]],
|
|
744
867
|
assistant_id: str,
|
|
745
868
|
) -> dict[str, Any]:
|
|
746
869
|
"""Create a final streaming update containing the response artifact."""
|
|
@@ -749,12 +872,44 @@ def _create_response_artifact_update(
|
|
|
749
872
|
"taskId": task_id,
|
|
750
873
|
"contextId": context_id,
|
|
751
874
|
"kind": "artifact-update",
|
|
752
|
-
"artifact": _create_response_artifact(
|
|
875
|
+
"artifact": _create_response_artifact(parts, assistant_id),
|
|
753
876
|
"append": False,
|
|
754
877
|
"lastChunk": True,
|
|
755
878
|
}
|
|
756
879
|
|
|
757
880
|
|
|
881
|
+
def _tool_result_data(message: dict[str, Any]) -> dict[str, Any] | None:
|
|
882
|
+
"""Build the published form of one tool result, or None if not publishable.
|
|
883
|
+
|
|
884
|
+
A tool result is only published when it is correlated to the call that
|
|
885
|
+
produced it: ``tool_call_id`` is what lets a client match the payload back
|
|
886
|
+
to its request. Uncorrelated tool output stays internal.
|
|
887
|
+
|
|
888
|
+
Only the correlation id, content, tool name, and status are copied. Raw
|
|
889
|
+
LangChain internals (``response_metadata``, ``additional_kwargs``,
|
|
890
|
+
``artifact``) are deliberately excluded.
|
|
891
|
+
"""
|
|
892
|
+
tool_call_id = message.get("tool_call_id")
|
|
893
|
+
if not isinstance(tool_call_id, str) or not tool_call_id:
|
|
894
|
+
return None
|
|
895
|
+
|
|
896
|
+
result: dict[str, Any] = {"toolCallId": tool_call_id}
|
|
897
|
+
content = message.get("content")
|
|
898
|
+
if content not in (None, ""):
|
|
899
|
+
result["content"] = content
|
|
900
|
+
for key in ("name", "status"):
|
|
901
|
+
value = message.get(key)
|
|
902
|
+
if isinstance(value, str) and value:
|
|
903
|
+
result[key] = value
|
|
904
|
+
return result
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
def _tool_results_data_part(tool_results: list[dict[str, Any]]) -> dict[str, Any]:
|
|
908
|
+
"""Wrap one or more tool results in a single A2A DataPart."""
|
|
909
|
+
|
|
910
|
+
return {"kind": "data", "data": {"tool_results": tool_results}}
|
|
911
|
+
|
|
912
|
+
|
|
758
913
|
def _lc_stream_items_to_a2a_message(
|
|
759
914
|
items: list[dict[str, Any]],
|
|
760
915
|
*,
|
|
@@ -765,8 +920,11 @@ def _lc_stream_items_to_a2a_message(
|
|
|
765
920
|
"""Convert LangChain stream "messages/*" items into a valid A2A Message.
|
|
766
921
|
|
|
767
922
|
This takes the list found in a messages/* StreamPart's data field and
|
|
768
|
-
constructs a single A2A Message object
|
|
769
|
-
|
|
923
|
+
constructs a single A2A Message object. Only public agent prose becomes
|
|
924
|
+
text; internal system/tool prose and LangChain metadata are omitted.
|
|
925
|
+
Correlated tool results are published separately as a structured DataPart
|
|
926
|
+
so data-consuming clients keep receiving them without tool output ever
|
|
927
|
+
being rendered as agent speech.
|
|
770
928
|
|
|
771
929
|
Args:
|
|
772
930
|
items: List of LangChain message dicts from stream (e.g., with keys like
|
|
@@ -780,8 +938,14 @@ def _lc_stream_items_to_a2a_message(
|
|
|
780
938
|
"""
|
|
781
939
|
# Aggregate any text content across items
|
|
782
940
|
text_parts: list[str] = []
|
|
941
|
+
tool_results: list[dict[str, Any]] = []
|
|
783
942
|
for it in items:
|
|
784
|
-
if not isinstance(it, dict)
|
|
943
|
+
if not isinstance(it, dict):
|
|
944
|
+
continue
|
|
945
|
+
if _a2a_role_for_message(it) is None:
|
|
946
|
+
tool_result = _tool_result_data(it)
|
|
947
|
+
if tool_result is not None:
|
|
948
|
+
tool_results.append(tool_result)
|
|
785
949
|
continue
|
|
786
950
|
text = _content_to_text(it.get("content"))
|
|
787
951
|
if text:
|
|
@@ -790,6 +954,8 @@ def _lc_stream_items_to_a2a_message(
|
|
|
790
954
|
parts: list[dict[str, Any]] = []
|
|
791
955
|
if text_parts:
|
|
792
956
|
parts.append({"kind": "text", "text": "".join(text_parts)})
|
|
957
|
+
if tool_results:
|
|
958
|
+
parts.append(_tool_results_data_part(tool_results))
|
|
793
959
|
|
|
794
960
|
# Ensure we always produce a minimally valid A2A Message
|
|
795
961
|
if not parts:
|
|
@@ -965,6 +1131,12 @@ def _convert_messages_to_a2a_format(
|
|
|
965
1131
|
) -> list[dict[str, Any]]:
|
|
966
1132
|
"""Convert LangChain messages to A2A message format.
|
|
967
1133
|
|
|
1134
|
+
Public human/agent turns become text (and file) parts. Internal messages
|
|
1135
|
+
never become prose: a system prompt or uncorrelated tool output is dropped
|
|
1136
|
+
outright, while a tool result correlated by ``tool_call_id`` is published
|
|
1137
|
+
as a data-only agent message so clients can consume the structured payload
|
|
1138
|
+
without it being rendered as agent speech.
|
|
1139
|
+
|
|
968
1140
|
Args:
|
|
969
1141
|
messages: List of LangChain messages
|
|
970
1142
|
task_id: The task ID to assign to all messages
|
|
@@ -980,20 +1152,27 @@ def _convert_messages_to_a2a_format(
|
|
|
980
1152
|
for msg in messages:
|
|
981
1153
|
if isinstance(msg, dict):
|
|
982
1154
|
a2a_role = _a2a_role_for_message(msg)
|
|
983
|
-
if a2a_role is None:
|
|
984
|
-
continue
|
|
985
1155
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1156
|
+
if a2a_role is None:
|
|
1157
|
+
# Internal message: publish a correlated tool result as data,
|
|
1158
|
+
# drop system prompts and uncorrelated output entirely.
|
|
1159
|
+
tool_result = _tool_result_data(msg)
|
|
1160
|
+
if tool_result is None:
|
|
1161
|
+
continue
|
|
1162
|
+
a2a_role = "ROLE_AGENT"
|
|
1163
|
+
parts = [_tool_results_data_part([tool_result])]
|
|
1164
|
+
else:
|
|
1165
|
+
parts = _content_to_a2a_parts(msg.get("content", ""))
|
|
1166
|
+
if a2a_role == "ROLE_AGENT" and not _a2a_parts_have_content(parts):
|
|
1167
|
+
continue
|
|
1168
|
+
if not parts:
|
|
1169
|
+
parts = [{"kind": "text", "text": ""}]
|
|
991
1170
|
|
|
992
1171
|
a2a_message = {
|
|
993
1172
|
"kind": "message",
|
|
994
1173
|
"role": a2a_role,
|
|
995
|
-
"parts":
|
|
996
|
-
"messageId": id,
|
|
1174
|
+
"parts": parts,
|
|
1175
|
+
"messageId": msg.get("id") or str(uuid7()),
|
|
997
1176
|
"taskId": task_id,
|
|
998
1177
|
"contextId": context_id,
|
|
999
1178
|
}
|
|
@@ -1556,6 +1735,13 @@ async def handle_message_send(
|
|
|
1556
1735
|
history_length=history_length,
|
|
1557
1736
|
)
|
|
1558
1737
|
|
|
1738
|
+
except InvalidAgentResponseError as e:
|
|
1739
|
+
return {
|
|
1740
|
+
"error": {
|
|
1741
|
+
"code": ERROR_CODE_INVALID_AGENT_RESPONSE,
|
|
1742
|
+
"message": str(e),
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1559
1745
|
except Exception:
|
|
1560
1746
|
logger.exception(f"Error in message/send for assistant {assistant_id}")
|
|
1561
1747
|
return {
|
|
@@ -1704,6 +1890,13 @@ async def handle_tasks_get(
|
|
|
1704
1890
|
context_id,
|
|
1705
1891
|
history_length=history_length,
|
|
1706
1892
|
)
|
|
1893
|
+
except InvalidAgentResponseError as e:
|
|
1894
|
+
return {
|
|
1895
|
+
"error": {
|
|
1896
|
+
"code": ERROR_CODE_INVALID_AGENT_RESPONSE,
|
|
1897
|
+
"message": str(e),
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1707
1900
|
except Exception as e:
|
|
1708
1901
|
await logger.aexception(
|
|
1709
1902
|
f"Failed to get thread state for tasks/get: {e}"
|
|
@@ -2106,6 +2299,13 @@ async def handle_list_tasks(
|
|
|
2106
2299
|
}
|
|
2107
2300
|
}
|
|
2108
2301
|
|
|
2302
|
+
except InvalidAgentResponseError as e:
|
|
2303
|
+
return {
|
|
2304
|
+
"error": {
|
|
2305
|
+
"code": ERROR_CODE_INVALID_AGENT_RESPONSE,
|
|
2306
|
+
"message": str(e),
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2109
2309
|
except Exception:
|
|
2110
2310
|
logger.exception("Error in ListTasks")
|
|
2111
2311
|
return {
|
|
@@ -2156,6 +2356,60 @@ async def handle_get_extended_card(
|
|
|
2156
2356
|
# ============================================================================
|
|
2157
2357
|
|
|
2158
2358
|
|
|
2359
|
+
def _validate_agent_card_modes(
|
|
2360
|
+
value: Any,
|
|
2361
|
+
*,
|
|
2362
|
+
field: str,
|
|
2363
|
+
default: tuple[str, ...],
|
|
2364
|
+
) -> list[str]:
|
|
2365
|
+
"""Validate one optional assistant A2A media-mode override."""
|
|
2366
|
+
|
|
2367
|
+
if value is None:
|
|
2368
|
+
return list(default)
|
|
2369
|
+
if not isinstance(value, list) or not value:
|
|
2370
|
+
raise ValueError(
|
|
2371
|
+
f"Assistant metadata.a2a.{field} must be a non-empty array of strings."
|
|
2372
|
+
)
|
|
2373
|
+
|
|
2374
|
+
modes: list[str] = []
|
|
2375
|
+
for mode in value:
|
|
2376
|
+
if not isinstance(mode, str) or not mode.strip():
|
|
2377
|
+
raise ValueError(
|
|
2378
|
+
f"Assistant metadata.a2a.{field} must be a non-empty array of strings."
|
|
2379
|
+
)
|
|
2380
|
+
modes.append(mode.strip())
|
|
2381
|
+
return modes
|
|
2382
|
+
|
|
2383
|
+
|
|
2384
|
+
def _resolve_agent_card_modes(
|
|
2385
|
+
assistant: dict[str, Any],
|
|
2386
|
+
) -> tuple[list[str], list[str]]:
|
|
2387
|
+
"""Resolve per-assistant A2A modes with backward-compatible defaults."""
|
|
2388
|
+
|
|
2389
|
+
metadata = assistant.get("metadata") or {}
|
|
2390
|
+
if not isinstance(metadata, dict):
|
|
2391
|
+
raise ValueError("Assistant metadata must be an object.")
|
|
2392
|
+
|
|
2393
|
+
a2a_metadata = metadata.get("a2a")
|
|
2394
|
+
if a2a_metadata is None:
|
|
2395
|
+
return list(_DEFAULT_A2A_INPUT_MODES), list(_DEFAULT_A2A_OUTPUT_MODES)
|
|
2396
|
+
if not isinstance(a2a_metadata, dict):
|
|
2397
|
+
raise ValueError("Assistant metadata.a2a must be an object.")
|
|
2398
|
+
|
|
2399
|
+
return (
|
|
2400
|
+
_validate_agent_card_modes(
|
|
2401
|
+
a2a_metadata.get("input_modes"),
|
|
2402
|
+
field="input_modes",
|
|
2403
|
+
default=_DEFAULT_A2A_INPUT_MODES,
|
|
2404
|
+
),
|
|
2405
|
+
_validate_agent_card_modes(
|
|
2406
|
+
a2a_metadata.get("output_modes"),
|
|
2407
|
+
field="output_modes",
|
|
2408
|
+
default=_DEFAULT_A2A_OUTPUT_MODES,
|
|
2409
|
+
),
|
|
2410
|
+
)
|
|
2411
|
+
|
|
2412
|
+
|
|
2159
2413
|
async def generate_agent_card(request: ApiRequest, assistant_id: str) -> dict[str, Any]:
|
|
2160
2414
|
"""Generate A2A Agent Card for a specific assistant.
|
|
2161
2415
|
|
|
@@ -2183,6 +2437,7 @@ async def generate_agent_card(request: ApiRequest, assistant_id: str) -> dict[st
|
|
|
2183
2437
|
assistant_description = (
|
|
2184
2438
|
assistant.get("description") or f"{assistant_name} assistant"
|
|
2185
2439
|
)
|
|
2440
|
+
input_modes, output_modes = _resolve_agent_card_modes(assistant)
|
|
2186
2441
|
|
|
2187
2442
|
# For now, each assistant has one main skill - itself
|
|
2188
2443
|
skills = [
|
|
@@ -2192,8 +2447,8 @@ async def generate_agent_card(request: ApiRequest, assistant_id: str) -> dict[st
|
|
|
2192
2447
|
"description": assistant_description,
|
|
2193
2448
|
"tags": ["assistant", "langgraph"],
|
|
2194
2449
|
"examples": [],
|
|
2195
|
-
"inputModes":
|
|
2196
|
-
"outputModes":
|
|
2450
|
+
"inputModes": input_modes,
|
|
2451
|
+
"outputModes": output_modes,
|
|
2197
2452
|
"metadata": {
|
|
2198
2453
|
"inputSchema": {
|
|
2199
2454
|
"required": required,
|
|
@@ -2242,8 +2497,8 @@ async def generate_agent_card(request: ApiRequest, assistant_id: str) -> dict[st
|
|
|
2242
2497
|
"pushNotifications": False, # Not implemented yet
|
|
2243
2498
|
"stateTransitionHistory": False,
|
|
2244
2499
|
},
|
|
2245
|
-
"defaultInputModes":
|
|
2246
|
-
"defaultOutputModes":
|
|
2500
|
+
"defaultInputModes": input_modes,
|
|
2501
|
+
"defaultOutputModes": output_modes,
|
|
2247
2502
|
"skills": skills,
|
|
2248
2503
|
"version": __version__,
|
|
2249
2504
|
}
|
|
@@ -2558,19 +2813,32 @@ async def handle_message_stream(
|
|
|
2558
2813
|
is_interrupt = (
|
|
2559
2814
|
isinstance(result, dict) and "__interrupt__" in result
|
|
2560
2815
|
)
|
|
2561
|
-
# Extract the final response
|
|
2816
|
+
# Extract the final response parts (shared by both
|
|
2562
2817
|
# the completed and interrupt paths).
|
|
2563
|
-
|
|
2818
|
+
final_parts: list[dict[str, Any]] | None = None
|
|
2564
2819
|
if isinstance(result, dict):
|
|
2565
2820
|
try:
|
|
2566
|
-
|
|
2821
|
+
final_parts = _extract_a2a_response(result)
|
|
2822
|
+
except InvalidAgentResponseError as e:
|
|
2823
|
+
yield (
|
|
2824
|
+
b"message",
|
|
2825
|
+
{
|
|
2826
|
+
"jsonrpc": "2.0",
|
|
2827
|
+
"id": rpc_id,
|
|
2828
|
+
"error": {
|
|
2829
|
+
"code": ERROR_CODE_INVALID_AGENT_RESPONSE,
|
|
2830
|
+
"message": str(e),
|
|
2831
|
+
},
|
|
2832
|
+
},
|
|
2833
|
+
)
|
|
2834
|
+
return
|
|
2567
2835
|
except Exception:
|
|
2568
2836
|
await logger.aexception(
|
|
2569
2837
|
"Failed to extract final message from result",
|
|
2570
2838
|
result=result,
|
|
2571
2839
|
)
|
|
2572
|
-
if
|
|
2573
|
-
|
|
2840
|
+
if final_parts is None:
|
|
2841
|
+
final_parts = [{"kind": "text", "text": str(result)}]
|
|
2574
2842
|
|
|
2575
2843
|
if is_interrupt:
|
|
2576
2844
|
# Interrupt path is unchanged: emit the interrupt
|
|
@@ -2579,7 +2847,7 @@ async def handle_message_stream(
|
|
|
2579
2847
|
final_message = {
|
|
2580
2848
|
"kind": "message",
|
|
2581
2849
|
"role": "ROLE_AGENT",
|
|
2582
|
-
"parts":
|
|
2850
|
+
"parts": final_parts,
|
|
2583
2851
|
"messageId": str(uuid.uuid4()),
|
|
2584
2852
|
"taskId": task_id,
|
|
2585
2853
|
"contextId": context_id,
|
|
@@ -2634,7 +2902,7 @@ async def handle_message_stream(
|
|
|
2634
2902
|
"result": _create_response_artifact_update(
|
|
2635
2903
|
task_id=task_id,
|
|
2636
2904
|
context_id=context_id,
|
|
2637
|
-
|
|
2905
|
+
parts=final_parts,
|
|
2638
2906
|
assistant_id=assistant_id,
|
|
2639
2907
|
),
|
|
2640
2908
|
},
|
|
@@ -2756,13 +3024,26 @@ async def handle_message_stream(
|
|
|
2756
3024
|
# its plain terminal status-update.
|
|
2757
3025
|
if fallback_state == "TASK_STATE_COMPLETED" and isinstance(result, dict):
|
|
2758
3026
|
try:
|
|
2759
|
-
|
|
3027
|
+
fallback_parts = _extract_a2a_response(result)
|
|
3028
|
+
except InvalidAgentResponseError as e:
|
|
3029
|
+
yield (
|
|
3030
|
+
b"message",
|
|
3031
|
+
{
|
|
3032
|
+
"jsonrpc": "2.0",
|
|
3033
|
+
"id": rpc_id,
|
|
3034
|
+
"error": {
|
|
3035
|
+
"code": ERROR_CODE_INVALID_AGENT_RESPONSE,
|
|
3036
|
+
"message": str(e),
|
|
3037
|
+
},
|
|
3038
|
+
},
|
|
3039
|
+
)
|
|
3040
|
+
return
|
|
2760
3041
|
except Exception:
|
|
2761
3042
|
await logger.aexception(
|
|
2762
3043
|
"Failed to extract final message from result",
|
|
2763
3044
|
result=result,
|
|
2764
3045
|
)
|
|
2765
|
-
|
|
3046
|
+
fallback_parts = [{"kind": "text", "text": str(result)}]
|
|
2766
3047
|
yield (
|
|
2767
3048
|
b"message",
|
|
2768
3049
|
{
|
|
@@ -2771,7 +3052,7 @@ async def handle_message_stream(
|
|
|
2771
3052
|
"result": _create_response_artifact_update(
|
|
2772
3053
|
task_id=task_id,
|
|
2773
3054
|
context_id=context_id,
|
|
2774
|
-
|
|
3055
|
+
parts=fallback_parts,
|
|
2775
3056
|
assistant_id=assistant_id,
|
|
2776
3057
|
),
|
|
2777
3058
|
},
|