langgraph-api 0.16.0.dev7__tar.gz → 0.16.0.dev8__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.16.0.dev7 → langgraph_api-0.16.0.dev8}/PKG-INFO +2 -1
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/README.md +11 -2
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/capacity-ci.js +359 -146
- langgraph_api-0.16.0.dev8/benchmark/capacity-ci.test.js +404 -0
- langgraph_api-0.16.0.dev8/benchmark/daily-report.js +503 -0
- langgraph_api-0.16.0.dev8/benchmark/daily-report.test.js +463 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/history.js +22 -2
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/history.test.js +46 -4
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/runner-descriptions.js +25 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/server-metrics.js +10 -0
- langgraph_api-0.16.0.dev8/benchmark/slack.js +49 -0
- langgraph_api-0.16.0.dev8/langgraph_api/__init__.py +1 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2a.py +8 -11
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/threads.py +2 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/schema.py +2 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/state.py +11 -5
- langgraph_api-0.16.0.dev8/langgraph_grpc_common/proto/core_api_pb2.py +274 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/core_api_pb2.pyi +10 -2
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/openapi.json +4 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/pyproject.toml +1 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/uv.lock +2 -0
- langgraph_api-0.16.0.dev7/benchmark/capacity-ci.test.js +0 -265
- langgraph_api-0.16.0.dev7/benchmark/daily-report.js +0 -358
- langgraph_api-0.16.0.dev7/benchmark/daily-report.test.js +0 -350
- langgraph_api-0.16.0.dev7/langgraph_api/__init__.py +0 -1
- langgraph_api-0.16.0.dev7/langgraph_grpc_common/proto/core_api_pb2.py +0 -274
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/.gitignore +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/LICENSE +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/Makefile +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/README.md +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/.gitignore +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/Makefile +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/assistant.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/benchmark-runner.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/benchmark_profiles.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/benchmarks.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/cancel_first_second_completes.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/classify-error.test.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/classify-error.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/delta-turns-lib.test.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/delta-turns-lib.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/delta_turns.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/enqueued_runs_order.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/interrupt_resume.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/log-failure.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/meta_workload.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/store.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/stream_write.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/thread.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/thread_runs_metadata_search.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/threads_search_metadata.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/types.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/benchmark-runners/wait_write.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/clean-cli.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/clean.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/README.md +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/pyproject.toml +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/runner.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/continuous/uv.lock +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/graphs.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/host-v2.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/host-v2.test.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/multer.test.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/package.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/ramp.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/reporting/dd_reporting.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/server-metrics.test.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/staircase.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/staircase_step_k6.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/tsconfig.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/update-revision.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/weather.js +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/benchmark/yarn.lock +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/constraints.txt +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/custom_store.sql +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/forbidden.txt +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/hatch_build.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/healthcheck.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph-cloud-debugging-20260210132856.zip +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_checkpointer/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_checkpointer/_adapter.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_checkpointer/protocol.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/_factory_utils.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/README.md +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/client_capabilities.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/client_data_model.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/client_to_server.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/a2ui_schemas/server_to_client.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/assistants.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/event_streaming.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_constants.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_handlers.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_models.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_routes.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/mcp/_sanitizers.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/meta.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/openapi.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/profile.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/runs.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/store.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/threads.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/api/ui.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/asgi_transport.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/asyncio.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/custom.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/errors.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/langsmith/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/langsmith/backend.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/langsmith/client.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/middleware.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/noop.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/auth/studio_user.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/beacon_data_plane_jwt_auth.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/cache.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/cli.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/command.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/config/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/config/_parse.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/config/schemas.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/cron_scheduler.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/aes_json.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/context.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/custom.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/middleware.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/encryption/shared.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/errors.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/capabilities.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/constants.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/event_normalizers.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/namespace.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/service.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/session.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/state_normalizers.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/event_streaming/types.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/feature_flags.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/graph.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/client.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/generated/core_api_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/assistants.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/cache.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/crons.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/ops/runs.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/server.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/servicers/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/servicers/checkpointer.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/grpc/servicers/encryption.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/http.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/http_metrics.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/http_metrics_utils.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/.gitignore +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/.prettierrc +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/.yarnclean +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/base.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/build.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/client.http.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/client.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/errors.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/global.d.ts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/package.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/remote.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/schema.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/graph.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/load.hooks.mjs +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/preload.mjs +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/experiment-tracing.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/files.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/importMap.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/src/utils/serde.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/sse.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/traceblock.mts +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/tsconfig.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/ui.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/js/yarn.lock +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/exceptions.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/policy.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/lc_security/transport.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/logging.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/metadata.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/metrics_collector.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/metrics_otlp.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/ensure_store.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/http_logger.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/private_network.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/middleware/request_id.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/models/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/models/run.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/otel_context.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/patch.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/queue_entrypoint.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/release_tags.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/route.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/runner/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/runner/__main__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/self_hosted_logs.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/self_hosted_metrics.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/serde.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/server.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/sse.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/store.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/stream.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/stream_v2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/timing/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/timing/profiler.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/timing/timer.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/traceblock.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/tracing_session.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/tunneling/cloudflare.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/cache.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/config.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/errors.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/extract.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/future.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/headers.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/network.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/retriable_client.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/stream_codec.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/utils/uuids.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/validation.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/webhook.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/worker.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_api/worker_runtime.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/checkpointer.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/_compat.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/checkpoint.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/config.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/durability.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/store.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/struct.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/conversion/value.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/checkpointer_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/core_api_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/core_api_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/encryption_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/engine_common_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cancel_run_action_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_control_signal_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_cron_on_run_completed_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_durability_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_multitask_strategy_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_run_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_status_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/enum_thread_stream_mode_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/errors_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/runner_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2_grpc.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/proto/store_pb2_grpc.pyi +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/serde.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_grpc_common/store.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_license/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_license/validation.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/__init__.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/checkpoint.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/database.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/lifespan.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/metrics.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/ops.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/queue.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/retry.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/routes.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/langgraph_runtime/store.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/logging.json +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/scripts/build_wheel.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/scripts/create_license.py +0 -0
- {langgraph_api-0.16.0.dev7 → langgraph_api-0.16.0.dev8}/scripts/run_a2a_tck.py +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.16.0.
|
|
3
|
+
Version: 0.16.0.dev8
|
|
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
|
+
Requires-Dist: anyio>=4.14.2
|
|
8
9
|
Requires-Dist: cloudpickle>=3.0.0
|
|
9
10
|
Requires-Dist: cryptography>=50.0.0
|
|
10
11
|
Requires-Dist: grpcio-health-checking<1.82.0,>=1.81.0
|
|
@@ -192,9 +192,18 @@ be compared on the bytes they occupy, which is what the feature exists to reduce
|
|
|
192
192
|
2. Fill in `deploymentId` and `baseUrl` in `CAPACITY_DEPLOYMENTS` at the top of [`capacity-ci.js`](capacity-ci.js).
|
|
193
193
|
3. Scheduled run: two parallel CI jobs (one per deployment), aggregate job posts Slack summary.
|
|
194
194
|
|
|
195
|
-
Each cell also records the deployment's own view of its window (queue and API pod counts, CPU peaks) from the control plane's deployment metrics route, and the
|
|
195
|
+
Each cell also records the deployment's own view of its window (queue and API pod counts, CPU peaks) from the control plane's deployment metrics route. The posted message names any component at or over 95% of its CPU request as that tier's bottleneck, and the full per-cell table goes to the message's thread. Every tier starts at one queue pod and autoscales during a cell, so a capacity number is partly a pod-count number; pinning pods at the tier maximum would need the benchmark deployments recreated as `external_docker` sources, the only kind whose `resource_spec` the API accepts.
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
### Slack reports
|
|
198
|
+
|
|
199
|
+
Every report follows one shape so the channel reads the same way each morning, on a phone as well as a desktop:
|
|
200
|
+
|
|
201
|
+
- The first line is the verdict: a dot (green quiet, yellow something regressed or a bottleneck or errors, red something failed), the report name and date, `manual run` when dispatched by hand, the API version, and a clause saying what needs attention. The second line says what the benchmark is, for a reader outside the team.
|
|
202
|
+
- Then `Failed`, `Regressed`, `Improved` and `Bottlenecks` or `Errors` lines, worst first. `Regressed` prints `none` rather than going quiet.
|
|
203
|
+
- One table per deployment, about 40 characters wide so it fits a phone, with `▲ better` / `▼ worse` markers on cells that left their usual range.
|
|
204
|
+
- One legend line (pass rule, arrows, dot colors), then a link to the thread, which holds the per-cell or per-run numbers and the longer *How to read*, and to the run's artifacts.
|
|
205
|
+
|
|
206
|
+
Both reports compare tonight with the previous scheduled nights (`history.js`, artifacts fetched with `gh`). A figure is flagged only when it leaves that cell's own observed range, and only once five same-kind nights exist; before that the table says how many nights it has. The daily benchmark posts one digest per workflow once its last runner finishes (`daily-report.js`, fed by each runner's artifact), not one message per runner.
|
|
198
207
|
|
|
199
208
|
Local commands:
|
|
200
209
|
|
|
@@ -18,23 +18,33 @@ import {
|
|
|
18
18
|
requireApiKey,
|
|
19
19
|
setResourceTiers,
|
|
20
20
|
} from "./host-v2.js";
|
|
21
|
-
import {
|
|
22
|
-
import { describeRunner, runnerShortName } from "./runner-descriptions.js";
|
|
21
|
+
import { RUNNERS, readApiVersion } from "./daily-report.js";
|
|
23
22
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
MIN_HISTORY_NIGHTS,
|
|
24
|
+
cellKey,
|
|
25
|
+
flaggedChange,
|
|
26
|
+
formatMove,
|
|
27
|
+
loadCapacityHistory,
|
|
28
|
+
} from "./history.js";
|
|
29
|
+
import {
|
|
30
|
+
describeRunnerBriefly,
|
|
31
|
+
runnerColumnName,
|
|
32
|
+
runnerGloss,
|
|
33
|
+
runnerShortName,
|
|
34
|
+
} from "./runner-descriptions.js";
|
|
35
|
+
import { cellWindow, peakCpu, podRange, summarizeServerMetrics } from "./server-metrics.js";
|
|
36
|
+
import { dotFor, postReport } from "./slack.js";
|
|
28
37
|
|
|
29
38
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
30
39
|
|
|
31
40
|
/**
|
|
32
41
|
* @typedef {{startLoad?: string, stepSize?: string, numSteps?: string, warmupLoad?: string}} StaircaseGeometry
|
|
33
|
-
* @type {Array<{slug: string, deploymentId: string, baseUrl: string, tiers: string[], staircase?: StaircaseGeometry}>}
|
|
42
|
+
* @type {Array<{slug: string, name: string, deploymentId: string, baseUrl: string, tiers: string[], staircase?: StaircaseGeometry}>}
|
|
34
43
|
*/
|
|
35
44
|
const CAPACITY_DEPLOYMENTS = [
|
|
36
45
|
{
|
|
37
46
|
slug: "daily-cap-benchmark-dedicated",
|
|
47
|
+
name: "Dedicated",
|
|
38
48
|
deploymentId: "22a22e9d-521e-4635-9bcb-a096a22820cc",
|
|
39
49
|
baseUrl:
|
|
40
50
|
"https://daily-cap-benchmark-dedicat-9669b63626045e0681f1f1fda08ef4ce.staging.langgraph.app",
|
|
@@ -45,6 +55,7 @@ const CAPACITY_DEPLOYMENTS = [
|
|
|
45
55
|
},
|
|
46
56
|
{
|
|
47
57
|
slug: "daily-cap-benchmark-serverless",
|
|
58
|
+
name: "Serverless",
|
|
48
59
|
deploymentId: "becfa8bb-e2e3-4d96-8d08-3191b17c5d4d",
|
|
49
60
|
baseUrl:
|
|
50
61
|
"https://daily-cap-benchmark-serverl-b5dc9d9f7fa05990b279939863ae08de.staging.langgraph.app",
|
|
@@ -56,8 +67,6 @@ const CAPACITY_DEPLOYMENTS = [
|
|
|
56
67
|
},
|
|
57
68
|
];
|
|
58
69
|
|
|
59
|
-
const RUNNERS = ["wait_write", "stream_write", "threads_search_metadata"];
|
|
60
|
-
|
|
61
70
|
// Open model: a fixed arrival rate per step, so capacity reads directly as the
|
|
62
71
|
// service rate. Closed-model users back off as the server slows and flatter it.
|
|
63
72
|
const STAIRCASE_EXECUTOR = "constant-arrival-rate";
|
|
@@ -195,135 +204,354 @@ export function capacityVus(summary) {
|
|
|
195
204
|
return perSec == null ? String(vus) : `${vus} (${perSec}/s)`;
|
|
196
205
|
}
|
|
197
206
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
const BOTTLENECK_CPU_PCT = 95;
|
|
208
|
+
const COMPONENTS = [
|
|
209
|
+
["queue", "queue"],
|
|
210
|
+
["api", "api"],
|
|
211
|
+
["db", "database"],
|
|
212
|
+
["redis", "redis"],
|
|
213
|
+
];
|
|
214
|
+
|
|
215
|
+
function deploymentName(deployment) {
|
|
216
|
+
return deployment.name ?? deployment.slug;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function tierLabel(deployment, tier) {
|
|
220
|
+
const prefix = `${deploymentName(deployment).toUpperCase()}_`;
|
|
221
|
+
return tier.startsWith(prefix) ? tier.slice(prefix.length) : tier;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function cellName(deployment, tier, runner) {
|
|
225
|
+
return `${deploymentName(deployment)} ${tierLabel(deployment, tier)} ${runnerColumnName(runner)}`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function indexCells(deployments, summaries) {
|
|
205
229
|
/** @type {Record<string, Record<string, Record<string, object>>>} */
|
|
206
230
|
const byDeployment = Object.fromEntries(deployments.map((d) => [d.slug, {}]));
|
|
207
|
-
|
|
208
231
|
for (const summary of summaries) {
|
|
209
|
-
const
|
|
210
|
-
const { deploymentSlug, computeTier, benchmarkType } = config;
|
|
232
|
+
const { deploymentSlug, computeTier, benchmarkType } = summary.config ?? {};
|
|
211
233
|
if (deploymentSlug && computeTier && benchmarkType) {
|
|
212
234
|
byDeployment[deploymentSlug] ??= {};
|
|
213
235
|
byDeployment[deploymentSlug][computeTier] ??= {};
|
|
214
236
|
byDeployment[deploymentSlug][computeTier][benchmarkType] = summary;
|
|
215
237
|
}
|
|
216
238
|
}
|
|
239
|
+
return byDeployment;
|
|
240
|
+
}
|
|
217
241
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const
|
|
242
|
+
function pastNights(deployment, tier, runner, summary, history) {
|
|
243
|
+
const executor = summary?.config?.k6Executor ?? "constant-vus";
|
|
244
|
+
// Nights measured in users and nights measured in req/s are different
|
|
245
|
+
// scales; only the same executor is a baseline.
|
|
246
|
+
return (history[cellKey({ deploymentSlug: deployment.slug, computeTier: tier, benchmarkType: runner })] ?? [])
|
|
247
|
+
.filter((night) => (night.executor ?? "constant-vus") === executor)
|
|
248
|
+
.map((night) => night.capacityVUs);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function analyseDeployment(deployment, cells, history) {
|
|
252
|
+
const rows = [];
|
|
253
|
+
let nights = 0;
|
|
254
|
+
for (const tier of deployment.tiers) {
|
|
255
|
+
for (const runner of RUNNERS) {
|
|
256
|
+
const summary = cells[tier]?.[runner];
|
|
257
|
+
const past = summary && !summary.error ? pastNights(deployment, tier, runner, summary, history) : [];
|
|
258
|
+
nights = Math.max(nights, past.length);
|
|
259
|
+
const change =
|
|
260
|
+
summary && !summary.error
|
|
261
|
+
? flaggedChange(summary.capacity?.targetVUs ?? 0, past, { higherIsBetter: true })
|
|
262
|
+
: null;
|
|
263
|
+
rows.push({
|
|
264
|
+
deployment,
|
|
265
|
+
tier,
|
|
266
|
+
runner,
|
|
267
|
+
summary,
|
|
268
|
+
change,
|
|
269
|
+
hot: hotComponents(summary),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return { rows, nights };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function hotComponents(summary) {
|
|
277
|
+
const groups = summary?.serverMetricsAtCapacity?.groups ?? {};
|
|
278
|
+
return COMPONENTS.flatMap(([label, name]) => {
|
|
279
|
+
const cpu = peakCpu(groups[label]);
|
|
280
|
+
return cpu != null && cpu >= BOTTLENECK_CPU_PCT ? [{ name, cpu: Math.round(cpu) }] : [];
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function bottleneckLines(rows) {
|
|
285
|
+
const groups = new Map();
|
|
286
|
+
for (const row of rows) {
|
|
287
|
+
for (const { name, cpu } of row.hot) {
|
|
288
|
+
const key = `${row.deployment.slug}|${name}`;
|
|
289
|
+
const group = groups.get(key) ?? { deployment: row.deployment, name, tiers: new Set(), cpus: [] };
|
|
290
|
+
group.tiers.add(tierLabel(row.deployment, row.tier));
|
|
291
|
+
group.cpus.push(cpu);
|
|
292
|
+
groups.set(key, group);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const order = (group) => COMPONENTS.findIndex(([, name]) => name === group.name);
|
|
296
|
+
return [...groups.values()].sort((a, b) => order(a) - order(b)).map(({ deployment, name, tiers, cpus }) => {
|
|
297
|
+
const low = Math.min(...cpus);
|
|
298
|
+
const high = Math.max(...cpus);
|
|
299
|
+
const range = low === high ? `${high}%` : `${low} to ${high}%`;
|
|
300
|
+
return `${deploymentName(deployment)} ${[...tiers].join(", ")}: ${name} at ${range}`;
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function crashedTiers(rows) {
|
|
305
|
+
const byTier = new Map();
|
|
306
|
+
for (const row of rows) {
|
|
307
|
+
if (!row.summary?.error) continue;
|
|
308
|
+
const key = `${row.deployment.slug}|${row.tier}`;
|
|
309
|
+
(byTier.get(key) ?? byTier.set(key, { row, runners: [] }).get(key)).runners.push(row.runner);
|
|
310
|
+
}
|
|
311
|
+
return [...byTier.values()].map(({ row, runners }) => {
|
|
312
|
+
const where = `${deploymentName(row.deployment)} ${tierLabel(row.deployment, row.tier)}`;
|
|
313
|
+
const detail = runners.length === RUNNERS.length
|
|
314
|
+
? `${where}, all ${RUNNERS.length} tests (ERR)`
|
|
315
|
+
: `${where} ${runners.map(runnerColumnName).join(", ")} (ERR)`;
|
|
316
|
+
return { where, detail };
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function moveLine(row, unit) {
|
|
321
|
+
const now = row.summary.capacity?.targetVUs ?? 0;
|
|
322
|
+
return `${cellName(row.deployment, row.tier, row.runner)} ${formatMove(Math.round(row.change.median), now, row.change.deltaPct, unit)}`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function capacityCell(summary) {
|
|
326
|
+
if (!summary) return "-";
|
|
327
|
+
if (summary.error) return "ERR";
|
|
328
|
+
return String(summary.capacity?.targetVUs ?? 0);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function plural(n, word) {
|
|
332
|
+
return `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function stepSecondsOf(summaries) {
|
|
336
|
+
const seen = [...new Set(
|
|
337
|
+
summaries.map((s) => s.config?.plateauDurationSeconds).filter((v) => v != null).map(String),
|
|
338
|
+
)];
|
|
339
|
+
if (seen.length === 0) return STAIRCASE_PLATEAU_DURATION;
|
|
340
|
+
return seen.sort((a, b) => Number(a) - Number(b)).join("/");
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** A dispatch can override the configured geometry; the report describes the run. */
|
|
344
|
+
function geometryOf(deployment, cells) {
|
|
345
|
+
const ran = ranGeometry(cells) ?? deployment.staircase ?? {};
|
|
346
|
+
return {
|
|
347
|
+
start: Number(ran.startLoad ?? STAIRCASE_START_LOAD),
|
|
348
|
+
step: Number(ran.stepSize ?? STAIRCASE_STEP_SIZE),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function capacityTable(deployment, rows, unit) {
|
|
353
|
+
const labels = deployment.tiers.map((tier) => tierLabel(deployment, tier));
|
|
354
|
+
const labelWidth = Math.max(2, ...labels.map((l) => l.length)) + 1;
|
|
355
|
+
const column = (text, arrow = " ") => `${text.padStart(6)}${arrow}`;
|
|
356
|
+
const lines = [
|
|
357
|
+
`*${deploymentName(deployment)}* · ${unit} at SLO`,
|
|
358
|
+
"```",
|
|
359
|
+
`${"".padEnd(labelWidth)}${RUNNERS.map((r) => column(runnerColumnName(r))).join("")}`,
|
|
360
|
+
];
|
|
361
|
+
for (const tier of deployment.tiers) {
|
|
362
|
+
const cells = rows.filter((row) => row.tier === tier);
|
|
363
|
+
lines.push(
|
|
364
|
+
`${tierLabel(deployment, tier).padEnd(labelWidth)}${cells.map((row) => column(capacityCell(row.summary), row.change?.arrow)).join("")}`,
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
lines.push("```");
|
|
368
|
+
return lines;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export function formatAggregateTable(
|
|
372
|
+
deployments,
|
|
373
|
+
summaries,
|
|
374
|
+
warnings = [],
|
|
375
|
+
now = new Date(),
|
|
376
|
+
history = {},
|
|
377
|
+
apiVersion = null,
|
|
378
|
+
manual = false,
|
|
379
|
+
) {
|
|
380
|
+
const byDeployment = indexCells(deployments, summaries);
|
|
381
|
+
const analysed = deployments.map((deployment) => ({
|
|
382
|
+
deployment,
|
|
383
|
+
...analyseDeployment(deployment, byDeployment[deployment.slug] ?? {}, history),
|
|
384
|
+
}));
|
|
385
|
+
const rows = analysed.flatMap((a) => a.rows);
|
|
386
|
+
|
|
387
|
+
const expected = rows.length;
|
|
388
|
+
const failed = rows.filter((row) => row.summary?.error).length;
|
|
389
|
+
const missing = rows.filter((row) => !row.summary).length;
|
|
390
|
+
const jobFailed = process.env.CAPACITY_JOB_RESULT === "failure";
|
|
391
|
+
const regressed = rows.filter((row) => row.change && !row.change.better);
|
|
392
|
+
const improved = rows.filter((row) => row.change?.better);
|
|
393
|
+
const bottlenecks = bottleneckLines(rows);
|
|
394
|
+
const checked = analysed.some((a) => a.nights >= MIN_HISTORY_NIGHTS);
|
|
395
|
+
const allWarnings = [...warnings, ...toolOverheadWarnings(summaries)];
|
|
231
396
|
|
|
232
397
|
const executor = executorOf(summaries);
|
|
233
|
-
const open = executor === OPEN_MODEL;
|
|
234
398
|
const unit = unitFor(executor);
|
|
399
|
+
const date = now.toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
|
|
400
|
+
const ran = failed + missing === 0 ? `all ${expected} cells ran` : `${expected - failed - missing} of ${expected} cells ran`;
|
|
401
|
+
const verdict = [];
|
|
402
|
+
const crashed = crashedTiers(rows);
|
|
403
|
+
if (crashed.length > 0) verdict.push(`${crashed.map((tier) => tier.where).join(", ")} crashed`);
|
|
404
|
+
if (missing > 0) verdict.push(`${missing} never ran`);
|
|
405
|
+
if (jobFailed) verdict.push("job failed");
|
|
406
|
+
if (regressed.length > 0) verdict.push(plural(regressed.length, "regression"));
|
|
407
|
+
if (improved.length > 0) verdict.push(plural(improved.length, "improvement"));
|
|
408
|
+
if (bottlenecks.length > 0) verdict.push(plural(bottlenecks.length, "bottleneck"));
|
|
409
|
+
if (verdict.length === 0) verdict.push("all quiet");
|
|
410
|
+
|
|
411
|
+
const dot = dotFor({
|
|
412
|
+
failed: failed + missing > 0 || jobFailed,
|
|
413
|
+
attention: regressed.length + bottlenecks.length + allWarnings.length > 0,
|
|
414
|
+
});
|
|
235
415
|
const lines = [
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
`*How:* ${open ? "the offered request rate" : "the number of users"} climbs in steps of ${stepSeconds}s. A step passes at success >= ${SLO.minSuccessRate}%, p50 <= ${SLO.maxP50Ms / 1000}s, p95 <= ${SLO.maxP95Ms / 1000}s. Capacity = the top passing step, with the step below also passing.${open ? " Requests the tool had to drop count as failures." : ""}`,
|
|
239
|
-
"*Graph:* `default`, 1 step, no LLM, 1KB checkpoint. Server overhead, not a customer workload.",
|
|
240
|
-
`*Tests:* ${RUNNERS.map((runner) => `${runnerShortName(runner)} = ${describeRunner(runner)}`).join(" · ")}`,
|
|
241
|
-
`*Reading a cell:* \`400 (398/s)\` held 400 ${unit} at SLO, serving 398 runs/sec · \`0 (~46/s ceiling)\` no step met SLO, best rate any step served · \`ERR\` crashed, no data · \`-\` never ran`,
|
|
242
|
-
"*Pods:* every tier starts at one queue pod and grows during a cell, so a low number can mean few pods rather than a slow server. Pod counts and CPU peaks are listed under each table where the control plane returned them.",
|
|
416
|
+
`${dot} *Capacity · ${date}*${manual ? " · manual run" : ""}${apiVersion ? ` · API ${apiVersion}` : ""} · ${ran} · ${verdict.join(", ")}`,
|
|
417
|
+
describeCapacity(analysed, summaries, executor),
|
|
243
418
|
];
|
|
244
419
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (failed > 0) problems.push(`${failed} failed`);
|
|
249
|
-
if (missing > 0) problems.push(`${missing} never ran`);
|
|
250
|
-
if (process.env.CAPACITY_JOB_RESULT === "failure") {
|
|
251
|
-
problems.push("the capacity job itself failed");
|
|
420
|
+
const failedParts = crashed.map((tier) => tier.detail);
|
|
421
|
+
for (const row of rows) {
|
|
422
|
+
if (!row.summary) failedParts.push(`${cellName(row.deployment, row.tier, row.runner)} never ran`);
|
|
252
423
|
}
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
424
|
+
if (jobFailed) failedParts.push("the capacity job exited with failure");
|
|
425
|
+
if (failedParts.length > 0) {
|
|
426
|
+
lines.push(`*Failed:* ${failedParts.join(" · ")} · treat the table as incomplete`);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (!checked) {
|
|
430
|
+
const nights = Math.max(...analysed.map((a) => a.nights));
|
|
431
|
+
lines.push(`*Regressed:* not checked, ${nights} of ${MIN_HISTORY_NIGHTS} nights of history`);
|
|
432
|
+
} else {
|
|
433
|
+
lines.push(`*Regressed:* ${regressed.length > 0 ? regressed.map((row) => moveLine(row, unit)).join(" · ") : "none"}`);
|
|
434
|
+
if (improved.length > 0) lines.push(`*Improved:* ${improved.map((row) => moveLine(row, unit)).join(" · ")}`);
|
|
435
|
+
}
|
|
436
|
+
lines.push(`*Bottlenecks:* ${bottlenecks.length > 0 ? bottlenecks.join(" · ") : "none reported"}`);
|
|
437
|
+
for (const warning of allWarnings) lines.push(`:warning: ${warning}`);
|
|
438
|
+
|
|
439
|
+
for (const { deployment, rows: deploymentRows, nights } of analysed) {
|
|
440
|
+
lines.push("", ...capacityTable(deployment, deploymentRows, unitFor(executorOf(deploymentRows.map((r) => r.summary).filter(Boolean)))));
|
|
441
|
+
if (checked && nights < MIN_HISTORY_NIGHTS) {
|
|
442
|
+
lines.push(`_${nights} of ${MIN_HISTORY_NIGHTS} nights of history, no change flags yet_`);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
lines.push(
|
|
447
|
+
"",
|
|
448
|
+
`▲ better ▼ worse than the last ${MIN_HISTORY_NIGHTS}+ nights · \`0\` no step passed · \`ERR\` crashed · \`-\` never ran · 🟢 quiet · 🟡 regression or bottleneck · 🔴 cells failed`,
|
|
449
|
+
);
|
|
450
|
+
return lines.join("\n");
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function describeCapacity(analysed, summaries, executor) {
|
|
454
|
+
const open = executor === OPEN_MODEL;
|
|
455
|
+
const unit = unitFor(executor);
|
|
456
|
+
const climb = analysed
|
|
457
|
+
.map(({ deployment, rows }) => {
|
|
458
|
+
const cells = indexCells([deployment], rows.map((r) => r.summary).filter(Boolean))[deployment.slug] ?? {};
|
|
459
|
+
const { start, step } = geometryOf(deployment, cells);
|
|
460
|
+
return `+${step} from ${start} (${deploymentName(deployment).toLowerCase()})`;
|
|
461
|
+
})
|
|
462
|
+
.join(" or ");
|
|
463
|
+
const where = analysed.length === 1 ? "one staging deployment" : `${analysed.length} staging deployments`;
|
|
464
|
+
return (
|
|
465
|
+
`k6 ${open ? "open-model" : "closed-model"} staircase, ${where} resized per tier: ${open ? "request rate" : "virtual users"} ${climb} every ${stepSecondsOf(summaries)} s, per path: ${RUNNERS.map(runnerGloss).join(", ")}. ` +
|
|
466
|
+
`Cell = highest ${unit} where success ≥ ${SLO.minSuccessRate}%, p50 ≤ ${SLO.maxP50Ms / 1000} s, p95 ≤ ${SLO.maxP95Ms / 1000} s held for two steps. ` +
|
|
467
|
+
"One-step graph, no LLM: server ceiling, not customer traffic."
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export function howToRead() {
|
|
472
|
+
return [
|
|
473
|
+
"*How to read*",
|
|
474
|
+
`• *Tests:* ${RUNNERS.map((r) => `${runnerColumnName(r)} = ${describeRunnerBriefly(r)}`).join(" · ")}.`,
|
|
475
|
+
`• *Regressed / Improved:* a cell outside its own usual range over the last ${MIN_HISTORY_NIGHTS}+ nights measured the same way.`,
|
|
476
|
+
`• *Bottleneck:* a component at or over ${BOTTLENECK_CPU_PCT}% of its CPU request while the tier held its top step. It is what stops the tier going higher.`,
|
|
477
|
+
"• Graph is one step, no LLM, so this is server overhead, not a customer workload.",
|
|
478
|
+
].join("\n");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function servedRate(summary) {
|
|
482
|
+
const rate = summary?.capacity?.successfulRunsPerSec;
|
|
483
|
+
if (rate != null) return String(Math.round(rate));
|
|
484
|
+
const ceiling = summary?.throughputCeiling?.successfulRunsPerSec;
|
|
485
|
+
return ceiling != null ? `0 (ceiling ${Math.round(ceiling)})` : "-";
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function serverColumns(summaries) {
|
|
489
|
+
const columns = [];
|
|
490
|
+
for (const [label, name] of COMPONENTS) {
|
|
491
|
+
const groups = summaries.map((s) => s?.serverMetrics?.groups?.[label]).filter(Boolean);
|
|
492
|
+
if (groups.length === 0) continue;
|
|
493
|
+
if (groups.some(podRange)) columns.push({ label, kind: "pods", width: 7 });
|
|
494
|
+
if (groups.some((g) => peakCpu(g) != null)) columns.push({ label, kind: "cpu", width: 6 });
|
|
257
495
|
}
|
|
258
|
-
|
|
259
|
-
|
|
496
|
+
return columns;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function serverCell(summary, column) {
|
|
500
|
+
const group = summary?.serverMetrics?.groups?.[column.label];
|
|
501
|
+
if (column.kind === "pods") {
|
|
502
|
+
const range = podRange(group);
|
|
503
|
+
return range ? `${range.min}→${range.max}` : "-";
|
|
260
504
|
}
|
|
261
|
-
|
|
505
|
+
const cpu = peakCpu(group);
|
|
506
|
+
return cpu != null ? String(Math.round(cpu)) : "-";
|
|
507
|
+
}
|
|
262
508
|
|
|
509
|
+
export function formatServerView(deployments, summaries) {
|
|
510
|
+
const byDeployment = indexCells(deployments, summaries);
|
|
511
|
+
const blocks = [];
|
|
263
512
|
for (const deployment of deployments) {
|
|
264
513
|
const cells = byDeployment[deployment.slug] ?? {};
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
for (const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
row += capacityVus(summary).padEnd(20);
|
|
284
|
-
}
|
|
285
|
-
lines.push(row);
|
|
514
|
+
const present = Object.values(cells).flatMap((byRunner) => Object.values(byRunner));
|
|
515
|
+
if (present.length === 0) continue;
|
|
516
|
+
const served = deployment.tiers
|
|
517
|
+
.map((tier) => `${tierLabel(deployment, tier)} ${RUNNERS.map((r) => servedRate(cells[tier]?.[r])).join(" / ")}`)
|
|
518
|
+
.join(" · ");
|
|
519
|
+
const servedLine = `Runs/sec actually served at the top step, as ${RUNNERS.map(runnerColumnName).join(" / ")}: ${served}`;
|
|
520
|
+
// The served rate is k6's; the pod and CPU columns are the dashboard's, which is best effort.
|
|
521
|
+
const columns = serverColumns(present);
|
|
522
|
+
if (columns.length === 0) {
|
|
523
|
+
blocks.push(`*${deploymentName(deployment)}*\n${servedLine}`);
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
const labelWidth = Math.max(...deployment.tiers.map((t) => tierLabel(deployment, t).length)) + 8;
|
|
527
|
+
const spans = [];
|
|
528
|
+
for (const column of columns) {
|
|
529
|
+
const last = spans[spans.length - 1];
|
|
530
|
+
if (last && last.label === column.label) last.width += column.width;
|
|
531
|
+
else spans.push({ label: column.label, width: column.width });
|
|
286
532
|
}
|
|
287
|
-
lines
|
|
533
|
+
const lines = [
|
|
534
|
+
`*${deploymentName(deployment)}*`,
|
|
535
|
+
"```",
|
|
536
|
+
`${"".padEnd(labelWidth)}${spans.map((s) => s.label.padStart(s.width)).join("")}`,
|
|
537
|
+
`${"".padEnd(labelWidth)}${columns.map((c) => c.kind.padStart(c.width)).join("")}`,
|
|
538
|
+
];
|
|
288
539
|
for (const tier of deployment.tiers) {
|
|
289
540
|
for (const runner of RUNNERS) {
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const drift = historyLine(deployment, cells, history);
|
|
295
|
-
if (drift) lines.push(drift);
|
|
296
|
-
lines.push("");
|
|
297
|
-
}
|
|
298
|
-
return lines.join("\n").trimEnd();
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function historyLine(deployment, cells, history) {
|
|
302
|
-
const moved = [];
|
|
303
|
-
let nights = 0;
|
|
304
|
-
for (const tier of deployment.tiers) {
|
|
305
|
-
for (const runner of RUNNERS) {
|
|
306
|
-
const summary = cells[tier]?.[runner];
|
|
307
|
-
if (!summary || summary.error) continue;
|
|
308
|
-
const executor = summary.config?.k6Executor ?? "constant-vus";
|
|
309
|
-
// Nights measured in users and nights measured in req/s are different
|
|
310
|
-
// scales; only the same executor is a baseline.
|
|
311
|
-
const past = (history[cellKey({ deploymentSlug: deployment.slug, computeTier: tier, benchmarkType: runner })] ?? [])
|
|
312
|
-
.filter((night) => (night.executor ?? "constant-vus") === executor);
|
|
313
|
-
const verdict = compare(summary.capacity?.targetVUs ?? 0, past.map((p) => p.capacityVUs));
|
|
314
|
-
if (!verdict) continue;
|
|
315
|
-
nights = Math.max(nights, verdict.nights);
|
|
316
|
-
if (verdict.outside) {
|
|
317
|
-
moved.push(
|
|
318
|
-
`${tier} ${runnerShortName(runner)} ${summary.capacity?.targetVUs ?? 0} vs median ${Math.round(verdict.median)} (${formatDelta(verdict.deltaPct)}, usual ±${verdict.spreadPct.toFixed(0)}%)`,
|
|
319
|
-
);
|
|
541
|
+
const summary = cells[tier]?.[runner];
|
|
542
|
+
if (!summary?.serverMetrics) continue;
|
|
543
|
+
const label = `${tierLabel(deployment, tier)} ${runnerColumnName(runner)}`;
|
|
544
|
+
lines.push(`${label.padEnd(labelWidth)}${columns.map((c) => serverCell(summary, c).padStart(c.width)).join("")}`);
|
|
320
545
|
}
|
|
321
546
|
}
|
|
547
|
+
lines.push("```", servedLine);
|
|
548
|
+
blocks.push(lines.join("\n"));
|
|
322
549
|
}
|
|
323
|
-
if (
|
|
324
|
-
return
|
|
325
|
-
|
|
326
|
-
|
|
550
|
+
if (blocks.length === 0) return null;
|
|
551
|
+
return [
|
|
552
|
+
"*Pods and CPU per cell*, peak over the whole cell including the steps that failed. Pods are start → end. CPU is % of the pod's request, so over 100 means bursting above it.",
|
|
553
|
+
...blocks,
|
|
554
|
+
].join("\n\n");
|
|
327
555
|
}
|
|
328
556
|
|
|
329
557
|
function toolOverheadWarnings(summaries) {
|
|
@@ -651,12 +879,20 @@ async function runDeploymentMatrix(deployment, apiKey) {
|
|
|
651
879
|
return { summaryPaths, failures, warnings };
|
|
652
880
|
}
|
|
653
881
|
|
|
882
|
+
// The steps past capacity saturate everything, so a bottleneck read over the
|
|
883
|
+
// whole cell names a component the tier never hit while it was passing.
|
|
654
884
|
async function attachServerMetrics(deployment, apiKey, summaryPath) {
|
|
655
885
|
const summary = JSON.parse(readFileSync(summaryPath, "utf8"));
|
|
656
886
|
const window = cellWindow(summary.steps);
|
|
657
887
|
if (!window) throw new Error("steps carry no timestamps");
|
|
658
|
-
|
|
659
|
-
|
|
888
|
+
summary.serverMetrics = summarizeServerMetrics(
|
|
889
|
+
await getDeploymentMetrics(deployment.deploymentId, apiKey, window),
|
|
890
|
+
);
|
|
891
|
+
const capacityStep = summary.capacity?.step;
|
|
892
|
+
const held = capacityStep ? cellWindow(summary.steps.filter((s) => s.step <= capacityStep)) : null;
|
|
893
|
+
summary.serverMetricsAtCapacity = held
|
|
894
|
+
? summarizeServerMetrics(await getDeploymentMetrics(deployment.deploymentId, apiKey, held))
|
|
895
|
+
: null;
|
|
660
896
|
writeFileSync(summaryPath, `${JSON.stringify(summary, null, 2)}\n`);
|
|
661
897
|
}
|
|
662
898
|
|
|
@@ -675,49 +911,26 @@ function collectSummaries(directory) {
|
|
|
675
911
|
);
|
|
676
912
|
}
|
|
677
913
|
|
|
678
|
-
async function postSlack(message) {
|
|
679
|
-
const token = process.env.SLACK_BOT_TOKEN;
|
|
680
|
-
const channel = process.env.SLACK_CHANNEL;
|
|
681
|
-
if (!token || !channel) {
|
|
682
|
-
console.log(
|
|
683
|
-
"SLACK_BOT_TOKEN or SLACK_CHANNEL not set; skipping Slack post",
|
|
684
|
-
);
|
|
685
|
-
console.log(message);
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
const response = await fetch("https://slack.com/api/chat.postMessage", {
|
|
690
|
-
method: "POST",
|
|
691
|
-
headers: {
|
|
692
|
-
"Content-Type": "application/json; charset=utf-8",
|
|
693
|
-
Authorization: `Bearer ${token}`,
|
|
694
|
-
},
|
|
695
|
-
body: JSON.stringify({ channel, text: message }),
|
|
696
|
-
});
|
|
697
|
-
const result = await response.json();
|
|
698
|
-
if (!result.ok) {
|
|
699
|
-
throw new Error(`Slack API error: ${result.error ?? "unknown"}`);
|
|
700
|
-
}
|
|
701
|
-
console.log("Posted aggregate summary to Slack");
|
|
702
|
-
}
|
|
703
|
-
|
|
704
914
|
async function runAggregate(summariesDir, { postToSlack, historyDir }) {
|
|
705
915
|
const summaries = collectSummaries(summariesDir);
|
|
706
916
|
const warnings = collectWarnings(summariesDir);
|
|
707
|
-
const
|
|
917
|
+
const history = historyDir ? loadCapacityHistory(historyDir) : {};
|
|
918
|
+
let text = formatAggregateTable(
|
|
708
919
|
CAPACITY_DEPLOYMENTS,
|
|
709
920
|
summaries,
|
|
710
921
|
warnings,
|
|
711
922
|
new Date(),
|
|
712
|
-
|
|
923
|
+
history,
|
|
924
|
+
process.env.API_VERSION || readApiVersion(),
|
|
925
|
+
process.env.MANUAL === "true",
|
|
713
926
|
);
|
|
714
|
-
|
|
927
|
+
const artifactUrl = process.env.GITHUB_RUN_URL;
|
|
928
|
+
text += `\n*Thread:* pods and CPU per cell, and how to read${artifactUrl ? ` · <${artifactUrl}|Artifacts:> raw k6 summaries` : ""}`;
|
|
929
|
+
const thread = [[formatServerView(CAPACITY_DEPLOYMENTS, summaries), howToRead()].filter(Boolean).join("\n\n")];
|
|
715
930
|
if (postToSlack) {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
: message;
|
|
720
|
-
await postSlack(slackMessage);
|
|
931
|
+
await postReport({ text, thread });
|
|
932
|
+
} else {
|
|
933
|
+
for (const part of [text, ...thread]) console.log(`${part}\n`);
|
|
721
934
|
}
|
|
722
935
|
}
|
|
723
936
|
|