langgraph-api 0.18.0.dev10__tar.gz → 0.18.0.dev12__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.18.0.dev10 → langgraph_api-0.18.0.dev12}/PKG-INFO +2 -2
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/REPORTS.md +25 -7
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/capacity-ci.js +40 -3
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/capacity-ci.test.js +40 -0
- langgraph_api-0.18.0.dev12/benchmark/cpu-probe.js +55 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/daily-report.js +28 -7
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/daily-report.test.js +50 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/delta-report.js +3 -2
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/delta-report.test.js +5 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/history.js +54 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/history.test.js +43 -1
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/ramp.js +5 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/staircase.py +8 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/staircase_step_k6.js +3 -0
- langgraph_api-0.18.0.dev12/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/threads.py +15 -18
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/graph.py +4 -1
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/client.py +8 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/ops/runs.py +7 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/ops/threads.py +19 -14
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/client.mts +86 -49
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/global.d.ts +1 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/remote.py +219 -54
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/metadata.py +7 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/models/run.py +5 -8
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/stream.py +36 -32
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/worker.py +9 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/store.py +9 -2
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/openapi.json +30 -4
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/pyproject.toml +1 -1
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/uv.lock +54 -23
- langgraph_api-0.18.0.dev10/langgraph_api/__init__.py +0 -1
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/.gitignore +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/LICENSE +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/Makefile +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/README.md +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/.gitignore +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/Makefile +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/README.md +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/classify-error.test.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/classify-error.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/delta-turns-lib.test.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/delta-turns-lib.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/delta_turns.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/store.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/clean.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/continuous/uv.lock +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/graphs.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/host-v2.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/host-v2.test.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/multer.test.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/package.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/runner-descriptions.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/server-metrics.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/server-metrics.test.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/slack.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/weather.js +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/benchmark/yarn.lock +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/constraints.txt +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/custom_store.sql +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/forbidden.txt +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/hatch_build.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/healthcheck.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/a2a.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/a2ui.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/a2ui_schemas/README.md +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/event_streaming.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_calls.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_origins.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_outcome.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_sdk.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_server.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/mcp/_tools.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/command.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/config/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/config/schemas.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/drain.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/service.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/executor/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/executor/__main__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/http.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/.yarnclean +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/package.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/auth-mutations.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/js/yarn.lock +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/metrics_collector.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/metrics_otlp.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/operator_routes.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/route.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/schema.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/server.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/state.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/store.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/timing/startup.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/tracing_session.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_api/worker_runtime.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/store.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/core_api_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/core_api_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/orchestrator_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/orchestrator_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/orchestrator_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/store_pb2.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/encryption.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/logging.json +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/scripts/create_license.py +0 -0
- {langgraph_api-0.18.0.dev10 → langgraph_api-0.18.0.dev12}/scripts/run_a2a_tck.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.18.0.
|
|
3
|
+
Version: 0.18.0.dev12
|
|
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
|
|
@@ -24,7 +24,7 @@ Requires-Dist: langsmith[otel]>=0.6.3
|
|
|
24
24
|
Requires-Dist: mcp<3,>=2.3.0
|
|
25
25
|
Requires-Dist: opentelemetry-api>=0.0.1
|
|
26
26
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=0.0.1
|
|
27
|
-
Requires-Dist: opentelemetry-exporter-prometheus<0.
|
|
27
|
+
Requires-Dist: opentelemetry-exporter-prometheus<0.67,>=0.63b1
|
|
28
28
|
Requires-Dist: opentelemetry-sdk>=0.0.1
|
|
29
29
|
Requires-Dist: orjson>=3.9.7
|
|
30
30
|
Requires-Dist: packaging>=23.2
|
|
@@ -16,13 +16,24 @@ in the same channel is separate and not covered here.
|
|
|
16
16
|
- **Failed / Errors / Regressed / Bottlenecks** lines only appear when there is
|
|
17
17
|
something to say, worst first.
|
|
18
18
|
- **Regressed / Improved.** A figure is flagged only when it leaves its own
|
|
19
|
-
usual range over the recent nights: the 9
|
|
20
|
-
|
|
21
|
-
mark the cell in the table. The usual range is half the spread
|
|
19
|
+
usual range over the recent nights: the 9 latest on tonight's CPUs for the
|
|
20
|
+
daily reports, the 9 before tonight for delta, the 7 latest on tonight's CPUs
|
|
21
|
+
for capacity, where ▲ better and ▼ worse also mark the cell in the table. The usual range is half the spread
|
|
22
22
|
between the best and worst of those nights, and never less than 10%, so a
|
|
23
23
|
series that swings 40% night to night is not flagged for moving 15%.
|
|
24
24
|
Flags start once five nights of history exist; until then the post says how
|
|
25
25
|
many it has.
|
|
26
|
+
- **Machines.** Staging hands out machines with CPUs of different
|
|
27
|
+
generations, and the oldest (Intel Broadwell) runs the same code about 1.5x
|
|
28
|
+
slower than AMD Rome. After each run, 20 short runs ask the benchmark graph
|
|
29
|
+
which CPU its workers are on (capacity asks after every step and keeps every
|
|
30
|
+
worker it saw), so the check never warms a deployment before it is timed. The first line of the daily reports names it
|
|
31
|
+
(`cpus differ by runner` when the paths got different ones), a `New machine:`
|
|
32
|
+
line says when a path or tier moved since the night before, and flags only
|
|
33
|
+
compare nights on the same CPUs, so a night on a slower machine starts its
|
|
34
|
+
own baseline instead of reading as a regression. A deployment with several
|
|
35
|
+
workers is compared by the set of CPUs they ran on; the thread gives the mix.
|
|
36
|
+
Nights from before this check only compare with each other.
|
|
26
37
|
- **The thread** holds the full numbers: per-run or per-cell detail and
|
|
27
38
|
improvements with before and after values; the daily threads also give the
|
|
28
39
|
load that ran.
|
|
@@ -84,7 +95,11 @@ it is shown but never flagged).
|
|
|
84
95
|
|
|
85
96
|
The daily benchmark against a second deployment that scales to zero when
|
|
86
97
|
idle. Scheduled runs redeploy it first, so the first minute includes the cold
|
|
87
|
-
start; a manual run skips the redeploy unless it is asked for.
|
|
98
|
+
start; a manual run skips the redeploy unless it is asked for. Its pods must
|
|
99
|
+
run on their cell's application machines (host-backend's
|
|
100
|
+
`HOST_DEV_ZERO_REQUIRED_CELL_POOL_PROJECT_IDS`, set for this deployment and the
|
|
101
|
+
serverless capacity one); other scale-to-zero deployments only prefer them and
|
|
102
|
+
also land on Redis machines or in another cell. 200 users per
|
|
88
103
|
path instead of the daily's 1,000 (300 for search), and the pass bar is p95
|
|
89
104
|
under 25 s to allow for the cold start. Read it like the [daily benchmark](#daily-benchmark).
|
|
90
105
|
|
|
@@ -94,7 +109,8 @@ under 25 s to allow for the cold start. Read it like the [daily benchmark](#dail
|
|
|
94
109
|
before it breaks its latency target, and what runs out first?
|
|
95
110
|
|
|
96
111
|
**How it runs.** Two staging deployments, one dedicated and one serverless,
|
|
97
|
-
|
|
112
|
+
get a new revision on scheduled runs and are then resized to each tier
|
|
113
|
+
(L, M, S) in turn. For each tier and path, k6 sends a
|
|
98
114
|
fixed request rate regardless of how fast the server answers (an "open
|
|
99
115
|
model", the way real traffic arrives), and raises it every 60 s: dedicated by
|
|
100
116
|
50 req/s starting at 50, serverless by 5 starting at 10.
|
|
@@ -118,7 +134,8 @@ number.
|
|
|
118
134
|
**Thread.** Improvements with before and after values, then per deployment
|
|
119
135
|
two small tables grouped by tier: peak CPU as % of the pod's request, and pods
|
|
120
136
|
at the start and end of the cell. Both cover the whole cell, including steps
|
|
121
|
-
that failed.
|
|
137
|
+
that failed. Then the request rate actually served at the top step, and the
|
|
138
|
+
CPU each tier ran on (`Machines:`, per path where a tier's paths differ).
|
|
122
139
|
|
|
123
140
|
## Delta channel
|
|
124
141
|
|
|
@@ -162,7 +179,8 @@ what the run returned.
|
|
|
162
179
|
|
|
163
180
|
**Thread.** Turn, write, read and data at turns 350, 700, 1050 and 1400, with
|
|
164
181
|
`gain`: how many times better delta is (`same` within 15%, below `1.0x` when
|
|
165
|
-
delta is worse). Then the run's size, failures
|
|
182
|
+
delta is worse). Then the run's size, failures, correctness checks and the
|
|
183
|
+
CPUs the workers ran on.
|
|
166
184
|
|
|
167
185
|
## Changing a report
|
|
168
186
|
|
|
@@ -22,9 +22,11 @@ import { RUNNERS } from "./daily-report.js";
|
|
|
22
22
|
import {
|
|
23
23
|
MIN_HISTORY_NIGHTS,
|
|
24
24
|
cellKey,
|
|
25
|
+
cpuSignature,
|
|
25
26
|
flaggedChange,
|
|
26
27
|
formatMove,
|
|
27
28
|
loadCapacityHistory,
|
|
29
|
+
sameCpu,
|
|
28
30
|
} from "./history.js";
|
|
29
31
|
import { runnerColumnName, runnerShortName } from "./runner-descriptions.js";
|
|
30
32
|
import { cellWindow, peakCpu, podRange, summarizeServerMetrics } from "./server-metrics.js";
|
|
@@ -229,15 +231,33 @@ function indexCells(deployments, summaries) {
|
|
|
229
231
|
return byDeployment;
|
|
230
232
|
}
|
|
231
233
|
|
|
232
|
-
function
|
|
234
|
+
function sameExecutorNights(deployment, tier, runner, summary, history) {
|
|
233
235
|
const executor = summary?.config?.k6Executor ?? "constant-vus";
|
|
234
236
|
// Nights measured in users and nights measured in req/s are different
|
|
235
237
|
// scales; only the same executor is a baseline.
|
|
236
238
|
return (history[cellKey({ deploymentSlug: deployment.slug, computeTier: tier, benchmarkType: runner })] ?? [])
|
|
237
|
-
.filter((night) => (night.executor ?? "constant-vus") === executor)
|
|
239
|
+
.filter((night) => (night.executor ?? "constant-vus") === executor);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// The baseline stays a week of nights on tonight's cpu; the workflow fetches more so a week can be found.
|
|
243
|
+
const PAST_NIGHTS = 7;
|
|
244
|
+
|
|
245
|
+
function pastNights(deployment, tier, runner, summary, history) {
|
|
246
|
+
return sameCpu(sameExecutorNights(deployment, tier, runner, summary, history), summary?.serverCpus)
|
|
247
|
+
.slice(0, PAST_NIGHTS)
|
|
238
248
|
.map((night) => night.capacityVUs);
|
|
239
249
|
}
|
|
240
250
|
|
|
251
|
+
/** Tonight's CPUs against the newest comparable night's, when both are known and differ. */
|
|
252
|
+
function newMachine(row, history) {
|
|
253
|
+
if (!row.summary || row.summary.error) return null;
|
|
254
|
+
const tonight = cpuSignature(row.summary.serverCpus);
|
|
255
|
+
const before = cpuSignature(sameExecutorNights(row.deployment, row.tier, row.runner, row.summary, history)[0]?.serverCpus);
|
|
256
|
+
return tonight && before && tonight !== before
|
|
257
|
+
? `${deploymentName(row.deployment)} ${tierLabel(row.deployment, row.tier)} on ${tonight} (was ${before})`
|
|
258
|
+
: null;
|
|
259
|
+
}
|
|
260
|
+
|
|
241
261
|
function analyseDeployment(deployment, cells, history) {
|
|
242
262
|
const rows = [];
|
|
243
263
|
let nights = 0;
|
|
@@ -404,12 +424,16 @@ export function formatAggregateTable(
|
|
|
404
424
|
if (reasons.size > 0) lines.push(`*Why:* ${[...reasons].join(" · ")}`);
|
|
405
425
|
if (regressed.length > 0) lines.push(`*Regressed:* ${regressed.map((row) => moveLine(row, unit)).join(" · ")}`);
|
|
406
426
|
if (bottlenecks.length > 0) lines.push(`*Bottlenecks:* ${bottlenecks.join(" · ")}`);
|
|
427
|
+
// A tier's runners share its pods, so one line per tier.
|
|
428
|
+
const moved = [...new Set(rows.map((row) => newMachine(row, history)).filter(Boolean))];
|
|
429
|
+
if (moved.length > 0) lines.push(`*New machine:* ${moved.join(" · ")} · compared only with nights on the same cpu`);
|
|
407
430
|
for (const warning of allWarnings) lines.push(`:warning: ${warning}`);
|
|
408
431
|
|
|
409
432
|
for (const { deployment, rows: deploymentRows, nights } of analysed) {
|
|
410
433
|
lines.push("", ...capacityTable(deployment, deploymentRows, unitFor(executorOf(deploymentRows.map((r) => r.summary).filter(Boolean)))));
|
|
411
434
|
if (nights < MIN_HISTORY_NIGHTS) {
|
|
412
|
-
|
|
435
|
+
const cpuKnown = deploymentRows.some((row) => cpuSignature(row.summary?.serverCpus));
|
|
436
|
+
lines.push(`_${nights} of ${MIN_HISTORY_NIGHTS} nights of history${cpuKnown ? " on this cpu" : ""}, no change flags yet_`);
|
|
413
437
|
}
|
|
414
438
|
}
|
|
415
439
|
return lines.join("\n");
|
|
@@ -473,6 +497,17 @@ function serverTable(deployment, cells, kind) {
|
|
|
473
497
|
return lines.join("\n");
|
|
474
498
|
}
|
|
475
499
|
|
|
500
|
+
/** "Machines: L amd rome · M intel broadwell", per runner only where a tier's runners differ. */
|
|
501
|
+
function machines(deployment, cells) {
|
|
502
|
+
const parts = [];
|
|
503
|
+
for (const tier of deployment.tiers) {
|
|
504
|
+
const cpus = RUNNERS.map((r) => cpuSignature(cells[tier]?.[r]?.serverCpus) ?? "-");
|
|
505
|
+
if (cpus.every((cpu) => cpu === "-")) continue;
|
|
506
|
+
parts.push(`${tierLabel(deployment, tier)} ${cpus.every((cpu) => cpu === cpus[0]) ? cpus[0] : cpus.join(" / ")}`);
|
|
507
|
+
}
|
|
508
|
+
return parts.length > 0 ? `Machines: ${parts.join(" · ")}` : null;
|
|
509
|
+
}
|
|
510
|
+
|
|
476
511
|
export function formatServerView(deployments, summaries) {
|
|
477
512
|
const byDeployment = indexCells(deployments, summaries);
|
|
478
513
|
const blocks = [];
|
|
@@ -484,6 +519,7 @@ export function formatServerView(deployments, summaries) {
|
|
|
484
519
|
.map((tier) => `${tierLabel(deployment, tier)} ${RUNNERS.map((r) => servedRate(cells[tier]?.[r])).join(" / ")}`)
|
|
485
520
|
.join(" · ");
|
|
486
521
|
const servedLine = `Runs/sec actually served at the top step, as ${RUNNERS.map(runnerColumnName).join(" / ")}: ${served}`;
|
|
522
|
+
const machinesLine = machines(deployment, cells);
|
|
487
523
|
// The served rate is k6's; the pod and CPU tables are the dashboard's, which is best effort.
|
|
488
524
|
const cpu = serverTable(deployment, cells, "cpu");
|
|
489
525
|
const pods = serverTable(deployment, cells, "pods");
|
|
@@ -493,6 +529,7 @@ export function formatServerView(deployments, summaries) {
|
|
|
493
529
|
cpu ? `_CPU, % of request_\n${cpu}` : null,
|
|
494
530
|
pods ? `_Pods, start → end_\n${pods}` : null,
|
|
495
531
|
servedLine,
|
|
532
|
+
machinesLine,
|
|
496
533
|
]
|
|
497
534
|
.filter(Boolean)
|
|
498
535
|
.join("\n"),
|
|
@@ -440,3 +440,43 @@ test("a crashed cell's multi-line error keeps its detail on the Why line", () =>
|
|
|
440
440
|
const table = formatAggregateTable(deployments, [buildErrorSummary({ deploymentSlug: "dep", computeTier: "TIER_A", benchmarkType: "wait_write" }, error)]);
|
|
441
441
|
assert.match(table, /^\*Why:\* PATCH \/resource-tiers failed: 409 \{ "detail": "Unable to resize the deployment database\." \}$/m);
|
|
442
442
|
});
|
|
443
|
+
|
|
444
|
+
const ROME = { "AuthenticAMD 143/49": 1 };
|
|
445
|
+
const BROADWELL = { "GenuineIntel 6/79": 1 };
|
|
446
|
+
const nightsOn = (serverCpus, ...values) => nights(...values).map((night) => ({ ...night, serverCpus }));
|
|
447
|
+
|
|
448
|
+
test("a cell that moved to an older cpu says so and is not compared with the faster cpu's nights", () => {
|
|
449
|
+
const deployments = [{ slug: "serverless", name: "Serverless", tiers: ["SERVERLESS_M"] }];
|
|
450
|
+
const tonight = (targetVUs, serverCpus) => ({
|
|
451
|
+
capacity: { targetVUs },
|
|
452
|
+
serverCpus,
|
|
453
|
+
config: { deploymentSlug: "serverless", computeTier: "SERVERLESS_M", benchmarkType: "wait_write", k6Executor: "constant-arrival-rate" },
|
|
454
|
+
});
|
|
455
|
+
const history = { "serverless|SERVERLESS_M|wait_write": nightsOn(ROME, 40, 40, 40, 40, 40) };
|
|
456
|
+
|
|
457
|
+
const moved = formatAggregateTable(deployments, [tonight(25, BROADWELL)], [], NIGHT, history);
|
|
458
|
+
assert.doesNotMatch(moved, /Regressed:/, "against the rome nights this would be -37%");
|
|
459
|
+
assert.match(moved, /^\*New machine:\* Serverless M on intel broadwell \(was amd rome\) · compared only with nights on the same cpu$/m);
|
|
460
|
+
assert.match(moved, /^_0 of 5 nights of history on this cpu, no change flags yet_$/m);
|
|
461
|
+
|
|
462
|
+
const stayed = formatAggregateTable(deployments, [tonight(25, ROME)], [], NIGHT, history);
|
|
463
|
+
assert.match(stayed, /^\*Regressed:\* Serverless M wait 40 → 25 req\/s \(-37%\)$/m, "the same drop on the same cpu is still a regression");
|
|
464
|
+
assert.doesNotMatch(stayed, /New machine/);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
test("the thread names each tier's cpu, per runner only where they differ", () => {
|
|
468
|
+
const deployments = [{ slug: "serverless", name: "Serverless", tiers: ["SERVERLESS_L", "SERVERLESS_S"] }];
|
|
469
|
+
const cell = (tier, benchmarkType, serverCpus) => ({
|
|
470
|
+
capacity: { targetVUs: 30, successfulRunsPerSec: 29.5 },
|
|
471
|
+
serverCpus,
|
|
472
|
+
config: { deploymentSlug: "serverless", computeTier: tier, benchmarkType, k6Executor: "constant-arrival-rate" },
|
|
473
|
+
});
|
|
474
|
+
const view = formatServerView(deployments, [
|
|
475
|
+
cell("SERVERLESS_L", "wait_write", ROME),
|
|
476
|
+
cell("SERVERLESS_L", "stream_write", ROME),
|
|
477
|
+
cell("SERVERLESS_L", "threads_search_metadata", ROME),
|
|
478
|
+
cell("SERVERLESS_S", "wait_write", BROADWELL),
|
|
479
|
+
cell("SERVERLESS_S", "stream_write", ROME),
|
|
480
|
+
]);
|
|
481
|
+
assert.match(view, /^Machines: L amd rome · S intel broadwell \/ amd rome \/ -$/m);
|
|
482
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Which CPUs the deployment's workers run on, asked of the benchmark graph:
|
|
3
|
+
* every run returns the `host` and `host_cpu` of the worker that ran it.
|
|
4
|
+
* Staging hands out machines of several CPU generations and the oldest runs the
|
|
5
|
+
* same code about 1.5x slower, so the reports only compare nights that ran on
|
|
6
|
+
* the same kind. Callers ask from handleSummary, after the measured scenario,
|
|
7
|
+
* so the probe never warms a fresh scale-to-zero deployment before its cold
|
|
8
|
+
* start is timed, and it sees the workers a deployment added under load.
|
|
9
|
+
*/
|
|
10
|
+
import http from 'k6/http';
|
|
11
|
+
|
|
12
|
+
// A dedicated deployment spreads runs over up to ten workers; twenty runs see most of them.
|
|
13
|
+
const PROBE_RUNS = 20;
|
|
14
|
+
// After an overloaded staircase step a run waits behind the backlog; the summary should not wait with it.
|
|
15
|
+
const PROBE_BUDGET_MS = 30000;
|
|
16
|
+
|
|
17
|
+
/** `{ "<host>": "<vendor family/model>" }` for each worker that answered. */
|
|
18
|
+
export function probeServerCpus(baseUrl, apiKey) {
|
|
19
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
20
|
+
if (apiKey) headers['x-api-key'] = apiKey;
|
|
21
|
+
const body = JSON.stringify({
|
|
22
|
+
assistant_id: 'benchmark',
|
|
23
|
+
input: {},
|
|
24
|
+
context: { steps: 1, expand: 1 },
|
|
25
|
+
config: { recursion_limit: 3 },
|
|
26
|
+
});
|
|
27
|
+
const deadline = Date.now() + PROBE_BUDGET_MS;
|
|
28
|
+
const cpuByHost = {};
|
|
29
|
+
for (let i = 0; i < PROBE_RUNS && Date.now() < deadline; i++) {
|
|
30
|
+
const response = http.post(`${baseUrl}/runs/wait`, body, {
|
|
31
|
+
headers,
|
|
32
|
+
timeout: Math.max(1000, deadline - Date.now()),
|
|
33
|
+
// Not part of the measurement, so a failed probe must not count against http_req_failed.
|
|
34
|
+
responseCallback: http.expectedStatuses({ min: 100, max: 599 }),
|
|
35
|
+
});
|
|
36
|
+
if (response.status !== 200) continue;
|
|
37
|
+
let output;
|
|
38
|
+
try {
|
|
39
|
+
output = response.json();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (typeof output?.host === 'string' && typeof output?.host_cpu === 'string') {
|
|
44
|
+
cpuByHost[output.host] = output.host_cpu;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return cpuByHost;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** `{ "<vendor family/model>": workers seen }`, or null when no worker answered. */
|
|
51
|
+
export function countByCpu(cpuByHost) {
|
|
52
|
+
const counts = {};
|
|
53
|
+
for (const cpu of Object.values(cpuByHost ?? {})) counts[cpu] = (counts[cpu] ?? 0) + 1;
|
|
54
|
+
return Object.keys(counts).length > 0 ? counts : null;
|
|
55
|
+
}
|
|
@@ -8,7 +8,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
10
10
|
|
|
11
|
-
import { MIN_HISTORY_NIGHTS, compare, flaggedChange, formatDelta, formatMove, loadDailyHistory, sparkline } from './history.js';
|
|
11
|
+
import { MIN_HISTORY_NIGHTS, compare, cpuSignature, describeCpus, flaggedChange, formatDelta, formatMove, loadDailyHistory, sameCpu, sparkline } from './history.js';
|
|
12
12
|
import { runnerColumnName, runnerShortName } from './runner-descriptions.js';
|
|
13
13
|
import { dotFor, footer, postReport } from './slack.js';
|
|
14
14
|
|
|
@@ -241,6 +241,24 @@ export const NIGHTS = 10;
|
|
|
241
241
|
|
|
242
242
|
const baseline = (run) => (run.history ?? []).slice(0, NIGHTS - 1);
|
|
243
243
|
|
|
244
|
+
// The trend draws every night; the flags compare only nights on tonight's kinds of CPU.
|
|
245
|
+
const comparable = (run) => sameCpu(run.history ?? [], run.summary?.metrics?.serverCpus).slice(0, NIGHTS - 1);
|
|
246
|
+
|
|
247
|
+
const cpuOf = (run) => cpuSignature(run.summary?.metrics?.serverCpus);
|
|
248
|
+
|
|
249
|
+
/** Tonight's CPUs against the newest past night's, when both are known and differ. */
|
|
250
|
+
function newMachine(run) {
|
|
251
|
+
const tonight = cpuOf(run);
|
|
252
|
+
const before = cpuSignature(run.history?.[0]?.serverCpus);
|
|
253
|
+
return tonight && before && tonight !== before ? `${runName(run)} on ${tonight} (was ${before})` : null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function cpuClause(runs) {
|
|
257
|
+
const known = runs.map(cpuOf).filter(Boolean);
|
|
258
|
+
if (known.length === 0) return '';
|
|
259
|
+
return known.every((cpu) => cpu === known[0]) ? ` · ${known[0]}` : ' · cpus differ by runner';
|
|
260
|
+
}
|
|
261
|
+
|
|
244
262
|
function p95Of(metrics) {
|
|
245
263
|
return succeeded(metrics) && isNumber(metrics?.p95Duration) ? metrics.p95Duration : null;
|
|
246
264
|
}
|
|
@@ -281,7 +299,7 @@ export function buildDigest(runs, context = {}) {
|
|
|
281
299
|
} = context;
|
|
282
300
|
|
|
283
301
|
const changesByRun = new Map(
|
|
284
|
-
runs.map((run) => [run, run.summary?.metrics ? figureChanges(run.summary.metrics,
|
|
302
|
+
runs.map((run) => [run, run.summary?.metrics ? figureChanges(run.summary.metrics, comparable(run)) : []])
|
|
285
303
|
);
|
|
286
304
|
const unhealthy = runs.filter((run) => !isHealthy({ stepOutcome: run.stepOutcome, metrics: run.summary?.metrics }));
|
|
287
305
|
const withErrors = runs.filter((run) => hasErrors(run.summary?.metrics));
|
|
@@ -295,7 +313,7 @@ export function buildDigest(runs, context = {}) {
|
|
|
295
313
|
if (moved.length > 0) list.push(`${runName(run)} ${moved.map((c, i) => (i === 0 ? `${c.label} ${c.move}` : `${c.label} ${roundedDelta(c.deltaPct)}`)).join(', ')}`);
|
|
296
314
|
}
|
|
297
315
|
}
|
|
298
|
-
const nights = Math.max(0, ...runs.map((run) =>
|
|
316
|
+
const nights = Math.max(0, ...runs.map((run) => comparable(run).length));
|
|
299
317
|
const checked = nights >= MIN_HISTORY_NIGHTS;
|
|
300
318
|
const tools = runs.map((run) => [run, toolLine(run.summary?.metrics)]).filter(([, line]) => line);
|
|
301
319
|
|
|
@@ -312,7 +330,7 @@ export function buildDigest(runs, context = {}) {
|
|
|
312
330
|
const date = now.toLocaleDateString('en-US', { month: 'short', day: 'numeric', timeZone: 'UTC' });
|
|
313
331
|
const passed = runs.length - unhealthy.length;
|
|
314
332
|
const lines = [
|
|
315
|
-
`${dot} *Daily Benchmark${titleSuffix} · ${date}*${manual ? ' · manual run' : ''}${apiVersion ? ` · API ${apiVersion}` : ''} · ${passed} of ${runs.length} passed · ${clauses.join(' · ')}`,
|
|
333
|
+
`${dot} *Daily Benchmark${titleSuffix} · ${date}*${manual ? ' · manual run' : ''}${apiVersion ? ` · API ${apiVersion}` : ''}${cpuClause(runs)} · ${passed} of ${runs.length} passed · ${clauses.join(' · ')}`,
|
|
316
334
|
];
|
|
317
335
|
if (unhealthy.length > 0) {
|
|
318
336
|
lines.push(`*Failed:* ${unhealthy.map((run) => `${runName(run)}: ${failureReason(run)}`).join(' · ')}`);
|
|
@@ -333,10 +351,12 @@ export function buildDigest(runs, context = {}) {
|
|
|
333
351
|
);
|
|
334
352
|
}
|
|
335
353
|
if (regressed.length > 0) lines.push(`*Regressed:* ${regressed.join(' · ')}`);
|
|
354
|
+
const moved = runs.map(newMachine).filter(Boolean);
|
|
355
|
+
if (moved.length > 0) lines.push(`*New machine:* ${moved.join(' · ')} · compared only with nights on the same cpu`);
|
|
336
356
|
for (const [run, line] of tools) lines.push(`:warning: ${runName(run)}: ${line}`);
|
|
337
357
|
|
|
338
358
|
lines.push(...digestTable(runs));
|
|
339
|
-
if (!checked) lines.push(`_${nights} of ${MIN_HISTORY_NIGHTS} nights of history, no change flags yet_`);
|
|
359
|
+
if (!checked) lines.push(`_${nights} of ${MIN_HISTORY_NIGHTS} nights of history${runs.some(cpuOf) ? ' on this cpu' : ''}, no change flags yet_`);
|
|
340
360
|
lines.push(footer(docsAnchor, artifactUrl));
|
|
341
361
|
|
|
342
362
|
return { text: lines.join('\n'), thread: [perRunDetail(runs, changesByRun, improved, loadSentence(runs))] };
|
|
@@ -365,9 +385,10 @@ function perRunDetail(runs, changesByRun, improved, load) {
|
|
|
365
385
|
lines.push(`${runName(run)}: ${noResults(run)}`);
|
|
366
386
|
continue;
|
|
367
387
|
}
|
|
368
|
-
const
|
|
388
|
+
const cpus = describeCpus(metrics.serverCpus);
|
|
389
|
+
const counts = `${count(metrics.totalRuns)} runs, ${count(metrics.failedRuns)} failed${cpus ? ` · ${cpus}` : ''}`;
|
|
369
390
|
const changes = changesByRun.get(run);
|
|
370
|
-
const nights =
|
|
391
|
+
const nights = comparable(run).length;
|
|
371
392
|
const drift =
|
|
372
393
|
changes.length > 0
|
|
373
394
|
? `vs ${nights} nights: ${changes.map((c) => `${c.label} ${formatDelta(c.deltaPct)}${c.flagged ? ` ${c.arrow}` : ''}`).join(' · ')}`
|
|
@@ -516,3 +516,53 @@ test('every table line in the channel message and the thread fits a phone', () =
|
|
|
516
516
|
assert.ok(widestCodeLine(text) <= PHONE_WIDTH, `channel table is ${widestCodeLine(text)} wide`);
|
|
517
517
|
assert.ok(widestCodeLine(thread[0]) <= PHONE_WIDTH, `thread table is ${widestCodeLine(thread[0])} wide`);
|
|
518
518
|
});
|
|
519
|
+
|
|
520
|
+
const ROME = { 'AuthenticAMD 143/49': 1 };
|
|
521
|
+
const BROADWELL = { 'GenuineIntel 6/79': 1 };
|
|
522
|
+
const on = (serverCpus) => () => ({ serverCpus });
|
|
523
|
+
|
|
524
|
+
test('a slow night on an older cpu is compared only with nights on that cpu, so it is no regression', () => {
|
|
525
|
+
const past = [...nights([9.6, 9.9, 10.2], on(BROADWELL)), ...nights([4.5, 4.5, 4.5, 4.5, 4.5, 4.5], on(ROME))];
|
|
526
|
+
const tonight = { ...healthyMetrics, p95Duration: 10.1, serverCpus: BROADWELL };
|
|
527
|
+
const { text, thread } = buildDigest([run('wait_write', { summary: { metrics: tonight }, history: past })], base);
|
|
528
|
+
assert.match(text, /^🟢 \*Daily Benchmark · Aug 17\* · API 0\.14\.0 · intel broadwell · 1 of 1 passed · all quiet$/m);
|
|
529
|
+
assert.doesNotMatch(text, /Regressed:/, 'against the rome nights this would be +124%');
|
|
530
|
+
assert.match(text, /^_3 of 5 nights of history on this cpu, no change flags yet_$/m);
|
|
531
|
+
assert.match(thread[0], /^wait_write: 133,000 runs, 0 failed · intel broadwell · vs 3 nights: /m);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
test('a regression on the same cpu is still flagged', () => {
|
|
535
|
+
const past = nights([4.5, 4.5, 4.5, 4.5, 4.5, 4.5], on(ROME));
|
|
536
|
+
const { text } = buildDigest([run('wait_write', { summary: { metrics: { ...healthyMetrics, p95Duration: 9.0, serverCpus: ROME } }, history: past })], base);
|
|
537
|
+
assert.match(text, /^\*Regressed:\* wait_write p95 4\.5 → 9\.0 s \(\+100%\)$/m);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
test('a night on a different cpu than the night before says so instead of flagging', () => {
|
|
541
|
+
const past = nights([4.5, 4.5, 4.5, 4.5, 4.5, 4.5], on(ROME));
|
|
542
|
+
const { text } = buildDigest([run('stream_write', { summary: { metrics: { ...healthyMetrics, p95Duration: 9.0, serverCpus: BROADWELL } }, history: past })], base);
|
|
543
|
+
assert.match(text, /^\*New machine:\* stream_write on intel broadwell \(was amd rome\) · compared only with nights on the same cpu$/m);
|
|
544
|
+
assert.doesNotMatch(text, /Regressed:/);
|
|
545
|
+
assert.match(text, /^_0 of 5 nights of history on this cpu, no change flags yet_$/m);
|
|
546
|
+
assert.match(text, /^stream\s+9\.0 [▁-█]+$/m, 'the trend still draws every night');
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
test('nights before the probe keep comparing with each other', () => {
|
|
550
|
+
const past = nights([4.5, 4.5, 4.5, 4.5, 4.5, 4.5]);
|
|
551
|
+
const { text } = buildDigest([run('wait_write', { summary: { metrics: { ...healthyMetrics, p95Duration: 9.0 } }, history: past })], base);
|
|
552
|
+
assert.match(text, /^\*Regressed:\* wait_write p95 4\.5 → 9\.0 s/m);
|
|
553
|
+
assert.doesNotMatch(text, /New machine|intel|amd/);
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
test('runners on different cpus say so in the header and name their cpu in the thread', () => {
|
|
557
|
+
const mixed = { 'AuthenticAMD 143/49': 6, 'GenuineIntel 6/79': 4 };
|
|
558
|
+
const runs = [
|
|
559
|
+
run('wait_write', { summary: { metrics: { ...healthyMetrics, serverCpus: BROADWELL } } }),
|
|
560
|
+
run('stream_write', { summary: { metrics: { ...healthyMetrics, serverCpus: mixed } } }),
|
|
561
|
+
];
|
|
562
|
+
const { text, thread } = buildDigest(runs, base);
|
|
563
|
+
assert.match(text, /· API 0\.14\.0 · cpus differ by runner · 2 of 2 passed/);
|
|
564
|
+
assert.match(thread[0], /^wait_write: 133,000 runs, 0 failed · intel broadwell · /m);
|
|
565
|
+
assert.match(thread[0], /^stream_write: 133,000 runs, 0 failed · 6 amd rome, 4 intel broadwell · /m);
|
|
566
|
+
const same = buildDigest([runs[1]], base).text;
|
|
567
|
+
assert.match(same, /· API 0\.14\.0 · amd rome \+ intel broadwell · 1 of 1 passed/);
|
|
568
|
+
});
|
|
@@ -10,7 +10,7 @@ import readline from 'node:readline';
|
|
|
10
10
|
import { fileURLToPath } from 'node:url';
|
|
11
11
|
|
|
12
12
|
import { ERROR_ATTENTION, MIN_SUCCESS_RATE, describeThreshold, errorParts, findLatestSummary, isHealthy, readApiVersion, readSummary } from './daily-report.js';
|
|
13
|
-
import { MIN_HISTORY_NIGHTS, flaggedChange, formatMove, sparkline } from './history.js';
|
|
13
|
+
import { MIN_HISTORY_NIGHTS, describeCpus, flaggedChange, formatMove, sparkline } from './history.js';
|
|
14
14
|
import { dotFor, footer, postReport } from './slack.js';
|
|
15
15
|
|
|
16
16
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -345,8 +345,9 @@ function threadText(run, metrics, guard, improved) {
|
|
|
345
345
|
const users = Number(run.load?.loadSize) || null;
|
|
346
346
|
const turns = Number(run.load?.turns) || null;
|
|
347
347
|
const shape = users && turns ? `${count(users)} users × ${count(turns)} turns × ${run.cells.length} setups · ` : '';
|
|
348
|
+
const cpus = describeCpus(metrics?.serverCpus);
|
|
348
349
|
const health = metrics
|
|
349
|
-
? `${count(metrics.failedRuns)} failed of ${count(metrics.totalRuns)} turns · ${guard > 0 ? `correctness check failed × ${count(guard)}` : 'no correctness failures'}`
|
|
350
|
+
? `${count(metrics.failedRuns)} failed of ${count(metrics.totalRuns)} turns · ${guard > 0 ? `correctness check failed × ${count(guard)}` : 'no correctness failures'}${cpus ? ` · ${cpus}` : ''}`
|
|
350
351
|
: 'no results';
|
|
351
352
|
return [
|
|
352
353
|
'*As the thread grows*',
|
|
@@ -194,3 +194,8 @@ test('a single downloaded artifact is read from the results directory itself', a
|
|
|
194
194
|
assert.equal(run.stepOutcome, 'success');
|
|
195
195
|
assert.equal(run.cells.find((c) => c.cell === 'delta_50').buckets['1-50'].saveMeanMs, 30);
|
|
196
196
|
});
|
|
197
|
+
|
|
198
|
+
test('the run line names the cpus the workers ran on', () => {
|
|
199
|
+
const { thread } = buildReport(run({ summary: { serverCpus: { 'AuthenticAMD 143/49': 6, 'GenuineIntel 6/79': 4 } } }), base);
|
|
200
|
+
assert.match(thread[0], /^\*Run\* · .* · no correctness failures · 6 amd rome, 4 intel broadwell$/m);
|
|
201
|
+
});
|
|
@@ -138,6 +138,7 @@ export function loadCapacityHistory(dir) {
|
|
|
138
138
|
if (summary.error) continue;
|
|
139
139
|
(history[cellKey(config)] ??= []).push({
|
|
140
140
|
executor: config.k6Executor ?? "constant-vus",
|
|
141
|
+
serverCpus: summary.serverCpus ?? null,
|
|
141
142
|
capacityVUs: summary.capacity?.targetVUs ?? 0,
|
|
142
143
|
runsPerSec:
|
|
143
144
|
summary.capacity?.successfulRunsPerSec ??
|
|
@@ -149,6 +150,59 @@ export function loadCapacityHistory(dir) {
|
|
|
149
150
|
return history;
|
|
150
151
|
}
|
|
151
152
|
|
|
153
|
+
// The CPUs staging's E2 machines come with, keyed `vendor family/model` as cpu-probe.js records them.
|
|
154
|
+
const CPU_NAMES = {
|
|
155
|
+
"GenuineIntel 6/63": "intel haswell",
|
|
156
|
+
"GenuineIntel 6/79": "intel broadwell",
|
|
157
|
+
"GenuineIntel 6/85": "intel skylake or cascade lake",
|
|
158
|
+
"AuthenticAMD 23/49": "amd rome",
|
|
159
|
+
"AuthenticAMD 25/1": "amd milan",
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/** gVisor prints an AMD family as `(extended << 4) | 0xF`, 143 where Linux says 23. */
|
|
163
|
+
function cpuName(key) {
|
|
164
|
+
const match = /^(\S+) (\d+)\/(\d+)$/.exec(key);
|
|
165
|
+
if (!match) return key;
|
|
166
|
+
const [, vendor, familyText, model] = match;
|
|
167
|
+
const raw = Number(familyText);
|
|
168
|
+
const family = raw > 0xf && (raw & 0xf) === 0xf ? 0xf + (raw >> 4) : raw;
|
|
169
|
+
const normalized = `${vendor} ${family}/${model}`;
|
|
170
|
+
return CPU_NAMES[normalized] ?? normalized;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function cpuCounts(serverCpus) {
|
|
174
|
+
const counts = {};
|
|
175
|
+
for (const [key, workers] of Object.entries(serverCpus ?? {})) {
|
|
176
|
+
const name = cpuName(key);
|
|
177
|
+
counts[name] = (counts[name] ?? 0) + (isNumber(workers) ? workers : 0);
|
|
178
|
+
}
|
|
179
|
+
return counts;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** The kinds of CPU a night ran on, the key the reports compare nights by; null when unknown. */
|
|
183
|
+
export function cpuSignature(serverCpus) {
|
|
184
|
+
const names = Object.keys(cpuCounts(serverCpus)).sort();
|
|
185
|
+
return names.length > 0 ? names.join(" + ") : null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** "amd rome" for one worker, "6 amd rome, 4 intel broadwell" for several. */
|
|
189
|
+
export function describeCpus(serverCpus) {
|
|
190
|
+
const entries = Object.entries(cpuCounts(serverCpus)).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
191
|
+
if (entries.length === 0) return null;
|
|
192
|
+
const workers = entries.reduce((sum, [, n]) => sum + n, 0);
|
|
193
|
+
return workers === 1 ? entries[0][0] : entries.map(([name, n]) => `${n} ${name}`).join(", ");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The nights that ran on tonight's kinds of CPU. A night without the probe only
|
|
198
|
+
* matches a night without it, so reports keep their history until the probe
|
|
199
|
+
* starts answering.
|
|
200
|
+
*/
|
|
201
|
+
export function sameCpu(nights, serverCpus) {
|
|
202
|
+
const tonight = cpuSignature(serverCpus);
|
|
203
|
+
return nights.filter((night) => cpuSignature(night?.serverCpus) === tonight);
|
|
204
|
+
}
|
|
205
|
+
|
|
152
206
|
function median(values) {
|
|
153
207
|
const sorted = [...values].sort((a, b) => a - b);
|
|
154
208
|
const mid = Math.floor(sorted.length / 2);
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
MIN_HISTORY_NIGHTS,
|
|
9
9
|
cellKey,
|
|
10
10
|
compare,
|
|
11
|
+
cpuSignature,
|
|
12
|
+
describeCpus,
|
|
11
13
|
flaggedChange,
|
|
12
14
|
formatDelta,
|
|
13
15
|
formatMove,
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
historyCandidates,
|
|
16
18
|
loadCapacityHistory,
|
|
17
19
|
loadDailyHistory,
|
|
20
|
+
sameCpu,
|
|
18
21
|
sparkline,
|
|
19
22
|
} from "./history.js";
|
|
20
23
|
|
|
@@ -112,7 +115,7 @@ test("capacity history groups nights by cell and skips crashed cells", () => {
|
|
|
112
115
|
const key = cellKey({ deploymentSlug: "d", computeTier: "L", benchmarkType: "wait_write" });
|
|
113
116
|
assert.deepEqual(history[key].map((n) => n.capacityVUs).sort((a, b) => a - b), [700, 1000]);
|
|
114
117
|
const serverless = history[cellKey({ deploymentSlug: "s", computeTier: "L", benchmarkType: "wait_write" })];
|
|
115
|
-
assert.deepEqual(serverless, [{ executor: "constant-vus", capacityVUs: 0, runsPerSec: 46.3 }], "a cell with no passing step keeps its ceiling, and a night without an executor is closed-model");
|
|
118
|
+
assert.deepEqual(serverless, [{ executor: "constant-vus", serverCpus: null, capacityVUs: 0, runsPerSec: 46.3 }], "a cell with no passing step keeps its ceiling, and a night without an executor is closed-model");
|
|
116
119
|
});
|
|
117
120
|
|
|
118
121
|
test("capacity history remembers which executor measured each night", () => {
|
|
@@ -125,6 +128,45 @@ test("capacity history remembers which executor measured each night", () => {
|
|
|
125
128
|
assert.equal(night.executor, "constant-arrival-rate");
|
|
126
129
|
});
|
|
127
130
|
|
|
131
|
+
test("capacity history remembers the CPUs each night ran on", () => {
|
|
132
|
+
const root = mkdtempSync(path.join(tmpdir(), "cap-cpu-"));
|
|
133
|
+
writeFileSync(path.join(runDir(root, 1), "staircase_summary_s.json"), JSON.stringify({
|
|
134
|
+
config: { deploymentSlug: "s", computeTier: "M", benchmarkType: "wait_write" },
|
|
135
|
+
capacity: { targetVUs: 40, successfulRunsPerSec: 39.6 },
|
|
136
|
+
serverCpus: { "GenuineIntel 6/79": 1 },
|
|
137
|
+
}));
|
|
138
|
+
const [night] = loadCapacityHistory(root)[cellKey({ deploymentSlug: "s", computeTier: "M", benchmarkType: "wait_write" })];
|
|
139
|
+
assert.equal(cpuSignature(night.serverCpus), "intel broadwell");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("cpus are named the same inside and outside gVisor, and unknown ones keep their numbers", () => {
|
|
143
|
+
assert.equal(cpuSignature({ "AuthenticAMD 143/49": 1 }), "amd rome", "gVisor's AMD family 143 is Linux's 23");
|
|
144
|
+
assert.equal(cpuSignature({ "AuthenticAMD 23/49": 1 }), "amd rome");
|
|
145
|
+
assert.equal(cpuSignature({ "GenuineIntel 6/79": 1 }), "intel broadwell");
|
|
146
|
+
assert.equal(cpuSignature({ "GenuineIntel 6/207": 1 }), "GenuineIntel 6/207");
|
|
147
|
+
assert.equal(cpuSignature({ "AuthenticAMD 175/17": 1 }), "AuthenticAMD 25/17", "an unnamed AMD still gets the Linux family");
|
|
148
|
+
assert.equal(cpuSignature(null), null);
|
|
149
|
+
assert.equal(cpuSignature({}), null);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("a mix of cpus is one signature, and the description counts the workers", () => {
|
|
153
|
+
const mixed = { "GenuineIntel 6/79": 4, "AuthenticAMD 143/49": 6 };
|
|
154
|
+
assert.equal(cpuSignature(mixed), "amd rome + intel broadwell");
|
|
155
|
+
assert.equal(describeCpus(mixed), "6 amd rome, 4 intel broadwell");
|
|
156
|
+
assert.equal(describeCpus({ "AuthenticAMD 143/49": 1 }), "amd rome", "one worker needs no count");
|
|
157
|
+
assert.equal(describeCpus(null), null);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("only nights on the same cpus compare, and nights before the probe only compare with each other", () => {
|
|
161
|
+
const rome = { serverCpus: { "AuthenticAMD 143/49": 1 }, p95Duration: 4.5 };
|
|
162
|
+
const broadwell = { serverCpus: { "GenuineIntel 6/79": 1 }, p95Duration: 9.8 };
|
|
163
|
+
const before = { p95Duration: 5.1 };
|
|
164
|
+
const nights = [broadwell, rome, before, rome];
|
|
165
|
+
assert.deepEqual(sameCpu(nights, rome.serverCpus), [rome, rome]);
|
|
166
|
+
assert.deepEqual(sameCpu(nights, broadwell.serverCpus), [broadwell]);
|
|
167
|
+
assert.deepEqual(sameCpu(nights, null), [before]);
|
|
168
|
+
});
|
|
169
|
+
|
|
128
170
|
test("sparkline keeps noise mid-height, draws a real step full height, and leaves gaps for missing nights", () => {
|
|
129
171
|
assert.equal(sparkline([5, 5.2, 4.9, 5.1, 5]), "▄▅▄▅▄");
|
|
130
172
|
assert.equal(sparkline([12.8, 12.5, 4.6, 4.8]), "██▁▁");
|
|
@@ -2,6 +2,7 @@ import { sleep } from 'k6';
|
|
|
2
2
|
import { Counter, Trend } from 'k6/metrics';
|
|
3
3
|
import { Benchmarks } from './benchmark-runners/dist/benchmarks.js';
|
|
4
4
|
import { get_profile } from './benchmark-runners/dist/benchmark_profiles.js';
|
|
5
|
+
import { countByCpu, probeServerCpus } from './cpu-probe.js';
|
|
5
6
|
|
|
6
7
|
// Custom metrics
|
|
7
8
|
const runDuration = new Trend('run_duration');
|
|
@@ -199,6 +200,8 @@ export function handleSummary(data) {
|
|
|
199
200
|
const successfulRuns = data.metrics.successful_runs?.values?.count || 0;
|
|
200
201
|
const failedRuns = data.metrics.failed_runs?.values?.count || 0;
|
|
201
202
|
const totalRuns = successfulRuns + failedRuns;
|
|
203
|
+
const serverCpus = countByCpu(probeServerCpus(BASE_URL, LANGSMITH_API_KEY));
|
|
204
|
+
console.log(`Server CPUs (workers seen): ${JSON.stringify(serverCpus)}`);
|
|
202
205
|
|
|
203
206
|
const summary = {
|
|
204
207
|
startTimestamp: data.setup_data.startTime,
|
|
@@ -218,6 +221,8 @@ export function handleSummary(data) {
|
|
|
218
221
|
: null,
|
|
219
222
|
clientOverheadMs: trendMs(data.metrics.client_overhead),
|
|
220
223
|
httpReqBlockedP95Ms: data.metrics.http_req_blocked?.values?.["p(95)"] ?? null,
|
|
224
|
+
// In metrics, not beside them, so every report's history carries it without another reader.
|
|
225
|
+
serverCpus,
|
|
221
226
|
errors: {
|
|
222
227
|
timeout: data.metrics.timeout_errors ? data.metrics.timeout_errors.values.count : 0,
|
|
223
228
|
connection: data.metrics.connection_errors ? data.metrics.connection_errors.values.count : 0,
|