diff --git a/.circleci/config.yml b/.circleci/config.yml index 77f3c2b9a7d..8672561f654 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -715,8 +715,8 @@ jobs: - run: name: Rename the coverage files command: | - mv coverage.xml litellm_router_coverage.xml - mv .coverage litellm_router_coverage + mv coverage.xml litellm_router_unit_coverage.xml + mv .coverage litellm_router_unit_coverage # Store test results - store_test_results: path: test-results @@ -724,8 +724,8 @@ jobs: - persist_to_workspace: root: . paths: - - litellm_router_coverage.xml - - litellm_router_coverage + - litellm_router_unit_coverage.xml + - litellm_router_unit_coverage litellm_security_tests: machine: image: ubuntu-2204:2023.10.1 @@ -1255,7 +1255,15 @@ jobs: ls # Add --timeout to kill hanging tests after 120s (2 min) # Add --durations=20 to show 20 slowest tests for debugging - python -m pytest -vv tests/llm_translation --cov=litellm --cov-report=xml -v --junitxml=test-results/junit.xml --durations=20 -n 4 --timeout=120 --timeout_method=thread + # Subdirectories with dedicated jobs (maintain this list as new jobs are added) + IGNORE_DIRS=( + "tests/llm_translation/realtime" + ) + IGNORE_ARGS="" + for dir in "${IGNORE_DIRS[@]}"; do + IGNORE_ARGS="$IGNORE_ARGS --ignore=$dir" + done + python -m pytest -vv tests/llm_translation $IGNORE_ARGS --cov=litellm --cov-report=xml -v --junitxml=test-results/junit.xml --durations=20 -n 4 --timeout=120 --timeout_method=thread no_output_timeout: 120m - run: name: Rename the coverage files @@ -1271,6 +1279,54 @@ jobs: paths: - llm_translation_coverage.xml - llm_translation_coverage + realtime_translation_testing: + docker: + - image: cimg/python:3.11 + auth: + username: ${DOCKERHUB_USERNAME} + password: ${DOCKERHUB_PASSWORD} + working_directory: ~/project + + steps: + - checkout + - setup_google_dns + - run: + name: Install Dependencies + command: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + pip install "pytest==7.3.1" + pip install "pytest-retry==1.6.3" + pip install "pytest-cov==5.0.0" + pip install "pytest-asyncio==0.21.1" + pip install "respx==0.22.0" + pip install "pytest-xdist==3.6.1" + pip install "pytest-timeout==2.2.0" + pip install "websockets" + # Run pytest and generate JUnit XML report + - run: + name: Run realtime tests + command: | + pwd + ls + # Add --timeout to kill hanging tests after 120s (2 min) + # Add --durations=20 to show 20 slowest tests for debugging + python -m pytest -vv tests/llm_translation/realtime --cov=litellm --cov-report=xml -v --junitxml=test-results/junit.xml --durations=20 -n 4 --timeout=120 --timeout_method=thread + no_output_timeout: 120m + - run: + name: Rename the coverage files + command: | + mv coverage.xml realtime_translation_coverage.xml + mv .coverage realtime_translation_coverage + + # Store test results + - store_test_results: + path: test-results + - persist_to_workspace: + root: . + paths: + - realtime_translation_coverage.xml + - realtime_translation_coverage mcp_testing: docker: - image: cimg/python:3.11 @@ -3407,6 +3463,110 @@ jobs: - store_test_results: path: test-results + proxy_e2e_anthropic_messages_tests: + machine: + image: ubuntu-2204:2023.10.1 + resource_class: xlarge + working_directory: ~/project + steps: + - checkout + - setup_google_dns + - run: + name: Install Docker CLI (In case it's not already installed) + command: | + curl -fsSL https://get.docker.com | sh + sudo usermod -aG docker $USER + docker version + - run: + name: Install Python 3.10 + command: | + curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output miniconda.sh + bash miniconda.sh -b -p $HOME/miniconda + export PATH="$HOME/miniconda/bin:$PATH" + conda init bash + source ~/.bashrc + conda create -n myenv python=3.10 -y + conda activate myenv + python --version + - run: + name: Install Dependencies + command: | + export PATH="$HOME/miniconda/bin:$PATH" + source $HOME/miniconda/etc/profile.d/conda.sh + conda activate myenv + pip install "pytest==7.3.1" + pip install "pytest-asyncio==0.21.1" + pip install "boto3==1.36.0" + pip install "httpx==0.27.0" + pip install "claude-agent-sdk" + pip install -r requirements.txt + - run: + name: Install dockerize + command: | + wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz + sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz + rm dockerize-linux-amd64-v0.6.1.tar.gz + - run: + name: Start PostgreSQL Database + command: | + docker run -d \ + --name postgres-db \ + -e POSTGRES_USER=postgres \ + -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_DB=circle_test \ + -p 5432:5432 \ + postgres:14 + - run: + name: Wait for PostgreSQL to be ready + command: dockerize -wait tcp://localhost:5432 -timeout 1m + - attach_workspace: + at: ~/project + - run: + name: Load Docker Database Image + command: | + gunzip -c litellm-docker-database.tar.gz | docker load + docker images | grep litellm-docker-database + - run: + name: Run Docker container with test config + command: | + docker run -d \ + -p 4000:4000 \ + -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ + -e LITELLM_MASTER_KEY="sk-1234" \ + -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ + -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ + -e AWS_REGION_NAME="us-east-1" \ + --add-host host.docker.internal:host-gateway \ + --name my-app \ + -v $(pwd)/tests/proxy_e2e_anthropic_messages_tests/test_config.yaml:/app/config.yaml \ + litellm-docker-database:ci \ + --config /app/config.yaml \ + --port 4000 \ + --detailed_debug + - run: + name: Start outputting logs + command: docker logs -f my-app + background: true + - run: + name: Wait for app to be ready + command: dockerize -wait http://localhost:4000 -timeout 5m + - run: + name: Run Claude Agent SDK E2E Tests + command: | + export PATH="$HOME/miniconda/bin:$PATH" + source $HOME/miniconda/etc/profile.d/conda.sh + conda activate myenv + export LITELLM_PROXY_URL="http://localhost:4000" + export LITELLM_API_KEY="sk-1234" + pwd + ls + python -m pytest -vv tests/proxy_e2e_anthropic_messages_tests/ -x -s --junitxml=test-results/junit.xml --durations=5 + no_output_timeout: 120m + + # Store test results + - store_test_results: + path: test-results + upload-coverage: docker: - image: cimg/python:3.9 @@ -3428,7 +3588,7 @@ jobs: python -m venv venv . venv/bin/activate pip install coverage - coverage combine llm_translation_coverage llm_responses_api_coverage ocr_coverage search_coverage mcp_coverage logging_coverage audio_coverage litellm_router_coverage local_testing_part1_coverage local_testing_part2_coverage litellm_assistants_api_coverage auth_ui_unit_tests_coverage langfuse_coverage caching_coverage litellm_proxy_unit_tests_part1_coverage litellm_proxy_unit_tests_part2_coverage image_gen_coverage pass_through_unit_tests_coverage batches_coverage litellm_security_tests_coverage guardrails_coverage litellm_mapped_tests_coverage + coverage combine llm_translation_coverage realtime_translation_coverage llm_responses_api_coverage ocr_coverage search_coverage mcp_coverage logging_coverage audio_coverage litellm_router_coverage litellm_router_unit_coverage local_testing_part1_coverage local_testing_part2_coverage litellm_assistants_api_coverage auth_ui_unit_tests_coverage langfuse_coverage caching_coverage litellm_proxy_unit_tests_part1_coverage litellm_proxy_unit_tests_part2_coverage image_gen_coverage pass_through_unit_tests_coverage batches_coverage litellm_security_tests_coverage guardrails_coverage litellm_mapped_tests_coverage coverage xml - codecov/upload: file: ./coverage.xml @@ -3478,8 +3638,22 @@ jobs: ls dist/ twine upload --verbose dist/* else - echo "Version ${VERSION} of package is already published on PyPI. Skipping PyPI publish." - circleci step halt + echo "Version ${VERSION} of package is already published on PyPI." + + # Check if corresponding Docker nightly image exists + NIGHTLY_TAG="v${VERSION}-nightly" + echo "Checking for Docker nightly image: litellm/litellm:${NIGHTLY_TAG}" + + # Check Docker Hub for the nightly image + if curl -s "https://hub.docker.com/v2/repositories/litellm/litellm/tags/${NIGHTLY_TAG}" | grep -q "name"; then + echo "Docker nightly image ${NIGHTLY_TAG} exists. This release was already completed successfully." + echo "Skipping PyPI publish and continuing to ensure Docker images are up to date." + circleci step halt + else + echo "ERROR: PyPI package ${VERSION} exists but Docker nightly image ${NIGHTLY_TAG} does not exist!" + echo "This indicates an incomplete release. Please investigate." + exit 1 + fi fi - run: name: Trigger Github Action for new Docker Container + Trigger Load Testing @@ -3488,11 +3662,21 @@ jobs: python3 -m pip install toml VERSION=$(python3 -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['version'])") echo "LiteLLM Version ${VERSION}" + + # Determine which branch to use for Docker build + if [[ "$CIRCLE_BRANCH" =~ ^litellm_release_day_.* ]]; then + BUILD_BRANCH="$CIRCLE_BRANCH" + echo "Using release branch: $BUILD_BRANCH" + else + BUILD_BRANCH="main" + echo "Using default branch: $BUILD_BRANCH" + fi + curl -X POST \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: Bearer $GITHUB_TOKEN" \ "https://api.github.com/repos/BerriAI/litellm/actions/workflows/ghcr_deploy.yml/dispatches" \ - -d "{\"ref\":\"main\", \"inputs\":{\"tag\":\"v${VERSION}-nightly\", \"commit_hash\":\"$CIRCLE_SHA1\"}}" + -d "{\"ref\":\"${BUILD_BRANCH}\", \"inputs\":{\"tag\":\"v${VERSION}-nightly\", \"commit_hash\":\"$CIRCLE_SHA1\"}}" echo "triggering load testing server for version ${VERSION} and commit ${CIRCLE_SHA1}" curl -X POST "https://proxyloadtester-production.up.railway.app/start/load/test?version=${VERSION}&commit_hash=${CIRCLE_SHA1}&release_type=nightly" @@ -3626,6 +3810,9 @@ jobs: cd ui/litellm-dashboard + # Remove node_modules and package-lock to ensure clean install (fixes dependency resolution issues) + rm -rf node_modules package-lock.json + # Install dependencies first npm install @@ -4051,12 +4238,26 @@ workflows: only: - main - /litellm_.*/ + - proxy_e2e_anthropic_messages_tests: + requires: + - build_docker_database_image + filters: + branches: + only: + - main + - /litellm_.*/ - llm_translation_testing: filters: branches: only: - main - /litellm_.*/ + - realtime_translation_testing: + filters: + branches: + only: + - main + - /litellm_.*/ - mcp_testing: filters: branches: @@ -4168,6 +4369,7 @@ workflows: - upload-coverage: requires: - llm_translation_testing + - realtime_translation_testing - mcp_testing - google_generate_content_endpoint_testing - guardrails_testing @@ -4235,6 +4437,7 @@ workflows: branches: only: - main + - /litellm_release_day_.*/ - publish_to_pypi: requires: - mypy_linting @@ -4244,6 +4447,7 @@ workflows: - e2e_openai_endpoints - test_bad_database_url - llm_translation_testing + - realtime_translation_testing - mcp_testing - google_generate_content_endpoint_testing - llm_responses_api_testing diff --git a/.circleci/requirements.txt b/.circleci/requirements.txt index 8c44dc18305..a5ec74424fe 100644 --- a/.circleci/requirements.txt +++ b/.circleci/requirements.txt @@ -16,4 +16,5 @@ uvloop==0.21.0 mcp==1.25.0 # for MCP server semantic_router==0.1.10 # for auto-routing with litellm fastuuid==0.12.0 -responses==0.25.7 # for proxy client tests \ No newline at end of file +responses==0.25.7 # for proxy client tests +pytest-retry==1.6.3 # for automatic test retries \ No newline at end of file diff --git a/.github/workflows/test-linting.yml b/.github/workflows/test-linting.yml index 35ebffeada3..7c5c269f899 100644 --- a/.github/workflows/test-linting.yml +++ b/.github/workflows/test-linting.yml @@ -73,4 +73,4 @@ jobs: - name: Check import safety run: | - poetry run python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1) \ No newline at end of file + poetry run python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1) diff --git a/.github/workflows/test-litellm.yml b/.github/workflows/test-litellm.yml index ba32dc1bf54..d9cf2e74a11 100644 --- a/.github/workflows/test-litellm.yml +++ b/.github/workflows/test-litellm.yml @@ -34,7 +34,7 @@ jobs: poetry run pip install "google-genai==1.22.0" poetry run pip install "google-cloud-aiplatform>=1.38" poetry run pip install "fastapi-offline==1.7.3" - poetry run pip install "python-multipart==0.0.18" + poetry run pip install "python-multipart==0.0.22" poetry run pip install "openapi-core" - name: Setup litellm-enterprise as local package run: | diff --git a/.github/workflows/test-model-map.yaml b/.github/workflows/test-model-map.yaml new file mode 100644 index 00000000000..ae5ac402e23 --- /dev/null +++ b/.github/workflows/test-model-map.yaml @@ -0,0 +1,15 @@ +name: Validate model_prices_and_context_window.json + +on: + pull_request: + branches: [ main ] + +jobs: + validate-model-prices-json: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Validate model_prices_and_context_window.json + run: | + jq empty model_prices_and_context_window.json diff --git a/.gitignore b/.gitignore index 0248d68c1e1..ddf5f6279b3 100644 --- a/.gitignore +++ b/.gitignore @@ -60,10 +60,6 @@ litellm/proxy/_super_secret_config.yaml litellm/proxy/myenv/bin/activate litellm/proxy/myenv/bin/Activate.ps1 myenv/* -litellm/proxy/_experimental/out/_next/ -litellm/proxy/_experimental/out/404/index.html -litellm/proxy/_experimental/out/model_hub/index.html -litellm/proxy/_experimental/out/onboarding/index.html litellm/tests/log.txt litellm/tests/langfuse.log litellm/tests/langfuse.log @@ -76,9 +72,6 @@ tests/local_testing/log.txt litellm/proxy/_new_new_secret_config.yaml litellm/proxy/custom_guardrail.py .mypy_cache/* -litellm/proxy/_experimental/out/404.html -litellm/proxy/_experimental/out/404.html -litellm/proxy/_experimental/out/model_hub.html .mypy_cache/* litellm/proxy/application.log tests/llm_translation/vertex_test_account.json @@ -100,9 +93,9 @@ litellm_config.yaml litellm/proxy/to_delete_loadtest_work/* update_model_cost_map.py tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server_manager.py -litellm/proxy/_experimental/out/guardrails/index.html scripts/test_vertex_ai_search.py LAZY_LOADING_IMPROVEMENTS.md +STABILIZATION_TODO.md **/test-results **/playwright-report **/*.storageState.json diff --git a/.trivyignore b/.trivyignore new file mode 100644 index 00000000000..0d04ecacdb5 --- /dev/null +++ b/.trivyignore @@ -0,0 +1,12 @@ +# LiteLLM Trivy Ignore File +# CVEs listed here are temporarily allowlisted pending fixes + +# Next.js vulnerabilities in UI dashboard (next@14.2.35) +# Allowlisted: 2026-01-31, 7-day fix timeline +# Fix: Upgrade to Next.js 15.5.10+ or 16.1.5+ + +# HIGH: DoS via request deserialization +GHSA-h25m-26qc-wcjf + +# MEDIUM: Image Optimizer DoS +CVE-2025-59471 diff --git a/AGENTS.md b/AGENTS.md index 61afbd035fe..5a48049ef45 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,12 +51,14 @@ LiteLLM is a unified interface for 100+ LLMs that: ### MAKING CODE CHANGES FOR THE UI (IGNORE FOR BACKEND) -1. **Use Common Components as much as possible**: +1. **Tremor is DEPRECATED, do not use Tremor components in new features/changes** + - The only exception is the Tremor Table component and its required Tremor Table sub components. + +2. **Use Common Components as much as possible**: - These are usually defined in the `common_components` directory - Use these components as much as possible and avoid building new components unless needed - - Tremor components are deprecated; prefer using Ant Design (AntD) as much as possible -2. **Testing**: +3. **Testing**: - The codebase uses **Vitest** and **React Testing Library** - **Query Priority Order**: Use query methods in this order: `getByRole`, `getByLabelText`, `getByPlaceholderText`, `getByText`, `getByTestId` - **Always use `screen`** instead of destructuring from `render()` (e.g., use `screen.getByText()` not `getByText`) diff --git a/Dockerfile b/Dockerfile index 0e7a8412bbc..4bfda939110 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,8 +46,9 @@ FROM $LITELLM_RUNTIME_IMAGE AS runtime # Ensure runtime stage runs as root USER root -# Install runtime dependencies -RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip +# Install runtime dependencies (libsndfile needed for audio processing on ARM64) +RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \ + npm install -g npm@latest tar@latest WORKDIR /app # Copy the current directory contents into the container at /app @@ -69,8 +70,8 @@ RUN find /usr/lib -type f -path "*/tornado/test/*" -delete && \ # Convert Windows line endings to Unix and make executable RUN sed -i 's/\r$//' docker/install_auto_router.sh && chmod +x docker/install_auto_router.sh && ./docker/install_auto_router.sh -# Generate prisma client -RUN prisma generate +# Generate prisma client using the correct schema +RUN prisma generate --schema=./litellm/proxy/schema.prisma # Convert Windows line endings to Unix for entrypoint scripts RUN sed -i 's/\r$//' docker/entrypoint.sh && chmod +x docker/entrypoint.sh RUN sed -i 's/\r$//' docker/prod_entrypoint.sh && chmod +x docker/prod_entrypoint.sh diff --git a/README.md b/README.md index 914fda384b0..77adddf8978 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,7 @@ Support for more providers. Missing a provider or LLM Platform, raise a [feature Greptile OpenHands

Netflix

+ OpenAI Agents SDK diff --git a/ci_cd/security_scans.sh b/ci_cd/security_scans.sh index cf026eb5263..340f8e96063 100755 --- a/ci_cd/security_scans.sh +++ b/ci_cd/security_scans.sh @@ -81,10 +81,10 @@ run_trivy_scans() { echo "Running Trivy scans..." echo "Scanning LiteLLM Docs..." - trivy fs --scanners vuln --dependency-tree --exit-code 1 --severity HIGH,CRITICAL,MEDIUM ./docs/ + trivy fs --ignorefile .trivyignore --scanners vuln --dependency-tree --exit-code 1 --severity HIGH,CRITICAL,MEDIUM ./docs/ echo "Scanning LiteLLM UI..." - trivy fs --scanners vuln --dependency-tree --exit-code 1 --severity HIGH,CRITICAL,MEDIUM ./ui/ + trivy fs --ignorefile .trivyignore --scanners vuln --dependency-tree --exit-code 1 --severity HIGH,CRITICAL,MEDIUM ./ui/ echo "Trivy scans completed successfully" } @@ -137,6 +137,7 @@ run_grype_scans() { "CVE-2019-1010025" # glibc pthread heap address leak - awaiting patched Wolfi glibc build "CVE-2026-22184" # zlib untgz buffer overflow - untgz unused + no fixed Wolfi build yet "GHSA-58pv-8j8x-9vj2" # jaraco.context path traversal - setuptools vendored only (v5.3.0), not used in application code (using v6.1.0+) + "GHSA-34x7-hfp2-rc4v" # node-tar hardlink path traversal - not applicable, tar CLI not exposed in application code "GHSA-r6q2-hw4h-h46w" # node-tar not used by application runtime, Linux-only container, not affect by macOS APFS-specific exploit "GHSA-8rrh-rw8j-w5fx" # wheel is from chainguard and will be handled by then TODO: Remove this after Chainguard updates the wheel "CVE-2025-59465" # We do not use Node in application runtime, only used for building Admin UI @@ -153,6 +154,7 @@ run_grype_scans() { "CVE-2025-15367" # No fix available yet "CVE-2025-12781" # No fix available yet "CVE-2025-11468" # No fix available yet + "CVE-2026-1299" # Python 3.13 email module header injection - not applicable, LiteLLM doesn't use BytesGenerator for email serialization ) # Build JSON array of allowlisted CVE IDs for jq diff --git a/cookbook/anthropic_agent_sdk/README.md b/cookbook/anthropic_agent_sdk/README.md new file mode 100644 index 00000000000..294d949e24e --- /dev/null +++ b/cookbook/anthropic_agent_sdk/README.md @@ -0,0 +1,144 @@ +# Claude Agent SDK with LiteLLM Gateway + +A simple example showing how to use Claude's Agent SDK with LiteLLM as a proxy. This lets you use any LLM provider (OpenAI, Bedrock, Azure, etc.) through the Agent SDK. + +## Quick Start + +### 1. Install dependencies + +```bash +pip install anthropic claude-agent-sdk litellm +``` + +### 2. Start LiteLLM proxy + +```bash +# Simple start with Claude +litellm --model claude-sonnet-4-20250514 + +# Or with a config file +litellm --config config.yaml +``` + +### 3. Run the chat + +**Basic Agent (no MCP):** + +```bash +python main.py +``` + +**Agent with MCP (DeepWiki2 for research):** + +```bash +python agent_with_mcp.py +``` + +If MCP connection fails, you can disable it: + +```bash +USE_MCP=false python agent_with_mcp.py +``` + +That's it! You can now chat with the agent in your terminal. + +### Chat Commands + +While chatting, you can use these commands: +- `models` - List all available models (fetched from your LiteLLM proxy) +- `model` - Switch to a different model +- `clear` - Start a new conversation +- `quit` or `exit` - End the chat + +The chat automatically fetches available models from your LiteLLM proxy's `/models` endpoint, so you'll always see what's currently configured. + +## Configuration + +Set these environment variables if needed: + +```bash +export LITELLM_PROXY_URL="http://localhost:4000" +export LITELLM_API_KEY="sk-1234" +export LITELLM_MODEL="bedrock-claude-sonnet-4.5" +``` + +Or just use the defaults - it'll connect to `http://localhost:4000` by default. + +## Files + +- `main.py` - Basic interactive agent without MCP +- `agent_with_mcp.py` - Agent with MCP server integration (DeepWiki2) +- `common.py` - Shared utilities and functions +- `config.example.yaml` - Example LiteLLM configuration +- `requirements.txt` - Python dependencies + +## Example Config File + +If you want to use multiple models, create a `config.yaml` (see `config.example.yaml`): + +```yaml +model_list: + - model_name: bedrock-claude-sonnet-4 + litellm_params: + model: "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-claude-sonnet-4.5 + litellm_params: + model: "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0" + aws_region_name: "us-east-1" +``` + +Then start LiteLLM with: `litellm --config config.yaml` + +## How It Works + +The key is pointing the Agent SDK to LiteLLM instead of directly to Anthropic: + +```python +# Point to LiteLLM gateway (not Anthropic) +os.environ["ANTHROPIC_BASE_URL"] = "http://localhost:4000" +os.environ["ANTHROPIC_API_KEY"] = "sk-1234" # Your LiteLLM key + +# Use any model configured in LiteLLM +options = ClaudeAgentOptions( + model="bedrock-claude-sonnet-4", # or gpt-4, or anything else + system_prompt="You are a helpful assistant.", + max_turns=50, +) +``` + +Note: Don't add `/anthropic` to the base URL - LiteLLM handles the routing automatically. + +## Why Use This? + +- **Switch providers easily**: Use the same code with OpenAI, Bedrock, Azure, etc. +- **Cost tracking**: LiteLLM tracks spending across all your agent conversations +- **Rate limiting**: Set budgets and limits on your agent usage +- **Load balancing**: Distribute requests across multiple API keys or regions +- **Fallbacks**: Automatically retry with a different model if one fails + +## Troubleshooting + +**Connection errors?** +- Make sure LiteLLM is running: `litellm --model your-model` +- Check the URL is correct (default: `http://localhost:4000`) + +**Authentication errors?** +- Verify your LiteLLM API key is correct +- Make sure the model is configured in your LiteLLM setup + +**Model not found?** +- Check the model name matches what's in your LiteLLM config +- Run `litellm --model your-model` to test it works + +**Agent with MCP stuck or failing?** +- The MCP server might not be available at `http://localhost:4000/mcp/deepwiki2` +- Try disabling MCP: `USE_MCP=false python agent_with_mcp.py` +- Or use the basic agent: `python main.py` + +## Learn More + +- [LiteLLM Docs](https://docs.litellm.ai/) +- [Claude Agent SDK](https://github.com/anthropics/anthropic-agent-sdk) +- [LiteLLM Proxy Guide](https://docs.litellm.ai/docs/proxy/quick_start) diff --git a/cookbook/anthropic_agent_sdk/agent_with_mcp.py b/cookbook/anthropic_agent_sdk/agent_with_mcp.py new file mode 100644 index 00000000000..ff25feb777f --- /dev/null +++ b/cookbook/anthropic_agent_sdk/agent_with_mcp.py @@ -0,0 +1,140 @@ +""" +Interactive Claude Agent SDK CLI with MCP Support + +This example demonstrates an interactive CLI chat with the Anthropic Agent SDK using LiteLLM as a proxy, +with MCP (Model Context Protocol) server integration for enhanced capabilities. +""" + +import asyncio +import os +from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions +from common import ( + Config, + fetch_available_models, + setup_litellm_env, + print_header, + handle_model_list, + handle_model_switch, + stream_response, +) + + +async def interactive_chat_with_mcp(): + """ + Interactive CLI chat with the agent and MCP server + """ + config = Config() + + # Configure Anthropic SDK to point to LiteLLM gateway + litellm_base_url = setup_litellm_env(config) + + # Fetch available models from proxy + available_models = await fetch_available_models(litellm_base_url, config.LITELLM_API_KEY) + + current_model = config.LITELLM_MODEL + + # MCP server configuration + mcp_server_url = f"{litellm_base_url}/mcp/deepwiki2" + use_mcp = os.getenv("USE_MCP", "true").lower() == "true" + + if not use_mcp: + print("āš ļø MCP disabled via USE_MCP=false") + + print_header(litellm_base_url, current_model, has_mcp=use_mcp) + + while True: + # Configure agent options + if use_mcp: + try: + # Try with MCP server (HTTP transport) + # Using McpHttpServerConfig format from Agent SDK + options = ClaudeAgentOptions( + system_prompt="You are a helpful AI assistant with access to DeepWiki for research. Be concise, accurate, and friendly.", + model=current_model, + max_turns=50, + mcp_servers={ + "deepwiki2": { + "type": "http", + "url": mcp_server_url, + "headers": { + "Authorization": f"Bearer {config.LITELLM_API_KEY}" + } + } + }, + ) + except Exception as e: + print(f"āš ļø Warning: Could not configure MCP server: {e}") + print("Continuing without MCP...\n") + use_mcp = False + options = ClaudeAgentOptions( + system_prompt="You are a helpful AI assistant. Be concise, accurate, and friendly.", + model=current_model, + max_turns=50, + ) + else: + # Without MCP + options = ClaudeAgentOptions( + system_prompt="You are a helpful AI assistant. Be concise, accurate, and friendly.", + model=current_model, + max_turns=50, + ) + + # Create agent client + try: + async with ClaudeSDKClient(options=options) as client: + conversation_active = True + + while conversation_active: + # Get user input + try: + user_input = input("\nšŸ‘¤ You: ").strip() + except (EOFError, KeyboardInterrupt): + print("\n\nšŸ‘‹ Goodbye!") + return + + # Handle commands + if user_input.lower() in ['quit', 'exit']: + print("\nšŸ‘‹ Goodbye!") + return + + if user_input.lower() == 'clear': + print("\nšŸ”„ Starting new conversation...\n") + conversation_active = False + continue + + if user_input.lower() == 'models': + handle_model_list(available_models, current_model) + continue + + if user_input.lower() == 'model': + new_model, should_restart = handle_model_switch(available_models, current_model) + if should_restart: + current_model = new_model + conversation_active = False + continue + + if not user_input: + continue + + # Stream response from agent + await stream_response(client, user_input) + + except Exception as e: + print(f"\nāŒ Error creating agent client: {e}") + print("This might be an MCP configuration issue. Try running without MCP:") + print(" USE_MCP=false python agent_with_mcp.py") + print("\nOr use the basic agent:") + print(" python main.py") + return + + +def main(): + """Run interactive chat with MCP""" + try: + asyncio.run(interactive_chat_with_mcp()) + except KeyboardInterrupt: + print("\n\nšŸ‘‹ Goodbye!") + + +if __name__ == "__main__": + main() diff --git a/cookbook/anthropic_agent_sdk/common.py b/cookbook/anthropic_agent_sdk/common.py new file mode 100644 index 00000000000..d9ee65cb58d --- /dev/null +++ b/cookbook/anthropic_agent_sdk/common.py @@ -0,0 +1,160 @@ +""" +Common utilities for Claude Agent SDK examples +""" + +import os +import httpx + + +class Config: + """Configuration for LiteLLM Gateway connection""" + + # LiteLLM proxy URL (default to local instance) + LITELLM_PROXY_URL = os.getenv("LITELLM_PROXY_URL", "http://localhost:4000") + + # LiteLLM API key (master key or virtual key) + LITELLM_API_KEY = os.getenv("LITELLM_API_KEY", "sk-1234") + + # Model name as configured in LiteLLM (e.g., "bedrock-claude-sonnet-4", "gpt-4", etc.) + LITELLM_MODEL = os.getenv("LITELLM_MODEL", "bedrock-claude-sonnet-4.5") + + +async def fetch_available_models(base_url: str, api_key: str) -> list[str]: + """ + Fetch available models from LiteLLM proxy /models endpoint + """ + try: + async with httpx.AsyncClient() as client: + response = await client.get( + f"{base_url}/models", + headers={"Authorization": f"Bearer {api_key}"}, + timeout=10.0 + ) + response.raise_for_status() + data = response.json() + return [model["id"] for model in data.get("data", [])] + except Exception as e: + print(f"āš ļø Warning: Could not fetch models from proxy: {e}") + print("Using default model list...") + # Fallback to default models + return [ + "bedrock-claude-sonnet-3.5", + "bedrock-claude-sonnet-4", + "bedrock-claude-sonnet-4.5", + "bedrock-claude-opus-4.5", + "bedrock-nova-premier", + ] + + +def setup_litellm_env(config: Config): + """ + Configure environment variables to point Agent SDK to LiteLLM + """ + litellm_base_url = config.LITELLM_PROXY_URL.rstrip('/') + os.environ["ANTHROPIC_BASE_URL"] = litellm_base_url + os.environ["ANTHROPIC_API_KEY"] = config.LITELLM_API_KEY + return litellm_base_url + + +def print_header(base_url: str, current_model: str, has_mcp: bool = False): + """ + Print the chat header + """ + mcp_indicator = " + MCP" if has_mcp else "" + print("=" * 70) + print(f"šŸ¤– Claude Agent SDK with LiteLLM Gateway{mcp_indicator} - Interactive Chat") + print("=" * 70) + print(f"šŸš€ Connected to: {base_url}") + print(f"šŸ“¦ Current model: {current_model}") + if has_mcp: + print("šŸ”Œ MCP: deepwiki2 enabled") + print("\nType your messages below. Commands:") + print(" - 'quit' or 'exit' to end the conversation") + print(" - 'clear' to start a new conversation") + print(" - 'model' to switch models") + print(" - 'models' to list available models") + print("=" * 70) + print() + + +def handle_model_list(available_models: list[str], current_model: str): + """ + Display available models + """ + print("\nšŸ“‹ Available models:") + for i, model in enumerate(available_models, 1): + marker = "āœ“" if model == current_model else " " + print(f" {marker} {i}. {model}") + + +def handle_model_switch(available_models: list[str], current_model: str) -> tuple[str, bool]: + """ + Handle model switching + + Returns: + tuple: (new_model, should_restart_conversation) + """ + print("\nšŸ“‹ Select a model:") + for i, model in enumerate(available_models, 1): + marker = "āœ“" if model == current_model else " " + print(f" {marker} {i}. {model}") + + try: + choice = input("\nEnter number (or press Enter to cancel): ").strip() + if choice: + idx = int(choice) - 1 + if 0 <= idx < len(available_models): + new_model = available_models[idx] + print(f"\nāœ… Switched to: {new_model}") + print("šŸ”„ Starting new conversation with new model...\n") + return new_model, True + else: + print("āŒ Invalid choice") + except (ValueError, IndexError): + print("āŒ Invalid input") + + return current_model, False + + +async def stream_response(client, user_input: str): + """ + Stream response from the agent + """ + print("\nšŸ¤– Assistant: ", end='', flush=True) + + try: + await client.query(user_input) + + # Show loading indicator + print("ā³ thinking...", end='', flush=True) + + # Stream the response + first_chunk = True + async for msg in client.receive_response(): + # Clear loading indicator on first message + if first_chunk: + print("\ršŸ¤– Assistant: ", end='', flush=True) + first_chunk = False + + # Handle different message types + if hasattr(msg, 'type'): + if msg.type == 'content_block_delta': + # Streaming text delta + if hasattr(msg, 'delta') and hasattr(msg.delta, 'text'): + print(msg.delta.text, end='', flush=True) + elif msg.type == 'content_block_start': + # Start of content block + if hasattr(msg, 'content_block') and hasattr(msg.content_block, 'text'): + print(msg.content_block.text, end='', flush=True) + + # Fallback to original content handling + if hasattr(msg, 'content'): + for content_block in msg.content: + if hasattr(content_block, 'text'): + print(content_block.text, end='', flush=True) + + print() # New line after response + + except Exception as e: + print(f"\r\nāŒ Error: {e}") + print("Please check your LiteLLM gateway is running and configured correctly.") diff --git a/cookbook/anthropic_agent_sdk/config.example.yaml b/cookbook/anthropic_agent_sdk/config.example.yaml new file mode 100644 index 00000000000..eb1984fc4ea --- /dev/null +++ b/cookbook/anthropic_agent_sdk/config.example.yaml @@ -0,0 +1,25 @@ +model_list: + - model_name: bedrock-claude-sonnet-3.5 + litellm_params: + model: "bedrock/us.anthropic.claude-3-5-sonnet-20240620-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-claude-sonnet-4 + litellm_params: + model: "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-claude-sonnet-4.5 + litellm_params: + model: "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-claude-opus-4.5 + litellm_params: + model: "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-nova-premier + litellm_params: + model: "bedrock/amazon.nova-premier-v1:0" + aws_region_name: "us-east-1" diff --git a/cookbook/anthropic_agent_sdk/main.py b/cookbook/anthropic_agent_sdk/main.py new file mode 100644 index 00000000000..231b57ca97b --- /dev/null +++ b/cookbook/anthropic_agent_sdk/main.py @@ -0,0 +1,95 @@ +""" +Simple Interactive Claude Agent SDK CLI using LiteLLM Gateway + +This example demonstrates an interactive CLI chat with the Anthropic Agent SDK using LiteLLM as a proxy. +LiteLLM acts as a unified interface, allowing you to use any LLM provider (OpenAI, Azure, Bedrock, etc.) +through the Claude Agent SDK by pointing it to the LiteLLM gateway. +""" + +import asyncio +from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions +from common import ( + Config, + fetch_available_models, + setup_litellm_env, + print_header, + handle_model_list, + handle_model_switch, + stream_response, +) + + +async def interactive_chat(): + """ + Interactive CLI chat with the agent + """ + config = Config() + + # Configure Anthropic SDK to point to LiteLLM gateway + litellm_base_url = setup_litellm_env(config) + + # Fetch available models from proxy + available_models = await fetch_available_models(litellm_base_url, config.LITELLM_API_KEY) + + current_model = config.LITELLM_MODEL + + print_header(litellm_base_url, current_model) + + while True: + # Configure agent options for each conversation + options = ClaudeAgentOptions( + system_prompt="You are a helpful AI assistant. Be concise, accurate, and friendly.", + model=current_model, + max_turns=50, + ) + + # Create agent client + async with ClaudeSDKClient(options=options) as client: + conversation_active = True + + while conversation_active: + # Get user input + try: + user_input = input("\nšŸ‘¤ You: ").strip() + except (EOFError, KeyboardInterrupt): + print("\n\nšŸ‘‹ Goodbye!") + return + + # Handle commands + if user_input.lower() in ['quit', 'exit']: + print("\nšŸ‘‹ Goodbye!") + return + + if user_input.lower() == 'clear': + print("\nšŸ”„ Starting new conversation...\n") + conversation_active = False + continue + + if user_input.lower() == 'models': + handle_model_list(available_models, current_model) + continue + + if user_input.lower() == 'model': + new_model, should_restart = handle_model_switch(available_models, current_model) + if should_restart: + current_model = new_model + conversation_active = False + continue + + if not user_input: + continue + + # Stream response from agent + await stream_response(client, user_input) + + +def main(): + """Run interactive chat""" + try: + asyncio.run(interactive_chat()) + except KeyboardInterrupt: + print("\n\nšŸ‘‹ Goodbye!") + + +if __name__ == "__main__": + main() diff --git a/cookbook/anthropic_agent_sdk/requirements.txt b/cookbook/anthropic_agent_sdk/requirements.txt new file mode 100644 index 00000000000..1e810bb7d99 --- /dev/null +++ b/cookbook/anthropic_agent_sdk/requirements.txt @@ -0,0 +1,2 @@ +claude-agent-sdk +httpx>=0.27.0 diff --git a/cookbook/livekit_agent_sdk/README.md b/cookbook/livekit_agent_sdk/README.md new file mode 100644 index 00000000000..1c3f0bf9564 --- /dev/null +++ b/cookbook/livekit_agent_sdk/README.md @@ -0,0 +1,114 @@ +# LiveKit Voice Agent with LiteLLM Gateway + +Simple example showing how to use LiveKit's xAI realtime plugin with LiteLLM as a proxy. This lets you switch between xAI, OpenAI, and Azure realtime APIs without changing your code. + +## Quick Start + +### 1. Install dependencies + +```bash +pip install livekit-agents[xai] websockets +``` + +### 2. Start LiteLLM proxy + +```bash +# With xAI +export XAI_API_KEY="your-xai-key" +litellm --config config.yaml --port 4000 +``` + +### 3. Run the voice agent + +```bash +python main.py +``` + +Type your message and get a voice response from Grok! + +## Configuration + +Set these environment variables if needed: + +```bash +export LITELLM_PROXY_URL="http://localhost:4000" +export LITELLM_API_KEY="sk-1234" +export LITELLM_MODEL="grok-voice-agent" +``` + +Or use the defaults - connects to `http://localhost:4000` by default. + +## Example Config File + +Create a `config.yaml` with your realtime models: + +```yaml +model_list: + - model_name: grok-voice-agent + litellm_params: + model: xai/grok-2-vision-1212 + api_key: os.environ/XAI_API_KEY + model_info: + mode: realtime + + - model_name: openai-voice-agent + litellm_params: + model: gpt-4o-realtime-preview + api_key: os.environ/OPENAI_API_KEY + model_info: + mode: realtime + +general_settings: + master_key: sk-1234 +``` + +Then start: `litellm --config config.yaml --port 4000` + +## How It Works + +LiveKit's xAI plugin connects through LiteLLM proxy by setting `base_url`: + +```python +from livekit.plugins import xai + +model = xai.realtime.RealtimeModel( + voice="ara", + api_key="sk-1234", # LiteLLM proxy key + base_url="http://localhost:4000", # Point to LiteLLM +) +``` + +## Switching Providers + +Just change the model in your config - no code changes needed: + +**xAI Grok:** +```yaml +model: xai/grok-2-vision-1212 +``` + +**OpenAI:** +```yaml +model: gpt-4o-realtime-preview +``` + +**Azure OpenAI:** +```yaml +model: azure/gpt-4o-realtime-preview +api_base: https://your-endpoint.openai.azure.com/ +``` + +## Why Use LiteLLM? + +- āœ… **Switch providers** without changing agent code +- āœ… **Cost tracking** across all voice sessions +- āœ… **Rate limiting** and budgets +- āœ… **Load balancing** across multiple API keys +- āœ… **Fallbacks** to backup models + +## Learn More + +- [LiveKit xAI Realtime Tutorial](/docs/tutorials/livekit_xai_realtime) +- [xAI Realtime Docs](/docs/providers/xai_realtime) +- [LiveKit Agents Documentation](https://docs.livekit.io/agents/) +- [LiteLLM Realtime API](/docs/realtime) diff --git a/cookbook/livekit_agent_sdk/config.example.yaml b/cookbook/livekit_agent_sdk/config.example.yaml new file mode 100644 index 00000000000..1361f36af34 --- /dev/null +++ b/cookbook/livekit_agent_sdk/config.example.yaml @@ -0,0 +1,21 @@ +model_list: + - model_name: grok-voice-agent + litellm_params: + model: xai/grok-2-vision-1212 + api_key: os.environ/XAI_API_KEY + model_info: + mode: realtime + + - model_name: openai-voice-agent + litellm_params: + model: gpt-4o-realtime-preview + api_key: os.environ/OPENAI_API_KEY + model_info: + mode: realtime + +litellm_settings: + drop_params: True + telemetry: False + +general_settings: + master_key: sk-1234 # Change this to a secure key diff --git a/cookbook/livekit_agent_sdk/main.py b/cookbook/livekit_agent_sdk/main.py new file mode 100644 index 00000000000..0e2d7ebdfaf --- /dev/null +++ b/cookbook/livekit_agent_sdk/main.py @@ -0,0 +1,112 @@ +""" +Simple xAI Voice Agent using LiveKit SDK with LiteLLM Gateway + +This example shows how to use LiveKit's xAI realtime plugin through LiteLLM proxy. +LiteLLM acts as a unified interface, allowing you to switch between xAI, OpenAI, +and Azure realtime APIs without changing your agent code. +""" +import asyncio +import json +import os +import websockets + +# Configuration +PROXY_URL = os.getenv("LITELLM_PROXY_URL", "http://localhost:4000") +API_KEY = os.getenv("LITELLM_API_KEY", "sk-1234") +MODEL = os.getenv("LITELLM_MODEL", "grok-voice-agent") + + +async def run_voice_agent(): + """ + Simple voice agent that: + 1. Connects to xAI realtime API through LiteLLM proxy + 2. Sends a user message + 3. Streams back the response + """ + + url = f"ws://{PROXY_URL.replace('http://', '').replace('https://', '')}/v1/realtime?model={MODEL}" + headers = {"Authorization": f"Bearer {API_KEY}"} + + print(f"šŸŽ™ļø Connecting to voice agent...") + print(f" Model: {MODEL}") + print(f" Proxy: {PROXY_URL}") + print() + + async with websockets.connect(url, additional_headers=headers) as ws: + # Receive initial connection event + initial = json.loads(await ws.recv()) + print(f"āœ… Connected! Event: {initial['type']}\n") + + # Get user input + user_message = input("šŸ’¬ Your message: ").strip() + if not user_message: + user_message = "Tell me a fun fact about AI!" + + print(f"\nšŸ¤– Sending to {MODEL}...\n") + + # Send user message + await ws.send(json.dumps({ + "type": "conversation.item.create", + "item": { + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": user_message}] + } + })) + + # Request response + await ws.send(json.dumps({ + "type": "response.create", + "response": {"modalities": ["text", "audio"]} + })) + + # Stream response + print("šŸŽ¤ Response: ", end='', flush=True) + transcript = [] + + try: + while True: + msg = await asyncio.wait_for(ws.recv(), timeout=15.0) + event = json.loads(msg) + + # Capture transcript deltas + if event['type'] == 'response.output_audio_transcript.delta': + delta = event.get('delta', '') + if delta: + print(delta, end='', flush=True) + transcript.append(delta) + + # Done when response completes + elif event['type'] == 'response.done': + break + + except asyncio.TimeoutError: + pass + + print("\n") + + if transcript: + print(f"āœ… Complete response: {''.join(transcript)}") + + await ws.close() + + +def main(): + """Run the voice agent""" + print("=" * 70) + print("LiveKit xAI Voice Agent via LiteLLM Proxy") + print("=" * 70) + print() + + try: + asyncio.run(run_voice_agent()) + except KeyboardInterrupt: + print("\n\nšŸ‘‹ Goodbye!") + except Exception as e: + print(f"\nāŒ Error: {e}") + print("\nMake sure LiteLLM proxy is running:") + print(f" litellm --config config.yaml --port 4000") + + +if __name__ == "__main__": + main() diff --git a/cookbook/livekit_agent_sdk/requirements.txt b/cookbook/livekit_agent_sdk/requirements.txt new file mode 100644 index 00000000000..9e3542fac27 --- /dev/null +++ b/cookbook/livekit_agent_sdk/requirements.txt @@ -0,0 +1,2 @@ +livekit-agents[xai]>=1.3.12 +websockets>=15.0.1 diff --git a/cookbook/nova_sonic_realtime.py b/cookbook/nova_sonic_realtime.py new file mode 100644 index 00000000000..0ea0badfb01 --- /dev/null +++ b/cookbook/nova_sonic_realtime.py @@ -0,0 +1,284 @@ +""" +Client script to test Nova Sonic realtime API through LiteLLM proxy. + +This script connects to LiteLLM proxy's realtime endpoint and enables +speech-to-speech conversation with Bedrock Nova Sonic. + +Prerequisites: +- LiteLLM proxy running with Bedrock configured +- pyaudio installed: pip install pyaudio +- websockets installed: pip install websockets + +Usage: + python nova_sonic_realtime.py +""" + +import asyncio +import base64 +import json +import pyaudio +import websockets +from typing import Optional + +# Audio configuration (matching Nova Sonic requirements) +INPUT_SAMPLE_RATE = 16000 # Nova Sonic expects 16kHz input +OUTPUT_SAMPLE_RATE = 24000 # Nova Sonic outputs 24kHz +CHANNELS = 1 +FORMAT = pyaudio.paInt16 +CHUNK_SIZE = 1024 + +# LiteLLM proxy configuration +LITELLM_PROXY_URL = "ws://localhost:4000/v1/realtime?model=bedrock-sonic" +LITELLM_API_KEY = "sk-12345" # Your LiteLLM API key + + +class RealtimeClient: + """Client for LiteLLM realtime API with audio support.""" + + def __init__(self, url: str, api_key: str): + self.url = url + self.api_key = api_key + self.ws: Optional[websockets.WebSocketClientProtocol] = None + self.is_active = False + self.audio_queue = asyncio.Queue() + self.pyaudio = pyaudio.PyAudio() + self.input_stream = None + self.output_stream = None + + async def connect(self): + """Connect to LiteLLM proxy realtime endpoint.""" + print(f"Connecting to {self.url}...") + + headers = {} + if self.api_key: + headers["Authorization"] = f"Bearer {self.api_key}" + + self.ws = await websockets.connect( + self.url, + additional_headers=headers, + max_size=10 * 1024 * 1024, # 10MB max message size + ) + self.is_active = True + print("āœ“ Connected to LiteLLM proxy") + + async def send_session_update(self): + """Send session configuration.""" + session_update = { + "type": "session.update", + "session": { + "instructions": "You are a friendly assistant. Keep your responses short and conversational.", + "voice": "matthew", + "temperature": 0.8, + "max_response_output_tokens": 1024, + "modalities": ["text", "audio"], + "input_audio_format": "pcm16", + "output_audio_format": "pcm16", + "turn_detection": { + "type": "server_vad", + "threshold": 0.5, + "prefix_padding_ms": 300, + "silence_duration_ms": 500, + }, + }, + } + await self.ws.send(json.dumps(session_update)) + print("āœ“ Session configuration sent") + + async def receive_messages(self): + """Receive and process messages from the server.""" + try: + async for message in self.ws: + if not self.is_active: + break + + try: + data = json.loads(message) + event_type = data.get("type") + + if event_type == "session.created": + print(f"āœ“ Session created: {data.get('session', {}).get('id')}") + + elif event_type == "response.created": + print("šŸ¤– Assistant is responding...") + + elif event_type == "response.text.delta": + # Print text transcription + delta = data.get("delta", "") + print(delta, end="", flush=True) + + elif event_type == "response.audio.delta": + # Queue audio for playback + audio_b64 = data.get("delta", "") + if audio_b64: + audio_bytes = base64.b64decode(audio_b64) + await self.audio_queue.put(audio_bytes) + + elif event_type == "response.text.done": + print() # New line after text + + elif event_type == "response.done": + print("āœ“ Response complete") + + elif event_type == "error": + print(f"āŒ Error: {data.get('error', {})}") + + else: + # Debug: print other event types + print(f"[{event_type}]", end=" ") + + except json.JSONDecodeError: + print(f"Failed to parse message: {message[:100]}") + + except websockets.exceptions.ConnectionClosed: + print("\nāœ— Connection closed") + except Exception as e: + print(f"\nāœ— Error receiving messages: {e}") + finally: + self.is_active = False + + async def send_audio_chunk(self, audio_bytes: bytes): + """Send audio chunk to server.""" + if not self.is_active or not self.ws: + return + + audio_b64 = base64.b64encode(audio_bytes).decode("utf-8") + message = { + "type": "input_audio_buffer.append", + "audio": audio_b64, + } + await self.ws.send(json.dumps(message)) + + async def commit_audio_buffer(self): + """Commit the audio buffer to trigger processing.""" + if not self.is_active or not self.ws: + return + + message = {"type": "input_audio_buffer.commit"} + await self.ws.send(json.dumps(message)) + + async def capture_audio(self): + """Capture audio from microphone and send to server.""" + print("\nšŸŽ¤ Starting audio capture...") + print("Speak into your microphone. Press Ctrl+C to stop.\n") + + self.input_stream = self.pyaudio.open( + format=FORMAT, + channels=CHANNELS, + rate=INPUT_SAMPLE_RATE, + input=True, + frames_per_buffer=CHUNK_SIZE, + ) + + try: + while self.is_active: + audio_data = self.input_stream.read(CHUNK_SIZE, exception_on_overflow=False) + await self.send_audio_chunk(audio_data) + await asyncio.sleep(0.01) # Small delay to prevent overwhelming + except Exception as e: + print(f"Error capturing audio: {e}") + finally: + if self.input_stream: + self.input_stream.stop_stream() + self.input_stream.close() + + async def play_audio(self): + """Play audio responses from the server.""" + print("šŸ”Š Starting audio playback...") + + self.output_stream = self.pyaudio.open( + format=FORMAT, + channels=CHANNELS, + rate=OUTPUT_SAMPLE_RATE, + output=True, + frames_per_buffer=CHUNK_SIZE, + ) + + try: + while self.is_active: + try: + audio_data = await asyncio.wait_for( + self.audio_queue.get(), timeout=0.1 + ) + if audio_data: + self.output_stream.write(audio_data) + except asyncio.TimeoutError: + continue + except Exception as e: + print(f"Error playing audio: {e}") + finally: + if self.output_stream: + self.output_stream.stop_stream() + self.output_stream.close() + + async def close(self): + """Close the connection and cleanup.""" + self.is_active = False + + if self.ws: + await self.ws.close() + + if self.input_stream: + self.input_stream.stop_stream() + self.input_stream.close() + + if self.output_stream: + self.output_stream.stop_stream() + self.output_stream.close() + + self.pyaudio.terminate() + print("\nāœ“ Connection closed") + + +async def main(): + """Main function to run the realtime client.""" + print("=" * 80) + print("Bedrock Nova Sonic Realtime Client") + print("=" * 80) + print() + + client = RealtimeClient(LITELLM_PROXY_URL, LITELLM_API_KEY) + + try: + # Connect to server + await client.connect() + + # Send session configuration + await client.send_session_update() + + # Wait a moment for session to be established + await asyncio.sleep(0.5) + + # Start tasks + receive_task = asyncio.create_task(client.receive_messages()) + capture_task = asyncio.create_task(client.capture_audio()) + playback_task = asyncio.create_task(client.play_audio()) + + # Wait for user to interrupt + await asyncio.gather( + receive_task, + capture_task, + playback_task, + return_exceptions=True, + ) + + except KeyboardInterrupt: + print("\n\n⚠ Interrupted by user") + except Exception as e: + print(f"\nāŒ Error: {e}") + import traceback + traceback.print_exc() + finally: + await client.close() + + +if __name__ == "__main__": + print("\nMake sure:") + print("1. LiteLLM proxy is running on port 4000") + print("2. Bedrock is configured in proxy_server_config.yaml") + print("3. AWS credentials are set") + print() + + try: + asyncio.run(main()) + except KeyboardInterrupt: + print("\n\nGoodbye!") diff --git a/deploy/charts/litellm-helm/templates/deployment.yaml b/deploy/charts/litellm-helm/templates/deployment.yaml index c3e0055e380..4ac5582d060 100644 --- a/deploy/charts/litellm-helm/templates/deployment.yaml +++ b/deploy/charts/litellm-helm/templates/deployment.yaml @@ -38,6 +38,10 @@ spec: serviceAccountName: {{ include "litellm.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- with .Values.extraInitContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: {{ include "litellm.name" . }} securityContext: diff --git a/deploy/charts/litellm-helm/templates/migrations-job.yaml b/deploy/charts/litellm-helm/templates/migrations-job.yaml index f8893a47afe..3459fa12d1c 100644 --- a/deploy/charts/litellm-helm/templates/migrations-job.yaml +++ b/deploy/charts/litellm-helm/templates/migrations-job.yaml @@ -35,6 +35,10 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ include "litellm.serviceAccountName" . }} + {{- with .Values.migrationJob.extraInitContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: prisma-migrations image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (printf "main-%s" .Chart.AppVersion) }}" diff --git a/deploy/charts/litellm-helm/values.yaml b/deploy/charts/litellm-helm/values.yaml index b75ce640370..cea25974bb0 100644 --- a/deploy/charts/litellm-helm/values.yaml +++ b/deploy/charts/litellm-helm/values.yaml @@ -281,6 +281,7 @@ migrationJob: # cpu: 100m # memory: 100Mi extraContainers: [] + extraInitContainers: [] # Hook configuration hooks: diff --git a/docker/Dockerfile.custom_ui b/docker/Dockerfile.custom_ui index c437929a27e..57926bcd170 100644 --- a/docker/Dockerfile.custom_ui +++ b/docker/Dockerfile.custom_ui @@ -5,7 +5,8 @@ FROM ghcr.io/berriai/litellm:litellm_fwd_server_root_path-dev WORKDIR /app # Install Node.js and npm (adjust version as needed) -RUN apt-get update && apt-get install -y nodejs npm +RUN apt-get update && apt-get install -y nodejs npm && \ + npm install -g npm@latest tar@latest # Copy the UI source into the container COPY ./ui/litellm-dashboard /app/ui/litellm-dashboard diff --git a/docker/Dockerfile.database b/docker/Dockerfile.database index 49655129506..24bf706434d 100644 --- a/docker/Dockerfile.database +++ b/docker/Dockerfile.database @@ -49,7 +49,8 @@ FROM $LITELLM_RUNTIME_IMAGE AS runtime USER root # Install runtime dependencies -RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile +RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \ + npm install -g npm@latest tar@latest WORKDIR /app # Copy the current directory contents into the container at /app diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index 67966f9c739..ae557d4647f 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -61,7 +61,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libatomic1 \ nodejs \ npm \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* \ + && npm install -g npm@latest tar@latest WORKDIR /app diff --git a/docker/Dockerfile.non_root b/docker/Dockerfile.non_root index 8c795f3b17f..9ff27e07494 100644 --- a/docker/Dockerfile.non_root +++ b/docker/Dockerfile.non_root @@ -104,7 +104,8 @@ RUN for i in 1 2 3; do \ done \ && for i in 1 2 3; do \ apk add --no-cache python3 py3-pip bash openssl tzdata nodejs npm supervisor && break || sleep 5; \ - done + done \ + && npm install -g npm@latest tar@latest # Copy artifacts from builder COPY --from=builder /app/requirements.txt /app/requirements.txt @@ -170,12 +171,14 @@ RUN sed -i 's/\r$//' docker/entrypoint.sh && \ [ -n "$LITELLM_PROXY_EXTRAS_PATH" ] && chmod -R g+w $LITELLM_PROXY_EXTRAS_PATH || true && \ chmod -R g+rX $PRISMA_PATH && \ chmod -R g+rX /app/.cache && \ - mkdir -p /tmp/.npm /nonexistent /.npm && \ - prisma generate + mkdir -p /tmp/.npm /nonexistent /.npm # Switch to non-root user for runtime USER nobody +# Generate Prisma client as nobody user to ensure correct file ownership +RUN prisma generate + # Prisma runtime knobs for offline containers ENV PRISMA_SKIP_POSTINSTALL_GENERATE=1 \ PRISMA_HIDE_UPDATE_MESSAGE=1 \ diff --git a/docs/my-website/blog/anthropic_opus_4_5_and_advanced_features/index.md b/docs/my-website/blog/anthropic_opus_4_5_and_advanced_features/index.md index 7015918e924..8a54426dfb0 100644 --- a/docs/my-website/blog/anthropic_opus_4_5_and_advanced_features/index.md +++ b/docs/my-website/blog/anthropic_opus_4_5_and_advanced_features/index.md @@ -15,6 +15,7 @@ authors: title: "CTO, LiteLLM" url: https://www.linkedin.com/in/reffajnaahsi/ image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +description: "Guide to Claude Opus 4.5 and advanced features in LiteLLM: Tool Search, Programmatic Tool Calling, and Effort Parameter." tags: [anthropic, claude, tool search, programmatic tool calling, effort, advanced features] hide_table_of_contents: false --- diff --git a/docs/my-website/blog/gemini_3/index.md b/docs/my-website/blog/gemini_3/index.md index 26dbc2d02b5..7263acc12c9 100644 --- a/docs/my-website/blog/gemini_3/index.md +++ b/docs/my-website/blog/gemini_3/index.md @@ -15,6 +15,7 @@ authors: title: "CTO, LiteLLM" url: https://www.linkedin.com/in/reffajnaahsi/ image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +description: "Common questions and best practices for using gemini-3-pro-preview with LiteLLM Proxy and SDK." tags: [gemini, day 0 support, llms] hide_table_of_contents: false --- diff --git a/docs/my-website/blog/gemini_3_flash/index.md b/docs/my-website/blog/gemini_3_flash/index.md index 6cb8ddad992..830c21e5f66 100644 --- a/docs/my-website/blog/gemini_3_flash/index.md +++ b/docs/my-website/blog/gemini_3_flash/index.md @@ -15,6 +15,7 @@ authors: title: "CTO, LiteLLM" url: https://www.linkedin.com/in/reffajnaahsi/ image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +description: "Guide to using Gemini 3 Flash on LiteLLM Proxy and SDK with day 0 support." tags: [gemini, day 0 support, llms] hide_table_of_contents: false --- diff --git a/docs/my-website/blog/sub_millisecond_proxy_overhead/index.md b/docs/my-website/blog/sub_millisecond_proxy_overhead/index.md new file mode 100644 index 00000000000..1857383363c --- /dev/null +++ b/docs/my-website/blog/sub_millisecond_proxy_overhead/index.md @@ -0,0 +1,92 @@ +--- +slug: sub-millisecond-proxy-overhead +title: "Achieving Sub-Millisecond Proxy Overhead" +date: 2026-02-02T10:00:00 +authors: + - name: Alexsander Hamir + title: "Performance Engineer, LiteLLM" + url: https://www.linkedin.com/in/alexsander-baptista/ + image_url: https://github.com/AlexsanderHamir.png + - name: Krrish Dholakia + title: "CEO, LiteLLM" + url: https://www.linkedin.com/in/krish-d/ + image_url: https://pbs.twimg.com/profile_images/1298587542745358340/DZv3Oj-h_400x400.jpg + - name: Ishaan Jaff + title: "CTO, LiteLLM" + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +description: "Our Q1 performance target and architectural direction for achieving sub-millisecond proxy overhead on modest hardware." +tags: [performance, architecture] +hide_table_of_contents: false +--- + +![Sidecar architecture: Python control plane vs. sidecar hot path](https://raw.githubusercontent.com/AlexsanderHamir/assets/main/Screenshot%202026-02-02%20172554.png) + +# Achieving Sub-Millisecond Proxy Overhead + +## Introduction + +Our Q1 performance target is to aggressively move toward sub-millisecond proxy overhead on a single instance with 4 CPUs and 8 GB of RAM, and to continue pushing that boundary over time. Our broader goal is to make LiteLLM inexpensive to deploy, lightweight, and fast. This post outlines the architectural direction behind that effort. + +Proxy overhead refers to the latency introduced by LiteLLM itself, independent of the upstream provider. + +To measure it, we run the same workload directly against the provider and through LiteLLM at identical QPS (for example, 1,000 QPS) and compare the latency delta. To reduce noise, the load generator, LiteLLM, and a mock LLM endpoint all run on the same machine, ensuring the difference reflects proxy overhead rather than network latency. + +--- + +## Where We're Coming From + +Under the same benchmark originally conducted by [TensorZero](https://www.tensorzero.com/docs/gateway/benchmarks), LiteLLM previously failed at around 1,000 QPS. + +That is no longer the case. Today, LiteLLM can be stress-tested at 1,000 QPS with no failures and can scale up to 5,000 QPS without failures on a 4-CPU, 8-GB RAM single instance setup. + +This establishes a more up to date baseline and provides useful context as we continue working on proxy overhead and overall performance. + +--- + +## Design Choice + +Achieving sub-millisecond proxy overhead with a Python-based system requires being deliberate about where work happens. + +Python is a strong fit for flexibility and extensibility: provider abstraction, configuration-driven routing, and a rich callback ecosystem. These are areas where development velocity and correctness matter more than raw throughput. + +At higher request rates, however, certain classes of work become expensive when executed inside the Python process on every request. Rather than rewriting LiteLLM or introducing complex deployment requirements, we adopt an optional **sidecar architecture**. + +This architectural change is how we intend to make LiteLLM **permanently fast**. While it supports our near-term performance targets, it is a long-term investment. + +Python continues to own: + +- Request validation and normalization +- Model and provider selection +- Callbacks and integrations + +The sidecar owns **performance-critical execution**, such as: + +- Efficient request forwarding +- Connection reuse and pooling +- Enforcing timeouts and limits +- Aggregating high-frequency metrics + +This separation allows each component to focus on what it does best: Python acts as the control plane, while the sidecar handles the hot path. + +--- + +### Why the Sidecar Is Optional + +The sidecar is intentionally **optional**. + +This allows us to ship it incrementally, validate it under real-world workloads, and avoid making it a hard dependency before it is fully battle-tested across all LiteLLM features. + +Just as importantly, this ensures that self-hosting LiteLLM remains simple. The sidecar is bundled and started automatically, requires no additional infrastructure, and can be disabled entirely. From a user's perspective, LiteLLM continues to behave like a single service. + +As of today, the sidecar is an optimization, not a requirement. + +--- + +## Conclusion + +Sub-millisecond proxy overhead is not achieved through a single optimization, but through architectural changes. + +By keeping Python focused on orchestration and extensibility, and offloading performance-critical execution to a sidecar, we establish a foundation for making LiteLLM **permanently fast over time**—even on modest hardware such as a 1-CPU, 2-GB RAM instance, while keeping deployment and self-hosting simple. + +This work extends beyond Q1, and we will continue sharing benchmarks and updates as the architecture evolves. diff --git a/docs/my-website/docs/a2a.md b/docs/my-website/docs/a2a.md index d7145e4b83c..b1166a7809c 100644 --- a/docs/my-website/docs/a2a.md +++ b/docs/my-website/docs/a2a.md @@ -68,116 +68,9 @@ Follow [this guide, to add your pydantic ai agent to LiteLLM Agent Gateway](./pr ## Invoking your Agents -Use the [A2A Python SDK](https://pypi.org/project/a2a/) to invoke agents through LiteLLM. - -This example shows how to: -1. **List available agents** - Query `/v1/agents` to see which agents your key can access -2. **Select an agent** - Pick an agent from the list -3. **Invoke via A2A** - Use the A2A protocol to send messages to the agent - -```python showLineNumbers title="invoke_a2a_agent.py" -from uuid import uuid4 -import httpx -import asyncio -from a2a.client import A2ACardResolver, A2AClient -from a2a.types import MessageSendParams, SendMessageRequest - -# === CONFIGURE THESE === -LITELLM_BASE_URL = "http://localhost:4000" # Your LiteLLM proxy URL -LITELLM_VIRTUAL_KEY = "sk-1234" # Your LiteLLM Virtual Key -# ======================= - -async def main(): - headers = {"Authorization": f"Bearer {LITELLM_VIRTUAL_KEY}"} - - async with httpx.AsyncClient(headers=headers) as client: - # Step 1: List available agents - response = await client.get(f"{LITELLM_BASE_URL}/v1/agents") - agents = response.json() - - print("Available agents:") - for agent in agents: - print(f" - {agent['agent_name']} (ID: {agent['agent_id']})") - - if not agents: - print("No agents available for this key") - return - - # Step 2: Select an agent and invoke it - selected_agent = agents[0] - agent_id = selected_agent["agent_id"] - agent_name = selected_agent["agent_name"] - print(f"\nInvoking: {agent_name}") - - # Step 3: Use A2A protocol to invoke the agent - base_url = f"{LITELLM_BASE_URL}/a2a/{agent_id}" - resolver = A2ACardResolver(httpx_client=client, base_url=base_url) - agent_card = await resolver.get_agent_card() - a2a_client = A2AClient(httpx_client=client, agent_card=agent_card) - - request = SendMessageRequest( - id=str(uuid4()), - params=MessageSendParams( - message={ - "role": "user", - "parts": [{"kind": "text", "text": "Hello, what can you do?"}], - "messageId": uuid4().hex, - } - ), - ) - response = await a2a_client.send_message(request) - print(f"Response: {response.model_dump(mode='json', exclude_none=True, indent=4)}") - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### Streaming Responses - -For streaming responses, use `send_message_streaming`: - -```python showLineNumbers title="invoke_a2a_agent_streaming.py" -from uuid import uuid4 -import httpx -import asyncio -from a2a.client import A2ACardResolver, A2AClient -from a2a.types import MessageSendParams, SendStreamingMessageRequest - -# === CONFIGURE THESE === -LITELLM_BASE_URL = "http://localhost:4000" # Your LiteLLM proxy URL -LITELLM_VIRTUAL_KEY = "sk-1234" # Your LiteLLM Virtual Key -LITELLM_AGENT_NAME = "ij-local" # Agent name registered in LiteLLM -# ======================= - -async def main(): - base_url = f"{LITELLM_BASE_URL}/a2a/{LITELLM_AGENT_NAME}" - headers = {"Authorization": f"Bearer {LITELLM_VIRTUAL_KEY}"} - - async with httpx.AsyncClient(headers=headers) as httpx_client: - # Resolve agent card and create client - resolver = A2ACardResolver(httpx_client=httpx_client, base_url=base_url) - agent_card = await resolver.get_agent_card() - client = A2AClient(httpx_client=httpx_client, agent_card=agent_card) - - # Send a streaming message - request = SendStreamingMessageRequest( - id=str(uuid4()), - params=MessageSendParams( - message={ - "role": "user", - "parts": [{"kind": "text", "text": "Hello, what can you do?"}], - "messageId": uuid4().hex, - } - ), - ) - - # Stream the response - async for chunk in client.send_message_streaming(request): - print(chunk.model_dump(mode="json", exclude_none=True)) - -if __name__ == "__main__": - asyncio.run(main()) -``` +See the [Invoking A2A Agents](./a2a_invoking_agents) guide to learn how to call your agents using: +- **A2A SDK** - Native A2A protocol with full support for tasks and artifacts +- **OpenAI SDK** - Familiar `/chat/completions` interface with `a2a/` model prefix ## Tracking Agent Logs @@ -193,6 +86,120 @@ The logs show: style={{width: '100%', display: 'block', margin: '2rem auto'}} /> + +## Forwarding LiteLLM Context Headers + +When LiteLLM invokes your A2A agent, it sends special headers that enable: +- **Trace Grouping**: All LLM calls from the same agent execution appear under one trace +- **Agent Spend Tracking**: Costs are attributed to the specific agent + +| Header | Purpose | +|--------|---------| +| `X-LiteLLM-Trace-Id` | Links all LLM calls to the same execution flow | +| `X-LiteLLM-Agent-Id` | Attributes spend to the correct agent | + + +To enable these features, your A2A server must **forward these headers** to any LLM calls it makes back to LiteLLM. + +### Implementation Steps + +**Step 1: Extract headers from incoming A2A request** +```python def get_litellm_headers(request) -> dict: + """Extract X-LiteLLM-* headers from incoming A2A request.""" + all_headers = request.call_context.state.get('headers', {}) + return { + k: v for k, v in all_headers.items() + if k.lower().startswith('x-litellm-') + } +``` + +**Step 2: Forward headers to your LLM calls** +Pass the extracted headers when making calls back to LiteLLM: + + + +```python from openai import OpenAI + +headers = get_litellm_headers(request) + +client = OpenAI( + api_key="sk-your-litellm-key", + base_url="http://localhost:4000", + default_headers=headers, # Forward headers +) + +response = client.chat.completions.create( + model="gpt-4o", + messages=[{"role": "user", "content": "Hello"}] +) +``` + + + + +```python +from langchain_openai import ChatOpenAI + +headers = get_litellm_headers(request) + +llm = ChatOpenAI( + model="gpt-4o", + openai_api_key="sk-your-litellm-key", + base_url="http://localhost:4000", + default_headers=headers, # Forward headers +) +``` + + + +```python +import litellm + +headers = get_litellm_headers(request) + +response = litellm.completion( + model="gpt-4o", + messages=[{"role": "user", "content": "Hello"}], + api_base="http://localhost:4000", + extra_headers=headers, # Forward headers +) +``` + + + +```python +import httpx + +headers = get_litellm_headers(request) +headers["Authorization"] = "Bearer sk-your-litellm-key" + +response = httpx.post( + "http://localhost:4000/v1/chat/completions", + headers=headers, + json={"model": "gpt-4o", "messages": [{"role": "user", "content": "Hello"}]} +) +``` + + + +### Result + +With header forwarding enabled, you'll see: + +**Trace Grouping in Langfuse:** + + + +**Agent Spend Attribution:** + + + ## API Reference ### Endpoint diff --git a/docs/my-website/docs/a2a_invoking_agents.md b/docs/my-website/docs/a2a_invoking_agents.md new file mode 100644 index 00000000000..3bb248e4561 --- /dev/null +++ b/docs/my-website/docs/a2a_invoking_agents.md @@ -0,0 +1,280 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Invoking A2A Agents + +Learn how to invoke A2A agents through LiteLLM using different methods. + +:::tip Deploy Your Own A2A Agent + +Want to test with your own agent? Deploy this template A2A agent powered by Google Gemini: + +[**shin-bot-litellm/a2a-gemini-agent**](https://github.com/shin-bot-litellm/a2a-gemini-agent) - Simple deployable A2A agent with streaming support + +::: + +## A2A SDK + +Use the [A2A Python SDK](https://pypi.org/project/a2a-sdk) to invoke agents through LiteLLM using the A2A protocol. + +### Non-Streaming + +This example shows how to: +1. **List available agents** - Query `/v1/agents` to see which agents your key can access +2. **Select an agent** - Pick an agent from the list +3. **Invoke via A2A** - Use the A2A protocol to send messages to the agent + +```python showLineNumbers title="invoke_a2a_agent.py" +from uuid import uuid4 +import httpx +import asyncio +from a2a.client import A2ACardResolver, A2AClient +from a2a.types import MessageSendParams, SendMessageRequest + +# === CONFIGURE THESE === +LITELLM_BASE_URL = "http://localhost:4000" # Your LiteLLM proxy URL +LITELLM_VIRTUAL_KEY = "sk-1234" # Your LiteLLM Virtual Key +# ======================= + +async def main(): + headers = {"Authorization": f"Bearer {LITELLM_VIRTUAL_KEY}"} + + async with httpx.AsyncClient(headers=headers) as client: + # Step 1: List available agents + response = await client.get(f"{LITELLM_BASE_URL}/v1/agents") + agents = response.json() + + print("Available agents:") + for agent in agents: + print(f" - {agent['agent_name']} (ID: {agent['agent_id']})") + + if not agents: + print("No agents available for this key") + return + + # Step 2: Select an agent and invoke it + selected_agent = agents[0] + agent_id = selected_agent["agent_id"] + agent_name = selected_agent["agent_name"] + print(f"\nInvoking: {agent_name}") + + # Step 3: Use A2A protocol to invoke the agent + base_url = f"{LITELLM_BASE_URL}/a2a/{agent_id}" + resolver = A2ACardResolver(httpx_client=client, base_url=base_url) + agent_card = await resolver.get_agent_card() + a2a_client = A2AClient(httpx_client=client, agent_card=agent_card) + + request = SendMessageRequest( + id=str(uuid4()), + params=MessageSendParams( + message={ + "role": "user", + "parts": [{"kind": "text", "text": "Hello, what can you do?"}], + "messageId": uuid4().hex, + } + ), + ) + response = await a2a_client.send_message(request) + print(f"Response: {response.model_dump(mode='json', exclude_none=True, indent=4)}") + +if __name__ == "__main__": + asyncio.run(main()) +``` + +### Streaming + +For streaming responses, use `send_message_streaming`: + +```python showLineNumbers title="invoke_a2a_agent_streaming.py" +from uuid import uuid4 +import httpx +import asyncio +from a2a.client import A2ACardResolver, A2AClient +from a2a.types import MessageSendParams, SendStreamingMessageRequest + +# === CONFIGURE THESE === +LITELLM_BASE_URL = "http://localhost:4000" # Your LiteLLM proxy URL +LITELLM_VIRTUAL_KEY = "sk-1234" # Your LiteLLM Virtual Key +LITELLM_AGENT_NAME = "ij-local" # Agent name registered in LiteLLM +# ======================= + +async def main(): + base_url = f"{LITELLM_BASE_URL}/a2a/{LITELLM_AGENT_NAME}" + headers = {"Authorization": f"Bearer {LITELLM_VIRTUAL_KEY}"} + + async with httpx.AsyncClient(headers=headers) as httpx_client: + # Resolve agent card and create client + resolver = A2ACardResolver(httpx_client=httpx_client, base_url=base_url) + agent_card = await resolver.get_agent_card() + client = A2AClient(httpx_client=httpx_client, agent_card=agent_card) + + # Send a streaming message + request = SendStreamingMessageRequest( + id=str(uuid4()), + params=MessageSendParams( + message={ + "role": "user", + "parts": [{"kind": "text", "text": "Tell me a long story"}], + "messageId": uuid4().hex, + } + ), + ) + + # Stream the response + async for chunk in client.send_message_streaming(request): + print(chunk.model_dump(mode="json", exclude_none=True)) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## /chat/completions API (OpenAI SDK) + +You can also invoke A2A agents using the familiar OpenAI SDK by using the `a2a/` model prefix. + +### Non-Streaming + + + + +```python showLineNumbers title="openai_non_streaming.py" +import openai + +client = openai.OpenAI( + api_key="sk-1234", # Your LiteLLM Virtual Key + base_url="http://localhost:4000" # Your LiteLLM proxy URL +) + +response = client.chat.completions.create( + model="a2a/my-agent", # Use a2a/ prefix with your agent name + messages=[ + {"role": "user", "content": "Hello, what can you do?"} + ] +) + +print(response.choices[0].message.content) +``` + + + + +```typescript showLineNumbers title="openai_non_streaming.ts" +import OpenAI from 'openai'; + +const client = new OpenAI({ + apiKey: 'sk-1234', // Your LiteLLM Virtual Key + baseURL: 'http://localhost:4000' // Your LiteLLM proxy URL +}); + +const response = await client.chat.completions.create({ + model: 'a2a/my-agent', // Use a2a/ prefix with your agent name + messages: [ + { role: 'user', content: 'Hello, what can you do?' } + ] +}); + +console.log(response.choices[0].message.content); +``` + + + + +```bash showLineNumbers title="curl_non_streaming.sh" +curl -X POST http://localhost:4000/v1/chat/completions \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "a2a/my-agent", + "messages": [ + {"role": "user", "content": "Hello, what can you do?"} + ] + }' +``` + + + + +### Streaming + + + + +```python showLineNumbers title="openai_streaming.py" +import openai + +client = openai.OpenAI( + api_key="sk-1234", # Your LiteLLM Virtual Key + base_url="http://localhost:4000" # Your LiteLLM proxy URL +) + +stream = client.chat.completions.create( + model="a2a/my-agent", # Use a2a/ prefix with your agent name + messages=[ + {"role": "user", "content": "Tell me a long story"} + ], + stream=True +) + +for chunk in stream: + if chunk.choices[0].delta.content: + print(chunk.choices[0].delta.content, end="", flush=True) +``` + + + + +```typescript showLineNumbers title="openai_streaming.ts" +import OpenAI from 'openai'; + +const client = new OpenAI({ + apiKey: 'sk-1234', // Your LiteLLM Virtual Key + baseURL: 'http://localhost:4000' // Your LiteLLM proxy URL +}); + +const stream = await client.chat.completions.create({ + model: 'a2a/my-agent', // Use a2a/ prefix with your agent name + messages: [ + { role: 'user', content: 'Tell me a long story' } + ], + stream: true +}); + +for await (const chunk of stream) { + const content = chunk.choices[0]?.delta?.content; + if (content) { + process.stdout.write(content); + } +} +``` + + + + +```bash showLineNumbers title="curl_streaming.sh" +curl -X POST http://localhost:4000/v1/chat/completions \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "a2a/my-agent", + "messages": [ + {"role": "user", "content": "Tell me a long story"} + ], + "stream": true + }' +``` + + + + +## Key Differences + +| Method | Use Case | Advantages | +|--------|----------|------------| +| **A2A SDK** | Native A2A protocol integration | • Full A2A protocol support
• Access to task states and artifacts
• Context management | +| **OpenAI SDK** | Familiar OpenAI-style interface | • Drop-in replacement for OpenAI calls
• Easier migration from LLM to agent workflows
• Works with existing OpenAI tooling | + +:::tip Model Prefix + +When using the OpenAI SDK, always prefix your agent name with `a2a/` (e.g., `a2a/my-agent`) to route requests to the A2A agent instead of an LLM provider. + +::: diff --git a/docs/my-website/docs/adding_provider/simple_guardrail_tutorial.md b/docs/my-website/docs/adding_provider/simple_guardrail_tutorial.md index 9c654cd1560..884a7397bde 100644 --- a/docs/my-website/docs/adding_provider/simple_guardrail_tutorial.md +++ b/docs/my-website/docs/adding_provider/simple_guardrail_tutorial.md @@ -101,12 +101,11 @@ model_list: - model_name: gpt-4 litellm_params: model: gpt-4 - api_key: os.environ/OPENAI_API_KEY + api_key: os.environ/OPENAI_API_KEY -litellm_settings: - guardrails: +guardrails: - guardrail_name: my_guardrail - litellm_params: + litellm_params: guardrail: my_guardrail mode: during_call api_key: os.environ/MY_GUARDRAIL_API_KEY diff --git a/docs/my-website/docs/benchmarks.md b/docs/my-website/docs/benchmarks.md index 640212808bd..a1489081b4c 100644 --- a/docs/my-website/docs/benchmarks.md +++ b/docs/my-website/docs/benchmarks.md @@ -48,6 +48,28 @@ In these tests the baseline latency characteristics are measured against a fake- - High-percentile latencies drop significantly: P95 630 ms → 150 ms, P99 1,200 ms → 240 ms. - Setting workers equal to CPU count gives optimal performance. +## `/realtime` API Benchmarks + +End-to-end latency benchmarks for the `/realtime` endpoint tested against a fake realtime endpoint. + +### Performance Metrics + +| Metric | Value | +| --------------- | ---------- | +| Median latency | 59 ms | +| p95 latency | 67 ms | +| p99 latency | 99 ms | +| Average latency | 63 ms | +| RPS | 1,207 | + +### Test Setup + +| Category | Specification | +|----------|---------------| +| **Load Testing** | Locust: 1,000 concurrent users, 500 ramp-up | +| **System** | 4 vCPUs, 8 GB RAM, 4 workers, 4 instances | +| **Database** | PostgreSQL (Redis unused) | + ## Machine Spec used for testing Each machine deploying LiteLLM had the following specs: diff --git a/docs/my-website/docs/enterprise.md b/docs/my-website/docs/enterprise.md index 2eed0f53e59..0a1b47f0621 100644 --- a/docs/my-website/docs/enterprise.md +++ b/docs/my-website/docs/enterprise.md @@ -74,6 +74,18 @@ You can find [supported data regions litellm here](../docs/data_security#support ## Frequently Asked Questions +### How to set up and verify your Enterprise License + +1. Add your license key to the environment: + +```env +LITELLM_LICENSE="eyJ..." +``` + +2. Restart LiteLLM Proxy. + +3. Open `http://:/` — the Swagger page should show **"Enterprise Edition"** in the description. If it doesn't, check that the key is correct, unexpired, and that the proxy was fully restarted. + ### SLA's + Professional Support Professional Support can assist with LLM/Provider integrations, deployment, upgrade management, and LLM Provider troubleshooting. We can’t solve your own infrastructure-related issues but we will guide you to fix them. diff --git a/docs/my-website/docs/mcp_semantic_filter.md b/docs/my-website/docs/mcp_semantic_filter.md new file mode 100644 index 00000000000..c58be80a680 --- /dev/null +++ b/docs/my-website/docs/mcp_semantic_filter.md @@ -0,0 +1,158 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# MCP Semantic Tool Filter + +Automatically filter MCP tools by semantic relevance. When you have many MCP tools registered, LiteLLM semantically matches the user's query against tool descriptions and sends only the most relevant tools to the LLM. + +## How It Works + +Tool search shifts tool selection from a prompt-engineering problem to a retrieval problem. Instead of injecting a large static list of tools into every prompt, the semantic filter: + +1. Builds a semantic index of all available MCP tools on startup +2. On each request, semantically matches the user's query against tool descriptions +3. Returns only the top-K most relevant tools to the LLM + +This approach improves context efficiency, increases reliability by reducing tool confusion, and enables scalability to ecosystems with hundreds or thousands of MCP tools. + +```mermaid +sequenceDiagram + participant Client + participant LiteLLM as LiteLLM Proxy + participant SemanticFilter as Semantic Filter + participant MCP as MCP Registry + participant LLM as LLM Provider + + Note over LiteLLM,MCP: Startup: Build Semantic Index + LiteLLM->>MCP: Fetch all registered MCP tools + MCP->>LiteLLM: Return all tools (e.g., 50 tools) + LiteLLM->>SemanticFilter: Build semantic router with embeddings + SemanticFilter->>LLM: Generate embeddings for tool descriptions + LLM->>SemanticFilter: Return embeddings + Note over SemanticFilter: Index ready for fast lookup + + Note over Client,LLM: Request: Semantic Tool Filtering + Client->>LiteLLM: POST /v1/responses with MCP tools + LiteLLM->>SemanticFilter: Expand MCP references (50 tools available) + SemanticFilter->>SemanticFilter: Extract user query from request + SemanticFilter->>LLM: Generate query embedding + LLM->>SemanticFilter: Return query embedding + SemanticFilter->>SemanticFilter: Match query against tool embeddings + SemanticFilter->>LiteLLM: Return top-K tools (e.g., 3 most relevant) + LiteLLM->>LLM: Forward request with filtered tools (3 tools) + LLM->>LiteLLM: Return response + LiteLLM->>Client: Response with headers
x-litellm-semantic-filter: 50->3
x-litellm-semantic-filter-tools: tool1,tool2,tool3 +``` + +## Configuration + +Enable semantic filtering in your LiteLLM config: + +```yaml title="config.yaml" showLineNumbers +litellm_settings: + mcp_semantic_tool_filter: + enabled: true + embedding_model: "text-embedding-3-small" # Model for semantic matching + top_k: 5 # Max tools to return + similarity_threshold: 0.3 # Min similarity score +``` + +**Configuration Options:** +- `enabled` - Enable/disable semantic filtering (default: `false`) +- `embedding_model` - Model for generating embeddings (default: `"text-embedding-3-small"`) +- `top_k` - Maximum number of tools to return (default: `10`) +- `similarity_threshold` - Minimum similarity score for matches (default: `0.3`) + +## Usage + +Use MCP tools normally with the Responses API or Chat Completions. The semantic filter runs automatically: + + + + +```bash title="Responses API with Semantic Filtering" showLineNumbers +curl --location 'http://localhost:4000/v1/responses' \ +--header 'Content-Type: application/json' \ +--header "Authorization: Bearer sk-1234" \ +--data '{ + "model": "gpt-4o", + "input": [ + { + "role": "user", + "content": "give me TLDR of what BerriAI/litellm repo is about", + "type": "message" + } + ], + "tools": [ + { + "type": "mcp", + "server_url": "litellm_proxy", + "require_approval": "never" + } + ], + "tool_choice": "required" +}' +``` + + + + +```bash title="Chat Completions with Semantic Filtering" showLineNumbers +curl --location 'http://localhost:4000/v1/chat/completions' \ +--header 'Content-Type: application/json' \ +--header "Authorization: Bearer sk-1234" \ +--data '{ + "model": "gpt-4o", + "messages": [ + {"role": "user", "content": "Search Wikipedia for LiteLLM"} + ], + "tools": [ + { + "type": "mcp", + "server_url": "litellm_proxy" + } + ] +}' +``` + + + + +## Response Headers + +The semantic filter adds diagnostic headers to every response: + +``` +x-litellm-semantic-filter: 10->3 +x-litellm-semantic-filter-tools: wikipedia-fetch,github-search,slack-post +``` + +- **`x-litellm-semantic-filter`** - Shows before→after tool count (e.g., `10->3` means 10 tools were filtered down to 3) +- **`x-litellm-semantic-filter-tools`** - CSV list of the filtered tool names (max 150 chars, clipped with `...` if longer) + +These headers help you understand which tools were selected for each request and verify the filter is working correctly. + +## Example + +If you have 50 MCP tools registered and make a request asking about Wikipedia, the semantic filter will: + +1. Semantically match your query `"Search Wikipedia for LiteLLM"` against all 50 tool descriptions +2. Select the top 5 most relevant tools (e.g., `wikipedia-fetch`, `wikipedia-search`, etc.) +3. Pass only those 5 tools to the LLM +4. Add headers showing `x-litellm-semantic-filter: 50->5` + +This dramatically reduces prompt size while ensuring the LLM has access to the right tools for the task. + +## Performance + +The semantic filter is optimized for production: +- Router builds once on startup (no per-request overhead) +- Semantic matching typically takes under 50ms +- Fails gracefully - returns all tools if filtering fails +- No impact on latency for requests without MCP tools + +## Related + +- [MCP Overview](./mcp.md) - Learn about MCP in LiteLLM +- [MCP Permission Management](./mcp_control.md) - Control tool access by key/team +- [Using MCP](./mcp_usage.md) - Complete MCP usage guide diff --git a/docs/my-website/docs/observability/datadog.md b/docs/my-website/docs/observability/datadog.md index 7cf91ced34c..6f785be1013 100644 --- a/docs/my-website/docs/observability/datadog.md +++ b/docs/my-website/docs/observability/datadog.md @@ -7,6 +7,7 @@ import TabItem from '@theme/TabItem'; LiteLLM Supports logging to the following Datdog Integrations: - `datadog` [Datadog Logs](https://docs.datadoghq.com/logs/) - `datadog_llm_observability` [Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) +- `datadog_cost_management` [Datadog Cloud Cost Management](#datadog-cloud-cost-management) - `ddtrace-run` [Datadog Tracing](#datadog-tracing) ## Datadog Logs @@ -73,7 +74,7 @@ Send logs through a local DataDog agent (useful for containerized environments): ```shell LITELLM_DD_AGENT_HOST="localhost" # hostname or IP of DataDog agent LITELLM_DD_AGENT_PORT="10518" # [OPTIONAL] port of DataDog agent (default: 10518) -DD_API_KEY="5f2d0f310***********" # [OPTIONAL] your datadog API Key (agent handles auth) +DD_API_KEY="5f2d0f310***********" # [OPTIONAL] your datadog API Key (Agent handles auth for Logs. REQUIRED for LLM Observability) DD_SOURCE="litellm_dev" # [OPTIONAL] your datadog source ``` @@ -84,6 +85,9 @@ When `LITELLM_DD_AGENT_HOST` is set, logs are sent to the agent instead of direc **Note:** We use `LITELLM_DD_AGENT_HOST` instead of `DD_AGENT_HOST` to avoid conflicts with `ddtrace` which automatically sets `DD_AGENT_HOST` for APM tracing. +> [!IMPORTANT] +> **Datadog LLM Observability**: `DD_API_KEY` is **REQUIRED** even when using the Datadog Agent (`LITELLM_DD_AGENT_HOST`). The agent acts as a proxy but the API key header is mandatory for the LLM Observability endpoint. + **Step 3**: Start the proxy, make a test request Start proxy @@ -161,6 +165,50 @@ On the Datadog LLM Observability page, you should see that both input messages a + + + +## Datadog Cloud Cost Management + +| Feature | Details | +|---------|---------| +| **What is logged** | Aggregated LLM Costs (FOCUS format) | +| **Events** | Periodic Uploads of Aggregated Cost Data | +| **Product Link** | [Datadog Cloud Cost Management](https://docs.datadoghq.com/cost_management/) | + +We will use the `--config` to set `litellm.callbacks = ["datadog_cost_management"]`. This will periodically upload aggregated LLM cost data to Datadog. + +**Step 1**: Create a `config.yaml` file and set `litellm_settings`: `success_callback` + +```yaml +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: gpt-3.5-turbo +litellm_settings: + callbacks: ["datadog_cost_management"] +``` + +**Step 2**: Set Required env variables + +```shell +DD_API_KEY="your-api-key" +DD_APP_KEY="your-app-key" # REQUIRED for Cost Management +DD_SITE="us5.datadoghq.com" +``` + +**Step 3**: Start the proxy + +```shell +litellm --config config.yaml +``` + +**How it works** +* LiteLLM aggregates costs in-memory by Provider, Model, Date, and Tags. +* Requires `DD_APP_KEY` for the Custom Costs API. +* Costs are uploaded periodically (flushed). + + ### Datadog Tracing Use `ddtrace-run` to enable [Datadog Tracing](https://ddtrace.readthedocs.io/en/stable/installation_quickstart.html) on litellm proxy @@ -203,5 +251,5 @@ LiteLLM supports customizing the following Datadog environment variables | `POD_NAME` | Pod name tag (useful for Kubernetes deployments) | "unknown" | āŒ No | \* **Required when using Direct API** (default): `DD_API_KEY` and `DD_SITE` are required -\* **Optional when using DataDog Agent**: Set `LITELLM_DD_AGENT_HOST` to use agent mode; `DD_API_KEY` and `DD_SITE` are not required +\* **Optional when using DataDog Agent**: Set `LITELLM_DD_AGENT_HOST` to use agent mode; `DD_API_KEY` and `DD_SITE` are not required for **Datadog Logs**. (**Note: `DD_API_KEY` IS REQUIRED for Datadog LLM Observability**) diff --git a/docs/my-website/docs/observability/langfuse_integration.md b/docs/my-website/docs/observability/langfuse_integration.md index a81336c5bc6..d3c5a44d481 100644 --- a/docs/my-website/docs/observability/langfuse_integration.md +++ b/docs/my-website/docs/observability/langfuse_integration.md @@ -215,6 +215,66 @@ The following parameters can be updated on a continuation of a trace by passing Any other key value pairs passed into the metadata not listed in the above spec for a `litellm` completion will be added as a metadata key value pair for the generation. +#### Multiple Langfuse Projects (Per-Request Credentials) + +You can send traces to different Langfuse projects per request by passing credentials directly to `completion()` or `acompletion()`. This works alongside (or instead of) the global env vars and is useful when different teams or business processes use different Langfuse projects. + +Pass **`langfuse_public_key`**, **`langfuse_secret_key`** (or **`langfuse_secret`**), and optionally **`langfuse_host`** as keyword arguments: + +```python +import litellm +from litellm import completion + +# Optional: set a default via env for requests that don't pass credentials +# os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-default..." +# os.environ["LANGFUSE_SECRET_KEY"] = "sk-default..." + +litellm.success_callback = ["langfuse"] +litellm.failure_callback = ["langfuse"] + +# Request 1 → Langfuse Project A +response_a = completion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hello from team A"}], + langfuse_public_key="pk-lf-project-a...", + langfuse_secret_key="sk-lf-project-a...", + langfuse_host="https://us.cloud.langfuse.com", # optional +) + +# Request 2 → Langfuse Project B (different project) +response_b = completion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hello from team B"}], + langfuse_public_key="pk-lf-project-b...", + langfuse_secret_key="sk-lf-project-b...", + langfuse_host="https://eu.cloud.langfuse.com", # optional, can differ per project +) +``` + +Async usage with per-request credentials: + +```python +import litellm +from litellm import acompletion + +litellm.success_callback = ["langfuse"] +litellm.failure_callback = ["langfuse"] + +response = await acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hi"}], + langfuse_public_key="pk-lf-...", + langfuse_secret_key="sk-lf-...", + langfuse_host="https://us.cloud.langfuse.com", # optional +) +``` + +- **`langfuse_public_key`** – Langfuse project public key (required for per-request override). +- **`langfuse_secret_key`** or **`langfuse_secret`** – Langfuse secret key (either name is accepted). +- **`langfuse_host`** – Langfuse host URL (e.g. `https://us.cloud.langfuse.com`); optional, defaults to env or Langfuse cloud. + +When these are passed, that request uses this project (and host) for the Langfuse callback; when omitted, the callback uses the global Langfuse client (from env vars if set). LiteLLM caches a Langfuse client per credential set to avoid creating a new client on every request. + #### Disable Logging - Specific Calls To disable logging for specific calls use the `no-log` flag. diff --git a/docs/my-website/docs/pass_through/openai_passthrough.md b/docs/my-website/docs/pass_through/openai_passthrough.md index d7c98eba7b3..49026f8aa2d 100644 --- a/docs/my-website/docs/pass_through/openai_passthrough.md +++ b/docs/my-website/docs/pass_through/openai_passthrough.md @@ -1,6 +1,6 @@ # OpenAI Passthrough -Pass-through endpoints for `/openai` +Pass-through endpoints for direct OpenAI API access ## Overview @@ -10,12 +10,27 @@ Pass-through endpoints for `/openai` | Logging | āœ… | Works across all integrations | | Streaming | āœ… | Fully supported | -### When to use this? +## Available Endpoints + +### `/openai_passthrough` - Recommended +Dedicated passthrough endpoint that guarantees direct routing to OpenAI without conflicts. + +**Use this for:** +- OpenAI Responses API (`/v1/responses`) +- Any endpoint where you need guaranteed passthrough +- When `/openai` routes are conflicting with LiteLLM's native implementations + +### `/openai` - Legacy +Standard passthrough endpoint that may conflict with LiteLLM's native implementations. + +**Note:** Some endpoints like `/openai/v1/responses` will be routed to LiteLLM's native implementation instead of OpenAI. + +## When to use this? - For 90% of your use cases, you should use the [native LiteLLM OpenAI Integration](https://docs.litellm.ai/docs/providers/openai) (`/chat/completions`, `/embeddings`, `/completions`, `/images`, `/batches`, etc.) -- Use this passthrough to call less popular or newer OpenAI endpoints that LiteLLM doesn't fully support yet, such as `/assistants`, `/threads`, `/vector_stores` +- Use `/openai_passthrough` to call less popular or newer OpenAI endpoints that LiteLLM doesn't fully support yet, such as `/assistants`, `/threads`, `/vector_stores`, `/responses` -Simply replace `https://api.openai.com` with `LITELLM_PROXY_BASE_URL/openai` +Simply replace `https://api.openai.com` with `LITELLM_PROXY_BASE_URL/openai_passthrough` ## Usage Examples @@ -34,7 +49,7 @@ Make sure you do the following: import openai client = openai.OpenAI( - base_url="http://0.0.0.0:4000/openai", # /openai + base_url="http://0.0.0.0:4000/openai_passthrough", # /openai_passthrough api_key="sk-anything" # ) ``` diff --git a/docs/my-website/docs/providers/azure_ai/azure_model_router.md b/docs/my-website/docs/providers/azure_ai/azure_model_router.md index 5e14c7283f6..16bc1afb70e 100644 --- a/docs/my-website/docs/providers/azure_ai/azure_model_router.md +++ b/docs/my-website/docs/providers/azure_ai/azure_model_router.md @@ -5,19 +5,38 @@ Azure Model Router is a feature in Azure AI Foundry that automatically routes yo ## Key Features - **Automatic Model Selection**: Azure Model Router dynamically selects the best model for your request -- **Cost Tracking**: LiteLLM automatically tracks costs based on the actual model used (e.g., `gpt-4.1-nano`), not the router endpoint +- **Cost Tracking**: LiteLLM automatically tracks costs based on the actual model used (e.g., `gpt-4.1-nano`), plus the Model Router infrastructure fee - **Streaming Support**: Full support for streaming responses with accurate cost calculation +- **Simple Configuration**: Easy to set up via UI or config file + +## Model Naming Pattern + +Use the pattern: `azure_ai/model_router/` + +**Components:** +- `azure_ai` - The provider identifier +- `model_router` - Indicates this is a Model Router deployment +- `` - Your actual deployment name from Azure AI Foundry (e.g., `azure-model-router`) + +**Example:** `azure_ai/model_router/azure-model-router` + +**How it works:** +- LiteLLM automatically strips the `model_router/` prefix when sending requests to Azure +- Only your deployment name (e.g., `azure-model-router`) is sent to the Azure API +- The full path is preserved in responses and logs for proper cost tracking ## LiteLLM Python SDK ### Basic Usage +Use the pattern `azure_ai/model_router/` where `` is your Azure deployment name: + ```python import litellm import os response = litellm.completion( - model="azure_ai/azure-model-router", + model="azure_ai/model_router/azure-model-router", # Use your deployment name messages=[{"role": "user", "content": "Hello!"}], api_base="https://your-endpoint.cognitiveservices.azure.com/openai/v1/", api_key=os.getenv("AZURE_MODEL_ROUTER_API_KEY"), @@ -26,6 +45,13 @@ response = litellm.completion( print(response) ``` +**Pattern Explanation:** +- `azure_ai` - The provider +- `model_router` - Indicates this is a model router deployment +- `azure-model-router` - Your actual deployment name from Azure AI Foundry + +LiteLLM will automatically strip the `model_router/` prefix when sending the request to Azure, so only `azure-model-router` is sent to the API. + ### Streaming with Usage Tracking ```python @@ -33,7 +59,7 @@ import litellm import os response = await litellm.acompletion( - model="azure_ai/azure-model-router", + model="azure_ai/model_router/azure-model-router", # Use your deployment name messages=[{"role": "user", "content": "hi"}], api_base="https://your-endpoint.cognitiveservices.azure.com/openai/v1/", api_key=os.getenv("AZURE_MODEL_ROUTER_API_KEY"), @@ -51,13 +77,15 @@ async for chunk in response: ```yaml model_list: - - model_name: azure-model-router + - model_name: azure-model-router # Public name for your users litellm_params: - model: azure_ai/azure-model-router + model: azure_ai/model_router/azure-model-router # Use your deployment name api_base: https://your-endpoint.cognitiveservices.azure.com/openai/v1/ api_key: os.environ/AZURE_MODEL_ROUTER_API_KEY ``` +**Note:** Replace `azure-model-router` in the model path with your actual deployment name from Azure AI Foundry. + ### Start Proxy ```bash @@ -80,49 +108,42 @@ curl -X POST http://localhost:4000/chat/completions \ This walkthrough shows how to add an Azure Model Router endpoint to LiteLLM using the Admin Dashboard. -### Select Provider +### Quick Start + +1. Navigate to the **Models** page in the LiteLLM UI +2. Select **"Azure AI Foundry (Studio)"** as the provider +3. Enter your deployment name (e.g., `azure-model-router`) +4. LiteLLM will automatically format it as `azure_ai/model_router/azure-model-router` +5. Add your API base URL and API key +6. Test and save + +### Detailed Walkthrough + +#### Step 1: Select Provider Navigate to the Models page and select "Azure AI Foundry (Studio)" as the provider. -#### Navigate to Models Page +##### Navigate to Models Page ![Navigate to Models](./img/azure_model_router_01.jpeg) -#### Click Provider Dropdown +##### Click Provider Dropdown ![Click Provider](./img/azure_model_router_02.jpeg) -#### Choose Azure AI Foundry +##### Choose Azure AI Foundry ![Select Azure AI Foundry](./img/azure_model_router_03.jpeg) -### Configure Model Name +#### Step 2: Enter Deployment Name -Set up the model name by entering `azure_ai/` followed by your model router deployment name from Azure. +**New Simplified Method:** Just enter your deployment name directly in the text field. If your deployment name contains "model-router" or "model_router", LiteLLM will automatically format it as `azure_ai/model_router/`. -#### Click Model Name Field +**Example:** +- Enter: `azure-model-router` +- LiteLLM creates: `azure_ai/model_router/azure-model-router` -![Click Model Field](./img/azure_model_router_04.jpeg) - -#### Select Custom Model Name - -![Select Custom Model](./img/azure_model_router_05.jpeg) - -#### Enter LiteLLM Model Name - -![LiteLLM Model Name](./img/azure_model_router_06.jpeg) - -#### Click Custom Model Name Field - -![Enter Custom Name Field](./img/azure_model_router_07.jpeg) - -#### Type Model Prefix - -Type `azure_ai/` as the prefix. - -![Type azure_ai prefix](./img/azure_model_router_08.jpeg) - -#### Copy Model Name from Azure Portal +##### Copy Deployment Name from Azure Portal Switch to Azure AI Foundry and copy your model router deployment name. @@ -130,73 +151,79 @@ Switch to Azure AI Foundry and copy your model router deployment name. ![Copy Model Name](./img/azure_model_router_10.jpeg) -#### Paste Model Name +##### Enter Deployment Name in LiteLLM -Paste to get `azure_ai/azure-model-router`. +Paste your deployment name (e.g., `azure-model-router`) directly into the text field. -![Paste Model Name](./img/azure_model_router_11.jpeg) +![Enter Deployment Name](./img/azure_model_router_04.jpeg) -### Configure API Base and Key +**What happens behind the scenes:** +- You enter: `azure-model-router` +- LiteLLM automatically detects this is a model router deployment +- The full model path becomes: `azure_ai/model_router/azure-model-router` +- When making API calls, only `azure-model-router` is sent to Azure + +#### Step 3: Configure API Base and Key Copy the endpoint URL and API key from Azure portal. -#### Copy API Base URL from Azure +##### Copy API Base URL from Azure ![Copy API Base](./img/azure_model_router_12.jpeg) -#### Enter API Base in LiteLLM +##### Enter API Base in LiteLLM ![Click API Base Field](./img/azure_model_router_13.jpeg) ![Paste API Base](./img/azure_model_router_14.jpeg) -#### Copy API Key from Azure +##### Copy API Key from Azure ![Copy API Key](./img/azure_model_router_15.jpeg) -#### Enter API Key in LiteLLM +##### Enter API Key in LiteLLM ![Enter API Key](./img/azure_model_router_16.jpeg) -### Test and Add Model +#### Step 4: Test and Add Model Verify your configuration works and save the model. -#### Test Connection +##### Test Connection ![Test Connection](./img/azure_model_router_17.jpeg) -#### Close Test Dialog +##### Close Test Dialog ![Close Dialog](./img/azure_model_router_18.jpeg) -#### Add Model +##### Add Model ![Add Model](./img/azure_model_router_19.jpeg) -### Verify in Playground +#### Step 5: Verify in Playground Test your model and verify cost tracking is working. -#### Open Playground +##### Open Playground ![Go to Playground](./img/azure_model_router_20.jpeg) -#### Select Model +##### Select Model ![Select Model](./img/azure_model_router_21.jpeg) -#### Send Test Message +##### Send Test Message ![Send Message](./img/azure_model_router_22.jpeg) -#### View Logs +##### View Logs ![View Logs](./img/azure_model_router_23.jpeg) -#### Verify Cost Tracking +##### Verify Cost Tracking -Cost is tracked based on the actual model used (e.g., `gpt-4.1-nano`). +Cost is tracked based on the actual model used (e.g., `gpt-4.1-nano`), plus a flat infrastructure cost of $0.14 per million input tokens for using the Model Router. ![Verify Cost](./img/azure_model_router_24.jpeg) @@ -205,28 +232,50 @@ Cost is tracked based on the actual model used (e.g., `gpt-4.1-nano`). LiteLLM automatically handles cost tracking for Azure Model Router by: 1. **Detecting the actual model**: When Azure Model Router routes your request to a specific model (e.g., `gpt-4.1-nano-2025-04-14`), LiteLLM extracts this from the response -2. **Calculating accurate costs**: Costs are calculated based on the actual model used, not the router endpoint name +2. **Calculating accurate costs**: Costs are calculated based on: + - The actual model used (e.g., `gpt-4.1-nano` token costs) + - Plus a flat infrastructure cost of **$0.14 per million input tokens** for using the Model Router 3. **Streaming support**: Cost tracking works correctly for both streaming and non-streaming requests +### Cost Breakdown + +When you use Azure Model Router, the total cost includes: + +- **Model Cost**: Based on the actual model that handled your request (e.g., `gpt-4.1-nano`) +- **Router Flat Cost**: $0.14 per million input tokens (Azure AI Foundry infrastructure fee) + ### Example Response with Cost ```python import litellm response = litellm.completion( - model="azure_ai/azure-model-router", + model="azure_ai/model_router/azure-model-router", messages=[{"role": "user", "content": "Hello!"}], api_base="https://your-endpoint.cognitiveservices.azure.com/openai/v1/", api_key="your-api-key", ) # The response will show the actual model used -print(f"Model used: {response.model}") # e.g., "gpt-4.1-nano-2025-04-14" +print(f"Model used: {response.model}") # e.g., "azure_ai/gpt-4.1-nano-2025-04-14" -# Get cost +# Get cost (includes both model cost and router flat cost) from litellm import completion_cost cost = completion_cost(completion_response=response) -print(f"Cost: ${cost}") +print(f"Total cost: ${cost}") + +# Access detailed cost breakdown +if hasattr(response, '_hidden_params') and 'response_cost' in response._hidden_params: + print(f"Response cost: ${response._hidden_params['response_cost']}") ``` +### Viewing Cost Breakdown in UI + +When viewing logs in the LiteLLM UI, you'll see: +- **Model Cost**: The cost for the actual model used +- **Azure Model Router Flat Cost**: The $0.14/M input tokens infrastructure fee +- **Total Cost**: Sum of both costs + +This breakdown helps you understand exactly what you're paying for when using the Model Router. + diff --git a/docs/my-website/docs/providers/bedrock.md b/docs/my-website/docs/providers/bedrock.md index 487212ad655..e546ed97656 100644 --- a/docs/my-website/docs/providers/bedrock.md +++ b/docs/my-website/docs/providers/bedrock.md @@ -9,7 +9,7 @@ ALL Bedrock models (Anthropic, Meta, Deepseek, Mistral, Amazon, etc.) are Suppor | Description | Amazon Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs). | | Provider Route on LiteLLM | `bedrock/`, [`bedrock/converse/`](#set-converse--invoke-route), [`bedrock/invoke/`](#set-invoke-route), [`bedrock/converse_like/`](#calling-via-internal-proxy), [`bedrock/llama/`](#deepseek-not-r1), [`bedrock/deepseek_r1/`](#deepseek-r1), [`bedrock/qwen3/`](#qwen3-imported-models), [`bedrock/qwen2/`](./bedrock_imported.md#qwen2-imported-models), [`bedrock/openai/`](./bedrock_imported.md#openai-compatible-imported-models-qwen-25-vl-etc), [`bedrock/moonshot`](./bedrock_imported.md#moonshot-kimi-k2-thinking) | | Provider Doc | [Amazon Bedrock ↗](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html) | -| Supported OpenAI Endpoints | `/chat/completions`, `/completions`, `/embeddings`, `/images/generations` | +| Supported OpenAI Endpoints | `/chat/completions`, `/completions`, `/embeddings`, `/images/generations`, `/v1/realtime`| | Rerank Endpoint | `/rerank` | | Pass-through Endpoint | [Supported](../pass_through/bedrock.md) | diff --git a/docs/my-website/docs/providers/bedrock_realtime_with_audio.md b/docs/my-website/docs/providers/bedrock_realtime_with_audio.md new file mode 100644 index 00000000000..a2d9813ffd9 --- /dev/null +++ b/docs/my-website/docs/providers/bedrock_realtime_with_audio.md @@ -0,0 +1,362 @@ +# Bedrock Realtime API + +## Overview + +Amazon Bedrock's Nova Sonic model supports real-time bidirectional audio streaming for voice conversations. This tutorial shows how to use it through LiteLLM Proxy. + +## Setup + +### 1. Configure LiteLLM Proxy + +Create a `config.yaml` file: + +```yaml +model_list: + - model_name: "bedrock-sonic" + litellm_params: + model: bedrock/amazon.nova-sonic-v1:0 + aws_region_name: us-east-1 # or your preferred region + model_info: + mode: realtime +``` + +### 2. Start LiteLLM Proxy + +```bash +litellm --config config.yaml +``` + +## Basic Text Interaction + +```python +import asyncio +import websockets +import json + +LITELLM_API_KEY = "sk-1234" # Your LiteLLM API key +LITELLM_URL = 'ws://localhost:4000/v1/realtime?model=bedrock-sonic' + +async def test_text_conversation(): + async with websockets.connect( + LITELLM_URL, + additional_headers={ + "Authorization": f"Bearer {LITELLM_API_KEY}" + } + ) as ws: + # Wait for session.created + response = await ws.recv() + print(f"Connected: {json.loads(response)['type']}") + + # Configure session + session_update = { + "type": "session.update", + "session": { + "instructions": "You are a helpful assistant.", + "modalities": ["text"], + "temperature": 0.8 + } + } + await ws.send(json.dumps(session_update)) + + # Send a message + message = { + "type": "conversation.item.create", + "item": { + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "Hello!"}] + } + } + await ws.send(json.dumps(message)) + + # Trigger response + await ws.send(json.dumps({"type": "response.create"})) + + # Listen for response + while True: + response = await ws.recv() + event = json.loads(response) + + if event['type'] == 'response.text.delta': + print(event['delta'], end='', flush=True) + elif event['type'] == 'response.done': + print("\nāœ“ Complete") + break + +if __name__ == "__main__": + asyncio.run(test_text_conversation()) +``` + +## Audio Streaming with Voice Conversation + +```python +import asyncio +import websockets +import json +import base64 +import pyaudio + +LITELLM_API_KEY = "sk-1234" +LITELLM_URL = 'ws://localhost:4000/v1/realtime?model=bedrock-sonic' + +# Audio configuration +INPUT_RATE = 16000 # Nova Sonic expects 16kHz input +OUTPUT_RATE = 24000 # Nova Sonic outputs 24kHz +CHUNK = 1024 + +async def audio_conversation(): + # Initialize PyAudio + p = pyaudio.PyAudio() + + # Input stream (microphone) + input_stream = p.open( + format=pyaudio.paInt16, + channels=1, + rate=INPUT_RATE, + input=True, + frames_per_buffer=CHUNK + ) + + # Output stream (speakers) + output_stream = p.open( + format=pyaudio.paInt16, + channels=1, + rate=OUTPUT_RATE, + output=True, + frames_per_buffer=CHUNK + ) + + async with websockets.connect( + LITELLM_URL, + additional_headers={"Authorization": f"Bearer {LITELLM_API_KEY}"} + ) as ws: + # Wait for session.created + await ws.recv() + print("āœ“ Connected") + + # Configure session with audio + session_update = { + "type": "session.update", + "session": { + "instructions": "You are a friendly voice assistant.", + "modalities": ["text", "audio"], + "voice": "matthew", + "input_audio_format": "pcm16", + "output_audio_format": "pcm16" + } + } + await ws.send(json.dumps(session_update)) + print("šŸŽ¤ Speak into your microphone...") + + async def send_audio(): + """Capture and send audio from microphone""" + while True: + audio_data = input_stream.read(CHUNK, exception_on_overflow=False) + audio_b64 = base64.b64encode(audio_data).decode('utf-8') + await ws.send(json.dumps({ + "type": "input_audio_buffer.append", + "audio": audio_b64 + })) + await asyncio.sleep(0.01) + + async def receive_audio(): + """Receive and play audio responses""" + while True: + response = await ws.recv() + event = json.loads(response) + + if event['type'] == 'response.audio.delta': + audio_b64 = event.get('delta', '') + if audio_b64: + audio_bytes = base64.b64decode(audio_b64) + output_stream.write(audio_bytes) + + elif event['type'] == 'response.text.delta': + print(event['delta'], end='', flush=True) + + elif event['type'] == 'response.done': + print("\nāœ“ Response complete") + + # Run both tasks concurrently + await asyncio.gather(send_audio(), receive_audio()) + +if __name__ == "__main__": + try: + asyncio.run(audio_conversation()) + except KeyboardInterrupt: + print("\n\nGoodbye!") +``` + +## Using Tools/Function Calling + +```python +import asyncio +import websockets +import json +from datetime import datetime + +LITELLM_API_KEY = "sk-1234" +LITELLM_URL = 'ws://localhost:4000/v1/realtime?model=bedrock-sonic' + +# Define tools +TOOLS = [ + { + "type": "function", + "function": { + "name": "get_weather", + "description": "Get current weather for a location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "City name" + } + }, + "required": ["location"] + } + } + } +] + +def get_weather(location: str) -> dict: + """Simulated weather function""" + return { + "location": location, + "temperature": 72, + "conditions": "sunny" + } + +async def conversation_with_tools(): + async with websockets.connect( + LITELLM_URL, + additional_headers={"Authorization": f"Bearer {LITELLM_API_KEY}"} + ) as ws: + # Wait for session.created + await ws.recv() + + # Configure session with tools + session_update = { + "type": "session.update", + "session": { + "instructions": "You are a helpful assistant with access to tools.", + "modalities": ["text"], + "tools": TOOLS + } + } + await ws.send(json.dumps(session_update)) + + # Send a message that requires a tool + message = { + "type": "conversation.item.create", + "item": { + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "What's the weather in San Francisco?"}] + } + } + await ws.send(json.dumps(message)) + await ws.send(json.dumps({"type": "response.create"})) + + # Handle responses and tool calls + while True: + response = await ws.recv() + event = json.loads(response) + + if event['type'] == 'response.text.delta': + print(event['delta'], end='', flush=True) + + elif event['type'] == 'response.function_call_arguments.done': + # Execute the tool + function_name = event['name'] + arguments = json.loads(event['arguments']) + + print(f"\nšŸ”§ Calling {function_name}({arguments})") + result = get_weather(**arguments) + + # Send tool result back + tool_result = { + "type": "conversation.item.create", + "item": { + "type": "function_call_output", + "call_id": event['call_id'], + "output": json.dumps(result) + } + } + await ws.send(json.dumps(tool_result)) + await ws.send(json.dumps({"type": "response.create"})) + + elif event['type'] == 'response.done': + print("\nāœ“ Complete") + break + +if __name__ == "__main__": + asyncio.run(conversation_with_tools()) +``` + +## Configuration Options + +### Voice Options +Available voices: `matthew`, `joanna`, `ruth`, `stephen`, `gregory`, `amy` + +### Audio Formats +- **Input**: 16kHz PCM16 (mono) +- **Output**: 24kHz PCM16 (mono) + +### Modalities +- `["text"]` - Text only +- `["audio"]` - Audio only +- `["text", "audio"]` - Both text and audio + +## Example Test Scripts + +Complete working examples are available in the LiteLLM repository: + +- **Basic audio streaming**: `test_bedrock_realtime_client.py` +- **Simple text test**: `test_bedrock_realtime_simple.py` +- **Tool calling**: `test_bedrock_realtime_tools.py` + +## Requirements + +```bash +pip install litellm websockets pyaudio +``` + +## AWS Configuration + +Ensure your AWS credentials are configured: + +```bash +export AWS_ACCESS_KEY_ID=your_access_key +export AWS_SECRET_ACCESS_KEY=your_secret_key +export AWS_REGION_NAME=us-east-1 +``` + +Or use AWS CLI configuration: + +```bash +aws configure +``` + +## Troubleshooting + +### Connection Issues +- Ensure LiteLLM proxy is running on the correct port +- Verify AWS credentials are properly configured +- Check that the Bedrock model is available in your region + +### Audio Issues +- Verify PyAudio is properly installed +- Check microphone/speaker permissions +- Ensure correct sample rates (16kHz input, 24kHz output) + +### Tool Calling Issues +- Ensure tools are properly defined in session.update +- Verify tool results are sent back with correct call_id +- Check that response.create is sent after tool result + +## Related Resources + +- [OpenAI Realtime API Documentation](https://platform.openai.com/docs/guides/realtime) +- [Amazon Bedrock Nova Sonic Documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/nova-sonic.html) +- [LiteLLM Realtime API Documentation](/docs/realtime) diff --git a/docs/my-website/docs/providers/gemini.md b/docs/my-website/docs/providers/gemini.md index 23a02f7365c..b9ad7820dd4 100644 --- a/docs/my-website/docs/providers/gemini.md +++ b/docs/my-website/docs/providers/gemini.md @@ -1840,6 +1840,57 @@ content = response.get('choices', [{}])[0].get('message', {}).get('content') print(content) ``` +## gemini-robotics-er-1.5-preview Usage + +```python +from litellm import api_base +from openai import OpenAI +import os +import base64 + +client = OpenAI(base_url="http://0.0.0.0:4000", api_key="sk-12345") +base64_image = base64.b64encode(open("closeup-object-on-table-many-260nw-1216144471.webp", "rb").read()).decode() + +import json +import re +tools = [{"codeExecution": {}}] +response = client.chat.completions.create( + model="gemini/gemini-robotics-er-1.5-preview", + messages=[ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "Point to no more than 10 items in the image. The label returned should be an identifying name for the object detected. The answer should follow the json format: [{\"point\": [y, x], \"label\": }, ...]. The points are in [y, x] format normalized to 0-1000." + }, + { + "type": "image_url", + "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"} + } + ] + } + ], + tools=tools +) + +# Extract JSON from markdown code block if present +content = response.choices[0].message.content +# Look for triple-backtick JSON block +match = re.search(r'```json\s*(.*?)\s*```', content, re.DOTALL) +if match: + json_str = match.group(1) +else: + json_str = content + +try: + data = json.loads(json_str) + print(json.dumps(data, indent=2)) +except Exception as e: + print("Error parsing response as JSON:", e) + print("Response content:", content) +``` + ## Usage - PDF / Videos / etc. Files ### Inline Data (e.g. audio stream) diff --git a/docs/my-website/docs/providers/github_copilot.md b/docs/my-website/docs/providers/github_copilot.md index 306c9f949ec..e9fd3444f5f 100644 --- a/docs/my-website/docs/providers/github_copilot.md +++ b/docs/my-website/docs/providers/github_copilot.md @@ -35,11 +35,10 @@ from litellm import completion response = completion( model="github_copilot/gpt-4", - messages=[{"role": "user", "content": "Write a Python function to calculate fibonacci numbers"}], - extra_headers={ - "editor-version": "vscode/1.85.1", - "Copilot-Integration-Id": "vscode-chat" - } + messages=[ + {"role": "system", "content": "You are a helpful coding assistant"}, + {"role": "user", "content": "Write a Python function to calculate fibonacci numbers"} + ] ) print(response) ``` @@ -50,11 +49,7 @@ from litellm import completion stream = completion( model="github_copilot/gpt-4", messages=[{"role": "user", "content": "Explain async/await in Python"}], - stream=True, - extra_headers={ - "editor-version": "vscode/1.85.1", - "Copilot-Integration-Id": "vscode-chat" - } + stream=True ) for chunk in stream: @@ -134,11 +129,7 @@ client = OpenAI( # Non-streaming response response = client.chat.completions.create( model="github_copilot/gpt-4", - messages=[{"role": "user", "content": "How do I optimize this SQL query?"}], - extra_headers={ - "editor-version": "vscode/1.85.1", - "Copilot-Integration-Id": "vscode-chat" - } + messages=[{"role": "user", "content": "How do I optimize this SQL query?"}] ) print(response.choices[0].message.content) @@ -156,11 +147,7 @@ response = litellm.completion( model="litellm_proxy/github_copilot/gpt-4", messages=[{"role": "user", "content": "Review this code for bugs"}], api_base="http://localhost:4000", - api_key="your-proxy-api-key", - extra_headers={ - "editor-version": "vscode/1.85.1", - "Copilot-Integration-Id": "vscode-chat" - } + api_key="your-proxy-api-key" ) print(response.choices[0].message.content) @@ -174,8 +161,6 @@ print(response.choices[0].message.content) curl http://localhost:4000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-proxy-api-key" \ - -H "editor-version: vscode/1.85.1" \ - -H "Copilot-Integration-Id: vscode-chat" \ -d '{ "model": "github_copilot/gpt-4", "messages": [{"role": "user", "content": "Explain this error message"}] @@ -211,9 +196,11 @@ export GITHUB_COPILOT_API_KEY_FILE="api-key.json" ### Headers -GitHub Copilot supports various editor-specific headers: +LiteLLM automatically injects the required GitHub Copilot headers (simulating VSCode). You don't need to specify them manually. -```python showLineNumbers title="Common Headers" +If you want to override the defaults (e.g., to simulate a different editor), you can use `extra_headers`: + +```python showLineNumbers title="Custom Headers (Optional)" extra_headers = { "editor-version": "vscode/1.85.1", # Editor version "editor-plugin-version": "copilot/1.155.0", # Plugin version diff --git a/docs/my-website/docs/providers/sarvam.md b/docs/my-website/docs/providers/sarvam.md new file mode 100644 index 00000000000..6a292456781 --- /dev/null +++ b/docs/my-website/docs/providers/sarvam.md @@ -0,0 +1,92 @@ +# Sarvam.ai + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +LiteLLM supports all the text models from [Sarvam ai](https://docs.sarvam.ai/api-reference-docs/chat/chat-completions) + +## Usage + +```python +import os +from litellm import completion + +# Set your Sarvam API key +os.environ["SARVAM_API_KEY"] = "" + +messages = [{"role": "user", "content": "Hello"}] + +response = completion( + model="sarvam/sarvam-m", + messages=messages, +) +print(response) +``` + +## Usage with LiteLLM Proxy Server + +Here's how to call a Sarvam.ai model with the LiteLLM Proxy Server + +1. **Modify the `config.yaml`:** + + ```yaml + model_list: + - model_name: my-model + litellm_params: + model: sarvam/ # add sarvam/ prefix to route as Sarvam provider + api_key: api-key # api key to send your model + ``` + +2. **Start the proxy:** + + ```bash + $ litellm --config /path/to/config.yaml + ``` + +3. **Send a request to LiteLLM Proxy Server:** + + + + + + ```python + import openai + + client = openai.OpenAI( + api_key="sk-1234", # pass litellm proxy key, if you're using virtual keys + base_url="http://0.0.0.0:4000" # litellm-proxy-base url + ) + + response = client.chat.completions.create( + model="my-model", + messages=[ + { + "role": "user", + "content": "what llm are you" + } + ], + ) + + print(response) + ``` + + + + + ```shell + curl --location 'http://0.0.0.0:4000/chat/completions' \ + --header 'Authorization: Bearer sk-1234' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": "my-model", + "messages": [ + { + "role": "user", + "content": "what llm are you" + } + ] + }' + ``` + + + diff --git a/docs/my-website/docs/providers/vercel_ai_gateway.md b/docs/my-website/docs/providers/vercel_ai_gateway.md index 91f0a18ea1c..3ff007171ed 100644 --- a/docs/my-website/docs/providers/vercel_ai_gateway.md +++ b/docs/my-website/docs/providers/vercel_ai_gateway.md @@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem'; | Provider Route on LiteLLM | `vercel_ai_gateway/` | | Link to Provider Doc | [Vercel AI Gateway Documentation ↗](https://vercel.com/docs/ai-gateway) | | Base URL | `https://ai-gateway.vercel.sh/v1` | -| Supported Operations | `/chat/completions`, `/models` | +| Supported Operations | `/chat/completions`, `/embeddings`, `/models` |

@@ -73,7 +73,7 @@ messages = [{"content": "Hello, how are you?", "role": "user"}] # Vercel AI Gateway call with streaming response = completion( - model="vercel_ai_gateway/openai/gpt-4o", + model="vercel_ai_gateway/openai/gpt-4o", messages=messages, stream=True ) @@ -82,6 +82,33 @@ for chunk in response: print(chunk) ``` +### Embeddings + +```python showLineNumbers title="Vercel AI Gateway Embeddings" +import os +from litellm import embedding + +os.environ["VERCEL_AI_GATEWAY_API_KEY"] = "your-api-key" + +# Vercel AI Gateway embedding call +response = embedding( + model="vercel_ai_gateway/openai/text-embedding-3-small", + input="Hello world" +) + +print(response.data[0]["embedding"][:5]) # Print first 5 dimensions +``` + +You can also specify the `dimensions` parameter: + +```python showLineNumbers title="Vercel AI Gateway Embeddings with Dimensions" +response = embedding( + model="vercel_ai_gateway/openai/text-embedding-3-small", + input=["Hello world", "Goodbye world"], + dimensions=768 +) +``` + ## Usage - LiteLLM Proxy Add the following to your LiteLLM Proxy configuration file: @@ -97,6 +124,11 @@ model_list: litellm_params: model: vercel_ai_gateway/anthropic/claude-4-sonnet api_key: os.environ/VERCEL_AI_GATEWAY_API_KEY + + - model_name: text-embedding-3-small-gateway + litellm_params: + model: vercel_ai_gateway/openai/text-embedding-3-small + api_key: os.environ/VERCEL_AI_GATEWAY_API_KEY ``` Start your LiteLLM Proxy server: diff --git a/docs/my-website/docs/providers/vertex_speech.md b/docs/my-website/docs/providers/vertex_speech.md index d0acacb5aec..751782a323c 100644 --- a/docs/my-website/docs/providers/vertex_speech.md +++ b/docs/my-website/docs/providers/vertex_speech.md @@ -312,6 +312,7 @@ Gemini models with audio output capabilities using the chat completions API. - Only supports `pcm16` audio format - Streaming not yet supported - Must set `modalities: ["audio"]` +- When using via LiteLLM Proxy, must include `"allowed_openai_params": ["audio", "modalities"]` in the request body to enable audio parameters ::: ### Quick Start @@ -372,7 +373,8 @@ curl http://0.0.0.0:4000/v1/chat/completions \ "model": "gemini-tts", "messages": [{"role": "user", "content": "Say hello in a friendly voice"}], "modalities": ["audio"], - "audio": {"voice": "Kore", "format": "pcm16"} + "audio": {"voice": "Kore", "format": "pcm16"}, + "allowed_openai_params": ["audio", "modalities"] }' ``` @@ -389,6 +391,7 @@ response = client.chat.completions.create( messages=[{"role": "user", "content": "Say hello in a friendly voice"}], modalities=["audio"], audio={"voice": "Kore", "format": "pcm16"}, + extra_body={"allowed_openai_params": ["audio", "modalities"]} ) print(response) ``` diff --git a/docs/my-website/docs/providers/xai_realtime.md b/docs/my-website/docs/providers/xai_realtime.md new file mode 100644 index 00000000000..b36908c4686 --- /dev/null +++ b/docs/my-website/docs/providers/xai_realtime.md @@ -0,0 +1,308 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# xAI Voice Agent (Realtime API) + +xAI's Grok Voice Agent provides real-time voice conversation capabilities through WebSocket connections, enabling natural bidirectional audio interactions. + +| Feature | Description | Comments | +| --- | --- | --- | +| LiteLLM AI Gateway | āœ… | | +| LiteLLM Python SDK | āœ… | Full support via `litellm.realtime()` | + +## Quick Start + +### Supported Model + +| Model | Context | Features | +|-------|---------|----------| +| `xai/grok-4-1-fast-non-reasoning` | 2M tokens | Voice conversation, Function calling, Vision, Audio, Web search, Caching | + +**Note:** xAI Realtime API uses the non-reasoning variant for optimal real-time performance. + +## Python SDK Usage + +### Basic Realtime Connection + +```python +import asyncio +from litellm import realtime + +async def test_xai_realtime(): + """ + Test xAI Grok Voice Agent via LiteLLM SDK + """ + # Initialize realtime connection + ws = await realtime( + model="xai/grok-4-1-fast-non-reasoning", + api_key="your-xai-api-key", # or set XAI_API_KEY env var + ) + + # Connection established, xAI sends "conversation.created" event + print("Connected to xAI Grok Voice Agent") + + # Send a message + await ws.send_text(json.dumps({ + "type": "conversation.item.create", + "item": { + "type": "message", + "role": "user", + "content": [{ + "type": "input_text", + "text": "Hello! How are you?" + }] + } + })) + + # Request a response + await ws.send_text(json.dumps({ + "type": "response.create" + })) + + # Listen for responses + async for message in ws: + data = json.loads(message) + print(f"Received: {data['type']}") + + if data['type'] == 'response.done': + break + + await ws.close() + +# Run the async function +asyncio.run(test_xai_realtime()) +``` + +### With Audio Input/Output + +```python +import asyncio +import json +from litellm import realtime + +async def xai_voice_conversation(): + """ + Voice conversation with xAI Grok Voice Agent + """ + ws = await realtime( + model="xai/grok-4-1-fast-non-reasoning", + api_key="your-xai-api-key", + ) + + # Send audio data (base64 encoded PCM16 24kHz) + await ws.send_text(json.dumps({ + "type": "conversation.item.create", + "item": { + "type": "message", + "role": "user", + "content": [{ + "type": "input_audio", + "audio": "base64_encoded_audio_data_here" + }] + } + })) + + # Request response with audio + await ws.send_text(json.dumps({ + "type": "response.create", + "response": { + "modalities": ["text", "audio"], + "instructions": "Please respond in a friendly tone." + } + })) + + # Process streaming audio response + async for message in ws: + data = json.loads(message) + + if data['type'] == 'response.audio.delta': + # Handle audio chunks + audio_chunk = data['delta'] + # Process audio_chunk (play it, save it, etc.) + + elif data['type'] == 'response.done': + break + + await ws.close() + +asyncio.run(xai_voice_conversation()) +``` + +## LiteLLM Proxy (AI Gateway) Usage + +Load balance across multiple xAI deployments or combine with other providers. + +### 1. Add Model to Config + +```yaml +model_list: + - model_name: grok-voice-agent + litellm_params: + model: xai/grok-4-1-fast-non-reasoning + api_key: os.environ/XAI_API_KEY + model_info: + mode: realtime + + # Optional: Add fallback to OpenAI + - model_name: grok-voice-agent + litellm_params: + model: openai/gpt-4o-realtime-preview-2024-10-01 + api_key: os.environ/OPENAI_API_KEY + model_info: + mode: realtime +``` + +### 2. Start Proxy + +```bash +litellm --config /path/to/config.yaml + +# RUNNING on http://0.0.0.0:4000 +``` + +### 3. Test Connection + +#### Python Client + +```python +import asyncio +import websockets +import json + +async def test_proxy(): + url = "ws://0.0.0.0:4000/v1/realtime?model=grok-voice-agent" + + async with websockets.connect( + url, + extra_headers={ + "Authorization": "Bearer sk-1234", # Your LiteLLM proxy key + "OpenAI-Beta": "realtime=v1" + } + ) as ws: + # Wait for conversation.created event from xAI + message = await ws.recv() + print(f"Connected: {message}") + + # Send a message + await ws.send(json.dumps({ + "type": "conversation.item.create", + "item": { + "type": "message", + "role": "user", + "content": [{ + "type": "input_text", + "text": "Hello from LiteLLM proxy!" + }] + } + })) + + # Request response + await ws.send(json.dumps({ + "type": "response.create" + })) + + # Listen for response + async for message in ws: + data = json.loads(message) + print(f"Event: {data['type']}") + + if data['type'] == 'response.done': + break + +asyncio.run(test_proxy()) +``` + +#### Node.js Client + +```javascript +// test.js - Run with: node test.js +const WebSocket = require("ws"); + +const url = "ws://0.0.0.0:4000/v1/realtime?model=grok-voice-agent"; + +const ws = new WebSocket(url, { + headers: { + "Authorization": "Bearer sk-1234", + "OpenAI-Beta": "realtime=v1", + }, +}); + +ws.on("open", function open() { + console.log("Connected to xAI via LiteLLM proxy"); + + // Send a message + ws.send(JSON.stringify({ + type: "conversation.item.create", + item: { + type: "message", + role: "user", + content: [{ + type: "input_text", + text: "What's the weather like?" + }] + } + })); + + // Request response + ws.send(JSON.stringify({ + type: "response.create", + response: { + modalities: ["text"], + instructions: "Please assist the user." + } + })); +}); + +ws.on("message", function incoming(message) { + const data = JSON.parse(message.toString()); + console.log(`Event: ${data.type}`); + + if (data.type === 'response.done') { + ws.close(); + } +}); + +ws.on("error", function handleError(error) { + console.error("Error: ", error); +}); +``` + +## Key Differences from OpenAI + +xAI's Grok Voice Agent has some differences from OpenAI's Realtime API: + +| Feature | xAI | OpenAI | LiteLLM Handling | +|---------|-----|--------|------------------| +| Initial Event | `conversation.created` | `session.created` | āš ļø Passed through as-is | +| WebSocket URL | `wss://api.x.ai/v1/realtime` | `wss://api.openai.com/v1/realtime` | āœ… Auto-configured | +| Model | `grok-4-1-fast-non-reasoning` | `gpt-4o-realtime-preview` | āœ… Via model prefix | +| Audio Format | PCM16 24kHz mono | PCM16 24kHz mono | āœ… Compatible | +| Context Window | 2M tokens | 128K tokens | N/A | + +**What LiteLLM Handles:** +- āœ… Automatic URL routing to correct provider +- āœ… Authentication headers (no `OpenAI-Beta` header for xAI) +- āœ… WebSocket connection management +- āœ… All other event types are compatible + +**What You Need to Handle:** +- āš ļø Initial event type difference (`conversation.created` vs `session.created`) + +**Tip:** Make your client compatible with both event types: +```python +# Handle both providers +if event['type'] in ['session.created', 'conversation.created']: + print("Connection established") +``` + +## Related Documentation + +- [xAI Chat/Text Models](/docs/providers/xai) +- [LiteLLM Realtime API Overview](/docs/realtime) +- [xAI Official Documentation](https://docs.x.ai/docs) + +## Support + +For issues or questions: +- [LiteLLM GitHub Issues](https://github.com/BerriAI/litellm/issues) +- [xAI Documentation](https://docs.x.ai/docs) diff --git a/docs/my-website/docs/proxy/call_hooks.md b/docs/my-website/docs/proxy/call_hooks.md index fe865f67e09..17354725fd5 100644 --- a/docs/my-website/docs/proxy/call_hooks.md +++ b/docs/my-website/docs/proxy/call_hooks.md @@ -19,6 +19,7 @@ import Image from '@theme/IdealImage'; | `async_post_call_success_hook` | Modify outgoing response (non-streaming) | After successful LLM API call, for non-streaming responses | | `async_post_call_failure_hook` | Transform error responses sent to clients | After failed LLM API call | | `async_post_call_streaming_hook` | Modify outgoing response (streaming) | After successful LLM API call, for streaming responses | +| `async_post_call_response_headers_hook` | Inject custom HTTP response headers | After LLM API call (both success and failure) | See a complete example with our [parallel request rate limiter](https://github.com/BerriAI/litellm/blob/main/litellm/proxy/hooks/parallel_request_limiter.py) @@ -115,6 +116,18 @@ class MyCustomHandler(CustomLogger): # https://docs.litellm.ai/docs/observabilit async for item in response: yield item + async def async_post_call_response_headers_hook( + self, + data: dict, + user_api_key_dict: UserAPIKeyAuth, + response: Any, + request_headers: Optional[Dict[str, str]] = None, + ) -> Optional[Dict[str, str]]: + """ + Inject custom headers into HTTP response (runs for both success and failure). + """ + return {"x-custom-header": "custom-value"} + proxy_handler_instance = MyCustomHandler() ``` @@ -389,3 +402,31 @@ proxy_handler_instance = MyErrorTransformer() ``` **Result:** Clients receive `"Your prompt is too long..."` instead of `"ContextWindowExceededError: Prompt exceeds context window"`. + +## Advanced - Inject Custom HTTP Response Headers + +Use `async_post_call_response_headers_hook` to inject custom HTTP headers into responses. This hook runs for **both successful and failed** LLM API calls. + +```python +from litellm.integrations.custom_logger import CustomLogger +from litellm.proxy.proxy_server import UserAPIKeyAuth +from typing import Any, Dict, Optional + +class CustomHeaderLogger(CustomLogger): + def __init__(self): + super().__init__() + + async def async_post_call_response_headers_hook( + self, + data: dict, + user_api_key_dict: UserAPIKeyAuth, + response: Any, + request_headers: Optional[Dict[str, str]] = None, + ) -> Optional[Dict[str, str]]: + """ + Inject custom headers into all responses (success and failure). + """ + return {"x-custom-header": "custom-value"} + +proxy_handler_instance = CustomHeaderLogger() +``` diff --git a/docs/my-website/docs/proxy/cli_sso.md b/docs/my-website/docs/proxy/cli_sso.md index cde6bf266d4..ad0f033f802 100644 --- a/docs/my-website/docs/proxy/cli_sso.md +++ b/docs/my-website/docs/proxy/cli_sso.md @@ -28,6 +28,37 @@ EXPERIMENTAL_UI_LOGIN="True" litellm --config config.yaml ::: +### Configuration + +#### JWT Token Expiration + +By default, CLI authentication tokens expire after **24 hours**. You can customize this expiration time by setting the `LITELLM_CLI_JWT_EXPIRATION_HOURS` environment variable when starting your LiteLLM Proxy: + +```bash +# Set CLI JWT tokens to expire after 48 hours +export LITELLM_CLI_JWT_EXPIRATION_HOURS=48 +export EXPERIMENTAL_UI_LOGIN="True" +litellm --config config.yaml +``` + +Or in a single command: + +```bash +LITELLM_CLI_JWT_EXPIRATION_HOURS=48 EXPERIMENTAL_UI_LOGIN="True" litellm --config config.yaml +``` + +**Examples:** +- `LITELLM_CLI_JWT_EXPIRATION_HOURS=12` - Tokens expire after 12 hours +- `LITELLM_CLI_JWT_EXPIRATION_HOURS=168` - Tokens expire after 7 days (168 hours) +- `LITELLM_CLI_JWT_EXPIRATION_HOURS=720` - Tokens expire after 30 days (720 hours) + +:::tip +You can check your current token's age and expiration status using: +```bash +litellm-proxy whoami +``` +::: + ### Steps 1. **Install the CLI** diff --git a/docs/my-website/docs/proxy/config_settings.md b/docs/my-website/docs/proxy/config_settings.md index 6d3fa206113..5cdae51f448 100644 --- a/docs/my-website/docs/proxy/config_settings.md +++ b/docs/my-website/docs/proxy/config_settings.md @@ -94,7 +94,7 @@ litellm_settings: # /chat/completions, /completions, /embeddings, /audio/transcriptions mode: default_off # if default_off, you need to opt in to caching on a per call basis ttl: 600 # ttl for caching - disable_copilot_system_to_assistant: False # If false (default), converts all 'system' role messages to 'assistant' for GitHub Copilot compatibility. Set to true to disable this behavior. + disable_copilot_system_to_assistant: False # DEPRECATED - GitHub Copilot API supports system prompts. callback_settings: otel: @@ -197,7 +197,7 @@ router_settings: | disable_add_transform_inline_image_block | boolean | For Fireworks AI models - if true, turns off the auto-add of `#transform=inline` to the url of the image_url, if the model is not a vision model. | | disable_hf_tokenizer_download | boolean | If true, it defaults to using the openai tokenizer for all models (including huggingface models). | | enable_json_schema_validation | boolean | If true, enables json schema validation for all requests. | -| disable_copilot_system_to_assistant | boolean | If false (default), converts all 'system' role messages to 'assistant' for GitHub Copilot compatibility. Set to true to disable this behavior. Useful for tools (like Claude Code) that send system messages, which Copilot does not support. | +| disable_copilot_system_to_assistant | boolean | **DEPRECATED** - GitHub Copilot API supports system prompts. | ### general_settings - Reference @@ -321,6 +321,7 @@ router_settings: | redis_host | string | The host address for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them** | | redis_password | string | The password for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them** | | redis_port | string | The port number for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them**| +| redis_db | int | The database number for the Redis server. **Only set this if you have multiple instances of LiteLLM Proxy and want current tpm/rpm tracking to be shared across them**| | enable_pre_call_check | boolean | If true, checks if a call is within the model's context window before making the call. [More information here](reliability) | | content_policy_fallbacks | array of objects | Specifies fallback models for content policy violations. [More information here](reliability) | | fallbacks | array of objects | Specifies fallback models for all types of errors. [More information here](reliability) | @@ -452,6 +453,8 @@ router_settings: | BERRISPEND_ACCOUNT_ID | Account ID for BerriSpend service | BRAINTRUST_API_KEY | API key for Braintrust integration | BRAINTRUST_API_BASE | Base URL for Braintrust API. Default is https://api.braintrustdata.com/v1 +| BRAINTRUST_MOCK | Enable mock mode for Braintrust integration testing. When set to true, intercepts Braintrust API calls and returns mock responses without making actual network calls. Default is false +| BRAINTRUST_MOCK_LATENCY_MS | Mock latency in milliseconds for Braintrust API calls when mock mode is enabled. Simulates network round-trip time. Default is 100ms | CACHED_STREAMING_CHUNK_DELAY | Delay in seconds for cached streaming chunks. Default is 0.02 | CHATGPT_API_BASE | Base URL for ChatGPT API. Default is https://chatgpt.com/backend-api/codex | CHATGPT_AUTH_FILE | Filename for ChatGPT authentication data. Default is "auth.json" @@ -462,6 +465,7 @@ router_settings: | CHATGPT_USER_AGENT_SUFFIX | Suffix to append to the ChatGPT user agent string | CIRCLE_OIDC_TOKEN | OpenID Connect token for CircleCI | CIRCLE_OIDC_TOKEN_V2 | Version 2 of the OpenID Connect token for CircleCI +| CLI_JWT_EXPIRATION_HOURS | Expiration time in hours for CLI-generated JWT tokens. Default is 24 hours. Can also be set via LITELLM_CLI_JWT_EXPIRATION_HOURS | CLOUDZERO_API_KEY | CloudZero API key for authentication | CLOUDZERO_CONNECTION_ID | CloudZero connection ID for data submission | CLOUDZERO_EXPORT_INTERVAL_MINUTES | Interval in minutes for CloudZero data export operations @@ -504,12 +508,15 @@ router_settings: | DD_AGENT_HOST | Hostname or IP of DataDog agent (e.g., "localhost"). When set, logs are sent to agent instead of direct API | DD_AGENT_PORT | Port of DataDog agent for log intake. Default is 10518 | DD_API_KEY | API key for Datadog integration +| DD_APP_KEY | Application key for Datadog Cost Management integration. Required along with DD_API_KEY for cost metrics | DD_SITE | Site URL for Datadog (e.g., datadoghq.com) | DD_SOURCE | Source identifier for Datadog logs | DD_TRACER_STREAMING_CHUNK_YIELD_RESOURCE | Resource name for Datadog tracing of streaming chunk yields. Default is "streaming.chunk.yield" | DD_ENV | Environment identifier for Datadog logs. Only supported for `datadog_llm_observability` callback | DD_SERVICE | Service identifier for Datadog logs. Defaults to "litellm-server" | DD_VERSION | Version identifier for Datadog logs. Defaults to "unknown" +| DATADOG_MOCK | Enable mock mode for Datadog integration testing. When set to true, intercepts Datadog API calls and returns mock responses without making actual network calls. Default is false +| DATADOG_MOCK_LATENCY_MS | Mock latency in milliseconds for Datadog API calls when mock mode is enabled. Simulates network round-trip time. Default is 100ms | DEBUG_OTEL | Enable debug mode for OpenTelemetry | DEFAULT_ALLOWED_FAILS | Maximum failures allowed before cooling down a model. Default is 3 | DEFAULT_A2A_AGENT_TIMEOUT | Default timeout in seconds for A2A (Agent-to-Agent) protocol requests. Default is 6000 @@ -538,6 +545,9 @@ router_settings: | DEFAULT_MAX_TOKENS | Default maximum tokens for LLM calls. Default is 4096 | DEFAULT_MAX_TOKENS_FOR_TRITON | Default maximum tokens for Triton models. Default is 2000 | DEFAULT_MAX_REDIS_BATCH_CACHE_SIZE | Default maximum size for redis batch cache. Default is 1000 +| DEFAULT_MCP_SEMANTIC_FILTER_EMBEDDING_MODEL | Default embedding model for MCP semantic tool filtering. Default is "text-embedding-3-small" +| DEFAULT_MCP_SEMANTIC_FILTER_SIMILARITY_THRESHOLD | Default similarity threshold for MCP semantic tool filtering. Default is 0.3 +| DEFAULT_MCP_SEMANTIC_FILTER_TOP_K | Default number of top results to return for MCP semantic tool filtering. Default is 10 | DEFAULT_MOCK_RESPONSE_COMPLETION_TOKEN_COUNT | Default token count for mock response completions. Default is 20 | DEFAULT_MOCK_RESPONSE_PROMPT_TOKEN_COUNT | Default token count for mock response prompts. Default is 10 | DEFAULT_MODEL_CREATED_AT_TIME | Default creation timestamp for models. Default is 1677610602 @@ -638,6 +648,10 @@ router_settings: | GENERIC_USERINFO_ENDPOINT | Endpoint to fetch user information in generic OAuth | GENERIC_LOGGER_ENDPOINT | Endpoint URL for the Generic Logger callback to send logs to | GENERIC_LOGGER_HEADERS | JSON string of headers to include in Generic Logger callback requests +| GENERIC_ROLE_MAPPINGS_DEFAULT_ROLE | Default LiteLLM role to assign when no role mapping matches in generic SSO. Used with GENERIC_ROLE_MAPPINGS_ROLES +| GENERIC_ROLE_MAPPINGS_GROUP_CLAIM | The claim/attribute name in the SSO token that contains the user's groups. Used for role mapping +| GENERIC_ROLE_MAPPINGS_ROLES | Python dict string mapping LiteLLM roles to SSO group names. Example: `{"proxy_admin": ["admin-group"], "internal_user": ["users"]}` +| GENERIC_USER_ROLE_MAPPINGS | Alternative to GENERIC_ROLE_MAPPINGS_ROLES for configuring user role mappings from SSO | GEMINI_API_BASE | Base URL for Gemini API. Default is https://generativelanguage.googleapis.com | GALILEO_BASE_URL | Base URL for Galileo platform | GALILEO_PASSWORD | Password for Galileo authentication @@ -674,6 +688,8 @@ router_settings: | HCP_VAULT_CERT_ROLE | Role for [Hashicorp Vault Secret Manager Auth](../secret.md#hashicorp-vault) | HELICONE_API_KEY | API key for Helicone service | HELICONE_API_BASE | Base URL for Helicone service, defaults to `https://api.helicone.ai` +| HELICONE_MOCK | Enable mock mode for Helicone integration testing. When set to true, intercepts Helicone API calls and returns mock responses without making actual network calls. Default is false +| HELICONE_MOCK_LATENCY_MS | Mock latency in milliseconds for Helicone API calls when mock mode is enabled. Simulates network round-trip time. Default is 100ms | HOSTNAME | Hostname for the server, this will be [emitted to `datadog` logs](https://docs.litellm.ai/docs/proxy/logging#datadog) | HOURS_IN_A_DAY | Hours in a day for calculation purposes. Default is 24 | HIDDENLAYER_API_BASE | Base URL for HiddenLayer API. Defaults to `https://api.hiddenlayer.ai` @@ -712,6 +728,8 @@ router_settings: | LANGSMITH_PROJECT | Project name for Langsmith integration | LANGSMITH_SAMPLING_RATE | Sampling rate for Langsmith logging | LANGSMITH_TENANT_ID | Tenant ID for Langsmith multi-tenant deployments +| LANGSMITH_MOCK | Enable mock mode for Langsmith integration testing. When set to true, intercepts Langsmith API calls and returns mock responses without making actual network calls. Default is false +| LANGSMITH_MOCK_LATENCY_MS | Mock latency in milliseconds for Langsmith API calls when mock mode is enabled. Simulates network round-trip time. Default is 100ms | LANGTRACE_API_KEY | API key for Langtrace service | LASSO_API_BASE | Base URL for Lasso API | LASSO_API_KEY | API key for Lasso service @@ -723,8 +741,10 @@ router_settings: | LITERAL_API_URL | API URL for Literal service | LITERAL_BATCH_SIZE | Batch size for Literal operations | LITELLM_ANTHROPIC_DISABLE_URL_SUFFIX | Disable automatic URL suffix appending for Anthropic API base URLs. When set to `true`, prevents LiteLLM from automatically adding `/v1/messages` or `/v1/complete` to custom Anthropic API endpoints +| LITELLM_CLI_JWT_EXPIRATION_HOURS | Expiration time in hours for CLI-generated JWT tokens. Default is 24 hours | LITELLM_DD_AGENT_HOST | Hostname or IP of DataDog agent for LiteLLM-specific logging. When set, logs are sent to agent instead of direct API | LITELLM_DD_AGENT_PORT | Port of DataDog agent for LiteLLM-specific log intake. Default is 10518 +| LITELLM_DD_LLM_OBS_PORT | Port for Datadog LLM Observability agent. Default is 8126 | LITELLM_DONT_SHOW_FEEDBACK_BOX | Flag to hide feedback box in LiteLLM UI | LITELLM_DROP_PARAMS | Parameters to drop in LiteLLM requests | LITELLM_MODIFY_PARAMS | Parameters to modify in LiteLLM requests @@ -785,6 +805,7 @@ router_settings: | MAXIMUM_TRACEBACK_LINES_TO_LOG | Maximum number of lines to log in traceback in LiteLLM Logs UI. Default is 100 | MAX_RETRY_DELAY | Maximum delay in seconds for retrying requests. Default is 8.0 | MAX_LANGFUSE_INITIALIZED_CLIENTS | Maximum number of Langfuse clients to initialize on proxy. Default is 50. This is set since langfuse initializes 1 thread everytime a client is initialized. We've had an incident in the past where we reached 100% cpu utilization because Langfuse was initialized several times. +| MAX_MCP_SEMANTIC_FILTER_TOOLS_HEADER_LENGTH | Maximum header length for MCP semantic filter tools. Default is 150 | MIN_NON_ZERO_TEMPERATURE | Minimum non-zero temperature value. Default is 0.0001 | MINIMUM_PROMPT_CACHE_TOKEN_COUNT | Minimum token count for caching a prompt. Default is 1024 | MISTRAL_API_BASE | Base URL for Mistral API. Default is https://api.mistral.ai @@ -820,6 +841,7 @@ router_settings: | OPENMETER_EVENT_TYPE | Type of events sent to OpenMeter | ONYX_API_BASE | Base URL for Onyx Security AI Guard service (defaults to https://ai-guard.onyx.security) | ONYX_API_KEY | API key for Onyx Security AI Guard service +| ONYX_TIMEOUT | Timeout in seconds for Onyx Guard server requests. Default is 10 | OTEL_ENDPOINT | OpenTelemetry endpoint for traces | OTEL_EXPORTER_OTLP_ENDPOINT | OpenTelemetry endpoint for traces | OTEL_ENVIRONMENT_NAME | Environment name for OpenTelemetry @@ -843,6 +865,8 @@ router_settings: | POD_NAME | Pod name for the server, this will be [emitted to `datadog` logs](https://docs.litellm.ai/docs/proxy/logging#datadog) as `POD_NAME` | POSTHOG_API_KEY | API key for PostHog analytics integration | POSTHOG_API_URL | Base URL for PostHog API (defaults to https://us.i.posthog.com) +| POSTHOG_MOCK | Enable mock mode for PostHog integration testing. When set to true, intercepts PostHog API calls and returns mock responses without making actual network calls. Default is false +| POSTHOG_MOCK_LATENCY_MS | Mock latency in milliseconds for PostHog API calls when mock mode is enabled. Simulates network round-trip time. Default is 100ms | PREDIBASE_API_BASE | Base URL for Predibase API | PRESIDIO_ANALYZER_API_BASE | Base URL for Presidio Analyzer service | PRESIDIO_ANONYMIZER_API_BASE | Base URL for Presidio Anonymizer service @@ -880,6 +904,8 @@ router_settings: | ROUTER_MAX_FALLBACKS | Maximum number of fallbacks for router. Default is 5 | RUNWAYML_DEFAULT_API_VERSION | Default API version for RunwayML service. Default is "2024-11-06" | RUNWAYML_POLLING_TIMEOUT | Timeout in seconds for RunwayML image generation polling. Default is 600 (10 minutes) +| S3_VECTORS_DEFAULT_DIMENSION | Default vector dimension for S3 Vectors RAG ingestion. Default is 1024 +| S3_VECTORS_DEFAULT_DISTANCE_METRIC | Default distance metric for S3 Vectors RAG ingestion. Options: "cosine", "euclidean". Default is "cosine" | SECRET_MANAGER_REFRESH_INTERVAL | Refresh interval in seconds for secret manager. Default is 86400 (24 hours) | SEPARATE_HEALTH_APP | If set to '1', runs health endpoints on a separate ASGI app and port. Default: '0'. | SEPARATE_HEALTH_PORT | Port for the separate health endpoints app. Only used if SEPARATE_HEALTH_APP=1. Default: 4001. diff --git a/docs/my-website/docs/proxy/custom_pricing.md b/docs/my-website/docs/proxy/custom_pricing.md index 8f4a4c450f5..b61da85bb1d 100644 --- a/docs/my-website/docs/proxy/custom_pricing.md +++ b/docs/my-website/docs/proxy/custom_pricing.md @@ -9,6 +9,7 @@ LiteLLM provides flexible cost tracking and pricing customization for all LLM pr - **Custom Pricing** - Override default model costs or set pricing for custom models - **Cost Per Token** - Track costs based on input/output tokens (most common) - **Cost Per Second** - Track costs based on runtime (e.g., Sagemaker) +- **Zero-Cost Models** - Bypass budget checks for free/on-premises models by setting costs to 0 - **[Provider Discounts](./provider_discounts.md)** - Apply percentage-based discounts to specific providers - **[Provider Margins](./provider_margins.md)** - Add fees/margins to LLM costs for internal billing - **Base Model Mapping** - Ensure accurate cost tracking for Azure deployments @@ -106,6 +107,51 @@ There are other keys you can use to specify costs for different scenarios and mo These keys evolve based on how new models handle multimodality. The latest version can be found at [https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json). +## Zero-Cost Models (Bypass Budget Checks) + +**Use Case**: You have on-premises or free models that should be accessible even when users exceed their budget limits. + +**Solution** āœ…: Set both `input_cost_per_token` and `output_cost_per_token` to `0` (explicitly) to bypass all budget checks for that model. + +:::info + +When a model is configured with zero cost, LiteLLM will automatically skip ALL budget checks (user, team, team member, end-user, organization, and global proxy budget) for requests to that model. + +**Important**: Both costs must be **explicitly set to 0**. If costs are `null` or undefined, the model will be treated as having cost and budget checks will apply. + +::: + +### Configuration Example + +```yaml +model_list: + # On-premises model - free to use + - model_name: on-prem-llama + litellm_params: + model: ollama/llama3 + api_base: http://localhost:11434 + model_info: + input_cost_per_token: 0 # šŸ‘ˆ Explicitly set to 0 + output_cost_per_token: 0 # šŸ‘ˆ Explicitly set to 0 + + # Paid cloud model - budget checks apply + - model_name: gpt-4 + litellm_params: + model: gpt-4 + api_key: os.environ/OPENAI_API_KEY + # No model_info - uses default pricing from cost map +``` + +### Behavior + +With the above configuration: + +- **User over budget** → Can still use `on-prem-llama` āœ…, but blocked from `gpt-4` āŒ +- **Team over budget** → Can still use `on-prem-llama` āœ…, but blocked from `gpt-4` āŒ +- **End-user over budget** → Can still use `on-prem-llama` āœ…, but blocked from `gpt-4` āŒ + +This ensures your free/on-premises models remain accessible regardless of budget constraints, while paid models are still properly governed. + ## Set 'base_model' for Cost Tracking (e.g. Azure deployments) **Problem**: Azure returns `gpt-4` in the response when `azure/gpt-4-1106-preview` is used. This leads to inaccurate cost tracking diff --git a/docs/my-website/docs/proxy/embedding.md b/docs/my-website/docs/proxy/embedding.md index 2adaaa24735..0e7c2d55c44 100644 --- a/docs/my-website/docs/proxy/embedding.md +++ b/docs/my-website/docs/proxy/embedding.md @@ -6,6 +6,16 @@ import TabItem from '@theme/TabItem'; See supported Embedding Providers & Models [here](https://docs.litellm.ai/docs/embedding/supported_embedding) +## Supported Input Formats + +The `/v1/embeddings` endpoint follows the [OpenAI embeddings API specification](https://platform.openai.com/docs/api-reference/embeddings/create). The following input formats are supported: + +| Format | Example | +|--------|---------| +| String | `"input": "Hello"` | +| Array of strings | `"input": ["Hello", "World"]` | +| Array of tokens (integers) | `"input": [1234, 5678, 9012]` | +| Array of token arrays | `"input": [[1234, 5678], [9012, 3456]]` | ## Quick start Here's how to route between GPT-J embedding (sagemaker endpoint), Amazon Titan embedding (Bedrock) and Azure OpenAI embedding on the proxy server: diff --git a/docs/my-website/docs/proxy/guardrails/custom_code_guardrail.md b/docs/my-website/docs/proxy/guardrails/custom_code_guardrail.md new file mode 100644 index 00000000000..cb246144497 --- /dev/null +++ b/docs/my-website/docs/proxy/guardrails/custom_code_guardrail.md @@ -0,0 +1,278 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Custom Code Guardrail + +Write custom guardrail logic using Python-like code that runs in a sandboxed environment. + +## Quick Start + +### 1. Define the guardrail in config + +```yaml +model_list: + - model_name: gpt-4 + litellm_params: + model: gpt-4 + api_key: os.environ/OPENAI_API_KEY + +guardrails: + - guardrail_name: block-ssn + litellm_params: + guardrail: custom_code + mode: pre_call + custom_code: | + def apply_guardrail(inputs, request_data, input_type): + for text in inputs["texts"]: + if regex_match(text, r"\d{3}-\d{2}-\d{4}"): + return block("SSN detected") + return allow() +``` + +### 2. Start proxy + +```bash +litellm --config config.yaml +``` + +### 3. Test + +```bash +curl -X POST http://localhost:4000/chat/completions \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "gpt-4", + "messages": [{"role": "user", "content": "My SSN is 123-45-6789"}], + "guardrails": ["block-ssn"] + }' +``` + +## Configuration + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `guardrail` | string | āœ… | Must be `custom_code` | +| `mode` | string | āœ… | When to run: `pre_call`, `post_call`, `during_call` | +| `custom_code` | string | āœ… | Python-like code with `apply_guardrail` function | +| `default_on` | bool | āŒ | Run on all requests (default: `false`) | + +## Writing Custom Code + +### Function Signature + +Your code must define an `apply_guardrail` function: + +```python +def apply_guardrail(inputs, request_data, input_type): + # inputs: see table below + # request_data: {"model": "...", "user_id": "...", "team_id": "...", "metadata": {...}} + # input_type: "request" or "response" + + return allow() # or block() or modify() +``` + +### `inputs` Parameter + +| Field | Type | Description | +|-------|------|-------------| +| `texts` | `List[str]` | Extracted text from the request/response | +| `images` | `List[str]` | Extracted images (for image guardrails) | +| `tools` | `List[dict]` | Tools sent to the LLM | +| `tool_calls` | `List[dict]` | Tool calls returned from the LLM | +| `structured_messages` | `List[dict]` | Full messages with role info (system/user/assistant) | +| `model` | `str` | The model being used | + +### `request_data` Parameter + +| Field | Type | Description | +|-------|------|-------------| +| `model` | `str` | Model name | +| `user_id` | `str` | User ID from API key | +| `team_id` | `str` | Team ID from API key | +| `end_user_id` | `str` | End user ID | +| `metadata` | `dict` | Request metadata | + +### Return Values + +| Function | Description | +|----------|-------------| +| `allow()` | Let request/response through | +| `block(reason)` | Reject with message | +| `modify(texts=[], images=[], tool_calls=[])` | Transform content | + +## Built-in Primitives + +### Regex + +| Function | Description | +|----------|-------------| +| `regex_match(text, pattern)` | Returns `True` if pattern found | +| `regex_replace(text, pattern, replacement)` | Replace all matches | +| `regex_find_all(text, pattern)` | Return list of matches | + +### JSON + +| Function | Description | +|----------|-------------| +| `json_parse(text)` | Parse JSON string, returns `None` on error | +| `json_stringify(obj)` | Convert to JSON string | +| `json_schema_valid(obj, schema)` | Validate against JSON schema | + +### URL + +| Function | Description | +|----------|-------------| +| `extract_urls(text)` | Extract all URLs from text | +| `is_valid_url(url)` | Check if URL is valid | +| `all_urls_valid(text)` | Check all URLs in text are valid | + +### Code Detection + +| Function | Description | +|----------|-------------| +| `detect_code(text)` | Returns `True` if code detected | +| `detect_code_languages(text)` | Returns list of detected languages | +| `contains_code_language(text, ["sql", "python"])` | Check for specific languages | + +### Text Utilities + +| Function | Description | +|----------|-------------| +| `contains(text, substring)` | Check if substring exists | +| `contains_any(text, [substr1, substr2])` | Check if any substring exists | +| `word_count(text)` | Count words | +| `char_count(text)` | Count characters | +| `lower(text)` / `upper(text)` / `trim(text)` | String transforms | + +## Examples + +### Block PII (SSN) + +```python +def apply_guardrail(inputs, request_data, input_type): + for text in inputs["texts"]: + if regex_match(text, r"\d{3}-\d{2}-\d{4}"): + return block("SSN detected") + return allow() +``` + +### Redact Email Addresses + +```python +def apply_guardrail(inputs, request_data, input_type): + pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" + modified = [] + for text in inputs["texts"]: + modified.append(regex_replace(text, pattern, "[EMAIL REDACTED]")) + return modify(texts=modified) +``` + +### Block SQL Injection + +```python +def apply_guardrail(inputs, request_data, input_type): + if input_type != "request": + return allow() + for text in inputs["texts"]: + if contains_code_language(text, ["sql"]): + return block("SQL code not allowed") + return allow() +``` + +### Validate JSON Response + +```python +def apply_guardrail(inputs, request_data, input_type): + if input_type != "response": + return allow() + + schema = { + "type": "object", + "required": ["name", "value"] + } + + for text in inputs["texts"]: + obj = json_parse(text) + if obj is None: + return block("Invalid JSON response") + if not json_schema_valid(obj, schema): + return block("Response missing required fields") + return allow() +``` + +### Check URLs in Response + +```python +def apply_guardrail(inputs, request_data, input_type): + if input_type != "response": + return allow() + for text in inputs["texts"]: + if not all_urls_valid(text): + return block("Response contains invalid URLs") + return allow() +``` + +### Combine Multiple Checks + +```python +def apply_guardrail(inputs, request_data, input_type): + modified = [] + + for text in inputs["texts"]: + # Redact SSN + text = regex_replace(text, r"\d{3}-\d{2}-\d{4}", "[SSN]") + # Redact credit cards + text = regex_replace(text, r"\d{16}", "[CARD]") + modified.append(text) + + # Block SQL in requests + if input_type == "request": + for text in inputs["texts"]: + if contains_code_language(text, ["sql"]): + return block("SQL injection blocked") + + return modify(texts=modified) +``` + +## Sandbox Restrictions + +Custom code runs in a restricted environment: + +- āŒ No `import` statements +- āŒ No file I/O +- āŒ No network access +- āŒ No `exec()` or `eval()` +- āœ… Only LiteLLM-provided primitives available + +## Per-Request Usage + +Enable guardrail per request: + +```bash +curl -X POST http://localhost:4000/chat/completions \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "gpt-4", + "messages": [{"role": "user", "content": "Hello"}], + "guardrails": ["block-ssn"] + }' +``` + +## Default On + +Run guardrail on all requests: + +```yaml +litellm_settings: + guardrails: + - guardrail_name: block-ssn + litellm_params: + guardrail: custom_code + mode: pre_call + default_on: true + custom_code: | + def apply_guardrail(inputs, request_data, input_type): + ... +``` diff --git a/docs/my-website/docs/proxy/guardrails/grayswan.md b/docs/my-website/docs/proxy/guardrails/grayswan.md index d6efaf15504..6c0ccbc293d 100644 --- a/docs/my-website/docs/proxy/guardrails/grayswan.md +++ b/docs/my-website/docs/proxy/guardrails/grayswan.md @@ -13,20 +13,26 @@ Cygnal returns a `violation` score between `0` and `1` (higher means more likely ### 1. Obtain Credentials -1. Create a Gray Swan account and generate a Cygnal API key. +1. Log in to our Gray Swan platform and generate a Cygnal API key. + + For existing customers, you should already have access to our [platform](https://platform.grayswan.ai). + + For new users, please register at this [page](https://hubs.ly/Q03-sX1J0) and we are more than happy to give you an onboarding! + + 2. Configure environment variables for the LiteLLM proxy host: -```bash -export GRAYSWAN_API_KEY="your-grayswan-key" -export GRAYSWAN_API_BASE="https://api.grayswan.ai" -``` + ```bash + export GRAYSWAN_API_KEY="your-grayswan-key" + export GRAYSWAN_API_BASE="https://api.grayswan.ai" + ``` ### 2. Configure `config.yaml` -Add a guardrail entry that references the Gray Swan integration. Below is a balanced example that monitors both input and output but only blocks once the violation score reaches the configured threshold. +Add a guardrail entry that references the Gray Swan integration. Below is our recommmended settings. ```yaml -model_list: +model_list: # this part is a standard litellm configuration for reference - model_name: openai/gpt-4.1-mini litellm_params: model: openai/gpt-4.1-mini @@ -40,13 +46,14 @@ guardrails: api_key: os.environ/GRAYSWAN_API_KEY api_base: os.environ/GRAYSWAN_API_BASE # optional optional_params: - on_flagged_action: monitor # or "block" + on_flagged_action: passthrough # or "block" or "monitor" violation_threshold: 0.5 # score >= threshold is flagged reasoning_mode: hybrid # off | hybrid | thinking - categories: - safety: "Detect jailbreaks and policy violations" - policy_id: "your-cygnal-policy-id" + policy_id: "your-cygnal-policy-id" # Optional: Your Cygnal policy ID. Defaults to a content safety policy if empty. + streaming_end_of_stream_only: true # For streaming API, only send the assembled message to Cygnal (post_call only). Defaults to false. default_on: true + guardrail_timeout: 30 # Defaults to 30 seconds. Change accordingly. + fail_open: true # Defaults to true; set to false to propagate guardrail errors. general_settings: master_key: "your-litellm-master-key" @@ -65,13 +72,13 @@ litellm --config config.yaml --port 4000 ## Choosing Guardrail Modes -Gray Swan can run during `pre_call`, `during_call`, and `post_call` stages. Combine modes based on your latency and coverage requirements. +Gray Swan can run during `pre_call`, `during_call`, and `post_call` stages. Combine modes based on your latency and coverage requirements. | Mode | When it Runs | Protects | Typical Use Case | |--------------|-------------------|-----------------------|------------------| | `pre_call` | Before LLM call | User input only | Block prompt injection before it reaches the model | | `during_call`| Parallel to call | User input only | Low-latency monitoring without blocking | -| `post_call` | After response | Full conversation | Scan output for policy violations, leaked secrets, or IPI | +| `post_call` | After response | Model Outputs | Scan output for policy violations, leaked secrets, or IPI | When using `during_call` with `on_flagged_action: block` or `on_flagged_action: passthrough`: @@ -81,87 +88,110 @@ When using `during_call` with `on_flagged_action: block` or `on_flagged_action: - The guardrail exception prevents the response from reaching the user, but **does not cancel the running LLM task** - This means you pay full LLM costs while returning an error/passthrough message to the user -**Recommendation:** For cost-sensitive applications, use `pre_call` and `post_call` instead of `during_call` for blocking or passthrough modes. Reserve `during_call` for `monitor` mode where you want low-latency logging without impacting the user experience. +**Recommendation:** Use `pre_call` and `post_call` instead of `during_call` for `passthrough` (or `block`) `on_flagged_action` (see our recommended configuration above). Reserve `during_call` for `monitor` mode ONLY when you want low-latency logging without impacting the user experience. - - +--- -```yaml -guardrails: - - guardrail_name: "cygnal-monitor-only" - litellm_params: - guardrail: grayswan - mode: "during_call" - api_key: os.environ/GRAYSWAN_API_KEY - optional_params: - on_flagged_action: monitor - violation_threshold: 0.6 - default_on: true +## Work with Claude Code + +Follow the official litellm [guide](https://docs.litellm.ai/docs/tutorials/claude_responses_api) on setting up Claude Code with litellm, with the guardrail part mentioned above added to your litellm configuration. Cygnal natively supports coding agent policies defense. Define your own policy or use the provided coding policies on the platform. The example config we show above is also the recommended setup for Claude Code (with the `policy_id` replaced with an appropriate one). + +--- + +## Per-request overrides via `extra_body` + +You can override parts of the Gray Swan guardrail configuration on a per-request basis by passing `litellm_metadata.guardrails[*].grayswan.extra_body`. + +`extra_body` is merged into the Cygnal request body and takes precedence over specific fields from `config.yaml`, which are `policy_id`, `violation_threshold`, and `reasoning_mode`. + +If you include a `metadata` field inside `extra_body`, it is forwarded to the Cygnal API as-is under the request body's `metadata` field. + +Example: + +```bash +curl -X POST "http://0.0.0.0:4000/v1/messages?beta=true" \ + -H "Authorization: Bearer token" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "openrouter/anthropic/claude-sonnet-4.5", + "messages": [{"role": "user", "content": "hello"}], + "litellm_metadata": { + "guardrails": [ + { + "cygnal-monitor": { + "extra_body": { + "policy_id": "specific policy id you want to use", + "metadata": { + "user": "health-check" + } + } + } + } + ] + } + }' ``` -Best for visibility without blocking. Alerts are logged via LiteLLM’s standard logging callbacks. +OpenAI client: - - +```python +from openai import OpenAI -```yaml -guardrails: - - guardrail_name: "cygnal-block-input" - litellm_params: - guardrail: grayswan - mode: "pre_call" - api_key: os.environ/GRAYSWAN_API_KEY - optional_params: - on_flagged_action: block - violation_threshold: 0.4 - categories: - pii: "Detect sensitive data" - default_on: true +client = OpenAI(api_key="anything", base_url="http://0.0.0.0:4000") + +resp = client.responses.create( + model="openrouter/anthropic/claude-sonnet-4.5", + input="hello", + extra_body={ + "litellm_metadata": { + "guardrails": [ + { + "cygnal-monitor": { + "extra_body": { + "policy_id": "69038214e5cdb6befc5e991e", + "metadata": {"trace_id": "trace-123"}, + } + } + } + ] + } + }, +) ``` -Stops malicious or sensitive prompts before any tokens are generated. +Anthropic client: - - +```python +from anthropic import Anthropic -```yaml -guardrails: - - guardrail_name: "cygnal-full-coverage" - litellm_params: - guardrail: grayswan - mode: [pre_call, post_call] - api_key: os.environ/GRAYSWAN_API_KEY - optional_params: - on_flagged_action: block - violation_threshold: 0.5 - reasoning_mode: thinking - policy_id: "policy-id-from-grayswan" - default_on: true +client = Anthropic(api_key="anything", base_url="http://0.0.0.0:4000") + +resp = client.messages.create( + model="openrouter/anthropic/claude-sonnet-4.5", + max_tokens=256, + messages=[{"role": "user", "content": "hello"}], + extra_body={ + "litellm_metadata": { + "guardrails": [ + { + "cygnal-monitor": { + "extra_body": { + "policy_id": "69038214e5cdb6befc5e991e", + "metadata": {"trace_id": "trace-123"}, + } + } + } + ] + } + }, +) ``` -Provides the strongest enforcement by inspecting both prompts and responses. +Notes: - - - -```yaml -guardrails: - - guardrail_name: "cygnal-passthrough" - litellm_params: - guardrail: grayswan - mode: [pre_call, post_call] - api_key: os.environ/GRAYSWAN_API_KEY - optional_params: - on_flagged_action: passthrough - violation_threshold: 0.5 - default_on: true -``` - -Allows requests to proceed without raising a 400 error when content is flagged. Instead of blocking, the model response content is replaced with a detailed violation message including violation score, violated rules, and detection flags (mutation, IPI). **Supported Response Formats:** OpenAI chat/text completions, Anthropic Messages API. Other response types (embeddings, images, etc.) will log a warning and return unchanged. - - - +- The guardrail name (for example, `cygnal-monitor`) must match the `guardrail_name` in `config.yaml`. +- Per-request guardrail overrides may require a premium license, depending on your proxy settings. --- @@ -170,9 +200,14 @@ Allows requests to proceed without raising a 400 error when content is flagged. | Parameter | Type | Description | |---------------------------------------|-----------------|-------------| | `api_key` | string | Gray Swan Cygnal API key. Reads from `GRAYSWAN_API_KEY` if omitted. | +| `api_base` | string | Override for the Gray Swan API base URL. Defaults to `https://api.grayswan.ai` or `GRAYSWAN_API_BASE`. | | `mode` | string or list | Guardrail stages (`pre_call`, `during_call`, `post_call`). | | `optional_params.on_flagged_action` | string | `monitor` (log only), `block` (raise `HTTPException`), or `passthrough` (replace response content with violation message, no 400 error). | -| `.optional_params.violation_threshold`| number (0-1) | Scores at or above this value are considered violations. | +| `optional_params.violation_threshold` | number (0-1) | Scores at or above this value are considered violations. | | `optional_params.reasoning_mode` | string | `off`, `hybrid`, or `thinking`. Enables Cygnal's reasoning capabilities. | | `optional_params.categories` | object | Map of custom category names to descriptions. | | `optional_params.policy_id` | string | Gray Swan policy identifier. | +| `guardrail_timeout` | number | Timeout in seconds for the Cygnal request. Defaults to 30. | +| `fail_open` | boolean | If true, errors contacting Cygnal are logged and the request proceeds; if false, errors propagate. Defaults to treu. | +| `streaming_end_of_stream_only` | boolean | For streaming `post_call`, only send the final assembled response to Cygnal. Defaults to false. | +| `default_on` | boolean | Run the guardrail on every request by default. | diff --git a/docs/my-website/docs/proxy/guardrails/onyx_security.md b/docs/my-website/docs/proxy/guardrails/onyx_security.md index 85b0ba9f830..d240902eb52 100644 --- a/docs/my-website/docs/proxy/guardrails/onyx_security.md +++ b/docs/my-website/docs/proxy/guardrails/onyx_security.md @@ -128,6 +128,7 @@ guardrails: mode: ["pre_call", "post_call", "during_call"] # Run at multiple stages api_key: os.environ/ONYX_API_KEY api_base: os.environ/ONYX_API_BASE + timeout: 10.0 # Optional, defaults to 10 seconds ``` ### Required Parameters @@ -137,6 +138,7 @@ guardrails: ### Optional Parameters - **`api_base`**: Onyx API base URL (defaults to `https://ai-guard.onyx.security`) +- **`timeout`**: Request timeout in seconds (defaults to `10.0`) ## Environment Variables @@ -145,4 +147,5 @@ You can set these environment variables instead of hardcoding values in your con ```shell export ONYX_API_KEY="your-api-key-here" export ONYX_API_BASE="https://ai-guard.onyx.security" # Optional +export ONYX_TIMEOUT=10 # Optional, timeout in seconds ``` diff --git a/docs/my-website/docs/proxy/guardrails/quick_start.md b/docs/my-website/docs/proxy/guardrails/quick_start.md index cb6379d49f4..ddb215fcb66 100644 --- a/docs/my-website/docs/proxy/guardrails/quick_start.md +++ b/docs/my-website/docs/proxy/guardrails/quick_start.md @@ -405,14 +405,10 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \ ## **Proxy Admin Controls** -### ✨ Monitoring Guardrails +### Monitoring Guardrails Monitor which guardrails were executed and whether they passed or failed. e.g. guardrail going rogue and failing requests we don't intend to fail -:::info - -✨ This is an Enterprise only feature [Get a free trial](https://www.litellm.ai/enterprise#trial) - ::: #### Setup diff --git a/docs/my-website/docs/proxy/load_balancing.md b/docs/my-website/docs/proxy/load_balancing.md index 42f6ef1aa51..186307d6498 100644 --- a/docs/my-website/docs/proxy/load_balancing.md +++ b/docs/my-website/docs/proxy/load_balancing.md @@ -69,6 +69,67 @@ router_settings: redis_port: 1992 ``` +## Enforce Model Rate Limits + +Strictly enforce RPM/TPM limits set on deployments. When limits are exceeded, requests are blocked **before** reaching the LLM provider with a `429 Too Many Requests` error. + +:::info +By default, `rpm` and `tpm` values are only used for **routing decisions** (picking deployments with capacity). With `enforce_model_rate_limits`, they become **hard limits**. +::: + +### Quick Start + +```yaml +model_list: + - model_name: gpt-4 + litellm_params: + model: openai/gpt-4 + api_key: os.environ/OPENAI_API_KEY + rpm: 60 # 60 requests per minute + tpm: 90000 # 90k tokens per minute + +router_settings: + optional_pre_call_checks: + - enforce_model_rate_limits # šŸ‘ˆ Enables strict enforcement +``` + +### How It Works + +| Limit Type | Enforcement | Accuracy | +|------------|-------------|----------| +| **RPM** | Hard limit - blocked at exact threshold | 100% accurate | +| **TPM** | Best-effort - may slightly exceed | Blocked when already over limit | + +**Why TPM is best-effort:** Token count is unknown until the LLM responds. TPM is checked before each request (blocks if already over), and tracked after (adds actual tokens used). + +### Error Response + +```json +{ + "error": { + "message": "Model rate limit exceeded. RPM limit=60, current usage=60", + "type": "rate_limit_error", + "code": 429 + } +} +``` + +Response includes `retry-after: 60` header. + +### Multi-Instance Deployment + +For multiple LiteLLM proxy instances, add Redis to share rate limit state: + +```yaml +router_settings: + optional_pre_call_checks: + - enforce_model_rate_limits + redis_host: redis.example.com + redis_port: 6379 + redis_password: your-password +``` + + :::info Detailed information about [routing strategies can be found here](../routing) ::: diff --git a/docs/my-website/docs/proxy/prometheus.md b/docs/my-website/docs/proxy/prometheus.md index cd2b3b68f37..93a0675f097 100644 --- a/docs/my-website/docs/proxy/prometheus.md +++ b/docs/my-website/docs/proxy/prometheus.md @@ -121,8 +121,8 @@ Use this to track overall LiteLLM Proxy usage. | Metric Name | Description | |----------------------|--------------------------------------| -| `litellm_proxy_failed_requests_metric` | Total number of failed responses from proxy - the client did not get a success response from litellm proxy. Labels: `"end_user", "hashed_api_key", "api_key_alias", "requested_model", "team", "team_alias", "user", "exception_status", "exception_class", "route"` | -| `litellm_proxy_total_requests_metric` | Total number of requests made to the proxy server - track number of client side requests. Labels: `"end_user", "hashed_api_key", "api_key_alias", "requested_model", "team", "team_alias", "user", "status_code", "user_email", "route"` | +| `litellm_proxy_failed_requests_metric` | Total number of failed responses from proxy - the client did not get a success response from litellm proxy. Labels: `"end_user", "hashed_api_key", "api_key_alias", "requested_model", "team", "team_alias", "user", "user_email", "exception_status", "exception_class", "route", "model_id"` | +| `litellm_proxy_total_requests_metric` | Total number of requests made to the proxy server - track number of client side requests. Labels: `"end_user", "hashed_api_key", "api_key_alias", "requested_model", "team", "team_alias", "user", "status_code", "user_email", "route", "model_id"` | ### Callback Logging Metrics @@ -130,7 +130,12 @@ Monitor failures while shipping logs to downstream callbacks like `s3_v3` cold s | Metric Name | Description | |----------------------|--------------------------------------| -| `litellm_callback_logging_failures_metric` | Total number of failed attempts to emit logs to a configured callback. Labels: `"callback_name"`. Use this to alert on callback delivery issues such as repeated failures when writing to `s3_v3`. | +| `litellm_callback_logging_failures_metric` | Total number of failed attempts to emit logs to a configured callback. Labels: `"callback_name"`. Use this to alert on callback delivery issues such as repeated failures when writing to `s3_v3`, `langfuse`, or `langfuse_otel` and other otel providers | + +**Supported Callbacks:** +- `S3Logger` - S3 v2 cold storage failures +- `langfuse` - Langfuse logging failures +- `otel` - OpenTelemetry logging failures ## LLM Provider Metrics @@ -191,10 +196,10 @@ Use this for LLM API Error monitoring and tracking remaining rate limits and tok | Metric Name | Description | |----------------------|--------------------------------------| -| `litellm_request_total_latency_metric` | Total latency (seconds) for a request to LiteLLM Proxy Server - tracked for labels "end_user", "hashed_api_key", "api_key_alias", "requested_model", "team", "team_alias", "user", "model" | +| `litellm_request_total_latency_metric` | Total latency (seconds) for a request to LiteLLM Proxy Server - tracked for labels "end_user", "hashed_api_key", "api_key_alias", "requested_model", "team", "team_alias", "user", "model", "model_id" | | `litellm_overhead_latency_metric` | Latency overhead (seconds) added by LiteLLM processing - tracked for labels "model_group", "api_provider", "api_base", "litellm_model_name", "hashed_api_key", "api_key_alias" | | `litellm_llm_api_latency_metric` | Latency (seconds) for just the LLM API call - tracked for labels "model", "hashed_api_key", "api_key_alias", "team", "team_alias", "requested_model", "end_user", "user" | -| `litellm_llm_api_time_to_first_token_metric` | Time to first token for LLM API call - tracked for labels `model`, `hashed_api_key`, `api_key_alias`, `team`, `team_alias` [Note: only emitted for streaming requests] | +| `litellm_llm_api_time_to_first_token_metric` | Time to first token for LLM API call - tracked for labels `model`, `hashed_api_key`, `api_key_alias`, `team`, `team_alias`, `requested_model`, `end_user`, `user`, `model_id` [Note: only emitted for streaming requests] | ## Tracking `end_user` on Prometheus diff --git a/docs/my-website/docs/proxy/request_tags.md b/docs/my-website/docs/proxy/request_tags.md new file mode 100644 index 00000000000..c78c48229b4 --- /dev/null +++ b/docs/my-website/docs/proxy/request_tags.md @@ -0,0 +1,58 @@ +# Request Tags for Spend Tracking + +Add tags to model deployments to track spend by environment, AWS account, or any custom label. + +Tags appear in the `request_tags` field of LiteLLM spend logs. + +## Config Setup + +Set tags on model deployments in `config.yaml`: + +```yaml title="config.yaml" +model_list: + - model_name: gpt-4 + litellm_params: + model: azure/gpt-4-prod + api_key: os.environ/AZURE_PROD_API_KEY + api_base: https://prod.openai.azure.com/ + tags: ["AWS_IAM_PROD"] # šŸ‘ˆ Tag for production + + - model_name: gpt-4-dev + litellm_params: + model: azure/gpt-4-dev + api_key: os.environ/AZURE_DEV_API_KEY + api_base: https://dev.openai.azure.com/ + tags: ["AWS_IAM_DEV"] # šŸ‘ˆ Tag for development +``` + +## Make Request + +Requests just specify the model - tags are automatically applied: + +```bash +curl -X POST 'http://0.0.0.0:4000/chat/completions' \ + -H 'Authorization: Bearer sk-1234' \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "gpt-4", + "messages": [{"role": "user", "content": "Hello"}] + }' +``` + +## Spend Logs + +The tag from the model config appears in `LiteLLM_SpendLogs`: + +```json +{ + "request_id": "chatcmpl-abc123", + "request_tags": ["AWS_IAM_PROD"], + "spend": 0.002, + "model": "gpt-4" +} +``` + +## Related + +- [Spend Tracking Overview](cost_tracking.md) +- [Tag Budgets](tag_budgets.md) - Set budget limits per tag diff --git a/docs/my-website/docs/proxy/ui/page_visibility.md b/docs/my-website/docs/proxy/ui/page_visibility.md new file mode 100644 index 00000000000..06b06f33219 --- /dev/null +++ b/docs/my-website/docs/proxy/ui/page_visibility.md @@ -0,0 +1,121 @@ +import Image from '@theme/IdealImage'; + +# Control Page Visibility for Internal Users + +Configure which navigation tabs and pages are visible to internal users (non-admin developers) in the LiteLLM UI. + +Use this feature to simplify the UI and control which pages your internal users/developers can see when signing in. + +## Overview + +By default, all pages accessible to internal users are visible in the navigation sidebar. The page visibility control allows admins to restrict which pages internal users can see, creating a more focused and streamlined experience. + + +## Configure Page Visibility + +### 1. Navigate to Settings + +Click the **Settings** icon in the sidebar. + +![Navigate to Settings](https://colony-recorder.s3.amazonaws.com/files/2026-01-28/cbb6f272-ab18-4996-b57d-7ed4aad721ea/ascreenshot_ab80f3175b1a41b0bdabdd2cd3980573_text_export.jpeg) + +### 2. Go to Admin Settings + +Click **Admin Settings** from the settings menu. + +![Go to Admin Settings](https://colony-recorder.s3.amazonaws.com/files/2026-01-28/e2b327bf-1cfd-4519-a9ce-8a6ecb2de53a/ascreenshot_23bb1577b3f84d22be78e0faa58dee3d_text_export.jpeg) + +### 3. Select UI Settings + +Click **UI Settings** to access the page visibility controls. + +![Select UI Settings](https://colony-recorder.s3.amazonaws.com/files/2026-01-28/fff0366a-4944-457a-8f6a-e22018dde108/ascreenshot_0e268e8651654e75bb9fb40d2ed366a9_text_export.jpeg) + +### 4. Open Page Visibility Configuration + +Click **Configure Page Visibility** to expand the configuration panel. + +![Open Configuration](https://colony-recorder.s3.amazonaws.com/files/2026-01-28/3a4761d6-145a-4afd-8abf-d92744b9ac9f/ascreenshot_23c16eb79c32481887b879d961f1f00a_text_export.jpeg) + +### 5. Select Pages to Make Visible + +Check the boxes for the pages you want internal users to see. Pages are organized by category for easy navigation. + +![Select Pages](https://colony-recorder.s3.amazonaws.com/files/2026-01-28/b9c96b54-6c20-484f-8b0b-3a86decb5717/ascreenshot_3347ade01ebe4ea390bc7b57e53db43f_text_export.jpeg) + +**Available pages include:** +- Virtual Keys +- Playground +- Models + Endpoints +- Agents +- MCP Servers +- Search Tools +- Vector Stores +- Logs +- Teams +- Organizations +- Usage +- Budgets +- And more... + +### 6. Save Your Configuration + +Click **Save Page Visibility Settings** to apply the changes. + +![Save Settings](https://colony-recorder.s3.amazonaws.com/files/2026-01-28/8a215378-44f5-4bb8-b984-06fa2aa03903/ascreenshot_44e7aeebe25a477ba92f73a3ed3df644_text_export.jpeg) + +### 7. Verify Changes + +Internal users will now only see the selected pages in their navigation sidebar. + +![Verify Changes](https://colony-recorder.s3.amazonaws.com/files/2026-01-28/493a7718-b276-40b9-970f-5814054932d9/ascreenshot_ad23b8691f824095ba60256f91ad24f8_text_export.jpeg) + +## Reset to Default + +To restore all pages to internal users: + +1. Open the Page Visibility configuration +2. Click **Reset to Default (All Pages)** +3. Click **Save Page Visibility Settings** + +This will clear the restriction and show all accessible pages to internal users. + +## API Configuration + +You can also configure page visibility programmatically using the API: + +### Get Current Settings + +```bash +curl -X GET 'http://localhost:4000/ui_settings/get' \ + -H 'Authorization: Bearer ' +``` + +### Update Page Visibility + +```bash +curl -X PATCH 'http://localhost:4000/ui_settings/update' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "enabled_ui_pages_internal_users": [ + "api-keys", + "agents", + "mcp-servers", + "logs", + "teams" + ] + }' +``` + +### Clear Page Visibility Restrictions + +```bash +curl -X PATCH 'http://localhost:4000/ui_settings/update' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "enabled_ui_pages_internal_users": null + }' +``` + diff --git a/docs/my-website/docs/proxy/ui_logs.md b/docs/my-website/docs/proxy/ui_logs.md index 61f328011c3..8cfe818ebfd 100644 --- a/docs/my-website/docs/proxy/ui_logs.md +++ b/docs/my-website/docs/proxy/ui_logs.md @@ -25,7 +25,10 @@ View Spend, Token Usage, Key, Team Name for Each Request to LiteLLM ## Tracking - Request / Response Content in Logs Page -If you want to view request and response content on LiteLLM Logs, you need to opt in with this setting +If you want to view request and response content on LiteLLM Logs, you can enable it in either place: + +- **From the UI (no restart):** Use [UI Spend Log Settings](./ui_spend_log_settings.md) — open Logs → Settings → enable "Store Prompts in Spend Logs" → Save. Takes effect immediately and overrides config. +- **From config:** Add this to your `proxy_config.yaml` (requires restart): ```yaml general_settings: @@ -34,6 +37,40 @@ general_settings: +## Tracing Tools + +View which tools were provided and called in your completion requests. + + + +**Example:** Make a completion request with tools: + +```bash +curl -X POST 'http://localhost:4000/chat/completions' \ + -H 'Authorization: Bearer sk-1234' \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "gpt-4", + "messages": [{"role": "user", "content": "What is the weather?"}], + "tools": [ + { + "type": "function", + "function": { + "name": "get_weather", + "description": "Get the current weather", + "parameters": { + "type": "object", + "properties": { + "location": {"type": "string"} + } + } + } + } + ] + }' +``` + +Check the Logs page to see all tools provided and which ones were called. ## Stop storing Error Logs in DB @@ -57,7 +94,10 @@ general_settings: If you're storing spend logs, it might be a good idea to delete them regularly to keep the database fast. -LiteLLM lets you configure this in your `proxy_config.yaml`: +You can set the retention period in either place: + +- **From the UI (no restart):** [UI Spend Log Settings](./ui_spend_log_settings.md) — Logs → Settings → set Retention Period → Save. +- **From config:** Add the following to your `proxy_config.yaml` (requires restart): ```yaml general_settings: diff --git a/docs/my-website/docs/proxy/ui_spend_log_settings.md b/docs/my-website/docs/proxy/ui_spend_log_settings.md new file mode 100644 index 00000000000..5e04974e3a7 --- /dev/null +++ b/docs/my-website/docs/proxy/ui_spend_log_settings.md @@ -0,0 +1,92 @@ +import Image from '@theme/IdealImage'; + +# UI Spend Log Settings + +Configure spend log behavior directly from the Admin UI—no config file edits or proxy restart required. This is especially useful for cloud deployments where updating the config is difficult or requires a long release process. + +## Overview + +Previously, spend log options (such as storing request/response content and retention period) had to be set in `proxy_config.yaml` under `general_settings`. Changing them required editing the config and restarting the proxy, which was a pain point for users-especially in cloud environments—who don't have easy access to the config or whose deployment process makes config updates slow. + + + +**UI Spend Log Settings** lets you: + +- **Store prompts in spend logs** – Enable or disable storing request and response content in the spend logs table (only affects logs created after you change the setting) +- **Set retention period** – Configure how long spend logs are kept before automatic cleanup (e.g. `7d`, `30d`) +- **Apply changes immediately** – No proxy restart needed; settings take effect for new requests as soon as you save + +:::warning UI overrides config +Settings changed in the UI **override** the values in your config file. For example, if `store_prompts_in_spend_logs` is explicitly set to `false` in `general_settings`, turning it on in the UI will still enable storing prompts. Use the UI when you want runtime control without redeploying. +::: + +## Settings You Can Configure + +| Setting | Description | +| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Store Prompts in Spend Logs** | When enabled, request messages and response content are stored for **new** spend logs so you can view them in the Logs UI. Logs created before you enabled this will not have request/response content. When disabled, only metadata (e.g. tokens, cost, model) is stored for new logs. | +| **Retention Period** | Maximum time to keep spend logs before they are automatically deleted (e.g. `7d`, `30d`). Optional; if not set, logs are retained according to your config or default behavior. | + +The same options can be set in config via [general_settings](./config_settings.md#general_settings---reference) (`store_prompts_in_spend_logs`, `maximum_spend_logs_retention_period`). Values set in the UI take precedence. + +## How to Configure Spend Log Settings in the UI + +### 1. Open the Logs page + +Navigate to the Admin UI (e.g. `http://localhost:4000/ui` or your `PROXY_BASE_URL/ui`) and click **Logs**. + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/815f4ab2-4b8c-4dfe-be39-689fd6e12167/ascreenshot_eaaeba1507b441408e0df8bf94bc70cc_text_export.jpeg) + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/815f4ab2-4b8c-4dfe-be39-689fd6e12167/ascreenshot_666628f5e62443688a58b7cee7d7559b_text_export.jpeg) + +### 2. Open Logs settings + +Click the **Settings** (gear) icon on the Logs page to open the spend log settings panel. + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/303077bd-80a0-4f3b-9dc1-4abb90af117f/ascreenshot_63f5dc21a545489ea9266f3bd3dc8455_text_export.jpeg) + +### 3. Enable Store Prompts in Spend Logs (optional) + +Turn on **Store Prompts in Spend Logs** if you want request and response content to be stored for new requests and visible when you open those log entries. This only affects logs created after you enable it; existing logs will not gain request/response content. Leave it off if you only need metadata (tokens, cost, model, etc.). + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/a25d0051-4b34-4270-99d6-6e8ae0d2936a/ascreenshot_374605862aad42c89a98da7bad910f58_text_export.jpeg) + +### 4. Set the retention period (optional) + +Optionally set the **Retention Period** (e.g. `7d`, `30d`) to control how long spend logs are kept before automatic cleanup. Uses the same format as the config option `maximum_spend_logs_retention_period`. + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/87086197-b082-4339-b798-37410f47d9ac/ascreenshot_564da14f492540ae8b0b782cfedceff9_text_export.jpeg) + +### 5. Save settings + +Click **Save Settings**. Changes take effect immediately for new requests; no proxy restart is required. Existing logs are not updated. + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/8cfd82c1-0ff4-4561-a806-33a7998cf0fd/ascreenshot_673f6155b17f45ee9b80fabdfc42a4ee_text_export.jpeg) + +### 6. Verify: view request and response in a log + +After enabling **Store Prompts in Spend Logs**, make a new request through the proxy, then open that log entry (or any other log created after you enabled the setting). The log details view will include the request and response content. Logs that existed before you turned the setting on will not have this content. + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/0fbec553-9a11-4f4f-8a1d-f969bb316c70/ascreenshot_62ecbcea97ea4a4abaa460d76e2cf924_text_export.jpeg) + +![](https://colony-recorder.s3.amazonaws.com/files/2026-01-31/30e7ea4d-2c03-4b96-88a9-eeee565eaf16/ascreenshot_c00ad6aa75b54b4988a1450647a76f6b_text_export.jpeg) + +## Use Cases + +### Cloud and managed deployments + +When the proxy runs in a managed or cloud environment, config may be in a separate repo, require a long release, or be controlled by another team. Using the UI lets you change spend log behavior (e.g. enable prompt storage for debugging or set retention) without going through that process. + +### Quick toggles for debugging + +Temporarily enable **Store Prompts in Spend Logs** to inspect request/response content on new requests when debugging, then turn it off again from the UI without editing config or restarting. Only logs created while the setting was on will contain the content. + +### Retention without redeploying + +Adjust how long spend logs are retained (e.g. shorten to reduce storage or extend for compliance) and have the new retention period and cleanup job take effect immediately. + +## Related Documentation + +- [Getting Started with UI Logs](./ui_logs.md) – Overview of what gets logged and config-based options +- [Config Settings](./config_settings.md) – `store_prompts_in_spend_logs`, `disable_spend_logs`, `maximum_spend_logs_retention_period` in `general_settings` +- [Spend Logs Deletion](./spend_logs_deletion.md) – How retention and cleanup work diff --git a/docs/my-website/docs/rag_ingest.md b/docs/my-website/docs/rag_ingest.md index 1133b85f206..7adc2d70b5b 100644 --- a/docs/my-website/docs/rag_ingest.md +++ b/docs/my-website/docs/rag_ingest.md @@ -5,7 +5,7 @@ All-in-one document ingestion pipeline: **Upload → Chunk → Embed → Vector | Feature | Supported | |---------|-----------| | Logging | Yes | -| Supported Providers | `openai`, `bedrock`, `vertex_ai`, `gemini` | +| Supported Providers | `openai`, `bedrock`, `vertex_ai`, `gemini`, `s3_vectors` | :::tip After ingesting documents, use [/rag/query](./rag_query.md) to search and generate responses with your ingested content. @@ -75,6 +75,31 @@ curl -X POST "http://localhost:4000/v1/rag/ingest" \ }" ``` +### AWS S3 Vectors + +```bash showLineNumbers title="Ingest to S3 Vectors" +curl -X POST "http://localhost:4000/v1/rag/ingest" \ + -H "Authorization: Bearer sk-1234" \ + -H "Content-Type: application/json" \ + -d "{ + \"file\": { + \"filename\": \"document.txt\", + \"content\": \"$(base64 -i document.txt)\", + \"content_type\": \"text/plain\" + }, + \"ingest_options\": { + \"embedding\": { + \"model\": \"text-embedding-3-small\" + }, + \"vector_store\": { + \"custom_llm_provider\": \"s3_vectors\", + \"vector_bucket_name\": \"my-embeddings\", + \"aws_region_name\": \"us-west-2\" + } + } + }" +``` + ## Response ```json @@ -265,6 +290,57 @@ When `vector_store_id` is omitted, LiteLLM automatically creates: 4. Install: `pip install 'google-cloud-aiplatform>=1.60.0'` ::: +### vector_store (AWS S3 Vectors) + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `custom_llm_provider` | string | - | `"s3_vectors"` | +| `vector_bucket_name` | string | **required** | S3 vector bucket name | +| `index_name` | string | auto-create | Vector index name | +| `dimension` | integer | auto-detect | Vector dimension (auto-detected from embedding model) | +| `distance_metric` | string | `cosine` | Distance metric: `cosine` or `euclidean` | +| `non_filterable_metadata_keys` | array | `["source_text"]` | Metadata keys excluded from filtering | +| `aws_region_name` | string | `us-west-2` | AWS region | +| `aws_access_key_id` | string | env | AWS access key | +| `aws_secret_access_key` | string | env | AWS secret key | + +:::info S3 Vectors Auto-Creation +When `index_name` is omitted, LiteLLM automatically creates: +- S3 vector bucket (if it doesn't exist) +- Vector index with auto-detected dimensions from your embedding model + +**Dimension Auto-Detection**: The vector dimension is automatically detected by making a test embedding request to your specified model. No need to manually specify dimensions! + +**Supported Embedding Models**: Works with any LiteLLM-supported embedding model (OpenAI, Cohere, Bedrock, Azure, etc.) +::: + +**Example with auto-detection:** +```json +{ + "embedding": { + "model": "text-embedding-3-small" // Dimension auto-detected as 1536 + }, + "vector_store": { + "custom_llm_provider": "s3_vectors", + "vector_bucket_name": "my-embeddings" + } +} +``` + +**Example with custom embedding provider:** +```json +{ + "embedding": { + "model": "cohere/embed-english-v3.0" // Dimension auto-detected as 1024 + }, + "vector_store": { + "custom_llm_provider": "s3_vectors", + "vector_bucket_name": "my-embeddings", + "distance_metric": "cosine" + } +} +``` + ## Input Examples ### File (Base64) diff --git a/docs/my-website/docs/realtime.md b/docs/my-website/docs/realtime.md index 0b3c823f5db..b191c82c670 100644 --- a/docs/my-website/docs/realtime.md +++ b/docs/my-website/docs/realtime.md @@ -3,13 +3,15 @@ import TabItem from '@theme/TabItem'; # /realtime -Use this to loadbalance across Azure + OpenAI. +Use this to loadbalance across Azure + OpenAI + xAI and more. Supported Providers: - OpenAI - Azure +- xAI ([see full docs](/docs/providers/xai_realtime)) - Google AI Studio (Gemini) - Vertex AI +- Bedrock ## Proxy Usage @@ -45,6 +47,21 @@ model_list: api_key: os.environ/OPENAI_API_KEY ``` + + + +```yaml +model_list: + - model_name: grok-voice-agent + litellm_params: + model: xai/grok-4-1-fast-non-reasoning + api_key: os.environ/XAI_API_KEY + model_info: + mode: realtime +``` + +**[See full xAI Realtime documentation →](/docs/providers/xai_realtime)** + diff --git a/docs/my-website/docs/routing.md b/docs/my-website/docs/routing.md index 47967775e1e..67e7f681147 100644 --- a/docs/my-website/docs/routing.md +++ b/docs/my-website/docs/routing.md @@ -830,6 +830,12 @@ asyncio.run(router_acompletion()) +## Traffic Mirroring / Silent Experiments + +Traffic mirroring allows you to "mimic" production traffic to a secondary (silent) model for evaluation purposes. The silent model's response is gathered in the background and does not affect the latency or result of the primary request. + +[**See detailed guide on A/B Testing - Traffic Mirroring here**](./traffic_mirroring.md) + ## Basic Reliability ### Deployment Ordering (Priority) @@ -1582,11 +1588,13 @@ Get a slack webhook url from https://api.slack.com/messaging/webhooks Initialize an `AlertingConfig` and pass it to `litellm.Router`. The following code will trigger an alert because `api_key=bad-key` which is invalid ```python -from litellm.router import AlertingConfig import litellm +from litellm.router import Router +from litellm.types.router import AlertingConfig import os +import asyncio -router = litellm.Router( +router = Router( model_list=[ { "model_name": "gpt-3.5-turbo", @@ -1597,17 +1605,28 @@ router = litellm.Router( } ], alerting_config= AlertingConfig( - alerting_threshold=10, # threshold for slow / hanging llm responses (in seconds). Defaults to 300 seconds - webhook_url= os.getenv("SLACK_WEBHOOK_URL") # webhook you want to send alerts to + alerting_threshold=10, + webhook_url= "https:/..." ), ) -try: - await router.acompletion( - model="gpt-3.5-turbo", - messages=[{"role": "user", "content": "Hey, how's it going?"}], - ) -except: - pass + +async def main(): + print(f"\n=== Configuration ===") + print(f"Slack logger exists: {router.slack_alerting_logger is not None}") + + try: + await router.acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hey, how's it going?"}], + ) + except Exception as e: + print(f"\n=== Exception caught ===") + print(f"Waiting 10 seconds for alerts to be sent via periodic flush...") + await asyncio.sleep(10) + print(f"\n=== After waiting ===") + print(f"Alert should have been sent to Slack!") + +asyncio.run(main()) ``` ## Track cost for Azure Deployments diff --git a/docs/my-website/docs/traffic_mirroring.md b/docs/my-website/docs/traffic_mirroring.md new file mode 100644 index 00000000000..3bdcb0f1614 --- /dev/null +++ b/docs/my-website/docs/traffic_mirroring.md @@ -0,0 +1,83 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# A/B Testing - Traffic Mirroring + +Traffic mirroring allows you to "mimic" production traffic to a secondary (silent) model for evaluation purposes. The silent model's response is gathered in the background and does not affect the latency or result of the primary request. + +This is useful for: +- Testing a new model's performance on production prompts before switching. +- Comparing costs and latency between different providers. +- Debugging issues by mirroring traffic to a more verbose model. + +## Quick Start + +To enable traffic mirroring, add `silent_model` to the `litellm_params` of a deployment. + + + + +```python +from litellm import Router + +model_list = [ + { + "model_name": "gpt-3.5-turbo", + "litellm_params": { + "model": "azure/chatgpt-v-2", + "api_key": "...", + "silent_model": "gpt-4" # šŸ‘ˆ Mirror traffic to gpt-4 + }, + }, + { + "model_name": "gpt-4", + "litellm_params": { + "model": "openai/gpt-4", + "api_key": "..." + }, + } +] + +router = Router(model_list=model_list) + +# The request to "gpt-3.5-turbo" will trigger a background call to "gpt-4" +response = await router.acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "How does traffic mirroring work?"}] +) +``` + + + + +Add `silent_model` to your `config.yaml`: + +```yaml +model_list: + - model_name: primary-model + litellm_params: + model: azure/gpt-35-turbo + api_key: os.environ/AZURE_API_KEY + silent_model: evaluation-model # šŸ‘ˆ Mirror traffic here + - model_name: evaluation-model + litellm_params: + model: openai/gpt-4o + api_key: os.environ/OPENAI_API_KEY +``` + + + + +## How it works +1. **Request Received**: A request is made to a model group (e.g. `primary-model`). +2. **Deployment Picked**: LiteLLM picks a deployment from the group. +3. **Primary Call**: LiteLLM makes the call to the primary deployment. +4. **Mirroring**: If `silent_model` is present, LiteLLM triggers a background call to that model. + - For **Sync** calls: Uses a shared thread pool. + - For **Async** calls: Uses `asyncio.create_task`. +5. **Isolation**: The background call uses a `deepcopy` of the original request parameters and sets `metadata["is_silent_experiment"] = True`. It also strips out logging IDs to prevent collisions in usage tracking. + +## Key Features +- **Latency Isolation**: The primary request returns as soon as it's ready. The background (silent) call does not block. +- **Unified Logging**: Background calls are processed via the Router, meaning they are automatically logged to your configured observability tools (Langfuse, S3, etc.). +- **Evaluation**: Use the `is_silent_experiment: True` flag in your logs to filter and compare results between the primary and mirrored calls. diff --git a/docs/my-website/docs/troubleshoot/prisma_migrations.md b/docs/my-website/docs/troubleshoot/prisma_migrations.md new file mode 100644 index 00000000000..9d9cb585b2b --- /dev/null +++ b/docs/my-website/docs/troubleshoot/prisma_migrations.md @@ -0,0 +1,113 @@ +# Troubleshooting Prisma Migration Errors + +Common Prisma migration issues encountered when upgrading or downgrading LiteLLM proxy versions, and how to fix them. + +## How Prisma Migrations Work in LiteLLM + +- LiteLLM uses [Prisma](https://www.prisma.io/) to manage its PostgreSQL database schema. +- Migration history is tracked in the `_prisma_migrations` table in your database. +- When LiteLLM starts, it runs `prisma migrate deploy` to apply any new migrations. +- Upgrading LiteLLM applies all migrations added since your last applied version. + +## Common Errors + +### 1. `relation "X" does not exist` + +**Example error:** + +``` +ERROR: relation "LiteLLM_DeletedTeamTable" does not exist +Migration: 20260116142756_update_deleted_keys_teams_table_routing_settings +``` + +**Cause:** This typically happens after a version rollback. The `_prisma_migrations` table still records migrations from the newer version as "applied," but the underlying database tables were modified, dropped, or never fully created. + +**How to fix:** + +#### Step 1 — Delete the failed migration entry and restart + +Remove the problematic migration from the history so it can be re-applied: + +```sql +-- View recent migrations +SELECT migration_name, finished_at, rolled_back_at, logs +FROM "_prisma_migrations" +ORDER BY started_at DESC +LIMIT 10; + +-- Delete the failed migration entry +DELETE FROM "_prisma_migrations" +WHERE migration_name = ''; +``` + +After deleting the entry, restart LiteLLM — it will re-apply the migration on startup. + +#### Step 2 — If that doesn't work, use `prisma db push` + +If deleting the migration entry and restarting doesn't resolve the issue, sync the schema directly: + +```bash +DATABASE_URL="" prisma db push +``` + +This bypasses migration history and forces the database schema to match the Prisma schema. + +--- + +### 2. `New migrations cannot be applied before the error is recovered from` + +**Cause:** A previous migration failed (recorded with an error in `_prisma_migrations`), and Prisma refuses to apply any new migrations until the failure is resolved. + +**How to fix:** + +1. Find the failed migration: + +```sql +SELECT migration_name, finished_at, rolled_back_at, logs +FROM "_prisma_migrations" +WHERE finished_at IS NULL OR rolled_back_at IS NOT NULL +ORDER BY started_at DESC; +``` + +2. Delete the failed entry and restart LiteLLM: + +```sql +DELETE FROM "_prisma_migrations" +WHERE migration_name = ''; +``` + +3. If that doesn't work, use `prisma db push`: + +```bash +DATABASE_URL="" prisma db push +``` + +--- + +### 3. Migration state mismatch after version rollback + +**Cause:** You upgraded to version X (new migrations applied), rolled back to version Y, then upgraded again. The `_prisma_migrations` table has stale entries for migrations that were partially applied or correspond to a schema state that no longer exists. + +**Fix:** + +1. Inspect the migration table for problematic entries: + +```sql +SELECT migration_name, started_at, finished_at, rolled_back_at, logs +FROM "_prisma_migrations" +ORDER BY started_at DESC +LIMIT 20; +``` + +2. For each migration that shouldn't be there (i.e., from the version you rolled back from), delete the entry: + ```sql + DELETE FROM "_prisma_migrations" WHERE migration_name = ''; + ``` + +3. Restart LiteLLM to re-run migrations. + +4. If that doesn't work, use `prisma db push`: + +```bash +DATABASE_URL="" prisma db push +``` diff --git a/docs/my-website/docs/tutorials/claude_agent_sdk.md b/docs/my-website/docs/tutorials/claude_agent_sdk.md new file mode 100644 index 00000000000..c56784ba2df --- /dev/null +++ b/docs/my-website/docs/tutorials/claude_agent_sdk.md @@ -0,0 +1,115 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Claude Agent SDK with LiteLLM + +Use Anthropic's Claude Agent SDK with any LLM provider through LiteLLM Proxy. + +The Claude Agent SDK provides a high-level interface for building AI agents. By pointing it to LiteLLM, you can use the same agent code with OpenAI, Bedrock, Azure, Vertex AI, or any other provider. + +## Quick Start + +### 1. Install Dependencies + +```bash +pip install claude-agent-sdk +``` + +### 2. Start LiteLLM Proxy + +```yaml title="config.yaml" showLineNumbers +model_list: + - model_name: bedrock-claude-sonnet-3.5 + litellm_params: + model: "bedrock/us.anthropic.claude-3-5-sonnet-20240620-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-claude-sonnet-4 + litellm_params: + model: "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-claude-sonnet-4.5 + litellm_params: + model: "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-claude-opus-4.5 + litellm_params: + model: "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0" + aws_region_name: "us-east-1" + + - model_name: bedrock-nova-premier + litellm_params: + model: "bedrock/amazon.nova-premier-v1:0" + aws_region_name: "us-east-1" +``` + +```bash +litellm --config config.yaml +``` + +### 3. Point Agent SDK to LiteLLM + +| Environment Variable | Value | Description | +|---------------------|-------|-------------| +| `ANTHROPIC_BASE_URL` | `http://localhost:4000` | LiteLLM proxy URL | +| `ANTHROPIC_API_KEY` | `sk-1234` | Your LiteLLM API key (not Anthropic key) | + +```python title="agent.py" showLineNumbers +import os +from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions + +# Point to LiteLLM proxy (not Anthropic) +os.environ["ANTHROPIC_BASE_URL"] = "http://localhost:4000" +os.environ["ANTHROPIC_API_KEY"] = "sk-1234" # Your LiteLLM key + +# Configure agent with any model from your config +options = ClaudeAgentOptions( + system_prompt="You are a helpful AI assistant.", + model="bedrock-claude-sonnet-4", # Use any model from config.yaml + max_turns=20, +) + +async with ClaudeSDKClient(options=options) as client: + await client.query("What is LiteLLM?") + + async for msg in client.receive_response(): + if hasattr(msg, 'content'): + for content_block in msg.content: + if hasattr(content_block, 'text'): + print(content_block.text, end='', flush=True) +``` + + + +## Why Use LiteLLM with Agent SDK? + +| Feature | Benefit | +|---------|---------| +| **Multi-Provider** | Use the same agent code with OpenAI, Bedrock, Azure, Vertex AI, etc. | +| **Cost Tracking** | Track spending across all agent conversations | +| **Rate Limiting** | Set budgets and limits on agent usage | +| **Load Balancing** | Distribute requests across multiple API keys or regions | +| **Fallbacks** | Automatically retry with different models if one fails | + +## Complete Example + +See our [cookbook example](https://github.com/BerriAI/litellm/tree/main/cookbook/anthropic_agent_sdk) for a complete interactive CLI agent that: +- Streams responses in real-time +- Switches between models dynamically +- Fetches available models from the proxy + +```bash +# Clone and run the example +git clone https://github.com/BerriAI/litellm.git +cd litellm/cookbook/anthropic_agent_sdk +pip install -r requirements.txt +python main.py +``` + +## Related Resources + +- [Claude Agent SDK Documentation](https://github.com/anthropics/anthropic-agent-sdk) +- [LiteLLM Proxy Quick Start](../proxy/quick_start) +- [Complete Cookbook Example](https://github.com/BerriAI/litellm/tree/main/cookbook/anthropic_agent_sdk) diff --git a/docs/my-website/docs/tutorials/claude_code_plugin_marketplace.md b/docs/my-website/docs/tutorials/claude_code_plugin_marketplace.md index 946fb47d92a..9d93c717c4f 100644 --- a/docs/my-website/docs/tutorials/claude_code_plugin_marketplace.md +++ b/docs/my-website/docs/tutorials/claude_code_plugin_marketplace.md @@ -2,7 +2,7 @@ import Image from '@theme/IdealImage'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Claude Code Plugin Marketplace +# Claude Code Plugin Marketplace (Managed Skills) LiteLLM AI Gateway acts as a central registry for Claude Code plugins. Admins can govern which plugins are available across the organization, and engineers can discover and install approved plugins from a single source. @@ -252,7 +252,7 @@ curl -X POST http://localhost:4000/claude-code/plugins \ }' ``` -### 3. Share with Your Team +### 3. Use in Claude Code Send engineers the marketplace URL: diff --git a/docs/my-website/docs/tutorials/copilotkit_sdk.md b/docs/my-website/docs/tutorials/copilotkit_sdk.md new file mode 100644 index 00000000000..fc4db8bfe3e --- /dev/null +++ b/docs/my-website/docs/tutorials/copilotkit_sdk.md @@ -0,0 +1,99 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# CopilotKit SDK with LiteLLM + +Use CopilotKit SDK with any LLM provider through LiteLLM Proxy. + +> **Note:** CopilotKit SDK integration with LiteLLM Proxy works with LiteLLM v1.81.7-nightly or higher. + + +## Quick Start + +### 1. Add Model to Config + +```yaml title="config.yaml" +model_list: + - model_name: claude-sonnet-4-5 + litellm_params: + model: "anthropic/claude-sonnet-4-5-20250514-v1:0" + api_key: "os.environ/ANTHROPIC_API_KEY" +``` + +### 2. Start LiteLLM Proxy + +```bash +litellm --config config.yaml +``` + +### 3. Use CopilotKit SDK + +```typescript +import OpenAI from "openai"; +import { + CopilotRuntime, + OpenAIAdapter, + copilotRuntimeNextJSAppRouterEndpoint, +} from "@copilotkit/runtime"; +import { NextRequest } from "next/server"; + +const model = "claude-sonnet-4-5"; + +const openai = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY || "sk-12345", + baseURL: process.env.OPENAI_BASE_URL || "http://localhost:4000/v1", +}); + +const serviceAdapter = new OpenAIAdapter({ openai, model }); +const runtime = new CopilotRuntime(); + +export const POST = async (req: NextRequest) => { + const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({ + runtime, + serviceAdapter, + endpoint: "/api/copilotkit", + }); + return handleRequest(req); +}; +``` + +### 4. Test + +```bash +curl -X POST http://localhost:3000/api/copilotkit \ + -H "Content-Type: application/json" \ + -d '{ + "method": "agent/run", + "params": { + "agentId": "default" + }, + "runId": "your_run_id", + "threadId": "your_thread_id", + "runId": ""your_run_id"", + "tools": [], + "context": [], + "forwardedProps": {}, + "state": {}, + "messages": [ + { + "id": "166e573e-f7c6-4c0f-8685-04dbefec18be", + "content": "Hi", + "role": "user" + } + ] + } +}' +``` + +## Environment Variables + +| Variable | Value | Description | +|----------|-------|-------------| +| `OPENAI_API_KEY` | `sk-12345` | Your LiteLLM API key | +| `OPENAI_BASE_URL` | `http://localhost:4000/v1` | LiteLLM proxy URL | + + +## Related Resources + +- [CopilotKit Documentation](https://docs.copilotkit.ai) +- [LiteLLM Proxy Quick Start](../proxy/quick_start) diff --git a/docs/my-website/docs/tutorials/livekit_xai_realtime.md b/docs/my-website/docs/tutorials/livekit_xai_realtime.md new file mode 100644 index 00000000000..1d70186382f --- /dev/null +++ b/docs/my-website/docs/tutorials/livekit_xai_realtime.md @@ -0,0 +1,190 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# LiveKit xAI Realtime Voice Agent + +Use LiveKit's xAI Grok Voice Agent plugin with LiteLLM Proxy to build low-latency voice AI agents. + +The LiveKit Agents framework provides tools for building real-time voice and video AI applications. By routing through LiteLLM Proxy, you get unified access to multiple realtime voice providers, cost tracking, rate limiting, and more. + +## Quick Start + +### 1. Install Dependencies + +```bash +pip install livekit-agents[xai] +``` + +### 2. Start LiteLLM Proxy + +Create a config file with your xAI realtime model: + +```yaml title="config.yaml" showLineNumbers +model_list: + - model_name: grok-voice-agent + litellm_params: + model: xai/grok-2-vision-1212 + api_key: os.environ/XAI_API_KEY + model_info: + mode: realtime + +litellm_settings: + drop_params: True + +general_settings: + master_key: sk-1234 # Change this to a secure key +``` + +Start the proxy: + +```bash +litellm --config config.yaml --port 4000 +``` + +### 3. Configure LiveKit xAI Plugin + +Point LiveKit's xAI plugin to your LiteLLM proxy: + +```python +from livekit.plugins import xai + +# Configure xAI to use LiteLLM proxy +model = xai.realtime.RealtimeModel( + voice="ara", # Voice option + api_key="sk-1234", # Your LiteLLM proxy master key + base_url="http://localhost:4000", # LiteLLM proxy URL +) +``` + +## Complete Example + +Here's a complete working example: + + + + +```python +#!/usr/bin/env python3 +""" +Simple xAI realtime voice agent through LiteLLM proxy. +""" +import asyncio +import json +import websockets + +PROXY_URL = "ws://localhost:4000/v1/realtime" +API_KEY = "sk-1234" +MODEL = "grok-voice-agent" + +async def run_voice_agent(): + """Connect to xAI realtime API through LiteLLM proxy""" + url = f"{PROXY_URL}?model={MODEL}" + headers = {"Authorization": f"Bearer {API_KEY}"} + + async with websockets.connect(url, extra_headers=headers) as ws: + # Wait for initial connection event + initial = json.loads(await ws.recv()) + print(f"āœ… Connected: {initial['type']}") + + # Send user message + await ws.send(json.dumps({ + "type": "conversation.item.create", + "item": { + "type": "message", + "role": "user", + "content": [{ + "type": "input_text", + "text": "Hello! Tell me a joke." + }] + } + })) + + # Request response + await ws.send(json.dumps({ + "type": "response.create", + "response": {"modalities": ["text", "audio"]} + })) + + # Collect response + transcript = [] + async for message in ws: + event = json.loads(message) + + # Capture text response + if event['type'] == 'response.output_audio_transcript.delta': + transcript.append(event['delta']) + print(event['delta'], end='', flush=True) + + # Done when response completes + elif event['type'] == 'response.done': + break + + print(f"\n\nāœ… Full response: {''.join(transcript)}") + +if __name__ == "__main__": + asyncio.run(run_voice_agent()) +``` + + + + + +```python +from livekit.agents import Agent, AgentSession, WorkerOptions, cli +from livekit.plugins import xai + +class VoiceAgent(Agent): + def __init__(self): + super().__init__( + instructions="You are a helpful voice assistant.", + llm=xai.realtime.RealtimeModel( + voice="ara", + api_key="sk-1234", + base_url="http://localhost:4000", + ), + ) + +if __name__ == "__main__": + cli.run_app( + WorkerOptions( + agent_factory=VoiceAgent, + ) + ) +``` + + + + +## Running the Example + +1. **Start LiteLLM Proxy** (if not already running): + ```bash + litellm --config config.yaml --port 4000 + ``` + +2. **Run the example**: + ```bash + python your_script.py + ``` + +## Expected Output + +``` +āœ… Connected: conversation.created +Hello! Here's a joke for you: Why don't scientists trust atoms? +Because they make up everything! + +āœ… Full response: Hello! Here's a joke for you: Why don't scientists trust atoms? Because they make up everything! +``` + + +## Complete Working Example + +**[LiveKit Agent SDK Cookbook](https://github.com/BerriAI/litellm/tree/main/cookbook/livekit_agent_sdk)** + + +## Learn More + +- [xAI Realtime API](/docs/providers/xai_realtime) +- [LiveKit xAI Plugin](https://docs.livekit.io/agents/models/realtime/plugins/xai/) +- [LiteLLM Realtime API](/docs/realtime) diff --git a/docs/my-website/img/a2a_agent_spend.png b/docs/my-website/img/a2a_agent_spend.png new file mode 100644 index 00000000000..15ec769392a Binary files /dev/null and b/docs/my-website/img/a2a_agent_spend.png differ diff --git a/docs/my-website/img/a2a_trace_grouping.png b/docs/my-website/img/a2a_trace_grouping.png new file mode 100644 index 00000000000..05130420aae Binary files /dev/null and b/docs/my-website/img/a2a_trace_grouping.png differ diff --git a/docs/my-website/img/ui_spend_logs_settings.png b/docs/my-website/img/ui_spend_logs_settings.png new file mode 100644 index 00000000000..334f5b1d93e Binary files /dev/null and b/docs/my-website/img/ui_spend_logs_settings.png differ diff --git a/docs/my-website/img/ui_tools.png b/docs/my-website/img/ui_tools.png new file mode 100644 index 00000000000..6f4d0f87410 Binary files /dev/null and b/docs/my-website/img/ui_tools.png differ diff --git a/docs/my-website/release_notes/v1.81.3-stable/index.md b/docs/my-website/release_notes/v1.81.3-stable/index.md new file mode 100644 index 00000000000..22b6f43deef --- /dev/null +++ b/docs/my-website/release_notes/v1.81.3-stable/index.md @@ -0,0 +1,423 @@ +--- +title: "v1.81.3-stable - Performance - 25% CPU Usage Reduction" +slug: "v1-81-3" +date: 2026-01-26T10:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://pbs.twimg.com/profile_images/1298587542745358340/DZv3Oj-h_400x400.jpg + - name: Ishaan Jaff + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +hide_table_of_contents: false +--- + +import Image from '@theme/IdealImage'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +## Deploy this version + + + + +``` showLineNumbers title="docker run litellm" +docker run \ +-e STORE_MODEL_IN_DB=True \ +-p 4000:4000 \ +docker.litellm.ai/berriai/litellm:v1.81.3.rc.2 +``` + + + + + +``` showLineNumbers title="pip install litellm" +pip install litellm==1.81.3.rc.2 +``` + + + + +--- + +## New Models / Updated Models + +### New Model Support + +| Provider | Model | Context Window | Input ($/1M tokens) | Output ($/1M tokens) | Deprecation Date | +| -------- | ----- | -------------- | ------------------- | -------------------- | ---------------- | +| OpenAI | `gpt-audio`, `gpt-audio-2025-08-28` | 128K | $32/1M audio tokens, $2.5/1M text tokens | $64/1M audio tokens, $10/1M text tokens | - | +| OpenAI | `gpt-audio-mini`, `gpt-audio-mini-2025-08-28` | 128K | $10/1M audio tokens, $0.6/1M text tokens | $20/1M audio tokens, $2.4/1M text tokens | - | +| Deepinfra, Vertex AI, Google AI Studio, OpenRouter, Vercel AI Gateway | `gemini-2.0-flash-001`, `gemini-2.0-flash` | - | - | - | 2026-03-31 | +| Groq | `openai/gpt-oss-120b` | 131K | 0.075/1M cache read | 0.6/1M output tokens | - | +| Groq | `groq/openai/gpt-oss-20b` | 131K | 0.0375/1M cache read, $0.075/1M text tokens | 0.3/1M output tokens | - | +| Vertex AI | `gemini-2.5-computer-use-preview-10-2025` | 128K | $1.25 | $10 | - | +| Azure AI | `claude-haiku-4-5` | $1.25/1M cache read, $2/1M cache read above 1 hr, $0.1/1M text tokens | $5/1M output tokens | - | +| Azure AI | `claude-sonnet-4-5` | $3.75/1M cache read, $6/1M cache read above 1 hr, $3/1M text tokens | $15/1M output tokens | - | +| Azure AI | `claude-opus-4-5` | $6.25/1M cache read, $10/1M cache read above 1 hr, $0.5/1M text tokens | $25/1M output tokens | - | +| Azure AI | `claude-opus-4-1` | $18.75/1M cache read, $30/1M cache read above 1 hr, $1.5/1M text tokens | $75/1M output tokens | - | + +### Features + +- **[OpenAI](../../docs/providers/openai)** + - Add gpt-audio and gpt-audio-mini models to pricing - [PR #19509](https://github.com/BerriAI/litellm/pull/19509) + - correct audio token costs for gpt-4o-audio-preview models - [PR #19500](https://github.com/BerriAI/litellm/pull/19500) + - Limit stop sequence as per openai spec (ensures JetBrains IDE compatibility) - [PR #19562](https://github.com/BerriAI/litellm/pull/19562) + +- **[VertexAI](../../docs/providers/vertex)** + - Docs - Google Workload Identity Federation (WIF) support - [PR #19320](https://github.com/BerriAI/litellm/pull/19320) + +- **[Agentcore](../../docs/providers/bedrock_agentcore)** + - Fixes streaming issues with AWS Bedrock AgentCore where responses would stop after the first chunk, particularly affecting OAuth-enabled agents - [PR #17141](https://github.com/BerriAI/litellm/pull/17141) + +- **[Chatgpt](../../docs/providers/chatgpt)** + - Adds support for calling chatgpt subscription via LiteLLM - [PR #19030](https://github.com/BerriAI/litellm/pull/19030) + - Adds responses API bridge support for chatgpt subscription provider - [PR #19030](https://github.com/BerriAI/litellm/pull/19030) + +- **[Bedrock](../../docs/providers/bedrock)** + - support for output format for bedrock invoke via v1/messages - [PR #19560](https://github.com/BerriAI/litellm/pull/19560) + +- **[Azure](../../docs/providers/azure/azure)** + - Add support for Azure OpenAI v1 API - [PR #19313](https://github.com/BerriAI/litellm/pull/19313) + - preserve content_policy_violation details for images (#19328) - [PR #19372](https://github.com/BerriAI/litellm/pull/19372) + - Support OpenAI-format nested tool definitions for Responses API - [PR #19526](https://github.com/BerriAI/litellm/pull/19526) + +- **Gemini([Vertex AI](../../docs/providers/vertex), [Google AI Studio](../../docs/providers/gemini))** + - use responseJsonSchema for Gemini 2.0+ models - [PR #19314](https://github.com/BerriAI/litellm/pull/19314) + +- **[Volcengine](../../docs/providers/volcano)** + - Support Volcengine responses api - [PR #18508](https://github.com/BerriAI/litellm/pull/18508) + +- **[Anthropic](../../docs/providers/anthropic)** + - Add Support for calling Claude Code Max subscriptions via LiteLLM - [PR #19453](https://github.com/BerriAI/litellm/pull/19453) + - Add Structured output for /v1/messages with Anthropic API, Azure Anthropic API, Bedrock Converse - [PR #19545](https://github.com/BerriAI/litellm/pull/19545) + +- **[Brave Search](../../docs/search/brave)** + - New Search provider - [PR #19433](https://github.com/BerriAI/litellm/pull/19433) + +- **Sarvam ai** + - Add support for new sarvam models - [PR #19479](https://github.com/BerriAI/litellm/pull/19479) + +- **[GMI](../../docs/providers/gmi)** + - add GMI Cloud provider support - [PR #19376](https://github.com/BerriAI/litellm/pull/19376) + + +### Bug Fixes + +- **[Anthropic](../../docs/providers/anthropic)** + - Fix anthropic-beta sent client side being overridden instead of appended to - [PR #19343](https://github.com/BerriAI/litellm/pull/19343) + - Filter out unsupported fields from JSON schema for Anthropic's output_format API - [PR #19482](https://github.com/BerriAI/litellm/pull/19482) + +- **[Bedrock](../../docs/providers/bedrock)** + - Expose stability models via /image_edits endpoint and ensure proper request transformation - [PR #19323](https://github.com/BerriAI/litellm/pull/19323) + - Claude Code x Bedrock Invoke fails with advanced-tool-use-2025-11-20 - [PR #19373](https://github.com/BerriAI/litellm/pull/19373) + - deduplicate tool calls in assistant history - [PR #19324](https://github.com/BerriAI/litellm/pull/19324) + - fix: correct us.anthropic.claude-opus-4-5 In-region pricing - [PR #19310](https://github.com/BerriAI/litellm/pull/19310) + - Fix request validation errors when using Claude 4 via bedrock invoke - [PR #19381](https://github.com/BerriAI/litellm/pull/19381) + - Handle thinking with tool calls for Claude 4 models - [PR #19506](https://github.com/BerriAI/litellm/pull/19506) + - correct streaming choice index for tool calls - [PR #19506](https://github.com/BerriAI/litellm/pull/19506) + +- **[Ollama](../../docs/providers/ollama)** + - Fix tool call errors due with improved message extraction - [PR #19369](https://github.com/BerriAI/litellm/pull/19369) + +- **[VertexAI](../../docs/providers/vertex)** + - Removed optionalĀ vertex_count_tokens_locationĀ param before request is sent to vertex - [PR #19359](https://github.com/BerriAI/litellm/pull/19359) + +- **Gemini([Vertex AI](../../docs/providers/vertex), [Google AI Studio](../../docs/providers/gemini))** + - Supports setting media_resolution and fps parameters on each video file, when using Gemini video understanding - [PR #19273](https://github.com/BerriAI/litellm/pull/19273) + - handle reasoning_effort as dict from OpenAI Agents SDK - [PR #19419](https://github.com/BerriAI/litellm/pull/19419) + - add file content support in tool results - [PR #19416](https://github.com/BerriAI/litellm/pull/19416) + +- **[Azure](../../docs/providers/azure_ai)** + - Fix Azure AI costs for Anthropic models - [PR #19530](https://github.com/BerriAI/litellm/pull/19530) + +- **[Giga Chat](../../docs/providers/gigachat)** + - Add tool choice mapping - [PR #19645](https://github.com/BerriAI/litellm/pull/19645) +--- + +## AI API Endpoints (LLMs, MCP, Agents) + +### Features + +- **[Files API](../../docs/files_endpoints)** + - Add managed files support when load_balancing is True - [PR #19338](https://github.com/BerriAI/litellm/pull/19338) + +- **[Claude Plugin Marketplace](../../docs/tutorials/claude_code_plugin_marketplace)** + - Add self hosted Claude Code Plugin Marketplace - [PR #19378](https://github.com/BerriAI/litellm/pull/19378) + +- **[MCP](../../docs/mcp)** + - Add MCP Protocol versionĀ 2025-11-25Ā support - [PR #19379](https://github.com/BerriAI/litellm/pull/19379) + - Log MCP tool calls and list tools in the LiteLLM Spend Logs table for easier debugging - [PR #19469](https://github.com/BerriAI/litellm/pull/19469) + +- **[Vertex AI](../../docs/providers/vertex)** + - Ensure only anthropic betas are forwarded down to LLM API (by default) - [PR #19542](https://github.com/BerriAI/litellm/pull/19542) + - Allow overriding to support forwarding incoming headers are forwarded down to target - [PR #19524](https://github.com/BerriAI/litellm/pull/19524) + +- **[Chat/Completions](../../docs/completion/input)** + - Add MCP tools response to chat completions - [PR #19552](https://github.com/BerriAI/litellm/pull/19552) + - Add custom vertex ai finish reasons to the output - [PR #19558](https://github.com/BerriAI/litellm/pull/19558) + - Return MCP execution in /chat/completions before model output during streaming - [PR #19623](https://github.com/BerriAI/litellm/pull/19623) + +### Bugs + +- **[Responses API](../../docs/response_api)** + - Fix duplicate messages during MCP streaming tool execution - [PR #19317](https://github.com/BerriAI/litellm/pull/19317) + - Fix pickle error when using OpenAI'sĀ Responses APIĀ withĀ stream=TrueĀ andĀ tool_choiceĀ of typeĀ allowed_toolsĀ (anĀ OpenAI-native parameter) - [PR #17205](https://github.com/BerriAI/litellm/pull/17205) + - stream tool call events for non-openai models - [PR #19368](https://github.com/BerriAI/litellm/pull/19368) + - preserve tool output ordering for gemini in responses bridgeĀ - [PR #19360](https://github.com/BerriAI/litellm/pull/19360) + - Add ID caching to prevent ID mismatch text-start and text-delta - [PR #19390](https://github.com/BerriAI/litellm/pull/19390) + - Include output_item, reasoning_summary_Text_done and reasoning_summary_part_done events for non-openai models - [PR #19472](https://github.com/BerriAI/litellm/pull/19472) + +- **[Chat/Completions](../../docs/completion/input)** + - fix: drop_params not dropping prompt_cache_key for non-OpenAI providers - [PR #19346](https://github.com/BerriAI/litellm/pull/19346) + +- **[Realtime API](../../docs/realtime)** + - disable SSL for ws:// WebSocket connections - [PR #19345](https://github.com/BerriAI/litellm/pull/19345) + +- **[Generate Content](../../docs/generateContent)** + - Log actual user input when google genai/vertex endpoints are called client-side - [PR #19156](https://github.com/BerriAI/litellm/pull/19156) + +- **[/messages/count_tokens Anthropic Token Counting](../../docs/anthropic_count_tokens)** + - ensure it works for Anthropic, Azure AI Anthropic on AI Gateway - [PR #19432](https://github.com/BerriAI/litellm/pull/19432) + +- **[MCP](../../docs/mcp)** + - forward static_headers to MCP servers - [PR #19366](https://github.com/BerriAI/litellm/pull/19366) + +- **[Batch API](../../docs/batches)** + - Fix: generation config empty for batch - [PR #19556](https://github.com/BerriAI/litellm/pull/19556) + +- **[Pass Through Endpoints](../../docs/proxy/pass_through)** + - Always reupdate registry - [PR #19420](https://github.com/BerriAI/litellm/pull/19420) +--- + +## Management Endpoints / UI + +### Features + +- **Cost Estimator** + - Fix model dropdown - [PR #19529](https://github.com/BerriAI/litellm/pull/19529) + +- **Claude Code Plugins** + - Allow Adding Claude Code Plugins via UI - [PR #19387](https://github.com/BerriAI/litellm/pull/19387) + +- **Guardrails** + - New Policy management UI - [PR #19668](https://github.com/BerriAI/litellm/pull/19668) + - Allow adding policies on Keys/Teams + Viewing on Info panels - [PR #19688](https://github.com/BerriAI/litellm/pull/19688) + +- **General** + - respects custom authentication header override - [PR #19276](https://github.com/BerriAI/litellm/pull/19276) + +- **Playground** + - Button to Fill Custom API Base - [PR #19440](https://github.com/BerriAI/litellm/pull/19440) + - display mcp output on the play ground - [PR #19553](https://github.com/BerriAI/litellm/pull/19553) + +- **Models** + - Paginate /v2/models/info - [PR #19521](https://github.com/BerriAI/litellm/pull/19521) + - All Model Tab Pagination - [PR #19525](https://github.com/BerriAI/litellm/pull/19525) + - Adding Optional scope Param to /models - [PR #19539](https://github.com/BerriAI/litellm/pull/19539) + - Model Search - [PR #19622](https://github.com/BerriAI/litellm/pull/19622) + - Filter by Model ID and Team ID - [PR #19713](https://github.com/BerriAI/litellm/pull/19713) + +- **MCP Servers** + - MCP Tools Tab Resetting to Overview - [PR #19468](https://github.com/BerriAI/litellm/pull/19468) + +- **Organizations** + - Prevent org admin from creating a new user with proxy_admin permissions - [PR #19296](https://github.com/BerriAI/litellm/pull/19296) + - Edit Page: Reusable Model Select - [PR #19601](https://github.com/BerriAI/litellm/pull/19601) + +- **Teams** + - Reusable Model Select - [PR #19543](https://github.com/BerriAI/litellm/pull/19543) + - [Fix] Team Update with Organization having All Proxy Models - [PR #19604](https://github.com/BerriAI/litellm/pull/19604) + +- **Logs** + - Include tool arguments in spend logs table - [PR #19640](https://github.com/BerriAI/litellm/pull/19640) + +- **Fallbacks / Loadbalancing** + - New fallbacks modal - [PR #19673](https://github.com/BerriAI/litellm/pull/19673) + - Set fallbacks/loadbalancing by team/key - [PR #19686](https://github.com/BerriAI/litellm/pull/19686) + +### Bugs + +- **Playground** + - increase model selector width in playground Compare view - [PR #19423](https://github.com/BerriAI/litellm/pull/19423) + +- **Virtual Keys** + - Sorting Shows Incorrect Entries - [PR #19534](https://github.com/BerriAI/litellm/pull/19534) + +- **General** + - UI 404 error when SERVER_ROOT_PATH is set - [PR #19467](https://github.com/BerriAI/litellm/pull/19467) + - Redirect to ui/login on expired JWT - [PR #19687](https://github.com/BerriAI/litellm/pull/19687) + +- **SSO** + - Fix SSO user roles not updating for existing users - [PR #19621](https://github.com/BerriAI/litellm/pull/19621) + +- **Guardrails** + - ensure guardrail patterns persist on edit and mode toggle - [PR #19265](https://github.com/BerriAI/litellm/pull/19265) +--- + +## AI Integrations + +### Logging + +- **General Logging** + - prevent printing duplicate StandardLoggingPayload logs - [PR #19325](https://github.com/BerriAI/litellm/pull/19325) + - Fix: log duplication when json_logs is enabled - [PR #19705](https://github.com/BerriAI/litellm/pull/19705) +- **Langfuse OTEL** + - ignore service logs and fix callback shadowing - [PR #19298](https://github.com/BerriAI/litellm/pull/19298) +- **Langfuse** + - Send litellm_trace_id - [PR #19528](https://github.com/BerriAI/litellm/pull/19528) + - Add Langfuse mock mode for testing without API calls - [PR #19676](https://github.com/BerriAI/litellm/pull/19676) +- **GCS Bucket** + - prevent unbounded queue growth due to slow API calls - [PR #19297](https://github.com/BerriAI/litellm/pull/19297) + - Add GCS mock mode for testing without API calls - [PR #19683](https://github.com/BerriAI/litellm/pull/19683) +- **Responses API Logging** + - Fix pydantic serialization error - [PR #19486](https://github.com/BerriAI/litellm/pull/19486) +- **Arize Phoenix** + - add openinference span kinds to arize phoenix - [PR #19267](https://github.com/BerriAI/litellm/pull/19267) +- **Prometheus** + - Added new prometheus metrics for user count and team count - [PR #19520](https://github.com/BerriAI/litellm/pull/19520) + +### Guardrails + +- **Bedrock Guardrails** + - Ensure post_call guardrail checks input+output - [PR #19151](https://github.com/BerriAI/litellm/pull/19151) +- **Prompt Security** + - fixing prompt-security's guardrail implementation - [PR #19374](https://github.com/BerriAI/litellm/pull/19374) +- **Presidio** + - Fixes crash in Presidio Guardrail when running in background threads (logging_hook) - [PR #19714](https://github.com/BerriAI/litellm/pull/19714) +- **Pillar Security** + - Migrate Pillar Security to Generic Guardrail API - [PR #19364](https://github.com/BerriAI/litellm/pull/19364) +- **Policy Engine** + - New LiteLLM Policy engine - create policies to manage guardrails, conditions - permissions per Key, Team - [PR #19612](https://github.com/BerriAI/litellm/pull/19612) +- **General** + - add case-insensitive support for guardrail mode and actions - [PR #19480](https://github.com/BerriAI/litellm/pull/19480) + +### Prompt Management + +- **General** + - fix prompt info lookup and delete using correct IDs - [PR #19358](https://github.com/BerriAI/litellm/pull/19358) + +### Secret Manager + +- **AWS Secret Manager** + - ensure auto-rotation updates existing AWS secret instead of creating new one - [PR #19455](https://github.com/BerriAI/litellm/pull/19455) +- **Hashicorp Vault** + - Ensure key rotations work with Vault - [PR #19634](https://github.com/BerriAI/litellm/pull/19634) + +--- + +## Spend Tracking, Budgets and Rate Limiting + +- **Pricing Updates** + - Add openai/dall-e base pricing entries - [PR #19133](https://github.com/BerriAI/litellm/pull/19133) + - Add `input_cost_per_video_per_second` in ModelInfoBase - [PR #19398](https://github.com/BerriAI/litellm/pull/19398) + +--- + +## Performance / Loadbalancing / Reliability improvements + + +- **General** + - Fix date overflow/division by zero in proxy utils - [PR #19527](https://github.com/BerriAI/litellm/pull/19527) + - Fix in-flight request termination on SIGTERM when health-check runs in a separate process - [PR #19427](https://github.com/BerriAI/litellm/pull/19427) + - Fix Pass through routes to work with server root path - [PR #19383](https://github.com/BerriAI/litellm/pull/19383) + - Fix logging error for stop iteration - [PR #19649](https://github.com/BerriAI/litellm/pull/19649) + - prevent retrying 4xx client errors - [PR #19275](https://github.com/BerriAI/litellm/pull/19275) + - add better error handling for misconfig on health check - [PR #19441](https://github.com/BerriAI/litellm/pull/19441) + +- **Router** + - Fix Azure RPM calculation formula - [PR #19513](https://github.com/BerriAI/litellm/pull/19513) + - Persist scheduler request queue to redis - [PR #19304](https://github.com/BerriAI/litellm/pull/19304) + - pass search_tools to Router during DB-triggered initialization - [PR #19388](https://github.com/BerriAI/litellm/pull/19388) + - Fixed PromptCachingCache to correctly handle messages where cache_control is a sibling key of string content - [PR #19266](https://github.com/BerriAI/litellm/pull/19266) + +- **Memory Leaks/OOM** + - prevent OOM with nested $defs in tool schemas - [PR #19112](https://github.com/BerriAI/litellm/pull/19112) + - fix: HTTP client memory leaks in Presidio, OpenAI, and Gemini - [PR #19190](https://github.com/BerriAI/litellm/pull/19190) + +- **Non root** + - fix logfile and pidfile of supervisor for non root environment - [PR #17267](https://github.com/BerriAI/litellm/pull/17267) + - resolve Read-only file system error in non-root images - [PR #19449](https://github.com/BerriAI/litellm/pull/19449) + +- **Dockerfile** + - Redis Semantic Caching - add missing redisvl dependency to requirements.txt - [PR #19417](https://github.com/BerriAI/litellm/pull/19417) + - Bump OTEL versions to support a2a dependency - resolves modulenotfounderror for Microsoft Agents byĀ @Harshit28jĀ inĀ #18991 + +- **DB** + - Handle PostgreSQL cached plan errors during rolling deployments - [PR #19424](https://github.com/BerriAI/litellm/pull/19424) + +- **Timeouts** + - Fix: total timeout is not respected - [PR #19389](https://github.com/BerriAI/litellm/pull/19389) + +- **SDK** + - Field-Existence Checks to Type Classes to Prevent Attribute Errors - [PR #18321](https://github.com/BerriAI/litellm/pull/18321) + - add google-cloud-aiplatform as optional dependency with clear error message - [PR #19437](https://github.com/BerriAI/litellm/pull/19437) + - MakeĀ grpcĀ dependency optional - [PR #19447](https://github.com/BerriAI/litellm/pull/19447) + - Add support for retry policies - [PR #19645](https://github.com/BerriAI/litellm/pull/19645) + +- **Performance** + - Cut chat_completion latency by ~21% by reducing pre-call processing time - [PR #19535](https://github.com/BerriAI/litellm/pull/19535) + - Optimize strip_trailing_slash with O(1) index check - [PR #19679](https://github.com/BerriAI/litellm/pull/19679) + - Optimize use_custom_pricing_for_model with set intersection - [PR #19677](https://github.com/BerriAI/litellm/pull/19677) + - perf: skip pattern_router.route() for non-wildcard models - [PR #19664](https://github.com/BerriAI/litellm/pull/19664) + - perf: Add LRU caching to get_model_info for faster cost lookups - [PR #19606](https://github.com/BerriAI/litellm/pull/19606) + +--- + +## General Proxy Improvements + +### Doc Improvements + - new tutorial for adding MCPs to Cursor via LiteLLM - [PR #19317](https://github.com/BerriAI/litellm/pull/19317) + - fix vertex_region to vertex_location in Vertex AI pass-through docs - [PR #19380](https://github.com/BerriAI/litellm/pull/19380) + - clarify Gemini and Vertex AI model prefix in json file - [PR #19443](https://github.com/BerriAI/litellm/pull/19443) + - update Claude Code integration guides - [PR #19415](https://github.com/BerriAI/litellm/pull/19415) + - adjust opencode tutorial - [PR #19605](https://github.com/BerriAI/litellm/pull/19605) + - add spend-queue-troubleshooting docs - [PR #19659](https://github.com/BerriAI/litellm/pull/19659) + - docs: add litellm-enterprise requirement for managed files - [PR #19689](https://github.com/BerriAI/litellm/pull/19689) + +### Helm + - Add support for keda in helm chart - [PR #19337](https://github.com/BerriAI/litellm/pull/19337) + - sync Helm chart version with LiteLLM release version - [PR #19438](https://github.com/BerriAI/litellm/pull/19438) + - Enable PreStop hook configuration in values.yaml - [PR #19613](https://github.com/BerriAI/litellm/pull/19613) + +### General + - Add health check scripts and parallel execution support - [PR #19295](https://github.com/BerriAI/litellm/pull/19295) + + +--- + +## New Contributors + + +* @dushyantzz made their first contribution in [PR #19158](https://github.com/BerriAI/litellm/pull/19158) +* @obod-mpw made their first contribution in [PR #19133](https://github.com/BerriAI/litellm/pull/19133) +* @msexxeta made their first contribution in [PR #19030](https://github.com/BerriAI/litellm/pull/19030) +* @rsicart made their first contribution in [PR #19337](https://github.com/BerriAI/litellm/pull/19337) +* @cluebbehusen made their first contribution in [PR #19311](https://github.com/BerriAI/litellm/pull/19311) +* @Lucky-Lodhi2004 made their first contribution in [PR #19315](https://github.com/BerriAI/litellm/pull/19315) +* @binbandit made their first contribution in [PR #19324](https://github.com/BerriAI/litellm/pull/19324) +* @flex-myeonghyeon made their first contribution in [PR #19381](https://github.com/BerriAI/litellm/pull/19381) +* @Lrakotoson made their first contribution in [PR #18321](https://github.com/BerriAI/litellm/pull/18321) +* @bensi94 made their first contribution in [PR #18787](https://github.com/BerriAI/litellm/pull/18787) +* @victorigualada made their first contribution in [PR #19368](https://github.com/BerriAI/litellm/pull/19368) +* @VedantMadane made their first contribution in #19266 +* @stiyyagura0901 made their first contribution in #19276 +* @kamilio made their first contribution in [PR #19447](https://github.com/BerriAI/litellm/pull/19447) +* @jonathansampson made their first contribution in [PR #19433](https://github.com/BerriAI/litellm/pull/19433) +* @rynecarbone made their first contribution in [PR #19416](https://github.com/BerriAI/litellm/pull/19416) +* @jayy-77 made their first contribution in #19366 +* @davida-ps made their first contribution in [PR #19374](https://github.com/BerriAI/litellm/pull/19374) +* @joaodinissf made their first contribution in [PR #19506](https://github.com/BerriAI/litellm/pull/19506) +* @ecao310 made their first contribution in [PR #19520](https://github.com/BerriAI/litellm/pull/19520) +* @mpcusack-altos made their first contribution in [PR #19577](https://github.com/BerriAI/litellm/pull/19577) +* @milan-berri made their first contribution in [PR #19602](https://github.com/BerriAI/litellm/pull/19602) +* @xqe2011 made their first contribution in #19621 + +--- + +## Full Changelog + +**[View complete changelog on GitHub](https://github.com/BerriAI/litellm/releases/tag/v1.81.3.rc)** diff --git a/docs/my-website/release_notes/v1.81.6.md b/docs/my-website/release_notes/v1.81.6.md new file mode 100644 index 00000000000..ef19276f2cf --- /dev/null +++ b/docs/my-website/release_notes/v1.81.6.md @@ -0,0 +1,384 @@ +--- +title: "v1.81.6 - Logs v2 with Tool Call Tracing" +slug: "v1-81-6" +date: 2026-01-31T00:00:00 +authors: + - name: Krrish Dholakia + title: CEO, LiteLLM + url: https://www.linkedin.com/in/krish-d/ + image_url: https://pbs.twimg.com/profile_images/1298587542745358340/DZv3Oj-h_400x400.jpg + - name: Ishaan Jaff + title: CTO, LiteLLM + url: https://www.linkedin.com/in/reffajnaahsi/ + image_url: https://pbs.twimg.com/profile_images/1613813310264340481/lz54oEiB_400x400.jpg +hide_table_of_contents: false +--- + +## Deploy this version + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Image from '@theme/IdealImage'; + + + + +```bash +docker run \ +-e STORE_MODEL_IN_DB=True \ +-p 4000:4000 \ +docker.litellm.ai/berriai/litellm:main-v1.81.6 +``` + + + + +```bash +pip install litellm==1.81.6 +``` + + + + +## Key Highlights + +Logs View v2 with Tool Call Tracing - Redesigned logs interface with side panel, structured tool visualization, and error message search for faster debugging. + +Let's dive in. + +### Logs View v2 with Tool Call Tracing + +This release introduces comprehensive tool call tracing through LiteLLM's redesigned Logs View v2, enabling developers to debug and monitor AI agent workflows in production environments seamlessly. + +This means you can now onboard use cases like tracing complex multi-step agent interactions, debugging tool execution failures, and monitoring MCP server calls while maintaining full visibility into request/response payloads with syntax highlighting. + +Developers can access the new Logs View through LiteLLM's UI to inspect tool calls in structured format, search logs by error messages or request patterns, and correlate agent activities across sessions with collapsible side panel views. + +{/* TODO: Add image from Slack (group_7219.png) - save as logs_v2_tool_tracing.png */} +{/* */} + +[Get Started](../../docs/proxy/ui_logs) + +## New Models / Updated Models + +#### New Model Support + +| Provider | Model | Context Window | Input ($/1M tokens) | Output ($/1M tokens) | Features | +| -------- | ----- | -------------- | ------------------- | -------------------- | -------- | +| AWS Bedrock | `amazon.nova-2-pro-preview-20251202-v1:0` | 1M | $2.19 | $17.50 | Chat completions, vision, video, PDF, function calling, prompt caching, reasoning | +| Google Vertex AI | `gemini-robotics-er-1.5-preview` | 1M | $0.30 | $2.50 | Chat completions, multimodal (text, image, video, audio), function calling, reasoning | +| OpenRouter | `openrouter/xiaomi/mimo-v2-flash` | 262K | $0.09 | $0.29 | Chat completions, function calling, reasoning | +| OpenRouter | `openrouter/moonshotai/kimi-k2.5` | - | - | - | Chat completions | +| OpenRouter | `openrouter/z-ai/glm-4.7` | 202K | $0.40 | $1.50 | Chat completions, vision, function calling, reasoning | + +#### Features + +- **[AWS Bedrock](../../docs/providers/bedrock)** + - Messages API Bedrock Converse caching and PDF support - [PR #19785](https://github.com/BerriAI/litellm/pull/19785) + - Translate advanced-tool-use to Bedrock-specific headers for Claude Opus 4.5 - [PR #19841](https://github.com/BerriAI/litellm/pull/19841) + - Support tool search header translation for Sonnet 4.5 - [PR #19871](https://github.com/BerriAI/litellm/pull/19871) + - Filter unsupported beta headers for AWS Bedrock Invoke API - [PR #19877](https://github.com/BerriAI/litellm/pull/19877) + - Nova grounding improvements - [PR #19598](https://github.com/BerriAI/litellm/pull/19598), [PR #20159](https://github.com/BerriAI/litellm/pull/20159) + +- **[Anthropic](../../docs/providers/anthropic)** + - Remove explicit cache_control null in tool_result content - [PR #19919](https://github.com/BerriAI/litellm/pull/19919) + - Fix tool handling - [PR #19805](https://github.com/BerriAI/litellm/pull/19805) + +- **[Google Gemini / Vertex AI](../../docs/providers/gemini)** + - Add Gemini Robotics-ER 1.5 preview support - [PR #19845](https://github.com/BerriAI/litellm/pull/19845) + - Support file retrieval in GoogleAIStudioFilesHandle - [PR #20018](https://github.com/BerriAI/litellm/pull/20018) + - Add /delete endpoint support - [PR #20055](https://github.com/BerriAI/litellm/pull/20055) + - Add custom_llm_provider as gemini translation - [PR #19988](https://github.com/BerriAI/litellm/pull/19988) + - Subtract implicit cached tokens from text_tokens for correct cost calculation - [PR #19775](https://github.com/BerriAI/litellm/pull/19775) + - Remove unsupported prompt-caching-scope-2026-01-05 header for vertex ai - [PR #20058](https://github.com/BerriAI/litellm/pull/20058) + - Add disable flag for anthropic gemini cache translation - [PR #20052](https://github.com/BerriAI/litellm/pull/20052) + - Convert image URLs to base64 in tool messages for Anthropic on Vertex AI - [PR #19896](https://github.com/BerriAI/litellm/pull/19896) + +- **[xAI](../../docs/providers/xai)** + - Add grok reasoning content support - [PR #19850](https://github.com/BerriAI/litellm/pull/19850) + - Add websearch params support for Responses API - [PR #19915](https://github.com/BerriAI/litellm/pull/19915) + - Add routing of xai chat completions to responses when web search options is present - [PR #20051](https://github.com/BerriAI/litellm/pull/20051) + - Correct cached token cost calculation - [PR #19772](https://github.com/BerriAI/litellm/pull/19772) + +- **[Azure OpenAI](../../docs/providers/azure)** + - Use generic cost calculator for audio token pricing - [PR #19771](https://github.com/BerriAI/litellm/pull/19771) + - Allow tool_choice for Azure GPT-5 chat models - [PR #19813](https://github.com/BerriAI/litellm/pull/19813) + - Set gpt-5.2-codex mode to responses for Azure and OpenRouter - [PR #19770](https://github.com/BerriAI/litellm/pull/19770) + +- **[OpenAI](../../docs/providers/openai)** + - Fix max_input_tokens for gpt-5.2-codex - [PR #20009](https://github.com/BerriAI/litellm/pull/20009) + - Fix gpt-image-1.5 cost calculation not including output image tokens - [PR #19515](https://github.com/BerriAI/litellm/pull/19515) + +- **[Hosted VLLM](../../docs/providers/vllm)** + - Support thinking parameter in anthropic_messages() and .completion() - [PR #19787](https://github.com/BerriAI/litellm/pull/19787) + - Route through base_llm_http_handler to support ssl_verify - [PR #19893](https://github.com/BerriAI/litellm/pull/19893) + - Fix vllm embedding format - [PR #20056](https://github.com/BerriAI/litellm/pull/20056) + +- **[OCI GenAI](../../docs/providers/oci)** + - Serialize imageUrl as object for OCI GenAI API - [PR #19661](https://github.com/BerriAI/litellm/pull/19661) + +- **[Volcengine](../../docs/providers/volcano)** + - Add context for volcengine models (deepseek-v3-2, glm-4-7, kimi-k2-thinking) - [PR #19335](https://github.com/BerriAI/litellm/pull/19335) + +- **[Chinese Providers](../../docs/providers/)** + - Add prompt caching and reasoning support for MiniMax, GLM, Xiaomi - [PR #19924](https://github.com/BerriAI/litellm/pull/19924) + +- **[Vercel AI Gateway](../../docs/providers/vercel_ai_gateway)** + - Add embeddings support - [PR #19660](https://github.com/BerriAI/litellm/pull/19660) + +### Bug Fixes + +- **[Google](../../docs/providers/gemini)** + - Fix gemini-robotics-er-1.5-preview entry - [PR #19974](https://github.com/BerriAI/litellm/pull/19974) + +- **General** + - Fix output_tokens_details.reasoning_tokens None - [PR #19914](https://github.com/BerriAI/litellm/pull/19914) + - Fix stream_chunk_builder to preserve images from streaming chunks - [PR #19654](https://github.com/BerriAI/litellm/pull/19654) + - Fix aspectRatio mapping in image edit - [PR #20053](https://github.com/BerriAI/litellm/pull/20053) + - Handle unknown models in Azure AI cost calculator - [PR #20150](https://github.com/BerriAI/litellm/pull/20150) + +- **[GigaChat](../../docs/providers/gigachat)** + - Ensure function content is valid JSON - [PR #19232](https://github.com/BerriAI/litellm/pull/19232) + +## LLM API Endpoints + +#### Features + +- **[Messages API (/messages)](../../docs/mcp)** + - Add LiteLLM x Claude Agent SDK Integration - [PR #20035](https://github.com/BerriAI/litellm/pull/20035) + +- **[A2A / MCP Gateway API (/a2a, /mcp)](../../docs/mcp)** + - Add A2A agent header-based context propagation support - [PR #19504](https://github.com/BerriAI/litellm/pull/19504) + - Enable progress notifications for MCP tool calls - [PR #19809](https://github.com/BerriAI/litellm/pull/19809) + - Fix support for non-standard MCP URL patterns - [PR #19738](https://github.com/BerriAI/litellm/pull/19738) + - Add backward compatibility for legacy A2A card formats (/.well-known/agent.json) - [PR #19949](https://github.com/BerriAI/litellm/pull/19949) + - Add support for agent parameter in /interactions endpoint - [PR #19866](https://github.com/BerriAI/litellm/pull/19866) + +- **[Responses API (/responses)](../../docs/response_api)** + - Fix custom_llm_provider for provider-specific params - [PR #19798](https://github.com/BerriAI/litellm/pull/19798) + - Extract input tokens details as dict in ResponseAPILoggingUtils - [PR #20046](https://github.com/BerriAI/litellm/pull/20046) + +- **[Batch API (/batches)](../../docs/batches)** + - Fix /batches to return encoded ids (from managed objects table) - [PR #19040](https://github.com/BerriAI/litellm/pull/19040) + - Fix Batch and File user level permissions - [PR #19981](https://github.com/BerriAI/litellm/pull/19981) + - Add cost tracking and usage object in retrieve_batch call type - [PR #19986](https://github.com/BerriAI/litellm/pull/19986) + +- **[Embeddings API (/embeddings)](../../docs/embedding/supported_embedding)** + - Add supported input formats documentation - [PR #20073](https://github.com/BerriAI/litellm/pull/20073) + +- **[RAG API (/rag/ingest, /vector_store)](../../docs/rag_ingest)** + - Add UI for /rag/ingest API - Upload docs, pdfs etc to create vector stores - [PR #19822](https://github.com/BerriAI/litellm/pull/19822) + - Add support for using S3 Vectors as Vector Store Provider - [PR #19888](https://github.com/BerriAI/litellm/pull/19888) + - Add s3_vectors as provider on /vector_store/search API + UI for creating + PDF support - [PR #19895](https://github.com/BerriAI/litellm/pull/19895) + - Add permission management for users and teams on Vector Stores - [PR #19972](https://github.com/BerriAI/litellm/pull/19972) + - Enable router support for completions in RAG query pipeline - [PR #19550](https://github.com/BerriAI/litellm/pull/19550) + +- **[Search API (/search)](../../docs/search)** + - Add /list endpoint to list what search tools exist in router - [PR #19969](https://github.com/BerriAI/litellm/pull/19969) + - Fix router search tools v2 integration - [PR #19840](https://github.com/BerriAI/litellm/pull/19840) + +- **[Passthrough Endpoints (/\{provider\}_passthrough)](../../docs/pass_through/intro)** + - Add /openai_passthrough route for OpenAI passthrough requests - [PR #19989](https://github.com/BerriAI/litellm/pull/19989) + - Add support for configuring role_mappings via environment variables - [PR #19498](https://github.com/BerriAI/litellm/pull/19498) + - Add Vertex AI LLM credentials sensitive keyword "vertex_credentials" for masking - [PR #19551](https://github.com/BerriAI/litellm/pull/19551) + - Fix prevention of provider-prefixed model name leaks in responses - [PR #19943](https://github.com/BerriAI/litellm/pull/19943) + - Fix proxy support for slashes in Google Vertex generateContent model names - [PR #19737](https://github.com/BerriAI/litellm/pull/19737), [PR #19753](https://github.com/BerriAI/litellm/pull/19753) + - Support model names with slashes in Vertex AI passthrough URLs - [PR #19944](https://github.com/BerriAI/litellm/pull/19944) + - Fix regression in Vertex AI passthroughs for router models - [PR #19967](https://github.com/BerriAI/litellm/pull/19967) + - Add regression tests for Vertex AI passthrough model names - [PR #19855](https://github.com/BerriAI/litellm/pull/19855) + +#### Bugs + +- **General** + - Fix token calculations and refactor - [PR #19696](https://github.com/BerriAI/litellm/pull/19696) + +## Management Endpoints / UI + +#### Features + +- **Proxy CLI Auth** + - Add configurable CLI JWT expiration via environment variable - [PR #19780](https://github.com/BerriAI/litellm/pull/19780) + - Fix team cli auth flow - [PR #19666](https://github.com/BerriAI/litellm/pull/19666) + +- **Virtual Keys** + - UI: Auto Truncation of Table Values - [PR #19718](https://github.com/BerriAI/litellm/pull/19718) + - Fix Create Key: Expire Key Input Duration - [PR #19807](https://github.com/BerriAI/litellm/pull/19807) + - Bulk Update Keys Endpoint - [PR #19886](https://github.com/BerriAI/litellm/pull/19886) + +- **Logs View** + - **v2 Logs view with side panel and improved UX** - [PR #20091](https://github.com/BerriAI/litellm/pull/20091) + - New View to render "Tools" on Logs View - [PR #20093](https://github.com/BerriAI/litellm/pull/20093) + - Add Pretty print view of request/response - [PR #20096](https://github.com/BerriAI/litellm/pull/20096) + - Add error_message search in Spend Logs Endpoint - [PR #19960](https://github.com/BerriAI/litellm/pull/19960) + - UI: Adding Error message search to ui spend logs - [PR #19963](https://github.com/BerriAI/litellm/pull/19963) + - Spend Logs: Settings Modal - [PR #19918](https://github.com/BerriAI/litellm/pull/19918) + - Fix error_code in Spend Logs metadata - [PR #20015](https://github.com/BerriAI/litellm/pull/20015) + - Spend Logs: Show Current Store and Retention Status - [PR #20017](https://github.com/BerriAI/litellm/pull/20017) + - Allow Dynamic Setting of store_prompts_in_spend_logs - [PR #19913](https://github.com/BerriAI/litellm/pull/19913) + - [Docs: UI Spend Logs Settings](../../docs/proxy/ui_spend_log_settings) - [PR #20197](https://github.com/BerriAI/litellm/pull/20197) + +- **Models + Endpoints** + - Add sortBy and sortOrder params for /v2/model/info - [PR #19903](https://github.com/BerriAI/litellm/pull/19903) + - Fix Sorting for /v2/model/info - [PR #19971](https://github.com/BerriAI/litellm/pull/19971) + - UI: Model Page Server Sort - [PR #19908](https://github.com/BerriAI/litellm/pull/19908) + +- **Usage & Analytics** + - UI: Usage Export: Breakdown by Teams and Keys - [PR #19953](https://github.com/BerriAI/litellm/pull/19953) + - UI: Usage: Model Breakdown Per Key - [PR #20039](https://github.com/BerriAI/litellm/pull/20039) + +- **UI Improvements** + - UI: Allow Admins to control what pages are visible on LeftNav - [PR #19907](https://github.com/BerriAI/litellm/pull/19907) + - UI: Add Light/Dark Mode Switch for Development - [PR #19804](https://github.com/BerriAI/litellm/pull/19804) + - UI: Dark Mode: Delete Resource Modal - [PR #20098](https://github.com/BerriAI/litellm/pull/20098) + - UI: Tables: Reusable Table Sort Component - [PR #19970](https://github.com/BerriAI/litellm/pull/19970) + - UI: New Badge Dot Render - [PR #20024](https://github.com/BerriAI/litellm/pull/20024) + - UI: Feedback Prompts: Option To Hide Prompts - [PR #19831](https://github.com/BerriAI/litellm/pull/19831) + - UI: Navbar: Fixed Default Logo + Bound Logo Box - [PR #20092](https://github.com/BerriAI/litellm/pull/20092) + - UI: Navbar: User Dropdown - [PR #20095](https://github.com/BerriAI/litellm/pull/20095) + - Change default key type from 'Default' to 'LLM API' - [PR #19516](https://github.com/BerriAI/litellm/pull/19516) + +- **Team & User Management** + - Fix /team/member_add User Email and ID Verifications - [PR #19814](https://github.com/BerriAI/litellm/pull/19814) + - Fix SSO Email Case Sensitivity - [PR #19799](https://github.com/BerriAI/litellm/pull/19799) + - UI: Internal User: Bulk Add - [PR #19721](https://github.com/BerriAI/litellm/pull/19721) + +- **AI Gateway Features** + - Add support for making silent LLM calls without logging - [PR #19544](https://github.com/BerriAI/litellm/pull/19544) + - UI: Fix MCP tools instructions to display comma-separated strings - [PR #20101](https://github.com/BerriAI/litellm/pull/20101) + +#### Bugs + +- Fix Model Name During Fallback - [PR #20177](https://github.com/BerriAI/litellm/pull/20177) +- Fix Health Endpoints when Callback Objects Defined - [PR #20182](https://github.com/BerriAI/litellm/pull/20182) +- Fix Unable to reset user max budget to unlimited - [PR #19796](https://github.com/BerriAI/litellm/pull/19796) +- Fix Password comparison with non-ASCII characters - [PR #19568](https://github.com/BerriAI/litellm/pull/19568) +- Correct error message for DISABLE_ADMIN_ENDPOINTS - [PR #19861](https://github.com/BerriAI/litellm/pull/19861) +- Prevent clearing content filter patterns when editing guardrail - [PR #19671](https://github.com/BerriAI/litellm/pull/19671) +- Fix Prompt Studio history to load tools and system messages - [PR #19920](https://github.com/BerriAI/litellm/pull/19920) +- Add WATSONX_ZENAPIKEY to WatsonX credentials - [PR #20086](https://github.com/BerriAI/litellm/pull/20086) +- UI: Vector Store: Allow Config Defined Models to Be Selected - [PR #20031](https://github.com/BerriAI/litellm/pull/20031) + +## Logging / Guardrail / Prompt Management Integrations + +#### Features + +- **[DataDog](../../docs/proxy/logging#datadog)** + - Add agent support for LLM Observability - [PR #19574](https://github.com/BerriAI/litellm/pull/19574) + - Add datadog cost management support and fix startup callback issue - [PR #19584](https://github.com/BerriAI/litellm/pull/19584) + - Add datadog_llm_observability to /health/services allowed list - [PR #19952](https://github.com/BerriAI/litellm/pull/19952) + - Check for agent mode before requiring DD_API_KEY/DD_SITE - [PR #20156](https://github.com/BerriAI/litellm/pull/20156) + +- **[OpenTelemetry](../../docs/observability/opentelemetry_integration)** + - Propagate JWT auth metadata to OTEL spans - [PR #19627](https://github.com/BerriAI/litellm/pull/19627) + - Fix thread leak in dynamic header path - [PR #19946](https://github.com/BerriAI/litellm/pull/19946) + +- **[Prometheus](../../docs/proxy/logging#prometheus)** + - Add callbacks and labels - [PR #19708](https://github.com/BerriAI/litellm/pull/19708) + - Add clientip and user agent in metrics - [PR #19717](https://github.com/BerriAI/litellm/pull/19717) + - Add tpm-rpm limit metrics - [PR #19725](https://github.com/BerriAI/litellm/pull/19725) + - Add model_id label to metrics - [PR #19678](https://github.com/BerriAI/litellm/pull/19678) + - Safely handle None metadata in logging - [PR #19691](https://github.com/BerriAI/litellm/pull/19691) + - Resolve high CPU when router_settings in DB by avoiding REGISTRY.collect() - [PR #20087](https://github.com/BerriAI/litellm/pull/20087) + +- **[Langfuse](../../docs/proxy/logging#langfuse)** + - Add litellm_callback_logging_failures_metric for Langfuse, Langfuse Otel and other Otel providers - [PR #19636](https://github.com/BerriAI/litellm/pull/19636) + +- **General Logging** + - Use return value from CustomLogger.async_post_call_success_hook - [PR #19670](https://github.com/BerriAI/litellm/pull/19670) + - Add async_post_call_response_headers_hook to CustomLogger - [PR #20083](https://github.com/BerriAI/litellm/pull/20083) + - Add mock client factory pattern and mock support for PostHog, Helicone, and Braintrust integrations - [PR #19707](https://github.com/BerriAI/litellm/pull/19707) + +#### Guardrails + +- **[Presidio](../../docs/proxy/guardrails/pii_masking_v2)** + - Reuse HTTP connections to prevent performance degradation - [PR #19964](https://github.com/BerriAI/litellm/pull/19964) + +- **Onyx** + - Add timeout to onyx guardrail - [PR #19731](https://github.com/BerriAI/litellm/pull/19731) + +- **General** + - Add guardrail model argument feature - [PR #19619](https://github.com/BerriAI/litellm/pull/19619) + - Fix guardrails issues with streaming-response regex - [PR #19901](https://github.com/BerriAI/litellm/pull/19901) + - Remove enterprise requirement for guardrail monitoring (docs) - [PR #19833](https://github.com/BerriAI/litellm/pull/19833) + +## Spend Tracking, Budgets and Rate Limiting + +- Add event-driven coordination for global spend query to prevent cache stampede - [PR #20030](https://github.com/BerriAI/litellm/pull/20030) + +## Performance / Loadbalancing / Reliability improvements + +- **Resolve high CPU when router_settings in DB** - by avoiding REGISTRY.collect() in PrometheusServicesLogger - [PR #20087](https://github.com/BerriAI/litellm/pull/20087) +- **Reuse HTTP connections in Presidio** - to prevent performance degradation - [PR #19964](https://github.com/BerriAI/litellm/pull/19964) +- **Event-driven coordination for global spend query** - prevent cache stampede - [PR #20030](https://github.com/BerriAI/litellm/pull/20030) +- Fix recursive Pydantic validation issue - [PR #19531](https://github.com/BerriAI/litellm/pull/19531) +- Refactor argument handling into helper function to reduce code bloat - [PR #19720](https://github.com/BerriAI/litellm/pull/19720) +- Optimize logo fetching and resolve MCP import blockers - [PR #19719](https://github.com/BerriAI/litellm/pull/19719) +- Improve logo download performance using async HTTP client - [PR #20155](https://github.com/BerriAI/litellm/pull/20155) +- Fix server root path configuration - [PR #19790](https://github.com/BerriAI/litellm/pull/19790) +- Refactor: Extract transport context creation into separate method - [PR #19794](https://github.com/BerriAI/litellm/pull/19794) +- Add native_background_mode configuration to override polling_via_cache for specific models - [PR #19899](https://github.com/BerriAI/litellm/pull/19899) +- Initialize tiktoken environment at import time to enable offline usage - [PR #19882](https://github.com/BerriAI/litellm/pull/19882) +- Improve tiktoken performance using local cache in lazy loading - [PR #19774](https://github.com/BerriAI/litellm/pull/19774) +- Fix timeout errors in chat completion calls to be correctly reported in failure callbacks - [PR #19842](https://github.com/BerriAI/litellm/pull/19842) +- Fix environment variable type handling for NUM_RETRIES - [PR #19507](https://github.com/BerriAI/litellm/pull/19507) +- Use safe_deep_copy in silent experiment kwargs to prevent mutation - [PR #20170](https://github.com/BerriAI/litellm/pull/20170) +- Improve error handling by inspecting BadRequestError after all other policy types - [PR #19878](https://github.com/BerriAI/litellm/pull/19878) + +## Database Changes + +### Schema Updates + +| Table | Change Type | Description | PR | Migration | +| ----- | ----------- | ----------- | -- | --------- | +| `LiteLLM_ManagedVectorStoresTable` | New Columns | Added `team_id` and `user_id` fields for permission management | [PR #19972](https://github.com/BerriAI/litellm/pull/19972) | [Migration](https://github.com/BerriAI/litellm/blob/main/litellm-proxy-extras/litellm_proxy_extras/migrations/20260131150814_add_team_user_to_vector_stores/migration.sql) | + +### Migration Improvements + +- Fix Docker: Use correct schema path for Prisma generation - [PR #19631](https://github.com/BerriAI/litellm/pull/19631) +- Resolve 'relation does not exist' migration errors in setup_database - [PR #19281](https://github.com/BerriAI/litellm/pull/19281) +- Fix migration issue and improve Docker image stability - [PR #19843](https://github.com/BerriAI/litellm/pull/19843) +- Run Prisma generate as nobody user in non-root Docker container for security - [PR #20000](https://github.com/BerriAI/litellm/pull/20000) +- Bump litellm-proxy-extras version to 0.4.28 - [PR #20166](https://github.com/BerriAI/litellm/pull/20166) + +## Documentation Updates + +- **[Add Claude Agents SDK x LiteLLM Guide](../../docs/mcp)** - [PR #20036](https://github.com/BerriAI/litellm/pull/20036) +- **[Add Cookbook: Using Claude Agent SDK + MCPs with LiteLLM](https://github.com/BerriAI/litellm/tree/main/cookbook)** - [PR #20081](https://github.com/BerriAI/litellm/pull/20081) +- Fix A2A Python SDK URL in documentation - [PR #19832](https://github.com/BerriAI/litellm/pull/19832) +- **[Add Sarvam usage documentation](../../docs/providers/sarvam)** - [PR #19844](https://github.com/BerriAI/litellm/pull/19844) +- **[Add supported input formats for embeddings](../../docs/embedding/supported_embedding)** - [PR #20073](https://github.com/BerriAI/litellm/pull/20073) +- **[UI Spend Logs Settings Docs](../../docs/proxy/ui_spend_log_settings)** - [PR #20197](https://github.com/BerriAI/litellm/pull/20197) +- Add OpenAI Agents SDK to OSS Adopters list in README - [PR #19820](https://github.com/BerriAI/litellm/pull/19820) +- Update docs: Remove enterprise requirement for guardrail monitoring - [PR #19833](https://github.com/BerriAI/litellm/pull/19833) +- Add missing environment variable documentation - [PR #20138](https://github.com/BerriAI/litellm/pull/20138) +- Improve documentation blog index page - [PR #20188](https://github.com/BerriAI/litellm/pull/20188) + +## Infrastructure / Testing Improvements + +- Add test coverage for Router.get_valid_args and improve code coverage reporting - [PR #19797](https://github.com/BerriAI/litellm/pull/19797) +- Add validation of model cost map as CI job - [PR #19993](https://github.com/BerriAI/litellm/pull/19993) +- Add Realtime API benchmarks - [PR #20074](https://github.com/BerriAI/litellm/pull/20074) +- Add Init Containers support in community helm chart - [PR #19816](https://github.com/BerriAI/litellm/pull/19816) +- Add libsndfile to main Dockerfile for ARM64 audio processing support - [PR #19776](https://github.com/BerriAI/litellm/pull/19776) + +## New Contributors + +* @ruanjf made their first contribution in https://github.com/BerriAI/litellm/pull/19551 +* @moh-dev-stack made their first contribution in https://github.com/BerriAI/litellm/pull/19507 +* @formorter made their first contribution in https://github.com/BerriAI/litellm/pull/19498 +* @priyam-that made their first contribution in https://github.com/BerriAI/litellm/pull/19516 +* @marcosgriselli made their first contribution in https://github.com/BerriAI/litellm/pull/19550 +* @natimofeev made their first contribution in https://github.com/BerriAI/litellm/pull/19232 +* @zifeo made their first contribution in https://github.com/BerriAI/litellm/pull/19805 +* @pragyasardana made their first contribution in https://github.com/BerriAI/litellm/pull/19816 +* @ryewilson made their first contribution in https://github.com/BerriAI/litellm/pull/19833 +* @lizhen921 made their first contribution in https://github.com/BerriAI/litellm/pull/19919 +* @boarder7395 made their first contribution in https://github.com/BerriAI/litellm/pull/19666 +* @rushilchugh01 made their first contribution in https://github.com/BerriAI/litellm/pull/19938 +* @cfchase made their first contribution in https://github.com/BerriAI/litellm/pull/19893 +* @ayim made their first contribution in https://github.com/BerriAI/litellm/pull/19872 +* @varunsripad123 made their first contribution in https://github.com/BerriAI/litellm/pull/20018 +* @nht1206 made their first contribution in https://github.com/BerriAI/litellm/pull/20046 +* @genga6 made their first contribution in https://github.com/BerriAI/litellm/pull/20009 + +**Full Changelog**: https://github.com/BerriAI/litellm/compare/v1.81.3.rc...v1.81.6 diff --git a/docs/my-website/sidebars.js b/docs/my-website/sidebars.js index 85573599e44..fda0e3be4e4 100644 --- a/docs/my-website/sidebars.js +++ b/docs/my-website/sidebars.js @@ -79,6 +79,7 @@ const sidebars = { "proxy/guardrails/panw_prisma_airs", "proxy/guardrails/secret_detection", "proxy/guardrails/custom_guardrail", + "proxy/guardrails/custom_code_guardrail", "proxy/guardrails/prompt_injection", "proxy/guardrails/tool_permission", "proxy/guardrails/zscaler_ai_guard", @@ -139,6 +140,22 @@ const sidebars = { "tutorials/openai_codex" ] }, + { + type: "category", + label: "Agent SDKs", + link: { + type: "generated-index", + title: "Agent SDKs", + description: "Use LiteLLM with agent frameworks and SDKs", + slug: "/agent_sdks" + }, + items: [ + "tutorials/claude_agent_sdk", + "tutorials/copilotkit_sdk", + "tutorials/google_adk", + "tutorials/livekit_xai_realtime", + ] + }, ], // But you can create a sidebar manually @@ -274,11 +291,19 @@ const sidebars = { "proxy/custom_sso", "proxy/ai_hub", "proxy/model_compare_ui", - "proxy/public_teams", - "proxy/self_serve", - "proxy/ui/bulk_edit_users", "proxy/ui_credentials", "tutorials/scim_litellm", + { + type: "category", + label: "UI User/Team Management", + items: [ + "proxy/access_control", + "proxy/public_teams", + "proxy/self_serve", + "proxy/ui/bulk_edit_users", + "proxy/ui/page_visibility", + ] + }, { type: "category", label: "UI Usage Tracking", @@ -292,6 +317,7 @@ const sidebars = { label: "UI Logs", items: [ "proxy/ui_logs", + "proxy/ui_spend_log_settings", "proxy/ui_logs_sessions", "proxy/deleted_keys_teams" ] @@ -364,6 +390,7 @@ const sidebars = { label: "Load Balancing, Routing, Fallbacks", href: "https://docs.litellm.ai/docs/routing-load-balancing", }, + "traffic_mirroring", { type: "category", label: "Logging, Alerting, Metrics", @@ -418,6 +445,7 @@ const sidebars = { label: "Spend Tracking", items: [ "proxy/cost_tracking", + "proxy/request_tags", "proxy/custom_pricing", "proxy/pricing_calculator", "proxy/provider_margins", @@ -444,6 +472,7 @@ const sidebars = { label: "/a2a - A2A Agent Gateway", items: [ "a2a", + "a2a_invoking_agents", "a2a_cost_tracking", "a2a_agent_permissions" ], @@ -513,6 +542,7 @@ const sidebars = { items: [ "mcp", "mcp_usage", + "mcp_semantic_filter", "mcp_control", "mcp_cost", "mcp_guardrail", @@ -691,6 +721,7 @@ const sidebars = { "providers/bedrock_agents", "providers/bedrock_writer", "providers/bedrock_batches", + "providers/bedrock_realtime_with_audio", "providers/aws_polly", "providers/bedrock_vector_store", ] @@ -775,6 +806,7 @@ const sidebars = { "providers/oci", "providers/ollama", "providers/openrouter", + "providers/sarvam", "providers/ovhcloud", "providers/perplexity", "providers/petals", @@ -822,7 +854,14 @@ const sidebars = { "providers/watsonx/audio_transcription", ] }, - "providers/xai", + { + type: "category", + label: "xAI", + items: [ + "providers/xai", + "providers/xai_realtime", + ] + }, "providers/xiaomi_mimo", "providers/xinference", "providers/zai", @@ -921,7 +960,6 @@ const sidebars = { type: "category", label: "LiteLLM Python SDK Tutorials", items: [ - 'tutorials/google_adk', 'tutorials/azure_openai', 'tutorials/instructor', "tutorials/gradio_integration", @@ -1017,6 +1055,7 @@ const sidebars = { type: "category", label: "Issue Reporting", items: [ + "troubleshoot/prisma_migrations", "troubleshoot/cpu_issues", "troubleshoot/memory_issues", "troubleshoot/spend_queue_warnings", diff --git a/docs/my-website/src/theme/BlogListPage/index.js b/docs/my-website/src/theme/BlogListPage/index.js new file mode 100644 index 00000000000..277556a3528 --- /dev/null +++ b/docs/my-website/src/theme/BlogListPage/index.js @@ -0,0 +1,123 @@ +import React from 'react'; +import Layout from '@theme/Layout'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +const TAG_COLORS = { + gemini: {bg: '#d2e3fc', text: '#174ea6', darkBg: '#1a3a5c', darkText: '#8ab4f8'}, + anthropic: {bg: '#fde0c4', text: '#b33d00', darkBg: '#4a2800', darkText: '#ffb74d'}, + claude: {bg: '#fde0c4', text: '#b33d00', darkBg: '#4a2800', darkText: '#ffb74d'}, + llms: {bg: '#c8e6c9', text: '#1b5e20', darkBg: '#1b3d1f', darkText: '#81c784'}, +}; + +function hashHue(str) { + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + return Math.abs(hash) % 360; +} + +function getTagColor(label) { + const key = label.toLowerCase(); + for (const [k, v] of Object.entries(TAG_COLORS)) { + if (key === k) return v; + } + const hue = hashHue(key); + return { + bg: `hsl(${hue}, 40%, 90%)`, + text: `hsl(${hue}, 60%, 25%)`, + darkBg: `hsl(${hue}, 40%, 20%)`, + darkText: `hsl(${hue}, 50%, 75%)`, + }; +} + +function formatDate(dateStr) { + const d = new Date(dateStr); + const now = new Date(); + const diffDays = Math.floor((now - d) / (1000 * 60 * 60 * 24)); + if (diffDays <= 0) return 'Today'; + if (diffDays === 1) return '1d ago'; + if (diffDays < 30) return `${diffDays}d ago`; + return d.toLocaleDateString('en-US', {month: 'short', day: 'numeric', year: 'numeric'}); +} + +function BlogCard({post, featured}) { + const {title, permalink, date, description, tags} = post; + const visibleTags = (tags || []).slice(0, 3); + + return ( + +
+
+ + {featured && Latest} +
+

{title}

+ {description &&

{description}

} + {visibleTags.length > 0 && ( +
+ {visibleTags.map(tag => { + const c = getTagColor(tag.label); + return ( + {tag.label} + ); + })} +
+ )} + +
+ + ); +} + +function Pagination({metadata}) { + const {previousPage, nextPage} = metadata; + if (!previousPage && !nextPage) return null; + return ( + + ); +} + +export default function BlogListPage(props) { + const items = props.items || []; + const metadata = props.metadata || {}; + const [first, ...rest] = items; + + return ( + +
+

The LiteLLM Blog

+

Guides, announcements, and best practices from the LiteLLM team.

+
+ +
+ {first && ( + + )} + {rest.map(({content}) => ( + + ))} +
+ + +
+ ); +} diff --git a/docs/my-website/src/theme/BlogListPage/styles.module.css b/docs/my-website/src/theme/BlogListPage/styles.module.css new file mode 100644 index 00000000000..747c9846a2c --- /dev/null +++ b/docs/my-website/src/theme/BlogListPage/styles.module.css @@ -0,0 +1,163 @@ +.hero { + max-width: 960px; + margin: 0 auto; + padding: 3rem 1.5rem 1rem; + text-align: center; +} + +.heroTitle { + font-size: 2.25rem; + font-weight: 700; + margin-bottom: 0.25rem; + letter-spacing: -0.02em; +} + +.heroSubtitle { + color: var(--ifm-color-emphasis-600); + font-size: 1.1rem; + margin-bottom: 0; +} + +.grid { + max-width: 960px; + margin: 0 auto; + padding: 1.5rem; + display: grid; + gap: 1rem; +} + +.cardLink { + display: block; + text-decoration: none; + color: inherit; +} + +.card { + position: relative; + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 12px; + padding: 1.5rem; + padding-right: 2.5rem; + height: 100%; + transition: border-color 0.15s, transform 0.15s, background 0.15s; + background: var(--ifm-background-surface-color, var(--ifm-background-color)); +} + +.card:hover { + border-color: var(--ifm-color-primary); + transform: translateY(-2px); + background: var(--ifm-color-emphasis-100); +} + +.cardFeatured { + composes: card; + border-color: var(--ifm-color-primary-lighter); + background: var(--ifm-color-emphasis-100); +} + +.meta { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.5rem; +} + +.time { + font-size: 0.8rem; + font-weight: 500; + color: var(--ifm-color-emphasis-600); + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.badge { + font-size: 0.65rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; + padding: 2px 8px; + border-radius: 99px; + background: var(--ifm-color-primary); + color: #fff; +} + +.title { + font-size: 1.15rem; + font-weight: 600; + margin: 0 0 0.4rem; + line-height: 1.35; +} + +.desc { + font-size: 0.88rem; + color: var(--ifm-color-emphasis-700); + line-height: 1.5; + margin: 0 0 0.75rem; +} + +.tags { + display: flex; + gap: 6px; + flex-wrap: wrap; +} + +.tag { + font-size: 0.7rem; + font-weight: 500; + padding: 2px 10px; + border-radius: 99px; + background: var(--tag-bg); + color: var(--tag-text); +} + +:global([data-theme='dark']) .tag { + background: var(--tag-bg-dark); + color: var(--tag-text-dark); +} + +.arrow { + position: absolute; + right: 1rem; + top: 50%; + transform: translateY(-50%); + color: var(--ifm-color-emphasis-400); + transition: color 0.15s, transform 0.15s; +} + +.card:hover .arrow { + color: var(--ifm-color-primary); + transform: translateY(-50%) translateX(3px); +} + +.pagination { + max-width: 960px; + margin: 0 auto; + padding: 1rem 1.5rem 3rem; + display: flex; + justify-content: space-between; +} + +.paginationLink { + font-size: 0.9rem; + font-weight: 500; + color: var(--ifm-color-primary); + text-decoration: none; +} + +.paginationLink:hover { + text-decoration: underline; +} + +@media (min-width: 640px) { + .grid { + grid-template-columns: repeat(2, 1fr); + } + + .grid .cardLink:first-child { + grid-column: 1 / -1; + } + + .grid .cardLink:last-child:nth-child(even) { + grid-column: 1 / -1; + } +} diff --git a/enterprise/dist/litellm_enterprise-0.1.29-py3-none-any.whl b/enterprise/dist/litellm_enterprise-0.1.29-py3-none-any.whl new file mode 100644 index 00000000000..0895ecbc427 Binary files /dev/null and b/enterprise/dist/litellm_enterprise-0.1.29-py3-none-any.whl differ diff --git a/enterprise/dist/litellm_enterprise-0.1.29.tar.gz b/enterprise/dist/litellm_enterprise-0.1.29.tar.gz new file mode 100644 index 00000000000..6781cf26cc9 Binary files /dev/null and b/enterprise/dist/litellm_enterprise-0.1.29.tar.gz differ diff --git a/enterprise/litellm_enterprise/proxy/auth/route_checks.py b/enterprise/litellm_enterprise/proxy/auth/route_checks.py index 6cce781faf3..6f7cf9143f4 100644 --- a/enterprise/litellm_enterprise/proxy/auth/route_checks.py +++ b/enterprise/litellm_enterprise/proxy/auth/route_checks.py @@ -36,7 +36,7 @@ class EnterpriseRouteChecks: if not premium_user: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"🚨🚨🚨 DISABLING LLM API ENDPOINTS is an Enterprise feature\n🚨 {CommonProxyErrors.not_premium_user.value}", + detail=f"🚨🚨🚨 DISABLING ADMIN ENDPOINTS is an Enterprise feature\n🚨 {CommonProxyErrors.not_premium_user.value}", ) return get_secret_bool("DISABLE_ADMIN_ENDPOINTS") is True diff --git a/enterprise/litellm_enterprise/proxy/common_utils/check_batch_cost.py b/enterprise/litellm_enterprise/proxy/common_utils/check_batch_cost.py index d4ee4042b1a..bb25e4f0626 100644 --- a/enterprise/litellm_enterprise/proxy/common_utils/check_batch_cost.py +++ b/enterprise/litellm_enterprise/proxy/common_utils/check_batch_cost.py @@ -53,7 +53,7 @@ class CheckBatchCost: jobs = await self.prisma_client.db.litellm_managedobjecttable.find_many( where={ - "status": "validating", + "status": {"in": ["validating", "in_progress", "finalizing"]}, "file_purpose": "batch", } ) diff --git a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py index 445d2b242b4..569ea17f6d8 100644 --- a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py +++ b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py @@ -166,7 +166,11 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): "updated_by": user_api_key_dict.user_id, "status": file_object.status, }, - "update": {}, # don't do anything if it already exists + "update": { + "file_object": file_object.model_dump_json(), + "status": file_object.status, + "updated_by": user_api_key_dict.user_id, + }, # FIX: Update status and file_object on every operation to keep state in sync }, ) @@ -244,6 +248,78 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): return managed_object.created_by == user_id return True # don't raise error if managed object is not found + async def list_user_batches( + self, + user_api_key_dict: UserAPIKeyAuth, + limit: Optional[int] = None, + after: Optional[str] = None, + provider: Optional[str] = None, + target_model_names: Optional[str] = None, + llm_router: Optional[Router] = None, + ) -> Dict[str, Any]: + # Provider filtering is not supported for managed batches + # This is because the encoded object ids stored in the managed objects table do not contain the provider information + # To support provider filtering, we would need to store the provider information in the encoded object ids + if provider: + raise Exception( + "Filtering by 'provider' is not supported when using managed batches." + ) + + # Model name filtering is not supported for managed batches + # This is because the encoded object ids stored in the managed objects table do not contain the model name + # A hash of the model name + litellm_params for the model name is encoded as the model id. This is not sufficient to reliably map the target model names to the model ids. + if target_model_names: + raise Exception( + "Filtering by 'target_model_names' is not supported when using managed batches." + ) + + where_clause: Dict[str, Any] = {"file_purpose": "batch"} + + # Filter by user who created the batch + if user_api_key_dict.user_id: + where_clause["created_by"] = user_api_key_dict.user_id + + if after: + where_clause["id"] = {"gt": after} + + # Fetch more than needed to allow for post-fetch filtering + fetch_limit = limit or 20 + if target_model_names: + # Fetch extra to account for filtering + fetch_limit = max(fetch_limit * 3, 100) + + batches = await self.prisma_client.db.litellm_managedobjecttable.find_many( + where=where_clause, + take=fetch_limit, + order={"created_at": "desc"}, + ) + + batch_objects: List[LiteLLMBatch] = [] + for batch in batches: + try: + # Stop once we have enough after filtering + if len(batch_objects) >= (limit or 20): + break + + batch_data = json.loads(batch.file_object) if isinstance(batch.file_object, str) else batch.file_object + batch_obj = LiteLLMBatch(**batch_data) + batch_obj.id = batch.unified_object_id + batch_objects.append(batch_obj) + + except Exception as e: + verbose_logger.warning( + f"Failed to parse batch object {batch.unified_object_id}: {e}" + ) + continue + + return { + "object": "list", + "data": batch_objects, + "first_id": batch_objects[0].id if batch_objects else None, + "last_id": batch_objects[-1].id if batch_objects else None, + "has_more": len(batch_objects) == (limit or 20), + } + async def get_user_created_file_ids( self, user_api_key_dict: UserAPIKeyAuth, model_object_ids: List[str] ) -> List[OpenAIFileObject]: @@ -282,6 +358,31 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): ) return False + async def check_file_ids_access( + self, file_ids: List[str], user_api_key_dict: UserAPIKeyAuth + ) -> None: + """ + Check if the user has access to a list of file IDs. + Only checks managed (unified) file IDs. + + Args: + file_ids: List of file IDs to check access for + user_api_key_dict: User API key authentication details + + Raises: + HTTPException: If user doesn't have access to any of the files + """ + for file_id in file_ids: + is_unified_file_id = _is_base64_encoded_unified_file_id(file_id) + if is_unified_file_id: + if not await self.can_user_call_unified_file_id( + file_id, user_api_key_dict + ): + raise HTTPException( + status_code=403, + detail=f"User {user_api_key_dict.user_id} does not have access to the file {file_id}", + ) + async def async_pre_call_hook( # noqa: PLR0915 self, user_api_key_dict: UserAPIKeyAuth, @@ -297,6 +398,8 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): if ( call_type == CallTypes.afile_content.value or call_type == CallTypes.afile_delete.value + or call_type == CallTypes.afile_retrieve.value + or call_type == CallTypes.afile_content.value ): await self.check_managed_file_id_access(data, user_api_key_dict) @@ -313,6 +416,9 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): if messages: file_ids = self.get_file_ids_from_messages(messages) if file_ids: + # Check user has access to all managed files + await self.check_file_ids_access(file_ids, user_api_key_dict) + # Check if any files are stored in storage backends and need base64 conversion # This is needed for Vertex AI/Gemini which requires base64 content is_vertex_ai = model and ("vertex_ai" in model or "gemini" in model.lower()) @@ -328,15 +434,27 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): ) data["model_file_id_mapping"] = model_file_id_mapping elif call_type == CallTypes.aresponses.value or call_type == CallTypes.responses.value: - # Handle managed files in responses API input + # Handle managed files in responses API input and tools + file_ids = [] + + # Extract file IDs from input parameter input_data = data.get("input") if input_data: - file_ids = self.get_file_ids_from_responses_input(input_data) - if file_ids: - model_file_id_mapping = await self.get_model_file_id_mapping( - file_ids, user_api_key_dict.parent_otel_span - ) - data["model_file_id_mapping"] = model_file_id_mapping + file_ids.extend(self.get_file_ids_from_responses_input(input_data)) + + # Extract file IDs from tools parameter (e.g., code_interpreter container) + tools = data.get("tools") + if tools: + file_ids.extend(self.get_file_ids_from_responses_tools(tools)) + + if file_ids: + # Check user has access to all managed files + await self.check_file_ids_access(file_ids, user_api_key_dict) + + model_file_id_mapping = await self.get_model_file_id_mapping( + file_ids, user_api_key_dict.parent_otel_span + ) + data["model_file_id_mapping"] = model_file_id_mapping elif call_type == CallTypes.afile_content.value: retrieve_file_id = cast(Optional[str], data.get("file_id")) potential_file_id = ( @@ -361,12 +479,16 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): data["model_file_id_mapping"] = model_file_id_mapping elif ( call_type == CallTypes.aretrieve_batch.value + or call_type == CallTypes.acancel_batch.value or call_type == CallTypes.acancel_fine_tuning_job.value or call_type == CallTypes.aretrieve_fine_tuning_job.value ): accessor_key: Optional[str] = None retrieve_object_id: Optional[str] = None - if call_type == CallTypes.aretrieve_batch.value: + if ( + call_type == CallTypes.aretrieve_batch.value + or call_type == CallTypes.acancel_batch.value + ): accessor_key = "batch_id" elif ( call_type == CallTypes.acancel_fine_tuning_job.value @@ -534,6 +656,41 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): return file_ids + def get_file_ids_from_responses_tools( + self, tools: List[Dict[str, Any]] + ) -> List[str]: + """ + Gets file ids from responses API tools parameter. + + The tools can contain code_interpreter with container.file_ids: + [ + { + "type": "code_interpreter", + "container": {"type": "auto", "file_ids": ["file-123", "file-456"]} + } + ] + """ + file_ids: List[str] = [] + + if not isinstance(tools, list): + return file_ids + + for tool in tools: + if not isinstance(tool, dict): + continue + + # Check for code_interpreter with container file_ids + if tool.get("type") == "code_interpreter": + container = tool.get("container") + if isinstance(container, dict): + container_file_ids = container.get("file_ids") + if isinstance(container_file_ids, list): + for file_id in container_file_ids: + if isinstance(file_id, str): + file_ids.append(file_id) + + return file_ids + async def get_model_file_id_mapping( self, file_ids: List[str], litellm_parent_otel_span: Span ) -> dict: @@ -673,6 +830,7 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): bytes=file_objects[0].bytes, filename=file_objects[0].filename, status="uploaded", + expires_at=file_objects[0].expires_at, ) return response @@ -893,8 +1051,10 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): delete_response = None specific_model_file_id_mapping = model_file_id_mapping.get(file_id) if specific_model_file_id_mapping: + # Remove conflicting keys from data to avoid duplicate keyword arguments + filtered_data = {k: v for k, v in data.items() if k not in ("model", "file_id")} for model_id, model_file_id in specific_model_file_id_mapping.items(): - delete_response = await llm_router.afile_delete(model=model_id, file_id=model_file_id, **data) # type: ignore + delete_response = await llm_router.afile_delete(model=model_id, file_id=model_file_id, **filtered_data) # type: ignore stored_file_object = await self.delete_unified_file_id( file_id, litellm_parent_otel_span diff --git a/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py b/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py index 21933165217..5e799599862 100644 --- a/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py +++ b/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py @@ -282,6 +282,8 @@ async def get_vector_store_info( updated_at=vector_store.get("updated_at") or None, litellm_credential_name=vector_store.get("litellm_credential_name"), litellm_params=vector_store.get("litellm_params") or None, + team_id=vector_store.get("team_id"), + user_id=vector_store.get("user_id"), ) return {"vector_store": vector_store_pydantic_obj} diff --git a/enterprise/pyproject.toml b/enterprise/pyproject.toml index 0d86460a649..c5aaa0a3407 100644 --- a/enterprise/pyproject.toml +++ b/enterprise/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "litellm-enterprise" -version = "0.1.28" +version = "0.1.29" description = "Package for LiteLLM Enterprise features" authors = ["BerriAI"] readme = "README.md" @@ -22,7 +22,7 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "0.1.28" +version = "0.1.29" version_files = [ "pyproject.toml:version", "../requirements.txt:litellm-enterprise==", diff --git a/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.28-py3-none-any.whl b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.28-py3-none-any.whl new file mode 100644 index 00000000000..f119a977e7c Binary files /dev/null and b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.28-py3-none-any.whl differ diff --git a/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.28.tar.gz b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.28.tar.gz new file mode 100644 index 00000000000..e0ecd0c4214 Binary files /dev/null and b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.28.tar.gz differ diff --git a/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.29-py3-none-any.whl b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.29-py3-none-any.whl new file mode 100644 index 00000000000..3e65fb66663 Binary files /dev/null and b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.29-py3-none-any.whl differ diff --git a/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.29.tar.gz b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.29.tar.gz new file mode 100644 index 00000000000..0439f3576b9 Binary files /dev/null and b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.29.tar.gz differ diff --git a/litellm-proxy-extras/litellm_proxy_extras/migrations/20251119131227_add_prompt_versioning/migration.sql b/litellm-proxy-extras/litellm_proxy_extras/migrations/20251119131227_add_prompt_versioning/migration.sql index a9d9528bd24..43eb2401422 100644 --- a/litellm-proxy-extras/litellm_proxy_extras/migrations/20251119131227_add_prompt_versioning/migration.sql +++ b/litellm-proxy-extras/litellm_proxy_extras/migrations/20251119131227_add_prompt_versioning/migration.sql @@ -1,12 +1,12 @@ -- DropIndex -DROP INDEX "LiteLLM_PromptTable_prompt_id_key"; +DROP INDEX IF EXISTS "LiteLLM_PromptTable_prompt_id_key"; -- AlterTable -ALTER TABLE "LiteLLM_PromptTable" ADD COLUMN "version" INTEGER NOT NULL DEFAULT 1; +ALTER TABLE "LiteLLM_PromptTable" +ADD COLUMN "version" INTEGER NOT NULL DEFAULT 1; -- CreateIndex -CREATE INDEX "LiteLLM_PromptTable_prompt_id_idx" ON "LiteLLM_PromptTable"("prompt_id"); +CREATE INDEX "LiteLLM_PromptTable_prompt_id_idx" ON "LiteLLM_PromptTable" ("prompt_id"); -- CreateIndex -CREATE UNIQUE INDEX "LiteLLM_PromptTable_prompt_id_version_key" ON "LiteLLM_PromptTable"("prompt_id", "version"); - +CREATE UNIQUE INDEX "LiteLLM_PromptTable_prompt_id_version_key" ON "LiteLLM_PromptTable" ("prompt_id", "version"); \ No newline at end of file diff --git a/litellm-proxy-extras/litellm_proxy_extras/migrations/20260131150814_add_team_user_to_vector_stores/migration.sql b/litellm-proxy-extras/litellm_proxy_extras/migrations/20260131150814_add_team_user_to_vector_stores/migration.sql new file mode 100644 index 00000000000..2032f76a5de --- /dev/null +++ b/litellm-proxy-extras/litellm_proxy_extras/migrations/20260131150814_add_team_user_to_vector_stores/migration.sql @@ -0,0 +1,10 @@ +-- AlterTable +ALTER TABLE "LiteLLM_ManagedVectorStoresTable" ADD COLUMN "team_id" TEXT, +ADD COLUMN "user_id" TEXT; + +-- CreateIndex +CREATE INDEX "LiteLLM_ManagedVectorStoresTable_team_id_idx" ON "LiteLLM_ManagedVectorStoresTable"("team_id"); + +-- CreateIndex +CREATE INDEX "LiteLLM_ManagedVectorStoresTable_user_id_idx" ON "LiteLLM_ManagedVectorStoresTable"("user_id"); + diff --git a/litellm-proxy-extras/litellm_proxy_extras/schema.prisma b/litellm-proxy-extras/litellm_proxy_extras/schema.prisma index d7aa6e9f0d0..dc49036cb15 100644 --- a/litellm-proxy-extras/litellm_proxy_extras/schema.prisma +++ b/litellm-proxy-extras/litellm_proxy_extras/schema.prisma @@ -5,6 +5,7 @@ datasource client { generator client { provider = "prisma-client-py" + binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x", "linux-musl", "linux-musl-openssl-3.0.x"] } // Budget / Rate Limits for an org @@ -128,6 +129,7 @@ model LiteLLM_TeamTable { team_member_permissions String[] @default([]) policies String[] @default([]) model_id Int? @unique // id for LiteLLM_ModelTable -> stores team-level model aliases + allow_team_guardrail_config Boolean @default(false) // if true, team admin can configure guardrails for this team litellm_organization_table LiteLLM_OrganizationTable? @relation(fields: [organization_id], references: [organization_id]) litellm_model_table LiteLLM_ModelTable? @relation(fields: [model_id], references: [id]) object_permission LiteLLM_ObjectPermissionTable? @relation(fields: [object_permission_id], references: [object_permission_id]) @@ -159,7 +161,8 @@ model LiteLLM_DeletedTeamTable { team_member_permissions String[] @default([]) policies String[] @default([]) model_id Int? // id for LiteLLM_ModelTable -> stores team-level model aliases - + allow_team_guardrail_config Boolean @default(false) + // Original timestamps from team creation/updates created_at DateTime? @map("created_at") updated_at DateTime? @map("updated_at") @@ -760,6 +763,11 @@ model LiteLLM_ManagedVectorStoresTable { updated_at DateTime @updatedAt litellm_credential_name String? litellm_params Json? + team_id String? + user_id String? + + @@index([team_id]) + @@index([user_id]) } // Guardrails table for storing guardrail configurations @@ -768,6 +776,7 @@ model LiteLLM_GuardrailsTable { guardrail_name String @unique litellm_params Json guardrail_info Json? + team_id String? created_at DateTime @default(now()) updated_at DateTime @updatedAt } diff --git a/litellm-proxy-extras/litellm_proxy_extras/utils.py b/litellm-proxy-extras/litellm_proxy_extras/utils.py index 7ffbe95be13..f3155722187 100644 --- a/litellm-proxy-extras/litellm_proxy_extras/utils.py +++ b/litellm-proxy-extras/litellm_proxy_extras/utils.py @@ -18,14 +18,15 @@ def str_to_bool(value: Optional[str]) -> bool: return value.lower() in ("true", "1", "t", "y", "yes") - def _get_prisma_env() -> dict: """Get environment variables for Prisma, handling offline mode if configured.""" prisma_env = os.environ.copy() if str_to_bool(os.getenv("PRISMA_OFFLINE_MODE")): # These env vars prevent Prisma from attempting downloads prisma_env["NPM_CONFIG_PREFER_OFFLINE"] = "true" - prisma_env["NPM_CONFIG_CACHE"] = os.getenv("NPM_CONFIG_CACHE", "/app/.cache/npm") + prisma_env["NPM_CONFIG_CACHE"] = os.getenv( + "NPM_CONFIG_CACHE", "/app/.cache/npm" + ) return prisma_env @@ -34,29 +35,28 @@ def _get_prisma_command() -> str: if str_to_bool(os.getenv("PRISMA_OFFLINE_MODE")): # Primary location where Prisma Python package installs the CLI default_cli_path = "/app/.cache/prisma-python/binaries/node_modules/.bin/prisma" - + # Check if custom path is provided (for flexibility) custom_cli_path = os.getenv("PRISMA_CLI_PATH") if custom_cli_path and os.path.exists(custom_cli_path): logger.info(f"Using custom Prisma CLI at {custom_cli_path}") return custom_cli_path - + # Check the default location if os.path.exists(default_cli_path): logger.info(f"Using cached Prisma CLI at {default_cli_path}") return default_cli_path - + # If not found, log warning and fall back logger.warning( f"Prisma CLI not found at {default_cli_path}. " "Falling back to Python wrapper (may attempt downloads)" ) - + # Fall back to the Python wrapper (will work in online mode) return "prisma" - class ProxyExtrasDBManager: @staticmethod def _get_prisma_dir() -> str: @@ -119,7 +119,7 @@ class ProxyExtrasDBManager: stdout=open(migration_file, "w"), check=True, timeout=30, - env=prisma_env + env=prisma_env, ) # 3. Mark the migration as applied since it represents current state @@ -134,7 +134,7 @@ class ProxyExtrasDBManager: ], check=True, timeout=30, - env=prisma_env + env=prisma_env, ) return True @@ -159,14 +159,20 @@ class ProxyExtrasDBManager: @staticmethod def _roll_back_migration(migration_name: str): """Mark a specific migration as rolled back""" - # Set up environment for offline mode if configured + # Set up environment for offline mode if configured prisma_env = _get_prisma_env() subprocess.run( - [_get_prisma_command(), "migrate", "resolve", "--rolled-back", migration_name], + [ + _get_prisma_command(), + "migrate", + "resolve", + "--rolled-back", + migration_name, + ], timeout=60, check=True, capture_output=True, - env=prisma_env + env=prisma_env, ) @staticmethod @@ -178,7 +184,7 @@ class ProxyExtrasDBManager: timeout=60, check=True, capture_output=True, - env=prisma_env + env=prisma_env, ) @staticmethod @@ -228,6 +234,8 @@ class ProxyExtrasDBManager: r"duplicate key value violates", r"relation .* already exists", r"constraint .* already exists", + r"does not exist", + r"Can't drop database.* because it doesn't exist", ] for pattern in idempotent_patterns: @@ -248,7 +256,7 @@ class ProxyExtrasDBManager: if not database_url: logger.error("DATABASE_URL not set") return - + diff_dir = ( Path(migrations_dir) / "migrations" @@ -283,7 +291,7 @@ class ProxyExtrasDBManager: check=True, timeout=60, stdout=f, - env=_get_prisma_env() + env=_get_prisma_env(), ) except subprocess.CalledProcessError as e: logger.warning(f"Failed to generate migration diff: {e.stderr}") @@ -313,7 +321,7 @@ class ProxyExtrasDBManager: check=True, capture_output=True, text=True, - env=_get_prisma_env() + env=_get_prisma_env(), ) logger.info(f"prisma db execute stdout: {result.stdout}") logger.info("āœ… Migration diff applied successfully") @@ -331,12 +339,18 @@ class ProxyExtrasDBManager: try: logger.info(f"Resolving migration: {migration_name}") subprocess.run( - [_get_prisma_command(), "migrate", "resolve", "--applied", migration_name], + [ + _get_prisma_command(), + "migrate", + "resolve", + "--applied", + migration_name, + ], timeout=60, check=True, capture_output=True, text=True, - env=_get_prisma_env() + env=_get_prisma_env(), ) logger.debug(f"Resolved migration: {migration_name}") except subprocess.CalledProcessError as e: @@ -375,7 +389,7 @@ class ProxyExtrasDBManager: check=True, capture_output=True, text=True, - env=_get_prisma_env() + env=_get_prisma_env(), ) logger.info(f"prisma migrate deploy stdout: {result.stdout}") @@ -397,27 +411,42 @@ class ProxyExtrasDBManager: ) if migration_match: failed_migration = migration_match.group(1) - logger.info( - f"Found failed migration: {failed_migration}, marking as rolled back" - ) - # Mark the failed migration as rolled back - subprocess.run( - [ - _get_prisma_command(), - "migrate", - "resolve", - "--rolled-back", - failed_migration, - ], - timeout=60, - check=True, - capture_output=True, - text=True, - env=_get_prisma_env() - ) - logger.info( - f"āœ… Migration {failed_migration} marked as rolled back... retrying" - ) + if ProxyExtrasDBManager._is_idempotent_error(e.stderr): + logger.info( + f"Migration {failed_migration} failed due to idempotent error (e.g., column already exists), resolving as applied" + ) + ProxyExtrasDBManager._roll_back_migration( + failed_migration + ) + ProxyExtrasDBManager._resolve_specific_migration( + failed_migration + ) + logger.info( + f"āœ… Migration {failed_migration} resolved." + ) + return True + else: + logger.info( + f"Found failed migration: {failed_migration}, marking as rolled back" + ) + # Mark the failed migration as rolled back + subprocess.run( + [ + _get_prisma_command(), + "migrate", + "resolve", + "--rolled-back", + failed_migration, + ], + timeout=60, + check=True, + capture_output=True, + text=True, + env=_get_prisma_env(), + ) + logger.info( + f"āœ… Migration {failed_migration} marked as rolled back... retrying" + ) elif ( "P3005" in e.stderr and "database schema is not empty" in e.stderr diff --git a/litellm-proxy-extras/pyproject.toml b/litellm-proxy-extras/pyproject.toml index 5a0aa364e7d..fb6996b71db 100644 --- a/litellm-proxy-extras/pyproject.toml +++ b/litellm-proxy-extras/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "litellm-proxy-extras" -version = "0.4.27" +version = "0.4.29" description = "Additional files for the LiteLLM Proxy. Reduces the size of the main litellm package." authors = ["BerriAI"] readme = "README.md" @@ -22,7 +22,7 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "0.4.27" +version = "0.4.29" version_files = [ "pyproject.toml:version", "../requirements.txt:litellm-proxy-extras==", diff --git a/litellm/__init__.py b/litellm/__init__.py index e5c09702b9b..8174b9d2655 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -80,6 +80,8 @@ import dotenv litellm_mode = os.getenv("LITELLM_MODE", "DEV") # "PRODUCTION", "DEV" if litellm_mode == "DEV": dotenv.load_dotenv() + + #################################################### if set_verbose: _turn_on_debug() @@ -254,10 +256,13 @@ disable_streaming_logging: bool = False disable_token_counter: bool = False disable_add_transform_inline_image_block: bool = False disable_add_user_agent_to_request_tags: bool = False +disable_anthropic_gemini_context_caching_transform: bool = False extra_spend_tag_headers: Optional[List[str]] = None in_memory_llm_clients_cache: "LLMClientCache" safe_memory_mode: bool = False enable_azure_ad_token_refresh: Optional[bool] = False +# Proxy Authentication - auto-obtain/refresh OAuth2/JWT tokens for LiteLLM Proxy +proxy_auth: Optional[Any] = None ### DEFAULT AZURE API VERSION ### AZURE_DEFAULT_API_VERSION = "2025-02-01-preview" # this is updated to the latest ### DEFAULT WATSONX API VERSION ### @@ -348,7 +353,7 @@ default_team_settings: Optional[List] = None max_user_budget: Optional[float] = None default_max_internal_user_budget: Optional[float] = None max_internal_user_budget: Optional[float] = None -max_ui_session_budget: Optional[float] = 10 # $10 USD budgets for UI Chat sessions +max_ui_session_budget: Optional[float] = 0.25 # $0.25 USD budgets for UI Chat sessions internal_user_budget_duration: Optional[str] = None tag_budget_config: Optional[Dict[str, "BudgetConfig"]] = None max_end_user_budget: Optional[float] = None @@ -1375,6 +1380,7 @@ if TYPE_CHECKING: from .llms.topaz.image_variations.transformation import TopazImageVariationConfig as TopazImageVariationConfig from litellm.llms.openai.completion.transformation import OpenAITextCompletionConfig as OpenAITextCompletionConfig from .llms.groq.chat.transformation import GroqChatConfig as GroqChatConfig + from .llms.a2a.chat.transformation import A2AConfig as A2AConfig from .llms.voyage.embedding.transformation import VoyageEmbeddingConfig as VoyageEmbeddingConfig from .llms.voyage.embedding.transformation_contextual import VoyageContextualEmbeddingConfig as VoyageContextualEmbeddingConfig from .llms.infinity.embedding.transformation import InfinityEmbeddingConfig as InfinityEmbeddingConfig @@ -1467,6 +1473,7 @@ if TYPE_CHECKING: from .llms.azure.chat.gpt_5_transformation import AzureOpenAIGPT5Config as AzureOpenAIGPT5Config from .llms.azure.completion.transformation import AzureOpenAITextConfig as AzureOpenAITextConfig from .llms.hosted_vllm.chat.transformation import HostedVLLMChatConfig as HostedVLLMChatConfig + from .llms.hosted_vllm.embedding.transformation import HostedVLLMEmbeddingConfig as HostedVLLMEmbeddingConfig from .llms.github_copilot.chat.transformation import GithubCopilotConfig as GithubCopilotConfig from .llms.github_copilot.responses.transformation import GithubCopilotResponsesAPIConfig as GithubCopilotResponsesAPIConfig from .llms.github_copilot.embedding.transformation import GithubCopilotEmbeddingConfig as GithubCopilotEmbeddingConfig diff --git a/litellm/_lazy_imports_registry.py b/litellm/_lazy_imports_registry.py index a92c6f95b0e..a01fe9c11db 100644 --- a/litellm/_lazy_imports_registry.py +++ b/litellm/_lazy_imports_registry.py @@ -20,25 +20,53 @@ LITELLM_LOGGING_NAMES = ( # Utils names that support lazy loading via _lazy_import_utils UTILS_NAMES = ( - "exception_type", "get_optional_params", "get_response_string", "token_counter", - "create_pretrained_tokenizer", "create_tokenizer", "supports_function_calling", - "supports_web_search", "supports_url_context", "supports_response_schema", - "supports_parallel_function_calling", "supports_vision", "supports_audio_input", - "supports_audio_output", "supports_system_messages", "supports_reasoning", - "get_litellm_params", "acreate", "get_max_tokens", "get_model_info", - "register_prompt_template", "validate_environment", "check_valid_key", - "register_model", "encode", "decode", "_calculate_retry_after", "_should_retry", - "get_supported_openai_params", "get_api_base", "get_first_chars_messages", - "ModelResponse", "ModelResponseStream", "EmbeddingResponse", "ImageResponse", - "TranscriptionResponse", "TextCompletionResponse", "get_provider_fields", - "ModelResponseListIterator", "get_valid_models", "timeout", - "get_llm_provider", "remove_index_from_tool_calls", + "exception_type", + "get_optional_params", + "get_response_string", + "token_counter", + "create_pretrained_tokenizer", + "create_tokenizer", + "supports_function_calling", + "supports_web_search", + "supports_url_context", + "supports_response_schema", + "supports_parallel_function_calling", + "supports_vision", + "supports_audio_input", + "supports_audio_output", + "supports_system_messages", + "supports_reasoning", + "get_litellm_params", + "acreate", + "get_max_tokens", + "get_model_info", + "register_prompt_template", + "validate_environment", + "check_valid_key", + "register_model", + "encode", + "decode", + "_calculate_retry_after", + "_should_retry", + "get_supported_openai_params", + "get_api_base", + "get_first_chars_messages", + "ModelResponse", + "ModelResponseStream", + "EmbeddingResponse", + "ImageResponse", + "TranscriptionResponse", + "TextCompletionResponse", + "get_provider_fields", + "ModelResponseListIterator", + "get_valid_models", + "timeout", + "get_llm_provider", + "remove_index_from_tool_calls", ) # Token counter names that support lazy loading via _lazy_import_token_counter -TOKEN_COUNTER_NAMES = ( - "get_modified_max_tokens", -) +TOKEN_COUNTER_NAMES = ("get_modified_max_tokens",) # LLM client cache names that support lazy loading via _lazy_import_llm_client_cache LLM_CLIENT_CACHE_NAMES = ( @@ -47,9 +75,7 @@ LLM_CLIENT_CACHE_NAMES = ( ) # Bedrock type names that support lazy loading via _lazy_import_bedrock_types -BEDROCK_TYPES_NAMES = ( - "COHERE_EMBEDDING_INPUT_TYPES", -) +BEDROCK_TYPES_NAMES = ("COHERE_EMBEDDING_INPUT_TYPES",) # Common types from litellm.types.utils that support lazy loading via # _lazy_import_types_utils @@ -187,6 +213,7 @@ LLM_CONFIG_NAMES = ( "TopazImageVariationConfig", "OpenAITextCompletionConfig", "GroqChatConfig", + "A2AConfig", "GenAIHubOrchestrationConfig", "VoyageEmbeddingConfig", "VoyageContextualEmbeddingConfig", @@ -236,6 +263,7 @@ LLM_CONFIG_NAMES = ( "AzureOpenAIGPT5Config", "AzureOpenAITextConfig", "HostedVLLMChatConfig", + "HostedVLLMEmbeddingConfig", # Alias for backwards compatibility "VolcEngineConfig", # Alias for VolcEngineChatConfig "LlamafileChatConfig", @@ -388,7 +416,10 @@ _UTILS_IMPORT_MAP = { "supports_web_search": (".utils", "supports_web_search"), "supports_url_context": (".utils", "supports_url_context"), "supports_response_schema": (".utils", "supports_response_schema"), - "supports_parallel_function_calling": (".utils", "supports_parallel_function_calling"), + "supports_parallel_function_calling": ( + ".utils", + "supports_parallel_function_calling", + ), "supports_vision": (".utils", "supports_vision"), "supports_audio_input": (".utils", "supports_audio_input"), "supports_audio_output": (".utils", "supports_audio_output"), @@ -419,8 +450,14 @@ _UTILS_IMPORT_MAP = { "ModelResponseListIterator": (".utils", "ModelResponseListIterator"), "get_valid_models": (".utils", "get_valid_models"), "timeout": (".timeout", "timeout"), - "get_llm_provider": ("litellm.litellm_core_utils.get_llm_provider_logic", "get_llm_provider"), - "remove_index_from_tool_calls": ("litellm.litellm_core_utils.core_helpers", "remove_index_from_tool_calls"), + "get_llm_provider": ( + "litellm.litellm_core_utils.get_llm_provider_logic", + "get_llm_provider", + ), + "remove_index_from_tool_calls": ( + "litellm.litellm_core_utils.core_helpers", + "remove_index_from_tool_calls", + ), } _COST_CALCULATOR_IMPORT_MAP = { @@ -442,11 +479,17 @@ _TYPES_UTILS_IMPORT_MAP = { } _TOKEN_COUNTER_IMPORT_MAP = { - "get_modified_max_tokens": ("litellm.litellm_core_utils.token_counter", "get_modified_max_tokens"), + "get_modified_max_tokens": ( + "litellm.litellm_core_utils.token_counter", + "get_modified_max_tokens", + ), } _BEDROCK_TYPES_IMPORT_MAP = { - "COHERE_EMBEDDING_INPUT_TYPES": ("litellm.types.llms.bedrock", "COHERE_EMBEDDING_INPUT_TYPES"), + "COHERE_EMBEDDING_INPUT_TYPES": ( + "litellm.types.llms.bedrock", + "COHERE_EMBEDDING_INPUT_TYPES", + ), } _CACHING_IMPORT_MAP = { @@ -458,294 +501,869 @@ _CACHING_IMPORT_MAP = { _LITELLM_LOGGING_IMPORT_MAP = { "Logging": ("litellm.litellm_core_utils.litellm_logging", "Logging"), - "modify_integration": ("litellm.litellm_core_utils.litellm_logging", "modify_integration"), + "modify_integration": ( + "litellm.litellm_core_utils.litellm_logging", + "modify_integration", + ), } _DOTPROMPT_IMPORT_MAP = { - "global_prompt_manager": ("litellm.integrations.dotprompt", "global_prompt_manager"), - "global_prompt_directory": ("litellm.integrations.dotprompt", "global_prompt_directory"), - "set_global_prompt_directory": ("litellm.integrations.dotprompt", "set_global_prompt_directory"), + "global_prompt_manager": ( + "litellm.integrations.dotprompt", + "global_prompt_manager", + ), + "global_prompt_directory": ( + "litellm.integrations.dotprompt", + "global_prompt_directory", + ), + "set_global_prompt_directory": ( + "litellm.integrations.dotprompt", + "set_global_prompt_directory", + ), } _TYPES_IMPORT_MAP = { "GuardrailItem": ("litellm.types.guardrails", "GuardrailItem"), - "DefaultTeamSSOParams": ("litellm.types.proxy.management_endpoints.ui_sso", "DefaultTeamSSOParams"), - "LiteLLM_UpperboundKeyGenerateParams": ("litellm.types.proxy.management_endpoints.ui_sso", "LiteLLM_UpperboundKeyGenerateParams"), - "KeyManagementSystem": ("litellm.types.secret_managers.main", "KeyManagementSystem"), - "PriorityReservationSettings": ("litellm.types.utils", "PriorityReservationSettings"), + "DefaultTeamSSOParams": ( + "litellm.types.proxy.management_endpoints.ui_sso", + "DefaultTeamSSOParams", + ), + "LiteLLM_UpperboundKeyGenerateParams": ( + "litellm.types.proxy.management_endpoints.ui_sso", + "LiteLLM_UpperboundKeyGenerateParams", + ), + "KeyManagementSystem": ( + "litellm.types.secret_managers.main", + "KeyManagementSystem", + ), + "PriorityReservationSettings": ( + "litellm.types.utils", + "PriorityReservationSettings", + ), "CustomLogger": ("litellm.integrations.custom_logger", "CustomLogger"), - "LoggingCallbackManager": ("litellm.litellm_core_utils.logging_callback_manager", "LoggingCallbackManager"), - "DatadogLLMObsInitParams": ("litellm.types.integrations.datadog_llm_obs", "DatadogLLMObsInitParams"), + "LoggingCallbackManager": ( + "litellm.litellm_core_utils.logging_callback_manager", + "LoggingCallbackManager", + ), + "DatadogLLMObsInitParams": ( + "litellm.types.integrations.datadog_llm_obs", + "DatadogLLMObsInitParams", + ), } _LLM_PROVIDER_LOGIC_IMPORT_MAP = { - "get_llm_provider": ("litellm.litellm_core_utils.get_llm_provider_logic", "get_llm_provider"), - "remove_index_from_tool_calls": ("litellm.litellm_core_utils.core_helpers", "remove_index_from_tool_calls"), + "get_llm_provider": ( + "litellm.litellm_core_utils.get_llm_provider_logic", + "get_llm_provider", + ), + "remove_index_from_tool_calls": ( + "litellm.litellm_core_utils.core_helpers", + "remove_index_from_tool_calls", + ), } _LLM_CONFIGS_IMPORT_MAP = { - "AmazonConverseConfig": (".llms.bedrock.chat.converse_transformation", "AmazonConverseConfig"), + "AmazonConverseConfig": ( + ".llms.bedrock.chat.converse_transformation", + "AmazonConverseConfig", + ), "OpenAILikeChatConfig": (".llms.openai_like.chat.handler", "OpenAILikeChatConfig"), - "GaladrielChatConfig": (".llms.galadriel.chat.transformation", "GaladrielChatConfig"), + "GaladrielChatConfig": ( + ".llms.galadriel.chat.transformation", + "GaladrielChatConfig", + ), "GithubChatConfig": (".llms.github.chat.transformation", "GithubChatConfig"), - "AzureAnthropicConfig": (".llms.azure_ai.anthropic.transformation", "AzureAnthropicConfig"), + "AzureAnthropicConfig": ( + ".llms.azure_ai.anthropic.transformation", + "AzureAnthropicConfig", + ), "BytezChatConfig": (".llms.bytez.chat.transformation", "BytezChatConfig"), - "CompactifAIChatConfig": (".llms.compactifai.chat.transformation", "CompactifAIChatConfig"), + "CompactifAIChatConfig": ( + ".llms.compactifai.chat.transformation", + "CompactifAIChatConfig", + ), "EmpowerChatConfig": (".llms.empower.chat.transformation", "EmpowerChatConfig"), "MinimaxChatConfig": (".llms.minimax.chat.transformation", "MinimaxChatConfig"), - "AiohttpOpenAIChatConfig": (".llms.aiohttp_openai.chat.transformation", "AiohttpOpenAIChatConfig"), - "HuggingFaceChatConfig": (".llms.huggingface.chat.transformation", "HuggingFaceChatConfig"), - "HuggingFaceEmbeddingConfig": (".llms.huggingface.embedding.transformation", "HuggingFaceEmbeddingConfig"), + "AiohttpOpenAIChatConfig": ( + ".llms.aiohttp_openai.chat.transformation", + "AiohttpOpenAIChatConfig", + ), + "HuggingFaceChatConfig": ( + ".llms.huggingface.chat.transformation", + "HuggingFaceChatConfig", + ), + "HuggingFaceEmbeddingConfig": ( + ".llms.huggingface.embedding.transformation", + "HuggingFaceEmbeddingConfig", + ), "OobaboogaConfig": (".llms.oobabooga.chat.transformation", "OobaboogaConfig"), "MaritalkConfig": (".llms.maritalk", "MaritalkConfig"), "OpenrouterConfig": (".llms.openrouter.chat.transformation", "OpenrouterConfig"), "DataRobotConfig": (".llms.datarobot.chat.transformation", "DataRobotConfig"), "AnthropicConfig": (".llms.anthropic.chat.transformation", "AnthropicConfig"), - "AnthropicTextConfig": (".llms.anthropic.completion.transformation", "AnthropicTextConfig"), + "AnthropicTextConfig": ( + ".llms.anthropic.completion.transformation", + "AnthropicTextConfig", + ), "GroqSTTConfig": (".llms.groq.stt.transformation", "GroqSTTConfig"), "TritonConfig": (".llms.triton.completion.transformation", "TritonConfig"), - "TritonGenerateConfig": (".llms.triton.completion.transformation", "TritonGenerateConfig"), - "TritonInferConfig": (".llms.triton.completion.transformation", "TritonInferConfig"), - "TritonEmbeddingConfig": (".llms.triton.embedding.transformation", "TritonEmbeddingConfig"), - "HuggingFaceRerankConfig": (".llms.huggingface.rerank.transformation", "HuggingFaceRerankConfig"), + "TritonGenerateConfig": ( + ".llms.triton.completion.transformation", + "TritonGenerateConfig", + ), + "TritonInferConfig": ( + ".llms.triton.completion.transformation", + "TritonInferConfig", + ), + "TritonEmbeddingConfig": ( + ".llms.triton.embedding.transformation", + "TritonEmbeddingConfig", + ), + "HuggingFaceRerankConfig": ( + ".llms.huggingface.rerank.transformation", + "HuggingFaceRerankConfig", + ), "DatabricksConfig": (".llms.databricks.chat.transformation", "DatabricksConfig"), - "DatabricksEmbeddingConfig": (".llms.databricks.embed.transformation", "DatabricksEmbeddingConfig"), + "DatabricksEmbeddingConfig": ( + ".llms.databricks.embed.transformation", + "DatabricksEmbeddingConfig", + ), "PredibaseConfig": (".llms.predibase.chat.transformation", "PredibaseConfig"), "ReplicateConfig": (".llms.replicate.chat.transformation", "ReplicateConfig"), "SnowflakeConfig": (".llms.snowflake.chat.transformation", "SnowflakeConfig"), "CohereRerankConfig": (".llms.cohere.rerank.transformation", "CohereRerankConfig"), - "CohereRerankV2Config": (".llms.cohere.rerank_v2.transformation", "CohereRerankV2Config"), - "AzureAIRerankConfig": (".llms.azure_ai.rerank.transformation", "AzureAIRerankConfig"), - "InfinityRerankConfig": (".llms.infinity.rerank.transformation", "InfinityRerankConfig"), + "CohereRerankV2Config": ( + ".llms.cohere.rerank_v2.transformation", + "CohereRerankV2Config", + ), + "AzureAIRerankConfig": ( + ".llms.azure_ai.rerank.transformation", + "AzureAIRerankConfig", + ), + "InfinityRerankConfig": ( + ".llms.infinity.rerank.transformation", + "InfinityRerankConfig", + ), "JinaAIRerankConfig": (".llms.jina_ai.rerank.transformation", "JinaAIRerankConfig"), - "DeepinfraRerankConfig": (".llms.deepinfra.rerank.transformation", "DeepinfraRerankConfig"), - "HostedVLLMRerankConfig": (".llms.hosted_vllm.rerank.transformation", "HostedVLLMRerankConfig"), - "NvidiaNimRerankConfig": (".llms.nvidia_nim.rerank.transformation", "NvidiaNimRerankConfig"), - "NvidiaNimRankingConfig": (".llms.nvidia_nim.rerank.ranking_transformation", "NvidiaNimRankingConfig"), - "VertexAIRerankConfig": (".llms.vertex_ai.rerank.transformation", "VertexAIRerankConfig"), - "FireworksAIRerankConfig": (".llms.fireworks_ai.rerank.transformation", "FireworksAIRerankConfig"), + "DeepinfraRerankConfig": ( + ".llms.deepinfra.rerank.transformation", + "DeepinfraRerankConfig", + ), + "HostedVLLMRerankConfig": ( + ".llms.hosted_vllm.rerank.transformation", + "HostedVLLMRerankConfig", + ), + "NvidiaNimRerankConfig": ( + ".llms.nvidia_nim.rerank.transformation", + "NvidiaNimRerankConfig", + ), + "NvidiaNimRankingConfig": ( + ".llms.nvidia_nim.rerank.ranking_transformation", + "NvidiaNimRankingConfig", + ), + "VertexAIRerankConfig": ( + ".llms.vertex_ai.rerank.transformation", + "VertexAIRerankConfig", + ), + "FireworksAIRerankConfig": ( + ".llms.fireworks_ai.rerank.transformation", + "FireworksAIRerankConfig", + ), "VoyageRerankConfig": (".llms.voyage.rerank.transformation", "VoyageRerankConfig"), "ClarifaiConfig": (".llms.clarifai.chat.transformation", "ClarifaiConfig"), "AI21ChatConfig": (".llms.ai21.chat.transformation", "AI21ChatConfig"), "LlamaAPIConfig": (".llms.meta_llama.chat.transformation", "LlamaAPIConfig"), - "TogetherAITextCompletionConfig": (".llms.together_ai.completion.transformation", "TogetherAITextCompletionConfig"), - "CloudflareChatConfig": (".llms.cloudflare.chat.transformation", "CloudflareChatConfig"), + "TogetherAITextCompletionConfig": ( + ".llms.together_ai.completion.transformation", + "TogetherAITextCompletionConfig", + ), + "CloudflareChatConfig": ( + ".llms.cloudflare.chat.transformation", + "CloudflareChatConfig", + ), "NovitaConfig": (".llms.novita.chat.transformation", "NovitaConfig"), "PetalsConfig": (".llms.petals.completion.transformation", "PetalsConfig"), "OllamaChatConfig": (".llms.ollama.chat.transformation", "OllamaChatConfig"), "OllamaConfig": (".llms.ollama.completion.transformation", "OllamaConfig"), "SagemakerConfig": (".llms.sagemaker.completion.transformation", "SagemakerConfig"), - "SagemakerChatConfig": (".llms.sagemaker.chat.transformation", "SagemakerChatConfig"), + "SagemakerChatConfig": ( + ".llms.sagemaker.chat.transformation", + "SagemakerChatConfig", + ), "CohereChatConfig": (".llms.cohere.chat.transformation", "CohereChatConfig"), - "AnthropicMessagesConfig": (".llms.anthropic.experimental_pass_through.messages.transformation", "AnthropicMessagesConfig"), - "AmazonAnthropicClaudeMessagesConfig": (".llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation", "AmazonAnthropicClaudeMessagesConfig"), + "AnthropicMessagesConfig": ( + ".llms.anthropic.experimental_pass_through.messages.transformation", + "AnthropicMessagesConfig", + ), + "AmazonAnthropicClaudeMessagesConfig": ( + ".llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation", + "AmazonAnthropicClaudeMessagesConfig", + ), "TogetherAIConfig": (".llms.together_ai.chat", "TogetherAIConfig"), "NLPCloudConfig": (".llms.nlp_cloud.chat.handler", "NLPCloudConfig"), - "VertexGeminiConfig": (".llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini", "VertexGeminiConfig"), - "GoogleAIStudioGeminiConfig": (".llms.gemini.chat.transformation", "GoogleAIStudioGeminiConfig"), - "VertexAIAnthropicConfig": (".llms.vertex_ai.vertex_ai_partner_models.anthropic.transformation", "VertexAIAnthropicConfig"), - "VertexAILlama3Config": (".llms.vertex_ai.vertex_ai_partner_models.llama3.transformation", "VertexAILlama3Config"), - "VertexAIAi21Config": (".llms.vertex_ai.vertex_ai_partner_models.ai21.transformation", "VertexAIAi21Config"), - "AmazonCohereChatConfig": (".llms.bedrock.chat.invoke_handler", "AmazonCohereChatConfig"), - "AmazonBedrockGlobalConfig": (".llms.bedrock.common_utils", "AmazonBedrockGlobalConfig"), - "AmazonAI21Config": (".llms.bedrock.chat.invoke_transformations.amazon_ai21_transformation", "AmazonAI21Config"), - "AmazonInvokeNovaConfig": (".llms.bedrock.chat.invoke_transformations.amazon_nova_transformation", "AmazonInvokeNovaConfig"), - "AmazonQwen2Config": (".llms.bedrock.chat.invoke_transformations.amazon_qwen2_transformation", "AmazonQwen2Config"), - "AmazonQwen3Config": (".llms.bedrock.chat.invoke_transformations.amazon_qwen3_transformation", "AmazonQwen3Config"), + "VertexGeminiConfig": ( + ".llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini", + "VertexGeminiConfig", + ), + "GoogleAIStudioGeminiConfig": ( + ".llms.gemini.chat.transformation", + "GoogleAIStudioGeminiConfig", + ), + "VertexAIAnthropicConfig": ( + ".llms.vertex_ai.vertex_ai_partner_models.anthropic.transformation", + "VertexAIAnthropicConfig", + ), + "VertexAILlama3Config": ( + ".llms.vertex_ai.vertex_ai_partner_models.llama3.transformation", + "VertexAILlama3Config", + ), + "VertexAIAi21Config": ( + ".llms.vertex_ai.vertex_ai_partner_models.ai21.transformation", + "VertexAIAi21Config", + ), + "AmazonCohereChatConfig": ( + ".llms.bedrock.chat.invoke_handler", + "AmazonCohereChatConfig", + ), + "AmazonBedrockGlobalConfig": ( + ".llms.bedrock.common_utils", + "AmazonBedrockGlobalConfig", + ), + "AmazonAI21Config": ( + ".llms.bedrock.chat.invoke_transformations.amazon_ai21_transformation", + "AmazonAI21Config", + ), + "AmazonInvokeNovaConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_nova_transformation", + "AmazonInvokeNovaConfig", + ), + "AmazonQwen2Config": ( + ".llms.bedrock.chat.invoke_transformations.amazon_qwen2_transformation", + "AmazonQwen2Config", + ), + "AmazonQwen3Config": ( + ".llms.bedrock.chat.invoke_transformations.amazon_qwen3_transformation", + "AmazonQwen3Config", + ), # Aliases for backwards compatibility - "VertexAIConfig": (".llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini", "VertexGeminiConfig"), # Alias - "GeminiConfig": (".llms.gemini.chat.transformation", "GoogleAIStudioGeminiConfig"), # Alias - "AmazonAnthropicConfig": (".llms.bedrock.chat.invoke_transformations.anthropic_claude2_transformation", "AmazonAnthropicConfig"), - "AmazonAnthropicClaudeConfig": (".llms.bedrock.chat.invoke_transformations.anthropic_claude3_transformation", "AmazonAnthropicClaudeConfig"), - "AmazonCohereConfig": (".llms.bedrock.chat.invoke_transformations.amazon_cohere_transformation", "AmazonCohereConfig"), - "AmazonLlamaConfig": (".llms.bedrock.chat.invoke_transformations.amazon_llama_transformation", "AmazonLlamaConfig"), - "AmazonDeepSeekR1Config": (".llms.bedrock.chat.invoke_transformations.amazon_deepseek_transformation", "AmazonDeepSeekR1Config"), - "AmazonMistralConfig": (".llms.bedrock.chat.invoke_transformations.amazon_mistral_transformation", "AmazonMistralConfig"), - "AmazonMoonshotConfig": (".llms.bedrock.chat.invoke_transformations.amazon_moonshot_transformation", "AmazonMoonshotConfig"), - "AmazonTitanConfig": (".llms.bedrock.chat.invoke_transformations.amazon_titan_transformation", "AmazonTitanConfig"), - "AmazonTwelveLabsPegasusConfig": (".llms.bedrock.chat.invoke_transformations.amazon_twelvelabs_pegasus_transformation", "AmazonTwelveLabsPegasusConfig"), - "AmazonInvokeConfig": (".llms.bedrock.chat.invoke_transformations.base_invoke_transformation", "AmazonInvokeConfig"), - "AmazonBedrockOpenAIConfig": (".llms.bedrock.chat.invoke_transformations.amazon_openai_transformation", "AmazonBedrockOpenAIConfig"), - "AmazonStabilityConfig": (".llms.bedrock.image_generation.amazon_stability1_transformation", "AmazonStabilityConfig"), - "AmazonStability3Config": (".llms.bedrock.image_generation.amazon_stability3_transformation", "AmazonStability3Config"), - "AmazonNovaCanvasConfig": (".llms.bedrock.image_generation.amazon_nova_canvas_transformation", "AmazonNovaCanvasConfig"), - "AmazonTitanG1Config": (".llms.bedrock.embed.amazon_titan_g1_transformation", "AmazonTitanG1Config"), - "AmazonTitanMultimodalEmbeddingG1Config": (".llms.bedrock.embed.amazon_titan_multimodal_transformation", "AmazonTitanMultimodalEmbeddingG1Config"), + "VertexAIConfig": ( + ".llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini", + "VertexGeminiConfig", + ), # Alias + "GeminiConfig": ( + ".llms.gemini.chat.transformation", + "GoogleAIStudioGeminiConfig", + ), # Alias + "AmazonAnthropicConfig": ( + ".llms.bedrock.chat.invoke_transformations.anthropic_claude2_transformation", + "AmazonAnthropicConfig", + ), + "AmazonAnthropicClaudeConfig": ( + ".llms.bedrock.chat.invoke_transformations.anthropic_claude3_transformation", + "AmazonAnthropicClaudeConfig", + ), + "AmazonCohereConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_cohere_transformation", + "AmazonCohereConfig", + ), + "AmazonLlamaConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_llama_transformation", + "AmazonLlamaConfig", + ), + "AmazonDeepSeekR1Config": ( + ".llms.bedrock.chat.invoke_transformations.amazon_deepseek_transformation", + "AmazonDeepSeekR1Config", + ), + "AmazonMistralConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_mistral_transformation", + "AmazonMistralConfig", + ), + "AmazonMoonshotConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_moonshot_transformation", + "AmazonMoonshotConfig", + ), + "AmazonTitanConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_titan_transformation", + "AmazonTitanConfig", + ), + "AmazonTwelveLabsPegasusConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_twelvelabs_pegasus_transformation", + "AmazonTwelveLabsPegasusConfig", + ), + "AmazonInvokeConfig": ( + ".llms.bedrock.chat.invoke_transformations.base_invoke_transformation", + "AmazonInvokeConfig", + ), + "AmazonBedrockOpenAIConfig": ( + ".llms.bedrock.chat.invoke_transformations.amazon_openai_transformation", + "AmazonBedrockOpenAIConfig", + ), + "AmazonStabilityConfig": ( + ".llms.bedrock.image_generation.amazon_stability1_transformation", + "AmazonStabilityConfig", + ), + "AmazonStability3Config": ( + ".llms.bedrock.image_generation.amazon_stability3_transformation", + "AmazonStability3Config", + ), + "AmazonNovaCanvasConfig": ( + ".llms.bedrock.image_generation.amazon_nova_canvas_transformation", + "AmazonNovaCanvasConfig", + ), + "AmazonTitanG1Config": ( + ".llms.bedrock.embed.amazon_titan_g1_transformation", + "AmazonTitanG1Config", + ), + "AmazonTitanMultimodalEmbeddingG1Config": ( + ".llms.bedrock.embed.amazon_titan_multimodal_transformation", + "AmazonTitanMultimodalEmbeddingG1Config", + ), "CohereV2ChatConfig": (".llms.cohere.chat.v2_transformation", "CohereV2ChatConfig"), - "BedrockCohereEmbeddingConfig": (".llms.bedrock.embed.cohere_transformation", "BedrockCohereEmbeddingConfig"), - "TwelveLabsMarengoEmbeddingConfig": (".llms.bedrock.embed.twelvelabs_marengo_transformation", "TwelveLabsMarengoEmbeddingConfig"), - "AmazonNovaEmbeddingConfig": (".llms.bedrock.embed.amazon_nova_transformation", "AmazonNovaEmbeddingConfig"), + "BedrockCohereEmbeddingConfig": ( + ".llms.bedrock.embed.cohere_transformation", + "BedrockCohereEmbeddingConfig", + ), + "TwelveLabsMarengoEmbeddingConfig": ( + ".llms.bedrock.embed.twelvelabs_marengo_transformation", + "TwelveLabsMarengoEmbeddingConfig", + ), + "AmazonNovaEmbeddingConfig": ( + ".llms.bedrock.embed.amazon_nova_transformation", + "AmazonNovaEmbeddingConfig", + ), "OpenAIConfig": (".llms.openai.openai", "OpenAIConfig"), "MistralEmbeddingConfig": (".llms.openai.openai", "MistralEmbeddingConfig"), - "OpenAIImageVariationConfig": (".llms.openai.image_variations.transformation", "OpenAIImageVariationConfig"), + "OpenAIImageVariationConfig": ( + ".llms.openai.image_variations.transformation", + "OpenAIImageVariationConfig", + ), "DeepInfraConfig": (".llms.deepinfra.chat.transformation", "DeepInfraConfig"), - "DeepgramAudioTranscriptionConfig": (".llms.deepgram.audio_transcription.transformation", "DeepgramAudioTranscriptionConfig"), - "TopazImageVariationConfig": (".llms.topaz.image_variations.transformation", "TopazImageVariationConfig"), - "OpenAITextCompletionConfig": ("litellm.llms.openai.completion.transformation", "OpenAITextCompletionConfig"), + "DeepgramAudioTranscriptionConfig": ( + ".llms.deepgram.audio_transcription.transformation", + "DeepgramAudioTranscriptionConfig", + ), + "TopazImageVariationConfig": ( + ".llms.topaz.image_variations.transformation", + "TopazImageVariationConfig", + ), + "OpenAITextCompletionConfig": ( + "litellm.llms.openai.completion.transformation", + "OpenAITextCompletionConfig", + ), "GroqChatConfig": (".llms.groq.chat.transformation", "GroqChatConfig"), - "GenAIHubOrchestrationConfig": (".llms.sap.chat.transformation", "GenAIHubOrchestrationConfig"), - "VoyageEmbeddingConfig": (".llms.voyage.embedding.transformation", "VoyageEmbeddingConfig"), - "VoyageContextualEmbeddingConfig": (".llms.voyage.embedding.transformation_contextual", "VoyageContextualEmbeddingConfig"), - "InfinityEmbeddingConfig": (".llms.infinity.embedding.transformation", "InfinityEmbeddingConfig"), - "AzureAIStudioConfig": (".llms.azure_ai.chat.transformation", "AzureAIStudioConfig"), + "A2AConfig": (".llms.a2a.chat.transformation", "A2AConfig"), + "GenAIHubOrchestrationConfig": ( + ".llms.sap.chat.transformation", + "GenAIHubOrchestrationConfig", + ), + "VoyageEmbeddingConfig": ( + ".llms.voyage.embedding.transformation", + "VoyageEmbeddingConfig", + ), + "VoyageContextualEmbeddingConfig": ( + ".llms.voyage.embedding.transformation_contextual", + "VoyageContextualEmbeddingConfig", + ), + "InfinityEmbeddingConfig": ( + ".llms.infinity.embedding.transformation", + "InfinityEmbeddingConfig", + ), + "AzureAIStudioConfig": ( + ".llms.azure_ai.chat.transformation", + "AzureAIStudioConfig", + ), "MistralConfig": (".llms.mistral.chat.transformation", "MistralConfig"), - "OpenAIResponsesAPIConfig": (".llms.openai.responses.transformation", "OpenAIResponsesAPIConfig"), - "AzureOpenAIResponsesAPIConfig": (".llms.azure.responses.transformation", "AzureOpenAIResponsesAPIConfig"), - "AzureOpenAIOSeriesResponsesAPIConfig": (".llms.azure.responses.o_series_transformation", "AzureOpenAIOSeriesResponsesAPIConfig"), - "XAIResponsesAPIConfig": (".llms.xai.responses.transformation", "XAIResponsesAPIConfig"), - "LiteLLMProxyResponsesAPIConfig": (".llms.litellm_proxy.responses.transformation", "LiteLLMProxyResponsesAPIConfig"), - "VolcEngineResponsesAPIConfig": (".llms.volcengine.responses.transformation", "VolcEngineResponsesAPIConfig"), - "ManusResponsesAPIConfig": (".llms.manus.responses.transformation", "ManusResponsesAPIConfig"), - "GoogleAIStudioInteractionsConfig": (".llms.gemini.interactions.transformation", "GoogleAIStudioInteractionsConfig"), - "OpenAIOSeriesConfig": (".llms.openai.chat.o_series_transformation", "OpenAIOSeriesConfig"), - "AnthropicSkillsConfig": (".llms.anthropic.skills.transformation", "AnthropicSkillsConfig"), - "BaseSkillsAPIConfig": (".llms.base_llm.skills.transformation", "BaseSkillsAPIConfig"), + "OpenAIResponsesAPIConfig": ( + ".llms.openai.responses.transformation", + "OpenAIResponsesAPIConfig", + ), + "AzureOpenAIResponsesAPIConfig": ( + ".llms.azure.responses.transformation", + "AzureOpenAIResponsesAPIConfig", + ), + "AzureOpenAIOSeriesResponsesAPIConfig": ( + ".llms.azure.responses.o_series_transformation", + "AzureOpenAIOSeriesResponsesAPIConfig", + ), + "XAIResponsesAPIConfig": ( + ".llms.xai.responses.transformation", + "XAIResponsesAPIConfig", + ), + "LiteLLMProxyResponsesAPIConfig": ( + ".llms.litellm_proxy.responses.transformation", + "LiteLLMProxyResponsesAPIConfig", + ), + "VolcEngineResponsesAPIConfig": ( + ".llms.volcengine.responses.transformation", + "VolcEngineResponsesAPIConfig", + ), + "ManusResponsesAPIConfig": ( + ".llms.manus.responses.transformation", + "ManusResponsesAPIConfig", + ), + "GoogleAIStudioInteractionsConfig": ( + ".llms.gemini.interactions.transformation", + "GoogleAIStudioInteractionsConfig", + ), + "OpenAIOSeriesConfig": ( + ".llms.openai.chat.o_series_transformation", + "OpenAIOSeriesConfig", + ), + "AnthropicSkillsConfig": ( + ".llms.anthropic.skills.transformation", + "AnthropicSkillsConfig", + ), + "BaseSkillsAPIConfig": ( + ".llms.base_llm.skills.transformation", + "BaseSkillsAPIConfig", + ), "GradientAIConfig": (".llms.gradient_ai.chat.transformation", "GradientAIConfig"), # Alias for backwards compatibility - "OpenAIO1Config": (".llms.openai.chat.o_series_transformation", "OpenAIOSeriesConfig"), # Alias + "OpenAIO1Config": ( + ".llms.openai.chat.o_series_transformation", + "OpenAIOSeriesConfig", + ), # Alias "OpenAIGPTConfig": (".llms.openai.chat.gpt_transformation", "OpenAIGPTConfig"), "OpenAIGPT5Config": (".llms.openai.chat.gpt_5_transformation", "OpenAIGPT5Config"), - "OpenAIWhisperAudioTranscriptionConfig": (".llms.openai.transcriptions.whisper_transformation", "OpenAIWhisperAudioTranscriptionConfig"), - "OpenAIGPTAudioTranscriptionConfig": (".llms.openai.transcriptions.gpt_transformation", "OpenAIGPTAudioTranscriptionConfig"), - "OpenAIGPTAudioConfig": (".llms.openai.chat.gpt_audio_transformation", "OpenAIGPTAudioConfig"), + "OpenAIWhisperAudioTranscriptionConfig": ( + ".llms.openai.transcriptions.whisper_transformation", + "OpenAIWhisperAudioTranscriptionConfig", + ), + "OpenAIGPTAudioTranscriptionConfig": ( + ".llms.openai.transcriptions.gpt_transformation", + "OpenAIGPTAudioTranscriptionConfig", + ), + "OpenAIGPTAudioConfig": ( + ".llms.openai.chat.gpt_audio_transformation", + "OpenAIGPTAudioConfig", + ), "NvidiaNimConfig": (".llms.nvidia_nim.chat.transformation", "NvidiaNimConfig"), "NvidiaNimEmbeddingConfig": (".llms.nvidia_nim.embed", "NvidiaNimEmbeddingConfig"), - "FeatherlessAIConfig": (".llms.featherless_ai.chat.transformation", "FeatherlessAIConfig"), + "FeatherlessAIConfig": ( + ".llms.featherless_ai.chat.transformation", + "FeatherlessAIConfig", + ), "CerebrasConfig": (".llms.cerebras.chat", "CerebrasConfig"), "BasetenConfig": (".llms.baseten.chat", "BasetenConfig"), "SambanovaConfig": (".llms.sambanova.chat", "SambanovaConfig"), - "SambaNovaEmbeddingConfig": (".llms.sambanova.embedding.transformation", "SambaNovaEmbeddingConfig"), - "FireworksAIConfig": (".llms.fireworks_ai.chat.transformation", "FireworksAIConfig"), - "FireworksAITextCompletionConfig": (".llms.fireworks_ai.completion.transformation", "FireworksAITextCompletionConfig"), - "FireworksAIAudioTranscriptionConfig": (".llms.fireworks_ai.audio_transcription.transformation", "FireworksAIAudioTranscriptionConfig"), - "FireworksAIEmbeddingConfig": (".llms.fireworks_ai.embed.fireworks_ai_transformation", "FireworksAIEmbeddingConfig"), - "FriendliaiChatConfig": (".llms.friendliai.chat.transformation", "FriendliaiChatConfig"), - "JinaAIEmbeddingConfig": (".llms.jina_ai.embedding.transformation", "JinaAIEmbeddingConfig"), + "SambaNovaEmbeddingConfig": ( + ".llms.sambanova.embedding.transformation", + "SambaNovaEmbeddingConfig", + ), + "FireworksAIConfig": ( + ".llms.fireworks_ai.chat.transformation", + "FireworksAIConfig", + ), + "FireworksAITextCompletionConfig": ( + ".llms.fireworks_ai.completion.transformation", + "FireworksAITextCompletionConfig", + ), + "FireworksAIAudioTranscriptionConfig": ( + ".llms.fireworks_ai.audio_transcription.transformation", + "FireworksAIAudioTranscriptionConfig", + ), + "FireworksAIEmbeddingConfig": ( + ".llms.fireworks_ai.embed.fireworks_ai_transformation", + "FireworksAIEmbeddingConfig", + ), + "FriendliaiChatConfig": ( + ".llms.friendliai.chat.transformation", + "FriendliaiChatConfig", + ), + "JinaAIEmbeddingConfig": ( + ".llms.jina_ai.embedding.transformation", + "JinaAIEmbeddingConfig", + ), "XAIChatConfig": (".llms.xai.chat.transformation", "XAIChatConfig"), "ZAIChatConfig": (".llms.zai.chat.transformation", "ZAIChatConfig"), "AIMLChatConfig": (".llms.aiml.chat.transformation", "AIMLChatConfig"), - "VolcEngineChatConfig": (".llms.volcengine.chat.transformation", "VolcEngineChatConfig"), - "CodestralTextCompletionConfig": (".llms.codestral.completion.transformation", "CodestralTextCompletionConfig"), - "AzureOpenAIAssistantsAPIConfig": (".llms.azure.azure", "AzureOpenAIAssistantsAPIConfig"), + "VolcEngineChatConfig": ( + ".llms.volcengine.chat.transformation", + "VolcEngineChatConfig", + ), + "CodestralTextCompletionConfig": ( + ".llms.codestral.completion.transformation", + "CodestralTextCompletionConfig", + ), + "AzureOpenAIAssistantsAPIConfig": ( + ".llms.azure.azure", + "AzureOpenAIAssistantsAPIConfig", + ), "HerokuChatConfig": (".llms.heroku.chat.transformation", "HerokuChatConfig"), "CometAPIConfig": (".llms.cometapi.chat.transformation", "CometAPIConfig"), "AzureOpenAIConfig": (".llms.azure.chat.gpt_transformation", "AzureOpenAIConfig"), - "AzureOpenAIGPT5Config": (".llms.azure.chat.gpt_5_transformation", "AzureOpenAIGPT5Config"), - "AzureOpenAITextConfig": (".llms.azure.completion.transformation", "AzureOpenAITextConfig"), - "HostedVLLMChatConfig": (".llms.hosted_vllm.chat.transformation", "HostedVLLMChatConfig"), + "AzureOpenAIGPT5Config": ( + ".llms.azure.chat.gpt_5_transformation", + "AzureOpenAIGPT5Config", + ), + "AzureOpenAITextConfig": ( + ".llms.azure.completion.transformation", + "AzureOpenAITextConfig", + ), + "HostedVLLMChatConfig": ( + ".llms.hosted_vllm.chat.transformation", + "HostedVLLMChatConfig", + ), + "HostedVLLMEmbeddingConfig": ( + ".llms.hosted_vllm.embedding.transformation", + "HostedVLLMEmbeddingConfig", + ), # Alias for backwards compatibility - "VolcEngineConfig": (".llms.volcengine.chat.transformation", "VolcEngineChatConfig"), # Alias - "LlamafileChatConfig": (".llms.llamafile.chat.transformation", "LlamafileChatConfig"), - "LiteLLMProxyChatConfig": (".llms.litellm_proxy.chat.transformation", "LiteLLMProxyChatConfig"), + "VolcEngineConfig": ( + ".llms.volcengine.chat.transformation", + "VolcEngineChatConfig", + ), # Alias + "LlamafileChatConfig": ( + ".llms.llamafile.chat.transformation", + "LlamafileChatConfig", + ), + "LiteLLMProxyChatConfig": ( + ".llms.litellm_proxy.chat.transformation", + "LiteLLMProxyChatConfig", + ), "VLLMConfig": (".llms.vllm.completion.transformation", "VLLMConfig"), "DeepSeekChatConfig": (".llms.deepseek.chat.transformation", "DeepSeekChatConfig"), "LMStudioChatConfig": (".llms.lm_studio.chat.transformation", "LMStudioChatConfig"), - "LmStudioEmbeddingConfig": (".llms.lm_studio.embed.transformation", "LmStudioEmbeddingConfig"), + "LmStudioEmbeddingConfig": ( + ".llms.lm_studio.embed.transformation", + "LmStudioEmbeddingConfig", + ), "NscaleConfig": (".llms.nscale.chat.transformation", "NscaleConfig"), - "PerplexityChatConfig": (".llms.perplexity.chat.transformation", "PerplexityChatConfig"), - "AzureOpenAIO1Config": (".llms.azure.chat.o_series_transformation", "AzureOpenAIO1Config"), - "IBMWatsonXAIConfig": (".llms.watsonx.completion.transformation", "IBMWatsonXAIConfig"), - "IBMWatsonXChatConfig": (".llms.watsonx.chat.transformation", "IBMWatsonXChatConfig"), - "IBMWatsonXEmbeddingConfig": (".llms.watsonx.embed.transformation", "IBMWatsonXEmbeddingConfig"), - "GenAIHubEmbeddingConfig": (".llms.sap.embed.transformation", "GenAIHubEmbeddingConfig"), - "IBMWatsonXAudioTranscriptionConfig": (".llms.watsonx.audio_transcription.transformation", "IBMWatsonXAudioTranscriptionConfig"), - "GithubCopilotConfig": (".llms.github_copilot.chat.transformation", "GithubCopilotConfig"), - "GithubCopilotResponsesAPIConfig": (".llms.github_copilot.responses.transformation", "GithubCopilotResponsesAPIConfig"), - "GithubCopilotEmbeddingConfig": (".llms.github_copilot.embedding.transformation", "GithubCopilotEmbeddingConfig"), + "PerplexityChatConfig": ( + ".llms.perplexity.chat.transformation", + "PerplexityChatConfig", + ), + "AzureOpenAIO1Config": ( + ".llms.azure.chat.o_series_transformation", + "AzureOpenAIO1Config", + ), + "IBMWatsonXAIConfig": ( + ".llms.watsonx.completion.transformation", + "IBMWatsonXAIConfig", + ), + "IBMWatsonXChatConfig": ( + ".llms.watsonx.chat.transformation", + "IBMWatsonXChatConfig", + ), + "IBMWatsonXEmbeddingConfig": ( + ".llms.watsonx.embed.transformation", + "IBMWatsonXEmbeddingConfig", + ), + "GenAIHubEmbeddingConfig": ( + ".llms.sap.embed.transformation", + "GenAIHubEmbeddingConfig", + ), + "IBMWatsonXAudioTranscriptionConfig": ( + ".llms.watsonx.audio_transcription.transformation", + "IBMWatsonXAudioTranscriptionConfig", + ), + "GithubCopilotConfig": ( + ".llms.github_copilot.chat.transformation", + "GithubCopilotConfig", + ), + "GithubCopilotResponsesAPIConfig": ( + ".llms.github_copilot.responses.transformation", + "GithubCopilotResponsesAPIConfig", + ), + "GithubCopilotEmbeddingConfig": ( + ".llms.github_copilot.embedding.transformation", + "GithubCopilotEmbeddingConfig", + ), "ChatGPTConfig": (".llms.chatgpt.chat.transformation", "ChatGPTConfig"), - "ChatGPTResponsesAPIConfig": (".llms.chatgpt.responses.transformation", "ChatGPTResponsesAPIConfig"), + "ChatGPTResponsesAPIConfig": ( + ".llms.chatgpt.responses.transformation", + "ChatGPTResponsesAPIConfig", + ), "NebiusConfig": (".llms.nebius.chat.transformation", "NebiusConfig"), "WandbConfig": (".llms.wandb.chat.transformation", "WandbConfig"), "GigaChatConfig": (".llms.gigachat.chat.transformation", "GigaChatConfig"), - "GigaChatEmbeddingConfig": (".llms.gigachat.embedding.transformation", "GigaChatEmbeddingConfig"), - "DashScopeChatConfig": (".llms.dashscope.chat.transformation", "DashScopeChatConfig"), + "GigaChatEmbeddingConfig": ( + ".llms.gigachat.embedding.transformation", + "GigaChatEmbeddingConfig", + ), + "DashScopeChatConfig": ( + ".llms.dashscope.chat.transformation", + "DashScopeChatConfig", + ), "MoonshotChatConfig": (".llms.moonshot.chat.transformation", "MoonshotChatConfig"), - "DockerModelRunnerChatConfig": (".llms.docker_model_runner.chat.transformation", "DockerModelRunnerChatConfig"), + "DockerModelRunnerChatConfig": ( + ".llms.docker_model_runner.chat.transformation", + "DockerModelRunnerChatConfig", + ), "V0ChatConfig": (".llms.v0.chat.transformation", "V0ChatConfig"), "OCIChatConfig": (".llms.oci.chat.transformation", "OCIChatConfig"), "MorphChatConfig": (".llms.morph.chat.transformation", "MorphChatConfig"), "RAGFlowConfig": (".llms.ragflow.chat.transformation", "RAGFlowConfig"), "LambdaAIChatConfig": (".llms.lambda_ai.chat.transformation", "LambdaAIChatConfig"), - "HyperbolicChatConfig": (".llms.hyperbolic.chat.transformation", "HyperbolicChatConfig"), - "VercelAIGatewayConfig": (".llms.vercel_ai_gateway.chat.transformation", "VercelAIGatewayConfig"), + "HyperbolicChatConfig": ( + ".llms.hyperbolic.chat.transformation", + "HyperbolicChatConfig", + ), + "VercelAIGatewayConfig": ( + ".llms.vercel_ai_gateway.chat.transformation", + "VercelAIGatewayConfig", + ), "OVHCloudChatConfig": (".llms.ovhcloud.chat.transformation", "OVHCloudChatConfig"), - "OVHCloudEmbeddingConfig": (".llms.ovhcloud.embedding.transformation", "OVHCloudEmbeddingConfig"), - "CometAPIEmbeddingConfig": (".llms.cometapi.embed.transformation", "CometAPIEmbeddingConfig"), + "OVHCloudEmbeddingConfig": ( + ".llms.ovhcloud.embedding.transformation", + "OVHCloudEmbeddingConfig", + ), + "CometAPIEmbeddingConfig": ( + ".llms.cometapi.embed.transformation", + "CometAPIEmbeddingConfig", + ), "LemonadeChatConfig": (".llms.lemonade.chat.transformation", "LemonadeChatConfig"), - "SnowflakeEmbeddingConfig": (".llms.snowflake.embedding.transformation", "SnowflakeEmbeddingConfig"), - "AmazonNovaChatConfig": (".llms.amazon_nova.chat.transformation", "AmazonNovaChatConfig"), + "SnowflakeEmbeddingConfig": ( + ".llms.snowflake.embedding.transformation", + "SnowflakeEmbeddingConfig", + ), + "AmazonNovaChatConfig": ( + ".llms.amazon_nova.chat.transformation", + "AmazonNovaChatConfig", + ), } # Import map for utils module lazy imports _UTILS_MODULE_IMPORT_MAP = { "encoding": ("litellm.main", "encoding"), - "BaseVectorStore": ("litellm.integrations.vector_store_integrations.base_vector_store", "BaseVectorStore"), - "CredentialAccessor": ("litellm.litellm_core_utils.credential_accessor", "CredentialAccessor"), - "exception_type": ("litellm.litellm_core_utils.exception_mapping_utils", "exception_type"), - "get_error_message": ("litellm.litellm_core_utils.exception_mapping_utils", "get_error_message"), - "_get_response_headers": ("litellm.litellm_core_utils.exception_mapping_utils", "_get_response_headers"), - "get_llm_provider": ("litellm.litellm_core_utils.get_llm_provider_logic", "get_llm_provider"), - "_is_non_openai_azure_model": ("litellm.litellm_core_utils.get_llm_provider_logic", "_is_non_openai_azure_model"), - "get_supported_openai_params": ("litellm.litellm_core_utils.get_supported_openai_params", "get_supported_openai_params"), - "LiteLLMResponseObjectHandler": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "LiteLLMResponseObjectHandler"), - "_handle_invalid_parallel_tool_calls": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "_handle_invalid_parallel_tool_calls"), - "convert_to_model_response_object": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "convert_to_model_response_object"), - "convert_to_streaming_response": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "convert_to_streaming_response"), - "convert_to_streaming_response_async": ("litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", "convert_to_streaming_response_async"), - "get_api_base": ("litellm.litellm_core_utils.llm_response_utils.get_api_base", "get_api_base"), - "ResponseMetadata": ("litellm.litellm_core_utils.llm_response_utils.response_metadata", "ResponseMetadata"), - "_parse_content_for_reasoning": ("litellm.litellm_core_utils.prompt_templates.common_utils", "_parse_content_for_reasoning"), - "LiteLLMLoggingObject": ("litellm.litellm_core_utils.redact_messages", "LiteLLMLoggingObject"), - "redact_message_input_output_from_logging": ("litellm.litellm_core_utils.redact_messages", "redact_message_input_output_from_logging"), - "CustomStreamWrapper": ("litellm.litellm_core_utils.streaming_handler", "CustomStreamWrapper"), - "BaseGoogleGenAIGenerateContentConfig": ("litellm.llms.base_llm.google_genai.transformation", "BaseGoogleGenAIGenerateContentConfig"), + "BaseVectorStore": ( + "litellm.integrations.vector_store_integrations.base_vector_store", + "BaseVectorStore", + ), + "CredentialAccessor": ( + "litellm.litellm_core_utils.credential_accessor", + "CredentialAccessor", + ), + "exception_type": ( + "litellm.litellm_core_utils.exception_mapping_utils", + "exception_type", + ), + "get_error_message": ( + "litellm.litellm_core_utils.exception_mapping_utils", + "get_error_message", + ), + "_get_response_headers": ( + "litellm.litellm_core_utils.exception_mapping_utils", + "_get_response_headers", + ), + "get_llm_provider": ( + "litellm.litellm_core_utils.get_llm_provider_logic", + "get_llm_provider", + ), + "_is_non_openai_azure_model": ( + "litellm.litellm_core_utils.get_llm_provider_logic", + "_is_non_openai_azure_model", + ), + "get_supported_openai_params": ( + "litellm.litellm_core_utils.get_supported_openai_params", + "get_supported_openai_params", + ), + "LiteLLMResponseObjectHandler": ( + "litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", + "LiteLLMResponseObjectHandler", + ), + "_handle_invalid_parallel_tool_calls": ( + "litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", + "_handle_invalid_parallel_tool_calls", + ), + "convert_to_model_response_object": ( + "litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", + "convert_to_model_response_object", + ), + "convert_to_streaming_response": ( + "litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", + "convert_to_streaming_response", + ), + "convert_to_streaming_response_async": ( + "litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response", + "convert_to_streaming_response_async", + ), + "get_api_base": ( + "litellm.litellm_core_utils.llm_response_utils.get_api_base", + "get_api_base", + ), + "ResponseMetadata": ( + "litellm.litellm_core_utils.llm_response_utils.response_metadata", + "ResponseMetadata", + ), + "_parse_content_for_reasoning": ( + "litellm.litellm_core_utils.prompt_templates.common_utils", + "_parse_content_for_reasoning", + ), + "LiteLLMLoggingObject": ( + "litellm.litellm_core_utils.redact_messages", + "LiteLLMLoggingObject", + ), + "redact_message_input_output_from_logging": ( + "litellm.litellm_core_utils.redact_messages", + "redact_message_input_output_from_logging", + ), + "CustomStreamWrapper": ( + "litellm.litellm_core_utils.streaming_handler", + "CustomStreamWrapper", + ), + "BaseGoogleGenAIGenerateContentConfig": ( + "litellm.llms.base_llm.google_genai.transformation", + "BaseGoogleGenAIGenerateContentConfig", + ), "BaseOCRConfig": ("litellm.llms.base_llm.ocr.transformation", "BaseOCRConfig"), - "BaseSearchConfig": ("litellm.llms.base_llm.search.transformation", "BaseSearchConfig"), - "BaseTextToSpeechConfig": ("litellm.llms.base_llm.text_to_speech.transformation", "BaseTextToSpeechConfig"), + "BaseSearchConfig": ( + "litellm.llms.base_llm.search.transformation", + "BaseSearchConfig", + ), + "BaseTextToSpeechConfig": ( + "litellm.llms.base_llm.text_to_speech.transformation", + "BaseTextToSpeechConfig", + ), "BedrockModelInfo": ("litellm.llms.bedrock.common_utils", "BedrockModelInfo"), "CohereModelInfo": ("litellm.llms.cohere.common_utils", "CohereModelInfo"), "MistralOCRConfig": ("litellm.llms.mistral.ocr.transformation", "MistralOCRConfig"), "Rules": ("litellm.litellm_core_utils.rules", "Rules"), "AsyncHTTPHandler": ("litellm.llms.custom_httpx.http_handler", "AsyncHTTPHandler"), "HTTPHandler": ("litellm.llms.custom_httpx.http_handler", "HTTPHandler"), - "get_num_retries_from_retry_policy": ("litellm.router_utils.get_retry_from_policy", "get_num_retries_from_retry_policy"), - "reset_retry_policy": ("litellm.router_utils.get_retry_from_policy", "reset_retry_policy"), + "get_num_retries_from_retry_policy": ( + "litellm.router_utils.get_retry_from_policy", + "get_num_retries_from_retry_policy", + ), + "reset_retry_policy": ( + "litellm.router_utils.get_retry_from_policy", + "reset_retry_policy", + ), "get_secret": ("litellm.secret_managers.main", "get_secret"), - "get_coroutine_checker": ("litellm.litellm_core_utils.cached_imports", "get_coroutine_checker"), - "get_litellm_logging_class": ("litellm.litellm_core_utils.cached_imports", "get_litellm_logging_class"), - "get_set_callbacks": ("litellm.litellm_core_utils.cached_imports", "get_set_callbacks"), - "get_litellm_metadata_from_kwargs": ("litellm.litellm_core_utils.core_helpers", "get_litellm_metadata_from_kwargs"), - "map_finish_reason": ("litellm.litellm_core_utils.core_helpers", "map_finish_reason"), - "process_response_headers": ("litellm.litellm_core_utils.core_helpers", "process_response_headers"), - "delete_nested_value": ("litellm.litellm_core_utils.dot_notation_indexing", "delete_nested_value"), - "is_nested_path": ("litellm.litellm_core_utils.dot_notation_indexing", "is_nested_path"), - "_get_base_model_from_litellm_call_metadata": ("litellm.litellm_core_utils.get_litellm_params", "_get_base_model_from_litellm_call_metadata"), - "get_litellm_params": ("litellm.litellm_core_utils.get_litellm_params", "get_litellm_params"), - "_ensure_extra_body_is_safe": ("litellm.litellm_core_utils.llm_request_utils", "_ensure_extra_body_is_safe"), - "get_formatted_prompt": ("litellm.litellm_core_utils.llm_response_utils.get_formatted_prompt", "get_formatted_prompt"), - "get_response_headers": ("litellm.litellm_core_utils.llm_response_utils.get_headers", "get_response_headers"), - "update_response_metadata": ("litellm.litellm_core_utils.llm_response_utils.response_metadata", "update_response_metadata"), + "get_coroutine_checker": ( + "litellm.litellm_core_utils.cached_imports", + "get_coroutine_checker", + ), + "get_litellm_logging_class": ( + "litellm.litellm_core_utils.cached_imports", + "get_litellm_logging_class", + ), + "get_set_callbacks": ( + "litellm.litellm_core_utils.cached_imports", + "get_set_callbacks", + ), + "get_litellm_metadata_from_kwargs": ( + "litellm.litellm_core_utils.core_helpers", + "get_litellm_metadata_from_kwargs", + ), + "map_finish_reason": ( + "litellm.litellm_core_utils.core_helpers", + "map_finish_reason", + ), + "process_response_headers": ( + "litellm.litellm_core_utils.core_helpers", + "process_response_headers", + ), + "delete_nested_value": ( + "litellm.litellm_core_utils.dot_notation_indexing", + "delete_nested_value", + ), + "is_nested_path": ( + "litellm.litellm_core_utils.dot_notation_indexing", + "is_nested_path", + ), + "_get_base_model_from_litellm_call_metadata": ( + "litellm.litellm_core_utils.get_litellm_params", + "_get_base_model_from_litellm_call_metadata", + ), + "get_litellm_params": ( + "litellm.litellm_core_utils.get_litellm_params", + "get_litellm_params", + ), + "_ensure_extra_body_is_safe": ( + "litellm.litellm_core_utils.llm_request_utils", + "_ensure_extra_body_is_safe", + ), + "get_formatted_prompt": ( + "litellm.litellm_core_utils.llm_response_utils.get_formatted_prompt", + "get_formatted_prompt", + ), + "get_response_headers": ( + "litellm.litellm_core_utils.llm_response_utils.get_headers", + "get_response_headers", + ), + "update_response_metadata": ( + "litellm.litellm_core_utils.llm_response_utils.response_metadata", + "update_response_metadata", + ), "executor": ("litellm.litellm_core_utils.thread_pool_executor", "executor"), - "BaseAnthropicMessagesConfig": ("litellm.llms.base_llm.anthropic_messages.transformation", "BaseAnthropicMessagesConfig"), - "BaseAudioTranscriptionConfig": ("litellm.llms.base_llm.audio_transcription.transformation", "BaseAudioTranscriptionConfig"), - "BaseBatchesConfig": ("litellm.llms.base_llm.batches.transformation", "BaseBatchesConfig"), - "BaseContainerConfig": ("litellm.llms.base_llm.containers.transformation", "BaseContainerConfig"), - "BaseEmbeddingConfig": ("litellm.llms.base_llm.embedding.transformation", "BaseEmbeddingConfig"), - "BaseImageEditConfig": ("litellm.llms.base_llm.image_edit.transformation", "BaseImageEditConfig"), - "BaseImageGenerationConfig": ("litellm.llms.base_llm.image_generation.transformation", "BaseImageGenerationConfig"), - "BaseImageVariationConfig": ("litellm.llms.base_llm.image_variations.transformation", "BaseImageVariationConfig"), - "BasePassthroughConfig": ("litellm.llms.base_llm.passthrough.transformation", "BasePassthroughConfig"), - "BaseRealtimeConfig": ("litellm.llms.base_llm.realtime.transformation", "BaseRealtimeConfig"), - "BaseRerankConfig": ("litellm.llms.base_llm.rerank.transformation", "BaseRerankConfig"), - "BaseVectorStoreConfig": ("litellm.llms.base_llm.vector_store.transformation", "BaseVectorStoreConfig"), - "BaseVectorStoreFilesConfig": ("litellm.llms.base_llm.vector_store_files.transformation", "BaseVectorStoreFilesConfig"), - "BaseVideoConfig": ("litellm.llms.base_llm.videos.transformation", "BaseVideoConfig"), - "ANTHROPIC_API_ONLY_HEADERS": ("litellm.types.llms.anthropic", "ANTHROPIC_API_ONLY_HEADERS"), - "AnthropicThinkingParam": ("litellm.types.llms.anthropic", "AnthropicThinkingParam"), + "BaseAnthropicMessagesConfig": ( + "litellm.llms.base_llm.anthropic_messages.transformation", + "BaseAnthropicMessagesConfig", + ), + "BaseAudioTranscriptionConfig": ( + "litellm.llms.base_llm.audio_transcription.transformation", + "BaseAudioTranscriptionConfig", + ), + "BaseBatchesConfig": ( + "litellm.llms.base_llm.batches.transformation", + "BaseBatchesConfig", + ), + "BaseContainerConfig": ( + "litellm.llms.base_llm.containers.transformation", + "BaseContainerConfig", + ), + "BaseEmbeddingConfig": ( + "litellm.llms.base_llm.embedding.transformation", + "BaseEmbeddingConfig", + ), + "BaseImageEditConfig": ( + "litellm.llms.base_llm.image_edit.transformation", + "BaseImageEditConfig", + ), + "BaseImageGenerationConfig": ( + "litellm.llms.base_llm.image_generation.transformation", + "BaseImageGenerationConfig", + ), + "BaseImageVariationConfig": ( + "litellm.llms.base_llm.image_variations.transformation", + "BaseImageVariationConfig", + ), + "BasePassthroughConfig": ( + "litellm.llms.base_llm.passthrough.transformation", + "BasePassthroughConfig", + ), + "BaseRealtimeConfig": ( + "litellm.llms.base_llm.realtime.transformation", + "BaseRealtimeConfig", + ), + "BaseRerankConfig": ( + "litellm.llms.base_llm.rerank.transformation", + "BaseRerankConfig", + ), + "BaseVectorStoreConfig": ( + "litellm.llms.base_llm.vector_store.transformation", + "BaseVectorStoreConfig", + ), + "BaseVectorStoreFilesConfig": ( + "litellm.llms.base_llm.vector_store_files.transformation", + "BaseVectorStoreFilesConfig", + ), + "BaseVideoConfig": ( + "litellm.llms.base_llm.videos.transformation", + "BaseVideoConfig", + ), + "ANTHROPIC_API_ONLY_HEADERS": ( + "litellm.types.llms.anthropic", + "ANTHROPIC_API_ONLY_HEADERS", + ), + "AnthropicThinkingParam": ( + "litellm.types.llms.anthropic", + "AnthropicThinkingParam", + ), "RerankResponse": ("litellm.types.rerank", "RerankResponse"), - "ChatCompletionDeltaToolCallChunk": ("litellm.types.llms.openai", "ChatCompletionDeltaToolCallChunk"), - "ChatCompletionToolCallChunk": ("litellm.types.llms.openai", "ChatCompletionToolCallChunk"), - "ChatCompletionToolCallFunctionChunk": ("litellm.types.llms.openai", "ChatCompletionToolCallFunctionChunk"), + "ChatCompletionDeltaToolCallChunk": ( + "litellm.types.llms.openai", + "ChatCompletionDeltaToolCallChunk", + ), + "ChatCompletionToolCallChunk": ( + "litellm.types.llms.openai", + "ChatCompletionToolCallChunk", + ), + "ChatCompletionToolCallFunctionChunk": ( + "litellm.types.llms.openai", + "ChatCompletionToolCallFunctionChunk", + ), "LiteLLM_Params": ("litellm.types.router", "LiteLLM_Params"), } diff --git a/litellm/a2a_protocol/card_resolver.py b/litellm/a2a_protocol/card_resolver.py new file mode 100644 index 00000000000..7c4c5af149d --- /dev/null +++ b/litellm/a2a_protocol/card_resolver.py @@ -0,0 +1,97 @@ +""" +Custom A2A Card Resolver for LiteLLM. + +Extends the A2A SDK's card resolver to support multiple well-known paths. +""" + +from typing import TYPE_CHECKING, Any, Dict, Optional + +from litellm._logging import verbose_logger + +if TYPE_CHECKING: + from a2a.types import AgentCard + +# Runtime imports with availability check +_A2ACardResolver: Any = None +AGENT_CARD_WELL_KNOWN_PATH: str = "/.well-known/agent-card.json" +PREV_AGENT_CARD_WELL_KNOWN_PATH: str = "/.well-known/agent.json" + +try: + from a2a.client import A2ACardResolver as _A2ACardResolver # type: ignore[no-redef] + from a2a.utils.constants import ( # type: ignore[no-redef] + AGENT_CARD_WELL_KNOWN_PATH, + PREV_AGENT_CARD_WELL_KNOWN_PATH, + ) +except ImportError: + pass + + +class LiteLLMA2ACardResolver(_A2ACardResolver): # type: ignore[misc] + """ + Custom A2A card resolver that supports multiple well-known paths. + + Extends the base A2ACardResolver to try both: + - /.well-known/agent-card.json (standard) + - /.well-known/agent.json (previous/alternative) + """ + + async def get_agent_card( + self, + relative_card_path: Optional[str] = None, + http_kwargs: Optional[Dict[str, Any]] = None, + ) -> "AgentCard": + """ + Fetch the agent card, trying multiple well-known paths. + + First tries the standard path, then falls back to the previous path. + + Args: + relative_card_path: Optional path to the agent card endpoint. + If None, tries both well-known paths. + http_kwargs: Optional dictionary of keyword arguments to pass to httpx.get + + Returns: + AgentCard from the A2A agent + + Raises: + A2AClientHTTPError or A2AClientJSONError if both paths fail + """ + # If a specific path is provided, use the parent implementation + if relative_card_path is not None: + return await super().get_agent_card( + relative_card_path=relative_card_path, + http_kwargs=http_kwargs, + ) + + # Try both well-known paths + paths = [ + AGENT_CARD_WELL_KNOWN_PATH, + PREV_AGENT_CARD_WELL_KNOWN_PATH, + ] + + last_error = None + for path in paths: + try: + verbose_logger.debug( + f"Attempting to fetch agent card from {self.base_url}{path}" + ) + return await super().get_agent_card( + relative_card_path=path, + http_kwargs=http_kwargs, + ) + except Exception as e: + verbose_logger.debug( + f"Failed to fetch agent card from {self.base_url}{path}: {e}" + ) + last_error = e + continue + + # If we get here, all paths failed - re-raise the last error + if last_error is not None: + raise last_error + + # This shouldn't happen, but just in case + raise Exception( + f"Failed to fetch agent card from {self.base_url}. " + f"Tried paths: {', '.join(paths)}" + ) diff --git a/litellm/a2a_protocol/main.py b/litellm/a2a_protocol/main.py index 2d36dbeacda..b326f9e7ed5 100644 --- a/litellm/a2a_protocol/main.py +++ b/litellm/a2a_protocol/main.py @@ -6,10 +6,11 @@ Provides standalone functions with @client decorator for LiteLLM logging integra import asyncio import datetime +import uuid from typing import TYPE_CHECKING, Any, AsyncIterator, Coroutine, Dict, Optional, Union import litellm -from litellm._logging import verbose_logger +from litellm._logging import verbose_logger, verbose_proxy_logger from litellm.a2a_protocol.streaming_iterator import A2AStreamingIterator from litellm.a2a_protocol.utils import A2ARequestUtils from litellm.constants import DEFAULT_A2A_AGENT_TIMEOUT @@ -35,13 +36,18 @@ A2ACardResolver: Any = None _A2AClient: Any = None try: - from a2a.client import A2ACardResolver # type: ignore[no-redef] from a2a.client import A2AClient as _A2AClient # type: ignore[no-redef] A2A_SDK_AVAILABLE = True except ImportError: pass +# Import our custom card resolver that supports multiple well-known paths +from litellm.a2a_protocol.card_resolver import LiteLLMA2ACardResolver + +# Use our custom resolver instead of the default A2A SDK resolver +A2ACardResolver = LiteLLMA2ACardResolver + def _set_usage_on_logging_obj( kwargs: Dict[str, Any], @@ -225,7 +231,11 @@ async def asend_message( raise ValueError( "Either a2a_client or api_base is required for standard A2A flow" ) - a2a_client = await create_a2a_client(base_url=api_base) + trace_id = str(uuid.uuid4()) + extra_headers = {"X-LiteLLM-Trace-Id": trace_id} + if agent_id: + extra_headers["X-LiteLLM-Agent-Id"] = agent_id + a2a_client = await create_a2a_client(base_url=api_base, extra_headers=extra_headers) # Type assertion: a2a_client is guaranteed to be non-None here assert a2a_client is not None @@ -490,6 +500,10 @@ async def create_a2a_client( ) httpx_client = http_handler.client + if extra_headers: + httpx_client.headers.update(extra_headers) + verbose_proxy_logger.debug(f"A2A client created with extra_headers={extra_headers}") + # Resolve agent card resolver = A2ACardResolver( httpx_client=httpx_client, diff --git a/litellm/batches/batch_utils.py b/litellm/batches/batch_utils.py index 8a078eeaca1..f80eae20f3b 100644 --- a/litellm/batches/batch_utils.py +++ b/litellm/batches/batch_utils.py @@ -192,6 +192,9 @@ async def _get_batch_output_file_content_as_dictionary( Get the batch output file content as a list of dictionaries """ from litellm.files.main import afile_content + from litellm.proxy.openai_files_endpoints.common_utils import ( + _is_base64_encoded_unified_file_id, + ) if custom_llm_provider == "vertex_ai": raise ValueError("Vertex AI does not support file content retrieval") @@ -199,8 +202,17 @@ async def _get_batch_output_file_content_as_dictionary( if batch.output_file_id is None: raise ValueError("Output file id is None cannot retrieve file content") + file_id = batch.output_file_id + is_base64_unified_file_id = _is_base64_encoded_unified_file_id(file_id) + if is_base64_unified_file_id: + try: + file_id = is_base64_unified_file_id.split("llm_output_file_id,")[1].split(";")[0] + verbose_logger.debug(f"Extracted LLM output file ID from unified file ID: {file_id}") + except (IndexError, AttributeError) as e: + verbose_logger.error(f"Failed to extract LLM output file ID from unified file ID: {batch.output_file_id}, error: {e}") + _file_content = await afile_content( - file_id=batch.output_file_id, + file_id=file_id, custom_llm_provider=custom_llm_provider, ) return _get_file_content_as_dictionary(_file_content.content) diff --git a/litellm/batches/main.py b/litellm/batches/main.py index 3367f567a7f..25f6e284bcd 100644 --- a/litellm/batches/main.py +++ b/litellm/batches/main.py @@ -31,7 +31,6 @@ from litellm.llms.openai.openai import OpenAIBatchesAPI from litellm.llms.vertex_ai.batches.handler import VertexAIBatchPrediction from litellm.secret_managers.main import get_secret_str from litellm.types.llms.openai import ( - Batch, CancelBatchRequest, CreateBatchRequest, RetrieveBatchRequest, @@ -868,7 +867,7 @@ async def acancel_batch( extra_headers: Optional[Dict[str, str]] = None, extra_body: Optional[Dict[str, str]] = None, **kwargs, -) -> Batch: +) -> LiteLLMBatch: """ Async: Cancels a batch. @@ -877,7 +876,9 @@ async def acancel_batch( try: loop = asyncio.get_event_loop() kwargs["acancel_batch"] = True - model = kwargs.pop("model", None) + # Preserve model parameter - only pop from kwargs if it exists there + # (to avoid passing it twice), otherwise keep the function parameter value + model = kwargs.pop("model", None) or model # Use a partial function to pass your keyword arguments func = partial( @@ -912,7 +913,7 @@ def cancel_batch( extra_headers: Optional[Dict[str, str]] = None, extra_body: Optional[Dict[str, str]] = None, **kwargs, -) -> Union[Batch, Coroutine[Any, Any, Batch]]: +) -> Union[LiteLLMBatch, Coroutine[Any, Any, LiteLLMBatch]]: """ Cancels a batch. diff --git a/litellm/completion_extras/litellm_responses_transformation/transformation.py b/litellm/completion_extras/litellm_responses_transformation/transformation.py index c98799d2542..753a94295b3 100644 --- a/litellm/completion_extras/litellm_responses_transformation/transformation.py +++ b/litellm/completion_extras/litellm_responses_transformation/transformation.py @@ -277,6 +277,8 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): responses_api_request["previous_response_id"] = value elif key == "reasoning_effort": responses_api_request["reasoning"] = self._map_reasoning_effort(value) + elif key == "web_search_options": + self._add_web_search_tool(responses_api_request, value) # Get stream parameter from litellm_params if not in optional_params stream = optional_params.get("stream") or litellm_params.get("stream", False) @@ -327,6 +329,9 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): else: request_data[key] = value + if headers: + request_data["extra_headers"] = headers + return request_data @staticmethod @@ -727,6 +732,34 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): return Reasoning(effort="minimal", summary="detailed") if auto_summary_enabled else Reasoning(effort="minimal") return None + def _add_web_search_tool( + self, + responses_api_request: ResponsesAPIOptionalRequestParams, + web_search_options: Any, + ) -> None: + """ + Add web search tool to responses API request. + + Args: + responses_api_request: The responses API request dict to modify + web_search_options: Web search configuration (dict or other value) + """ + if "tools" not in responses_api_request or responses_api_request["tools"] is None: + responses_api_request["tools"] = [] + + # Get the tools list with proper type narrowing + tools = responses_api_request["tools"] + if tools is None: + tools = [] + responses_api_request["tools"] = tools + + web_search_tool: Dict[str, Any] = {"type": "web_search"} + if isinstance(web_search_options, dict): + web_search_tool.update(web_search_options) + + # Cast to Any to match the expected union type for tools list items + tools.append(cast(Any, web_search_tool)) + def _transform_response_format_to_text_format( self, response_format: Union[Dict[str, Any], Any] ) -> Optional[Dict[str, Any]]: diff --git a/litellm/constants.py b/litellm/constants.py index 49ca3a509b1..444e78f8ed4 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -67,6 +67,20 @@ DEFAULT_REASONING_EFFORT_DISABLE_THINKING_BUDGET = int( os.getenv("DEFAULT_REASONING_EFFORT_DISABLE_THINKING_BUDGET", 0) ) +# MCP Semantic Tool Filter Defaults +DEFAULT_MCP_SEMANTIC_FILTER_EMBEDDING_MODEL = str( + os.getenv("DEFAULT_MCP_SEMANTIC_FILTER_EMBEDDING_MODEL", "text-embedding-3-small") +) +DEFAULT_MCP_SEMANTIC_FILTER_TOP_K = int( + os.getenv("DEFAULT_MCP_SEMANTIC_FILTER_TOP_K", 10) +) +DEFAULT_MCP_SEMANTIC_FILTER_SIMILARITY_THRESHOLD = float( + os.getenv("DEFAULT_MCP_SEMANTIC_FILTER_SIMILARITY_THRESHOLD", 0.3) +) +MAX_MCP_SEMANTIC_FILTER_TOOLS_HEADER_LENGTH = int( + os.getenv("MAX_MCP_SEMANTIC_FILTER_TOOLS_HEADER_LENGTH", 150) +) + # Gemini model-specific minimal thinking budget constants DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET_GEMINI_2_5_FLASH = int( os.getenv("DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET_GEMINI_2_5_FLASH", 1) @@ -85,6 +99,9 @@ DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET = int( os.getenv("DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET", 128) ) +# Provider-specific API base URLs +XAI_API_BASE = "https://api.x.ai/v1" + DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET = int( os.getenv("DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET", 1024) ) @@ -980,6 +997,7 @@ BEDROCK_CONVERSE_MODELS = [ "meta.llama3-2-90b-instruct-v1:0", "amazon.nova-lite-v1:0", "amazon.nova-2-lite-v1:0", + "amazon.nova-2-pro-preview-20251202-v1:0", "amazon.nova-pro-v1:0", "writer.palmyra-x4-v1:0", "writer.palmyra-x5-v1:0", @@ -1165,6 +1183,12 @@ LITELLM_CLI_SOURCE_IDENTIFIER = "litellm-cli" LITELLM_CLI_SESSION_TOKEN_PREFIX = "litellm-session-token" CLI_SSO_SESSION_CACHE_KEY_PREFIX = "cli_sso_session" CLI_JWT_TOKEN_NAME = "cli-jwt-token" +# Support both CLI_JWT_EXPIRATION_HOURS and LITELLM_CLI_JWT_EXPIRATION_HOURS for backwards compatibility +CLI_JWT_EXPIRATION_HOURS = int( + os.getenv("CLI_JWT_EXPIRATION_HOURS") + or os.getenv("LITELLM_CLI_JWT_EXPIRATION_HOURS") + or 24 +) ########################### DB CRON JOB NAMES ########################### DB_SPEND_UPDATE_JOB_NAME = "db_spend_update_job" @@ -1326,6 +1350,13 @@ COROUTINE_CHECKER_MAX_SIZE_IN_MEMORY = int( DEFAULT_CHUNK_SIZE = int(os.getenv("DEFAULT_CHUNK_SIZE", 1000)) DEFAULT_CHUNK_OVERLAP = int(os.getenv("DEFAULT_CHUNK_OVERLAP", 200)) +########################### S3 Vectors RAG Constants ########################### +S3_VECTORS_DEFAULT_DIMENSION = int(os.getenv("S3_VECTORS_DEFAULT_DIMENSION", 1024)) +S3_VECTORS_DEFAULT_DISTANCE_METRIC = str( + os.getenv("S3_VECTORS_DEFAULT_DISTANCE_METRIC", "cosine") +) +S3_VECTORS_DEFAULT_NON_FILTERABLE_METADATA_KEYS = ["source_text"] + ########################### Microsoft SSO Constants ########################### MICROSOFT_USER_EMAIL_ATTRIBUTE = str( os.getenv("MICROSOFT_USER_EMAIL_ATTRIBUTE", "userPrincipalName") diff --git a/litellm/cost_calculator.py b/litellm/cost_calculator.py index 1ab7e260a83..bef4d52ce49 100644 --- a/litellm/cost_calculator.py +++ b/litellm/cost_calculator.py @@ -23,7 +23,11 @@ from litellm.litellm_core_utils.llm_cost_calc.usage_object_transformation import from litellm.litellm_core_utils.llm_cost_calc.utils import ( CostCalculatorUtils, _generic_cost_per_character, + _get_service_tier_cost_key, + _parse_prompt_tokens_details, + calculate_cost_component, generic_cost_per_token, + get_billable_input_tokens, select_cost_metric_for_model, ) from litellm.llms.anthropic.cost_calculation import ( @@ -32,6 +36,9 @@ from litellm.llms.anthropic.cost_calculation import ( from litellm.llms.azure.cost_calculation import ( cost_per_token as azure_openai_cost_per_token, ) +from litellm.llms.azure_ai.cost_calculator import ( + cost_per_token as azure_ai_cost_per_token, +) from litellm.llms.base_llm.search.transformation import SearchResponse from litellm.llms.bedrock.cost_calculation import ( cost_per_token as bedrock_cost_per_token, @@ -134,6 +141,51 @@ def _cost_per_token_custom_pricing_helper( return None +def _get_additional_costs( + model: str, + custom_llm_provider: Optional[str], + prompt_tokens: int, + completion_tokens: int, +) -> Optional[dict]: + """ + Calculate additional costs beyond standard token costs. + + This function delegates to provider-specific config classes to calculate + any additional costs like routing fees, infrastructure costs, etc. + + Args: + model: The model name + custom_llm_provider: The provider name (optional) + prompt_tokens: Number of prompt tokens + completion_tokens: Number of completion tokens + + Returns: + Optional dictionary with cost names and amounts, or None if no additional costs + """ + if not custom_llm_provider: + return None + + try: + config_class = None + if custom_llm_provider == "azure_ai": + from litellm.llms.azure_ai.common_utils import AzureFoundryModelInfo + config_class = AzureFoundryModelInfo.get_azure_ai_config_for_model(model) + # Add more providers here as needed + # elif custom_llm_provider == "other_provider": + # config_class = get_other_provider_config(model) + + if config_class and hasattr(config_class, 'calculate_additional_costs'): + return config_class.calculate_additional_costs( + model=model, + prompt_tokens=prompt_tokens, + completion_tokens=completion_tokens, + ) + except Exception as e: + verbose_logger.debug(f"Error calculating additional costs: {e}") + + return None + + def _transcription_usage_has_token_details( usage_block: Optional[Usage], ) -> bool: @@ -423,20 +475,26 @@ def cost_per_token( # noqa: PLR0915 return dashscope_cost_per_token(model=model, usage=usage_block) elif custom_llm_provider == "azure_ai": - return generic_cost_per_token( - model=model, usage=usage_block, custom_llm_provider=custom_llm_provider + return azure_ai_cost_per_token( + model=model, usage=usage_block, response_time_ms=response_time_ms ) else: model_info = _cached_get_model_info_helper( model=model, custom_llm_provider=custom_llm_provider ) - if model_info["input_cost_per_token"] > 0: - ## COST PER TOKEN ## - prompt_tokens_cost_usd_dollar = ( - model_info["input_cost_per_token"] * prompt_tokens + if ( + model_info.get("input_cost_per_token", 0) > 0 + or model_info.get("output_cost_per_token", 0) > 0 + ): + return generic_cost_per_token( + model=model, + usage=usage_block, + custom_llm_provider=custom_llm_provider, + service_tier=service_tier, ) - elif ( + + if ( model_info.get("input_cost_per_second", None) is not None and response_time_ms is not None ): @@ -451,11 +509,7 @@ def cost_per_token( # noqa: PLR0915 model_info["input_cost_per_second"] * response_time_ms / 1000 # type: ignore ) - if model_info["output_cost_per_token"] > 0: - completion_tokens_cost_usd_dollar = ( - model_info["output_cost_per_token"] * completion_tokens - ) - elif ( + if ( model_info.get("output_cost_per_second", None) is not None and response_time_ms is not None ): @@ -799,6 +853,7 @@ def _store_cost_breakdown_in_logging_obj( completion_tokens_cost_usd_dollar: float, cost_for_built_in_tools_cost_usd_dollar: float, total_cost_usd_dollar: float, + additional_costs: Optional[dict] = None, original_cost: Optional[float] = None, discount_percent: Optional[float] = None, discount_amount: Optional[float] = None, @@ -815,6 +870,7 @@ def _store_cost_breakdown_in_logging_obj( completion_tokens_cost_usd_dollar: Cost of completion tokens (includes reasoning if applicable) cost_for_built_in_tools_cost_usd_dollar: Cost of built-in tools total_cost_usd_dollar: Total cost of request + additional_costs: Free-form additional costs dict (e.g., {"azure_model_router_flat_cost": 0.00014}) original_cost: Cost before discount discount_percent: Discount percentage applied (0.05 = 5%) discount_amount: Discount amount in USD @@ -832,6 +888,7 @@ def _store_cost_breakdown_in_logging_obj( output_cost=completion_tokens_cost_usd_dollar, total_cost=total_cost_usd_dollar, cost_for_built_in_tools_cost_usd_dollar=cost_for_built_in_tools_cost_usd_dollar, + additional_costs=additional_costs, original_cost=original_cost, discount_percent=discount_percent, discount_amount=discount_amount, @@ -955,7 +1012,10 @@ def completion_cost( # noqa: PLR0915 router_model_id=router_model_id, ) - potential_model_names = [selected_model, _get_response_model(completion_response)] + potential_model_names = [ + selected_model, + _get_response_model(completion_response), + ] if model is not None: potential_model_names.append(model) @@ -1326,6 +1386,15 @@ def completion_cost( # noqa: PLR0915 service_tier=service_tier, response=completion_response, ) + + # Get additional costs from provider (e.g., routing fees, infrastructure costs) + additional_costs = _get_additional_costs( + model=model, + custom_llm_provider=custom_llm_provider, + prompt_tokens=prompt_tokens, + completion_tokens=completion_tokens, + ) + _final_cost = ( prompt_tokens_cost_usd_dollar + completion_tokens_cost_usd_dollar ) @@ -1365,6 +1434,7 @@ def completion_cost( # noqa: PLR0915 completion_tokens_cost_usd_dollar=completion_tokens_cost_usd_dollar, cost_for_built_in_tools_cost_usd_dollar=cost_for_built_in_tools, total_cost_usd_dollar=_final_cost, + additional_costs=additional_costs, original_cost=original_cost, discount_percent=discount_percent, discount_amount=discount_amount, @@ -1710,10 +1780,16 @@ def default_image_cost_calculator( ) # Priority 1: Use per-image pricing if available (for gpt-image-1 and similar models) - if "input_cost_per_image" in cost_info and cost_info["input_cost_per_image"] is not None: + if ( + "input_cost_per_image" in cost_info + and cost_info["input_cost_per_image"] is not None + ): return cost_info["input_cost_per_image"] * n # Priority 2: Fall back to per-pixel pricing for backward compatibility - elif "input_cost_per_pixel" in cost_info and cost_info["input_cost_per_pixel"] is not None: + elif ( + "input_cost_per_pixel" in cost_info + and cost_info["input_cost_per_pixel"] is not None + ): return cost_info["input_cost_per_pixel"] * height * width * n else: raise Exception( @@ -1833,9 +1909,22 @@ def batch_cost_calculator( if input_cost_per_token_batches: total_prompt_cost = usage.prompt_tokens * input_cost_per_token_batches elif input_cost_per_token: + # Subtract cached tokens from prompt_tokens before calculating cost + # Fixes issue where cached tokens are being charged again total_prompt_cost = ( - usage.prompt_tokens * (input_cost_per_token) / 2 + get_billable_input_tokens(usage) * (input_cost_per_token) / 2 ) # batch cost is usually half of the regular token cost + + # Add cache read cost if applicable + details = _parse_prompt_tokens_details(usage) + cache_read_tokens = details["cache_hit_tokens"] + cache_read_cost_key = _get_service_tier_cost_key( + "cache_read_input_token_cost", None + ) + total_prompt_cost += ( + calculate_cost_component(model_info, cache_read_cost_key, cache_read_tokens) + / 2 + ) if output_cost_per_token_batches: total_completion_cost = usage.completion_tokens * output_cost_per_token_batches elif output_cost_per_token: diff --git a/litellm/experimental_mcp_client/client.py b/litellm/experimental_mcp_client/client.py index 5ad2dd54853..3e8f9bc337b 100644 --- a/litellm/experimental_mcp_client/client.py +++ b/litellm/experimental_mcp_client/client.py @@ -4,13 +4,19 @@ LiteLLM Proxy uses this MCP Client to connnect to other MCP servers. import asyncio import base64 -from typing import Awaitable, Callable, Dict, List, Optional, TypeVar, Union +from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, TypeVar, Union import httpx from mcp import ClientSession, ReadResourceResult, Resource, StdioServerParameters from mcp.client.sse import sse_client from mcp.client.stdio import stdio_client -from mcp.client.streamable_http import streamable_http_client + +streamable_http_client: Optional[Any] = None +try: + import mcp.client.streamable_http as streamable_http_module # type: ignore + streamable_http_client = getattr(streamable_http_module, "streamable_http_client", None) +except ImportError: + pass from mcp.types import CallToolRequestParams as MCPCallToolRequestParams from mcp.types import CallToolResult as MCPCallToolResult from mcp.types import ( @@ -74,97 +80,108 @@ class MCPClient: if auth_value: self.update_auth_value(auth_value) + def _create_transport_context( + self, + ) -> Tuple[Any, Optional[httpx.AsyncClient]]: + """ + Create the appropriate transport context based on transport type. + + Returns: + Tuple of (transport_context, http_client). + http_client is only set for HTTP transport and needs cleanup. + """ + http_client: Optional[httpx.AsyncClient] = None + + if self.transport_type == MCPTransport.stdio: + if not self.stdio_config: + raise ValueError("stdio_config is required for stdio transport") + server_params = StdioServerParameters( + command=self.stdio_config.get("command", ""), + args=self.stdio_config.get("args", []), + env=self.stdio_config.get("env", {}), + ) + return stdio_client(server_params), None + + if self.transport_type == MCPTransport.sse: + headers = self._get_auth_headers() + httpx_client_factory = self._create_httpx_client_factory() + return sse_client( + url=self.server_url, + timeout=self.timeout, + headers=headers, + httpx_client_factory=httpx_client_factory, + ), None + + # HTTP transport (default) + if streamable_http_client is None: + raise ImportError( + "streamable_http_client is not available. " + "Please install mcp with HTTP support." + ) + + headers = self._get_auth_headers() + httpx_client_factory = self._create_httpx_client_factory() + verbose_logger.debug( + "litellm headers for streamable_http_client: %s", headers + ) + http_client = httpx_client_factory( + headers=headers, + timeout=httpx.Timeout(self.timeout), + ) + transport_ctx = streamable_http_client( + url=self.server_url, + http_client=http_client, + ) + return transport_ctx, http_client + + async def _execute_session_operation( + self, + transport_ctx: Any, + operation: Callable[[ClientSession], Awaitable[TSessionResult]], + ) -> TSessionResult: + """ + Execute an operation within a transport and session context. + + Handles entering/exiting contexts and running the operation. + """ + transport = await transport_ctx.__aenter__() + try: + read_stream, write_stream = transport[0], transport[1] + session_ctx = ClientSession(read_stream, write_stream) + session = await session_ctx.__aenter__() + try: + await session.initialize() + return await operation(session) + finally: + try: + await session_ctx.__aexit__(None, None, None) + except BaseException as e: + verbose_logger.debug(f"Error during session context exit: {e}") + finally: + try: + await transport_ctx.__aexit__(None, None, None) + except BaseException as e: + verbose_logger.debug(f"Error during transport context exit: {e}") + async def run_with_session( self, operation: Callable[[ClientSession], Awaitable[TSessionResult]] ) -> TSessionResult: """Open a session, run the provided coroutine, and clean up.""" - transport_ctx = None http_client: Optional[httpx.AsyncClient] = None - transport = None - session_ctx = None - try: - if self.transport_type == MCPTransport.stdio: - if not self.stdio_config: - raise ValueError("stdio_config is required for stdio transport") - - server_params = StdioServerParameters( - command=self.stdio_config.get("command", ""), - args=self.stdio_config.get("args", []), - env=self.stdio_config.get("env", {}), - ) - transport_ctx = stdio_client(server_params) - elif self.transport_type == MCPTransport.sse: - headers = self._get_auth_headers() - httpx_client_factory = self._create_httpx_client_factory() - transport_ctx = sse_client( - url=self.server_url, - timeout=self.timeout, - headers=headers, - httpx_client_factory=httpx_client_factory, - ) - else: - headers = self._get_auth_headers() - httpx_client_factory = self._create_httpx_client_factory() - verbose_logger.debug( - "litellm headers for streamable_http_client: %s", headers - ) - http_client = httpx_client_factory( - headers=headers, - timeout=httpx.Timeout(self.timeout), - ) - transport_ctx = streamable_http_client( - url=self.server_url, - http_client=http_client, - ) - - if transport_ctx is None: - raise RuntimeError("Failed to create transport context") - - # Enter transport context - transport = await transport_ctx.__aenter__() - try: - read_stream, write_stream = transport[0], transport[1] - session_ctx = ClientSession(read_stream, write_stream) - - # Enter session context - session = await session_ctx.__aenter__() - try: - await session.initialize() - result = await operation(session) - return result - finally: - # Ensure session context is properly exited - if session_ctx is not None: - try: - await session_ctx.__aexit__(None, None, None) - except Exception as e: - verbose_logger.debug( - f"Error during session context exit: {e}" - ) - finally: - # Ensure transport context is properly exited - if transport_ctx is not None: - try: - await transport_ctx.__aexit__(None, None, None) - except Exception as e: - verbose_logger.debug( - f"Error during transport context exit: {e}" - ) + transport_ctx, http_client = self._create_transport_context() + return await self._execute_session_operation(transport_ctx, operation) except Exception: verbose_logger.warning( "MCP client run_with_session failed for %s", self.server_url or "stdio" ) raise finally: - # Always clean up http_client if it was created if http_client is not None: try: await http_client.aclose() - except Exception as e: - verbose_logger.debug( - f"Error during http_client cleanup: {e}" - ) + except BaseException as e: + verbose_logger.debug(f"Error during http_client cleanup: {e}") def update_auth_value(self, mcp_auth_value: Union[str, Dict[str, str]]): """ @@ -277,7 +294,9 @@ class MCPClient: return [] async def call_tool( - self, call_tool_request_params: MCPCallToolRequestParams + self, + call_tool_request_params: MCPCallToolRequestParams, + host_progress_callback: Optional[Callable] = None ) -> MCPCallToolResult: """ Call an MCP Tool. @@ -286,13 +305,28 @@ class MCPClient: f"MCP client calling tool '{call_tool_request_params.name}' with arguments: {call_tool_request_params.arguments}" ) + async def on_progress(progress: float, total: float | None, message: str | None): + percentage = (progress / total * 100) if total else 0 + verbose_logger.info( + f"MCP Tool '{call_tool_request_params.name}' progress: " + f"{progress}/{total} ({percentage:.0f}%) - {message or ''}" + ) + + # Forward to Host if callback provided + if host_progress_callback: + try: + await host_progress_callback(progress, total) + except Exception as e: + verbose_logger.warning(f"Failed to forward to Host: {e}") + async def _call_tool_operation(session: ClientSession): verbose_logger.debug("MCP client sending tool call to session") return await session.call_tool( name=call_tool_request_params.name, arguments=call_tool_request_params.arguments, - ) + progress_callback=on_progress, + ) try: tool_result = await self.run_with_session(_call_tool_operation) verbose_logger.info( diff --git a/litellm/files/main.py b/litellm/files/main.py index 913ec84626d..78e41bb5a68 100644 --- a/litellm/files/main.py +++ b/litellm/files/main.py @@ -9,6 +9,7 @@ import asyncio import contextvars import os import time +import uuid as uuid_module from functools import partial from typing import Any, Coroutine, Dict, Literal, Optional, Union, cast @@ -61,7 +62,7 @@ async def acreate_file( file: FileTypes, purpose: Literal["assistants", "batch", "fine-tune"], expires_after: Optional[FileExpiresAfter] = None, - custom_llm_provider: Literal["openai", "azure", "vertex_ai", "bedrock", "hosted_vllm", "manus"] = "openai", + custom_llm_provider: Literal["openai", "azure", "gemini", "vertex_ai", "bedrock", "hosted_vllm", "manus"] = "openai", extra_headers: Optional[Dict[str, str]] = None, extra_body: Optional[Dict[str, str]] = None, **kwargs, @@ -106,7 +107,7 @@ def create_file( file: FileTypes, purpose: Literal["assistants", "batch", "fine-tune"], expires_after: Optional[FileExpiresAfter] = None, - custom_llm_provider: Optional[Literal["openai", "azure", "vertex_ai", "bedrock", "hosted_vllm", "manus"]] = None, + custom_llm_provider: Optional[Literal["openai", "azure", "gemini", "vertex_ai", "bedrock", "hosted_vllm", "manus"]] = None, extra_headers: Optional[Dict[str, str]] = None, extra_body: Optional[Dict[str, str]] = None, **kwargs, @@ -294,7 +295,7 @@ def create_file( @client async def afile_retrieve( file_id: str, - custom_llm_provider: Literal["openai", "azure", "hosted_vllm", "manus"] = "openai", + custom_llm_provider: Literal["openai", "azure", "gemini", "hosted_vllm", "manus"] = "openai", extra_headers: Optional[Dict[str, str]] = None, extra_body: Optional[Dict[str, str]] = None, **kwargs, @@ -450,7 +451,7 @@ def file_retrieve( stream=False, call_type="afile_retrieve" if _is_async else "file_retrieve", start_time=time.time(), - litellm_call_id=kwargs.get("litellm_call_id", str(uuid.uuid4())), + litellm_call_id=kwargs.get("litellm_call_id", str(uuid_module.uuid4())), function_id=str(kwargs.get("id") or ""), ) @@ -493,7 +494,7 @@ def file_retrieve( @client async def afile_delete( file_id: str, - custom_llm_provider: Literal["openai", "azure", "manus"] = "openai", + custom_llm_provider: Literal["openai", "azure", "gemini", "manus"] = "openai", extra_headers: Optional[Dict[str, str]] = None, extra_body: Optional[Dict[str, str]] = None, **kwargs, @@ -537,7 +538,7 @@ async def afile_delete( def file_delete( file_id: str, model: Optional[str] = None, - custom_llm_provider: Union[Literal["openai", "azure", "manus"], str] = "openai", + custom_llm_provider: Union[Literal["openai", "azure", "gemini", "manus"], str] = "openai", extra_headers: Optional[Dict[str, str]] = None, extra_body: Optional[Dict[str, str]] = None, **kwargs, @@ -659,7 +660,7 @@ def file_delete( stream=False, call_type="afile_delete" if _is_async else "file_delete", start_time=time.time(), - litellm_call_id=kwargs.get("litellm_call_id", str(uuid.uuid4())), + litellm_call_id=kwargs.get("litellm_call_id", str(uuid_module.uuid4())), function_id=str(kwargs.get("id") or ""), ) @@ -680,7 +681,7 @@ def file_delete( ) else: raise litellm.exceptions.BadRequestError( - message="LiteLLM doesn't support {} for 'file_delete'. Only 'openai', 'azure', and 'manus' are supported.".format( + message="LiteLLM doesn't support {} for 'file_delete'. Only 'openai', 'azure', 'gemini', and 'manus' are supported.".format( custom_llm_provider ), model="n/a", @@ -792,7 +793,7 @@ def file_list( stream=False, call_type="afile_list" if _is_async else "file_list", start_time=time.time(), - litellm_call_id=kwargs.get("litellm_call_id", str(uuid.uuid4())), + litellm_call_id=kwargs.get("litellm_call_id", str(uuid_module.uuid4())), function_id=str(kwargs.get("id", "")), ) diff --git a/litellm/integrations/SlackAlerting/slack_alerting.py b/litellm/integrations/SlackAlerting/slack_alerting.py index 0c36e15db01..8fb3e132ded 100644 --- a/litellm/integrations/SlackAlerting/slack_alerting.py +++ b/litellm/integrations/SlackAlerting/slack_alerting.py @@ -1378,6 +1378,11 @@ Model Info: """ if self.alerting is None: return + + # Start periodic flush if not already started + if not self.periodic_started and self.alerting is not None and len(self.alerting) > 0: + asyncio.create_task(self.periodic_flush()) + self.periodic_started = True if ( "webhook" in self.alerting diff --git a/litellm/integrations/braintrust_logging.py b/litellm/integrations/braintrust_logging.py index 585de510e8b..42e9680a7fc 100644 --- a/litellm/integrations/braintrust_logging.py +++ b/litellm/integrations/braintrust_logging.py @@ -9,6 +9,10 @@ import httpx import litellm from litellm import verbose_logger +from litellm.integrations.braintrust_mock_client import ( + should_use_braintrust_mock, + create_mock_braintrust_client, +) from litellm.integrations.custom_logger import CustomLogger from litellm.llms.custom_httpx.http_handler import ( HTTPHandler, @@ -34,6 +38,10 @@ class BraintrustLogger(CustomLogger): self, api_key: Optional[str] = None, api_base: Optional[str] = None ) -> None: super().__init__() + self.is_mock_mode = should_use_braintrust_mock() + if self.is_mock_mode: + create_mock_braintrust_client() + verbose_logger.info("[BRAINTRUST MOCK] Braintrust logger initialized in mock mode") self.validate_environment(api_key=api_key) self.api_base = api_base or os.getenv("BRAINTRUST_API_BASE") or API_BASE self.default_project_id = None @@ -254,6 +262,8 @@ class BraintrustLogger(CustomLogger): json={"events": [request_data]}, headers=self.headers, ) + if self.is_mock_mode: + print_verbose("[BRAINTRUST MOCK] Sync event successfully mocked") except httpx.HTTPStatusError as e: raise Exception(e.response.text) except Exception as e: @@ -399,6 +409,8 @@ class BraintrustLogger(CustomLogger): json={"events": [request_data]}, headers=self.headers, ) + if self.is_mock_mode: + print_verbose("[BRAINTRUST MOCK] Async event successfully mocked") except httpx.HTTPStatusError as e: raise Exception(e.response.text) except Exception as e: diff --git a/litellm/integrations/braintrust_mock_client.py b/litellm/integrations/braintrust_mock_client.py new file mode 100644 index 00000000000..030aa62cd0f --- /dev/null +++ b/litellm/integrations/braintrust_mock_client.py @@ -0,0 +1,131 @@ +""" +Mock HTTP client for Braintrust integration testing. + +This module intercepts Braintrust API calls and returns successful mock responses, +allowing full code execution without making actual network calls. + +Usage: + Set BRAINTRUST_MOCK=true in environment variables or config to enable mock mode. +""" + +import os +import time +from urllib.parse import urlparse + +from litellm._logging import verbose_logger +from litellm.integrations.mock_client_factory import MockClientConfig, MockResponse, create_mock_client_factory + +# Use factory for should_use_mock and MockResponse +# Braintrust uses both HTTPHandler (sync) and AsyncHTTPHandler (async) +# Braintrust needs endpoint-specific responses, so we use custom HTTPHandler.post patching +_config = MockClientConfig( + "BRAINTRUST", + "BRAINTRUST_MOCK", + default_latency_ms=100, + default_status_code=200, + default_json_data={"id": "mock-project-id", "status": "success"}, + url_matchers=[ + ".braintrustdata.com", + "braintrustdata.com", + ".braintrust.dev", + "braintrust.dev", + ], + patch_async_handler=True, # Patch AsyncHTTPHandler.post for async calls + patch_sync_client=False, # HTTPHandler uses self.client.send(), not self.client.post() + patch_http_handler=False, # We use custom patching for endpoint-specific responses +) + +# Get should_use_mock and create_mock_client from factory +# We need to call the factory's create_mock_client to patch AsyncHTTPHandler.post +create_mock_braintrust_factory_client, should_use_braintrust_mock = create_mock_client_factory(_config) + +# Store original HTTPHandler.post method (Braintrust-specific for sync calls with custom logic) +_original_http_handler_post = None +_mocks_initialized = False + +# Default mock latency in seconds +_MOCK_LATENCY_SECONDS = float(os.getenv("BRAINTRUST_MOCK_LATENCY_MS", "100")) / 1000.0 + + +def _is_braintrust_url(url: str) -> bool: + """Check if URL is a Braintrust API URL.""" + if not isinstance(url, str): + return False + + parsed = urlparse(url) + host = (parsed.hostname or "").lower() + + if not host: + return False + + return ( + host == "braintrustdata.com" + or host.endswith(".braintrustdata.com") + or host == "braintrust.dev" + or host.endswith(".braintrust.dev") + ) + + +def _mock_http_handler_post(self, url, data=None, json=None, params=None, headers=None, timeout=None, stream=False, files=None, content=None, logging_obj=None): + """Monkey-patched HTTPHandler.post that intercepts Braintrust calls with endpoint-specific responses.""" + # Only mock Braintrust API calls + if isinstance(url, str) and _is_braintrust_url(url): + verbose_logger.info(f"[BRAINTRUST MOCK] POST to {url}") + time.sleep(_MOCK_LATENCY_SECONDS) + # Return appropriate mock response based on endpoint + if "/project" in url: + # Project creation/retrieval/register endpoint + project_name = json.get("name", "litellm") if json else "litellm" + mock_data = {"id": f"mock-project-id-{project_name}", "name": project_name} + elif "/project_logs" in url: + # Log insertion endpoint + mock_data = {"status": "success"} + else: + mock_data = _config.default_json_data + return MockResponse( + status_code=_config.default_status_code, + json_data=mock_data, + url=url, + elapsed_seconds=_MOCK_LATENCY_SECONDS + ) + if _original_http_handler_post is not None: + return _original_http_handler_post(self, url=url, data=data, json=json, params=params, headers=headers, timeout=timeout, stream=stream, files=files, content=content, logging_obj=logging_obj) + raise RuntimeError("Original HTTPHandler.post not available") + + +def create_mock_braintrust_client(): + """ + Monkey-patch HTTPHandler.post to intercept Braintrust sync calls. + + Braintrust uses HTTPHandler for sync calls and AsyncHTTPHandler for async calls. + HTTPHandler.post uses self.client.send(), not self.client.post(), so we need + custom patching for sync (similar to Helicone). + AsyncHTTPHandler.post is patched by the factory. + + We use custom patching instead of factory's patch_http_handler because we need + endpoint-specific responses (different for /project vs /project_logs). + + This function is idempotent - it only initializes mocks once, even if called multiple times. + """ + global _original_http_handler_post, _mocks_initialized + + if _mocks_initialized: + return + + verbose_logger.debug("[BRAINTRUST MOCK] Initializing Braintrust mock client...") + + from litellm.llms.custom_httpx.http_handler import HTTPHandler + + if _original_http_handler_post is None: + _original_http_handler_post = HTTPHandler.post + HTTPHandler.post = _mock_http_handler_post # type: ignore + verbose_logger.debug("[BRAINTRUST MOCK] Patched HTTPHandler.post") + + # CRITICAL: Call the factory's initialization function to patch AsyncHTTPHandler.post + # This is required for async calls to be mocked + create_mock_braintrust_factory_client() + + verbose_logger.debug(f"[BRAINTRUST MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms") + verbose_logger.debug("[BRAINTRUST MOCK] Braintrust mock client initialization complete") + + _mocks_initialized = True diff --git a/litellm/integrations/callback_configs.json b/litellm/integrations/callback_configs.json index 6b30b6b736e..6a003b8c499 100644 --- a/litellm/integrations/callback_configs.json +++ b/litellm/integrations/callback_configs.json @@ -83,6 +83,33 @@ }, "description": "Datadog Logging Integration" }, + { + "id": "datadog_cost_management", + "displayName": "Datadog Cost Management", + "logo": "datadog.png", + "supports_key_team_logging": false, + "dynamic_params": { + "dd_api_key": { + "type": "password", + "ui_name": "API Key", + "description": "Datadog API key for authentication", + "required": true + }, + "dd_app_key": { + "type": "password", + "ui_name": "App Key", + "description": "Datadog Application Key for Cloud Cost Management", + "required": true + }, + "dd_site": { + "type": "text", + "ui_name": "Site", + "description": "Datadog site URL (e.g., us5.datadoghq.com)", + "required": true + } + }, + "description": "Datadog Cloud Cost Management Integration" + }, { "id": "lago", "displayName": "Lago", @@ -407,4 +434,4 @@ }, "description": "SQS Queue (AWS) Logging Integration" } -] +] \ No newline at end of file diff --git a/litellm/integrations/custom_guardrail.py b/litellm/integrations/custom_guardrail.py index 6a76b57e7f7..1652ec2aa0c 100644 --- a/litellm/integrations/custom_guardrail.py +++ b/litellm/integrations/custom_guardrail.py @@ -475,11 +475,18 @@ class CustomGuardrail(CustomLogger): guardrail_config: DynamicGuardrailParams = DynamicGuardrailParams( **guardrail[self.guardrail_name] ) + extra_body = guardrail_config.get("extra_body", {}) if self._validate_premium_user() is not True: + if isinstance(extra_body, dict) and extra_body: + verbose_logger.warning( + "Guardrail %s: ignoring dynamic extra_body keys %s because premium_user is False", + self.guardrail_name, + list(extra_body.keys()), + ) return {} # Return the extra_body if it exists, otherwise empty dict - return guardrail_config.get("extra_body", {}) + return extra_body return {} @@ -516,7 +523,9 @@ class CustomGuardrail(CustomLogger): from litellm.types.utils import GuardrailMode # Use event_type if provided, otherwise fall back to self.event_hook - guardrail_mode: Union[GuardrailEventHooks, GuardrailMode, List[GuardrailEventHooks]] + guardrail_mode: Union[ + GuardrailEventHooks, GuardrailMode, List[GuardrailEventHooks] + ] if event_type is not None: guardrail_mode = event_type elif isinstance(self.event_hook, Mode): @@ -524,11 +533,21 @@ class CustomGuardrail(CustomLogger): else: guardrail_mode = self.event_hook # type: ignore[assignment] + from litellm.litellm_core_utils.core_helpers import ( + filter_exceptions_from_params, + ) + + # Sanitize the response to ensure it's JSON serializable and free of circular refs + # This prevents RecursionErrors in downstream loggers (Langfuse, Datadog, etc.) + clean_guardrail_response = filter_exceptions_from_params( + guardrail_json_response + ) + slg = StandardLoggingGuardrailInformation( guardrail_name=self.guardrail_name, guardrail_provider=guardrail_provider, guardrail_mode=guardrail_mode, - guardrail_response=guardrail_json_response, + guardrail_response=clean_guardrail_response, guardrail_status=guardrail_status, start_time=start_time, end_time=end_time, diff --git a/litellm/integrations/custom_logger.py b/litellm/integrations/custom_logger.py index 12243a19184..07d237c4758 100644 --- a/litellm/integrations/custom_logger.py +++ b/litellm/integrations/custom_logger.py @@ -371,6 +371,28 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac ]: # raise exception if invalid, return a str for the user to receive - if rejected, or return a modified dictionary for passing into litellm pass + async def async_post_call_response_headers_hook( + self, + data: dict, + user_api_key_dict: UserAPIKeyAuth, + response: Any, + request_headers: Optional[Dict[str, str]] = None, + ) -> Optional[Dict[str, str]]: + """ + Called after an LLM API call (success or failure) to allow injecting custom HTTP response headers. + + Args: + - data: dict - The request data. + - user_api_key_dict: UserAPIKeyAuth - The user API key dictionary. + - response: Any - The response object (None for failure cases). + - request_headers: Optional[Dict[str, str]] - The original request headers. + + Returns: + - Optional[Dict[str, str]]: A dictionary of headers to inject into the HTTP response. + Return None to not inject any headers. + """ + return None + async def async_post_call_failure_hook( self, request_data: dict, diff --git a/litellm/integrations/datadog/datadog.py b/litellm/integrations/datadog/datadog.py index 503e8d8c87a..127b0e53fa8 100644 --- a/litellm/integrations/datadog/datadog.py +++ b/litellm/integrations/datadog/datadog.py @@ -27,11 +27,16 @@ import litellm from litellm._logging import verbose_logger from litellm._uuid import uuid from litellm.integrations.custom_batch_logger import CustomBatchLogger +from litellm.integrations.datadog.datadog_mock_client import ( + should_use_datadog_mock, + create_mock_datadog_client, +) from litellm.integrations.datadog.datadog_handler import ( get_datadog_hostname, get_datadog_service, get_datadog_source, get_datadog_tags, + get_datadog_base_url_from_env, ) from litellm.litellm_core_utils.dd_tracing import tracer from litellm.llms.custom_httpx.http_handler import ( @@ -80,6 +85,12 @@ class DataDogLogger( """ try: verbose_logger.debug("Datadog: in init datadog logger") + + self.is_mock_mode = should_use_datadog_mock() + + if self.is_mock_mode: + create_mock_datadog_client() + verbose_logger.debug("[DATADOG MOCK] Datadog logger initialized in mock mode") ######################################################### # Handle datadog_params set as litellm.datadog_params @@ -100,7 +111,9 @@ class DataDogLogger( self._configure_dd_direct_api() # Optional override for testing - self._apply_dd_base_url_override() + dd_base_url = get_datadog_base_url_from_env() + if dd_base_url: + self.intake_url = f"{dd_base_url}/api/v2/logs" self.sync_client = _get_httpx_client() asyncio.create_task(self.periodic_flush()) self.flush_lock = asyncio.Lock() @@ -159,18 +172,6 @@ class DataDogLogger( self.DD_API_KEY = os.getenv("DD_API_KEY") self.intake_url = f"https://http-intake.logs.{os.getenv('DD_SITE')}/api/v2/logs" - def _apply_dd_base_url_override(self) -> None: - """ - Apply base URL override for testing purposes - """ - dd_base_url: Optional[str] = ( - os.getenv("_DATADOG_BASE_URL") - or os.getenv("DATADOG_BASE_URL") - or os.getenv("DD_BASE_URL") - ) - if dd_base_url is not None: - self.intake_url = f"{dd_base_url}/api/v2/logs" - async def async_log_success_event(self, kwargs, response_obj, start_time, end_time): """ Async Log success events to Datadog @@ -229,6 +230,9 @@ class DataDogLogger( len(self.log_queue), self.intake_url, ) + + if self.is_mock_mode: + verbose_logger.debug("[DATADOG MOCK] Mock mode enabled - API calls will be intercepted") response = await self.async_send_compressed_data(self.log_queue) if response.status_code == 413: @@ -241,11 +245,16 @@ class DataDogLogger( f"Response from datadog API status_code: {response.status_code}, text: {response.text}" ) - verbose_logger.debug( - "Datadog: Response from datadog API status_code: %s, text: %s", - response.status_code, - response.text, - ) + if self.is_mock_mode: + verbose_logger.debug( + f"[DATADOG MOCK] Batch of {len(self.log_queue)} events successfully mocked" + ) + else: + verbose_logger.debug( + "Datadog: Response from datadog API status_code: %s, text: %s", + response.status_code, + response.text, + ) except Exception as e: verbose_logger.exception( f"Datadog Error sending batch API - {str(e)}\n{traceback.format_exc()}" diff --git a/litellm/integrations/datadog/datadog_cost_management.py b/litellm/integrations/datadog/datadog_cost_management.py new file mode 100644 index 00000000000..2eb94b59dd8 --- /dev/null +++ b/litellm/integrations/datadog/datadog_cost_management.py @@ -0,0 +1,204 @@ +import asyncio +import os +import time +from datetime import datetime +from typing import Dict, List, Optional, Tuple + +from litellm._logging import verbose_logger +from litellm.integrations.custom_batch_logger import CustomBatchLogger +from litellm.llms.custom_httpx.http_handler import ( + get_async_httpx_client, + httpxSpecialProvider, +) +from litellm.types.integrations.datadog_cost_management import ( + DatadogFOCUSCostEntry, +) +from litellm.types.utils import StandardLoggingPayload + + +class DatadogCostManagementLogger(CustomBatchLogger): + def __init__(self, **kwargs): + self.dd_api_key = os.getenv("DD_API_KEY") + self.dd_app_key = os.getenv("DD_APP_KEY") + self.dd_site = os.getenv("DD_SITE", "datadoghq.com") + + if not self.dd_api_key or not self.dd_app_key: + verbose_logger.warning( + "Datadog Cost Management: DD_API_KEY and DD_APP_KEY are required. Integration will not work." + ) + + self.upload_url = f"https://api.{self.dd_site}/api/v2/cost/custom_costs" + + self.async_client = get_async_httpx_client( + llm_provider=httpxSpecialProvider.LoggingCallback + ) + + # Initialize lock and start periodic flush task + self.flush_lock = asyncio.Lock() + asyncio.create_task(self.periodic_flush()) + + # Check if flush_lock is already in kwargs to avoid double passing (unlikely but safe) + if "flush_lock" not in kwargs: + kwargs["flush_lock"] = self.flush_lock + + super().__init__(**kwargs) + + async def async_log_success_event(self, kwargs, response_obj, start_time, end_time): + try: + standard_logging_object: Optional[StandardLoggingPayload] = kwargs.get( + "standard_logging_object", None + ) + + if standard_logging_object is None: + return + + # Only log if there is a cost associated + if standard_logging_object.get("response_cost", 0) > 0: + self.log_queue.append(standard_logging_object) + + if len(self.log_queue) >= self.batch_size: + await self.async_send_batch() + + except Exception as e: + verbose_logger.exception( + f"Datadog Cost Management: Error in async_log_success_event: {str(e)}" + ) + + async def async_send_batch(self): + if not self.log_queue: + return + + try: + # Aggregate costs from the batch + aggregated_entries = self._aggregate_costs(self.log_queue) + + if not aggregated_entries: + return + + # Send to Datadog + await self._upload_to_datadog(aggregated_entries) + + # Clear queue only on success (or if we decide to drop on failure) + # CustomBatchLogger clears queue in flush_queue, so we just process here + + except Exception as e: + verbose_logger.exception( + f"Datadog Cost Management: Error in async_send_batch: {str(e)}" + ) + + def _aggregate_costs( + self, logs: List[StandardLoggingPayload] + ) -> List[DatadogFOCUSCostEntry]: + """ + Aggregates costs by Provider, Model, and Date. + Returns a list of DatadogFOCUSCostEntry. + """ + aggregator: Dict[Tuple[str, str, str, Tuple[Tuple[str, str], ...]], DatadogFOCUSCostEntry] = {} + + for log in logs: + try: + # Extract keys for aggregation + provider = log.get("custom_llm_provider") or "unknown" + model = log.get("model") or "unknown" + cost = log.get("response_cost", 0) + + if cost == 0: + continue + + # Get date strings (FOCUS format requires specific keys, but for aggregation we group by Day) + # UTC date + # We interpret "ChargePeriod" as the day of the request. + ts = log.get("startTime") or time.time() + dt = datetime.fromtimestamp(ts) + date_str = dt.strftime("%Y-%m-%d") + + # ChargePeriodStart and End + # If we want daily granularity, end date is usually same day or next day? + # Datadog Custom Costs usually expects periods. + # "ChargePeriodStart": "2023-01-01", "ChargePeriodEnd": "2023-12-31" in example. + # If we send daily, we can say Start=Date, End=Date. + + # Grouping Key: Provider + Model + Date + Tags? + # For simplicity, let's aggregate by Provider + Model + Date first. + # If we handle tags, we need to include them in the key. + + tags = self._extract_tags(log) + tags_key = tuple(sorted(tags.items())) if tags else () + + key = (provider, model, date_str, tags_key) + + if key not in aggregator: + aggregator[key] = { + "ProviderName": provider, + "ChargeDescription": f"LLM Usage for {model}", + "ChargePeriodStart": date_str, + "ChargePeriodEnd": date_str, + "BilledCost": 0.0, + "BillingCurrency": "USD", + "Tags": tags if tags else None, + } + + aggregator[key]["BilledCost"] += cost + + except Exception as e: + verbose_logger.warning( + f"Error processing log for cost aggregation: {e}" + ) + continue + + return list(aggregator.values()) + + def _extract_tags(self, log: StandardLoggingPayload) -> Dict[str, str]: + from litellm.integrations.datadog.datadog_handler import ( + get_datadog_env, + get_datadog_hostname, + get_datadog_pod_name, + get_datadog_service, + ) + + tags = { + "env": get_datadog_env(), + "service": get_datadog_service(), + "host": get_datadog_hostname(), + "pod_name": get_datadog_pod_name(), + } + + # Add metadata as tags + metadata = log.get("metadata", {}) + if metadata: + # Add user info + if "user_api_key_alias" in metadata: + tags["user"] = str(metadata["user_api_key_alias"]) + if "user_api_key_team_alias" in metadata: + tags["team"] = str(metadata["user_api_key_team_alias"]) + # model_group is not in StandardLoggingMetadata TypedDict, so we need to access it via dict.get() + model_group = metadata.get("model_group") # type: ignore[misc] + if model_group: + tags["model_group"] = str(model_group) + + return tags + + async def _upload_to_datadog(self, payload: List[Dict]): + if not self.dd_api_key or not self.dd_app_key: + return + + headers = { + "Content-Type": "application/json", + "DD-API-KEY": self.dd_api_key, + "DD-APPLICATION-KEY": self.dd_app_key, + } + + # The API endpoint expects a list of objects directly in the body (file content behavior) + from litellm.litellm_core_utils.safe_json_dumps import safe_dumps + + data_json = safe_dumps(payload) + + response = await self.async_client.put( + self.upload_url, content=data_json, headers=headers + ) + + response.raise_for_status() + + verbose_logger.debug( + f"Datadog Cost Management: Uploaded {len(payload)} cost entries. Status: {response.status_code}" + ) diff --git a/litellm/integrations/datadog/datadog_handler.py b/litellm/integrations/datadog/datadog_handler.py index 26fab77759e..e2f30f2f614 100644 --- a/litellm/integrations/datadog/datadog_handler.py +++ b/litellm/integrations/datadog/datadog_handler.py @@ -20,6 +20,14 @@ def get_datadog_hostname() -> str: return os.getenv("HOSTNAME", "") +def get_datadog_base_url_from_env() -> Optional[str]: + """ + Get base URL override from common DD_BASE_URL env var. + This is useful for testing or custom endpoints. + """ + return os.getenv("DD_BASE_URL") + + def get_datadog_env() -> str: return os.getenv("DD_ENV", "unknown") diff --git a/litellm/integrations/datadog/datadog_llm_obs.py b/litellm/integrations/datadog/datadog_llm_obs.py index 6ffdbc0a005..e5ce9997491 100644 --- a/litellm/integrations/datadog/datadog_llm_obs.py +++ b/litellm/integrations/datadog/datadog_llm_obs.py @@ -18,9 +18,14 @@ import httpx import litellm from litellm._logging import verbose_logger from litellm.integrations.custom_batch_logger import CustomBatchLogger +from litellm.integrations.datadog.datadog_mock_client import ( + should_use_datadog_mock, + create_mock_datadog_client, +) from litellm.integrations.datadog.datadog_handler import ( get_datadog_service, get_datadog_tags, + get_datadog_base_url_from_env, ) from litellm.litellm_core_utils.dd_tracing import tracer from litellm.litellm_core_utils.prompt_templates.common_utils import ( @@ -43,24 +48,37 @@ class DataDogLLMObsLogger(CustomBatchLogger): def __init__(self, **kwargs): try: verbose_logger.debug("DataDogLLMObs: Initializing logger") - if os.getenv("DD_API_KEY", None) is None: - raise Exception("DD_API_KEY is not set, set 'DD_API_KEY=<>'") - if os.getenv("DD_SITE", None) is None: - raise Exception( - "DD_SITE is not set, set 'DD_SITE=<>', example sit = `us5.datadoghq.com`" - ) + + self.is_mock_mode = should_use_datadog_mock() + + if self.is_mock_mode: + create_mock_datadog_client() + verbose_logger.debug("[DATADOG MOCK] DataDogLLMObs logger initialized in mock mode") + + # Configure DataDog endpoint (Agent or Direct API) + # Use LITELLM_DD_AGENT_HOST to avoid conflicts with ddtrace's DD_AGENT_HOST + # Check for agent mode FIRST - agent mode doesn't require DD_API_KEY or DD_SITE + dd_agent_host = os.getenv("LITELLM_DD_AGENT_HOST") self.async_client = get_async_httpx_client( llm_provider=httpxSpecialProvider.LoggingCallback ) self.DD_API_KEY = os.getenv("DD_API_KEY") - self.DD_SITE = os.getenv("DD_SITE") - self.intake_url = ( - f"https://api.{self.DD_SITE}/api/intake/llm-obs/v1/trace/spans" - ) - # testing base url - dd_base_url = os.getenv("DD_BASE_URL") + if dd_agent_host: + self._configure_dd_agent(dd_agent_host=dd_agent_host) + else: + # Only require DD_API_KEY and DD_SITE for direct API mode + if os.getenv("DD_API_KEY", None) is None: + raise Exception("DD_API_KEY is not set, set 'DD_API_KEY=<>'") + if os.getenv("DD_SITE", None) is None: + raise Exception( + "DD_SITE is not set, set 'DD_SITE=<>', example sit = `us5.datadoghq.com`" + ) + self._configure_dd_direct_api() + + # Optional override for testing + dd_base_url = get_datadog_base_url_from_env() if dd_base_url: self.intake_url = f"{dd_base_url}/api/intake/llm-obs/v1/trace/spans" @@ -78,6 +96,38 @@ class DataDogLLMObsLogger(CustomBatchLogger): verbose_logger.exception(f"DataDogLLMObs: Error initializing - {str(e)}") raise e + def _configure_dd_agent(self, dd_agent_host: str): + """ + Configure the Datadog logger to send traces to the Agent. + """ + # When using the Agent, LLM Observability Intake does NOT require the API Key + # Reference: https://docs.datadoghq.com/llm_observability/setup/sdk/#agent-setup + + # Use specific port for LLM Obs (Trace Agent) to avoid conflict with Logs Agent (10518) + agent_port = os.getenv("LITELLM_DD_LLM_OBS_PORT", "8126") + self.DD_SITE = "localhost" # Not used for URL construction in agent mode + self.intake_url = ( + f"http://{dd_agent_host}:{agent_port}/api/intake/llm-obs/v1/trace/spans" + ) + verbose_logger.debug(f"DataDogLLMObs: Using DD Agent at {self.intake_url}") + + def _configure_dd_direct_api(self): + """ + Configure the Datadog logger to send traces directly to the Datadog API. + """ + if not self.DD_API_KEY: + raise Exception("DD_API_KEY is not set, set 'DD_API_KEY=<>'") + + self.DD_SITE = os.getenv("DD_SITE") + if not self.DD_SITE: + raise Exception( + "DD_SITE is not set, set 'DD_SITE=<>', example site = `us5.datadoghq.com`" + ) + + self.intake_url = ( + f"https://api.{self.DD_SITE}/api/intake/llm-obs/v1/trace/spans" + ) + def _get_datadog_llm_obs_params(self) -> Dict: """ Get the datadog_llm_observability_params from litellm.datadog_llm_observability_params @@ -139,6 +189,9 @@ class DataDogLLMObsLogger(CustomBatchLogger): verbose_logger.debug( f"DataDogLLMObs: Flushing {len(self.log_queue)} events" ) + + if self.is_mock_mode: + verbose_logger.debug("[DATADOG MOCK] Mock mode enabled - API calls will be intercepted") # Prepare the payload payload = { @@ -164,13 +217,14 @@ class DataDogLLMObsLogger(CustomBatchLogger): json_payload = safe_dumps(payload) + headers = {"Content-Type": "application/json"} + if self.DD_API_KEY: + headers["DD-API-KEY"] = self.DD_API_KEY + response = await self.async_client.post( url=self.intake_url, content=json_payload, - headers={ - "DD-API-KEY": self.DD_API_KEY, - "Content-Type": "application/json", - }, + headers=headers, ) if response.status_code != 202: @@ -178,9 +232,14 @@ class DataDogLLMObsLogger(CustomBatchLogger): f"DataDogLLMObs: Unexpected response - status_code: {response.status_code}, text: {response.text}" ) - verbose_logger.debug( - f"DataDogLLMObs: Successfully sent batch - status_code: {response.status_code}" - ) + if self.is_mock_mode: + verbose_logger.debug( + f"[DATADOG MOCK] Batch of {len(self.log_queue)} events successfully mocked" + ) + else: + verbose_logger.debug( + f"DataDogLLMObs: Successfully sent batch - status_code: {response.status_code}" + ) self.log_queue.clear() except httpx.HTTPStatusError as e: verbose_logger.exception( diff --git a/litellm/integrations/datadog/datadog_mock_client.py b/litellm/integrations/datadog/datadog_mock_client.py new file mode 100644 index 00000000000..a0a760deb0b --- /dev/null +++ b/litellm/integrations/datadog/datadog_mock_client.py @@ -0,0 +1,28 @@ +""" +Mock client for Datadog integration testing. + +This module intercepts Datadog API calls and returns successful mock responses, +allowing full code execution without making actual network calls. + +Usage: + Set DATADOG_MOCK=true in environment variables or config to enable mock mode. +""" + +from litellm.integrations.mock_client_factory import MockClientConfig, create_mock_client_factory + +# Create mock client using factory +_config = MockClientConfig( + name="DATADOG", + env_var="DATADOG_MOCK", + default_latency_ms=100, + default_status_code=202, + default_json_data={"status": "ok"}, + url_matchers=[ + ".datadoghq.com", + "datadoghq.com", + ], + patch_async_handler=True, + patch_sync_client=True, +) + +create_mock_datadog_client, should_use_datadog_mock = create_mock_client_factory(_config) diff --git a/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py b/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py index 6201dc343dc..2d14f5eb962 100644 --- a/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py +++ b/litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py @@ -8,20 +8,28 @@ Usage: Set GCS_MOCK=true in environment variables or config to enable mock mode. """ -import httpx -import json import asyncio -from datetime import timedelta -from typing import Dict, Optional from litellm._logging import verbose_logger +from litellm.integrations.mock_client_factory import MockClientConfig, create_mock_client_factory, MockResponse -# Store original methods for restoration -_original_async_handler_post = None +# Use factory for POST handler +_config = MockClientConfig( + name="GCS", + env_var="GCS_MOCK", + default_latency_ms=150, + default_status_code=200, + default_json_data={"kind": "storage#object", "name": "mock-object"}, + url_matchers=["storage.googleapis.com"], + patch_async_handler=True, + patch_sync_client=False, +) + +_create_mock_gcs_post, should_use_gcs_mock = create_mock_client_factory(_config) + +# Store original methods for GET/DELETE (GCS-specific) _original_async_handler_get = None _original_async_handler_delete = None - -# Track if mocks have been initialized to avoid duplicate initialization _mocks_initialized = False # Default mock latency in seconds (simulates network round-trip) @@ -29,84 +37,59 @@ _mocks_initialized = False _MOCK_LATENCY_SECONDS = float(__import__("os").getenv("GCS_MOCK_LATENCY_MS", "150")) / 1000.0 -class MockGCSResponse: - """Mock httpx.Response that satisfies GCS API requirements.""" - - def __init__(self, status_code: int = 200, json_data: Optional[Dict] = None, url: Optional[str] = None, elapsed_seconds: float = 0.0): - self.status_code = status_code - self._json_data = json_data or {"kind": "storage#object", "name": "mock-object"} - self.headers = httpx.Headers({}) - self.is_success = status_code < 400 - self.is_error = status_code >= 400 - self.is_redirect = 300 <= status_code < 400 - self.url = httpx.URL(url) if url else httpx.URL("") - # Set realistic elapsed time based on mock latency - elapsed_time = elapsed_seconds if elapsed_seconds > 0 else _MOCK_LATENCY_SECONDS - self.elapsed = timedelta(seconds=elapsed_time) - self._text = json.dumps(self._json_data) - self._content = self._text.encode("utf-8") - - @property - def text(self) -> str: - """Return response text.""" - return self._text - - @property - def content(self) -> bytes: - """Return response content.""" - return self._content - - def json(self) -> Dict: - """Return JSON response data.""" - return self._json_data - - def read(self) -> bytes: - """Read response content.""" - return self._content - - def raise_for_status(self): - """Raise exception for error status codes.""" - if self.status_code >= 400: - raise Exception(f"HTTP {self.status_code}") - - -async def _mock_async_handler_post(self, url, data=None, json=None, params=None, headers=None, timeout=None, stream=False, logging_obj=None, files=None, content=None): - """Monkey-patched AsyncHTTPHandler.post that intercepts GCS calls.""" - # Only mock GCS API calls - if isinstance(url, str) and "storage.googleapis.com" in url: - verbose_logger.info(f"[GCS MOCK] POST to {url}") - # Simulate network latency - await asyncio.sleep(_MOCK_LATENCY_SECONDS) - return MockGCSResponse( - status_code=200, - json_data={"kind": "storage#object", "name": "mock-object"}, - url=url, - elapsed_seconds=_MOCK_LATENCY_SECONDS - ) - # For non-GCS calls, use original method - if _original_async_handler_post is not None: - return await _original_async_handler_post(self, url=url, data=data, json=json, params=params, headers=headers, timeout=timeout, stream=stream, logging_obj=logging_obj, files=files, content=content) - # Fallback: if original not set, raise error - raise RuntimeError("Original AsyncHTTPHandler.post not available") - - async def _mock_async_handler_get(self, url, params=None, headers=None, follow_redirects=None): """Monkey-patched AsyncHTTPHandler.get that intercepts GCS calls.""" # Only mock GCS API calls if isinstance(url, str) and "storage.googleapis.com" in url: verbose_logger.info(f"[GCS MOCK] GET to {url}") - # Simulate network latency await asyncio.sleep(_MOCK_LATENCY_SECONDS) - return MockGCSResponse( - status_code=200, - json_data={"data": "mock-log-data"}, + # Return a minimal but valid StandardLoggingPayload JSON string as bytes + # This matches what GCS returns when downloading with ?alt=media + mock_payload = { + "id": "mock-request-id", + "trace_id": "mock-trace-id", + "call_type": "completion", + "stream": False, + "response_cost": 0.0, + "status": "success", + "status_fields": {"llm_api_status": "success"}, + "custom_llm_provider": "mock", + "total_tokens": 0, + "prompt_tokens": 0, + "completion_tokens": 0, + "startTime": 0.0, + "endTime": 0.0, + "completionStartTime": 0.0, + "response_time": 0.0, + "model_map_information": {"model": "mock-model"}, + "model": "mock-model", + "model_id": None, + "model_group": None, + "api_base": "https://api.mock.com", + "metadata": {}, + "cache_hit": None, + "cache_key": None, + "saved_cache_cost": 0.0, + "request_tags": [], + "end_user": None, + "requester_ip_address": None, + "messages": None, + "response": None, + "error_str": None, + "error_information": None, + "model_parameters": {}, + "hidden_params": {}, + "guardrail_information": None, + "standard_built_in_tools_params": None, + } + return MockResponse( + status_code=200, + json_data=mock_payload, url=url, elapsed_seconds=_MOCK_LATENCY_SECONDS ) - # For non-GCS calls, use original method if _original_async_handler_get is not None: return await _original_async_handler_get(self, url=url, params=params, headers=headers, follow_redirects=follow_redirects) - # Fallback: if original not set, raise error raise RuntimeError("Original AsyncHTTPHandler.get not available") @@ -115,18 +98,16 @@ async def _mock_async_handler_delete(self, url, data=None, json=None, params=Non # Only mock GCS API calls if isinstance(url, str) and "storage.googleapis.com" in url: verbose_logger.info(f"[GCS MOCK] DELETE to {url}") - # Simulate network latency await asyncio.sleep(_MOCK_LATENCY_SECONDS) - return MockGCSResponse( - status_code=204, - json_data={}, + # DELETE returns 204 No Content with empty body (not JSON) + return MockResponse( + status_code=204, + json_data=None, # Empty body for DELETE url=url, elapsed_seconds=_MOCK_LATENCY_SECONDS ) - # For non-GCS calls, use original method if _original_async_handler_delete is not None: return await _original_async_handler_delete(self, url=url, data=data, json=json, params=params, headers=headers, timeout=timeout, stream=stream, content=content) - # Fallback: if original not set, raise error raise RuntimeError("Original AsyncHTTPHandler.delete not available") @@ -139,30 +120,26 @@ def create_mock_gcs_client(): This function is idempotent - it only initializes mocks once, even if called multiple times. """ - global _original_async_handler_post, _original_async_handler_get, _original_async_handler_delete - global _mocks_initialized + global _original_async_handler_get, _original_async_handler_delete, _mocks_initialized - # If already initialized, skip + # Use factory for POST handler + _create_mock_gcs_post() + + # If already initialized, skip GET/DELETE patching if _mocks_initialized: return - verbose_logger.debug("[GCS MOCK] Initializing GCS mock client...") + verbose_logger.debug("[GCS MOCK] Initializing GCS GET/DELETE handlers...") - # Patch AsyncHTTPHandler methods (used by LiteLLM's custom httpx handler) - if _original_async_handler_post is None: - from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler - _original_async_handler_post = AsyncHTTPHandler.post - AsyncHTTPHandler.post = _mock_async_handler_post # type: ignore - verbose_logger.debug("[GCS MOCK] Patched AsyncHTTPHandler.post") + # Patch GET and DELETE handlers (GCS-specific) + from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler if _original_async_handler_get is None: - from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler _original_async_handler_get = AsyncHTTPHandler.get AsyncHTTPHandler.get = _mock_async_handler_get # type: ignore verbose_logger.debug("[GCS MOCK] Patched AsyncHTTPHandler.get") if _original_async_handler_delete is None: - from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler _original_async_handler_delete = AsyncHTTPHandler.delete AsyncHTTPHandler.delete = _mock_async_handler_delete # type: ignore verbose_logger.debug("[GCS MOCK] Patched AsyncHTTPHandler.delete") @@ -212,25 +189,4 @@ def mock_vertex_auth_methods(): verbose_logger.debug("[GCS MOCK] Patched Vertex AI auth methods") -def should_use_gcs_mock() -> bool: - """ - Determine if GCS should run in mock mode. - - Checks the GCS_MOCK environment variable. - - Returns: - bool: True if mock mode should be enabled - """ - import os - from litellm.secret_managers.main import str_to_bool - - mock_mode = os.getenv("GCS_MOCK", "false") - result = str_to_bool(mock_mode) - - # Ensure we return a bool, not None - result = bool(result) if result is not None else False - - if result: - verbose_logger.info("GCS Mock Mode: ENABLED - API calls will be mocked") - - return result +# should_use_gcs_mock is already created by the factory diff --git a/litellm/integrations/helicone.py b/litellm/integrations/helicone.py index 198cbaf4058..b996813b4e7 100644 --- a/litellm/integrations/helicone.py +++ b/litellm/integrations/helicone.py @@ -4,6 +4,11 @@ import os import traceback import litellm +from litellm._logging import verbose_logger +from litellm.integrations.helicone_mock_client import ( + should_use_helicone_mock, + create_mock_helicone_client, +) class HeliconeLogger: @@ -22,6 +27,11 @@ class HeliconeLogger: def __init__(self): # Instance variables + self.is_mock_mode = should_use_helicone_mock() + if self.is_mock_mode: + create_mock_helicone_client() + verbose_logger.info("[HELICONE MOCK] Helicone logger initialized in mock mode") + self.provider_url = "https://api.openai.com/v1" self.key = os.getenv("HELICONE_API_KEY") self.api_base = os.getenv("HELICONE_API_BASE") or "https://api.hconeai.com" @@ -185,7 +195,10 @@ class HeliconeLogger: } response = litellm.module_level_client.post(url, headers=headers, json=data) if response.status_code == 200: - print_verbose("Helicone Logging - Success!") + if self.is_mock_mode: + print_verbose("[HELICONE MOCK] Helicone Logging - Successfully mocked!") + else: + print_verbose("Helicone Logging - Success!") else: print_verbose( f"Helicone Logging - Error Request was not successful. Status Code: {response.status_code}" diff --git a/litellm/integrations/helicone_mock_client.py b/litellm/integrations/helicone_mock_client.py new file mode 100644 index 00000000000..0f4670a1d2c --- /dev/null +++ b/litellm/integrations/helicone_mock_client.py @@ -0,0 +1,32 @@ +""" +Mock HTTP client for Helicone integration testing. + +This module intercepts Helicone API calls and returns successful mock responses, +allowing full code execution without making actual network calls. + +Usage: + Set HELICONE_MOCK=true in environment variables or config to enable mock mode. +""" + +from litellm.integrations.mock_client_factory import MockClientConfig, create_mock_client_factory + +# Create mock client using factory +# Helicone uses HTTPHandler which internally uses httpx.Client.send(), not httpx.Client.post() +_config = MockClientConfig( + name="HELICONE", + env_var="HELICONE_MOCK", + default_latency_ms=100, + default_status_code=200, + default_json_data={"status": "success"}, + url_matchers=[ + ".hconeai.com", + "hconeai.com", + ".helicone.ai", + "helicone.ai", + ], + patch_async_handler=False, + patch_sync_client=False, # HTTPHandler uses self.client.send(), not self.client.post() + patch_http_handler=True, # Patch HTTPHandler.post directly +) + +create_mock_helicone_client, should_use_helicone_mock = create_mock_client_factory(_config) diff --git a/litellm/integrations/langfuse/langfuse.py b/litellm/integrations/langfuse/langfuse.py index 46ada3c3930..7bf97665fd2 100644 --- a/litellm/integrations/langfuse/langfuse.py +++ b/litellm/integrations/langfuse/langfuse.py @@ -23,6 +23,7 @@ from litellm.constants import MAX_LANGFUSE_INITIALIZED_CLIENTS from litellm.litellm_core_utils.core_helpers import ( safe_deep_copy, reconstruct_model_name, + filter_exceptions_from_params, ) from litellm.litellm_core_utils.redact_messages import redact_user_api_key_info from litellm.integrations.langfuse.langfuse_mock_client import ( @@ -75,9 +76,8 @@ def _extract_cache_read_input_tokens(usage_obj) -> int: # Check prompt_tokens_details.cached_tokens (used by Gemini and other providers) if hasattr(usage_obj, "prompt_tokens_details"): prompt_tokens_details = getattr(usage_obj, "prompt_tokens_details", None) - if ( - prompt_tokens_details is not None - and hasattr(prompt_tokens_details, "cached_tokens") + if prompt_tokens_details is not None and hasattr( + prompt_tokens_details, "cached_tokens" ): cached_tokens = getattr(prompt_tokens_details, "cached_tokens", None) if ( @@ -540,7 +540,6 @@ class LangFuseLogger: verbose_logger.debug("Langfuse Layer Logging - logging to langfuse v2") try: - metadata = metadata or {} standard_logging_object: Optional[StandardLoggingPayload] = cast( Optional[StandardLoggingPayload], kwargs.get("standard_logging_object", None), @@ -706,9 +705,10 @@ class LangFuseLogger: clean_metadata["litellm_response_cost"] = cost if standard_logging_object is not None: - clean_metadata["hidden_params"] = standard_logging_object[ - "hidden_params" - ] + hidden_params = standard_logging_object.get("hidden_params", {}) + clean_metadata["hidden_params"] = filter_exceptions_from_params( + hidden_params + ) if ( litellm.langfuse_default_tags is not None diff --git a/litellm/integrations/langfuse/langfuse_mock_client.py b/litellm/integrations/langfuse/langfuse_mock_client.py index 1dc739ea328..8ed6cff8d47 100644 --- a/litellm/integrations/langfuse/langfuse_mock_client.py +++ b/litellm/integrations/langfuse/langfuse_mock_client.py @@ -9,113 +9,27 @@ Usage: """ import httpx -import json -from datetime import timedelta -from typing import Dict, Optional +from litellm.integrations.mock_client_factory import MockClientConfig, create_mock_client_factory -from litellm._logging import verbose_logger - -_original_httpx_post = None - -# Default mock latency in seconds (simulates network round-trip) -# Typical Langfuse API calls take 50-150ms -_MOCK_LATENCY_SECONDS = float(__import__("os").getenv("LANGFUSE_MOCK_LATENCY_MS", "100")) / 1000.0 - - -class MockLangfuseResponse: - """Mock httpx.Response that satisfies Langfuse SDK requirements.""" - - def __init__(self, status_code: int = 200, json_data: Optional[Dict] = None, url: Optional[str] = None, elapsed_seconds: float = 0.0): - self.status_code = status_code - self._json_data = json_data or {"status": "success"} - self.headers = httpx.Headers({}) - self.is_success = status_code < 400 - self.is_error = status_code >= 400 - self.is_redirect = 300 <= status_code < 400 - self.url = httpx.URL(url) if url else httpx.URL("") - # Set realistic elapsed time based on mock latency - elapsed_time = elapsed_seconds if elapsed_seconds > 0 else _MOCK_LATENCY_SECONDS - self.elapsed = timedelta(seconds=elapsed_time) - self._text = json.dumps(self._json_data) - self._content = self._text.encode("utf-8") - - @property - def text(self) -> str: - return self._text - - @property - def content(self) -> bytes: - return self._content - - def json(self) -> Dict: - return self._json_data - - def read(self) -> bytes: - return self._content - - def raise_for_status(self): - if self.status_code >= 400: - raise Exception(f"HTTP {self.status_code}") - - -def _is_langfuse_url(url) -> bool: - """Check if URL is a Langfuse domain.""" - try: - parsed_url = httpx.URL(url) if isinstance(url, str) else url - hostname = parsed_url.host or "" - - return ( - hostname.endswith(".langfuse.com") or - hostname == "langfuse.com" or - (hostname in ("localhost", "127.0.0.1") and "langfuse" in str(parsed_url).lower()) - ) - except Exception: - return False - - -def _mock_httpx_post(self, url, **kwargs): - """Monkey-patched httpx.Client.post that intercepts Langfuse calls.""" - if _is_langfuse_url(url): - verbose_logger.info(f"[LANGFUSE MOCK] POST to {url}") - return MockLangfuseResponse(status_code=200, json_data={"status": "success"}, url=url, elapsed_seconds=_MOCK_LATENCY_SECONDS) - - if _original_httpx_post is not None: - return _original_httpx_post(self, url, **kwargs) +# Create mock client using factory +_config = MockClientConfig( + name="LANGFUSE", + env_var="LANGFUSE_MOCK", + default_latency_ms=100, + default_status_code=200, + default_json_data={"status": "success"}, + url_matchers=[ + ".langfuse.com", + "langfuse.com", + ], + patch_async_handler=False, + patch_sync_client=True, +) +_create_mock_langfuse_client_internal, should_use_langfuse_mock = create_mock_client_factory(_config) +# Langfuse needs to return an httpx.Client instance def create_mock_langfuse_client(): - """ - Monkey-patch httpx.Client.post to intercept Langfuse calls. - - Returns a real httpx.Client instance - the monkey-patch intercepts all calls. - """ - global _original_httpx_post - - if _original_httpx_post is None: - _original_httpx_post = httpx.Client.post - httpx.Client.post = _mock_httpx_post # type: ignore - verbose_logger.debug("[LANGFUSE MOCK] Patched httpx.Client.post") - + """Create and return an httpx.Client instance - the monkey-patch intercepts all calls.""" + _create_mock_langfuse_client_internal() return httpx.Client() - - -def should_use_langfuse_mock() -> bool: - """ - Determine if Langfuse should run in mock mode. - - Checks the LANGFUSE_MOCK environment variable. - - Returns: - bool: True if mock mode should be enabled - """ - import os - from litellm.secret_managers.main import str_to_bool - - mock_mode = os.getenv("LANGFUSE_MOCK", "false") - result = str_to_bool(mock_mode) - result = bool(result) if result is not None else False - - if result: - verbose_logger.info("Langfuse Mock Mode: ENABLED - API calls will be mocked") - - return result diff --git a/litellm/integrations/langfuse/langfuse_prompt_management.py b/litellm/integrations/langfuse/langfuse_prompt_management.py index 8f73eabad44..3986fc6a6ef 100644 --- a/litellm/integrations/langfuse/langfuse_prompt_management.py +++ b/litellm/integrations/langfuse/langfuse_prompt_management.py @@ -300,43 +300,59 @@ class LangfusePromptManagement(LangFuseLogger, PromptManagementBase, CustomLogge ) async def async_log_success_event(self, kwargs, response_obj, start_time, end_time): - standard_callback_dynamic_params = kwargs.get( - "standard_callback_dynamic_params" - ) - langfuse_logger_to_use = LangFuseHandler.get_langfuse_logger_for_request( - globalLangfuseLogger=self, - standard_callback_dynamic_params=standard_callback_dynamic_params, - in_memory_dynamic_logger_cache=in_memory_dynamic_logger_cache, - ) - langfuse_logger_to_use.log_event_on_langfuse( - kwargs=kwargs, - response_obj=response_obj, - start_time=start_time, - end_time=end_time, - user_id=kwargs.get("user", None), - ) + try: + standard_callback_dynamic_params = kwargs.get( + "standard_callback_dynamic_params" + ) + langfuse_logger_to_use = LangFuseHandler.get_langfuse_logger_for_request( + globalLangfuseLogger=self, + standard_callback_dynamic_params=standard_callback_dynamic_params, + in_memory_dynamic_logger_cache=in_memory_dynamic_logger_cache, + ) + langfuse_logger_to_use.log_event_on_langfuse( + kwargs=kwargs, + response_obj=response_obj, + start_time=start_time, + end_time=end_time, + user_id=kwargs.get("user", None), + ) + except Exception as e: + from litellm._logging import verbose_logger + + verbose_logger.exception( + f"Langfuse Layer Error - Exception occurred while logging success event: {str(e)}" + ) + self.handle_callback_failure(callback_name="langfuse") async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time): - standard_callback_dynamic_params = kwargs.get( - "standard_callback_dynamic_params" - ) - langfuse_logger_to_use = LangFuseHandler.get_langfuse_logger_for_request( - globalLangfuseLogger=self, - standard_callback_dynamic_params=standard_callback_dynamic_params, - in_memory_dynamic_logger_cache=in_memory_dynamic_logger_cache, - ) - standard_logging_object = cast( - Optional[StandardLoggingPayload], - kwargs.get("standard_logging_object", None), - ) - if standard_logging_object is None: - return - langfuse_logger_to_use.log_event_on_langfuse( - start_time=start_time, - end_time=end_time, - response_obj=None, - user_id=kwargs.get("user", None), - status_message=standard_logging_object["error_str"], - level="ERROR", - kwargs=kwargs, - ) + try: + standard_callback_dynamic_params = kwargs.get( + "standard_callback_dynamic_params" + ) + langfuse_logger_to_use = LangFuseHandler.get_langfuse_logger_for_request( + globalLangfuseLogger=self, + standard_callback_dynamic_params=standard_callback_dynamic_params, + in_memory_dynamic_logger_cache=in_memory_dynamic_logger_cache, + ) + standard_logging_object = cast( + Optional[StandardLoggingPayload], + kwargs.get("standard_logging_object", None), + ) + if standard_logging_object is None: + return + langfuse_logger_to_use.log_event_on_langfuse( + start_time=start_time, + end_time=end_time, + response_obj=None, + user_id=kwargs.get("user", None), + status_message=standard_logging_object["error_str"], + level="ERROR", + kwargs=kwargs, + ) + except Exception as e: + from litellm._logging import verbose_logger + + verbose_logger.exception( + f"Langfuse Layer Error - Exception occurred while logging failure event: {str(e)}" + ) + self.handle_callback_failure(callback_name="langfuse") diff --git a/litellm/integrations/langsmith.py b/litellm/integrations/langsmith.py index 5893f14105d..ebd005f8804 100644 --- a/litellm/integrations/langsmith.py +++ b/litellm/integrations/langsmith.py @@ -15,6 +15,10 @@ from pydantic import BaseModel # type: ignore import litellm from litellm._logging import verbose_logger from litellm.integrations.custom_batch_logger import CustomBatchLogger +from litellm.integrations.langsmith_mock_client import ( + should_use_langsmith_mock, + create_mock_langsmith_client, +) from litellm.llms.custom_httpx.http_handler import ( get_async_httpx_client, httpxSpecialProvider, @@ -45,6 +49,12 @@ class LangsmithLogger(CustomBatchLogger): ): self.flush_lock = asyncio.Lock() super().__init__(**kwargs, flush_lock=self.flush_lock) + self.is_mock_mode = should_use_langsmith_mock() + + if self.is_mock_mode: + create_mock_langsmith_client() + verbose_logger.debug("[LANGSMITH MOCK] LangSmith logger initialized in mock mode") + self.default_credentials = self.get_credentials_from_env( langsmith_api_key=langsmith_api_key, langsmith_project=langsmith_project, @@ -388,6 +398,8 @@ class LangsmithLogger(CustomBatchLogger): verbose_logger.debug( "Sending batch of %s runs to Langsmith", len(elements_to_log) ) + if self.is_mock_mode: + verbose_logger.debug("[LANGSMITH MOCK] Mock mode enabled - API calls will be intercepted") response = await self.async_httpx_client.post( url=url, json={"post": elements_to_log}, @@ -400,9 +412,14 @@ class LangsmithLogger(CustomBatchLogger): f"Langsmith Error: {response.status_code} - {response.text}" ) else: - verbose_logger.debug( - f"Batch of {len(self.log_queue)} runs successfully created" - ) + if self.is_mock_mode: + verbose_logger.debug( + f"[LANGSMITH MOCK] Batch of {len(elements_to_log)} runs successfully mocked" + ) + else: + verbose_logger.debug( + f"Batch of {len(self.log_queue)} runs successfully created" + ) except httpx.HTTPStatusError as e: verbose_logger.exception( f"Langsmith HTTP Error: {e.response.status_code} - {e.response.text}" diff --git a/litellm/integrations/langsmith_mock_client.py b/litellm/integrations/langsmith_mock_client.py new file mode 100644 index 00000000000..ef602908231 --- /dev/null +++ b/litellm/integrations/langsmith_mock_client.py @@ -0,0 +1,29 @@ +""" +Mock client for LangSmith integration testing. + +This module intercepts LangSmith API calls and returns successful mock responses, +allowing full code execution without making actual network calls. + +Usage: + Set LANGSMITH_MOCK=true in environment variables or config to enable mock mode. +""" + +from litellm.integrations.mock_client_factory import MockClientConfig, create_mock_client_factory + +# Create mock client using factory +_config = MockClientConfig( + name="LANGSMITH", + env_var="LANGSMITH_MOCK", + default_latency_ms=100, + default_status_code=200, + default_json_data={"status": "success", "ids": ["mock-run-id"]}, + url_matchers=[ + ".smith.langchain.com", + "api.smith.langchain.com", + "smith.langchain.com", + ], + patch_async_handler=True, + patch_sync_client=False, +) + +create_mock_langsmith_client, should_use_langsmith_mock = create_mock_client_factory(_config) diff --git a/litellm/integrations/mock_client_factory.py b/litellm/integrations/mock_client_factory.py new file mode 100644 index 00000000000..2f04fae9f76 --- /dev/null +++ b/litellm/integrations/mock_client_factory.py @@ -0,0 +1,216 @@ +""" +Factory for creating mock HTTP clients for integration testing. + +This module provides a simple factory pattern to create mock clients that intercept +API calls and return successful mock responses, allowing full code execution without +making actual network calls. +""" + +import httpx +import json +import asyncio +from datetime import timedelta +from typing import Dict, Optional, List, cast +from dataclasses import dataclass + +from litellm._logging import verbose_logger + + +@dataclass +class MockClientConfig: + """Configuration for creating a mock client.""" + name: str # e.g., "GCS", "LANGFUSE", "LANGSMITH", "DATADOG" + env_var: str # e.g., "GCS_MOCK", "LANGFUSE_MOCK" + default_latency_ms: int = 100 # Default mock latency in milliseconds + default_status_code: int = 200 # Default HTTP status code + default_json_data: Optional[Dict] = None # Default JSON response data + url_matchers: Optional[List[str]] = None # List of strings to match in URLs (e.g., ["storage.googleapis.com"]) + patch_async_handler: bool = True # Whether to patch AsyncHTTPHandler.post + patch_sync_client: bool = False # Whether to patch httpx.Client.post + patch_http_handler: bool = False # Whether to patch HTTPHandler.post (for sync calls that use HTTPHandler) + + def __post_init__(self): + """Ensure url_matchers is a list.""" + if self.url_matchers is None: + self.url_matchers = [] + + +class MockResponse: + """Generic mock httpx.Response that satisfies API requirements.""" + + def __init__(self, status_code: int = 200, json_data: Optional[Dict] = None, url: Optional[str] = None, elapsed_seconds: float = 0.0): + self.status_code = status_code + self._json_data = json_data or {"status": "success"} + self.headers = httpx.Headers({}) + self.is_success = status_code < 400 + self.is_error = status_code >= 400 + self.is_redirect = 300 <= status_code < 400 + self.url = httpx.URL(url) if url else httpx.URL("") + self.elapsed = timedelta(seconds=elapsed_seconds) + self._text = json.dumps(self._json_data) if json_data else "" + self._content = self._text.encode("utf-8") + + @property + def text(self) -> str: + """Return response text.""" + return self._text + + @property + def content(self) -> bytes: + """Return response content.""" + return self._content + + def json(self) -> Dict: + """Return JSON response data.""" + return self._json_data + + def read(self) -> bytes: + """Read response content.""" + return self._content + + def raise_for_status(self): + """Raise exception for error status codes.""" + if self.status_code >= 400: + raise Exception(f"HTTP {self.status_code}") + + +def _is_url_match(url, matchers: List[str]) -> bool: + """Check if URL matches any of the provided matchers.""" + try: + parsed_url = httpx.URL(url) if isinstance(url, str) else url + url_str = str(parsed_url).lower() + hostname = parsed_url.host or "" + + for matcher in matchers: + if matcher.lower() in url_str or matcher.lower() in hostname.lower(): + return True + + # Also check for localhost with matcher in path + if hostname in ("localhost", "127.0.0.1"): + for matcher in matchers: + if matcher.lower() in url_str: + return True + + return False + except Exception: + return False + + +def create_mock_client_factory(config: MockClientConfig): # noqa: PLR0915 + """ + Factory function that creates mock client functions based on configuration. + + Returns: + tuple: (create_mock_client_func, should_use_mock_func) + """ + # Store original methods for restoration + _original_async_handler_post = None + _original_sync_client_post = None + _original_http_handler_post = None + _mocks_initialized = False + + # Calculate mock latency + import os + latency_env = f"{config.name.upper()}_MOCK_LATENCY_MS" + _MOCK_LATENCY_SECONDS = float(os.getenv(latency_env, str(config.default_latency_ms))) / 1000.0 + + # Create URL matcher function + def _is_mock_url(url) -> bool: + # url_matchers is guaranteed to be a list after __post_init__ + return _is_url_match(url, cast(List[str], config.url_matchers)) + + # Create async handler mock + async def _mock_async_handler_post(self, url, data=None, json=None, params=None, headers=None, timeout=None, stream=False, logging_obj=None, files=None, content=None): + """Monkey-patched AsyncHTTPHandler.post that intercepts API calls.""" + if isinstance(url, str) and _is_mock_url(url): + verbose_logger.info(f"[{config.name} MOCK] POST to {url}") + await asyncio.sleep(_MOCK_LATENCY_SECONDS) + return MockResponse( + status_code=config.default_status_code, + json_data=config.default_json_data, + url=url, + elapsed_seconds=_MOCK_LATENCY_SECONDS + ) + if _original_async_handler_post is not None: + return await _original_async_handler_post(self, url=url, data=data, json=json, params=params, headers=headers, timeout=timeout, stream=stream, logging_obj=logging_obj, files=files, content=content) + raise RuntimeError("Original AsyncHTTPHandler.post not available") + + # Create sync client mock + def _mock_sync_client_post(self, url, **kwargs): + """Monkey-patched httpx.Client.post that intercepts API calls.""" + if _is_mock_url(url): + verbose_logger.info(f"[{config.name} MOCK] POST to {url} (sync)") + return MockResponse( + status_code=config.default_status_code, + json_data=config.default_json_data, + url=url, + elapsed_seconds=_MOCK_LATENCY_SECONDS + ) + if _original_sync_client_post is not None: + return _original_sync_client_post(self, url, **kwargs) + + # Create HTTPHandler mock (for sync calls that use HTTPHandler.post) + def _mock_http_handler_post(self, url, data=None, json=None, params=None, headers=None, timeout=None, stream=False, files=None, content=None, logging_obj=None): + """Monkey-patched HTTPHandler.post that intercepts API calls.""" + if isinstance(url, str) and _is_mock_url(url): + verbose_logger.info(f"[{config.name} MOCK] POST to {url}") + import time + time.sleep(_MOCK_LATENCY_SECONDS) + return MockResponse( + status_code=config.default_status_code, + json_data=config.default_json_data, + url=url, + elapsed_seconds=_MOCK_LATENCY_SECONDS + ) + if _original_http_handler_post is not None: + return _original_http_handler_post(self, url=url, data=data, json=json, params=params, headers=headers, timeout=timeout, stream=stream, files=files, content=content, logging_obj=logging_obj) + raise RuntimeError("Original HTTPHandler.post not available") + + # Create mock client initialization function + def create_mock_client(): + """Initialize the mock client by patching HTTP handlers.""" + nonlocal _original_async_handler_post, _original_sync_client_post, _original_http_handler_post, _mocks_initialized + + if _mocks_initialized: + return + + verbose_logger.debug(f"[{config.name} MOCK] Initializing {config.name} mock client...") + + if config.patch_async_handler and _original_async_handler_post is None: + from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler + _original_async_handler_post = AsyncHTTPHandler.post + AsyncHTTPHandler.post = _mock_async_handler_post # type: ignore + verbose_logger.debug(f"[{config.name} MOCK] Patched AsyncHTTPHandler.post") + + if config.patch_sync_client and _original_sync_client_post is None: + _original_sync_client_post = httpx.Client.post + httpx.Client.post = _mock_sync_client_post # type: ignore + verbose_logger.debug(f"[{config.name} MOCK] Patched httpx.Client.post") + + if config.patch_http_handler and _original_http_handler_post is None: + from litellm.llms.custom_httpx.http_handler import HTTPHandler + _original_http_handler_post = HTTPHandler.post + HTTPHandler.post = _mock_http_handler_post # type: ignore + verbose_logger.debug(f"[{config.name} MOCK] Patched HTTPHandler.post") + + verbose_logger.debug(f"[{config.name} MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms") + verbose_logger.debug(f"[{config.name} MOCK] {config.name} mock client initialization complete") + + _mocks_initialized = True + + # Create should_use_mock function + def should_use_mock() -> bool: + """Determine if mock mode should be enabled.""" + import os + from litellm.secret_managers.main import str_to_bool + + mock_mode = os.getenv(config.env_var, "false") + result = str_to_bool(mock_mode) + result = bool(result) if result is not None else False + + if result: + verbose_logger.info(f"{config.name} Mock Mode: ENABLED - API calls will be mocked") + + return result + + return create_mock_client, should_use_mock diff --git a/litellm/integrations/opentelemetry.py b/litellm/integrations/opentelemetry.py index a8a7fa77b3d..18898be7dce 100644 --- a/litellm/integrations/opentelemetry.py +++ b/litellm/integrations/opentelemetry.py @@ -144,6 +144,7 @@ class OpenTelemetry(CustomLogger): self.OTEL_EXPORTER = self.config.exporter self.OTEL_ENDPOINT = self.config.endpoint self.OTEL_HEADERS = self.config.headers + self._tracer_provider_cache: Dict[str, Any] = {} self._init_tracing(tracer_provider) _debug_otel = str(os.getenv("DEBUG_OTEL", "False")).lower() @@ -615,12 +616,20 @@ class OpenTelemetry(CustomLogger): """Create a temporary tracer with dynamic headers for this request only.""" from opentelemetry.sdk.trace import TracerProvider + # Prevents thread exhaustion by reusing providers for the same credential sets (e.g. per-team keys) + cache_key = str(sorted(dynamic_headers.items())) + if cache_key in self._tracer_provider_cache: + return self._tracer_provider_cache[cache_key].get_tracer(LITELLM_TRACER_NAME) + # Create a temporary tracer provider with dynamic headers temp_provider = TracerProvider(resource=self._get_litellm_resource(self.config)) temp_provider.add_span_processor( self._get_span_processor(dynamic_headers=dynamic_headers) ) + # Store in cache for reuse + self._tracer_provider_cache[cache_key] = temp_provider + return temp_provider.get_tracer(LITELLM_TRACER_NAME) def construct_dynamic_otel_headers( @@ -995,9 +1004,13 @@ class OpenTelemetry(CustomLogger): from opentelemetry._logs import SeverityNumber, get_logger, get_logger_provider try: - from opentelemetry.sdk._logs import LogRecord as SdkLogRecord # type: ignore[attr-defined] # OTEL < 1.39.0 + from opentelemetry.sdk._logs import ( + LogRecord as SdkLogRecord, # type: ignore[attr-defined] # OTEL < 1.39.0 + ) except ImportError: - from opentelemetry.sdk._logs._internal import LogRecord as SdkLogRecord # OTEL >= 1.39.0 + from opentelemetry.sdk._logs._internal import ( + LogRecord as SdkLogRecord, # OTEL >= 1.39.0 + ) otel_logger = get_logger(LITELLM_LOGGER_NAME) @@ -1618,6 +1631,7 @@ class OpenTelemetry(CustomLogger): ) except Exception as e: + self.handle_callback_failure(callback_name=self.callback_name or "opentelemetry") verbose_logger.exception( "OpenTelemetry logging error in set_attributes %s", str(e) ) diff --git a/litellm/integrations/posthog.py b/litellm/integrations/posthog.py index 468b1a441fb..dd7c3627b87 100644 --- a/litellm/integrations/posthog.py +++ b/litellm/integrations/posthog.py @@ -17,6 +17,10 @@ from typing import Any, Dict, Optional, Tuple from litellm._logging import verbose_logger from litellm._uuid import uuid from litellm.integrations.custom_batch_logger import CustomBatchLogger +from litellm.integrations.posthog_mock_client import ( + should_use_posthog_mock, + create_mock_posthog_client, +) from litellm.llms.custom_httpx.http_handler import ( _get_httpx_client, get_async_httpx_client, @@ -40,6 +44,12 @@ class PostHogLogger(CustomBatchLogger): """ try: verbose_logger.debug("PostHog: in init posthog logger") + + self.is_mock_mode = should_use_posthog_mock() + if self.is_mock_mode: + create_mock_posthog_client() + verbose_logger.debug("[POSTHOG MOCK] PostHog logger initialized in mock mode") + if os.getenv("POSTHOG_API_KEY", None) is None: raise Exception("POSTHOG_API_KEY is not set, set 'POSTHOG_API_KEY=<>'") @@ -100,7 +110,10 @@ class PostHogLogger(CustomBatchLogger): f"Response from PostHog API status_code: {response.status_code}, text: {response.text}" ) - verbose_logger.debug("PostHog: Sync event successfully sent") + if self.is_mock_mode: + verbose_logger.debug("[POSTHOG MOCK] Sync event successfully mocked") + else: + verbose_logger.debug("PostHog: Sync event successfully sent") except Exception as e: verbose_logger.exception(f"PostHog Sync Layer Error - {str(e)}") @@ -320,6 +333,9 @@ class PostHogLogger(CustomBatchLogger): verbose_logger.debug( f"PostHog: Sending batch of {len(self.log_queue)} events" ) + + if self.is_mock_mode: + verbose_logger.debug("[POSTHOG MOCK] Mock mode enabled - API calls will be intercepted") # Group events by credentials for batch sending batches_by_credentials: Dict[tuple[str, str], list] = {} @@ -350,9 +366,12 @@ class PostHogLogger(CustomBatchLogger): f"Response from PostHog API status_code: {response.status_code}, text: {response.text}" ) - verbose_logger.debug( - f"PostHog: Batch of {len(self.log_queue)} events successfully sent" - ) + if self.is_mock_mode: + verbose_logger.debug(f"[POSTHOG MOCK] Batch of {len(self.log_queue)} events successfully mocked") + else: + verbose_logger.debug( + f"PostHog: Batch of {len(self.log_queue)} events successfully sent" + ) except Exception as e: verbose_logger.exception(f"PostHog Error sending batch API - {str(e)}") @@ -429,9 +448,14 @@ class PostHogLogger(CustomBatchLogger): f"PostHog: Failed to flush on exit - status {response.status_code}" ) - verbose_logger.debug( - f"PostHog: Successfully flushed {len(self.log_queue)} events on exit" - ) + if self.is_mock_mode: + verbose_logger.debug( + f"[POSTHOG MOCK] Successfully flushed {len(self.log_queue)} events on exit" + ) + else: + verbose_logger.debug( + f"PostHog: Successfully flushed {len(self.log_queue)} events on exit" + ) self.log_queue.clear() except Exception as e: diff --git a/litellm/integrations/posthog_mock_client.py b/litellm/integrations/posthog_mock_client.py new file mode 100644 index 00000000000..b713587ed6f --- /dev/null +++ b/litellm/integrations/posthog_mock_client.py @@ -0,0 +1,30 @@ +""" +Mock httpx client for PostHog integration testing. + +This module intercepts PostHog API calls and returns successful mock responses, +allowing full code execution without making actual network calls. + +Usage: + Set POSTHOG_MOCK=true in environment variables or config to enable mock mode. +""" + +from litellm.integrations.mock_client_factory import MockClientConfig, create_mock_client_factory + +# Create mock client using factory +_config = MockClientConfig( + name="POSTHOG", + env_var="POSTHOG_MOCK", + default_latency_ms=100, + default_status_code=200, + default_json_data={"status": "success"}, + url_matchers=[ + ".posthog.com", + "posthog.com", + "us.i.posthog.com", + "app.posthog.com", + ], + patch_async_handler=True, + patch_sync_client=True, +) + +create_mock_posthog_client, should_use_posthog_mock = create_mock_client_factory(_config) diff --git a/litellm/integrations/prometheus.py b/litellm/integrations/prometheus.py index bafb0d88c82..00c38eac188 100644 --- a/litellm/integrations/prometheus.py +++ b/litellm/integrations/prometheus.py @@ -229,14 +229,18 @@ class PrometheusLogger(CustomLogger): self.litellm_remaining_api_key_requests_for_model = self._gauge_factory( "litellm_remaining_api_key_requests_for_model", "Remaining Requests API Key can make for model (model based rpm limit on key)", - labelnames=["hashed_api_key", "api_key_alias", "model"], + labelnames=self.get_labels_for_metric( + "litellm_remaining_api_key_requests_for_model" + ), ) # Remaining MODEL TPM limit for API Key self.litellm_remaining_api_key_tokens_for_model = self._gauge_factory( "litellm_remaining_api_key_tokens_for_model", "Remaining Tokens API Key can make for model (model based tpm limit on key)", - labelnames=["hashed_api_key", "api_key_alias", "model"], + labelnames=self.get_labels_for_metric( + "litellm_remaining_api_key_tokens_for_model" + ), ) ######################################## @@ -312,6 +316,18 @@ class PrometheusLogger(CustomLogger): labelnames=self.get_labels_for_metric("litellm_deployment_state"), ) + self.litellm_deployment_tpm_limit = self._gauge_factory( + "litellm_deployment_tpm_limit", + "Deployment TPM limit found in config", + labelnames=self.get_labels_for_metric("litellm_deployment_tpm_limit"), + ) + + self.litellm_deployment_rpm_limit = self._gauge_factory( + "litellm_deployment_rpm_limit", + "Deployment RPM limit found in config", + labelnames=self.get_labels_for_metric("litellm_deployment_rpm_limit"), + ) + self.litellm_deployment_cooled_down = self._counter_factory( "litellm_deployment_cooled_down", "LLM Deployment Analytics - Number of times a deployment has been cooled down by LiteLLM load balancing logic. exception_status is the status of the exception that caused the deployment to be cooled down", @@ -373,15 +389,9 @@ class PrometheusLogger(CustomLogger): self.litellm_llm_api_failed_requests_metric = self._counter_factory( name="litellm_llm_api_failed_requests_metric", documentation="deprecated - use litellm_proxy_failed_requests_metric", - labelnames=[ - "end_user", - "hashed_api_key", - "api_key_alias", - "model", - "team", - "team_alias", - "user", - ], + labelnames=self.get_labels_for_metric( + "litellm_llm_api_failed_requests_metric" + ), ) self.litellm_requests_metric = self._counter_factory( @@ -891,7 +901,7 @@ class PrometheusLogger(CustomLogger): model = kwargs.get("model", "") litellm_params = kwargs.get("litellm_params", {}) or {} - _metadata = litellm_params.get("metadata", {}) + _metadata = litellm_params.get("metadata") or {} get_end_user_id_for_cost_tracking = _get_cached_end_user_id_for_cost_tracking() end_user_id = get_end_user_id_for_cost_tracking( @@ -954,6 +964,8 @@ class PrometheusLogger(CustomLogger): route=standard_logging_payload["metadata"].get( "user_api_key_request_route" ), + client_ip=standard_logging_payload["metadata"].get("requester_ip_address"), + user_agent=standard_logging_payload["metadata"].get("user_agent"), ) if ( @@ -1011,6 +1023,7 @@ class PrometheusLogger(CustomLogger): user_api_key_alias=user_api_key_alias, kwargs=kwargs, metadata=_metadata, + model_id=enum_values.model_id, ) # set latency metrics @@ -1165,26 +1178,15 @@ class PrometheusLogger(CustomLogger): response_cost: float, user_id: Optional[str] = None, ): - _team_spend = litellm_params.get("metadata", {}).get( - "user_api_key_team_spend", None - ) - _team_max_budget = litellm_params.get("metadata", {}).get( - "user_api_key_team_max_budget", None - ) + _metadata = litellm_params.get("metadata") or {} + _team_spend = _metadata.get("user_api_key_team_spend", None) + _team_max_budget = _metadata.get("user_api_key_team_max_budget", None) - _api_key_spend = litellm_params.get("metadata", {}).get( - "user_api_key_spend", None - ) - _api_key_max_budget = litellm_params.get("metadata", {}).get( - "user_api_key_max_budget", None - ) + _api_key_spend = _metadata.get("user_api_key_spend", None) + _api_key_max_budget = _metadata.get("user_api_key_max_budget", None) - _user_spend = litellm_params.get("metadata", {}).get( - "user_api_key_user_spend", None - ) - _user_max_budget = litellm_params.get("metadata", {}).get( - "user_api_key_user_max_budget", None - ) + _user_spend = _metadata.get("user_api_key_user_spend", None) + _user_max_budget = _metadata.get("user_api_key_user_max_budget", None) await self._set_api_key_budget_metrics_after_api_request( user_api_key=user_api_key, @@ -1245,6 +1247,7 @@ class PrometheusLogger(CustomLogger): user_api_key_alias: Optional[str], kwargs: dict, metadata: dict, + model_id: Optional[str] = None, ): from litellm.proxy.common_utils.callback_utils import ( get_model_group_from_litellm_kwargs, @@ -1266,11 +1269,11 @@ class PrometheusLogger(CustomLogger): ) self.litellm_remaining_api_key_requests_for_model.labels( - user_api_key, user_api_key_alias, model_group + user_api_key, user_api_key_alias, model_group, model_id ).set(remaining_requests) self.litellm_remaining_api_key_tokens_for_model.labels( - user_api_key, user_api_key_alias, model_group + user_api_key, user_api_key_alias, model_group, model_id ).set(remaining_tokens) def _set_latency_metrics( @@ -1296,12 +1299,14 @@ class PrometheusLogger(CustomLogger): time_to_first_token_seconds is not None and kwargs.get("stream", False) is True # only emit for streaming requests ): + _ttft_labels = prometheus_label_factory( + supported_enum_labels=self.get_labels_for_metric( + metric_name="litellm_llm_api_time_to_first_token_metric" + ), + enum_values=enum_values, + ) self.litellm_llm_api_time_to_first_token_metric.labels( - model, - user_api_key, - user_api_key_alias, - user_api_team, - user_api_team_alias, + **_ttft_labels ).observe(time_to_first_token_seconds) else: verbose_logger.debug( @@ -1341,7 +1346,7 @@ class PrometheusLogger(CustomLogger): # request queue time (time from arrival to processing start) _litellm_params = kwargs.get("litellm_params", {}) or {} - queue_time_seconds = _litellm_params.get("metadata", {}).get( + queue_time_seconds = (_litellm_params.get("metadata") or {}).get( "queue_time_seconds" ) if queue_time_seconds is not None and queue_time_seconds >= 0: @@ -1365,14 +1370,14 @@ class PrometheusLogger(CustomLogger): standard_logging_payload: StandardLoggingPayload = kwargs.get( "standard_logging_object", {} ) - + if self._should_skip_metrics_for_invalid_key( kwargs=kwargs, standard_logging_payload=standard_logging_payload ): return - + model = kwargs.get("model", "") - + litellm_params = kwargs.get("litellm_params", {}) or {} get_end_user_id_for_cost_tracking = _get_cached_end_user_id_for_cost_tracking() @@ -1396,6 +1401,7 @@ class PrometheusLogger(CustomLogger): user_api_team, user_api_team_alias, user_id, + standard_logging_payload.get("model_id", ""), ).inc() self.set_llm_deployment_failure_metrics(kwargs) except Exception as e: @@ -1413,49 +1419,57 @@ class PrometheusLogger(CustomLogger): ) -> Optional[int]: """ Extract HTTP status code from various input formats for validation. - + This is a centralized helper to extract status code from different callback function signatures. Handles both ProxyException (uses 'code') and standard exceptions (uses 'status_code'). - + Args: kwargs: Dictionary potentially containing 'exception' key enum_values: Object with 'status_code' attribute exception: Exception object to extract status code from directly - + Returns: Status code as integer if found, None otherwise """ status_code = None - + # Try from enum_values first (most common in our callbacks) - if enum_values and hasattr(enum_values, "status_code") and enum_values.status_code: + if ( + enum_values + and hasattr(enum_values, "status_code") + and enum_values.status_code + ): try: status_code = int(enum_values.status_code) except (ValueError, TypeError): pass - + if not status_code and exception: # ProxyException uses 'code' attribute, other exceptions may use 'status_code' - status_code = getattr(exception, "status_code", None) or getattr(exception, "code", None) + status_code = getattr(exception, "status_code", None) or getattr( + exception, "code", None + ) if status_code is not None: try: status_code = int(status_code) except (ValueError, TypeError): status_code = None - + if not status_code and kwargs: exception_in_kwargs = kwargs.get("exception") if exception_in_kwargs: - status_code = getattr(exception_in_kwargs, "status_code", None) or getattr(exception_in_kwargs, "code", None) + status_code = getattr( + exception_in_kwargs, "status_code", None + ) or getattr(exception_in_kwargs, "code", None) if status_code is not None: try: status_code = int(status_code) except (ValueError, TypeError): status_code = None - + return status_code - + def _is_invalid_api_key_request( self, status_code: Optional[int], @@ -1463,23 +1477,23 @@ class PrometheusLogger(CustomLogger): ) -> bool: """ Determine if a request has an invalid API key based on status code and exception. - + This method prevents invalid authentication attempts from being recorded in Prometheus metrics. A 401 status code is the definitive indicator of authentication failure. Additionally, we check exception messages for authentication error patterns to catch cases where the exception hasn't been converted to a ProxyException yet. - + Args: status_code: HTTP status code (401 indicates authentication error) exception: Exception object to check for auth-related error messages - + Returns: True if the request has an invalid API key and metrics should be skipped, False otherwise """ if status_code == 401: return True - + # Handle cases where AssertionError is raised before conversion to ProxyException if exception is not None: exception_str = str(exception).lower() @@ -1492,9 +1506,9 @@ class PrometheusLogger(CustomLogger): ] if any(pattern in exception_str for pattern in auth_error_patterns): return True - + return False - + def _should_skip_metrics_for_invalid_key( self, kwargs: Optional[dict] = None, @@ -1505,18 +1519,18 @@ class PrometheusLogger(CustomLogger): ) -> bool: """ Determine if Prometheus metrics should be skipped for invalid API key requests. - + This is a centralized validation method that extracts status code and exception information from various callback function signatures and determines if the request represents an invalid API key attempt that should be filtered from metrics. - + Args: kwargs: Dictionary potentially containing exception and other data user_api_key_dict: User API key authentication object (currently unused) enum_values: Object with status_code attribute standard_logging_payload: Standard logging payload dictionary exception: Exception object to check directly - + Returns: True if metrics should be skipped (invalid key detected), False otherwise """ @@ -1525,17 +1539,17 @@ class PrometheusLogger(CustomLogger): enum_values=enum_values, exception=exception, ) - + if exception is None and kwargs: exception = kwargs.get("exception") - + if self._is_invalid_api_key_request(status_code, exception=exception): verbose_logger.debug( "Skipping Prometheus metrics for invalid API key request: " f"status_code={status_code}, exception={type(exception).__name__ if exception else None}" ) return True - + return False async def async_post_call_failure_hook( @@ -1576,6 +1590,10 @@ class PrometheusLogger(CustomLogger): litellm_params=request_data, proxy_server_request=request_data.get("proxy_server_request", {}), ) + _metadata = request_data.get("metadata", {}) or {} + model_id = _metadata.get("model_info", {}).get("id") or request_data.get( + "model_info", {} + ).get("id") enum_values = UserAPIKeyLabelValues( end_user=user_api_key_dict.end_user_id, user=user_api_key_dict.user_id, @@ -1590,6 +1608,9 @@ class PrometheusLogger(CustomLogger): exception_class=self._get_exception_class_name(original_exception), tags=_tags, route=user_api_key_dict.request_route, + client_ip=_metadata.get("requester_ip_address"), + user_agent=_metadata.get("user_agent"), + model_id=model_id, ) _labels = prometheus_label_factory( supported_enum_labels=self.get_labels_for_metric( @@ -1629,6 +1650,7 @@ class PrometheusLogger(CustomLogger): ): return + _metadata = data.get("metadata", {}) or {} enum_values = UserAPIKeyLabelValues( end_user=user_api_key_dict.end_user_id, hashed_api_key=user_api_key_dict.api_key, @@ -1644,6 +1666,8 @@ class PrometheusLogger(CustomLogger): litellm_params=data, proxy_server_request=data.get("proxy_server_request", {}), ), + client_ip=_metadata.get("requester_ip_address"), + user_agent=_metadata.get("user_agent"), ) _labels = prometheus_label_factory( supported_enum_labels=self.get_labels_for_metric( @@ -1659,6 +1683,108 @@ class PrometheusLogger(CustomLogger): ) pass + def _safe_get(self, obj: Any, key: str, default: Any = None) -> Any: + """Get value from dict or Pydantic model.""" + if obj is None: + return default + if isinstance(obj, dict): + return obj.get(key, default) + return getattr(obj, key, default) + + def _extract_deployment_failure_label_values( + self, request_kwargs: dict + ) -> Dict[str, Optional[str]]: + """ + Extract label values for deployment failure metrics from all available + sources in request_kwargs. Falls back to litellm_params metadata and + user_api_key_auth when standard_logging_payload has None values. + """ + standard_logging_payload = ( + request_kwargs.get("standard_logging_object", {}) or {} + ) + _litellm_params = request_kwargs.get("litellm_params", {}) or {} + _metadata_raw = self._safe_get(standard_logging_payload, "metadata") or {} + if isinstance(_metadata_raw, dict): + _metadata = _metadata_raw + else: + _metadata = { + "user_api_key_alias": getattr( + _metadata_raw, "user_api_key_alias", None + ), + "user_api_key_team_id": getattr( + _metadata_raw, "user_api_key_team_id", None + ), + "user_api_key_team_alias": getattr( + _metadata_raw, "user_api_key_team_alias", None + ), + "user_api_key_hash": getattr(_metadata_raw, "user_api_key_hash", None), + "requester_ip_address": getattr( + _metadata_raw, "requester_ip_address", None + ), + "user_agent": getattr(_metadata_raw, "user_agent", None), + } + _litellm_params_metadata = _litellm_params.get("metadata", {}) or {} + + # Extract user_api_key_auth if present (proxy injects this, skipped in merge) + user_api_key_auth = _litellm_params_metadata.get("user_api_key_auth") + + def _get_api_key_alias() -> Optional[str]: + val = _metadata.get("user_api_key_alias") + if val is not None: + return val + val = _litellm_params_metadata.get("user_api_key_alias") + if val is not None: + return val + if user_api_key_auth is not None: + return getattr(user_api_key_auth, "key_alias", None) + return None + + def _get_team_id() -> Optional[str]: + val = _metadata.get("user_api_key_team_id") + if val is not None: + return val + val = _litellm_params_metadata.get("user_api_key_team_id") + if val is not None: + return val + if user_api_key_auth is not None: + return getattr(user_api_key_auth, "team_id", None) + return None + + def _get_team_alias() -> Optional[str]: + val = _metadata.get("user_api_key_team_alias") + if val is not None: + return val + val = _litellm_params_metadata.get("user_api_key_team_alias") + if val is not None: + return val + if user_api_key_auth is not None: + return getattr(user_api_key_auth, "team_alias", None) + return None + + def _get_hashed_api_key() -> Optional[str]: + val = _metadata.get("user_api_key_hash") + if val is not None: + return val + val = _litellm_params_metadata.get("user_api_key_hash") + if val is not None: + return val + if user_api_key_auth is not None: + return getattr(user_api_key_auth, "api_key", None) or getattr( + user_api_key_auth, "api_key_hash", None + ) + return None + + return { + "api_key_alias": _get_api_key_alias(), + "team": _get_team_id(), + "team_alias": _get_team_alias(), + "hashed_api_key": _get_hashed_api_key(), + "client_ip": _metadata.get("requester_ip_address") + or _litellm_params_metadata.get("requester_ip_address"), + "user_agent": _metadata.get("user_agent") + or _litellm_params_metadata.get("user_agent"), + } + def set_llm_deployment_failure_metrics(self, request_kwargs: dict): """ Sets Failure metrics when an LLM API call fails @@ -1683,16 +1809,59 @@ class PrometheusLogger(CustomLogger): model_id = standard_logging_payload.get("model_id", None) exception = request_kwargs.get("exception", None) + # Fallback: model_id from litellm_metadata.model_info + if model_id is None: + _model_info = ( + (_litellm_params.get("litellm_metadata") or {}).get("model_info") + or (_litellm_params.get("metadata") or {}).get("model_info") + or {} + ) + model_id = _model_info.get("id") + + # Fallback: model_group from litellm_metadata + if model_group is None: + model_group = (_litellm_params.get("litellm_metadata") or {}).get( + "model_group" + ) or (_litellm_params.get("metadata") or {}).get("model_group") + llm_provider = _litellm_params.get("custom_llm_provider", None) - + if self._should_skip_metrics_for_invalid_key( kwargs=request_kwargs, standard_logging_payload=standard_logging_payload, ): return - hashed_api_key = standard_logging_payload.get("metadata", {}).get( + + # Extract context labels from all available sources (fix for None labels) + fallback_values = self._extract_deployment_failure_label_values( + request_kwargs + ) + _metadata = standard_logging_payload.get("metadata", {}) or {} + hashed_api_key = fallback_values.get("hashed_api_key") or _metadata.get( "user_api_key_hash" ) + api_key_alias = fallback_values.get("api_key_alias") or _metadata.get( + "user_api_key_alias" + ) + team = fallback_values.get("team") or _metadata.get("user_api_key_team_id") + team_alias = fallback_values.get("team_alias") or _metadata.get( + "user_api_key_team_alias" + ) + client_ip = fallback_values.get("client_ip") or _metadata.get( + "requester_ip_address" + ) + user_agent = fallback_values.get("user_agent") or _metadata.get( + "user_agent" + ) + + # exception_status: prefer status_code, fallback to exception class for known types + exception_status = None + if exception is not None: + exception_status = str(getattr(exception, "status_code", None)) + if exception_status == "None" or not exception_status: + code = getattr(exception, "code", None) + if code is not None: + exception_status = str(code) # Create enum_values for the label factory (always create for use in different metrics) enum_values = UserAPIKeyLabelValues( @@ -1700,22 +1869,18 @@ class PrometheusLogger(CustomLogger): model_id=model_id, api_base=api_base, api_provider=llm_provider, - exception_status=( - str(getattr(exception, "status_code", None)) if exception else None - ), + exception_status=exception_status, exception_class=( self._get_exception_class_name(exception) if exception else None ), - requested_model=model_group, + requested_model=model_group or litellm_model_name, hashed_api_key=hashed_api_key, - api_key_alias=standard_logging_payload["metadata"][ - "user_api_key_alias" - ], - team=standard_logging_payload["metadata"]["user_api_key_team_id"], - team_alias=standard_logging_payload["metadata"][ - "user_api_key_team_alias" - ], + api_key_alias=api_key_alias, + team=team, + team_alias=team_alias, tags=standard_logging_payload.get("request_tags", []), + client_ip=client_ip, + user_agent=user_agent, ) """ @@ -1753,6 +1918,49 @@ class PrometheusLogger(CustomLogger): ) ) + def _set_deployment_tpm_rpm_limit_metrics( + self, + model_info: dict, + litellm_params: dict, + litellm_model_name: Optional[str], + model_id: Optional[str], + api_base: Optional[str], + llm_provider: Optional[str], + ): + """ + Set the deployment TPM and RPM limits metrics + """ + tpm = model_info.get("tpm") or litellm_params.get("tpm") + rpm = model_info.get("rpm") or litellm_params.get("rpm") + + if tpm is not None: + _labels = prometheus_label_factory( + supported_enum_labels=self.get_labels_for_metric( + metric_name="litellm_deployment_tpm_limit" + ), + enum_values=UserAPIKeyLabelValues( + litellm_model_name=litellm_model_name, + model_id=model_id, + api_base=api_base, + api_provider=llm_provider, + ), + ) + self.litellm_deployment_tpm_limit.labels(**_labels).set(tpm) + + if rpm is not None: + _labels = prometheus_label_factory( + supported_enum_labels=self.get_labels_for_metric( + metric_name="litellm_deployment_rpm_limit" + ), + enum_values=UserAPIKeyLabelValues( + litellm_model_name=litellm_model_name, + model_id=model_id, + api_base=api_base, + api_provider=llm_provider, + ), + ) + self.litellm_deployment_rpm_limit.labels(**_labels).set(rpm) + def set_llm_deployment_success_metrics( self, request_kwargs: dict, @@ -1786,6 +1994,16 @@ class PrometheusLogger(CustomLogger): _model_info = _metadata.get("model_info") or {} model_id = _model_info.get("id", None) + if _model_info or _litellm_params: + self._set_deployment_tpm_rpm_limit_metrics( + model_info=_model_info, + litellm_params=_litellm_params, + litellm_model_name=litellm_model_name, + model_id=model_id, + api_base=api_base, + llm_provider=llm_provider, + ) + remaining_requests: Optional[int] = None remaining_tokens: Optional[int] = None if additional_headers := standard_logging_payload["hidden_params"][ @@ -2263,7 +2481,10 @@ class PrometheusLogger(CustomLogger): async def fetch_keys( page_size: int, page: int - ) -> Tuple[List[Union[str, UserAPIKeyAuth, LiteLLM_DeletedVerificationToken]], Optional[int]]: + ) -> Tuple[ + List[Union[str, UserAPIKeyAuth, LiteLLM_DeletedVerificationToken]], + Optional[int], + ]: key_list_response = await _list_key_helper( prisma_client=prisma_client, page=page, @@ -2379,12 +2600,16 @@ class PrometheusLogger(CustomLogger): # Get total user count total_users = await prisma_client.db.litellm_usertable.count() self.litellm_total_users_metric.set(total_users) - verbose_logger.debug(f"Prometheus: set litellm_total_users to {total_users}") + verbose_logger.debug( + f"Prometheus: set litellm_total_users to {total_users}" + ) # Get total team count total_teams = await prisma_client.db.litellm_teamtable.count() self.litellm_teams_count_metric.set(total_teams) - verbose_logger.debug(f"Prometheus: set litellm_teams_count to {total_teams}") + verbose_logger.debug( + f"Prometheus: set litellm_teams_count to {total_teams}" + ) except Exception as e: verbose_logger.exception( f"Error initializing user/team count metrics: {str(e)}" @@ -2412,8 +2637,8 @@ class PrometheusLogger(CustomLogger): self, user_api_team: Optional[str], user_api_team_alias: Optional[str], - team_spend: float, - team_max_budget: float, + team_spend: Optional[float], + team_max_budget: Optional[float], response_cost: float, ): """ @@ -2575,7 +2800,7 @@ class PrometheusLogger(CustomLogger): user_api_key: Optional[str], user_api_key_alias: Optional[str], response_cost: float, - key_max_budget: float, + key_max_budget: Optional[float], key_spend: Optional[float], ): if user_api_key: @@ -2592,7 +2817,7 @@ class PrometheusLogger(CustomLogger): self, user_api_key: str, user_api_key_alias: str, - key_max_budget: float, + key_max_budget: Optional[float], key_spend: Optional[float], response_cost: float, ) -> UserAPIKeyAuth: diff --git a/litellm/integrations/prometheus_services.py b/litellm/integrations/prometheus_services.py index a5f2f0b5c72..55ce758ece6 100644 --- a/litellm/integrations/prometheus_services.py +++ b/litellm/integrations/prometheus_services.py @@ -105,6 +105,11 @@ class PrometheusServicesLogger: return metrics def is_metric_registered(self, metric_name) -> bool: + # Use _names_to_collectors (O(1)) instead of REGISTRY.collect() (O(n)) to avoid + # perf regression when a new Router is created per request (e.g. router_settings in DB). + names_to_collectors = getattr(self.REGISTRY, "_names_to_collectors", None) + if names_to_collectors is not None: + return metric_name in names_to_collectors for metric in self.REGISTRY.collect(): if metric_name == metric.name: return True diff --git a/litellm/litellm_core_utils/core_helpers.py b/litellm/litellm_core_utils/core_helpers.py index 9cb0a00d9fc..00695cbfb5b 100644 --- a/litellm/litellm_core_utils/core_helpers.py +++ b/litellm/litellm_core_utils/core_helpers.py @@ -351,9 +351,9 @@ def filter_exceptions_from_params(data: Any, max_depth: int = 20) -> Any: # Skip callable objects (functions, methods, lambdas) but not classes (type objects) if callable(data) and not isinstance(data, type): return None - # Skip known non-serializable object types (Logging, etc.) + # Skip known non-serializable object types (Logging, Router, etc.) obj_type_name = type(data).__name__ - if obj_type_name in ["Logging", "LiteLLMLoggingObj"]: + if obj_type_name in ["Logging", "LiteLLMLoggingObj", "Router"]: return None if isinstance(data, dict): diff --git a/litellm/litellm_core_utils/get_litellm_params.py b/litellm/litellm_core_utils/get_litellm_params.py index e290101f8bf..060e98fd49f 100644 --- a/litellm/litellm_core_utils/get_litellm_params.py +++ b/litellm/litellm_core_utils/get_litellm_params.py @@ -93,8 +93,11 @@ def get_litellm_params( "text_completion": text_completion, "azure_ad_token_provider": azure_ad_token_provider, "user_continue_message": user_continue_message, - "base_model": base_model or ( - _get_base_model_from_litellm_call_metadata(metadata=metadata) if metadata else None + "base_model": base_model + or ( + _get_base_model_from_litellm_call_metadata(metadata=metadata) + if metadata + else None ), "litellm_trace_id": litellm_trace_id, "litellm_session_id": litellm_session_id, @@ -139,5 +142,7 @@ def get_litellm_params( "aws_sts_endpoint": kwargs.get("aws_sts_endpoint"), "aws_external_id": kwargs.get("aws_external_id"), "aws_bedrock_runtime_endpoint": kwargs.get("aws_bedrock_runtime_endpoint"), + "tpm": kwargs.get("tpm"), + "rpm": kwargs.get("rpm"), } return litellm_params diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index fadeeffa9cc..1b3a687f1f3 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -335,7 +335,9 @@ class Logging(LiteLLMLoggingBaseClass): self.start_time = start_time # log the call start time self.call_type = call_type self.litellm_call_id = litellm_call_id - self.litellm_trace_id: str = litellm_trace_id if litellm_trace_id else str(uuid.uuid4()) + self.litellm_trace_id: str = ( + litellm_trace_id if litellm_trace_id else str(uuid.uuid4()) + ) self.function_id = function_id self.streaming_chunks: List[Any] = [] # for generating complete stream response self.sync_streaming_chunks: List[ @@ -544,7 +546,10 @@ class Logging(LiteLLMLoggingBaseClass): if "stream_options" in additional_params: self.stream_options = additional_params["stream_options"] ## check if custom pricing set ## - if any(litellm_params.get(key) is not None for key in _CUSTOM_PRICING_KEYS & litellm_params.keys()): + if any( + litellm_params.get(key) is not None + for key in _CUSTOM_PRICING_KEYS & litellm_params.keys() + ): self.custom_pricing = True if "custom_llm_provider" in self.model_call_details: @@ -1292,6 +1297,7 @@ class Logging(LiteLLMLoggingBaseClass): output_cost: float, total_cost: float, cost_for_built_in_tools_cost_usd_dollar: float, + additional_costs: Optional[dict] = None, original_cost: Optional[float] = None, discount_percent: Optional[float] = None, discount_amount: Optional[float] = None, @@ -1307,6 +1313,7 @@ class Logging(LiteLLMLoggingBaseClass): output_cost: Cost of output/completion tokens cost_for_built_in_tools_cost_usd_dollar: Cost of built-in tools total_cost: Total cost of request + additional_costs: Free-form additional costs dict (e.g., {"azure_model_router_flat_cost": 0.00014}) original_cost: Cost before discount discount_percent: Discount percentage (0.05 = 5%) discount_amount: Discount amount in USD @@ -1322,6 +1329,10 @@ class Logging(LiteLLMLoggingBaseClass): tool_usage_cost=cost_for_built_in_tools_cost_usd_dollar, ) + # Store additional costs if provided (free-form dict for extensibility) + if additional_costs and isinstance(additional_costs, dict) and len(additional_costs) > 0: + self.cost_breakdown["additional_costs"] = additional_costs + # Store discount information if provided if original_cost is not None: self.cost_breakdown["original_cost"] = original_cost @@ -1633,11 +1644,19 @@ class Logging(LiteLLMLoggingBaseClass): "standard_logging_object" ) ) is not None: - standard_logging_payload["response"] = ( + response_dict = ( result.model_dump() if hasattr(result, "model_dump") else dict(result) ) + # Ensure usage is properly included with transformed chat format + if transformed_usage is not None: + response_dict["usage"] = ( + transformed_usage.model_dump() + if hasattr(transformed_usage, "model_dump") + else dict(transformed_usage) + ) + standard_logging_payload["response"] = response_dict elif isinstance(result, TranscriptionResponse): from litellm.litellm_core_utils.llm_cost_calc.usage_object_transformation import ( TranscriptionUsageObjectTransformation, @@ -2323,18 +2342,28 @@ class Logging(LiteLLMLoggingBaseClass): batch_cost = kwargs.get("batch_cost", None) batch_usage = kwargs.get("batch_usage", None) batch_models = kwargs.get("batch_models", None) - if all([batch_cost, batch_usage, batch_models]) is not None: + has_explicit_batch_data = all( + x is not None for x in (batch_cost, batch_usage, batch_models) + ) + + should_compute_batch_data = ( + not is_base64_unified_file_id + or not has_explicit_batch_data + and result.status == "completed" + ) + if has_explicit_batch_data: result._hidden_params["response_cost"] = batch_cost result._hidden_params["batch_models"] = batch_models result.usage = batch_usage - elif not is_base64_unified_file_id: # only run for non-unified file ids + elif should_compute_batch_data: ( response_cost, batch_usage, batch_models, ) = await _handle_completed_batch( - batch=result, custom_llm_provider=self.custom_llm_provider + batch=result, + custom_llm_provider=self.custom_llm_provider, ) result._hidden_params["response_cost"] = response_cost @@ -2406,6 +2435,36 @@ class Logging(LiteLLMLoggingBaseClass): standard_built_in_tools_params=self.standard_built_in_tools_params, ) + # print standard logging payload + if ( + standard_logging_payload := self.model_call_details.get( + "standard_logging_object" + ) + ) is not None: + emit_standard_logging_payload(standard_logging_payload) + elif self.call_type == "pass_through_endpoint": + print_verbose( + "Async success callbacks: Got a pass-through endpoint response" + ) + + self.model_call_details["async_complete_streaming_response"] = result + + # cost calculation not possible for pass-through + self.model_call_details["response_cost"] = None + + ## STANDARDIZED LOGGING PAYLOAD + self.model_call_details[ + "standard_logging_object" + ] = get_standard_logging_object_payload( + kwargs=self.model_call_details, + init_response_obj=result, + start_time=start_time, + end_time=end_time, + logging_obj=self, + status="success", + standard_built_in_tools_params=self.standard_built_in_tools_params, + ) + # print standard logging payload if ( standard_logging_payload := self.model_call_details.get( @@ -3299,6 +3358,7 @@ def _get_masked_values( "token", "key", "secret", + "vertex_credentials", ] return { k: ( @@ -4453,6 +4513,7 @@ class StandardLoggingPayloadSetup: user_api_key_request_route=None, spend_logs_metadata=None, requester_ip_address=None, + user_agent=None, requester_metadata=None, prompt_management_metadata=prompt_management_metadata, applied_guardrails=applied_guardrails, @@ -4533,6 +4594,10 @@ class StandardLoggingPayloadSetup: ) elif isinstance(usage, Usage): return usage + elif isinstance(usage, ResponseAPIUsage): + return ResponseAPILoggingUtils._transform_response_api_usage_to_chat_usage( + usage + ) elif isinstance(usage, dict): if ResponseAPILoggingUtils._is_response_api_usage(usage): return ( @@ -4733,7 +4798,14 @@ class StandardLoggingPayloadSetup: ) -> StandardLoggingPayloadErrorInformation: from litellm.constants import MAXIMUM_TRACEBACK_LINES_TO_LOG - error_status: str = str(getattr(original_exception, "status_code", "")) + # Check for 'code' first (used by ProxyException), then fall back to 'status_code' (used by LiteLLM exceptions) + # Ensure error_code is always a string for Prisma Python JSON field compatibility + error_code_attr = getattr(original_exception, "code", None) + if error_code_attr is not None and str(error_code_attr) not in ("", "None"): + error_status: str = str(error_code_attr) + else: + status_code_attr = getattr(original_exception, "status_code", None) + error_status = str(status_code_attr) if status_code_attr is not None else "" error_class: str = ( str(original_exception.__class__.__name__) if original_exception else "" ) @@ -5138,6 +5210,7 @@ def get_standard_logging_object_payload( model_group=_model_group, model_id=_model_id, requester_ip_address=clean_metadata.get("requester_ip_address", None), + user_agent=clean_metadata.get("user_agent", None), messages=StandardLoggingPayloadSetup.append_system_prompt_messages( kwargs=kwargs, messages=kwargs.get("messages") ), @@ -5203,6 +5276,7 @@ def get_standard_logging_metadata( user_api_key_team_alias=None, spend_logs_metadata=None, requester_ip_address=None, + user_agent=None, requester_metadata=None, user_api_key_end_user_id=None, prompt_management_metadata=None, diff --git a/litellm/litellm_core_utils/llm_cost_calc/utils.py b/litellm/litellm_core_utils/llm_cost_calc/utils.py index 785976ed319..2308dc7beca 100644 --- a/litellm/litellm_core_utils/llm_cost_calc/utils.py +++ b/litellm/litellm_core_utils/llm_cost_calc/utils.py @@ -23,6 +23,15 @@ def _is_above_128k(tokens: float) -> bool: return False +def get_billable_input_tokens(usage: Usage) -> int: + """ + Returns the number of billable input tokens. + Subtracts cached tokens from prompt tokens if applicable. + """ + details = _parse_prompt_tokens_details(usage) + return usage.prompt_tokens - details["cache_hit_tokens"] + + def select_cost_metric_for_model( model_info: ModelInfo, ) -> Literal["cost_per_character", "cost_per_token"]: @@ -190,7 +199,6 @@ def _get_token_base_cost( 1000 if "k" in threshold_str else 1 ) if usage.prompt_tokens > threshold: - prompt_base_cost = cast( float, _get_cost_per_unit(model_info, key, prompt_base_cost) ) @@ -207,6 +215,9 @@ def _get_token_base_cost( cache_creation_tiered_key = ( f"cache_creation_input_token_cost_above_{threshold_str}_tokens" ) + cache_creation_1hr_tiered_key = ( + f"cache_creation_input_token_cost_above_1hr_above_{threshold_str}_tokens" + ) cache_read_tiered_key = ( f"cache_read_input_token_cost_above_{threshold_str}_tokens" ) @@ -221,6 +232,16 @@ def _get_token_base_cost( ), ) + if cache_creation_1hr_tiered_key in model_info: + cache_creation_cost_above_1hr = cast( + float, + _get_cost_per_unit( + model_info, + cache_creation_1hr_tiered_key, + cache_creation_cost_above_1hr, + ), + ) + if cache_read_tiered_key in model_info: cache_read_cost = cast( float, @@ -566,14 +587,28 @@ def generic_cost_per_token( # noqa: PLR0915 if usage.prompt_tokens_details: prompt_tokens_details = _parse_prompt_tokens_details(usage) - ## EDGE CASE - text tokens not set inside PromptTokensDetails + ## EDGE CASE - text tokens not set or includes cached tokens (double-counting) + ## Some providers (like xAI) report text_tokens = prompt_tokens (including cached) + ## We detect this when: text_tokens + cached_tokens + other > prompt_tokens + ## Ref: https://github.com/BerriAI/litellm/issues/19680, #14874, #14875 - if prompt_tokens_details["text_tokens"] == 0: + cache_hit = prompt_tokens_details["cache_hit_tokens"] + text_tokens = prompt_tokens_details["text_tokens"] + audio_tokens = prompt_tokens_details["audio_tokens"] + cache_creation = prompt_tokens_details["cache_creation_tokens"] + image_tokens = prompt_tokens_details["image_tokens"] + + # Check for double-counting: sum of details > prompt_tokens means overlap + total_details = text_tokens + cache_hit + audio_tokens + cache_creation + image_tokens + has_double_counting = cache_hit > 0 and total_details > usage.prompt_tokens + + if text_tokens == 0 or has_double_counting: text_tokens = ( usage.prompt_tokens - - prompt_tokens_details["cache_hit_tokens"] - - prompt_tokens_details["audio_tokens"] - - prompt_tokens_details["cache_creation_tokens"] + - cache_hit + - audio_tokens + - cache_creation + - image_tokens ) prompt_tokens_details["text_tokens"] = text_tokens @@ -619,7 +654,11 @@ def generic_cost_per_token( # noqa: PLR0915 # Calculate text tokens as remainder when we have a breakdown # This handles cases like OpenAI's reasoning models where text_tokens isn't provided text_tokens = max( - 0, usage.completion_tokens - reasoning_tokens - audio_tokens - image_tokens + 0, + usage.completion_tokens + - reasoning_tokens + - audio_tokens + - image_tokens, ) else: # No breakdown at all, all tokens are text tokens diff --git a/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py b/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py index bbe28e3ec2c..25ad0a570cb 100644 --- a/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py +++ b/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py @@ -21,11 +21,13 @@ from litellm.types.utils import ( ChatCompletionMessageToolCall, ChatCompletionRedactedThinkingBlock, Choices, + CompletionTokensDetailsWrapper, Delta, EmbeddingResponse, Function, HiddenParams, ImageResponse, + PromptTokensDetailsWrapper, ) from litellm.types.utils import Logprobs as TextCompletionLogprobs from litellm.types.utils import ( @@ -304,6 +306,22 @@ class LiteLLMResponseObjectHandler: "text_tokens": 0, } + # Map Responses API naming to Chat Completions API naming for cost calculator + if usage.get("prompt_tokens") is None: + usage["prompt_tokens"] = usage.get("input_tokens", 0) + if usage.get("completion_tokens") is None: + usage["completion_tokens"] = usage.get("output_tokens", 0) + + # Convert dicts to wrapper objects so getattr() works in cost calculation + if isinstance(usage.get("input_tokens_details"), dict): + usage["prompt_tokens_details"] = PromptTokensDetailsWrapper( + **usage["input_tokens_details"] + ) + if isinstance(usage.get("output_tokens_details"), dict): + usage["completion_tokens_details"] = CompletionTokensDetailsWrapper( + **usage["output_tokens_details"] + ) + if model_response_object is None: model_response_object = ImageResponse(**response_object) return model_response_object diff --git a/litellm/litellm_core_utils/logging_worker.py b/litellm/litellm_core_utils/logging_worker.py index 13a83956edd..d5eca9eeb55 100644 --- a/litellm/litellm_core_utils/logging_worker.py +++ b/litellm/litellm_core_utils/logging_worker.py @@ -415,6 +415,28 @@ class LoggingWorker: """ Safely log a message during shutdown, suppressing errors if logging is closed. """ + # Check if logger has valid handlers before attempting to log + # During shutdown, handlers may be closed, causing ValueError when writing + if not hasattr(verbose_logger, 'handlers') or not verbose_logger.handlers: + return + + # Check if any handler has a valid stream + has_valid_handler = False + for handler in verbose_logger.handlers: + try: + if hasattr(handler, 'stream') and handler.stream and not handler.stream.closed: + has_valid_handler = True + break + elif not hasattr(handler, 'stream'): + # Non-stream handlers (like NullHandler) are always valid + has_valid_handler = True + break + except (AttributeError, ValueError): + continue + + if not has_valid_handler: + return + try: if level == "debug": verbose_logger.debug(message) diff --git a/litellm/litellm_core_utils/model_param_helper.py b/litellm/litellm_core_utils/model_param_helper.py index 91f2f1341cf..4d45c47c224 100644 --- a/litellm/litellm_core_utils/model_param_helper.py +++ b/litellm/litellm_core_utils/model_param_helper.py @@ -17,15 +17,16 @@ from litellm.types.rerank import RerankRequest class ModelParamHelper: + # Cached at class level — deterministic set built from static OpenAI type annotations + _relevant_logging_args: frozenset = frozenset() + @staticmethod def get_standard_logging_model_parameters( model_parameters: dict, ) -> dict: """ """ standard_logging_model_parameters: dict = {} - supported_model_parameters = ( - ModelParamHelper._get_relevant_args_to_use_for_logging() - ) + supported_model_parameters = ModelParamHelper._relevant_logging_args for key, value in model_parameters.items(): if key in supported_model_parameters: @@ -172,3 +173,8 @@ class ModelParamHelper: Get the kwargs to exclude from the cache key """ return set(["metadata"]) + + +ModelParamHelper._relevant_logging_args = frozenset( + ModelParamHelper._get_relevant_args_to_use_for_logging() +) diff --git a/litellm/litellm_core_utils/prompt_templates/common_utils.py b/litellm/litellm_core_utils/prompt_templates/common_utils.py index 7790fb83361..b1c2d0a52f5 100644 --- a/litellm/litellm_core_utils/prompt_templates/common_utils.py +++ b/litellm/litellm_core_utils/prompt_templates/common_utils.py @@ -443,13 +443,21 @@ def update_messages_with_model_file_ids( def update_responses_input_with_model_file_ids( input: Any, + model_id: Optional[str] = None, + model_file_id_mapping: Optional[Dict[str, Dict[str, str]]] = None, ) -> Union[str, List[Dict[str, Any]]]: """ Updates responses API input with provider-specific file IDs. File IDs are always inside the content array, not as direct input_file items. - For managed files (unified file IDs), decodes the base64-encoded unified file ID - and extracts the llm_output_file_id directly. + For managed files (unified file IDs), uses model_file_id_mapping if provided, + otherwise decodes the base64-encoded unified file ID and extracts the llm_output_file_id directly. + + Args: + input: The responses API input parameter + model_id: The model ID to use for looking up provider-specific file IDs + model_file_id_mapping: Dictionary mapping litellm file IDs to provider file IDs + Format: {"litellm_file_id": {"model_id": "provider_file_id"}} """ from litellm.proxy.openai_files_endpoints.common_utils import ( _is_base64_encoded_unified_file_id, @@ -479,22 +487,35 @@ def update_responses_input_with_model_file_ids( ): file_id = content_item.get("file_id") if file_id: - # Check if this is a managed file ID (base64-encoded unified file ID) - is_unified_file_id = _is_base64_encoded_unified_file_id(file_id) - if is_unified_file_id: - unified_file_id = convert_b64_uid_to_unified_uid(file_id) - if "llm_output_file_id," in unified_file_id: - provider_file_id = unified_file_id.split( - "llm_output_file_id," - )[1].split(";")[0] - else: - # Fallback: keep original if we can't extract - provider_file_id = file_id + provider_file_id = file_id # Default to original + + # Check if we have a mapping for this file ID + if model_file_id_mapping and model_id and file_id in model_file_id_mapping: + # Use the model-specific file ID from mapping + provider_file_id = ( + model_file_id_mapping.get(file_id, {}).get(model_id) + or file_id + ) updated_content_item = content_item.copy() updated_content_item["file_id"] = provider_file_id updated_content.append(updated_content_item) else: - updated_content.append(content_item) + # Check if this is a base64-encoded unified file ID without mapping + is_unified_file_id = _is_base64_encoded_unified_file_id(file_id) + if is_unified_file_id: + # Fallback: decode unified file ID + unified_file_id = convert_b64_uid_to_unified_uid(file_id) + if "llm_output_file_id," in unified_file_id: + provider_file_id = unified_file_id.split( + "llm_output_file_id," + )[1].split(";")[0] + + updated_content_item = content_item.copy() + updated_content_item["file_id"] = provider_file_id + updated_content.append(updated_content_item) + else: + # Not a managed file, keep as-is + updated_content.append(content_item) else: updated_content.append(content_item) else: @@ -506,6 +527,68 @@ def update_responses_input_with_model_file_ids( return updated_input +def update_responses_tools_with_model_file_ids( + tools: Optional[List[Dict[str, Any]]], + model_id: Optional[str] = None, + model_file_id_mapping: Optional[Dict[str, Dict[str, str]]] = None, +) -> Optional[List[Dict[str, Any]]]: + """ + Updates responses API tools with provider-specific file IDs. + + Handles code_interpreter tools with container.file_ids. + + Args: + tools: The responses API tools parameter + model_id: The model ID to use for looking up provider-specific file IDs + model_file_id_mapping: Dictionary mapping litellm file IDs to provider file IDs + Format: {"litellm_file_id": {"model_id": "provider_file_id"}} + """ + if not tools or not isinstance(tools, list): + return tools + + if not model_file_id_mapping or not model_id: + return tools + + updated_tools = [] + for tool in tools: + if not isinstance(tool, dict): + updated_tools.append(tool) + continue + + updated_tool = tool.copy() + + # Handle code_interpreter with container file_ids + if tool.get("type") == "code_interpreter": + container = tool.get("container") + if isinstance(container, dict): + container_file_ids = container.get("file_ids") + if isinstance(container_file_ids, list): + updated_file_ids = [] + for file_id in container_file_ids: + if isinstance(file_id, str): + # Check if we have a mapping for this file ID + if file_id in model_file_id_mapping: + # Map to provider-specific file ID + provider_file_id = ( + model_file_id_mapping.get(file_id, {}).get(model_id) + or file_id + ) + updated_file_ids.append(provider_file_id) + else: + updated_file_ids.append(file_id) + else: + updated_file_ids.append(file_id) + + # Update the tool with new file IDs + updated_container = container.copy() + updated_container["file_ids"] = updated_file_ids + updated_tool["container"] = updated_container + + updated_tools.append(updated_tool) + + return updated_tools + + def extract_file_data(file_data: FileTypes) -> ExtractedFileData: """ Extracts and processes file data from various input formats. diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py index 30263543fc6..53d2ca2f23f 100644 --- a/litellm/litellm_core_utils/prompt_templates/factory.py +++ b/litellm/litellm_core_utils/prompt_templates/factory.py @@ -1632,6 +1632,7 @@ def _sanitize_anthropic_tool_use_id(tool_use_id: str) -> str: def convert_to_anthropic_tool_result( message: Union[ChatCompletionToolMessage, ChatCompletionFunctionMessage], + force_base64: bool = False, ) -> AnthropicMessagesToolResultParam: """ OpenAI message with a tool result looks like: @@ -1677,13 +1678,16 @@ def convert_to_anthropic_tool_result( ] = [] for content in content_list: if content["type"] == "text": - anthropic_content_list.append( - AnthropicMessagesToolResultContent( - type="text", - text=content["text"], - cache_control=content.get("cache_control", None), - ) - ) + # Only include cache_control if explicitly set and not None + # to avoid sending "cache_control": null which breaks some API channels + text_content: AnthropicMessagesToolResultContent = { + "type": "text", + "text": content["text"], + } + cache_control_value = content.get("cache_control") + if cache_control_value is not None: + text_content["cache_control"] = cache_control_value + anthropic_content_list.append(text_content) elif content["type"] == "image_url": format = ( content["image_url"].get("format") @@ -1691,7 +1695,7 @@ def convert_to_anthropic_tool_result( else None ) _anthropic_image_param = create_anthropic_image_param( - content["image_url"], format=format + content["image_url"], format=format, is_bedrock_invoke=force_base64 ) _anthropic_image_param = add_cache_control_to_content( anthropic_content_element=_anthropic_image_param, @@ -2053,6 +2057,12 @@ def anthropic_messages_pt( # noqa: PLR0915 else: messages.append(DEFAULT_USER_CONTINUE_MESSAGE_TYPED) + # Bedrock invoke models have format: invoke/... + # Vertex AI Anthropic also doesn't support URL sources for images + is_bedrock_invoke = model.lower().startswith("invoke/") + is_vertex_ai = llm_provider.startswith("vertex_ai") if llm_provider else False + force_base64 = is_bedrock_invoke or is_vertex_ai + msg_i = 0 while msg_i < len(messages): user_content: List[AnthropicMessagesUserMessageValues] = [] @@ -2162,7 +2172,9 @@ def anthropic_messages_pt( # noqa: PLR0915 ): # OpenAI's tool message content will always be a string user_content.append( - convert_to_anthropic_tool_result(user_message_types_block) + convert_to_anthropic_tool_result( + user_message_types_block, force_base64=force_base64 + ) ) msg_i += 1 @@ -3387,6 +3399,59 @@ def _convert_to_bedrock_tool_call_result( return content_block +def _deduplicate_bedrock_content_blocks( + blocks: List[BedrockContentBlock], + block_key: str, + id_key: str = "toolUseId", +) -> List[BedrockContentBlock]: + """ + Remove duplicate content blocks that share the same ID under ``block_key``. + + Bedrock requires all toolResult and toolUse IDs within a single message to + be unique. When merging consecutive messages, duplicates can occur if the + same tool_call_id appears multiple times in conversation history. + + When duplicates exist, the first occurrence is retained and subsequent ones + are discarded. A warning is logged for every dropped block so that + upstream duplication bugs remain visible. + + Blocks that do not contain ``block_key`` (e.g., cachePoint, text) are + always preserved. + + Args: + blocks: The list of Bedrock content blocks to deduplicate. + block_key: The dict key to inspect (e.g. ``"toolResult"`` or ``"toolUse"``). + id_key: The nested key that holds the unique ID (default ``"toolUseId"``). + """ + seen_ids: Set[str] = set() + deduplicated: List[BedrockContentBlock] = [] + for block in blocks: + keyed = block.get(block_key) + if keyed is not None and isinstance(keyed, dict): + block_id = keyed.get(id_key) + if block_id: + if block_id in seen_ids: + verbose_logger.warning( + "Bedrock Converse: dropping duplicate %s block with " + "%s=%s. This may indicate duplicate tool messages in " + "conversation history.", + block_key, + id_key, + block_id, + ) + continue + seen_ids.add(block_id) + deduplicated.append(block) + return deduplicated + + +def _deduplicate_bedrock_tool_content( + tool_content: List[BedrockContentBlock], +) -> List[BedrockContentBlock]: + """Convenience wrapper: deduplicate ``toolResult`` blocks by ``toolUseId``.""" + return _deduplicate_bedrock_content_blocks(tool_content, "toolResult") + + def _insert_assistant_continue_message( messages: List[BedrockMessageBlock], assistant_continue_message: Optional[ @@ -3855,6 +3920,8 @@ class BedrockConverseMessagesProcessor: tool_content.append(cache_point_block) msg_i += 1 + # Deduplicate toolResult blocks with the same toolUseId + tool_content = _deduplicate_bedrock_tool_content(tool_content) if tool_content: # if last message was a 'user' message, then add a blank assistant message (bedrock requires alternating roles) if len(contents) > 0 and contents[-1]["role"] == "user": @@ -3920,10 +3987,12 @@ class BedrockConverseMessagesProcessor: assistant_parts=assistants_parts, ) elif element["type"] == "text": - assistants_part = BedrockContentBlock( - text=element["text"] - ) - assistants_parts.append(assistants_part) + # Skip completely empty strings to avoid blank content blocks + if element.get("text", "").strip(): + assistants_part = BedrockContentBlock( + text=element["text"] + ) + assistants_parts.append(assistants_part) elif element["type"] == "image_url": if isinstance(element["image_url"], dict): image_url = element["image_url"]["url"] @@ -3948,9 +4017,12 @@ class BedrockConverseMessagesProcessor: elif _assistant_content is not None and isinstance( _assistant_content, str ): - assistant_content.append( - BedrockContentBlock(text=_assistant_content) - ) + # Skip completely empty strings to avoid blank content blocks + if _assistant_content.strip(): + assistant_content.append( + BedrockContentBlock(text=_assistant_content) + ) + # If content is empty/whitespace, skip it (don't add a placeholder) # Add cache point block for assistant string content _cache_point_block = ( litellm.AmazonConverseConfig()._get_cache_point_block( @@ -3968,6 +4040,8 @@ class BedrockConverseMessagesProcessor: msg_i += 1 + assistant_content = _deduplicate_bedrock_content_blocks(assistant_content, "toolUse") + if assistant_content: contents.append( BedrockMessageBlock(role="assistant", content=assistant_content) @@ -4218,6 +4292,8 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915 tool_content.append(cache_point_block) msg_i += 1 + # Deduplicate toolResult blocks with the same toolUseId + tool_content = _deduplicate_bedrock_tool_content(tool_content) if tool_content: # if last message was a 'user' message, then add a blank assistant message (bedrock requires alternating roles) if len(contents) > 0 and contents[-1]["role"] == "user": @@ -4277,12 +4353,11 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915 assistant_parts=assistants_parts, ) elif element["type"] == "text": - # AWS Bedrock doesn't allow empty or whitespace-only text content, so use placeholder for empty strings - text_content = ( - element["text"] if element["text"].strip() else "." - ) - assistants_part = BedrockContentBlock(text=text_content) - assistants_parts.append(assistants_part) + # AWS Bedrock doesn't allow empty or whitespace-only text content + # Skip completely empty strings to avoid blank content blocks + if element.get("text", "").strip(): + assistants_part = BedrockContentBlock(text=element["text"]) + assistants_parts.append(assistants_part) elif element["type"] == "image_url": if isinstance(element["image_url"], dict): image_url = element["image_url"]["url"] @@ -4305,9 +4380,9 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915 assistants_parts.append(_cache_point_block) assistant_content.extend(assistants_parts) elif _assistant_content is not None and isinstance(_assistant_content, str): - # AWS Bedrock doesn't allow empty or whitespace-only text content, so use placeholder for empty strings - text_content = _assistant_content if _assistant_content.strip() else "." - assistant_content.append(BedrockContentBlock(text=text_content)) + # Skip completely empty strings to avoid blank content blocks + if _assistant_content.strip(): + assistant_content.append(BedrockContentBlock(text=_assistant_content)) # Add cache point block for assistant string content _cache_point_block = ( litellm.AmazonConverseConfig()._get_cache_point_block( @@ -4324,6 +4399,8 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915 msg_i += 1 + assistant_content = _deduplicate_bedrock_content_blocks(assistant_content, "toolUse") + if assistant_content: contents.append( BedrockMessageBlock(role="assistant", content=assistant_content) @@ -4383,6 +4460,32 @@ def add_cache_point_tool_block(tool: dict) -> Optional[BedrockToolBlock]: return None +def _is_bedrock_tool_block(tool: dict) -> bool: + """ + Check if a tool is already a BedrockToolBlock. + + BedrockToolBlock has one of: systemTool, toolSpec, or cachePoint. + This is used to detect tools that are already in Bedrock format + (e.g., systemTool for Nova grounding) vs OpenAI-style function tools + that need transformation. + + Args: + tool: The tool dict to check + + Returns: + True if the tool is already a BedrockToolBlock, False otherwise + + Examples: + >>> _is_bedrock_tool_block({"systemTool": {"name": "nova_grounding"}}) + True + >>> _is_bedrock_tool_block({"type": "function", "function": {...}}) + False + """ + return isinstance(tool, dict) and ( + "systemTool" in tool or "toolSpec" in tool or "cachePoint" in tool + ) + + def _bedrock_tools_pt(tools: List) -> List[BedrockToolBlock]: """ OpenAI tools looks like: @@ -4408,7 +4511,7 @@ def _bedrock_tools_pt(tools: List) -> List[BedrockToolBlock]: ] """ """ - Bedrock toolConfig looks like: + Bedrock toolConfig looks like: "tools": [ { "toolSpec": { @@ -4436,6 +4539,13 @@ def _bedrock_tools_pt(tools: List) -> List[BedrockToolBlock]: tool_block_list: List[BedrockToolBlock] = [] for tool in tools: + # Check if tool is already a BedrockToolBlock (e.g., systemTool for Nova grounding) + if _is_bedrock_tool_block(tool): + # Already a BedrockToolBlock, pass it through + tool_block_list.append(tool) # type: ignore + continue + + # Handle regular OpenAI-style function tools parameters = tool.get("function", {}).get( "parameters", {"type": "object", "properties": {}} ) diff --git a/litellm/litellm_core_utils/prompt_templates/image_handling.py b/litellm/litellm_core_utils/prompt_templates/image_handling.py index 5d0bedb776d..7137a4e4222 100644 --- a/litellm/litellm_core_utils/prompt_templates/image_handling.py +++ b/litellm/litellm_core_utils/prompt_templates/image_handling.py @@ -31,15 +31,19 @@ def _process_image_response(response: Response, url: str) -> str: f"Error: Image size ({size_mb:.2f}MB) exceeds maximum allowed size ({MAX_IMAGE_URL_DOWNLOAD_SIZE_MB}MB). url={url}" ) - image_bytes = response.content + # Stream download with size checking to prevent downloading huge files + max_bytes = int(MAX_IMAGE_URL_DOWNLOAD_SIZE_MB * 1024 * 1024) + image_bytes = bytearray() + bytes_downloaded = 0 - # Check actual size after download if Content-Length was not available - if content_length is None: - size_mb = len(image_bytes) / (1024 * 1024) - if size_mb > MAX_IMAGE_URL_DOWNLOAD_SIZE_MB: + for chunk in response.iter_bytes(chunk_size=8192): + bytes_downloaded += len(chunk) + if bytes_downloaded > max_bytes: + size_mb = bytes_downloaded / (1024 * 1024) raise litellm.ImageFetchError( f"Error: Image size ({size_mb:.2f}MB) exceeds maximum allowed size ({MAX_IMAGE_URL_DOWNLOAD_SIZE_MB}MB). url={url}" ) + image_bytes.extend(chunk) base64_image = base64.b64encode(image_bytes).decode("utf-8") diff --git a/litellm/llms/a2a/__init__.py b/litellm/llms/a2a/__init__.py new file mode 100644 index 00000000000..043efa5e8bf --- /dev/null +++ b/litellm/llms/a2a/__init__.py @@ -0,0 +1,6 @@ +""" +A2A (Agent-to-Agent) Protocol Provider for LiteLLM +""" +from .chat.transformation import A2AConfig + +__all__ = ["A2AConfig"] diff --git a/litellm/llms/a2a/chat/__init__.py b/litellm/llms/a2a/chat/__init__.py new file mode 100644 index 00000000000..76bf4dd71d9 --- /dev/null +++ b/litellm/llms/a2a/chat/__init__.py @@ -0,0 +1,6 @@ +""" +A2A Chat Completion Implementation +""" +from .transformation import A2AConfig + +__all__ = ["A2AConfig"] diff --git a/litellm/llms/a2a/chat/streaming_iterator.py b/litellm/llms/a2a/chat/streaming_iterator.py new file mode 100644 index 00000000000..4b689414ddd --- /dev/null +++ b/litellm/llms/a2a/chat/streaming_iterator.py @@ -0,0 +1,103 @@ +""" +A2A Streaming Response Iterator +""" +from typing import Optional, Union + +from litellm.llms.base_llm.base_model_iterator import BaseModelResponseIterator +from litellm.types.utils import GenericStreamingChunk, ModelResponseStream + +from ..common_utils import extract_text_from_a2a_response + + +class A2AModelResponseIterator(BaseModelResponseIterator): + """ + Iterator for parsing A2A streaming responses. + + Converts A2A JSON-RPC streaming chunks to OpenAI-compatible format. + """ + + def __init__( + self, + streaming_response, + sync_stream: bool, + json_mode: Optional[bool] = False, + model: str = "a2a/agent", + ): + super().__init__( + streaming_response=streaming_response, + sync_stream=sync_stream, + json_mode=json_mode, + ) + self.model = model + + def chunk_parser(self, chunk: dict) -> Union[GenericStreamingChunk, ModelResponseStream]: + """ + Parse A2A streaming chunk to OpenAI format. + + A2A chunk format: + { + "jsonrpc": "2.0", + "id": "request-id", + "result": { + "message": { + "parts": [{"kind": "text", "text": "content"}] + } + } + } + + Or for tasks: + { + "jsonrpc": "2.0", + "result": { + "kind": "task", + "status": {"state": "running"}, + "artifacts": [{"parts": [{"kind": "text", "text": "content"}]}] + } + } + """ + try: + # Extract text from A2A response + text = extract_text_from_a2a_response(chunk) + + # Determine finish reason + finish_reason = self._get_finish_reason(chunk) + + # Return generic streaming chunk + return GenericStreamingChunk( + text=text, + is_finished=bool(finish_reason), + finish_reason=finish_reason or "", + usage=None, + index=0, + tool_use=None, + ) + except Exception: + # Return empty chunk on parse error + return GenericStreamingChunk( + text="", + is_finished=False, + finish_reason="", + usage=None, + index=0, + tool_use=None, + ) + + def _get_finish_reason(self, chunk: dict) -> Optional[str]: + """Extract finish reason from A2A chunk""" + result = chunk.get("result", {}) + + # Check for task completion + if isinstance(result, dict): + status = result.get("status", {}) + if isinstance(status, dict): + state = status.get("state") + if state == "completed": + return "stop" + elif state == "failed": + return "stop" # Map failed state to 'stop' (valid finish_reason) + + # Check for [DONE] marker + if chunk.get("done") is True: + return "stop" + + return None diff --git a/litellm/llms/a2a/chat/transformation.py b/litellm/llms/a2a/chat/transformation.py new file mode 100644 index 00000000000..163cd5ab22e --- /dev/null +++ b/litellm/llms/a2a/chat/transformation.py @@ -0,0 +1,370 @@ +""" +A2A Protocol Transformation for LiteLLM +""" +import uuid +from typing import Any, Dict, Iterator, List, Optional, Union + +import httpx + +from litellm.llms.base_llm.base_model_iterator import BaseModelResponseIterator +from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException +from litellm.types.llms.openai import AllMessageValues +from litellm.types.utils import Choices, Message, ModelResponse + +from ..common_utils import ( + A2AError, + convert_messages_to_prompt, + extract_text_from_a2a_response, +) +from .streaming_iterator import A2AModelResponseIterator + + +class A2AConfig(BaseConfig): + """ + Configuration for A2A (Agent-to-Agent) Protocol. + + Handles transformation between OpenAI and A2A JSON-RPC 2.0 formats. + """ + + @staticmethod + def resolve_agent_config_from_registry( + model: str, + api_base: Optional[str], + api_key: Optional[str], + headers: Optional[Dict[str, Any]], + optional_params: Dict[str, Any], + ) -> tuple[Optional[str], Optional[str], Optional[Dict[str, Any]]]: + """ + Resolve agent configuration from registry if model format is "a2a/". + + Extracts agent name from model string and looks up configuration in the + agent registry (if available in proxy context). + + Args: + model: Model string (e.g., "a2a/my-agent") + api_base: Explicit api_base (takes precedence over registry) + api_key: Explicit api_key (takes precedence over registry) + headers: Explicit headers (takes precedence over registry) + optional_params: Dict to merge additional litellm_params into + + Returns: + Tuple of (api_base, api_key, headers) with registry values filled in + """ + # Extract agent name from model (e.g., "a2a/my-agent" -> "my-agent") + agent_name = model.split("/", 1)[1] if "/" in model else None + + # Only lookup if agent name exists and some config is missing + if not agent_name or (api_base is not None and api_key is not None and headers is not None): + return api_base, api_key, headers + + # Try registry lookup (only available in proxy context) + try: + from litellm.proxy.agent_endpoints.agent_registry import ( + global_agent_registry, + ) + + agent = global_agent_registry.get_agent_by_name(agent_name) + if agent: + # Get api_base from agent card URL + if api_base is None and agent.agent_card_params: + api_base = agent.agent_card_params.get("url") + + # Get api_key, headers, and other params from litellm_params + if agent.litellm_params: + if api_key is None: + api_key = agent.litellm_params.get("api_key") + + if headers is None: + agent_headers = agent.litellm_params.get("headers") + if agent_headers: + headers = agent_headers + + # Merge other litellm_params (timeout, max_retries, etc.) + for key, value in agent.litellm_params.items(): + if key not in ["api_key", "api_base", "headers", "model"] and key not in optional_params: + optional_params[key] = value + except ImportError: + pass # Registry not available (not running in proxy context) + + return api_base, api_key, headers + + def get_supported_openai_params(self, model: str) -> List[str]: + """Return list of supported OpenAI parameters""" + return [ + "stream", + "temperature", + "max_tokens", + "top_p", + ] + + def map_openai_params( + self, + non_default_params: dict, + optional_params: dict, + model: str, + drop_params: bool, + ) -> dict: + """ + Map OpenAI parameters to A2A parameters. + + For A2A protocol, we need to map the stream parameter so + transform_request can determine which JSON-RPC method to use. + """ + # Map stream parameter + for param, value in non_default_params.items(): + if param == "stream" and value is True: + optional_params["stream"] = value + + return optional_params + + def validate_environment( + self, + headers: dict, + model: str, + messages: List[AllMessageValues], + optional_params: dict, + litellm_params: dict, + api_key: Optional[str] = None, + api_base: Optional[str] = None, + ) -> dict: + """ + Validate environment and set headers for A2A requests. + + Args: + headers: Request headers dict + model: Model name + messages: Messages list + optional_params: Optional parameters + litellm_params: LiteLLM parameters + api_key: API key (optional for A2A) + api_base: API base URL + + Returns: + Updated headers dict + """ + # Ensure Content-Type is set to application/json for JSON-RPC 2.0 + if "content-type" not in headers and "Content-Type" not in headers: + headers["Content-Type"] = "application/json" + + # Add Authorization header if API key is provided + if api_key is not None: + headers["Authorization"] = f"Bearer {api_key}" + + return headers + + def get_complete_url( + self, + api_base: Optional[str], + api_key: Optional[str], + model: str, + optional_params: dict, + litellm_params: dict, + stream: Optional[bool] = None, + ) -> str: + """ + Get the complete A2A agent endpoint URL. + + A2A agents use JSON-RPC 2.0 at the base URL, not specific paths. + The method (message/send or message/stream) is specified in the + JSON-RPC request body, not in the URL. + + Args: + api_base: Base URL of the A2A agent (e.g., "http://0.0.0.0:9999") + api_key: API key (not used for URL construction) + model: Model name (not used for A2A, agent determined by api_base) + optional_params: Optional parameters + litellm_params: LiteLLM parameters + stream: Whether this is a streaming request (affects JSON-RPC method) + + Returns: + Complete URL for the A2A endpoint (base URL) + """ + if api_base is None: + raise ValueError("api_base is required for A2A provider") + + # A2A uses JSON-RPC 2.0 at the base URL + # Remove trailing slash for consistency + return api_base.rstrip("/") + + def transform_request( + self, + model: str, + messages: List[AllMessageValues], + optional_params: dict, + litellm_params: dict, + headers: dict, + ) -> dict: + """ + Transform OpenAI request to A2A JSON-RPC 2.0 format. + + Args: + model: Model name + messages: List of OpenAI messages + optional_params: Optional parameters + litellm_params: LiteLLM parameters + headers: Request headers + + Returns: + A2A JSON-RPC 2.0 request dict + """ + # Generate request ID + request_id = str(uuid.uuid4()) + + if not messages: + raise ValueError("At least one message is required for A2A completion") + + # Convert all messages to maintain conversation history + # Use helper to format conversation with role prefixes + full_context = convert_messages_to_prompt(messages) + + # Create single A2A message with full conversation context + a2a_message = { + "role": "user", + "parts": [{"kind": "text", "text": full_context}], + "messageId": str(uuid.uuid4()), + } + + # Build JSON-RPC 2.0 request + # For A2A protocol, the method is "message/send" for non-streaming + # and "message/stream" for streaming + stream = optional_params.get("stream", False) + method = "message/stream" if stream else "message/send" + + request_data = { + "jsonrpc": "2.0", + "id": request_id, + "method": method, + "params": { + "message": a2a_message + } + } + + return request_data + + def transform_response( + self, + model: str, + raw_response: httpx.Response, + model_response: ModelResponse, + logging_obj: Any, + request_data: dict, + messages: List[AllMessageValues], + optional_params: dict, + litellm_params: dict, + encoding: Any, + api_key: Optional[str] = None, + json_mode: Optional[bool] = None, + ) -> ModelResponse: + """ + Transform A2A JSON-RPC 2.0 response to OpenAI format. + + Args: + model: Model name + raw_response: HTTP response from A2A agent + model_response: Model response object to populate + logging_obj: Logging object + request_data: Original request data + messages: Original messages + optional_params: Optional parameters + litellm_params: LiteLLM parameters + encoding: Encoding object + api_key: API key + json_mode: JSON mode flag + + Returns: + Populated ModelResponse object + """ + try: + response_json = raw_response.json() + except Exception as e: + raise A2AError( + status_code=raw_response.status_code, + message=f"Failed to parse A2A response: {str(e)}", + headers=dict(raw_response.headers), + ) + + # Check for JSON-RPC error + if "error" in response_json: + error = response_json["error"] + raise A2AError( + status_code=raw_response.status_code, + message=f"A2A error: {error.get('message', 'Unknown error')}", + headers=dict(raw_response.headers), + ) + + # Extract text from A2A response + text = extract_text_from_a2a_response(response_json) + + # Populate model response + model_response.choices = [ + Choices( + finish_reason="stop", + index=0, + message=Message( + content=text, + role="assistant", + ), + ) + ] + + # Set model + model_response.model = model + + # Set ID from response + model_response.id = response_json.get("id", str(uuid.uuid4())) + + return model_response + + def get_model_response_iterator( + self, + streaming_response: Union[Iterator, Any], + sync_stream: bool, + json_mode: Optional[bool] = False, + ) -> BaseModelResponseIterator: + """ + Get streaming iterator for A2A responses. + + Args: + streaming_response: Streaming response iterator + sync_stream: Whether this is a sync stream + json_mode: JSON mode flag + + Returns: + A2A streaming iterator + """ + return A2AModelResponseIterator( + streaming_response=streaming_response, + sync_stream=sync_stream, + json_mode=json_mode, + ) + + def _openai_message_to_a2a_message(self, message: Dict[str, Any]) -> Dict[str, Any]: + """ + Convert OpenAI message to A2A message format. + + Args: + message: OpenAI message dict + + Returns: + A2A message dict + """ + content = message.get("content", "") + role = message.get("role", "user") + + return { + "role": role, + "parts": [{"kind": "text", "text": str(content)}], + "messageId": str(uuid.uuid4()), + } + + def get_error_class( + self, error_message: str, status_code: int, headers: Union[dict, httpx.Headers] + ) -> BaseLLMException: + """Return appropriate error class for A2A errors""" + # Convert headers to dict if needed + headers_dict = dict(headers) if isinstance(headers, httpx.Headers) else headers + return A2AError( + status_code=status_code, + message=error_message, + headers=headers_dict, + ) diff --git a/litellm/llms/a2a/common_utils.py b/litellm/llms/a2a/common_utils.py new file mode 100644 index 00000000000..116e1205409 --- /dev/null +++ b/litellm/llms/a2a/common_utils.py @@ -0,0 +1,152 @@ +""" +Common utilities for A2A (Agent-to-Agent) Protocol +""" +from typing import Any, Dict, List + +from pydantic import BaseModel + +from litellm.litellm_core_utils.prompt_templates.common_utils import ( + convert_content_list_to_str, +) +from litellm.llms.base_llm.chat.transformation import BaseLLMException +from litellm.types.llms.openai import AllMessageValues + + +class A2AError(BaseLLMException): + """Base exception for A2A protocol errors""" + + def __init__( + self, + status_code: int, + message: str, + headers: Dict[str, Any] = {}, + ): + super().__init__( + status_code=status_code, + message=message, + headers=headers, + ) + + +def convert_messages_to_prompt(messages: List[AllMessageValues]) -> str: + """ + Convert OpenAI messages to a single prompt string for A2A agent. + + Formats each message as "{role}: {content}" and joins with newlines + to preserve conversation history. Handles both string and list content. + + Args: + messages: List of OpenAI-format messages + + Returns: + Formatted prompt string with full conversation context + """ + conversation_parts = [] + for msg in messages: + # Use LiteLLM's helper to extract text from content (handles both str and list) + content_text = convert_content_list_to_str(message=msg) + + # Get role + if isinstance(msg, BaseModel): + role = msg.model_dump().get("role", "user") + elif isinstance(msg, dict): + role = msg.get("role", "user") + else: + role = dict(msg).get("role", "user") # type: ignore + + if content_text: + conversation_parts.append(f"{role}: {content_text}") + + return "\n".join(conversation_parts) + + +def extract_text_from_a2a_message( + message: Dict[str, Any], depth: int = 0, max_depth: int = 10 +) -> str: + """ + Extract text content from A2A message parts. + + Args: + message: A2A message dict with 'parts' containing text parts + depth: Current recursion depth (internal use) + max_depth: Maximum recursion depth to prevent infinite loops + + Returns: + Concatenated text from all text parts + """ + if message is None or depth >= max_depth: + return "" + + parts = message.get("parts", []) + text_parts: List[str] = [] + + for part in parts: + if part.get("kind") == "text": + text_parts.append(part.get("text", "")) + # Handle nested parts if they exist + elif "parts" in part: + nested_text = extract_text_from_a2a_message(part, depth + 1, max_depth) + if nested_text: + text_parts.append(nested_text) + + return " ".join(text_parts) + + +def extract_text_from_a2a_response( + response_dict: Dict[str, Any], max_depth: int = 10 +) -> str: + """ + Extract text content from A2A response result. + + Args: + response_dict: A2A response dict with 'result' containing message + max_depth: Maximum recursion depth to prevent infinite loops + + Returns: + Text from response message parts + """ + result = response_dict.get("result", {}) + if not isinstance(result, dict): + return "" + + # A2A response can have different formats: + # 1. Direct message: {"result": {"kind": "message", "parts": [...]}} + # 2. Nested message: {"result": {"message": {"parts": [...]}}} + # 3. Task with artifacts: {"result": {"kind": "task", "artifacts": [{"parts": [...]}]}} + # 4. Task with status message: {"result": {"kind": "task", "status": {"message": {"parts": [...]}}}} + # 5. Streaming artifact-update: {"result": {"kind": "artifact-update", "artifact": {"parts": [...]}}} + + # Check if result itself has parts (direct message) + if "parts" in result: + return extract_text_from_a2a_message(result, depth=0, max_depth=max_depth) + + # Check for nested message + message = result.get("message") + if message: + return extract_text_from_a2a_message(message, depth=0, max_depth=max_depth) + + # Check for streaming artifact-update (singular artifact) + artifact = result.get("artifact") + if artifact and isinstance(artifact, dict): + return extract_text_from_a2a_message( + artifact, depth=0, max_depth=max_depth + ) + + # Check for task status message (common in Gemini A2A agents) + status = result.get("status", {}) + if isinstance(status, dict): + status_message = status.get("message") + if status_message: + return extract_text_from_a2a_message( + status_message, depth=0, max_depth=max_depth + ) + + # Handle task result with artifacts (plural, array) + artifacts = result.get("artifacts", []) + if artifacts and len(artifacts) > 0: + first_artifact = artifacts[0] + return extract_text_from_a2a_message( + first_artifact, depth=0, max_depth=max_depth + ) + + return "" diff --git a/litellm/llms/anthropic/chat/guardrail_translation/handler.py b/litellm/llms/anthropic/chat/guardrail_translation/handler.py index 9d50cc4d92d..a14e7d118e8 100644 --- a/litellm/llms/anthropic/chat/guardrail_translation/handler.py +++ b/litellm/llms/anthropic/chat/guardrail_translation/handler.py @@ -34,6 +34,7 @@ from litellm.types.llms.openai import ( ) from litellm.types.utils import ( ChatCompletionMessageToolCall, + Choices, GenericGuardrailAPIInputs, ModelResponse, ) @@ -74,9 +75,10 @@ class AnthropicMessagesHandler(BaseTranslation): if messages is None: return data - chat_completion_compatible_request = ( + chat_completion_compatible_request, tool_name_mapping = ( LiteLLMAnthropicMessagesAdapter().translate_anthropic_to_openai( - anthropic_message_request=cast(AnthropicMessagesRequest, data) + # Use a shallow copy to avoid mutating request data (pop on litellm_metadata). + anthropic_message_request=cast(AnthropicMessagesRequest, data.copy()) ) ) @@ -84,9 +86,9 @@ class AnthropicMessagesHandler(BaseTranslation): texts_to_check: List[str] = [] images_to_check: List[str] = [] - tools_to_check: List[ChatCompletionToolParam] = ( - chat_completion_compatible_request.get("tools", []) - ) + tools_to_check: List[ + ChatCompletionToolParam + ] = chat_completion_compatible_request.get("tools", []) task_mappings: List[Tuple[int, Optional[int]]] = [] # Track (message_index, content_index) for each text # content_index is None for string content, int for list content @@ -110,6 +112,10 @@ class AnthropicMessagesHandler(BaseTranslation): inputs["tools"] = tools_to_check if structured_messages: inputs["structured_messages"] = structured_messages + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, request_data=data, @@ -278,7 +284,10 @@ class AnthropicMessagesHandler(BaseTranslation): if hasattr(content_block, "model_dump"): block_dict = content_block.model_dump() else: - block_dict = {"type": block_type, "text": getattr(content_block, "text", None)} + block_dict = { + "type": block_type, + "text": getattr(content_block, "text", None), + } else: continue @@ -309,6 +318,14 @@ class AnthropicMessagesHandler(BaseTranslation): inputs["images"] = images_to_check if tool_calls_to_check: inputs["tool_calls"] = tool_calls_to_check + # Include model information from the response if available + response_model = None + if isinstance(response, dict): + response_model = response.get("model") + elif hasattr(response, "model"): + response_model = getattr(response, "model", None) + if response_model: + inputs["model"] = response_model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, @@ -346,30 +363,40 @@ class AnthropicMessagesHandler(BaseTranslation): """ has_ended = self._check_streaming_has_ended(responses_so_far) if has_ended: - # build the model response from the responses_so_far - model_response = cast( - ModelResponse, - AnthropicPassthroughLoggingHandler._build_complete_streaming_response( - all_chunks=responses_so_far, - litellm_logging_obj=cast("LiteLLMLoggingObj", litellm_logging_obj), - model="", - ), + built_response = AnthropicPassthroughLoggingHandler._build_complete_streaming_response( + all_chunks=responses_so_far, + litellm_logging_obj=cast("LiteLLMLoggingObj", litellm_logging_obj), + model="", ) - tool_calls_list = cast(Optional[List[ChatCompletionMessageToolCall]], model_response.choices[0].message.tool_calls) # type: ignore - string_so_far = model_response.choices[0].message.content # type: ignore - guardrail_inputs = GenericGuardrailAPIInputs() - if string_so_far: - guardrail_inputs["texts"] = [string_so_far] - if tool_calls_list: - guardrail_inputs["tool_calls"] = tool_calls_list - _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( # allow rejecting the response, if invalid - inputs=guardrail_inputs, - request_data={}, - input_type="response", - logging_obj=litellm_logging_obj, - ) + # Check if model_response is valid and has choices before accessing + if ( + built_response is not None + and hasattr(built_response, "choices") + and built_response.choices + ): + model_response = cast(ModelResponse, built_response) + first_choice = cast(Choices, model_response.choices[0]) + tool_calls_list = cast( + Optional[List[ChatCompletionMessageToolCall]], + first_choice.message.tool_calls, + ) + string_so_far = first_choice.message.content + guardrail_inputs = GenericGuardrailAPIInputs() + if string_so_far: + guardrail_inputs["texts"] = [string_so_far] + if tool_calls_list: + guardrail_inputs["tool_calls"] = tool_calls_list + + _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( # allow rejecting the response, if invalid + inputs=guardrail_inputs, + request_data={}, + input_type="response", + logging_obj=litellm_logging_obj, + ) + else: + verbose_proxy_logger.debug("Skipping output guardrail - model response has no choices") return responses_so_far string_so_far = self.get_streaming_string_so_far(responses_so_far) @@ -552,7 +579,7 @@ class AnthropicMessagesHandler(BaseTranslation): response_content = response.get("content", []) else: response_content = getattr(response, "content", None) or [] - + if not response_content: return False for content_block in response_content: @@ -636,7 +663,10 @@ class AnthropicMessagesHandler(BaseTranslation): if isinstance(content_block, dict): if content_block.get("type") == "text": cast(Dict[str, Any], content_block)["text"] = guardrail_response - elif hasattr(content_block, "type") and getattr(content_block, "type", None) == "text": + elif ( + hasattr(content_block, "type") + and getattr(content_block, "type", None) == "text" + ): # Update Pydantic object's text attribute if hasattr(content_block, "text"): content_block.text = guardrail_response diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index 82eccee596d..1b61b533275 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -290,10 +290,19 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): elif tool_choice == "none": _tool_choice = AnthropicMessagesToolChoice(type="none") elif isinstance(tool_choice, dict): - _tool_name = tool_choice.get("function", {}).get("name") - _tool_choice = AnthropicMessagesToolChoice(type="tool") - if _tool_name is not None: - _tool_choice["name"] = _tool_name + if "type" in tool_choice and "function" not in tool_choice: + tool_type = tool_choice.get("type") + if tool_type == "auto": + _tool_choice = AnthropicMessagesToolChoice(type="auto") + elif tool_type == "required" or tool_type == "any": + _tool_choice = AnthropicMessagesToolChoice(type="any") + elif tool_type == "none": + _tool_choice = AnthropicMessagesToolChoice(type="none") + else: + _tool_name = tool_choice.get("function", {}).get("name") + if _tool_name is not None: + _tool_choice = AnthropicMessagesToolChoice(type="tool") + _tool_choice["name"] = _tool_name if parallel_tool_use is not None: # Anthropic uses 'disable_parallel_tool_use' flag to determine if parallel tool use is allowed @@ -1369,7 +1378,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): else 0 ) completion_token_details = CompletionTokensDetailsWrapper( - reasoning_tokens=reasoning_tokens if reasoning_tokens > 0 else None, + reasoning_tokens=reasoning_tokens if reasoning_tokens > 0 else 0, text_tokens=completion_tokens - reasoning_tokens if reasoning_tokens > 0 else completion_tokens, ) total_tokens = prompt_tokens + completion_tokens diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py b/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py index 8fa7bb7e65e..a17eba75b3b 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py @@ -6,6 +6,7 @@ from typing import ( Dict, List, Optional, + Tuple, Union, cast, ) @@ -47,8 +48,14 @@ class LiteLLMMessagesToCompletionTransformationHandler: top_p: Optional[float] = None, output_format: Optional[Dict] = None, extra_kwargs: Optional[Dict[str, Any]] = None, - ) -> Dict[str, Any]: - """Prepare kwargs for litellm.completion/acompletion""" + ) -> Tuple[Dict[str, Any], Dict[str, str]]: + """Prepare kwargs for litellm.completion/acompletion. + + Returns: + Tuple of (completion_kwargs, tool_name_mapping) + - tool_name_mapping maps truncated tool names back to original names + for tools that exceeded OpenAI's 64-char limit + """ from litellm.litellm_core_utils.litellm_logging import ( Logging as LiteLLMLoggingObject, ) @@ -80,7 +87,7 @@ class LiteLLMMessagesToCompletionTransformationHandler: if output_format: request_data["output_format"] = output_format - openai_request = ANTHROPIC_ADAPTER.translate_completion_input_params( + openai_request, tool_name_mapping = ANTHROPIC_ADAPTER.translate_completion_input_params_with_tool_mapping( request_data ) @@ -116,7 +123,7 @@ class LiteLLMMessagesToCompletionTransformationHandler: ): completion_kwargs[key] = value - return completion_kwargs + return completion_kwargs, tool_name_mapping @staticmethod async def async_anthropic_messages_handler( @@ -137,7 +144,7 @@ class LiteLLMMessagesToCompletionTransformationHandler: **kwargs, ) -> Union[AnthropicMessagesResponse, AsyncIterator]: """Handle non-Anthropic models asynchronously using the adapter""" - completion_kwargs = ( + completion_kwargs, tool_name_mapping = ( LiteLLMMessagesToCompletionTransformationHandler._prepare_completion_kwargs( max_tokens=max_tokens, messages=messages, @@ -164,6 +171,7 @@ class LiteLLMMessagesToCompletionTransformationHandler: ANTHROPIC_ADAPTER.translate_completion_output_params_streaming( completion_response, model=model, + tool_name_mapping=tool_name_mapping, ) ) if transformed_stream is not None: @@ -172,7 +180,8 @@ class LiteLLMMessagesToCompletionTransformationHandler: else: anthropic_response = ( ANTHROPIC_ADAPTER.translate_completion_output_params( - cast(ModelResponse, completion_response) + cast(ModelResponse, completion_response), + tool_name_mapping=tool_name_mapping, ) ) if anthropic_response is not None: @@ -222,7 +231,7 @@ class LiteLLMMessagesToCompletionTransformationHandler: **kwargs, ) - completion_kwargs = ( + completion_kwargs, tool_name_mapping = ( LiteLLMMessagesToCompletionTransformationHandler._prepare_completion_kwargs( max_tokens=max_tokens, messages=messages, @@ -249,6 +258,7 @@ class LiteLLMMessagesToCompletionTransformationHandler: ANTHROPIC_ADAPTER.translate_completion_output_params_streaming( completion_response, model=model, + tool_name_mapping=tool_name_mapping, ) ) if transformed_stream is not None: @@ -257,7 +267,8 @@ class LiteLLMMessagesToCompletionTransformationHandler: else: anthropic_response = ( ANTHROPIC_ADAPTER.translate_completion_output_params( - cast(ModelResponse, completion_response) + cast(ModelResponse, completion_response), + tool_name_mapping=tool_name_mapping, ) ) if anthropic_response is not None: diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py index 24524233ddf..a86820f82e8 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py @@ -3,7 +3,7 @@ import json import traceback from collections import deque -from typing import TYPE_CHECKING, Any, AsyncIterator, Iterator, Literal, Optional +from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, Iterator, Literal, Optional from litellm import verbose_logger from litellm._uuid import uuid @@ -44,9 +44,16 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): pending_new_content_block: bool = False chunk_queue: deque = deque() # Queue for buffering multiple chunks - def __init__(self, completion_stream: Any, model: str): + def __init__( + self, + completion_stream: Any, + model: str, + tool_name_mapping: Optional[Dict[str, str]] = None, + ): super().__init__(completion_stream) self.model = model + # Mapping of truncated tool names to original names (for OpenAI's 64-char limit) + self.tool_name_mapping = tool_name_mapping or {} def _create_initial_usage_delta(self) -> UsageDelta: """ @@ -401,6 +408,19 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): choices=chunk.choices # type: ignore ) + # Restore original tool name if it was truncated for OpenAI's 64-char limit + if block_type == "tool_use": + # Type narrowing: content_block_start is ToolUseBlock when block_type is "tool_use" + from typing import cast + from litellm.types.llms.anthropic import ToolUseBlock + + tool_block = cast(ToolUseBlock, content_block_start) + + if tool_block.get("name"): + truncated_name = tool_block["name"] + original_name = self.tool_name_mapping.get(truncated_name, truncated_name) + tool_block["name"] = original_name + if block_type != self.current_content_block_type: self.current_content_block_type = block_type self.current_content_block_start = content_block_start @@ -408,9 +428,14 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): # For parallel tool calls, we'll necessarily have a new content block # if we get a function name since it signals a new tool call - if block_type == "tool_use" and content_block_start.get("name"): - self.current_content_block_type = block_type - self.current_content_block_start = content_block_start - return True + if block_type == "tool_use": + from typing import cast + from litellm.types.llms.anthropic import ToolUseBlock + + tool_block = cast(ToolUseBlock, content_block_start) + if tool_block.get("name"): + self.current_content_block_type = block_type + self.current_content_block_start = content_block_start + return True return False diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py index 1706f045f14..169b138a5f7 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py @@ -1,3 +1,4 @@ +import hashlib import json from typing import ( TYPE_CHECKING, @@ -12,6 +13,54 @@ from typing import ( cast, ) +# OpenAI has a 64-character limit for function/tool names +# Anthropic does not have this limit, so we need to truncate long names +OPENAI_MAX_TOOL_NAME_LENGTH = 64 +TOOL_NAME_HASH_LENGTH = 8 +TOOL_NAME_PREFIX_LENGTH = OPENAI_MAX_TOOL_NAME_LENGTH - TOOL_NAME_HASH_LENGTH - 1 # 55 + + +def truncate_tool_name(name: str) -> str: + """ + Truncate tool names that exceed OpenAI's 64-character limit. + + Uses format: {55-char-prefix}_{8-char-hash} to avoid collisions + when multiple tools have similar long names. + + Args: + name: The original tool name + + Returns: + The original name if <= 64 chars, otherwise truncated with hash + """ + if len(name) <= OPENAI_MAX_TOOL_NAME_LENGTH: + return name + + # Create deterministic hash from full name to avoid collisions + name_hash = hashlib.sha256(name.encode()).hexdigest()[:TOOL_NAME_HASH_LENGTH] + return f"{name[:TOOL_NAME_PREFIX_LENGTH]}_{name_hash}" + + +def create_tool_name_mapping( + tools: List[Dict[str, Any]], +) -> Dict[str, str]: + """ + Create a mapping of truncated tool names to original names. + + Args: + tools: List of tool definitions with 'name' field + + Returns: + Dict mapping truncated names to original names (only for truncated tools) + """ + mapping: Dict[str, str] = {} + for tool in tools: + original_name = tool.get("name", "") + truncated_name = truncate_tool_name(original_name) + if truncated_name != original_name: + mapping[truncated_name] = original_name + return mapping + from openai.types.chat.chat_completion_chunk import Choice as OpenAIStreamingChoice from litellm.litellm_core_utils.prompt_templates.common_utils import ( @@ -77,8 +126,29 @@ class AnthropicAdapter: self, kwargs ) -> Optional[ChatCompletionRequest]: """ + Translate Anthropic request params to OpenAI format. + - translate params, where needed - pass rest, as is + + Note: Use translate_completion_input_params_with_tool_mapping() if you need + the tool name mapping for restoring original names in responses. + """ + result, _ = self.translate_completion_input_params_with_tool_mapping(kwargs) + return result + + def translate_completion_input_params_with_tool_mapping( + self, kwargs + ) -> Tuple[Optional[ChatCompletionRequest], Dict[str, str]]: + """ + Translate Anthropic request params to OpenAI format, returning tool name mapping. + + This method handles truncation of tool names that exceed OpenAI's 64-character + limit. The mapping allows restoring original names when translating responses. + + Returns: + Tuple of (openai_request, tool_name_mapping) + - tool_name_mapping maps truncated tool names back to original names """ ######################################################### @@ -102,26 +172,51 @@ class AnthropicAdapter: model=model, messages=messages, **kwargs ) - translated_body = ( + translated_body, tool_name_mapping = ( LiteLLMAnthropicMessagesAdapter().translate_anthropic_to_openai( anthropic_message_request=request_body ) ) - return translated_body + return translated_body, tool_name_mapping def translate_completion_output_params( - self, response: ModelResponse + self, + response: ModelResponse, + tool_name_mapping: Optional[Dict[str, str]] = None, ) -> Optional[AnthropicMessagesResponse]: + """ + Translate OpenAI response to Anthropic format. + + Args: + response: The OpenAI ModelResponse + tool_name_mapping: Optional mapping of truncated tool names to original names. + Used to restore original names for tools that exceeded + OpenAI's 64-char limit. + """ return LiteLLMAnthropicMessagesAdapter().translate_openai_response_to_anthropic( - response=response + response=response, + tool_name_mapping=tool_name_mapping, ) def translate_completion_output_params_streaming( - self, completion_stream: Any, model: str + self, + completion_stream: Any, + model: str, + tool_name_mapping: Optional[Dict[str, str]] = None, ) -> Union[AsyncIterator[bytes], None]: + """ + Translate OpenAI streaming response to Anthropic format. + + Args: + completion_stream: The OpenAI streaming response + model: The model name + tool_name_mapping: Optional mapping of truncated tool names to original names. + """ anthropic_wrapper = AnthropicStreamWrapper( - completion_stream=completion_stream, model=model + completion_stream=completion_stream, + model=model, + tool_name_mapping=tool_name_mapping, ) # Return the SSE-wrapped version for proper event formatting return anthropic_wrapper.async_anthropic_sse_wrapper() @@ -168,6 +263,36 @@ class LiteLLMAnthropicMessagesAdapter: return provider_specific_fields.get("signature") return None + def _add_cache_control_if_applicable( + self, + source: Any, + target: Any, + model: Optional[str], + ) -> None: + """ + Extract cache_control from source and add to target if it should be preserved. + + This method accepts Any type to support both regular dicts and TypedDict objects. + TypedDict objects (like ChatCompletionTextObject, ChatCompletionImageObject, etc.) + are dicts at runtime but have specific types at type-check time. Using Any allows + this method to work with both while maintaining runtime correctness. + + Args: + source: Dict or TypedDict containing potential cache_control field + target: Dict or TypedDict to add cache_control to + model: Model name to check if cache_control should be preserved + """ + # TypedDict objects are dicts at runtime, so .get() works + cache_control = source.get("cache_control") if isinstance(source, dict) else getattr(source, "cache_control", None) + if cache_control and model and self.is_anthropic_claude_model(model): + # TypedDict objects support dict operations at runtime + # Use type ignore consistent with codebase pattern (see anthropic/chat/transformation.py:432) + if isinstance(target, dict): + target["cache_control"] = cache_control # type: ignore[typeddict-item] + else: + # Fallback for non-dict objects (shouldn't happen in practice) + cast(Dict[str, Any], target)["cache_control"] = cache_control + def translatable_anthropic_params(self) -> List: """ Which anthropic params, we need to translate to the openai format. @@ -205,12 +330,8 @@ class LiteLLMAnthropicMessagesAdapter: text_obj = ChatCompletionTextObject( type="text", text=content.get("text", "") ) - # Preserve cache_control if present (for prompt caching) - # Only for Anthropic models that support prompt caching - cache_control = content.get("cache_control") - if cache_control and model and self.is_anthropic_claude_model(model): - text_obj["cache_control"] = cache_control # type: ignore - new_user_content_list.append(text_obj) + self._add_cache_control_if_applicable(content, text_obj, model) + new_user_content_list.append(text_obj) # type: ignore elif content.get("type") == "image": # Convert Anthropic image format to OpenAI format source = content.get("source", {}) @@ -225,7 +346,24 @@ class LiteLLMAnthropicMessagesAdapter: image_obj = ChatCompletionImageObject( type="image_url", image_url=image_url_obj ) - new_user_content_list.append(image_obj) + self._add_cache_control_if_applicable(content, image_obj, model) + new_user_content_list.append(image_obj) # type: ignore + elif content.get("type") == "document": + # Convert Anthropic document format (PDF, etc.) to OpenAI format + source = content.get("source", {}) + openai_image_url = ( + self._translate_anthropic_image_to_openai(cast(dict, source)) + ) + + if openai_image_url: + image_url_obj = ChatCompletionImageUrlObject( + url=openai_image_url + ) + doc_obj = ChatCompletionImageObject( + type="image_url", image_url=image_url_obj + ) + self._add_cache_control_if_applicable(content, doc_obj, model) + new_user_content_list.append(doc_obj) # type: ignore elif content.get("type") == "tool_result": if "content" not in content: tool_result = ChatCompletionToolMessage( @@ -233,14 +371,16 @@ class LiteLLMAnthropicMessagesAdapter: tool_call_id=content.get("tool_use_id", ""), content="", ) - tool_message_list.append(tool_result) + self._add_cache_control_if_applicable(content, tool_result, model) + tool_message_list.append(tool_result) # type: ignore[arg-type] elif isinstance(content.get("content"), str): tool_result = ChatCompletionToolMessage( role="tool", tool_call_id=content.get("tool_use_id", ""), content=str(content.get("content", "")), ) - tool_message_list.append(tool_result) + self._add_cache_control_if_applicable(content, tool_result, model) + tool_message_list.append(tool_result) # type: ignore[arg-type] elif isinstance(content.get("content"), list): # Combine all content items into a single tool message # to avoid creating multiple tool_result blocks with the same ID @@ -256,7 +396,8 @@ class LiteLLMAnthropicMessagesAdapter: tool_call_id=content.get("tool_use_id", ""), content=c, ) - tool_message_list.append(tool_result) + self._add_cache_control_if_applicable(content, tool_result, model) + tool_message_list.append(tool_result) # type: ignore[arg-type] elif isinstance(c, dict): if c.get("type") == "text": tool_result = ChatCompletionToolMessage( @@ -266,7 +407,8 @@ class LiteLLMAnthropicMessagesAdapter: ), content=c.get("text", ""), ) - tool_message_list.append(tool_result) + self._add_cache_control_if_applicable(content, tool_result, model) + tool_message_list.append(tool_result) # type: ignore[arg-type] elif c.get("type") == "image": source = c.get("source", {}) openai_image_url = ( @@ -282,7 +424,8 @@ class LiteLLMAnthropicMessagesAdapter: ), content=openai_image_url, ) - tool_message_list.append(tool_result) + self._add_cache_control_if_applicable(content, tool_result, model) + tool_message_list.append(tool_result) # type: ignore[arg-type] else: # For multiple content items, combine into a single tool message # with list content to preserve all items while having one tool_use_id @@ -331,7 +474,8 @@ class LiteLLMAnthropicMessagesAdapter: tool_call_id=content.get("tool_use_id", ""), content=combined_content_parts, # type: ignore ) - tool_message_list.append(tool_result) + self._add_cache_control_if_applicable(content, tool_result, model) + tool_message_list.append(tool_result) # type: ignore[arg-type] if len(tool_message_list) > 0: new_messages.extend(tool_message_list) @@ -344,6 +488,8 @@ class LiteLLMAnthropicMessagesAdapter: ## ASSISTANT MESSAGE ## assistant_message_str: Optional[str] = None + assistant_content_list: List[Dict[str, Any]] = [] # For content blocks with cache_control + has_cache_control_in_text = False tool_calls: List[ChatCompletionAssistantToolCall] = [] thinking_blocks: List[ Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock] @@ -357,13 +503,19 @@ class LiteLLMAnthropicMessagesAdapter: assistant_message_str = str(content) elif isinstance(content, dict): if content.get("type") == "text": - if assistant_message_str is None: - assistant_message_str = content.get("text", "") - else: - assistant_message_str += content.get("text", "") + text_block: Dict[str, Any] = { + "type": "text", + "text": content.get("text", ""), + } + self._add_cache_control_if_applicable(content, text_block, model) + if "cache_control" in text_block: + has_cache_control_in_text = True + assistant_content_list.append(text_block) elif content.get("type") == "tool_use": + # Truncate tool name for OpenAI's 64-char limit + tool_name = truncate_tool_name(content.get("name", "")) function_chunk: ChatCompletionToolCallFunctionChunk = { - "name": content.get("name", ""), + "name": tool_name, "arguments": json.dumps(content.get("input", {})), } signature = ( @@ -384,13 +536,13 @@ class LiteLLMAnthropicMessagesAdapter: provider_specific_fields ) - tool_calls.append( - ChatCompletionAssistantToolCall( - id=content.get("id", ""), - type="function", - function=function_chunk, - ) + tool_call = ChatCompletionAssistantToolCall( + id=content.get("id", ""), + type="function", + function=function_chunk, ) + self._add_cache_control_if_applicable(content, tool_call, model) + tool_calls.append(tool_call) elif content.get("type") == "thinking": thinking_block = ChatCompletionThinkingBlock( type="thinking", @@ -411,18 +563,30 @@ class LiteLLMAnthropicMessagesAdapter: if ( assistant_message_str is not None + or len(assistant_content_list) > 0 or len(tool_calls) > 0 or len(thinking_blocks) > 0 ): + # Use list format if any text block has cache_control, otherwise use string + if has_cache_control_in_text and len(assistant_content_list) > 0: + assistant_content: Any = assistant_content_list + elif len(assistant_content_list) > 0 and not has_cache_control_in_text: + # Concatenate text blocks into string when no cache_control + assistant_content = "".join( + block.get("text", "") for block in assistant_content_list + ) + else: + assistant_content = assistant_message_str + assistant_message = ChatCompletionAssistantMessage( role="assistant", - content=assistant_message_str, + content=assistant_content, thinking_blocks=( thinking_blocks if len(thinking_blocks) > 0 else None ), ) if len(tool_calls) > 0: - assistant_message["tool_calls"] = tool_calls + assistant_message["tool_calls"] = tool_calls # type: ignore if len(thinking_blocks) > 0: assistant_message["thinking_blocks"] = thinking_blocks # type: ignore new_messages.append(assistant_message) @@ -520,8 +684,11 @@ class LiteLLMAnthropicMessagesAdapter: elif tool_choice["type"] == "auto": return "auto" elif tool_choice["type"] == "tool": + # Truncate tool name if it exceeds OpenAI's 64-char limit + original_name = tool_choice.get("name", "") + truncated_name = truncate_tool_name(original_name) tc_function_param = ChatCompletionToolChoiceFunctionParam( - name=tool_choice.get("name", "") + name=truncated_name ) return ChatCompletionToolChoiceObjectParam( type="function", function=tc_function_param @@ -532,13 +699,29 @@ class LiteLLMAnthropicMessagesAdapter: ) def translate_anthropic_tools_to_openai( - self, tools: List[AllAnthropicToolsValues] - ) -> List[ChatCompletionToolParam]: + self, tools: List[AllAnthropicToolsValues], model: Optional[str] = None + ) -> Tuple[List[ChatCompletionToolParam], Dict[str, str]]: + """ + Translate Anthropic tools to OpenAI format. + + Returns: + Tuple of (translated_tools, tool_name_mapping) + - tool_name_mapping maps truncated names back to original names + for tools that exceeded OpenAI's 64-char limit + """ new_tools: List[ChatCompletionToolParam] = [] - mapped_tool_params = ["name", "input_schema", "description"] + tool_name_mapping: Dict[str, str] = {} + mapped_tool_params = ["name", "input_schema", "description", "cache_control"] for tool in tools: + original_name = tool["name"] + truncated_name = truncate_tool_name(original_name) + + # Store mapping if name was truncated + if truncated_name != original_name: + tool_name_mapping[truncated_name] = original_name + function_chunk = ChatCompletionToolParamFunctionChunk( - name=tool["name"], + name=truncated_name, ) if "input_schema" in tool: function_chunk["parameters"] = tool["input_schema"] # type: ignore @@ -548,11 +731,11 @@ class LiteLLMAnthropicMessagesAdapter: for k, v in tool.items(): if k not in mapped_tool_params: # pass additional computer kwargs function_chunk.setdefault("parameters", {}).update({k: v}) - new_tools.append( - ChatCompletionToolParam(type="function", function=function_chunk) - ) + tool_param = ChatCompletionToolParam(type="function", function=function_chunk) + self._add_cache_control_if_applicable(tool, tool_param, model) + new_tools.append(tool_param) # type: ignore[arg-type] - return new_tools + return new_tools, tool_name_mapping # type: ignore[return-value] def translate_anthropic_output_format_to_openai( self, output_format: Any @@ -590,14 +773,55 @@ class LiteLLMAnthropicMessagesAdapter: }, } + def _add_system_message_to_messages( + self, + new_messages: List[AllMessageValues], + anthropic_message_request: AnthropicMessagesRequest, + ) -> None: + """Add system message to messages list if present in request.""" + if "system" not in anthropic_message_request: + return + system_content = anthropic_message_request["system"] + if not system_content: + return + # Handle system as string or array of content blocks + if isinstance(system_content, str): + new_messages.insert( + 0, + ChatCompletionSystemMessage(role="system", content=system_content), + ) + elif isinstance(system_content, list): + # Convert Anthropic system content blocks to OpenAI format + openai_system_content: List[Dict[str, Any]] = [] + model_name = anthropic_message_request.get("model", "") + for block in system_content: + if isinstance(block, dict) and block.get("type") == "text": + text_block: Dict[str, Any] = { + "type": "text", + "text": block.get("text", ""), + } + self._add_cache_control_if_applicable(block, text_block, model_name) + openai_system_content.append(text_block) + if openai_system_content: + new_messages.insert( + 0, + ChatCompletionSystemMessage(role="system", content=openai_system_content), # type: ignore + ) + def translate_anthropic_to_openai( self, anthropic_message_request: AnthropicMessagesRequest - ) -> ChatCompletionRequest: + ) -> Tuple[ChatCompletionRequest, Dict[str, str]]: """ This is used by the beta Anthropic Adapter, for translating anthropic `/v1/messages` requests to the openai format. + + Returns: + Tuple of (openai_request, tool_name_mapping) + - tool_name_mapping maps truncated tool names back to original names + for tools that exceeded OpenAI's 64-char limit """ # Debug: Processing Anthropic message request new_messages: List[AllMessageValues] = [] + tool_name_mapping: Dict[str, str] = {} ## CONVERT ANTHROPIC MESSAGES TO OPENAI messages_list: List[ @@ -618,13 +842,7 @@ class LiteLLMAnthropicMessagesAdapter: model=anthropic_message_request.get("model"), ) ## ADD SYSTEM MESSAGE TO MESSAGES - if "system" in anthropic_message_request: - system_content = anthropic_message_request["system"] - if system_content: - new_messages.insert( - 0, - ChatCompletionSystemMessage(role="system", content=system_content), - ) + self._add_system_message_to_messages(new_messages, anthropic_message_request) new_kwargs: ChatCompletionRequest = { "model": anthropic_message_request["model"], @@ -654,8 +872,9 @@ class LiteLLMAnthropicMessagesAdapter: if "tools" in anthropic_message_request: tools = anthropic_message_request["tools"] if tools: - new_kwargs["tools"] = self.translate_anthropic_tools_to_openai( - tools=cast(List[AllAnthropicToolsValues], tools) + new_kwargs["tools"], tool_name_mapping = self.translate_anthropic_tools_to_openai( + tools=cast(List[AllAnthropicToolsValues], tools), + model=new_kwargs.get("model"), ) ## CONVERT THINKING @@ -687,7 +906,7 @@ class LiteLLMAnthropicMessagesAdapter: if k not in translatable_params: # pass remaining params as is new_kwargs[k] = v # type: ignore - return new_kwargs + return new_kwargs, tool_name_mapping def _translate_anthropic_image_to_openai(self, image_source: dict) -> Optional[str]: """ @@ -716,22 +935,12 @@ class LiteLLMAnthropicMessagesAdapter: return None - def _translate_openai_content_to_anthropic(self, choices: List[Choices]) -> List[ - Union[ - AnthropicResponseContentBlockText, - AnthropicResponseContentBlockToolUse, - AnthropicResponseContentBlockThinking, - AnthropicResponseContentBlockRedactedThinking, - ] - ]: - new_content: List[ - Union[ - AnthropicResponseContentBlockText, - AnthropicResponseContentBlockToolUse, - AnthropicResponseContentBlockThinking, - AnthropicResponseContentBlockRedactedThinking, - ] - ] = [] + def _translate_openai_content_to_anthropic( + self, + choices: List[Choices], + tool_name_mapping: Optional[Dict[str, str]] = None, + ) -> List[Dict[str, Any]]: + new_content: List[Dict[str, Any]] = [] for choice in choices: # Handle thinking blocks first if ( @@ -755,7 +964,7 @@ class LiteLLMAnthropicMessagesAdapter: if signature_value is not None else None ), - ) + ).model_dump() ) elif thinking_block.get("type") == "redacted_thinking": data_value = thinking_block.get("data", "") @@ -763,15 +972,27 @@ class LiteLLMAnthropicMessagesAdapter: AnthropicResponseContentBlockRedactedThinking( type="redacted_thinking", data=str(data_value) if data_value is not None else "", - ) + ).model_dump() ) + # Handle reasoning_content when thinking_blocks is not present + elif ( + hasattr(choice.message, "reasoning_content") + and choice.message.reasoning_content + ): + new_content.append( + AnthropicResponseContentBlockThinking( + type="thinking", + thinking=str(choice.message.reasoning_content), + signature=None, + ).model_dump() + ) # Handle text content if choice.message.content is not None: new_content.append( AnthropicResponseContentBlockText( type="text", text=choice.message.content - ) + ).model_dump() ) # Handle tool calls (in parallel to text content) if ( @@ -786,13 +1007,21 @@ class LiteLLMAnthropicMessagesAdapter: if signature: provider_specific_fields["signature"] = signature + # Restore original tool name if it was truncated + truncated_name = tool_call.function.name or "" + original_name = ( + tool_name_mapping.get(truncated_name, truncated_name) + if tool_name_mapping + else truncated_name + ) + tool_use_block = AnthropicResponseContentBlockToolUse( type="tool_use", id=tool_call.id, - name=tool_call.function.name or "", + name=original_name, input=parse_tool_call_arguments( tool_call.function.arguments, - tool_name=tool_call.function.name, + tool_name=original_name, context="Anthropic pass-through adapter", ), ) @@ -801,7 +1030,7 @@ class LiteLLMAnthropicMessagesAdapter: tool_use_block.provider_specific_fields = ( provider_specific_fields ) - new_content.append(tool_use_block) + new_content.append(tool_use_block.model_dump()) return new_content @@ -817,10 +1046,24 @@ class LiteLLMAnthropicMessagesAdapter: return "end_turn" def translate_openai_response_to_anthropic( - self, response: ModelResponse + self, + response: ModelResponse, + tool_name_mapping: Optional[Dict[str, str]] = None, ) -> AnthropicMessagesResponse: + """ + Translate OpenAI response to Anthropic format. + + Args: + response: The OpenAI ModelResponse + tool_name_mapping: Optional mapping of truncated tool names to original names. + Used to restore original names for tools that exceeded + OpenAI's 64-char limit. + """ ## translate content block - anthropic_content = self._translate_openai_content_to_anthropic(choices=response.choices) # type: ignore + anthropic_content = self._translate_openai_content_to_anthropic( + choices=response.choices, # type: ignore + tool_name_mapping=tool_name_mapping, + ) ## extract finish reason anthropic_finish_reason = self._translate_openai_finish_reason_to_anthropic( openai_finish_reason=response.choices[0].finish_reason # type: ignore @@ -843,7 +1086,7 @@ class LiteLLMAnthropicMessagesAdapter: role="assistant", model=response.model or "unknown-model", stop_sequence=None, - usage=anthropic_usage, + usage=anthropic_usage, # type: ignore content=anthropic_content, # type: ignore stop_reason=anthropic_finish_reason, ) @@ -939,6 +1182,13 @@ class LiteLLMAnthropicMessagesAdapter: reasoning_content += thinking reasoning_signature += signature + # Handle reasoning_content when thinking_blocks is not present + # This handles providers like OpenRouter that return reasoning_content + elif isinstance(choice, StreamingChoices) and hasattr( + choice.delta, "reasoning_content" + ): + if choice.delta.reasoning_content is not None: + reasoning_content += choice.delta.reasoning_content if reasoning_content and reasoning_signature: raise ValueError( @@ -992,7 +1242,7 @@ class LiteLLMAnthropicMessagesAdapter: else: usage_delta = UsageDelta(input_tokens=0, output_tokens=0) return MessageBlockDelta( - type="message_delta", delta=delta, usage=usage_delta + type="message_delta", delta=delta, usage=usage_delta # type: ignore ) ( type_of_content, diff --git a/litellm/llms/azure/batches/handler.py b/litellm/llms/azure/batches/handler.py index 3996cb808e4..aaefe801687 100644 --- a/litellm/llms/azure/batches/handler.py +++ b/litellm/llms/azure/batches/handler.py @@ -5,12 +5,10 @@ Azure Batches API Handler from typing import Any, Coroutine, Optional, Union, cast import httpx - from openai import AsyncOpenAI, OpenAI from litellm.llms.azure.azure import AsyncAzureOpenAI, AzureOpenAI from litellm.types.llms.openai import ( - Batch, CancelBatchRequest, CreateBatchRequest, RetrieveBatchRequest, @@ -130,9 +128,9 @@ class AzureBatchesAPI(BaseAzureLLM): self, cancel_batch_data: CancelBatchRequest, client: Union[AsyncAzureOpenAI, AsyncOpenAI], - ) -> Batch: + ) -> LiteLLMBatch: response = await client.batches.cancel(**cancel_batch_data) - return response + return LiteLLMBatch(**response.model_dump()) def cancel_batch( self, @@ -160,8 +158,23 @@ class AzureBatchesAPI(BaseAzureLLM): raise ValueError( "OpenAI client is not initialized. Make sure api_key is passed or OPENAI_API_KEY is set in the environment." ) + + if _is_async is True: + if not isinstance(azure_client, (AsyncAzureOpenAI, AsyncOpenAI)): + raise ValueError( + "Azure client is not an instance of AsyncAzureOpenAI or AsyncOpenAI. Make sure you passed an async client." + ) + return self.acancel_batch( # type: ignore + cancel_batch_data=cancel_batch_data, client=azure_client + ) + + # At this point, azure_client is guaranteed to be a sync client + if not isinstance(azure_client, (AzureOpenAI, OpenAI)): + raise ValueError( + "Azure client is not an instance of AzureOpenAI or OpenAI. Make sure you passed a sync client." + ) response = azure_client.batches.cancel(**cancel_batch_data) - return response + return LiteLLMBatch(**response.model_dump()) async def alist_batches( self, diff --git a/litellm/llms/azure/chat/gpt_5_transformation.py b/litellm/llms/azure/chat/gpt_5_transformation.py index 506b7fdfe5e..eeb55911ecf 100644 --- a/litellm/llms/azure/chat/gpt_5_transformation.py +++ b/litellm/llms/azure/chat/gpt_5_transformation.py @@ -22,7 +22,8 @@ class AzureOpenAIGPT5Config(AzureOpenAIConfig, OpenAIGPT5Config): Accepts both explicit gpt-5 model names and the ``gpt5_series/`` prefix used for manual routing. """ - return "gpt-5" in model or "gpt5_series" in model + # gpt-5-chat* is a chat model and shouldn't go through GPT-5 reasoning restrictions. + return ("gpt-5" in model and "gpt-5-chat" not in model) or "gpt5_series" in model def get_supported_openai_params(self, model: str) -> List[str]: """Get supported parameters for Azure OpenAI GPT-5 models. @@ -37,6 +38,11 @@ class AzureOpenAIGPT5Config(AzureOpenAIConfig, OpenAIGPT5Config): """ params = OpenAIGPT5Config.get_supported_openai_params(self, model=model) + # Azure supports tool_choice for GPT-5 deployments, but the base GPT-5 config + # can drop it when the deployment name isn't in the OpenAI model registry. + if "tool_choice" not in params: + params.append("tool_choice") + # Only gpt-5.2 has been verified to support logprobs on Azure if self.is_model_gpt_5_2_model(model): azure_supported_params = ["logprobs", "top_logprobs"] diff --git a/litellm/llms/azure/cost_calculation.py b/litellm/llms/azure/cost_calculation.py index 96c58d95ff2..5b411095ea1 100644 --- a/litellm/llms/azure/cost_calculation.py +++ b/litellm/llms/azure/cost_calculation.py @@ -1,11 +1,12 @@ """ Helper util for handling azure openai-specific cost calculation -- e.g.: prompt caching +- e.g.: prompt caching, audio tokens """ from typing import Optional, Tuple from litellm._logging import verbose_logger +from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_token from litellm.types.utils import Usage from litellm.utils import get_model_info @@ -18,34 +19,15 @@ def cost_per_token( Input: - model: str, the model name without provider prefix - - usage: LiteLLM Usage block, containing anthropic caching information + - usage: LiteLLM Usage block, containing caching and audio token information Returns: Tuple[float, float] - prompt_cost_in_usd, completion_cost_in_usd """ ## GET MODEL INFO model_info = get_model_info(model=model, custom_llm_provider="azure") - cached_tokens: Optional[int] = None - ## CALCULATE INPUT COST - non_cached_text_tokens = usage.prompt_tokens - if usage.prompt_tokens_details and usage.prompt_tokens_details.cached_tokens: - cached_tokens = usage.prompt_tokens_details.cached_tokens - non_cached_text_tokens = non_cached_text_tokens - cached_tokens - prompt_cost: float = non_cached_text_tokens * model_info["input_cost_per_token"] - ## CALCULATE OUTPUT COST - completion_cost: float = ( - usage["completion_tokens"] * model_info["output_cost_per_token"] - ) - - ## Prompt Caching cost calculation - if model_info.get("cache_read_input_token_cost") is not None and cached_tokens: - # Note: We read ._cache_read_input_tokens from the Usage - since cost_calculator.py standardizes the cache read tokens on usage._cache_read_input_tokens - prompt_cost += cached_tokens * ( - model_info.get("cache_read_input_token_cost", 0) or 0 - ) - - ## Speech / Audio cost calculation + ## Speech / Audio cost calculation (cost per second for TTS models) if ( "output_cost_per_second" in model_info and model_info["output_cost_per_second"] is not None @@ -55,7 +37,14 @@ def cost_per_token( f"For model={model} - output_cost_per_second: {model_info.get('output_cost_per_second')}; response time: {response_time_ms}" ) ## COST PER SECOND ## - prompt_cost = 0 + prompt_cost = 0.0 completion_cost = model_info["output_cost_per_second"] * response_time_ms / 1000 + return prompt_cost, completion_cost - return prompt_cost, completion_cost + ## Use generic cost calculator for all other cases + ## This properly handles: text tokens, audio tokens, cached tokens, reasoning tokens, etc. + return generic_cost_per_token( + model=model, + usage=usage, + custom_llm_provider="azure", + ) diff --git a/litellm/llms/azure_ai/anthropic/count_tokens/transformation.py b/litellm/llms/azure_ai/anthropic/count_tokens/transformation.py index e284595cc8a..09b83b7c971 100644 --- a/litellm/llms/azure_ai/anthropic/count_tokens/transformation.py +++ b/litellm/llms/azure_ai/anthropic/count_tokens/transformation.py @@ -30,30 +30,32 @@ class AzureAIAnthropicCountTokensConfig(AnthropicCountTokensConfig): """ Get the required headers for the Azure AI Anthropic CountTokens API. - Uses Azure authentication (api-key header) instead of Anthropic's x-api-key. + Azure AI Anthropic uses Anthropic's native API format, which requires the + x-api-key header for authentication (in addition to Azure's api-key header). Args: api_key: The Azure AI API key litellm_params: Optional LiteLLM parameters for additional auth config Returns: - Dictionary of required headers with Azure authentication + Dictionary of required headers with both x-api-key and Azure authentication """ - # Start with base headers + # Start with base headers including x-api-key for Anthropic API compatibility headers = { "Content-Type": "application/json", "anthropic-version": "2023-06-01", "anthropic-beta": ANTHROPIC_TOKEN_COUNTING_BETA_VERSION, + "x-api-key": api_key, # Azure AI Anthropic requires this header } - # Use Azure authentication + # Also set up Azure auth headers for flexibility litellm_params = litellm_params or {} if "api_key" not in litellm_params: litellm_params["api_key"] = api_key litellm_params_obj = GenericLiteLLMParams(**litellm_params) - # Get Azure auth headers + # Get Azure auth headers (api-key or Authorization) azure_headers = BaseAzureLLM._base_validate_azure_environment( headers={}, litellm_params=litellm_params_obj ) @@ -68,7 +70,7 @@ class AzureAIAnthropicCountTokensConfig(AnthropicCountTokensConfig): Get the Azure AI Anthropic CountTokens API endpoint. Args: - api_base: The Azure AI API base URL + api_base: The Azure AI API base URL (e.g., https://my-resource.services.ai.azure.com or https://my-resource.services.ai.azure.com/anthropic) diff --git a/litellm/llms/azure_ai/azure_model_router/__init__.py b/litellm/llms/azure_ai/azure_model_router/__init__.py new file mode 100644 index 00000000000..0165d60b643 --- /dev/null +++ b/litellm/llms/azure_ai/azure_model_router/__init__.py @@ -0,0 +1,4 @@ +"""Azure AI Foundry Model Router support.""" +from .transformation import AzureModelRouterConfig + +__all__ = ["AzureModelRouterConfig"] diff --git a/litellm/llms/azure_ai/azure_model_router/transformation.py b/litellm/llms/azure_ai/azure_model_router/transformation.py new file mode 100644 index 00000000000..3d6dc53c515 --- /dev/null +++ b/litellm/llms/azure_ai/azure_model_router/transformation.py @@ -0,0 +1,125 @@ +""" +Transformation for Azure AI Foundry Model Router. + +The Model Router is a special Azure AI deployment that automatically routes requests +to the best available model. It has specific cost tracking requirements. +""" +from typing import Any, List, Optional + +from httpx import Response + +from litellm.llms.azure_ai.chat.transformation import AzureAIStudioConfig +from litellm.llms.base_llm.chat.transformation import LiteLLMLoggingObj +from litellm.types.llms.openai import AllMessageValues +from litellm.types.utils import ModelResponse + + +class AzureModelRouterConfig(AzureAIStudioConfig): + """ + Configuration for Azure AI Foundry Model Router. + + Handles: + - Stripping model_router prefix before sending to Azure API + - Preserving full model path in responses for cost tracking + - Calculating flat infrastructure costs for Model Router + """ + + def transform_request( + self, + model: str, + messages: List[AllMessageValues], + optional_params: dict, + litellm_params: dict, + headers: dict, + ) -> dict: + """ + Transform request for Model Router. + + Strips the model_router/ prefix so only the deployment name is sent to Azure. + Example: model_router/azure-model-router -> azure-model-router + """ + from litellm.llms.azure_ai.common_utils import AzureFoundryModelInfo + + # Get base model name (strips routing prefixes like model_router/) + base_model: str = AzureFoundryModelInfo.get_base_model(model) + + return super().transform_request( + base_model, messages, optional_params, litellm_params, headers + ) + + def transform_response( + self, + model: str, + raw_response: Response, + model_response: ModelResponse, + logging_obj: LiteLLMLoggingObj, + request_data: dict, + messages: List[AllMessageValues], + optional_params: dict, + litellm_params: dict, + encoding: Any, + api_key: Optional[str] = None, + json_mode: Optional[bool] = None, + ) -> ModelResponse: + """ + Transform response for Model Router. + + Preserves the original model path (including model_router/ prefix) in the response + for proper cost tracking and logging. + """ + from litellm.llms.azure_ai.common_utils import AzureFoundryModelInfo + + # Preserve the original model from litellm_params (includes routing prefixes like model_router/) + # This ensures cost tracking and logging use the full model path + original_model: str = litellm_params.get("model") or model + if not original_model.startswith("azure_ai/"): + # Add provider prefix if not already present + model_response.model = f"azure_ai/{original_model}" + else: + model_response.model = original_model + + # Get base model for the parent call (strips routing prefixes for API compatibility) + base_model: str = AzureFoundryModelInfo.get_base_model(model) + + return super().transform_response( + model=base_model, + raw_response=raw_response, + model_response=model_response, + logging_obj=logging_obj, + request_data=request_data, + messages=messages, + optional_params=optional_params, + litellm_params=litellm_params, + encoding=encoding, + api_key=api_key, + json_mode=json_mode, + ) + + def calculate_additional_costs( + self, model: str, prompt_tokens: int, completion_tokens: int + ) -> Optional[dict]: + """ + Calculate additional costs for Azure Model Router. + + Adds a flat infrastructure cost of $0.14 per M input tokens for using the Model Router. + + Args: + model: The model name (should be a model router model) + prompt_tokens: Number of prompt tokens + completion_tokens: Number of completion tokens + + Returns: + Dictionary with additional costs, or None if not applicable. + """ + from litellm.llms.azure_ai.cost_calculator import ( + calculate_azure_model_router_flat_cost, + ) + + flat_cost = calculate_azure_model_router_flat_cost( + model=model, prompt_tokens=prompt_tokens + ) + + if flat_cost > 0: + return {"Azure Model Router Flat Cost": flat_cost} + + return None diff --git a/litellm/llms/azure_ai/common_utils.py b/litellm/llms/azure_ai/common_utils.py index 01a3f5766c6..47d397d6e98 100644 --- a/litellm/llms/azure_ai/common_utils.py +++ b/litellm/llms/azure_ai/common_utils.py @@ -13,14 +13,28 @@ class AzureFoundryModelInfo(BaseLLMModelInfo): self._model = model @staticmethod - def get_azure_ai_route(model: str) -> Literal["agents", "default"]: + def get_azure_ai_route(model: str) -> Literal["agents", "model_router", "default"]: """ Get the Azure AI route for the given model. Similar to BedrockModelInfo.get_bedrock_route(). + + Supported routes: + - agents: azure_ai/agents/ + - model_router: azure_ai/model_router/ or models with "model-router"/"model_router" in name + - default: standard models """ if "agents/" in model: return "agents" + # Detect model router by prefix (model_router/) or by name containing "model-router"/"model_router" + model_lower = model.lower() + if ( + "model_router/" in model_lower + or "model-router/" in model_lower + or "model-router" in model_lower + or "model_router" in model_lower + ): + return "model_router" return "default" @staticmethod @@ -75,8 +89,73 @@ class AzureFoundryModelInfo(BaseLLMModelInfo): ######################################################### @staticmethod - def get_base_model(model: str) -> Optional[str]: - raise NotImplementedError("Azure Foundry does not support base model") + def strip_model_router_prefix(model: str) -> str: + """ + Strip the model_router prefix from model name. + + Examples: + - "model_router/gpt-4o" -> "gpt-4o" + - "model-router/gpt-4o" -> "gpt-4o" + - "gpt-4o" -> "gpt-4o" + + Args: + model: Model name potentially with model_router prefix + + Returns: + Model name without the prefix + """ + if "model_router/" in model: + return model.split("model_router/", 1)[1] + if "model-router/" in model: + return model.split("model-router/", 1)[1] + return model + + @staticmethod + def get_base_model(model: str) -> str: + """ + Get the base model name, stripping any Azure AI routing prefixes. + + Args: + model: Model name potentially with routing prefixes + + Returns: + Base model name + """ + # Strip model_router prefix if present + model = AzureFoundryModelInfo.strip_model_router_prefix(model) + return model + + @staticmethod + def get_azure_ai_config_for_model(model: str): + """ + Get the appropriate Azure AI config class for the given model. + + Routes to specialized configs based on model type: + - Model Router: AzureModelRouterConfig + - Claude models: AzureAnthropicConfig + - Default: AzureAIStudioConfig + + Args: + model: The model name + + Returns: + The appropriate config instance + """ + azure_ai_route = AzureFoundryModelInfo.get_azure_ai_route(model) + + if azure_ai_route == "model_router": + from litellm.llms.azure_ai.azure_model_router.transformation import ( + AzureModelRouterConfig, + ) + return AzureModelRouterConfig() + elif "claude" in model.lower(): + from litellm.llms.azure_ai.anthropic.transformation import ( + AzureAnthropicConfig, + ) + return AzureAnthropicConfig() + else: + from litellm.llms.azure_ai.chat.transformation import AzureAIStudioConfig + return AzureAIStudioConfig() def validate_environment( self, diff --git a/litellm/llms/azure_ai/cost_calculator.py b/litellm/llms/azure_ai/cost_calculator.py new file mode 100644 index 00000000000..999f94da182 --- /dev/null +++ b/litellm/llms/azure_ai/cost_calculator.py @@ -0,0 +1,121 @@ +""" +Azure AI cost calculation helper. +Handles Azure AI Foundry Model Router flat cost and other Azure AI specific pricing. +""" + +from typing import Optional, Tuple + +from litellm._logging import verbose_logger +from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_token +from litellm.types.utils import Usage +from litellm.utils import get_model_info + + +def _is_azure_model_router(model: str) -> bool: + """ + Check if the model is Azure AI Foundry Model Router. + + Detects patterns like: + - "azure-model-router" + - "model-router" + - "model_router/" + - "model-router/" + + Args: + model: The model name + + Returns: + bool: True if this is a model router model + """ + model_lower = model.lower() + return ( + "model-router" in model_lower + or "model_router" in model_lower + or model_lower == "azure-model-router" + ) + + +def calculate_azure_model_router_flat_cost(model: str, prompt_tokens: int) -> float: + """ + Calculate the flat cost for Azure AI Foundry Model Router. + + Args: + model: The model name (should be a model router model) + prompt_tokens: Number of prompt tokens + + Returns: + float: The flat cost in USD, or 0.0 if not applicable + """ + if not _is_azure_model_router(model): + return 0.0 + + # Get the model router pricing from model_prices_and_context_window.json + # Use "model_router" as the key (without actual model name suffix) + model_info = get_model_info(model="model_router", custom_llm_provider="azure_ai") + router_flat_cost_per_token = model_info.get("input_cost_per_token", 0) + + if router_flat_cost_per_token > 0: + return prompt_tokens * router_flat_cost_per_token + + return 0.0 + + +def cost_per_token( + model: str, usage: Usage, response_time_ms: Optional[float] = 0.0 +) -> Tuple[float, float]: + """ + Calculate the cost per token for Azure AI models. + + For Azure AI Foundry Model Router: + - Adds a flat cost of $0.14 per million input tokens (from model_prices_and_context_window.json) + - Plus the cost of the actual model used (handled by generic_cost_per_token) + + Args: + model: str, the model name without provider prefix + usage: LiteLLM Usage block + response_time_ms: Optional response time in milliseconds + + Returns: + Tuple[float, float] - prompt_cost_in_usd, completion_cost_in_usd + + Raises: + ValueError: If the model is not found in the cost map and cost cannot be calculated + (except for Model Router models where we return just the routing flat cost) + """ + prompt_cost = 0.0 + completion_cost = 0.0 + + # Calculate base cost using generic cost calculator + # This may raise an exception if the model is not in the cost map + try: + prompt_cost, completion_cost = generic_cost_per_token( + model=model, + usage=usage, + custom_llm_provider="azure_ai", + ) + except Exception as e: + # For Model Router, the model name (e.g., "azure-model-router") may not be in the cost map + # because it's a routing service, not an actual model. In this case, we continue + # to calculate just the routing flat cost. + if not _is_azure_model_router(model): + # Re-raise for non-router models - they should have pricing defined + raise + verbose_logger.debug( + f"Azure AI Model Router: model '{model}' not in cost map, calculating routing flat cost only. Error: {e}" + ) + + # Add flat cost for Azure Model Router + # The flat cost is defined in model_prices_and_context_window.json for azure_ai/model_router + if _is_azure_model_router(model): + router_flat_cost = calculate_azure_model_router_flat_cost(model, usage.prompt_tokens) + + if router_flat_cost > 0: + verbose_logger.debug( + f"Azure AI Model Router flat cost: ${router_flat_cost:.6f} " + f"({usage.prompt_tokens} tokens Ɨ ${router_flat_cost / usage.prompt_tokens:.9f}/token)" + ) + + # Add flat cost to prompt cost + prompt_cost += router_flat_cost + + return prompt_cost, completion_cost diff --git a/litellm/llms/azure_ai/rerank/transformation.py b/litellm/llms/azure_ai/rerank/transformation.py index a47b6082c37..f577a42ed58 100644 --- a/litellm/llms/azure_ai/rerank/transformation.py +++ b/litellm/llms/azure_ai/rerank/transformation.py @@ -11,6 +11,7 @@ from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLogging from litellm.llms.cohere.rerank.transformation import CohereRerankConfig from litellm.secret_managers.main import get_secret_str from litellm.types.utils import RerankResponse +from litellm.utils import _add_path_to_api_base class AzureAIRerankConfig(CohereRerankConfig): @@ -28,9 +29,34 @@ class AzureAIRerankConfig(CohereRerankConfig): raise ValueError( "Azure AI API Base is required. api_base=None. Set in call or via `AZURE_AI_API_BASE` env var." ) - if not api_base.endswith("/v1/rerank"): - api_base = f"{api_base}/v1/rerank" - return api_base + original_url = httpx.URL(api_base) + if not original_url.is_absolute_url: + raise ValueError( + "Azure AI API Base must be an absolute URL including scheme (e.g. " + "'https://.services.ai.azure.com'). " + f"Got api_base={api_base!r}." + ) + normalized_path = original_url.path.rstrip("/") + + # Allow callers to pass either full v1/v2 rerank endpoints: + # - https://.services.ai.azure.com/v1/rerank + # - https://.services.ai.azure.com/providers/cohere/v2/rerank + if normalized_path.endswith("/v1/rerank") or normalized_path.endswith("/v2/rerank"): + return str(original_url.copy_with(path=normalized_path or "/")) + + # If callers pass just the version path (e.g. ".../v2" or ".../providers/cohere/v2"), append "/rerank" + if ( + normalized_path.endswith("/v1") + or normalized_path.endswith("/v2") + or normalized_path.endswith("/providers/cohere/v2") + ): + return _add_path_to_api_base( + api_base=str(original_url.copy_with(path=normalized_path or "/")), + ending_path="/rerank", + ) + + # Backwards compatible default: Azure AI rerank was originally exposed under /v1/rerank + return _add_path_to_api_base(api_base=api_base, ending_path="/v1/rerank") def validate_environment( self, diff --git a/litellm/llms/base_llm/chat/transformation.py b/litellm/llms/base_llm/chat/transformation.py index 41a1797cebe..ac209904e6e 100644 --- a/litellm/llms/base_llm/chat/transformation.py +++ b/litellm/llms/base_llm/chat/transformation.py @@ -437,3 +437,23 @@ class BaseConfig(ABC): By default, this is true for almost all providers. """ return True + + def calculate_additional_costs( + self, model: str, prompt_tokens: int, completion_tokens: int + ) -> Optional[dict]: + """ + Calculate any additional costs beyond standard token costs. + + This is used for provider-specific infrastructure costs, routing fees, etc. + + Args: + model: The model name + prompt_tokens: Number of prompt tokens + completion_tokens: Number of completion tokens + + Returns: + Optional dictionary with cost names and amounts, e.g.: + {"Infrastructure Fee": 0.001, "Routing Cost": 0.0005} + Returns None if no additional costs apply. + """ + return None diff --git a/litellm/llms/base_llm/vector_store/transformation.py b/litellm/llms/base_llm/vector_store/transformation.py index 89f2094d5df..935fd53c199 100644 --- a/litellm/llms/base_llm/vector_store/transformation.py +++ b/litellm/llms/base_llm/vector_store/transformation.py @@ -5,8 +5,8 @@ import httpx from litellm.types.router import GenericLiteLLMParams from litellm.types.vector_stores import ( - BaseVectorStoreAuthCredentials, VECTOR_STORE_OPENAI_PARAMS, + BaseVectorStoreAuthCredentials, VectorStoreCreateOptionalRequestParams, VectorStoreCreateResponse, VectorStoreIndexEndpoints, @@ -64,6 +64,30 @@ class BaseVectorStoreConfig: pass + async def atransform_search_vector_store_request( + self, + vector_store_id: str, + query: Union[str, List[str]], + vector_store_search_optional_params: VectorStoreSearchOptionalRequestParams, + api_base: str, + litellm_logging_obj: LiteLLMLoggingObj, + litellm_params: dict, + ) -> Tuple[str, Dict]: + """ + Optional async version of transform_search_vector_store_request. + If not implemented, the handler will fall back to the sync version. + Providers that need to make async calls (e.g., generating embeddings) should override this. + """ + # Default implementation: call the sync version + return self.transform_search_vector_store_request( + vector_store_id=vector_store_id, + query=query, + vector_store_search_optional_params=vector_store_search_optional_params, + api_base=api_base, + litellm_logging_obj=litellm_logging_obj, + litellm_params=litellm_params, + ) + @abstractmethod def transform_search_vector_store_response( self, response: httpx.Response, litellm_logging_obj: LiteLLMLoggingObj diff --git a/litellm/llms/bedrock/base_aws_llm.py b/litellm/llms/bedrock/base_aws_llm.py index 642d15fe3ed..1de1c40c438 100644 --- a/litellm/llms/bedrock/base_aws_llm.py +++ b/litellm/llms/bedrock/base_aws_llm.py @@ -1163,7 +1163,7 @@ class BaseAWSLLM: def _sign_request( self, - service_name: Literal["bedrock", "sagemaker", "bedrock-agentcore"], + service_name: Literal["bedrock", "sagemaker", "bedrock-agentcore", "s3vectors"], headers: dict, optional_params: dict, request_data: dict, diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index cb26a22edfa..f6d7e128580 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -76,6 +76,13 @@ BEDROCK_COMPUTER_USE_TOOLS = [ "text_editor_", ] +# Beta header patterns that are not supported by Bedrock Converse API +# These will be filtered out to prevent errors +UNSUPPORTED_BEDROCK_CONVERSE_BETA_PATTERNS = [ + "advanced-tool-use", # Bedrock Converse doesn't support advanced-tool-use beta headers + "prompt-caching", # Prompt caching not supported in Converse API +] + class AmazonConverseConfig(BaseConfig): """ @@ -298,6 +305,39 @@ class AmazonConverseConfig(BaseConfig): # Check if the model is specifically Nova Lite 2 return "nova-2-lite" in model_without_region + def _map_web_search_options( + self, + web_search_options: dict, + model: str + ) -> Optional[BedrockToolBlock]: + """ + Map web_search_options to Nova grounding systemTool. + + Nova grounding (web search) is only supported on Amazon Nova models. + Returns None for non-Nova models. + + Args: + web_search_options: The web_search_options dict from the request + model: The model identifier string + + Returns: + BedrockToolBlock with systemTool for Nova models, None otherwise + + Reference: https://docs.aws.amazon.com/nova/latest/userguide/grounding.html + """ + # Only Nova models support nova_grounding + # Model strings can be like: "amazon.nova-pro-v1:0", "us.amazon.nova-pro-v1:0", etc. + if "nova" not in model.lower(): + verbose_logger.debug( + f"web_search_options passed but model {model} is not a Nova model. " + "Nova grounding is only supported on Amazon Nova models." + ) + return None + + # Nova doesn't support search_context_size or user_location params + # (unlike Anthropic), so we just enable grounding with no options + return BedrockToolBlock(systemTool={"name": "nova_grounding"}) + def _transform_reasoning_effort_to_reasoning_config( self, reasoning_effort: str ) -> dict: @@ -438,6 +478,10 @@ class AmazonConverseConfig(BaseConfig): ): supported_params.append("tools") + # Nova models support web_search_options (mapped to nova_grounding systemTool) + if base_model.startswith("amazon.nova"): + supported_params.append("web_search_options") + if litellm.utils.supports_tool_choice( model=model, custom_llm_provider=self.custom_llm_provider ) or litellm.utils.supports_tool_choice( @@ -573,6 +617,37 @@ class AmazonConverseConfig(BaseConfig): return transformed_tools + def _filter_unsupported_beta_headers_for_bedrock( + self, model: str, beta_list: list + ) -> list: + """ + Remove beta headers that are not supported on Bedrock Converse API for the given model. + + Extended thinking beta headers are only supported on specific Claude 4+ models. + Some beta headers are universally unsupported on Bedrock Converse API. + + Args: + model: The model name + beta_list: The list of beta headers to filter + + Returns: + Filtered list of beta headers + """ + filtered_betas = [] + + # 1. Filter out beta headers that are universally unsupported on Bedrock Converse + for beta in beta_list: + should_keep = True + for unsupported_pattern in UNSUPPORTED_BEDROCK_CONVERSE_BETA_PATTERNS: + if unsupported_pattern in beta.lower(): + should_keep = False + break + + if should_keep: + filtered_betas.append(beta) + + return filtered_betas + def _separate_computer_use_tools( self, tools: List[OpenAIChatCompletionToolParam], model: str ) -> Tuple[ @@ -730,6 +805,15 @@ class AmazonConverseConfig(BaseConfig): if bedrock_tier in ("default", "flex", "priority"): optional_params["serviceTier"] = {"type": bedrock_tier} + if param == "web_search_options" and isinstance(value, dict): + # Note: we use `isinstance(value, dict)` instead of `value and isinstance(value, dict)` + # because empty dict {} is falsy but is a valid way to enable Nova grounding + grounding_tool = self._map_web_search_options(value, model) + if grounding_tool is not None: + optional_params = self._add_tools_to_optional_params( + optional_params=optional_params, tools=[grounding_tool] + ) + # Only update thinking tokens for non-GPT-OSS models and non-Nova-Lite-2 models # Nova Lite 2 handles token budgeting differently through reasoningConfig if "gpt-oss" not in model and not self._is_nova_lite_2_model(model): @@ -997,10 +1081,16 @@ class AmazonConverseConfig(BaseConfig): user_betas = get_anthropic_beta_from_headers(headers) anthropic_beta_list.extend(user_betas) - # Filter out tool search tools - Bedrock Converse API doesn't support them + # Separate pre-formatted Bedrock tools (e.g. systemTool from web_search_options) + # from OpenAI-format tools that need transformation via _bedrock_tools_pt filtered_tools = [] + pre_formatted_tools: List[ToolBlock] = [] if original_tools: for tool in original_tools: + # Already-formatted Bedrock tools (e.g. systemTool for Nova grounding) + if "systemTool" in tool: + pre_formatted_tools.append(tool) + continue tool_type = tool.get("type", "") if tool_type in ( "tool_search_tool_regex_20251119", @@ -1032,6 +1122,9 @@ class AmazonConverseConfig(BaseConfig): # No computer use tools, process all tools as regular tools bedrock_tools = _bedrock_tools_pt(filtered_tools) + # Append pre-formatted tools (systemTool etc.) after transformation + bedrock_tools.extend(pre_formatted_tools) + # Set anthropic_beta in additional_request_params if we have any beta features # ONLY apply to Anthropic/Claude models - other models (e.g., Qwen, Llama) don't support this field # and will error with "unknown variant anthropic_beta" if included @@ -1044,7 +1137,14 @@ class AmazonConverseConfig(BaseConfig): if beta not in seen: unique_betas.append(beta) seen.add(beta) - additional_request_params["anthropic_beta"] = unique_betas + + # Filter out unsupported beta headers for Bedrock Converse API + filtered_betas = self._filter_unsupported_beta_headers_for_bedrock( + model=model, + beta_list=unique_betas, + ) + + additional_request_params["anthropic_beta"] = filtered_betas return bedrock_tools, anthropic_beta_list @@ -1388,20 +1488,23 @@ class AmazonConverseConfig(BaseConfig): str, List[ChatCompletionToolCallChunk], Optional[List[BedrockConverseReasoningContentBlock]], + Optional[List[CitationsContentBlock]], ]: """ - Translate the message content to a string and a list of tool calls and reasoning content blocks + Translate the message content to a string and a list of tool calls, reasoning content blocks, and citations. Returns: content_str: str tools: List[ChatCompletionToolCallChunk] reasoningContentBlocks: Optional[List[BedrockConverseReasoningContentBlock]] + citationsContentBlocks: Optional[List[CitationsContentBlock]] - Citations from Nova grounding """ content_str = "" tools: List[ChatCompletionToolCallChunk] = [] reasoningContentBlocks: Optional[List[BedrockConverseReasoningContentBlock]] = ( None ) + citationsContentBlocks: Optional[List[CitationsContentBlock]] = None for idx, content in enumerate(content_blocks): """ - Content is either a tool response or text @@ -1446,10 +1549,15 @@ class AmazonConverseConfig(BaseConfig): if reasoningContentBlocks is None: reasoningContentBlocks = [] reasoningContentBlocks.append(content["reasoningContent"]) + # Handle Nova grounding citations content + if "citationsContent" in content: + if citationsContentBlocks is None: + citationsContentBlocks = [] + citationsContentBlocks.append(content["citationsContent"]) - return content_str, tools, reasoningContentBlocks + return content_str, tools, reasoningContentBlocks, citationsContentBlocks - def _transform_response( + def _transform_response( # noqa: PLR0915 self, model: str, response: httpx.Response, @@ -1525,18 +1633,27 @@ class AmazonConverseConfig(BaseConfig): reasoningContentBlocks: Optional[List[BedrockConverseReasoningContentBlock]] = ( None ) + citationsContentBlocks: Optional[List[CitationsContentBlock]] = None if message is not None: ( content_str, tools, reasoningContentBlocks, + citationsContentBlocks, ) = self._translate_message_content(message["content"]) + # Initialize provider_specific_fields if we have any special content blocks + provider_specific_fields: dict = {} + if reasoningContentBlocks is not None: + provider_specific_fields["reasoningContentBlocks"] = reasoningContentBlocks + if citationsContentBlocks is not None: + provider_specific_fields["citationsContent"] = citationsContentBlocks + + if provider_specific_fields: + chat_completion_message["provider_specific_fields"] = provider_specific_fields + if reasoningContentBlocks is not None: - chat_completion_message["provider_specific_fields"] = { - "reasoningContentBlocks": reasoningContentBlocks, - } chat_completion_message["reasoning_content"] = ( self._transform_reasoning_content(reasoningContentBlocks) ) diff --git a/litellm/llms/bedrock/chat/invoke_handler.py b/litellm/llms/bedrock/chat/invoke_handler.py index 17474fa022b..1c58a11eebe 100644 --- a/litellm/llms/bedrock/chat/invoke_handler.py +++ b/litellm/llms/bedrock/chat/invoke_handler.py @@ -1476,6 +1476,11 @@ class AWSEventStreamDecoder: reasoning_content = ( "" # set to non-empty string to ensure consistency with Anthropic ) + elif "citationsContent" in delta_obj: + # Handle Nova grounding citations in streaming responses + provider_specific_fields = { + "citationsContent": delta_obj["citationsContent"], + } return ( text, tool_use, diff --git a/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py index 53e08229799..c936b2cd23c 100644 --- a/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py @@ -53,13 +53,26 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig): model: str, drop_params: bool, ) -> dict: - return AnthropicConfig.map_openai_params( + # Force tool-based structured outputs for Bedrock Invoke + # (similar to VertexAI fix in #19201) + # Bedrock Invoke doesn't support output_format parameter + original_model = model + if "response_format" in non_default_params: + # Use a model name that forces tool-based approach + model = "claude-3-sonnet-20240229" + + optional_params = AnthropicConfig.map_openai_params( self, non_default_params, optional_params, model, drop_params, ) + + # Restore original model name + model = original_model + + return optional_params def transform_request( @@ -90,6 +103,8 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig): _anthropic_request.pop("model", None) _anthropic_request.pop("stream", None) + # Bedrock Invoke doesn't support output_format parameter + _anthropic_request.pop("output_format", None) if "anthropic_version" not in _anthropic_request: _anthropic_request["anthropic_version"] = self.anthropic_version @@ -117,6 +132,26 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig): if "opus-4" in model.lower() or "opus_4" in model.lower(): beta_set.add("tool-search-tool-2025-10-19") + # Filter out beta headers that Bedrock Invoke doesn't support + # AWS Bedrock only supports a specific whitelist of beta flags + # Reference: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html + BEDROCK_SUPPORTED_BETAS = { + "computer-use-2024-10-22", # Legacy computer use + "computer-use-2025-01-24", # Current computer use (Claude 3.7 Sonnet) + "token-efficient-tools-2025-02-19", # Tool use (Claude 3.7+ and Claude 4+) + "interleaved-thinking-2025-05-14", # Interleaved thinking (Claude 4+) + "output-128k-2025-02-19", # 128K output tokens (Claude 3.7 Sonnet) + "dev-full-thinking-2025-05-14", # Developer mode for raw thinking (Claude 4+) + "context-1m-2025-08-07", # 1 million tokens (Claude Sonnet 4) + "context-management-2025-06-27", # Context management (Claude Sonnet/Haiku 4.5) + "effort-2025-11-24", # Effort parameter (Claude Opus 4.5) + "tool-search-tool-2025-10-19", # Tool search (Claude Opus 4.5) + "tool-examples-2025-10-29", # Tool use examples (Claude Opus 4.5) + } + + # Only keep beta headers that Bedrock supports + beta_set = {beta for beta in beta_set if beta in BEDROCK_SUPPORTED_BETAS} + if beta_set: _anthropic_request["anthropic_beta"] = list(beta_set) diff --git a/litellm/llms/bedrock/common_utils.py b/litellm/llms/bedrock/common_utils.py index 89b42f5e947..65d237bdbdf 100644 --- a/litellm/llms/bedrock/common_utils.py +++ b/litellm/llms/bedrock/common_utils.py @@ -797,7 +797,7 @@ class BedrockEventStreamDecoderBase: def get_anthropic_beta_from_headers(headers: dict) -> List[str]: """ Extract anthropic-beta header values and convert them to a list. - Supports comma-separated values from user headers. + Supports both JSON array format and comma-separated values from user headers. Used by both converse and invoke transformations for consistent handling of anthropic-beta headers that should be passed to AWS Bedrock. @@ -812,8 +812,25 @@ def get_anthropic_beta_from_headers(headers: dict) -> List[str]: if not anthropic_beta_header: return [] - # Split comma-separated values and strip whitespace - return [beta.strip() for beta in anthropic_beta_header.split(",")] + # If it's already a list, return it + if isinstance(anthropic_beta_header, list): + return anthropic_beta_header + + # Try to parse as JSON array first (e.g., '["interleaved-thinking-2025-05-14", "claude-code-20250219"]') + if isinstance(anthropic_beta_header, str): + anthropic_beta_header = anthropic_beta_header.strip() + if anthropic_beta_header.startswith("[") and anthropic_beta_header.endswith("]"): + try: + parsed = json.loads(anthropic_beta_header) + if isinstance(parsed, list): + return [str(beta).strip() for beta in parsed] + except json.JSONDecodeError: + pass # Fall through to comma-separated parsing + + # Fall back to comma-separated values + return [beta.strip() for beta in anthropic_beta_header.split(",")] + + return [] class CommonBatchFilesUtils: diff --git a/litellm/llms/bedrock/embed/cohere_transformation.py b/litellm/llms/bedrock/embed/cohere_transformation.py index 490cd71b793..d00cb74aae0 100644 --- a/litellm/llms/bedrock/embed/cohere_transformation.py +++ b/litellm/llms/bedrock/embed/cohere_transformation.py @@ -15,7 +15,7 @@ class BedrockCohereEmbeddingConfig: pass def get_supported_openai_params(self) -> List[str]: - return ["encoding_format"] + return ["encoding_format", "dimensions"] def map_openai_params( self, non_default_params: dict, optional_params: dict @@ -23,6 +23,8 @@ class BedrockCohereEmbeddingConfig: for k, v in non_default_params.items(): if k == "encoding_format": optional_params["embedding_types"] = v + elif k == "dimensions": + optional_params["output_dimension"] = v return optional_params def _is_v3_model(self, model: str) -> bool: diff --git a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py index a7065caece2..b1c45ea83a2 100644 --- a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py @@ -54,6 +54,7 @@ class AmazonAnthropicClaudeMessagesConfig( # These will be filtered out to prevent 400 "invalid beta flag" errors UNSUPPORTED_BEDROCK_INVOKE_BETA_PATTERNS = [ "advanced-tool-use", # Bedrock Invoke doesn't support advanced-tool-use beta headers + "prompt-caching-scope" ] def __init__(self, **kwargs): @@ -162,6 +163,49 @@ class AmazonAnthropicClaudeMessagesConfig( return any(pattern in model_lower for pattern in supported_patterns) + def _is_claude_opus_4_5(self, model: str) -> bool: + """ + Check if the model is Claude Opus 4.5. + + Args: + model: The model name + + Returns: + True if the model is Claude Opus 4.5 + """ + model_lower = model.lower() + opus_4_5_patterns = [ + "opus-4.5", "opus_4.5", "opus-4-5", "opus_4_5", + ] + return any(pattern in model_lower for pattern in opus_4_5_patterns) + + def _supports_tool_search_on_bedrock(self, model: str) -> bool: + """ + Check if the model supports tool search on Bedrock. + + On Amazon Bedrock, server-side tool search is supported on Claude Opus 4.5 + and Claude Sonnet 4.5 with the tool-search-tool-2025-10-19 beta header. + + Ref: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool + + Args: + model: The model name + + Returns: + True if the model supports tool search on Bedrock + """ + model_lower = model.lower() + + # Supported models for tool search on Bedrock + supported_patterns = [ + # Opus 4.5 + "opus-4.5", "opus_4.5", "opus-4-5", "opus_4_5", + # Sonnet 4.5 + "sonnet-4.5", "sonnet_4.5", "sonnet-4-5", "sonnet_4_5", + ] + + return any(pattern in model_lower for pattern in supported_patterns) + def _filter_unsupported_beta_headers_for_bedrock( self, model: str, beta_set: set ) -> None: @@ -169,25 +213,33 @@ class AmazonAnthropicClaudeMessagesConfig( Remove beta headers that are not supported on Bedrock for the given model. Extended thinking beta headers are only supported on specific Claude 4+ models. - Advanced tool use headers are not supported on Bedrock Invoke API. + Advanced tool use headers are not supported on Bedrock Invoke API, but need to be + translated to Bedrock-specific headers for models that support tool search + (Claude Opus 4.5, Sonnet 4.5). This prevents 400 "invalid beta flag" errors on Bedrock. Note: Bedrock Invoke API fails with a 400 error when unsupported beta headers are sent, returning: {"message":"invalid beta flag"} + Translation for models supporting tool search (Opus 4.5, Sonnet 4.5): + - advanced-tool-use-2025-11-20 -> tool-search-tool-2025-10-19 + tool-examples-2025-10-29 + Args: model: The model name beta_set: The set of beta headers to filter in-place """ beta_headers_to_remove = set() + has_advanced_tool_use = False - # 1. Filter out beta headers that are universally unsupported on Bedrock Invoke + # 1. Filter out beta headers that are universally unsupported on Bedrock Invoke and track if advanced-tool-use header is present for beta in beta_set: for unsupported_pattern in self.UNSUPPORTED_BEDROCK_INVOKE_BETA_PATTERNS: if unsupported_pattern in beta.lower(): beta_headers_to_remove.add(beta) + has_advanced_tool_use = True break - + + # 2. Filter out extended thinking headers for models that don't support them extended_thinking_patterns = [ "extended-thinking", @@ -204,6 +256,14 @@ class AmazonAnthropicClaudeMessagesConfig( for beta in beta_headers_to_remove: beta_set.discard(beta) + # 3. Translate advanced-tool-use to Bedrock-specific headers for models that support tool search + # Ref: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages-request-response.html + # Ref: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool + if has_advanced_tool_use and self._supports_tool_search_on_bedrock(model): + beta_set.add("tool-search-tool-2025-10-19") + beta_set.add("tool-examples-2025-10-29") + + def _get_tool_search_beta_header_for_bedrock( self, model: str, @@ -256,7 +316,7 @@ class AmazonAnthropicClaudeMessagesConfig( Ref: https://aws.amazon.com/blogs/machine-learning/structured-data-response-with-amazon-bedrock-prompt-engineering-and-tool-use/ """ import json - + # Extract schema from output_format schema = output_format.get("schema") if not schema: diff --git a/litellm/llms/bedrock/realtime/handler.py b/litellm/llms/bedrock/realtime/handler.py new file mode 100644 index 00000000000..9b6a80f4a2f --- /dev/null +++ b/litellm/llms/bedrock/realtime/handler.py @@ -0,0 +1,307 @@ +""" +This file contains the handler for AWS Bedrock Nova Sonic realtime API. + +This uses aws_sdk_bedrock_runtime for bidirectional streaming with Nova Sonic. +""" + +import asyncio +import json +from typing import Any, Optional + +from litellm._logging import verbose_proxy_logger +from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLogging + +from ..base_aws_llm import BaseAWSLLM +from .transformation import BedrockRealtimeConfig + + +class BedrockRealtime(BaseAWSLLM): + """Handler for Bedrock Nova Sonic realtime speech-to-speech API.""" + + def __init__(self): + super().__init__() + + async def async_realtime( + self, + model: str, + websocket: Any, + logging_obj: LiteLLMLogging, + api_base: Optional[str] = None, + api_key: Optional[str] = None, + timeout: Optional[float] = None, + aws_region_name: Optional[str] = None, + aws_access_key_id: Optional[str] = None, + aws_secret_access_key: Optional[str] = None, + aws_session_token: Optional[str] = None, + aws_role_name: Optional[str] = None, + aws_session_name: Optional[str] = None, + aws_profile_name: Optional[str] = None, + aws_web_identity_token: Optional[str] = None, + aws_sts_endpoint: Optional[str] = None, + aws_bedrock_runtime_endpoint: Optional[str] = None, + aws_external_id: Optional[str] = None, + **kwargs, + ): + """ + Establish bidirectional streaming connection with Bedrock Nova Sonic. + + Args: + model: Model ID (e.g., 'amazon.nova-sonic-v1:0') + websocket: Client WebSocket connection + logging_obj: LiteLLM logging object + aws_region_name: AWS region + Various AWS authentication parameters + """ + try: + from aws_sdk_bedrock_runtime.client import ( + BedrockRuntimeClient, + InvokeModelWithBidirectionalStreamOperationInput, + ) + from aws_sdk_bedrock_runtime.config import Config + from smithy_aws_core.identity.environment import ( + EnvironmentCredentialsResolver, + ) + except ImportError: + raise ImportError( + "Missing aws_sdk_bedrock_runtime. Install with: pip install aws-sdk-bedrock-runtime" + ) + + # Get AWS region + if aws_region_name is None: + optional_params = { + "aws_region_name": aws_region_name, + } + aws_region_name = self._get_aws_region_name(optional_params, model) + + # Get endpoint URL + if api_base is not None: + endpoint_uri = api_base + elif aws_bedrock_runtime_endpoint is not None: + endpoint_uri = aws_bedrock_runtime_endpoint + else: + endpoint_uri = f"https://bedrock-runtime.{aws_region_name}.amazonaws.com" + + verbose_proxy_logger.debug( + f"Bedrock Realtime: Connecting to {endpoint_uri} with model {model}" + ) + + # Initialize Bedrock client with aws_sdk_bedrock_runtime + config = Config( + endpoint_uri=endpoint_uri, + region=aws_region_name, + aws_credentials_identity_resolver=EnvironmentCredentialsResolver(), + ) + bedrock_client = BedrockRuntimeClient(config=config) + + transformation_config = BedrockRealtimeConfig() + + try: + # Initialize the bidirectional stream + bedrock_stream = await bedrock_client.invoke_model_with_bidirectional_stream( + InvokeModelWithBidirectionalStreamOperationInput(model_id=model) + ) + + verbose_proxy_logger.debug( + "Bedrock Realtime: Bidirectional stream established" + ) + + # Track state for transformation + session_state = { + "current_output_item_id": None, + "current_response_id": None, + "current_conversation_id": None, + "current_delta_chunks": None, + "current_item_chunks": None, + "current_delta_type": None, + "session_configuration_request": None, + } + + # Create tasks for bidirectional forwarding + client_to_bedrock_task = asyncio.create_task( + self._forward_client_to_bedrock( + websocket, + bedrock_stream, + transformation_config, + model, + session_state, + ) + ) + + bedrock_to_client_task = asyncio.create_task( + self._forward_bedrock_to_client( + bedrock_stream, + websocket, + transformation_config, + model, + logging_obj, + session_state, + ) + ) + + # Wait for both tasks to complete + await asyncio.gather( + client_to_bedrock_task, + bedrock_to_client_task, + return_exceptions=True, + ) + + except Exception as e: + verbose_proxy_logger.exception( + f"Error in BedrockRealtime.async_realtime: {e}" + ) + try: + await websocket.close(code=1011, reason=f"Internal error: {str(e)}") + except Exception: + pass + raise + + async def _forward_client_to_bedrock( + self, + client_ws: Any, + bedrock_stream: Any, + transformation_config: BedrockRealtimeConfig, + model: str, + session_state: dict, + ): + """Forward messages from client WebSocket to Bedrock stream.""" + try: + from aws_sdk_bedrock_runtime.models import ( + BidirectionalInputPayloadPart, + InvokeModelWithBidirectionalStreamInputChunk, + ) + + while True: + # Receive message from client + message = await client_ws.receive_text() + verbose_proxy_logger.debug( + f"Bedrock Realtime: Received from client: {message[:200]}" + ) + + # Transform OpenAI format to Bedrock format + transformed_messages = transformation_config.transform_realtime_request( + message=message, + model=model, + session_configuration_request=session_state.get( + "session_configuration_request" + ), + ) + + # Send transformed messages to Bedrock + for bedrock_message in transformed_messages: + event = InvokeModelWithBidirectionalStreamInputChunk( + value=BidirectionalInputPayloadPart( + bytes_=bedrock_message.encode("utf-8") + ) + ) + await bedrock_stream.input_stream.send(event) + verbose_proxy_logger.debug( + f"Bedrock Realtime: Sent to Bedrock: {bedrock_message[:200]}" + ) + + except Exception as e: + verbose_proxy_logger.debug( + f"Client to Bedrock forwarding ended: {e}", exc_info=True + ) + # Close the Bedrock stream input + try: + await bedrock_stream.input_stream.close() + except Exception: + pass + + async def _forward_bedrock_to_client( + self, + bedrock_stream: Any, + client_ws: Any, + transformation_config: BedrockRealtimeConfig, + model: str, + logging_obj: LiteLLMLogging, + session_state: dict, + ): + """Forward messages from Bedrock stream to client WebSocket.""" + try: + while True: + # Receive from Bedrock + output = await bedrock_stream.await_output() + result = await output[1].receive() + + if result.value and result.value.bytes_: + bedrock_response = result.value.bytes_.decode("utf-8") + verbose_proxy_logger.debug( + f"Bedrock Realtime: Received from Bedrock: {bedrock_response[:200]}" + ) + + # Transform Bedrock format to OpenAI format + from litellm.types.realtime import RealtimeResponseTransformInput + + realtime_response_transform_input: RealtimeResponseTransformInput = { + "current_output_item_id": session_state.get( + "current_output_item_id" + ), + "current_response_id": session_state.get("current_response_id"), + "current_conversation_id": session_state.get( + "current_conversation_id" + ), + "current_delta_chunks": session_state.get( + "current_delta_chunks" + ), + "current_item_chunks": session_state.get("current_item_chunks"), + "current_delta_type": session_state.get("current_delta_type"), + "session_configuration_request": session_state.get( + "session_configuration_request" + ), + } + + transformed_response = ( + transformation_config.transform_realtime_response( + message=bedrock_response, + model=model, + logging_obj=logging_obj, + realtime_response_transform_input=realtime_response_transform_input, + ) + ) + + # Update session state + session_state.update( + { + "current_output_item_id": transformed_response.get( + "current_output_item_id" + ), + "current_response_id": transformed_response.get( + "current_response_id" + ), + "current_conversation_id": transformed_response.get( + "current_conversation_id" + ), + "current_delta_chunks": transformed_response.get( + "current_delta_chunks" + ), + "current_item_chunks": transformed_response.get( + "current_item_chunks" + ), + "current_delta_type": transformed_response.get( + "current_delta_type" + ), + "session_configuration_request": transformed_response.get( + "session_configuration_request" + ), + } + ) + + # Send transformed messages to client + openai_messages = transformed_response.get("response", []) + for openai_message in openai_messages: + message_json = json.dumps(openai_message) + await client_ws.send_text(message_json) + verbose_proxy_logger.debug( + f"Bedrock Realtime: Sent to client: {message_json[:200]}" + ) + + except Exception as e: + verbose_proxy_logger.debug( + f"Bedrock to client forwarding ended: {e}", exc_info=True + ) + # Close the client WebSocket + try: + await client_ws.close() + except Exception: + pass diff --git a/litellm/llms/bedrock/realtime/transformation.py b/litellm/llms/bedrock/realtime/transformation.py new file mode 100644 index 00000000000..1dde1b47fe3 --- /dev/null +++ b/litellm/llms/bedrock/realtime/transformation.py @@ -0,0 +1,1156 @@ +""" +This file contains the transformation logic for Bedrock Nova Sonic realtime API. + +Transforms between OpenAI Realtime API format and Bedrock Nova Sonic format. +""" + +import json +import uuid as uuid_lib +from typing import Any, List, Optional, Union + +from litellm._logging import verbose_logger +from litellm._uuid import uuid +from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj +from litellm.llms.base_llm.realtime.transformation import BaseRealtimeConfig +from litellm.types.llms.openai import ( + OpenAIRealtimeContentPartDone, + OpenAIRealtimeDoneEvent, + OpenAIRealtimeEvents, + OpenAIRealtimeOutputItemDone, + OpenAIRealtimeResponseAudioDone, + OpenAIRealtimeResponseContentPartAdded, + OpenAIRealtimeResponseDelta, + OpenAIRealtimeResponseDoneObject, + OpenAIRealtimeResponseTextDone, + OpenAIRealtimeStreamResponseBaseObject, + OpenAIRealtimeStreamResponseOutputItemAdded, + OpenAIRealtimeStreamSession, + OpenAIRealtimeStreamSessionEvents, +) +from litellm.types.realtime import ( + ALL_DELTA_TYPES, + RealtimeResponseTransformInput, + RealtimeResponseTypedDict, +) +from litellm.utils import get_empty_usage + + +class BedrockRealtimeConfig(BaseRealtimeConfig): + """Configuration for Bedrock Nova Sonic realtime transformations.""" + + def __init__(self): + # Track session state + self.prompt_name = str(uuid_lib.uuid4()) + self.content_name = str(uuid_lib.uuid4()) + self.audio_content_name = str(uuid_lib.uuid4()) + + # Default configuration values + # Inference configuration + self.max_tokens = 1024 + self.top_p = 0.9 + self.temperature = 0.7 + + # Audio output configuration + self.output_sample_rate_hertz = 24000 + self.output_sample_size_bits = 16 + self.output_channel_count = 1 + self.voice_id = "matthew" + self.output_encoding = "base64" + self.output_audio_type = "SPEECH" + self.output_media_type = "audio/lpcm" + + # Audio input configuration + self.input_sample_rate_hertz = 16000 + self.input_sample_size_bits = 16 + self.input_channel_count = 1 + self.input_encoding = "base64" + self.input_audio_type = "SPEECH" + self.input_media_type = "audio/lpcm" + + # Text configuration + self.text_media_type = "text/plain" + + def validate_environment( + self, headers: dict, model: str, api_key: Optional[str] = None + ) -> dict: + """Validate environment - no special validation needed for Bedrock.""" + return headers + + def get_complete_url( + self, api_base: Optional[str], model: str, api_key: Optional[str] = None + ) -> str: + """Get complete URL - handled by aws_sdk_bedrock_runtime.""" + return api_base or "" + + def requires_session_configuration(self) -> bool: + """Bedrock requires session configuration.""" + return True + + def session_configuration_request(self, model: str, tools: Optional[List[dict]] = None) -> str: + """ + Create initial session configuration for Bedrock Nova Sonic. + + Args: + model: Model ID + tools: Optional list of tool definitions + + Returns JSON string with session start and prompt start events. + """ + session_start = { + "event": { + "sessionStart": { + "inferenceConfiguration": { + "maxTokens": self.max_tokens, + "topP": self.top_p, + "temperature": self.temperature, + } + } + } + } + + prompt_start_config = { + "promptName": self.prompt_name, + "textOutputConfiguration": {"mediaType": self.text_media_type}, + "audioOutputConfiguration": { + "mediaType": self.output_media_type, + "sampleRateHertz": self.output_sample_rate_hertz, + "sampleSizeBits": self.output_sample_size_bits, + "channelCount": self.output_channel_count, + "voiceId": self.voice_id, + "encoding": self.output_encoding, + "audioType": self.output_audio_type, + }, + } + + # Add tool configuration if tools are provided + if tools: + prompt_start_config["toolUseOutputConfiguration"] = { + "mediaType": "application/json" + } + prompt_start_config["toolConfiguration"] = { + "tools": self._transform_tools_to_bedrock_format(tools) + } + + prompt_start = {"event": {"promptStart": prompt_start_config}} + + # Return as a marker that we've sent the configuration + return json.dumps( + {"session_start": session_start, "prompt_start": prompt_start} + ) + + def _transform_tools_to_bedrock_format(self, tools: List[dict]) -> List[dict]: + """ + Transform OpenAI tool format to Bedrock tool format. + + Args: + tools: List of OpenAI format tools + + Returns: + List of Bedrock format tools + """ + bedrock_tools = [] + for tool in tools: + if tool.get("type") == "function": + function = tool.get("function", {}) + bedrock_tool = { + "toolSpec": { + "name": function.get("name", ""), + "description": function.get("description", ""), + "inputSchema": { + "json": json.dumps(function.get("parameters", {})) + } + } + } + bedrock_tools.append(bedrock_tool) + return bedrock_tools + + def _map_audio_format_to_sample_rate(self, audio_format: str, is_output: bool = True) -> int: + """ + Map OpenAI audio format to sample rate. + + Args: + audio_format: OpenAI audio format (pcm16, g711_ulaw, g711_alaw) + is_output: Whether this is for output (True) or input (False) + + Returns: + Sample rate in Hz + """ + # OpenAI uses 24kHz for output and can vary for input + # Bedrock Nova Sonic uses 24kHz for output and 16kHz for input by default + if audio_format == "pcm16": + return 24000 if is_output else 16000 + elif audio_format in ["g711_ulaw", "g711_alaw"]: + return 8000 # G.711 typically uses 8kHz + return 24000 if is_output else 16000 + + def transform_session_update_event(self, json_message: dict) -> List[str]: + """ + Transform session.update event to Bedrock session configuration. + + Args: + json_message: OpenAI session.update message + + Returns: + List of Bedrock format messages (JSON strings) + """ + verbose_logger.debug("Handling session.update") + messages: List[str] = [] + + session_config = json_message.get("session", {}) + + # Update inference configuration from session if provided + if "max_response_output_tokens" in session_config: + self.max_tokens = session_config["max_response_output_tokens"] + if "temperature" in session_config: + self.temperature = session_config["temperature"] + + # Update audio output configuration from session if provided + if "voice" in session_config: + self.voice_id = session_config["voice"] + if "output_audio_format" in session_config: + output_format = session_config["output_audio_format"] + self.output_sample_rate_hertz = self._map_audio_format_to_sample_rate( + output_format, is_output=True + ) + + # Update audio input configuration from session if provided + if "input_audio_format" in session_config: + input_format = session_config["input_audio_format"] + self.input_sample_rate_hertz = self._map_audio_format_to_sample_rate( + input_format, is_output=False + ) + + # Allow direct override of sample rates if provided (custom extension) + if "output_sample_rate_hertz" in session_config: + self.output_sample_rate_hertz = session_config["output_sample_rate_hertz"] + if "input_sample_rate_hertz" in session_config: + self.input_sample_rate_hertz = session_config["input_sample_rate_hertz"] + + # Send session start + session_start = { + "event": { + "sessionStart": { + "inferenceConfiguration": { + "maxTokens": self.max_tokens, + "topP": self.top_p, + "temperature": self.temperature, + } + } + } + } + messages.append(json.dumps(session_start)) + + # Send prompt start + prompt_start_config = { + "promptName": self.prompt_name, + "textOutputConfiguration": {"mediaType": self.text_media_type}, + "audioOutputConfiguration": { + "mediaType": self.output_media_type, + "sampleRateHertz": self.output_sample_rate_hertz, + "sampleSizeBits": self.output_sample_size_bits, + "channelCount": self.output_channel_count, + "voiceId": self.voice_id, + "encoding": self.output_encoding, + "audioType": self.output_audio_type, + }, + } + + # Add tool configuration if tools are provided + tools = session_config.get("tools") + if tools: + prompt_start_config["toolUseOutputConfiguration"] = { + "mediaType": "application/json" + } + prompt_start_config["toolConfiguration"] = { + "tools": self._transform_tools_to_bedrock_format(tools) + } + + prompt_start = {"event": {"promptStart": prompt_start_config}} + messages.append(json.dumps(prompt_start)) + + # Send system prompt if provided + instructions = session_config.get("instructions") + if instructions: + text_content_name = str(uuid_lib.uuid4()) + + # Content start + text_content_start = { + "event": { + "contentStart": { + "promptName": self.prompt_name, + "contentName": text_content_name, + "type": "TEXT", + "interactive": False, + "role": "SYSTEM", + "textInputConfiguration": {"mediaType": self.text_media_type}, + } + } + } + messages.append(json.dumps(text_content_start)) + + # Text input + text_input = { + "event": { + "textInput": { + "promptName": self.prompt_name, + "contentName": text_content_name, + "content": instructions, + } + } + } + messages.append(json.dumps(text_input)) + + # Content end + text_content_end = { + "event": { + "contentEnd": { + "promptName": self.prompt_name, + "contentName": text_content_name, + } + } + } + messages.append(json.dumps(text_content_end)) + + return messages + + def transform_input_audio_buffer_append_event(self, json_message: dict) -> List[str]: + """ + Transform input_audio_buffer.append event to Bedrock audio input. + + Args: + json_message: OpenAI input_audio_buffer.append message + + Returns: + List of Bedrock format messages (JSON strings) + """ + verbose_logger.debug("Handling input_audio_buffer.append") + messages: List[str] = [] + + # Check if we need to start audio content + if not hasattr(self, "_audio_content_started"): + audio_content_start = { + "event": { + "contentStart": { + "promptName": self.prompt_name, + "contentName": self.audio_content_name, + "type": "AUDIO", + "interactive": True, + "role": "USER", + "audioInputConfiguration": { + "mediaType": self.input_media_type, + "sampleRateHertz": self.input_sample_rate_hertz, + "sampleSizeBits": self.input_sample_size_bits, + "channelCount": self.input_channel_count, + "audioType": self.input_audio_type, + "encoding": self.input_encoding, + }, + } + } + } + messages.append(json.dumps(audio_content_start)) + self._audio_content_started = True + + # Send audio chunk + audio_data = json_message.get("audio", "") + audio_event = { + "event": { + "audioInput": { + "promptName": self.prompt_name, + "contentName": self.audio_content_name, + "content": audio_data, + } + } + } + messages.append(json.dumps(audio_event)) + + return messages + + def transform_input_audio_buffer_commit_event(self, json_message: dict) -> List[str]: + """ + Transform input_audio_buffer.commit event to Bedrock audio content end. + + Args: + json_message: OpenAI input_audio_buffer.commit message + + Returns: + List of Bedrock format messages (JSON strings) + """ + verbose_logger.debug("Handling input_audio_buffer.commit") + messages: List[str] = [] + + if hasattr(self, "_audio_content_started"): + audio_content_end = { + "event": { + "contentEnd": { + "promptName": self.prompt_name, + "contentName": self.audio_content_name, + } + } + } + messages.append(json.dumps(audio_content_end)) + delattr(self, "_audio_content_started") + + return messages + + def transform_conversation_item_create_event(self, json_message: dict) -> List[str]: + """ + Transform conversation.item.create event to Bedrock text input or tool result. + + Args: + json_message: OpenAI conversation.item.create message + + Returns: + List of Bedrock format messages (JSON strings) + """ + verbose_logger.debug("Handling conversation.item.create") + messages: List[str] = [] + + item = json_message.get("item", {}) + item_type = item.get("type") + + # Handle tool result + if item_type == "function_call_output": + return self.transform_conversation_item_create_tool_result_event(json_message) + + # Handle regular message + if item_type == "message": + content = item.get("content", []) + for content_part in content: + if content_part.get("type") == "input_text": + text_content_name = str(uuid_lib.uuid4()) + + # Content start + text_content_start = { + "event": { + "contentStart": { + "promptName": self.prompt_name, + "contentName": text_content_name, + "type": "TEXT", + "interactive": True, + "role": "USER", + "textInputConfiguration": { + "mediaType": self.text_media_type + }, + } + } + } + messages.append(json.dumps(text_content_start)) + + # Text input + text_input = { + "event": { + "textInput": { + "promptName": self.prompt_name, + "contentName": text_content_name, + "content": content_part.get("text", ""), + } + } + } + messages.append(json.dumps(text_input)) + + # Content end + text_content_end = { + "event": { + "contentEnd": { + "promptName": self.prompt_name, + "contentName": text_content_name, + } + } + } + messages.append(json.dumps(text_content_end)) + + return messages + + def transform_response_create_event(self, json_message: dict) -> List[str]: + """ + Transform response.create event to Bedrock format. + + Args: + json_message: OpenAI response.create message + + Returns: + List of Bedrock format messages (JSON strings) + """ + verbose_logger.debug("Handling response.create") + # Bedrock starts generating automatically, no explicit trigger needed + return [] + + def transform_response_cancel_event(self, json_message: dict) -> List[str]: + """ + Transform response.cancel event to Bedrock format. + + Args: + json_message: OpenAI response.cancel message + + Returns: + List of Bedrock format messages (JSON strings) + """ + verbose_logger.debug("Handling response.cancel") + # Send interrupt signal if needed + return [] + + def transform_realtime_request( + self, + message: str, + model: str, + session_configuration_request: Optional[str] = None, + ) -> List[str]: + """ + Transform OpenAI realtime request to Bedrock Nova Sonic format. + + Args: + message: OpenAI format message (JSON string) + model: Model ID + session_configuration_request: Previous session config + + Returns: + List of Bedrock format messages (JSON strings) + """ + try: + json_message = json.loads(message) + except json.JSONDecodeError: + verbose_logger.warning(f"Invalid JSON message: {message[:200]}") + return [] + + message_type = json_message.get("type") + + # Route to appropriate transformation method + if message_type == "session.update": + return self.transform_session_update_event(json_message) + elif message_type == "input_audio_buffer.append": + return self.transform_input_audio_buffer_append_event(json_message) + elif message_type == "input_audio_buffer.commit": + return self.transform_input_audio_buffer_commit_event(json_message) + elif message_type == "conversation.item.create": + return self.transform_conversation_item_create_event(json_message) + elif message_type == "response.create": + return self.transform_response_create_event(json_message) + elif message_type == "response.cancel": + return self.transform_response_cancel_event(json_message) + else: + verbose_logger.warning(f"Unknown message type: {message_type}") + return [] + + def transform_session_start_event( + self, + event: dict, + model: str, + logging_obj: LiteLLMLoggingObj, + ) -> OpenAIRealtimeStreamSessionEvents: + """ + Transform Bedrock sessionStart event to OpenAI session.created. + + Args: + event: Bedrock sessionStart event + model: Model ID + logging_obj: Logging object + + Returns: + OpenAI session.created event + """ + verbose_logger.debug("Handling sessionStart") + + session = OpenAIRealtimeStreamSession( + id=logging_obj.litellm_trace_id, + modalities=["text", "audio"], + ) + if model is not None and isinstance(model, str): + session["model"] = model + + return OpenAIRealtimeStreamSessionEvents( + type="session.created", + session=session, + event_id=str(uuid.uuid4()), + ) + + def transform_content_start_event( + self, + event: dict, + current_response_id: Optional[str], + current_output_item_id: Optional[str], + current_conversation_id: Optional[str], + ) -> tuple[ + List[OpenAIRealtimeEvents], + Optional[str], + Optional[str], + Optional[str], + Optional[ALL_DELTA_TYPES], + ]: + """ + Transform Bedrock contentStart event to OpenAI response events. + + Args: + event: Bedrock contentStart event + current_response_id: Current response ID + current_output_item_id: Current output item ID + current_conversation_id: Current conversation ID + + Returns: + Tuple of (events, response_id, output_item_id, conversation_id, delta_type) + """ + content_start = event["contentStart"] + role = content_start.get("role") + + if role != "ASSISTANT": + return [], current_response_id, current_output_item_id, current_conversation_id, None + + verbose_logger.debug("Handling ASSISTANT contentStart") + + # Initialize IDs if needed + if not current_response_id: + current_response_id = f"resp_{uuid.uuid4()}" + if not current_output_item_id: + current_output_item_id = f"item_{uuid.uuid4()}" + if not current_conversation_id: + current_conversation_id = f"conv_{uuid.uuid4()}" + + # Determine content type + content_type = content_start.get("type", "TEXT") + current_delta_type: ALL_DELTA_TYPES = "text" if content_type == "TEXT" else "audio" + + returned_messages: List[OpenAIRealtimeEvents] = [] + + # Send response.created + response_created = OpenAIRealtimeStreamResponseBaseObject( + type="response.created", + event_id=f"event_{uuid.uuid4()}", + response={ + "object": "realtime.response", + "id": current_response_id, + "status": "in_progress", + "output": [], + "conversation_id": current_conversation_id, + }, + ) + returned_messages.append(response_created) + + # Send response.output_item.added + output_item_added = OpenAIRealtimeStreamResponseOutputItemAdded( + type="response.output_item.added", + response_id=current_response_id, + output_index=0, + item={ + "id": current_output_item_id, + "object": "realtime.item", + "type": "message", + "status": "in_progress", + "role": "assistant", + "content": [], + }, + ) + returned_messages.append(output_item_added) + + # Send response.content_part.added + content_part_added = OpenAIRealtimeResponseContentPartAdded( + type="response.content_part.added", + content_index=0, + output_index=0, + event_id=f"event_{uuid.uuid4()}", + item_id=current_output_item_id, + part=( + {"type": "text", "text": ""} + if current_delta_type == "text" + else {"type": "audio", "transcript": ""} + ), + response_id=current_response_id, + ) + returned_messages.append(content_part_added) + + return ( + returned_messages, + current_response_id, + current_output_item_id, + current_conversation_id, + current_delta_type, + ) + + def transform_text_output_event( + self, + event: dict, + current_output_item_id: Optional[str], + current_response_id: Optional[str], + current_delta_chunks: Optional[List[OpenAIRealtimeResponseDelta]], + ) -> tuple[List[OpenAIRealtimeEvents], Optional[List[OpenAIRealtimeResponseDelta]]]: + """ + Transform Bedrock textOutput event to OpenAI response.text.delta. + + Args: + event: Bedrock textOutput event + current_output_item_id: Current output item ID + current_response_id: Current response ID + current_delta_chunks: Current delta chunks + + Returns: + Tuple of (events, updated_delta_chunks) + """ + verbose_logger.debug("Handling textOutput") + text_content = event["textOutput"].get("content", "") + + if not current_output_item_id or not current_response_id: + return [], current_delta_chunks + + text_delta = OpenAIRealtimeResponseDelta( + type="response.text.delta", + content_index=0, + event_id=f"event_{uuid.uuid4()}", + item_id=current_output_item_id, + output_index=0, + response_id=current_response_id, + delta=text_content, + ) + + # Track delta chunks + if current_delta_chunks is None: + current_delta_chunks = [] + current_delta_chunks.append(text_delta) + + return [text_delta], current_delta_chunks + + def transform_audio_output_event( + self, + event: dict, + current_output_item_id: Optional[str], + current_response_id: Optional[str], + ) -> List[OpenAIRealtimeEvents]: + """ + Transform Bedrock audioOutput event to OpenAI response.audio.delta. + + Args: + event: Bedrock audioOutput event + current_output_item_id: Current output item ID + current_response_id: Current response ID + + Returns: + List of OpenAI events + """ + verbose_logger.debug("Handling audioOutput") + audio_content = event["audioOutput"].get("content", "") + + if not current_output_item_id or not current_response_id: + return [] + + audio_delta = OpenAIRealtimeResponseDelta( + type="response.audio.delta", + content_index=0, + event_id=f"event_{uuid.uuid4()}", + item_id=current_output_item_id, + output_index=0, + response_id=current_response_id, + delta=audio_content, + ) + + return [audio_delta] + + def transform_content_end_event( + self, + event: dict, + current_output_item_id: Optional[str], + current_response_id: Optional[str], + current_delta_type: Optional[str], + current_delta_chunks: Optional[List[OpenAIRealtimeResponseDelta]], + ) -> tuple[List[OpenAIRealtimeEvents], Optional[List[OpenAIRealtimeResponseDelta]]]: + """ + Transform Bedrock contentEnd event to OpenAI response done events. + + Args: + event: Bedrock contentEnd event + current_output_item_id: Current output item ID + current_response_id: Current response ID + current_delta_type: Current delta type (text or audio) + current_delta_chunks: Current delta chunks + + Returns: + Tuple of (events, reset_delta_chunks) + """ + content_end = event["contentEnd"] + verbose_logger.debug(f"Handling contentEnd: {content_end}") + + if not current_output_item_id or not current_response_id: + return [], current_delta_chunks + + returned_messages: List[OpenAIRealtimeEvents] = [] + + # Send appropriate done event based on type + if current_delta_type == "text": + # Accumulate text + accumulated_text = "" + if current_delta_chunks: + accumulated_text = "".join( + [chunk.get("delta", "") for chunk in current_delta_chunks] + ) + + text_done = OpenAIRealtimeResponseTextDone( + type="response.text.done", + content_index=0, + event_id=f"event_{uuid.uuid4()}", + item_id=current_output_item_id, + output_index=0, + response_id=current_response_id, + text=accumulated_text, + ) + returned_messages.append(text_done) + + # Send content_part.done + content_part_done = OpenAIRealtimeContentPartDone( + type="response.content_part.done", + content_index=0, + event_id=f"event_{uuid.uuid4()}", + item_id=current_output_item_id, + output_index=0, + part={"type": "text", "text": accumulated_text}, + response_id=current_response_id, + ) + returned_messages.append(content_part_done) + + elif current_delta_type == "audio": + audio_done = OpenAIRealtimeResponseAudioDone( + type="response.audio.done", + content_index=0, + event_id=f"event_{uuid.uuid4()}", + item_id=current_output_item_id, + output_index=0, + response_id=current_response_id, + ) + returned_messages.append(audio_done) + + # Send content_part.done + content_part_done = OpenAIRealtimeContentPartDone( + type="response.content_part.done", + content_index=0, + event_id=f"event_{uuid.uuid4()}", + item_id=current_output_item_id, + output_index=0, + part={"type": "audio", "transcript": ""}, + response_id=current_response_id, + ) + returned_messages.append(content_part_done) + + # Send output_item.done + output_item_done = OpenAIRealtimeOutputItemDone( + type="response.output_item.done", + event_id=f"event_{uuid.uuid4()}", + output_index=0, + response_id=current_response_id, + item={ + "id": current_output_item_id, + "object": "realtime.item", + "type": "message", + "status": "completed", + "role": "assistant", + "content": [], + }, + ) + returned_messages.append(output_item_done) + + # Reset delta chunks + return returned_messages, None + + def transform_prompt_end_event( + self, + event: dict, + current_response_id: Optional[str], + current_conversation_id: Optional[str], + ) -> tuple[List[OpenAIRealtimeEvents], Optional[str], Optional[str], Optional[ALL_DELTA_TYPES]]: + """ + Transform Bedrock promptEnd event to OpenAI response.done. + + Args: + event: Bedrock promptEnd event + current_response_id: Current response ID + current_conversation_id: Current conversation ID + + Returns: + Tuple of (events, reset_output_item_id, reset_response_id, reset_delta_type) + """ + verbose_logger.debug("Handling promptEnd") + + if not current_response_id or not current_conversation_id: + return [], None, None, None + + usage_obj = get_empty_usage() + response_done = OpenAIRealtimeDoneEvent( + type="response.done", + event_id=f"event_{uuid.uuid4()}", + response=OpenAIRealtimeResponseDoneObject( + object="realtime.response", + id=current_response_id, + status="completed", + output=[], + conversation_id=current_conversation_id, + usage={ + "prompt_tokens": usage_obj.prompt_tokens, + "completion_tokens": usage_obj.completion_tokens, + "total_tokens": usage_obj.total_tokens, + }, + ), + ) + + # Reset state for next response + return [response_done], None, None, None + + def transform_tool_use_event( + self, + event: dict, + current_output_item_id: Optional[str], + current_response_id: Optional[str], + ) -> tuple[List[OpenAIRealtimeEvents], str, str]: + """ + Transform Bedrock toolUse event to OpenAI format. + + Args: + event: Bedrock toolUse event + current_output_item_id: Current output item ID + current_response_id: Current response ID + + Returns: + Tuple of (events, tool_call_id, tool_name) for tracking + """ + verbose_logger.debug("Handling toolUse") + tool_use = event["toolUse"] + + if not current_output_item_id or not current_response_id: + return [], "", "" + + # Parse the tool input + tool_input = {} + if "input" in tool_use: + try: + tool_input = json.loads(tool_use["input"]) if isinstance(tool_use["input"], str) else tool_use["input"] + except json.JSONDecodeError: + tool_input = {} + + tool_call_id = tool_use.get("toolUseId", "") + tool_name = tool_use.get("toolName", "") + + # Create a function call arguments done event + # This is a custom event format that matches what clients expect + from typing import cast + function_call_event: dict[str, Any] = { + "type": "response.function_call_arguments.done", + "event_id": f"event_{uuid.uuid4()}", + "response_id": current_response_id, + "item_id": current_output_item_id, + "output_index": 0, + "call_id": tool_call_id, + "name": tool_name, + "arguments": json.dumps(tool_input), + } + + return [cast(OpenAIRealtimeEvents, function_call_event)], tool_call_id, tool_name + + def transform_conversation_item_create_tool_result_event(self, json_message: dict) -> List[str]: + """ + Transform conversation.item.create with tool result to Bedrock format. + + Args: + json_message: OpenAI conversation.item.create message with tool result + + Returns: + List of Bedrock format messages (JSON strings) + """ + verbose_logger.debug("Handling conversation.item.create for tool result") + messages: List[str] = [] + + item = json_message.get("item", {}) + if item.get("type") == "function_call_output": + tool_content_name = str(uuid_lib.uuid4()) + call_id = item.get("call_id", "") + output = item.get("output", "") + + # Content start for tool result + tool_content_start = { + "event": { + "contentStart": { + "promptName": self.prompt_name, + "contentName": tool_content_name, + "interactive": False, + "type": "TOOL", + "role": "TOOL", + "toolResultInputConfiguration": { + "toolUseId": call_id, + "type": "TEXT", + "textInputConfiguration": { + "mediaType": "text/plain" + } + } + } + } + } + messages.append(json.dumps(tool_content_start)) + + # Tool result + tool_result = { + "event": { + "toolResult": { + "promptName": self.prompt_name, + "contentName": tool_content_name, + "content": output if isinstance(output, str) else json.dumps(output) + } + } + } + messages.append(json.dumps(tool_result)) + + # Content end + tool_content_end = { + "event": { + "contentEnd": { + "promptName": self.prompt_name, + "contentName": tool_content_name, + } + } + } + messages.append(json.dumps(tool_content_end)) + + return messages + + def transform_realtime_response( + self, + message: Union[str, bytes], + model: str, + logging_obj: LiteLLMLoggingObj, + realtime_response_transform_input: RealtimeResponseTransformInput, + ) -> RealtimeResponseTypedDict: + """ + Transform Bedrock Nova Sonic response to OpenAI realtime format. + + Args: + message: Bedrock format message (JSON string) + model: Model ID + logging_obj: Logging object + realtime_response_transform_input: Current state + + Returns: + Transformed response with updated state + """ + try: + json_message = json.loads(message) + except json.JSONDecodeError: + message_preview = message[:200].decode('utf-8', errors='replace') if isinstance(message, bytes) else message[:200] + verbose_logger.warning(f"Invalid JSON message: {message_preview}") + return { + "response": [], + "current_output_item_id": realtime_response_transform_input.get( + "current_output_item_id" + ), + "current_response_id": realtime_response_transform_input.get( + "current_response_id" + ), + "current_delta_chunks": realtime_response_transform_input.get( + "current_delta_chunks" + ), + "current_conversation_id": realtime_response_transform_input.get( + "current_conversation_id" + ), + "current_item_chunks": realtime_response_transform_input.get( + "current_item_chunks" + ), + "current_delta_type": realtime_response_transform_input.get( + "current_delta_type" + ), + "session_configuration_request": realtime_response_transform_input.get( + "session_configuration_request" + ), + } + + # Extract state + current_output_item_id = realtime_response_transform_input.get( + "current_output_item_id" + ) + current_response_id = realtime_response_transform_input.get( + "current_response_id" + ) + current_conversation_id = realtime_response_transform_input.get( + "current_conversation_id" + ) + current_delta_chunks = realtime_response_transform_input.get( + "current_delta_chunks" + ) + current_delta_type = realtime_response_transform_input.get("current_delta_type") + session_configuration_request = realtime_response_transform_input.get( + "session_configuration_request" + ) + + returned_messages: List[OpenAIRealtimeEvents] = [] + + # Parse Bedrock event + event = json_message.get("event", {}) + + # Route to appropriate transformation method + if "sessionStart" in event: + session_created = self.transform_session_start_event( + event, model, logging_obj + ) + returned_messages.append(session_created) + session_configuration_request = json.dumps({"configured": True}) + + elif "contentStart" in event: + ( + events, + current_response_id, + current_output_item_id, + current_conversation_id, + current_delta_type, + ) = self.transform_content_start_event( + event, + current_response_id, + current_output_item_id, + current_conversation_id, + ) + returned_messages.extend(events) + + elif "textOutput" in event: + events, current_delta_chunks = self.transform_text_output_event( + event, + current_output_item_id, + current_response_id, + current_delta_chunks, + ) + returned_messages.extend(events) + + elif "audioOutput" in event: + events = self.transform_audio_output_event( + event, current_output_item_id, current_response_id + ) + returned_messages.extend(events) + + elif "contentEnd" in event: + events, current_delta_chunks = self.transform_content_end_event( + event, + current_output_item_id, + current_response_id, + current_delta_type, + current_delta_chunks, + ) + returned_messages.extend(events) + + elif "toolUse" in event: + events, tool_call_id, tool_name = self.transform_tool_use_event( + event, current_output_item_id, current_response_id + ) + returned_messages.extend(events) + # Store tool call info for potential use + verbose_logger.debug(f"Tool use event: {tool_name} (ID: {tool_call_id})") + + elif "promptEnd" in event: + ( + events, + current_output_item_id, + current_response_id, + current_delta_type, + ) = self.transform_prompt_end_event( + event, current_response_id, current_conversation_id + ) + returned_messages.extend(events) + + return { + "response": returned_messages, + "current_output_item_id": current_output_item_id, + "current_response_id": current_response_id, + "current_delta_chunks": current_delta_chunks, + "current_conversation_id": current_conversation_id, + "current_item_chunks": realtime_response_transform_input.get( + "current_item_chunks" + ), + "current_delta_type": current_delta_type, + "session_configuration_request": session_configuration_request, + } diff --git a/litellm/llms/cerebras/chat.py b/litellm/llms/cerebras/chat.py index 4e9c6811a77..9929e2ab9a2 100644 --- a/litellm/llms/cerebras/chat.py +++ b/litellm/llms/cerebras/chat.py @@ -7,6 +7,7 @@ this is OpenAI compatible - no translation needed / occurs from typing import Optional from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig +from litellm.utils import supports_reasoning class CerebrasConfig(OpenAIGPTConfig): @@ -24,6 +25,7 @@ class CerebrasConfig(OpenAIGPTConfig): tool_choice: Optional[str] = None tools: Optional[list] = None user: Optional[str] = None + reasoning_effort: Optional[str] = None def __init__( self, @@ -37,6 +39,7 @@ class CerebrasConfig(OpenAIGPTConfig): tool_choice: Optional[str] = None, tools: Optional[list] = None, user: Optional[str] = None, + reasoning_effort: Optional[str] = None, ) -> None: locals_ = locals().copy() for key, value in locals_.items(): @@ -53,7 +56,7 @@ class CerebrasConfig(OpenAIGPTConfig): """ - return [ + supported_params = [ "max_tokens", "max_completion_tokens", "response_format", @@ -67,6 +70,12 @@ class CerebrasConfig(OpenAIGPTConfig): "user", ] + # Only add reasoning_effort for models that support it + if supports_reasoning(model=model, custom_llm_provider="cerebras"): + supported_params.append("reasoning_effort") + + return supported_params + def map_openai_params( self, non_default_params: dict, diff --git a/litellm/llms/cohere/rerank/guardrail_translation/handler.py b/litellm/llms/cohere/rerank/guardrail_translation/handler.py index 6893a5991c3..b8133c59f7d 100644 --- a/litellm/llms/cohere/rerank/guardrail_translation/handler.py +++ b/litellm/llms/cohere/rerank/guardrail_translation/handler.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Optional from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation +from litellm.types.utils import GenericGuardrailAPIInputs if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail @@ -49,8 +50,13 @@ class CohereRerankHandler(BaseTranslation): # Process query only query = data.get("query") if query is not None and isinstance(query, str): + inputs = GenericGuardrailAPIInputs(texts=[query]) + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [query]}, + inputs=inputs, request_data=data, input_type="request", logging_obj=litellm_logging_obj, diff --git a/litellm/llms/custom_httpx/http_handler.py b/litellm/llms/custom_httpx/http_handler.py index 4f86877a6c0..ac9dd5998e2 100644 --- a/litellm/llms/custom_httpx/http_handler.py +++ b/litellm/llms/custom_httpx/http_handler.py @@ -50,9 +50,21 @@ try: except Exception: version = "0.0.0" -headers = { - "User-Agent": f"litellm/{version}", -} +def get_default_headers() -> dict: + """ + Get default headers for HTTP requests. + + - Default: `User-Agent: litellm/{version}` + - Override: set `LITELLM_USER_AGENT` to fully override the header value. + """ + user_agent = os.environ.get("LITELLM_USER_AGENT") + if user_agent is not None: + return {"User-Agent": user_agent} + + return {"User-Agent": f"litellm/{version}"} + +# Initialize headers (User-Agent) +headers = get_default_headers() # https://www.python-httpx.org/advanced/timeouts _DEFAULT_TIMEOUT = httpx.Timeout(timeout=5.0, connect=5.0) @@ -371,13 +383,16 @@ class AsyncHTTPHandler: shared_session=shared_session, ) + # Get default headers (User-Agent, overridable via LITELLM_USER_AGENT) + default_headers = get_default_headers() + return httpx.AsyncClient( transport=transport, event_hooks=event_hooks, timeout=timeout, verify=ssl_config, cert=cert, - headers=headers, + headers=default_headers, follow_redirects=True, ) @@ -899,6 +914,9 @@ class HTTPHandler: # /path/to/client.pem cert = os.getenv("SSL_CERTIFICATE", litellm.ssl_certificate) + # Get default headers (User-Agent, overridable via LITELLM_USER_AGENT) + default_headers = get_default_headers() if not disable_default_headers else None + if client is None: transport = self._create_sync_transport() @@ -908,7 +926,7 @@ class HTTPHandler: timeout=timeout, verify=ssl_config, cert=cert, - headers=headers if not disable_default_headers else None, + headers=default_headers, follow_redirects=True, ) else: diff --git a/litellm/llms/custom_httpx/httpx_handler.py b/litellm/llms/custom_httpx/httpx_handler.py index 6f684ba01c2..491cd97f7db 100644 --- a/litellm/llms/custom_httpx/httpx_handler.py +++ b/litellm/llms/custom_httpx/httpx_handler.py @@ -1,3 +1,4 @@ +import os from typing import Optional, Union import httpx @@ -7,13 +8,22 @@ try: except Exception: version = "0.0.0" -headers = { - "User-Agent": f"litellm/{version}", -} +def get_default_headers() -> dict: + """ + Get default headers for HTTP requests. + - Default: `User-Agent: litellm/{version}` + - Override: set `LITELLM_USER_AGENT` to fully override the header value. + """ + user_agent = os.environ.get("LITELLM_USER_AGENT") + if user_agent is not None: + return {"User-Agent": user_agent} + + return {"User-Agent": f"litellm/{version}"} class HTTPHandler: def __init__(self, concurrent_limit=1000): + headers = get_default_headers() # Create a client with a connection pool self.client = httpx.AsyncClient( limits=httpx.Limits( diff --git a/litellm/llms/custom_httpx/llm_http_handler.py b/litellm/llms/custom_httpx/llm_http_handler.py index 6a87967c3aa..d2ea7e872a2 100644 --- a/litellm/llms/custom_httpx/llm_http_handler.py +++ b/litellm/llms/custom_httpx/llm_http_handler.py @@ -7033,17 +7033,31 @@ class BaseLLMHTTPHandler: litellm_params=dict(litellm_params), ) - ( - url, - request_body, - ) = vector_store_provider_config.transform_search_vector_store_request( - vector_store_id=vector_store_id, - query=query, - vector_store_search_optional_params=vector_store_search_optional_params, - api_base=api_base, - litellm_logging_obj=logging_obj, - litellm_params=dict(litellm_params), - ) + # Check if provider has async transform method + if hasattr(vector_store_provider_config, "atransform_search_vector_store_request"): + ( + url, + request_body, + ) = await vector_store_provider_config.atransform_search_vector_store_request( + vector_store_id=vector_store_id, + query=query, + vector_store_search_optional_params=vector_store_search_optional_params, + api_base=api_base, + litellm_logging_obj=logging_obj, + litellm_params=dict(litellm_params), + ) + else: + ( + url, + request_body, + ) = vector_store_provider_config.transform_search_vector_store_request( + vector_store_id=vector_store_id, + query=query, + vector_store_search_optional_params=vector_store_search_optional_params, + api_base=api_base, + litellm_logging_obj=logging_obj, + litellm_params=dict(litellm_params), + ) all_optional_params: Dict[str, Any] = dict(litellm_params) all_optional_params.update(vector_store_search_optional_params or {}) headers, signed_json_body = vector_store_provider_config.sign_request( diff --git a/litellm/llms/fireworks_ai/chat/transformation.py b/litellm/llms/fireworks_ai/chat/transformation.py index 86bcd94450f..7ec32fecc46 100644 --- a/litellm/llms/fireworks_ai/chat/transformation.py +++ b/litellm/llms/fireworks_ai/chat/transformation.py @@ -236,6 +236,10 @@ class FireworksAIConfig(OpenAIGPTConfig): disable_add_transform_inline_image_block=disable_add_transform_inline_image_block, ) filter_value_from_dict(cast(dict, message), "cache_control") + # Remove fields not permitted by FireworksAI that may cause: + # "Not permitted, field: 'messages[n].provider_specific_fields'" + if isinstance(message, dict) and "provider_specific_fields" in message: + cast(dict, message).pop("provider_specific_fields", None) return messages diff --git a/litellm/llms/gemini/chat/transformation.py b/litellm/llms/gemini/chat/transformation.py index f6d075392b2..d5a5ab667a6 100644 --- a/litellm/llms/gemini/chat/transformation.py +++ b/litellm/llms/gemini/chat/transformation.py @@ -92,7 +92,7 @@ class GoogleAIStudioGeminiConfig(VertexGeminiConfig): "parallel_tool_calls", "web_search_options", ] - if supports_reasoning(model): + if supports_reasoning(model, custom_llm_provider="gemini"): supported_params.append("reasoning_effort") supported_params.append("thinking") if self.is_model_gemini_audio_model(model): diff --git a/litellm/llms/gemini/files/transformation.py b/litellm/llms/gemini/files/transformation.py index d9ebf69a97a..cc799cfd6aa 100644 --- a/litellm/llms/gemini/files/transformation.py +++ b/litellm/llms/gemini/files/transformation.py @@ -4,7 +4,7 @@ Supports writing files to Google AI Studio Files API. For vertex ai, check out the vertex_ai/files/handler.py file. """ import time -from typing import List, Optional +from typing import Any, List, Literal, Optional import httpx from openai.types.file_deleted import FileDeleted @@ -17,6 +17,7 @@ from litellm.llms.base_llm.files.transformation import ( ) from litellm.types.llms.gemini import GeminiCreateFilesResponseObject from litellm.types.llms.openai import ( + AllMessageValues, CreateFileRequest, HttpxBinaryResponseContent, OpenAICreateFileRequestOptionalParams, @@ -35,6 +36,27 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig): def custom_llm_provider(self) -> LlmProviders: return LlmProviders.GEMINI + def validate_environment( + self, + headers: dict[Any, Any], + model: str, + messages: List[AllMessageValues], + optional_params: dict[Any, Any], + litellm_params: dict[Any, Any], + api_key: Optional[str] = None, + api_base: Optional[str] = None, + ) -> dict[Any, Any]: + """ + Validate environment and add Gemini API key to headers. + Google AI Studio uses x-goog-api-key header for authentication. + """ + resolved_api_key = self.get_api_key(api_key) + if not resolved_api_key: + raise ValueError("GEMINI_API_KEY is required for Google AI Studio file operations") + + headers["x-goog-api-key"] = resolved_api_key + return headers + def get_complete_url( self, api_base: Optional[str], @@ -56,10 +78,12 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig): if not api_base: raise ValueError("api_base is required") - if not api_key: + # Get API key from multiple sources + final_api_key = api_key or litellm_params.get("api_key") or self.get_api_key() + if not final_api_key: raise ValueError("api_key is required") - url = "{}/{}?key={}".format(api_base, endpoint, api_key) + url = "{}/{}?key={}".format(api_base, endpoint, final_api_key) return url def get_supported_openai_params( @@ -180,7 +204,26 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig): optional_params: dict, litellm_params: dict, ) -> tuple[str, dict]: - raise NotImplementedError("GoogleAIStudioFilesHandler does not support file retrieval") + """ + Get the URL to retrieve a file from Google AI Studio. + + We expect file_id to be the URI (e.g. https://generativelanguage.googleapis.com/v1beta/files/...) + as returned by the upload response. + """ + api_key = litellm_params.get("api_key") or self.get_api_key() + if not api_key: + raise ValueError("api_key is required") + + if file_id.startswith("http"): + url = "{}?key={}".format(file_id, api_key) + else: + # Fallback for just file name (files/...) + api_base = self.get_api_base(litellm_params.get("api_base")) or "https://generativelanguage.googleapis.com" + api_base = api_base.rstrip("/") + url = "{}/v1beta/{}?key={}".format(api_base, file_id, api_key) + + # Return empty params dict - API key is already in URL, no query params needed + return url, {} def transform_retrieve_file_response( self, @@ -188,7 +231,42 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig): logging_obj: LiteLLMLoggingObj, litellm_params: dict, ) -> OpenAIFileObject: - raise NotImplementedError("GoogleAIStudioFilesHandler does not support file retrieval") + """ + Transform Gemini's file retrieval response into OpenAI-style FileObject + """ + try: + response_json = raw_response.json() + + # Map Gemini state to OpenAI status + gemini_state = response_json.get("state", "STATE_UNSPECIFIED") + # Explicitly type status as the Literal union + if gemini_state == "ACTIVE": + status: Literal["uploaded", "processed", "error"] = "processed" + elif gemini_state == "FAILED": + status = "error" + else: + status = "uploaded" + + return OpenAIFileObject( + id=response_json.get("uri", ""), + bytes=int(response_json.get("sizeBytes", 0)), + created_at=int( + time.mktime( + time.strptime( + response_json["createTime"].replace("Z", "+00:00"), + "%Y-%m-%dT%H:%M:%S.%f%z", + ) + ) + ), + filename=response_json.get("displayName", ""), + object="file", + purpose="user_data", + status=status, + status_details=str(response_json.get("error", "")) if gemini_state == "FAILED" else None, + ) + except Exception as e: + verbose_logger.exception(f"Error parsing file retrieve response: {str(e)}") + raise ValueError(f"Error parsing file retrieve response: {str(e)}") def transform_delete_file_request( self, @@ -196,7 +274,41 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig): optional_params: dict, litellm_params: dict, ) -> tuple[str, dict]: - raise NotImplementedError("GoogleAIStudioFilesHandler does not support file deletion") + """ + Transform delete file request for Google AI Studio. + + Args: + file_id: The file URI (e.g., "files/abc123" or full URI) + optional_params: Optional parameters + litellm_params: LiteLLM parameters containing api_key + + Returns: + tuple[str, dict]: (url, params) for the DELETE request + """ + api_base = self.get_api_base(litellm_params.get("api_base")) + if not api_base: + raise ValueError("api_base is required") + + # Get API key from multiple sources (same pattern as get_complete_url) + api_key = litellm_params.get("api_key") or self.get_api_key() + if not api_key: + raise ValueError("api_key is required") + + # Extract file name from URI if full URI is provided + # file_id could be "files/abc123" or "https://generativelanguage.googleapis.com/v1beta/files/abc123" + if file_id.startswith("http"): + # Extract the file path from full URI + file_name = file_id.split("/v1beta/")[-1] + else: + file_name = file_id if file_id.startswith("files/") else f"files/{file_id}" + + # Construct the delete URL + url = f"{api_base}/v1beta/{file_name}" + + # Add API key as header (Google AI Studio uses x-goog-api-key header) + params: dict = {} + + return url, params def transform_delete_file_response( self, @@ -204,7 +316,34 @@ class GoogleAIStudioFilesHandler(GeminiModelInfo, BaseFilesConfig): logging_obj: LiteLLMLoggingObj, litellm_params: dict, ) -> FileDeleted: - raise NotImplementedError("GoogleAIStudioFilesHandler does not support file deletion") + """ + Transform Gemini's file delete response into OpenAI-style FileDeleted. + + Google AI Studio returns an empty JSON object {} on successful deletion. + """ + try: + # Google AI Studio returns {} on successful deletion + if raw_response.status_code == 200: + # Extract file ID from the request URL if possible + file_id = "deleted" + if hasattr(raw_response, "request") and raw_response.request: + url = str(raw_response.request.url) + if "/files/" in url: + file_id = url.split("/files/")[-1].split("?")[0] + # Add the files/ prefix if not present + if not file_id.startswith("files/"): + file_id = f"files/{file_id}" + + return FileDeleted( + id=file_id, + deleted=True, + object="file" + ) + else: + raise ValueError(f"Failed to delete file: {raw_response.text}") + except Exception as e: + verbose_logger.exception(f"Error parsing file delete response: {str(e)}") + raise ValueError(f"Error parsing file delete response: {str(e)}") def transform_list_files_request( self, diff --git a/litellm/llms/gemini/image_edit/transformation.py b/litellm/llms/gemini/image_edit/transformation.py index 16541138217..c3ea63ad43b 100644 --- a/litellm/llms/gemini/image_edit/transformation.py +++ b/litellm/llms/gemini/image_edit/transformation.py @@ -106,7 +106,10 @@ class GeminiImageEditConfig(BaseImageEditConfig): generation_config: Dict[str, Any] = {} if "aspectRatio" in image_edit_optional_request_params: - generation_config["aspectRatio"] = image_edit_optional_request_params[ + # Move aspectRatio into imageConfig inside generationConfig + if "imageConfig" not in generation_config: + generation_config["imageConfig"] = {} + generation_config["imageConfig"]["aspectRatio"] = image_edit_optional_request_params[ "aspectRatio" ] diff --git a/litellm/llms/gemini/image_generation/transformation.py b/litellm/llms/gemini/image_generation/transformation.py index 63b835df9d0..73aef15e4c7 100644 --- a/litellm/llms/gemini/image_generation/transformation.py +++ b/litellm/llms/gemini/image_generation/transformation.py @@ -255,9 +255,11 @@ class GoogleImageGenConfig(BaseImageGenerationConfig): if "inlineData" in part: inline_data = part["inlineData"] if "data" in inline_data: + thought_sig = part.get("thoughtSignature") model_response.data.append(ImageObject( b64_json=inline_data["data"], url=None, + provider_specific_fields={"thought_signature": thought_sig} if thought_sig else None, )) # Extract usage metadata for Gemini models diff --git a/litellm/llms/gigachat/chat/transformation.py b/litellm/llms/gigachat/chat/transformation.py index 90cf67da6b2..ba14de1f65d 100644 --- a/litellm/llms/gigachat/chat/transformation.py +++ b/litellm/llms/gigachat/chat/transformation.py @@ -31,6 +31,16 @@ else: GIGACHAT_BASE_URL = "https://gigachat.devices.sberbank.ru/api/v1" +def is_valid_json(value: str) -> bool: + """Checks whether the value passed is a valid serialized JSON string""" + try: + json.loads(value) + except json.JSONDecodeError: + return False + else: + return True + + class GigaChatError(BaseLLMException): """GigaChat API error.""" @@ -101,7 +111,11 @@ class GigaChatConfig(BaseConfig): Set up headers with OAuth token. """ # Get access token - credentials = api_key or get_secret_str("GIGACHAT_CREDENTIALS") or get_secret_str("GIGACHAT_API_KEY") + credentials = ( + api_key + or get_secret_str("GIGACHAT_CREDENTIALS") + or get_secret_str("GIGACHAT_API_KEY") + ) access_token = get_access_token(credentials=credentials) # Store credentials for image uploads @@ -193,11 +207,13 @@ class GigaChatConfig(BaseConfig): for tool in tools: if tool.get("type") == "function": func = tool.get("function", {}) - functions.append({ - "name": func.get("name", ""), - "description": func.get("description", ""), - "parameters": func.get("parameters", {}), - }) + functions.append( + { + "name": func.get("name", ""), + "description": func.get("description", ""), + "parameters": func.get("parameters", {}), + } + ) return functions def _map_tool_choice( @@ -281,8 +297,14 @@ class GigaChatConfig(BaseConfig): } # Add optional params - for key in ["temperature", "top_p", "max_tokens", "stream", - "repetition_penalty", "profanity_check"]: + for key in [ + "temperature", + "top_p", + "max_tokens", + "stream", + "repetition_penalty", + "profanity_check", + ]: if key in optional_params: request_data[key] = optional_params[key] @@ -314,7 +336,7 @@ class GigaChatConfig(BaseConfig): elif role == "tool": message["role"] = "function" content = message.get("content", "") - if not isinstance(content, str): + if not isinstance(content, str) or not is_valid_json(content): message["content"] = json.dumps(content, ensure_ascii=False) # Handle None content @@ -441,14 +463,16 @@ class GigaChatConfig(BaseConfig): # Convert to tool_calls format if isinstance(args, dict): args = json.dumps(args, ensure_ascii=False) - message_data["tool_calls"] = [{ - "id": f"call_{uuid.uuid4().hex[:24]}", - "type": "function", - "function": { - "name": func_call.get("name", ""), - "arguments": args, + message_data["tool_calls"] = [ + { + "id": f"call_{uuid.uuid4().hex[:24]}", + "type": "function", + "function": { + "name": func_call.get("name", ""), + "arguments": args, + }, } - }] + ] message_data.pop("function_call", None) finish_reason = "tool_calls" diff --git a/litellm/llms/github_copilot/chat/transformation.py b/litellm/llms/github_copilot/chat/transformation.py index 50f18cedf9b..945b7ebf7ff 100644 --- a/litellm/llms/github_copilot/chat/transformation.py +++ b/litellm/llms/github_copilot/chat/transformation.py @@ -1,11 +1,15 @@ -from typing import Any, Optional, Tuple, cast, List +from typing import Any, List, Optional, Tuple, cast from litellm.exceptions import AuthenticationError from litellm.llms.openai.openai import OpenAIConfig from litellm.types.llms.openai import AllMessageValues from ..authenticator import Authenticator -from ..common_utils import GetAPIKeyError, GITHUB_COPILOT_API_BASE +from ..common_utils import ( + GITHUB_COPILOT_API_BASE, + GetAPIKeyError, + get_copilot_default_headers, +) class GithubCopilotConfig(OpenAIConfig): @@ -45,14 +49,24 @@ class GithubCopilotConfig(OpenAIConfig): ): import litellm - disable_copilot_system_to_assistant = ( - litellm.disable_copilot_system_to_assistant - ) - if not disable_copilot_system_to_assistant: - for message in messages: - if "role" in message and message["role"] == "system": - cast(Any, message)["role"] = "assistant" - return messages + # Check if system-to-assistant conversion is disabled + if litellm.disable_copilot_system_to_assistant: + # GitHub Copilot API now supports system prompts for all models (Claude, GPT, etc.) + # No conversion needed - just return messages as-is + return messages + + # Default behavior: convert system messages to assistant for compatibility + transformed_messages = [] + for message in messages: + if message.get("role") == "system": + # Convert system message to assistant message + transformed_message = message.copy() + transformed_message["role"] = "assistant" + transformed_messages.append(transformed_message) + else: + transformed_messages.append(message) + + return transformed_messages def validate_environment( self, @@ -69,6 +83,14 @@ class GithubCopilotConfig(OpenAIConfig): headers, model, messages, optional_params, litellm_params, api_key, api_base ) + # Add Copilot-specific headers (editor-version, user-agent, etc.) + try: + copilot_api_key = self.authenticator.get_api_key() + copilot_headers = get_copilot_default_headers(copilot_api_key) + validated_headers = {**copilot_headers, **validated_headers} + except GetAPIKeyError: + pass # Will be handled later in the request flow + # Add X-Initiator header based on message roles initiator = self._determine_initiator(messages) validated_headers["X-Initiator"] = initiator @@ -87,7 +109,7 @@ class GithubCopilotConfig(OpenAIConfig): For other models, returns standard OpenAI parameters (which may include reasoning_effort for o-series models). """ from litellm.utils import supports_reasoning - + # Get base OpenAI parameters base_params = super().get_supported_openai_params(model) diff --git a/litellm/llms/groq/chat/transformation.py b/litellm/llms/groq/chat/transformation.py index a75ecd8cc7b..34ea7b03dd9 100644 --- a/litellm/llms/groq/chat/transformation.py +++ b/litellm/llms/groq/chat/transformation.py @@ -323,4 +323,12 @@ class GroqChatCompletionStreamingHandler(OpenAIChatCompletionStreamingHandler): status_code=error.get("code"), message=error.get("message"), body=error ) + # Map Groq's 'reasoning' field to LiteLLM's 'reasoning_content' field + # Groq returns delta.reasoning, but LiteLLM expects delta.reasoning_content + choices = chunk.get("choices", []) + for choice in choices: + delta = choice.get("delta", {}) + if "reasoning" in delta: + delta["reasoning_content"] = delta.pop("reasoning") + return super().chunk_parser(chunk) diff --git a/litellm/llms/hosted_vllm/chat/transformation.py b/litellm/llms/hosted_vllm/chat/transformation.py index 1d21490ea31..e955800b947 100644 --- a/litellm/llms/hosted_vllm/chat/transformation.py +++ b/litellm/llms/hosted_vllm/chat/transformation.py @@ -23,7 +23,7 @@ from ...openai.chat.gpt_transformation import OpenAIGPTConfig class HostedVLLMChatConfig(OpenAIGPTConfig): def get_supported_openai_params(self, model: str) -> List[str]: params = super().get_supported_openai_params(model) - params.append("reasoning_effort") + params.extend(["reasoning_effort", "thinking"]) return params def map_openai_params( @@ -41,6 +41,27 @@ class HostedVLLMChatConfig(OpenAIGPTConfig): _tools = _remove_strict_from_schema(_tools) if _tools is not None: non_default_params["tools"] = _tools + + # Handle thinking parameter - convert Anthropic-style to OpenAI-style reasoning_effort + # vLLM is OpenAI-compatible, so it understands reasoning_effort, not thinking + # Reference: https://github.com/BerriAI/litellm/issues/19761 + thinking = non_default_params.pop("thinking", None) + if thinking is not None and isinstance(thinking, dict): + if thinking.get("type") == "enabled": + # Only convert if reasoning_effort not already set + if "reasoning_effort" not in non_default_params: + budget_tokens = thinking.get("budget_tokens", 0) + # Map budget_tokens to reasoning_effort level + # Same logic as Anthropic adapter (translate_anthropic_thinking_to_reasoning_effort) + if budget_tokens >= 10000: + non_default_params["reasoning_effort"] = "high" + elif budget_tokens >= 5000: + non_default_params["reasoning_effort"] = "medium" + elif budget_tokens >= 2000: + non_default_params["reasoning_effort"] = "low" + else: + non_default_params["reasoning_effort"] = "minimal" + return super().map_openai_params( non_default_params, optional_params, model, drop_params ) diff --git a/litellm/llms/hosted_vllm/embedding/transformation.py b/litellm/llms/hosted_vllm/embedding/transformation.py new file mode 100644 index 00000000000..9c3e8c6c7cc --- /dev/null +++ b/litellm/llms/hosted_vllm/embedding/transformation.py @@ -0,0 +1,180 @@ +""" +Hosted VLLM Embedding API Configuration. + +This module provides the configuration for hosted VLLM's Embedding API. +VLLM is OpenAI-compatible and supports embeddings via the /v1/embeddings endpoint. + +Docs: https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html +""" + +from typing import TYPE_CHECKING, Any, List, Optional, Union + +import httpx + +from litellm.llms.base_llm.chat.transformation import BaseLLMException +from litellm.llms.base_llm.embedding.transformation import BaseEmbeddingConfig +from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import AllEmbeddingInputValues, AllMessageValues +from litellm.types.utils import EmbeddingResponse +from litellm.utils import convert_to_model_response_object + +if TYPE_CHECKING: + from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj + + LiteLLMLoggingObj = _LiteLLMLoggingObj +else: + LiteLLMLoggingObj = Any + + +class HostedVLLMEmbeddingError(BaseLLMException): + """Exception class for Hosted VLLM Embedding errors.""" + + pass + + +class HostedVLLMEmbeddingConfig(BaseEmbeddingConfig): + """ + Configuration for Hosted VLLM's Embedding API. + + Reference: https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html + """ + + def validate_environment( + self, + headers: dict, + model: str, + messages: List[AllMessageValues], + optional_params: dict, + litellm_params: dict, + api_key: Optional[str] = None, + api_base: Optional[str] = None, + ) -> dict: + """ + Validate environment and set up headers for Hosted VLLM API. + """ + if api_key is None: + api_key = get_secret_str("HOSTED_VLLM_API_KEY") or "fake-api-key" + + default_headers = { + "Content-Type": "application/json", + } + + # Only add Authorization header if api_key is not "fake-api-key" + if api_key and api_key != "fake-api-key": + default_headers["Authorization"] = f"Bearer {api_key}" + + # Merge with existing headers (user's headers take priority) + return {**default_headers, **headers} + + def get_complete_url( + self, + api_base: Optional[str], + api_key: Optional[str], + model: str, + optional_params: dict, + litellm_params: dict, + stream: Optional[bool] = None, + ) -> str: + """ + Get the complete URL for Hosted VLLM Embedding API endpoint. + """ + if api_base is None: + api_base = get_secret_str("HOSTED_VLLM_API_BASE") + if api_base is None: + raise ValueError("api_base is required for hosted_vllm embeddings") + + # Remove trailing slashes + api_base = api_base.rstrip("/") + + # Ensure the URL ends with /embeddings + if not api_base.endswith("/embeddings"): + api_base = f"{api_base}/embeddings" + + return api_base + + def transform_embedding_request( + self, + model: str, + input: AllEmbeddingInputValues, + optional_params: dict, + headers: dict, + ) -> dict: + """ + Transform embedding request to Hosted VLLM format (OpenAI-compatible). + """ + # Ensure input is a list + if isinstance(input, str): + input = [input] + + # Strip 'hosted_vllm/' prefix if present + if model.startswith("hosted_vllm/"): + model = model.replace("hosted_vllm/", "", 1) + + return { + "model": model, + "input": input, + **optional_params, + } + + def transform_embedding_response( + self, + model: str, + raw_response: httpx.Response, + model_response: EmbeddingResponse, + logging_obj: LiteLLMLoggingObj, + api_key: Optional[str], + request_data: dict, + optional_params: dict, + litellm_params: dict, + ) -> EmbeddingResponse: + """ + Transform embedding response from Hosted VLLM format (OpenAI-compatible). + """ + logging_obj.post_call(original_response=raw_response.text) + + # VLLM returns standard OpenAI-compatible embedding response + response_json = raw_response.json() + + return convert_to_model_response_object( + response_object=response_json, + model_response_object=model_response, + response_type="embedding", + ) + + def get_supported_openai_params(self, model: str) -> list: + """ + Get list of supported OpenAI parameters for Hosted VLLM embeddings. + """ + return [ + "timeout", + "dimensions", + "encoding_format", + "user", + ] + + def map_openai_params( + self, + non_default_params: dict, + optional_params: dict, + model: str, + drop_params: bool, + ) -> dict: + """ + Map OpenAI parameters to Hosted VLLM format. + """ + for param, value in non_default_params.items(): + if param in self.get_supported_openai_params(model): + optional_params[param] = value + return optional_params + + def get_error_class( + self, error_message: str, status_code: int, headers: Union[dict, httpx.Headers] + ) -> BaseLLMException: + """ + Get the error class for Hosted VLLM errors. + """ + return HostedVLLMEmbeddingError( + message=error_message, + status_code=status_code, + headers=headers, + ) diff --git a/litellm/llms/minimax/chat/transformation.py b/litellm/llms/minimax/chat/transformation.py index ed80ff8aed1..3e9dc0209f2 100644 --- a/litellm/llms/minimax/chat/transformation.py +++ b/litellm/llms/minimax/chat/transformation.py @@ -1,11 +1,12 @@ """ MiniMax OpenAI transformation config - extends OpenAI chat config for MiniMax's OpenAI-compatible API """ -from typing import Optional +from typing import List, Optional, Tuple import litellm from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import AllMessageValues, ChatCompletionToolParam class MinimaxChatConfig(OpenAIGPTConfig): @@ -73,11 +74,33 @@ class MinimaxChatConfig(OpenAIGPTConfig): else: return f"{base_url}/v1/chat/completions" + def remove_cache_control_flag_from_messages_and_tools( + self, + model: str, + messages: List[AllMessageValues], + tools: Optional[List[ChatCompletionToolParam]] = None, + ) -> Tuple[List[AllMessageValues], Optional[List[ChatCompletionToolParam]]]: + """ + Override to preserve cache_control for MiniMax. + MiniMax supports cache_control - don't strip it. + """ + # MiniMax supports cache_control, so return messages and tools unchanged + return messages, tools + def get_supported_openai_params(self, model: str) -> list: """ Get supported OpenAI parameters for MiniMax. - Adds reasoning_split to the list of supported params. + Adds reasoning_split and thinking to the list of supported params. """ base_params = super().get_supported_openai_params(model=model) - return base_params + ["reasoning_split"] + additional_params = ["reasoning_split"] + + # Add thinking parameter if model supports reasoning + try: + if litellm.supports_reasoning(model=model, custom_llm_provider="minimax"): + additional_params.append("thinking") + except Exception: + pass + + return base_params + additional_params diff --git a/litellm/llms/oci/chat/transformation.py b/litellm/llms/oci/chat/transformation.py index 7af7be2094a..84f39ef2525 100644 --- a/litellm/llms/oci/chat/transformation.py +++ b/litellm/llms/oci/chat/transformation.py @@ -32,6 +32,7 @@ from litellm.types.llms.oci import ( OCICompletionResponse, OCIContentPartUnion, OCIImageContentPart, + OCIImageUrl, OCIMessage, OCIRoles, OCIServingMode, @@ -1129,7 +1130,7 @@ def adapt_messages_to_generic_oci_standard_content_message( image_url = image_url.get("url") if not isinstance(image_url, str): raise Exception("Prop `image_url` must be a string or an object with a `url` property") - new_content.append(OCIImageContentPart(imageUrl=image_url)) + new_content.append(OCIImageContentPart(imageUrl=OCIImageUrl(url=image_url))) return OCIMessage( role=open_ai_to_generic_oci_role_map[role], diff --git a/litellm/llms/openai/chat/gpt_5_transformation.py b/litellm/llms/openai/chat/gpt_5_transformation.py index 3fffa335fdc..05c003c8b7a 100644 --- a/litellm/llms/openai/chat/gpt_5_transformation.py +++ b/litellm/llms/openai/chat/gpt_5_transformation.py @@ -19,7 +19,9 @@ class OpenAIGPT5Config(OpenAIGPTConfig): @classmethod def is_model_gpt_5_model(cls, model: str) -> bool: - return "gpt-5" in model + # gpt-5-chat* behaves like a regular chat model (supports temperature, etc.) + # Don't route it through GPT-5 reasoning-specific parameter restrictions. + return "gpt-5" in model and "gpt-5-chat" not in model @classmethod def is_model_gpt_5_codex_model(cls, model: str) -> bool: diff --git a/litellm/llms/openai/chat/guardrail_translation/handler.py b/litellm/llms/openai/chat/guardrail_translation/handler.py index d0ed3f165cc..c406f502b45 100644 --- a/litellm/llms/openai/chat/guardrail_translation/handler.py +++ b/litellm/llms/openai/chat/guardrail_translation/handler.py @@ -21,7 +21,13 @@ from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation from litellm.main import stream_chunk_builder from litellm.types.llms.openai import ChatCompletionToolParam -from litellm.types.utils import Choices, GenericGuardrailAPIInputs, ModelResponse, ModelResponseStream, StreamingChoices +from litellm.types.utils import ( + Choices, + GenericGuardrailAPIInputs, + ModelResponse, + ModelResponseStream, + StreamingChoices, +) if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail @@ -80,13 +86,17 @@ class OpenAIChatCompletionsHandler(BaseTranslation): if tool_calls_to_check: inputs["tool_calls"] = tool_calls_to_check # type: ignore if messages: - inputs["structured_messages"] = ( - messages # pass the openai /chat/completions messages to the guardrail, as-is - ) + inputs[ + "structured_messages" + ] = messages # pass the openai /chat/completions messages to the guardrail, as-is # Pass tools (function definitions) to the guardrail tools = data.get("tools") if tools: inputs["tools"] = tools + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, @@ -297,6 +307,9 @@ class OpenAIChatCompletionsHandler(BaseTranslation): inputs["images"] = images_to_check if tool_calls_to_check: inputs["tool_calls"] = tool_calls_to_check # type: ignore + # Include model information from the response if available + if hasattr(response, "model") and response.model: + inputs["model"] = response.model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, @@ -355,14 +368,17 @@ class OpenAIChatCompletionsHandler(BaseTranslation): # check if the stream has ended has_stream_ended = False for chunk in responses_so_far: - if chunk.choices[0].finish_reason is not None: + if chunk.choices and chunk.choices[0].finish_reason is not None: has_stream_ended = True break if has_stream_ended: # convert to model response model_response = cast( - ModelResponse, stream_chunk_builder(chunks=responses_so_far, logging_obj=litellm_logging_obj) + ModelResponse, + stream_chunk_builder( + chunks=responses_so_far, logging_obj=litellm_logging_obj + ), ) # run process_output_response await self.process_output_response( @@ -417,6 +433,13 @@ class OpenAIChatCompletionsHandler(BaseTranslation): inputs = GenericGuardrailAPIInputs(texts=texts_to_check) if images_to_check: inputs["images"] = images_to_check + # Include model information from the first response if available + if ( + responses_so_far + and hasattr(responses_so_far[0], "model") + and responses_so_far[0].model + ): + inputs["model"] = responses_so_far[0].model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, request_data=request_data, diff --git a/litellm/llms/openai/common_utils.py b/litellm/llms/openai/common_utils.py index 8bcecd35232..ce470f04aca 100644 --- a/litellm/llms/openai/common_utils.py +++ b/litellm/llms/openai/common_utils.py @@ -15,14 +15,12 @@ if TYPE_CHECKING: from aiohttp import ClientSession import litellm -from litellm._logging import verbose_logger from litellm.llms.base_llm.chat.transformation import BaseLLMException from litellm.llms.custom_httpx.http_handler import ( _DEFAULT_TTL_FOR_HTTPX_CLIENTS, AsyncHTTPHandler, get_ssl_configuration, ) -from litellm.types.utils import LlmProviders class OpenAIError(BaseLLMException): @@ -205,67 +203,30 @@ class BaseOpenAILLM: if litellm.aclient_session is not None: return litellm.aclient_session - # Use the global cached client system to prevent memory leaks (issue #14540) - # This routes through get_async_httpx_client() which provides TTL-based caching - from litellm.llms.custom_httpx.http_handler import get_async_httpx_client + # Get unified SSL configuration + ssl_config = get_ssl_configuration() - try: - # Get SSL config and include in params for proper cache key - ssl_config = get_ssl_configuration() - params = {"ssl_verify": ssl_config} if ssl_config is not None else {} - params["disable_aiohttp_transport"] = litellm.disable_aiohttp_transport - - # Get a cached AsyncHTTPHandler which manages the httpx.AsyncClient - cached_handler = get_async_httpx_client( - llm_provider=LlmProviders.OPENAI, # Cache key includes provider - params=params, # Include SSL config in cache key + return httpx.AsyncClient( + verify=ssl_config, + transport=AsyncHTTPHandler._create_async_transport( + ssl_context=ssl_config + if isinstance(ssl_config, ssl.SSLContext) + else None, + ssl_verify=ssl_config if isinstance(ssl_config, bool) else None, shared_session=shared_session, - ) - # Return the underlying httpx client from the handler - return cached_handler.client - except (ImportError, AttributeError, KeyError) as e: - # Fallback to creating a client directly if caching system unavailable - # This preserves backwards compatibility - verbose_logger.debug( - f"Client caching unavailable ({type(e).__name__}), using direct client creation" - ) - ssl_config = get_ssl_configuration() - return httpx.AsyncClient( - verify=ssl_config, - transport=AsyncHTTPHandler._create_async_transport( - ssl_context=ssl_config - if isinstance(ssl_config, ssl.SSLContext) - else None, - ssl_verify=ssl_config if isinstance(ssl_config, bool) else None, - shared_session=shared_session, - ), - follow_redirects=True, - ) + ), + follow_redirects=True, + ) @staticmethod def _get_sync_http_client() -> Optional[httpx.Client]: if litellm.client_session is not None: return litellm.client_session - # Use the global cached client system to prevent memory leaks (issue #14540) - from litellm.llms.custom_httpx.http_handler import _get_httpx_client + # Get unified SSL configuration + ssl_config = get_ssl_configuration() - try: - # Get SSL config and include in params for proper cache key - ssl_config = get_ssl_configuration() - params = {"ssl_verify": ssl_config} if ssl_config is not None else None - - # Get a cached HTTPHandler which manages the httpx.Client - cached_handler = _get_httpx_client(params=params) - # Return the underlying httpx client from the handler - return cached_handler.client - except (ImportError, AttributeError, KeyError) as e: - # Fallback to creating a client directly if caching system unavailable - verbose_logger.debug( - f"Client caching unavailable ({type(e).__name__}), using direct client creation" - ) - ssl_config = get_ssl_configuration() - return httpx.Client( - verify=ssl_config, - follow_redirects=True, - ) + return httpx.Client( + verify=ssl_config, + follow_redirects=True, + ) diff --git a/litellm/llms/openai/completion/guardrail_translation/handler.py b/litellm/llms/openai/completion/guardrail_translation/handler.py index 73d08cfead4..1f8c6159da0 100644 --- a/litellm/llms/openai/completion/guardrail_translation/handler.py +++ b/litellm/llms/openai/completion/guardrail_translation/handler.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Optional from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation +from litellm.types.utils import GenericGuardrailAPIInputs if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail @@ -53,8 +54,13 @@ class OpenAITextCompletionHandler(BaseTranslation): if isinstance(prompt, str): # Single string prompt + inputs = GenericGuardrailAPIInputs(texts=[prompt]) + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [prompt]}, + inputs=inputs, request_data=data, input_type="request", logging_obj=litellm_logging_obj, @@ -80,8 +86,13 @@ class OpenAITextCompletionHandler(BaseTranslation): text_indices.append(idx) if texts_to_check: + inputs = GenericGuardrailAPIInputs(texts=texts_to_check) + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": texts_to_check}, + inputs=inputs, request_data=data, input_type="request", logging_obj=litellm_logging_obj, @@ -154,8 +165,12 @@ class OpenAITextCompletionHandler(BaseTranslation): if user_metadata: request_data["litellm_metadata"] = user_metadata + inputs = GenericGuardrailAPIInputs(texts=texts_to_check) + # Include model information from the response if available + if hasattr(response, "model") and response.model: + inputs["model"] = response.model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": texts_to_check}, + inputs=inputs, request_data=request_data, input_type="response", logging_obj=litellm_logging_obj, diff --git a/litellm/llms/openai/image_generation/cost_calculator.py b/litellm/llms/openai/image_generation/cost_calculator.py index 35caaf6e9b1..988d5626134 100644 --- a/litellm/llms/openai/image_generation/cost_calculator.py +++ b/litellm/llms/openai/image_generation/cost_calculator.py @@ -8,8 +8,7 @@ from typing import Optional from litellm import verbose_logger from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_token -from litellm.responses.utils import ResponseAPILoggingUtils -from litellm.types.utils import ImageResponse +from litellm.types.utils import ImageResponse, Usage def cost_calculator( @@ -39,11 +38,18 @@ def cost_calculator( ) return 0.0 - # Transform ImageUsage to Usage using the existing helper - # ImageUsage has the same format as ResponseAPIUsage - chat_usage = ResponseAPILoggingUtils._transform_response_api_usage_to_chat_usage( - usage - ) + # If usage is already a Usage object with completion_tokens_details set, + # use it directly (it was already transformed in convert_to_image_response) + if isinstance(usage, Usage) and usage.completion_tokens_details is not None: + chat_usage = usage + else: + # Transform ImageUsage to Usage using the existing helper + # ImageUsage has the same format as ResponseAPIUsage + from litellm.responses.utils import ResponseAPILoggingUtils + + chat_usage = ResponseAPILoggingUtils._transform_response_api_usage_to_chat_usage( + usage + ) # Use generic_cost_per_token for cost calculation prompt_cost, completion_cost = generic_cost_per_token( diff --git a/litellm/llms/openai/image_generation/guardrail_translation/handler.py b/litellm/llms/openai/image_generation/guardrail_translation/handler.py index 842a64b1878..e6340ba4705 100644 --- a/litellm/llms/openai/image_generation/guardrail_translation/handler.py +++ b/litellm/llms/openai/image_generation/guardrail_translation/handler.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Optional from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation +from litellm.types.utils import GenericGuardrailAPIInputs if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail @@ -52,8 +53,13 @@ class OpenAIImageGenerationHandler(BaseTranslation): # Apply guardrail to the prompt if isinstance(prompt, str): + inputs = GenericGuardrailAPIInputs(texts=[prompt]) + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [prompt]}, + inputs=inputs, request_data=data, input_type="request", logging_obj=litellm_logging_obj, diff --git a/litellm/llms/openai/openai.py b/litellm/llms/openai/openai.py index 4d623097478..8a8070240da 100644 --- a/litellm/llms/openai/openai.py +++ b/litellm/llms/openai/openai.py @@ -1923,10 +1923,10 @@ class OpenAIBatchesAPI(BaseLLM): self, cancel_batch_data: CancelBatchRequest, openai_client: AsyncOpenAI, - ) -> Batch: + ) -> LiteLLMBatch: verbose_logger.debug("async cancelling batch, args= %s", cancel_batch_data) response = await openai_client.batches.cancel(**cancel_batch_data) - return response + return LiteLLMBatch(**response.model_dump()) def cancel_batch( self, @@ -1962,8 +1962,13 @@ class OpenAIBatchesAPI(BaseLLM): cancel_batch_data=cancel_batch_data, openai_client=openai_client ) + # At this point, openai_client is guaranteed to be a sync OpenAI client + if not isinstance(openai_client, OpenAI): + raise ValueError( + "OpenAI client is not an instance of OpenAI. Make sure you passed a sync OpenAI client." + ) response = openai_client.batches.cancel(**cancel_batch_data) - return response + return LiteLLMBatch(**response.model_dump()) async def alist_batches( self, diff --git a/litellm/llms/openai/realtime/handler.py b/litellm/llms/openai/realtime/handler.py index fd04ac4d458..ef9cc43c3e1 100644 --- a/litellm/llms/openai/realtime/handler.py +++ b/litellm/llms/openai/realtime/handler.py @@ -16,6 +16,62 @@ from ..openai import OpenAIChatCompletion class OpenAIRealtime(OpenAIChatCompletion): + """ + Base handler for OpenAI-compatible realtime WebSocket connections. + + Subclasses can override template methods to customize: + - _get_default_api_base(): Default API base URL + - _get_additional_headers(): Extra headers beyond Authorization + - _get_ssl_config(): SSL configuration for WebSocket connection + """ + + def _get_default_api_base(self) -> str: + """ + Get the default API base URL for this provider. + Override this in subclasses to set provider-specific defaults. + """ + return "https://api.openai.com/" + + def _get_additional_headers(self, api_key: str) -> dict: + """ + Get additional headers beyond Authorization. + Override this in subclasses to customize headers (e.g., remove OpenAI-Beta). + + Args: + api_key: API key for authentication + + Returns: + Dictionary of additional headers + """ + return { + "Authorization": f"Bearer {api_key}", + "OpenAI-Beta": "realtime=v1", + } + + def _get_ssl_config(self, url: str) -> Any: + """ + Get SSL configuration for WebSocket connection. + Override this in subclasses to customize SSL behavior. + + Args: + url: WebSocket URL (ws:// or wss://) + + Returns: + SSL configuration (None, True, or SSLContext) + """ + if url.startswith("ws://"): + return None + + # Use the shared SSL context which respects custom CA certs and SSL settings + ssl_config = get_shared_realtime_ssl_context() + + # If ssl_config is False (ssl_verify=False), websockets library needs True instead + # to establish connection without verification (False would fail) + if ssl_config is False: + return True + + return ssl_config + def _construct_url(self, api_base: str, query_params: RealtimeQueryParams) -> str: """ Construct the backend websocket URL with all query parameters (including 'model'). @@ -45,8 +101,9 @@ class OpenAIRealtime(OpenAIChatCompletion): ): import websockets from websockets.asyncio.client import ClientConnection + if api_base is None: - api_base = "https://api.openai.com/" + api_base = self._get_default_api_base() if api_key is None: raise ValueError("api_key is required for OpenAI realtime calls") @@ -56,30 +113,27 @@ class OpenAIRealtime(OpenAIChatCompletion): url = self._construct_url(api_base, query_params) try: - # Only use SSL context for secure websocket connections (wss://) - # websockets library doesn't accept ssl argument for ws:// URIs - ssl_context = None if url.startswith("ws://") else get_shared_realtime_ssl_context() + # Get provider-specific SSL configuration + ssl_config = self._get_ssl_config(url) + + # Get provider-specific headers + headers = self._get_additional_headers(api_key) + # Log a masked request preview consistent with other endpoints. logging_obj.pre_call( input=None, api_key=api_key, additional_args={ "api_base": url, - "headers": { - "Authorization": f"Bearer {api_key}", - "OpenAI-Beta": "realtime=v1", - }, + "headers": headers, "complete_input_dict": {"query_params": query_params}, }, ) async with websockets.connect( # type: ignore url, - additional_headers={ - "Authorization": f"Bearer {api_key}", # type: ignore - "OpenAI-Beta": "realtime=v1", - }, + additional_headers=headers, # type: ignore max_size=REALTIME_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES, - ssl=ssl_context, + ssl=ssl_config, ) as backend_ws: realtime_streaming = RealTimeStreaming( websocket, cast(ClientConnection, backend_ws), logging_obj diff --git a/litellm/llms/openai/responses/guardrail_translation/handler.py b/litellm/llms/openai/responses/guardrail_translation/handler.py index 9b8f15c7623..ad3d4c932d4 100644 --- a/litellm/llms/openai/responses/guardrail_translation/handler.py +++ b/litellm/llms/openai/responses/guardrail_translation/handler.py @@ -105,6 +105,10 @@ class OpenAIResponsesHandler(BaseTranslation): inputs["tools"] = tools_to_check if structured_messages: inputs["structured_messages"] = structured_messages # type: ignore + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, @@ -150,6 +154,10 @@ class OpenAIResponsesHandler(BaseTranslation): inputs["tools"] = tools_to_check if structured_messages: inputs["structured_messages"] = structured_messages # type: ignore + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, request_data=data, @@ -311,9 +319,7 @@ class OpenAIResponsesHandler(BaseTranslation): return response if not response_output: - verbose_proxy_logger.debug( - "OpenAI Responses API: Empty output in response" - ) + verbose_proxy_logger.debug("OpenAI Responses API: Empty output in response") return response # Step 1: Extract all text content and tool calls from response output @@ -344,6 +350,14 @@ class OpenAIResponsesHandler(BaseTranslation): inputs["images"] = images_to_check if tool_calls_to_check: inputs["tool_calls"] = tool_calls_to_check + # Include model information from the response if available + response_model = None + if isinstance(response, dict): + response_model = response.get("model") + elif hasattr(response, "model"): + response_model = getattr(response, "model", None) + if response_model: + inputs["model"] = response_model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, @@ -388,12 +402,15 @@ class OpenAIResponsesHandler(BaseTranslation): tool_calls = model_response_stream.choices[0].delta.tool_calls if tool_calls: + inputs = GenericGuardrailAPIInputs() + inputs["tool_calls"] = cast( + List[ChatCompletionToolCallChunk], tool_calls + ) + # Include model information if available + if hasattr(model_response_stream, "model") and model_response_stream.model: + inputs["model"] = model_response_stream.model _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={ - "tool_calls": cast( - List[ChatCompletionToolCallChunk], tool_calls - ) - }, + inputs=inputs, request_data={}, input_type="response", logging_obj=litellm_logging_obj, @@ -408,29 +425,42 @@ class OpenAIResponsesHandler(BaseTranslation): handle_raw_dict_callback=None, ) - tool_calls = model_response_choices[0].message.tool_calls - text = model_response_choices[0].message.content - guardrail_inputs = GenericGuardrailAPIInputs() - if text: - guardrail_inputs["texts"] = [text] - if tool_calls: - guardrail_inputs["tool_calls"] = cast( - List[ChatCompletionToolCallChunk], tool_calls - ) - if tool_calls: - _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs=guardrail_inputs, - request_data={}, - input_type="response", - logging_obj=litellm_logging_obj, - ) - return responses_so_far + if model_response_choices: + tool_calls = model_response_choices[0].message.tool_calls + text = model_response_choices[0].message.content + guardrail_inputs = GenericGuardrailAPIInputs() + if text: + guardrail_inputs["texts"] = [text] + if tool_calls: + guardrail_inputs["tool_calls"] = cast( + List[ChatCompletionToolCallChunk], tool_calls + ) + # Include model information from the response if available + response_model = final_chunk.get("response", {}).get("model") + if response_model: + guardrail_inputs["model"] = response_model + if tool_calls or text: + _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( + inputs=guardrail_inputs, + request_data={}, + input_type="response", + logging_obj=litellm_logging_obj, + ) + return responses_so_far + else: + verbose_proxy_logger.debug("Skipping output guardrail - model response has no choices") # model_response_stream = OpenAiResponsesToChatCompletionStreamIterator.translate_responses_chunk_to_openai_stream(final_chunk) # tool_calls = model_response_stream.choices[0].tool_calls # convert openai response to model response string_so_far = self.get_streaming_string_so_far(responses_so_far) + inputs = GenericGuardrailAPIInputs(texts=[string_so_far]) + # Try to get model from the final chunk if available + if isinstance(final_chunk, dict): + response_model = final_chunk.get("response", {}).get("model") if isinstance(final_chunk.get("response"), dict) else None + if response_model: + inputs["model"] = response_model _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [string_so_far]}, + inputs=inputs, request_data={}, input_type="response", logging_obj=litellm_logging_obj, @@ -484,11 +514,9 @@ class OpenAIResponsesHandler(BaseTranslation): # Check if it's an OutputText with text if isinstance(content_item, OutputText): if content_item.text: - return True elif isinstance(content_item, dict): if content_item.get("text"): - return True return False diff --git a/litellm/llms/openai/speech/guardrail_translation/handler.py b/litellm/llms/openai/speech/guardrail_translation/handler.py index 4c2f71477be..e6796fbac2a 100644 --- a/litellm/llms/openai/speech/guardrail_translation/handler.py +++ b/litellm/llms/openai/speech/guardrail_translation/handler.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Optional from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation +from litellm.types.utils import GenericGuardrailAPIInputs if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail @@ -50,8 +51,13 @@ class OpenAITextToSpeechHandler(BaseTranslation): return data if isinstance(input_text, str): + inputs = GenericGuardrailAPIInputs(texts=[input_text]) + # Include model information if available (voice model) + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [input_text]}, + inputs=inputs, request_data=data, input_type="request", logging_obj=litellm_logging_obj, diff --git a/litellm/llms/openai/transcriptions/guardrail_translation/handler.py b/litellm/llms/openai/transcriptions/guardrail_translation/handler.py index ac416f42c81..3d76a21c389 100644 --- a/litellm/llms/openai/transcriptions/guardrail_translation/handler.py +++ b/litellm/llms/openai/transcriptions/guardrail_translation/handler.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Optional from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation +from litellm.types.utils import GenericGuardrailAPIInputs if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail @@ -88,8 +89,12 @@ class OpenAIAudioTranscriptionHandler(BaseTranslation): if user_metadata: request_data["litellm_metadata"] = user_metadata + inputs = GenericGuardrailAPIInputs(texts=[original_text]) + # Include model information from the response if available + if hasattr(response, "model") and response.model: + inputs["model"] = response.model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [original_text]}, + inputs=inputs, request_data=request_data, input_type="response", logging_obj=litellm_logging_obj, diff --git a/litellm/llms/openai_like/embedding/handler.py b/litellm/llms/openai_like/embedding/handler.py index 95a4aa854ad..d0d26d5959f 100644 --- a/litellm/llms/openai_like/embedding/handler.py +++ b/litellm/llms/openai_like/embedding/handler.py @@ -105,7 +105,8 @@ class OpenAILikeEmbeddingHandler(OpenAILikeBase): custom_endpoint=custom_endpoint, ) model = model - data = {"model": model, "input": input, **optional_params} + filtered_optional_params = {k: v for k, v in optional_params.items() if v not in (None, '')} + data = {"model": model, "input": input, **filtered_optional_params} ## LOGGING logging_obj.pre_call( diff --git a/litellm/llms/openrouter/chat/transformation.py b/litellm/llms/openrouter/chat/transformation.py index b5610852fd2..e3770dbbf49 100644 --- a/litellm/llms/openrouter/chat/transformation.py +++ b/litellm/llms/openrouter/chat/transformation.py @@ -26,6 +26,9 @@ class CacheControlSupportedModels(str, Enum): """Models that support cache_control in content blocks.""" CLAUDE = "claude" GEMINI = "gemini" + MINIMAX = "minimax" + GLM = "glm" + ZAI = "z-ai" class OpenrouterConfig(OpenAIGPTConfig): @@ -39,6 +42,7 @@ class OpenrouterConfig(OpenAIGPTConfig): model=model, custom_llm_provider="openrouter" ) or litellm.supports_reasoning(model=model): supported_params.append("reasoning_effort") + supported_params.append("thinking") except Exception: pass return list(dict.fromkeys(supported_params)) diff --git a/litellm/llms/pass_through/guardrail_translation/handler.py b/litellm/llms/pass_through/guardrail_translation/handler.py index c0979e37e66..40433d53413 100644 --- a/litellm/llms/pass_through/guardrail_translation/handler.py +++ b/litellm/llms/pass_through/guardrail_translation/handler.py @@ -11,6 +11,7 @@ from typing import TYPE_CHECKING, Any, List, Optional from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation from litellm.proxy._types import PassThroughGuardrailSettings +from litellm.types.utils import GenericGuardrailAPIInputs if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail @@ -118,8 +119,13 @@ class PassThroughEndpointHandler(BaseTranslation): return data # Apply guardrail (pass-through doesn't modify the text, just checks it) + inputs = GenericGuardrailAPIInputs(texts=[text_to_check]) + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [text_to_check]}, + inputs=inputs, request_data=data, input_type="request", logging_obj=litellm_logging_obj, @@ -178,8 +184,13 @@ class PassThroughEndpointHandler(BaseTranslation): request_data["litellm_metadata"] = user_metadata # Apply guardrail (pass-through doesn't modify the text, just checks it) + inputs = GenericGuardrailAPIInputs(texts=[text_to_check]) + # Include model information from the response if available + response_model = response.get("model") if isinstance(response, dict) else None + if response_model: + inputs["model"] = response_model _guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs={"texts": [text_to_check]}, + inputs=inputs, request_data=request_data, input_type="response", logging_obj=litellm_logging_obj, diff --git a/litellm/llms/s3_vectors/__init__.py b/litellm/llms/s3_vectors/__init__.py new file mode 100644 index 00000000000..e8367949c3e --- /dev/null +++ b/litellm/llms/s3_vectors/__init__.py @@ -0,0 +1 @@ +# S3 Vectors LLM integration diff --git a/litellm/llms/s3_vectors/vector_stores/__init__.py b/litellm/llms/s3_vectors/vector_stores/__init__.py new file mode 100644 index 00000000000..ac24b4a38da --- /dev/null +++ b/litellm/llms/s3_vectors/vector_stores/__init__.py @@ -0,0 +1 @@ +# S3 Vectors vector store integration diff --git a/litellm/llms/s3_vectors/vector_stores/transformation.py b/litellm/llms/s3_vectors/vector_stores/transformation.py new file mode 100644 index 00000000000..df81a78289a --- /dev/null +++ b/litellm/llms/s3_vectors/vector_stores/transformation.py @@ -0,0 +1,254 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union + +import httpx + +from litellm.llms.base_llm.vector_store.transformation import BaseVectorStoreConfig +from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM +from litellm.types.router import GenericLiteLLMParams +from litellm.types.vector_stores import ( + VECTOR_STORE_OPENAI_PARAMS, + BaseVectorStoreAuthCredentials, + VectorStoreIndexEndpoints, + VectorStoreResultContent, + VectorStoreSearchOptionalRequestParams, + VectorStoreSearchResponse, + VectorStoreSearchResult, +) + +if TYPE_CHECKING: + from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj +else: + LiteLLMLoggingObj = Any + + +class S3VectorsVectorStoreConfig(BaseVectorStoreConfig, BaseAWSLLM): + """Vector store configuration for AWS S3 Vectors.""" + + def __init__(self) -> None: + BaseVectorStoreConfig.__init__(self) + BaseAWSLLM.__init__(self) + + def get_auth_credentials( + self, litellm_params: dict + ) -> BaseVectorStoreAuthCredentials: + return {} + + def get_vector_store_endpoints_by_type(self) -> VectorStoreIndexEndpoints: + return { + "read": [("POST", "/QueryVectors")], + "write": [], + } + + def get_supported_openai_params( + self, model: str + ) -> List[VECTOR_STORE_OPENAI_PARAMS]: + return ["max_num_results"] + + def map_openai_params( + self, + non_default_params: dict, + optional_params: dict, + drop_params: bool, + ) -> dict: + for param, value in non_default_params.items(): + if param == "max_num_results": + optional_params["maxResults"] = value + return optional_params + + def validate_environment( + self, headers: dict, litellm_params: Optional[GenericLiteLLMParams] + ) -> dict: + headers = headers or {} + headers.setdefault("Content-Type", "application/json") + return headers + + def get_complete_url(self, api_base: Optional[str], litellm_params: dict) -> str: + aws_region_name = litellm_params.get("aws_region_name") + if not aws_region_name: + raise ValueError("aws_region_name is required for S3 Vectors") + return f"https://s3vectors.{aws_region_name}.api.aws" + + def transform_search_vector_store_request( + self, + vector_store_id: str, + query: Union[str, List[str]], + vector_store_search_optional_params: VectorStoreSearchOptionalRequestParams, + api_base: str, + litellm_logging_obj: LiteLLMLoggingObj, + litellm_params: dict, + ) -> Tuple[str, Dict]: + """Sync version - generates embedding synchronously.""" + # For S3 Vectors, vector_store_id should be in format: bucket_name:index_name + # If not in that format, try to construct it from litellm_params + bucket_name: str + index_name: str + + if ":" in vector_store_id: + bucket_name, index_name = vector_store_id.split(":", 1) + else: + # Try to get bucket_name from litellm_params + bucket_name_from_params = litellm_params.get("vector_bucket_name") + if not bucket_name_from_params or not isinstance(bucket_name_from_params, str): + raise ValueError( + "vector_store_id must be in format 'bucket_name:index_name' for S3 Vectors, " + "or vector_bucket_name must be provided in litellm_params" + ) + bucket_name = bucket_name_from_params + index_name = vector_store_id + + if isinstance(query, list): + query = " ".join(query) + + # Generate embedding for the query + embedding_model = litellm_params.get("embedding_model", "text-embedding-3-small") + + import litellm as litellm_module + embedding_response = litellm_module.embedding(model=embedding_model, input=[query]) + query_embedding = embedding_response.data[0]["embedding"] + + url = f"{api_base}/QueryVectors" + + request_body: Dict[str, Any] = { + "vectorBucketName": bucket_name, + "indexName": index_name, + "queryVector": {"float32": query_embedding}, + "topK": vector_store_search_optional_params.get("max_num_results", 5), # Default to 5 + "returnDistance": True, + "returnMetadata": True, + } + + litellm_logging_obj.model_call_details["query"] = query + return url, request_body + + async def atransform_search_vector_store_request( + self, + vector_store_id: str, + query: Union[str, List[str]], + vector_store_search_optional_params: VectorStoreSearchOptionalRequestParams, + api_base: str, + litellm_logging_obj: LiteLLMLoggingObj, + litellm_params: dict, + ) -> Tuple[str, Dict]: + """Async version - generates embedding asynchronously.""" + # For S3 Vectors, vector_store_id should be in format: bucket_name:index_name + # If not in that format, try to construct it from litellm_params + bucket_name: str + index_name: str + + if ":" in vector_store_id: + bucket_name, index_name = vector_store_id.split(":", 1) + else: + # Try to get bucket_name from litellm_params + bucket_name_from_params = litellm_params.get("vector_bucket_name") + if not bucket_name_from_params or not isinstance(bucket_name_from_params, str): + raise ValueError( + "vector_store_id must be in format 'bucket_name:index_name' for S3 Vectors, " + "or vector_bucket_name must be provided in litellm_params" + ) + bucket_name = bucket_name_from_params + index_name = vector_store_id + + if isinstance(query, list): + query = " ".join(query) + + # Generate embedding for the query asynchronously + embedding_model = litellm_params.get("embedding_model", "text-embedding-3-small") + + import litellm as litellm_module + embedding_response = await litellm_module.aembedding(model=embedding_model, input=[query]) + query_embedding = embedding_response.data[0]["embedding"] + + url = f"{api_base}/QueryVectors" + + request_body: Dict[str, Any] = { + "vectorBucketName": bucket_name, + "indexName": index_name, + "queryVector": {"float32": query_embedding}, + "topK": vector_store_search_optional_params.get("max_num_results", 5), # Default to 5 + "returnDistance": True, + "returnMetadata": True, + } + + litellm_logging_obj.model_call_details["query"] = query + return url, request_body + + def sign_request( + self, + headers: dict, + optional_params: Dict, + request_data: Dict, + api_base: str, + api_key: Optional[str] = None, + ) -> Tuple[dict, Optional[bytes]]: + return self._sign_request( + service_name="s3vectors", + headers=headers, + optional_params=optional_params, + request_data=request_data, + api_base=api_base, + api_key=api_key, + ) + + def transform_search_vector_store_response( + self, response: httpx.Response, litellm_logging_obj: LiteLLMLoggingObj + ) -> VectorStoreSearchResponse: + try: + response_data = response.json() + results: List[VectorStoreSearchResult] = [] + + for item in response_data.get("vectors", []) or []: + metadata = item.get("metadata", {}) or {} + source_text = metadata.get("source_text", "") + + if not source_text: + continue + + # Extract file information from metadata + chunk_index = metadata.get("chunk_index", "0") + file_id = f"s3-vectors-chunk-{chunk_index}" + filename = metadata.get("filename", f"document-{chunk_index}") + + # S3 Vectors returns distance, convert to similarity score (0-1) + # Lower distance = higher similarity + # We'll normalize using 1 / (1 + distance) to get a 0-1 score + distance = item.get("distance") + score = None + if distance is not None: + # Convert distance to similarity score between 0 and 1 + # For cosine distance: similarity = 1 - distance + # For euclidean: use 1 / (1 + distance) + # Assuming cosine distance here + score = max(0.0, min(1.0, 1.0 - float(distance))) + + results.append( + VectorStoreSearchResult( + score=score, + content=[VectorStoreResultContent(text=source_text, type="text")], + file_id=file_id, + filename=filename, + attributes=metadata, + ) + ) + + return VectorStoreSearchResponse( + object="vector_store.search_results.page", + search_query=litellm_logging_obj.model_call_details.get("query", ""), + data=results, + ) + except Exception as e: + raise self.get_error_class( + error_message=str(e), + status_code=response.status_code, + headers=response.headers, + ) + + # Vector store creation is not yet implemented + def transform_create_vector_store_request( + self, + vector_store_create_optional_params, + api_base: str, + ) -> Tuple[str, Dict]: + raise NotImplementedError + + def transform_create_vector_store_response(self, response: httpx.Response): + raise NotImplementedError diff --git a/litellm/llms/vercel_ai_gateway/embedding/__init__.py b/litellm/llms/vercel_ai_gateway/embedding/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/litellm/llms/vercel_ai_gateway/embedding/transformation.py b/litellm/llms/vercel_ai_gateway/embedding/transformation.py new file mode 100644 index 00000000000..7238b05f10d --- /dev/null +++ b/litellm/llms/vercel_ai_gateway/embedding/transformation.py @@ -0,0 +1,176 @@ +""" +Vercel AI Gateway Embedding API Configuration. + +This module provides the configuration for Vercel AI Gateway's Embedding API. +Vercel AI Gateway is OpenAI-compatible and supports embeddings via the /v1/embeddings endpoint. + +Docs: https://vercel.com/docs/ai-gateway/openai-compat/embeddings +""" + +from typing import TYPE_CHECKING, Any, Optional + +import httpx + +from litellm.llms.base_llm.embedding.transformation import BaseEmbeddingConfig +from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import AllEmbeddingInputValues +from litellm.types.utils import EmbeddingResponse +from litellm.utils import convert_to_model_response_object + +from ..common_utils import VercelAIGatewayException + +if TYPE_CHECKING: + from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj + + LiteLLMLoggingObj = _LiteLLMLoggingObj +else: + LiteLLMLoggingObj = Any + + +class VercelAIGatewayEmbeddingConfig(BaseEmbeddingConfig): + """ + Configuration for Vercel AI Gateway's Embedding API. + + Reference: https://vercel.com/docs/ai-gateway/openai-compat/embeddings + """ + + def validate_environment( + self, + headers: dict, + model: str, + messages: list, + optional_params: dict, + litellm_params: dict, + api_key: Optional[str] = None, + api_base: Optional[str] = None, + ) -> dict: + """ + Validate environment and set up headers for Vercel AI Gateway API. + + Vercel AI Gateway requires: + - Authorization header with Bearer token (API key or OIDC token) + """ + vercel_headers = { + "Content-Type": "application/json", + } + + # Add Authorization header if api_key is provided + if api_key: + vercel_headers["Authorization"] = f"Bearer {api_key}" + + # Merge with existing headers (user's extra_headers take priority) + merged_headers = {**vercel_headers, **headers} + + return merged_headers + + def get_complete_url( + self, + api_base: Optional[str], + api_key: Optional[str], + model: str, + optional_params: dict, + litellm_params: dict, + stream: Optional[bool] = None, + ) -> str: + """ + Get the complete URL for Vercel AI Gateway Embedding API endpoint. + """ + if api_base: + api_base = api_base.rstrip("/") + else: + api_base = ( + get_secret_str("VERCEL_AI_GATEWAY_API_BASE") + or "https://ai-gateway.vercel.sh/v1" + ) + + return f"{api_base}/embeddings" + + def transform_embedding_request( + self, + model: str, + input: AllEmbeddingInputValues, + optional_params: dict, + headers: dict, + ) -> dict: + """ + Transform embedding request to Vercel AI Gateway format (OpenAI-compatible). + """ + # Ensure input is a list + if isinstance(input, str): + input = [input] + + # Strip 'vercel_ai_gateway/' prefix if present + if model.startswith("vercel_ai_gateway/"): + model = model.replace("vercel_ai_gateway/", "", 1) + + return { + "model": model, + "input": input, + **optional_params, + } + + def transform_embedding_response( + self, + model: str, + raw_response: httpx.Response, + model_response: EmbeddingResponse, + logging_obj: LiteLLMLoggingObj, + api_key: Optional[str], + request_data: dict, + optional_params: dict, + litellm_params: dict, + ) -> EmbeddingResponse: + """ + Transform embedding response from Vercel AI Gateway format (OpenAI-compatible). + """ + logging_obj.post_call(original_response=raw_response.text) + + # Vercel AI Gateway returns standard OpenAI-compatible embedding response + response_json = raw_response.json() + + return convert_to_model_response_object( + response_object=response_json, + model_response_object=model_response, + response_type="embedding", + ) + + def get_supported_openai_params(self, model: str) -> list: + """ + Get list of supported OpenAI parameters for Vercel AI Gateway embeddings. + + Vercel AI Gateway supports the standard OpenAI embeddings parameters + and auto-maps 'dimensions' to each provider's expected field. + """ + return [ + "timeout", + "dimensions", + "encoding_format", + "user", + ] + + def map_openai_params( + self, + non_default_params: dict, + optional_params: dict, + model: str, + drop_params: bool, + ) -> dict: + """ + Map OpenAI parameters to Vercel AI Gateway format. + """ + for param, value in non_default_params.items(): + if param in self.get_supported_openai_params(model): + optional_params[param] = value + return optional_params + + def get_error_class( + self, error_message: str, status_code: int, headers: Any + ) -> Any: + """ + Get the error class for Vercel AI Gateway errors. + """ + return VercelAIGatewayException( + message=error_message, + status_code=status_code, + headers=headers, + ) diff --git a/litellm/llms/vertex_ai/common_utils.py b/litellm/llms/vertex_ai/common_utils.py index 152b99ca4db..a0e2ddf5e98 100644 --- a/litellm/llms/vertex_ai/common_utils.py +++ b/litellm/llms/vertex_ai/common_utils.py @@ -849,7 +849,7 @@ def get_vertex_model_id_from_url(url: str) -> Optional[str]: `https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}:streamGenerateContent` """ - match = re.search(r"/models/([^/:]+)", url) + match = re.search(r"/models/([^:]+)", url) return match.group(1) if match else None diff --git a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py index 289963e917a..ed4d2d6a740 100644 --- a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py +++ b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py @@ -27,6 +27,8 @@ local_cache_obj = Cache( type=LiteLLMCacheType.LOCAL ) # only used for calling 'get_cache_key' function +MAX_PAGINATION_PAGES = 100 # Reasonable upper bound for pagination + class ContextCachingEndpoints(VertexBase): """ @@ -115,7 +117,7 @@ class ContextCachingEndpoints(VertexBase): - None """ - _, url = self._get_token_and_url_context_caching( + _, base_url = self._get_token_and_url_context_caching( gemini_api_key=api_key, custom_llm_provider=custom_llm_provider, api_base=api_base, @@ -123,43 +125,63 @@ class ContextCachingEndpoints(VertexBase): vertex_location=vertex_location, vertex_auth_header=vertex_auth_header ) - try: - ## LOGGING - logging_obj.pre_call( - input="", - api_key="", - additional_args={ - "complete_input_dict": {}, - "api_base": url, - "headers": headers, - }, - ) - resp = client.get(url=url, headers=headers) - resp.raise_for_status() - except httpx.HTTPStatusError as e: - if e.response.status_code == 403: + page_token: Optional[str] = None + + # Iterate through all pages + for _ in range(MAX_PAGINATION_PAGES): + # Build URL with pagination token if present + if page_token: + separator = "&" if "?" in base_url else "?" + url = f"{base_url}{separator}pageToken={page_token}" + else: + url = base_url + + try: + ## LOGGING + logging_obj.pre_call( + input="", + api_key="", + additional_args={ + "complete_input_dict": {}, + "api_base": url, + "headers": headers, + }, + ) + + resp = client.get(url=url, headers=headers) + resp.raise_for_status() + except httpx.HTTPStatusError as e: + if e.response.status_code == 403: + return None + raise VertexAIError( + status_code=e.response.status_code, message=e.response.text + ) + except Exception as e: + raise VertexAIError(status_code=500, message=str(e)) + + raw_response = resp.json() + logging_obj.post_call(original_response=raw_response) + + if "cachedContents" not in raw_response: return None - raise VertexAIError( - status_code=e.response.status_code, message=e.response.text - ) - except Exception as e: - raise VertexAIError(status_code=500, message=str(e)) - raw_response = resp.json() - logging_obj.post_call(original_response=raw_response) - if "cachedContents" not in raw_response: - return None + all_cached_items = CachedContentListAllResponseBody(**raw_response) - all_cached_items = CachedContentListAllResponseBody(**raw_response) + if "cachedContents" not in all_cached_items: + return None - if "cachedContents" not in all_cached_items: - return None + # Check current page for matching cache_key + for cached_item in all_cached_items["cachedContents"]: + display_name = cached_item.get("displayName") + if display_name is not None and display_name == cache_key: + return cached_item.get("name") - for cached_item in all_cached_items["cachedContents"]: - display_name = cached_item.get("displayName") - if display_name is not None and display_name == cache_key: - return cached_item.get("name") + # Check if there are more pages + page_token = all_cached_items.get("nextPageToken") + if not page_token: + # No more pages, cache not found + break return None @@ -187,7 +209,7 @@ class ContextCachingEndpoints(VertexBase): - None """ - _, url = self._get_token_and_url_context_caching( + _, base_url = self._get_token_and_url_context_caching( gemini_api_key=api_key, custom_llm_provider=custom_llm_provider, api_base=api_base, @@ -195,43 +217,63 @@ class ContextCachingEndpoints(VertexBase): vertex_location=vertex_location, vertex_auth_header=vertex_auth_header ) - try: - ## LOGGING - logging_obj.pre_call( - input="", - api_key="", - additional_args={ - "complete_input_dict": {}, - "api_base": url, - "headers": headers, - }, - ) - resp = await client.get(url=url, headers=headers) - resp.raise_for_status() - except httpx.HTTPStatusError as e: - if e.response.status_code == 403: + page_token: Optional[str] = None + + # Iterate through all pages + for _ in range(MAX_PAGINATION_PAGES): + # Build URL with pagination token if present + if page_token: + separator = "&" if "?" in base_url else "?" + url = f"{base_url}{separator}pageToken={page_token}" + else: + url = base_url + + try: + ## LOGGING + logging_obj.pre_call( + input="", + api_key="", + additional_args={ + "complete_input_dict": {}, + "api_base": url, + "headers": headers, + }, + ) + + resp = await client.get(url=url, headers=headers) + resp.raise_for_status() + except httpx.HTTPStatusError as e: + if e.response.status_code == 403: + return None + raise VertexAIError( + status_code=e.response.status_code, message=e.response.text + ) + except Exception as e: + raise VertexAIError(status_code=500, message=str(e)) + + raw_response = resp.json() + logging_obj.post_call(original_response=raw_response) + + if "cachedContents" not in raw_response: return None - raise VertexAIError( - status_code=e.response.status_code, message=e.response.text - ) - except Exception as e: - raise VertexAIError(status_code=500, message=str(e)) - raw_response = resp.json() - logging_obj.post_call(original_response=raw_response) - if "cachedContents" not in raw_response: - return None + all_cached_items = CachedContentListAllResponseBody(**raw_response) - all_cached_items = CachedContentListAllResponseBody(**raw_response) + if "cachedContents" not in all_cached_items: + return None - if "cachedContents" not in all_cached_items: - return None + # Check current page for matching cache_key + for cached_item in all_cached_items["cachedContents"]: + display_name = cached_item.get("displayName") + if display_name is not None and display_name == cache_key: + return cached_item.get("name") - for cached_item in all_cached_items["cachedContents"]: - display_name = cached_item.get("displayName") - if display_name is not None and display_name == cache_key: - return cached_item.get("name") + # Check if there are more pages + page_token = all_cached_items.get("nextPageToken") + if not page_token: + # No more pages, cache not found + break return None @@ -501,4 +543,4 @@ class ContextCachingEndpoints(VertexBase): pass async def async_get_cache(self): - pass + pass \ No newline at end of file diff --git a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py index b78ac8f9e98..b5a6949f272 100644 --- a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py +++ b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py @@ -478,6 +478,13 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): if "type" in tool and tool["type"] == "computer_use": computer_use_config = {k: v for k, v in tool.items() if k != "type"} tool = {VertexToolName.COMPUTER_USE.value: computer_use_config} + # Handle OpenAI-style web_search and web_search_preview tools + # Transform them to Gemini's googleSearch tool + elif "type" in tool and tool["type"] in ("web_search", "web_search_preview"): + verbose_logger.info( + f"Gemini: Transforming OpenAI-style '{tool['type']}' tool to googleSearch" + ) + tool = {VertexToolName.GOOGLE_SEARCH.value: {}} # Handle tools with 'type' field (OpenAI spec compliance) Ignore this field -> https://github.com/BerriAI/litellm/issues/14644#issuecomment-3342061838 elif "type" in tool: tool = {k: tool[k] for k in tool if k != "type"} @@ -1657,7 +1664,17 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): ## This is necessary because promptTokensDetails includes both cached and non-cached tokens ## See: https://github.com/BerriAI/litellm/issues/18750 if cached_text_tokens is not None and prompt_text_tokens is not None: + # Explicit caching: subtract cached tokens per modality from cacheTokensDetails prompt_text_tokens = prompt_text_tokens - cached_text_tokens + elif ( + cached_tokens is not None + and prompt_text_tokens is not None + and cached_text_tokens is None + ): + # Implicit caching: only cachedContentTokenCount is provided (no cacheTokensDetails) + # Subtract from text tokens since implicit caching is primarily for text content + # See: https://github.com/BerriAI/litellm/issues/16341 + prompt_text_tokens = prompt_text_tokens - cached_tokens if cached_audio_tokens is not None and prompt_audio_tokens is not None: prompt_audio_tokens = prompt_audio_tokens - cached_audio_tokens if cached_image_tokens is not None and prompt_image_tokens is not None: diff --git a/litellm/llms/vertex_ai/image_generation/vertex_gemini_transformation.py b/litellm/llms/vertex_ai/image_generation/vertex_gemini_transformation.py index 89ed9f1a8a5..ba3df88be14 100644 --- a/litellm/llms/vertex_ai/image_generation/vertex_gemini_transformation.py +++ b/litellm/llms/vertex_ai/image_generation/vertex_gemini_transformation.py @@ -295,9 +295,11 @@ class VertexAIGeminiImageGenerationConfig(BaseImageGenerationConfig, VertexLLM): if "inlineData" in part: inline_data = part["inlineData"] if "data" in inline_data: + thought_sig = part.get("thoughtSignature") model_response.data.append(ImageObject( b64_json=inline_data["data"], url=None, + provider_specific_fields={"thought_signature": thought_sig} if thought_sig else None, )) if usage_metadata := response_data.get("usageMetadata", None): diff --git a/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py b/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py index fc75376c0cb..9b8ff3ecc2d 100644 --- a/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py +++ b/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py @@ -7,6 +7,7 @@ from litellm.llms.anthropic.experimental_pass_through.messages.transformation im from litellm.types.llms.anthropic import ( ANTHROPIC_BETA_HEADER_VALUES, ANTHROPIC_HOSTED_TOOLS, + ANTHROPIC_PROMPT_CACHING_SCOPE_BETA_HEADER, ) from litellm.types.llms.anthropic_tool_search import get_tool_search_beta_header from litellm.types.llms.vertex_ai import VertexPartnerProvider @@ -65,6 +66,10 @@ class VertexAIPartnerModelsAnthropicMessagesConfig(AnthropicMessagesConfig, Vert if existing_beta: beta_values.update(b.strip() for b in existing_beta.split(",")) + # Use the helper to remove unsupported beta headers + self.remove_unsupported_beta(headers) + beta_values.discard(ANTHROPIC_PROMPT_CACHING_SCOPE_BETA_HEADER) + # Check for web search tool for tool in tools: if isinstance(tool, dict) and tool.get("type", "").startswith(ANTHROPIC_HOSTED_TOOLS.WEB_SEARCH.value): @@ -123,3 +128,23 @@ class VertexAIPartnerModelsAnthropicMessagesConfig(AnthropicMessagesConfig, Vert ) # do not pass output_format in request body to vertex ai - vertex ai does not support output_format as yet return anthropic_messages_request + + def remove_unsupported_beta(self, headers: dict) -> None: + """ + Helper method to remove unsupported beta headers from the beta headers. + Modifies headers in place. + """ + unsupported_beta_headers = [ + ANTHROPIC_PROMPT_CACHING_SCOPE_BETA_HEADER + ] + existing_beta = headers.get("anthropic-beta") + if existing_beta: + filtered_beta = [ + b.strip() + for b in existing_beta.split(",") + if b.strip() not in unsupported_beta_headers + ] + if filtered_beta: + headers["anthropic-beta"] = ",".join(filtered_beta) + elif "anthropic-beta" in headers: + del headers["anthropic-beta"] diff --git a/litellm/llms/vertex_ai/vertex_llm_base.py b/litellm/llms/vertex_ai/vertex_llm_base.py index a185370e376..4613b6a5715 100644 --- a/litellm/llms/vertex_ai/vertex_llm_base.py +++ b/litellm/llms/vertex_ai/vertex_llm_base.py @@ -20,6 +20,7 @@ from .common_utils import ( _get_vertex_url, all_gemini_url_modes, get_vertex_base_model_name, + get_vertex_base_url, is_global_only_vertex_model, ) @@ -200,12 +201,7 @@ class VertexBase: ) -> str: if api_base: return api_base - elif vertex_location == "global": - return "https://aiplatform.googleapis.com" - elif vertex_location: - return f"https://{vertex_location}-aiplatform.googleapis.com" - else: - return f"https://{self.get_default_vertex_location()}-aiplatform.googleapis.com" + return get_vertex_base_url(vertex_location or self.get_default_vertex_location()) @staticmethod def create_vertex_url( @@ -218,7 +214,8 @@ class VertexBase: ) -> str: """Return the base url for the vertex partner models""" - api_base = api_base or f"https://{vertex_location}-aiplatform.googleapis.com" + if api_base is None: + api_base = get_vertex_base_url(vertex_location) if partner == VertexPartnerProvider.llama: return f"{api_base}/v1/projects/{vertex_project}/locations/{vertex_location}/endpoints/openapi/chat/completions" elif partner == VertexPartnerProvider.mistralai: @@ -247,11 +244,13 @@ class VertexBase: stream: Optional[bool], model: str, ) -> str: + # Use get_vertex_region to handle global-only models + resolved_location = self.get_vertex_region(vertex_location, model) api_base = self.get_api_base( - api_base=custom_api_base, vertex_location=vertex_location + api_base=custom_api_base, vertex_location=resolved_location ) default_api_base = VertexBase.create_vertex_url( - vertex_location=vertex_location or "us-central1", + vertex_location=resolved_location, vertex_project=vertex_project or project_id, partner=partner, stream=stream, @@ -274,7 +273,7 @@ class VertexBase: url=default_api_base, model=model, vertex_project=vertex_project or project_id, - vertex_location=vertex_location or "us-central1", + vertex_location=resolved_location, vertex_api_version="v1", # Partner models typically use v1 ) return api_base diff --git a/litellm/llms/watsonx/common_utils.py b/litellm/llms/watsonx/common_utils.py index 774f6dc1f3d..230c9f4cf6e 100644 --- a/litellm/llms/watsonx/common_utils.py +++ b/litellm/llms/watsonx/common_utils.py @@ -42,6 +42,7 @@ def generate_iam_token(api_key=None, **params) -> str: get_secret_str("WX_API_KEY") or get_secret_str("WATSONX_API_KEY") or get_secret_str("WATSONX_APIKEY") + or get_secret_str("WATSONX_ZENAPIKEY") ) if api_key is None: raise ValueError("API key is required") @@ -319,6 +320,7 @@ class IBMWatsonXMixin: or get_secret_str("WATSONX_APIKEY") or get_secret_str("WATSONX_API_KEY") or get_secret_str("WX_API_KEY") + or get_secret_str("WATSONX_ZENAPIKEY") ) api_base = ( diff --git a/litellm/llms/xai/chat/transformation.py b/litellm/llms/xai/chat/transformation.py index 245e10e45c1..21782fc6fbf 100644 --- a/litellm/llms/xai/chat/transformation.py +++ b/litellm/llms/xai/chat/transformation.py @@ -4,6 +4,7 @@ import httpx import litellm from litellm._logging import verbose_logger +from litellm.constants import XAI_API_BASE from litellm.litellm_core_utils.prompt_templates.common_utils import ( filter_value_from_dict, strip_name_from_messages, @@ -14,8 +15,6 @@ from litellm.types.utils import Choices, ModelResponse, Usage, PromptTokensDetai from ...openai.chat.gpt_transformation import OpenAIGPTConfig -XAI_API_BASE = "https://api.x.ai/v1" - class XAIChatConfig(OpenAIGPTConfig): @property diff --git a/litellm/llms/xai/realtime/__init__.py b/litellm/llms/xai/realtime/__init__.py new file mode 100644 index 00000000000..3b0d345f2c2 --- /dev/null +++ b/litellm/llms/xai/realtime/__init__.py @@ -0,0 +1,5 @@ +"""xAI Realtime API handler.""" + +from .handler import XAIRealtime + +__all__ = ["XAIRealtime"] diff --git a/litellm/llms/xai/realtime/handler.py b/litellm/llms/xai/realtime/handler.py new file mode 100644 index 00000000000..c79477ba1df --- /dev/null +++ b/litellm/llms/xai/realtime/handler.py @@ -0,0 +1,38 @@ +""" +This file contains the handler for xAI's Grok Voice Agent API `/v1/realtime` endpoint. + +xAI's Realtime API is fully OpenAI-compatible, so we inherit from OpenAIRealtime +and only override the configuration differences. + +This requires websockets, and is currently only supported on LiteLLM Proxy. +""" + +from litellm.constants import XAI_API_BASE + +from ...openai.realtime.handler import OpenAIRealtime + + +class XAIRealtime(OpenAIRealtime): + """ + Handler for xAI Grok Voice Agent API. + + xAI's Realtime API uses the same WebSocket protocol as OpenAI but with: + - Different endpoint: wss://api.x.ai/v1/realtime (via _get_default_api_base) + - No OpenAI-Beta header required (via _get_additional_headers) + - Model: grok-4-1-fast-non-reasoning + + All WebSocket logic is inherited from OpenAIRealtime. + """ + + def _get_default_api_base(self) -> str: + """xAI uses a different API base URL.""" + return XAI_API_BASE + + def _get_additional_headers(self, api_key: str) -> dict: + """ + xAI does NOT require the OpenAI-Beta header. + Only send Authorization header. + """ + return { + "Authorization": f"Bearer {api_key}", + } diff --git a/litellm/llms/xai/responses/transformation.py b/litellm/llms/xai/responses/transformation.py index bd422c8d81e..95873aab846 100644 --- a/litellm/llms/xai/responses/transformation.py +++ b/litellm/llms/xai/responses/transformation.py @@ -1,10 +1,12 @@ -from typing import TYPE_CHECKING, Any, Dict, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union import litellm from litellm._logging import verbose_logger +from litellm.constants import XAI_API_BASE from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig from litellm.secret_managers.main import get_secret_str from litellm.types.llms.openai import ResponsesAPIOptionalRequestParams +from litellm.types.llms.xai import XAIWebSearchTool, XAIXSearchTool from litellm.types.router import GenericLiteLLMParams from litellm.types.utils import LlmProviders @@ -15,8 +17,6 @@ if TYPE_CHECKING: else: LiteLLMLoggingObj = Any -XAI_API_BASE = "https://api.x.ai/v1" - class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): """ @@ -49,6 +49,85 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): return supported_params + def _transform_web_search_tool(self, tool: Dict[str, Any]) -> Union[XAIWebSearchTool, Dict[str, Any]]: + """ + Transform web_search tool to XAI format. + + XAI supports web_search with specific filters: + - allowed_domains (max 5) + - excluded_domains (max 5) + - enable_image_understanding + + XAI does NOT support search_context_size (OpenAI-specific). + """ + xai_tool: Dict[str, Any] = {"type": "web_search"} + + # Remove search_context_size if present (not supported by XAI) + if "search_context_size" in tool: + verbose_logger.info( + "XAI does not support 'search_context_size' parameter. Removing it from web_search tool." + ) + + # Handle filters (XAI-specific structure) + filters = {} + if "allowed_domains" in tool: + allowed_domains = tool["allowed_domains"] + filters["allowed_domains"] = allowed_domains + + if "excluded_domains" in tool: + excluded_domains = tool["excluded_domains"] + filters["excluded_domains"] = excluded_domains + + # Add filters if any were specified + if filters: + xai_tool["filters"] = filters + + # Handle enable_image_understanding (top-level in XAI format) + if "enable_image_understanding" in tool: + xai_tool["enable_image_understanding"] = tool["enable_image_understanding"] + + return xai_tool + + def _transform_x_search_tool(self, tool: Dict[str, Any]) -> Union[XAIXSearchTool, Dict[str, Any]]: + """ + Transform x_search tool to XAI format. + + XAI supports x_search with specific parameters: + - allowed_x_handles (max 10) + - excluded_x_handles (max 10) + - from_date (ISO8601: YYYY-MM-DD) + - to_date (ISO8601: YYYY-MM-DD) + - enable_image_understanding + - enable_video_understanding + """ + xai_tool: Dict[str, Any] = {"type": "x_search"} + + # Handle allowed_x_handles + if "allowed_x_handles" in tool: + allowed_handles = tool["allowed_x_handles"] + xai_tool["allowed_x_handles"] = allowed_handles + + # Handle excluded_x_handles + if "excluded_x_handles" in tool: + excluded_handles = tool["excluded_x_handles"] + xai_tool["excluded_x_handles"] = excluded_handles + + # Handle date range + if "from_date" in tool: + xai_tool["from_date"] = tool["from_date"] + + if "to_date" in tool: + xai_tool["to_date"] = tool["to_date"] + + # Handle media understanding flags + if "enable_image_understanding" in tool: + xai_tool["enable_image_understanding"] = tool["enable_image_understanding"] + + if "enable_video_understanding" in tool: + xai_tool["enable_video_understanding"] = tool["enable_video_understanding"] + + return xai_tool + def map_openai_params( self, response_api_optional_params: ResponsesAPIOptionalRequestParams, @@ -61,7 +140,9 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): Handles XAI-specific transformations: 1. Drops 'instructions' parameter (not supported) 2. Transforms code_interpreter tools to remove 'container' field - 3. Sets store=false when images are detected (recommended by XAI) + 3. Transforms web_search tools to XAI format (removes search_context_size, adds filters) + 4. Transforms x_search tools to XAI format + 5. Sets store=false when images are detected (recommended by XAI) """ params = dict(response_api_optional_params) @@ -72,7 +153,13 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): ) params.pop("instructions") - # Transform code_interpreter tools - remove container field + if "metadata" in params: + verbose_logger.debug( + "XAI Responses API does not support 'metadata' parameter. Dropping it." + ) + params.pop("metadata") + + # Transform tools if "tools" in params and params["tools"]: tools_list = params["tools"] # Ensure tools is a list for iteration @@ -81,15 +168,36 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): transformed_tools: List[Any] = [] for tool in tools_list: - if isinstance(tool, dict) and tool.get("type") == "code_interpreter": - # XAI supports code_interpreter but doesn't use the container field - # Keep only the type field - verbose_logger.debug( - "XAI: Transforming code_interpreter tool, removing container field" - ) - transformed_tools.append({"type": "code_interpreter"}) + if isinstance(tool, dict): + tool_type = tool.get("type") + + if tool_type == "code_interpreter": + # XAI supports code_interpreter but doesn't use the container field + verbose_logger.debug( + "XAI: Transforming code_interpreter tool, removing container field" + ) + transformed_tools.append({"type": "code_interpreter"}) + + elif tool_type == "web_search": + # Transform web_search to XAI format + verbose_logger.debug( + "XAI: Transforming web_search tool to XAI format" + ) + transformed_tools.append(self._transform_web_search_tool(tool)) + + elif tool_type == "x_search": + # Transform x_search to XAI format + verbose_logger.debug( + "XAI: Transforming x_search tool to XAI format" + ) + transformed_tools.append(self._transform_x_search_tool(tool)) + + else: + # Keep other tools as-is + transformed_tools.append(tool) else: transformed_tools.append(tool) + params["tools"] = transformed_tools return params diff --git a/litellm/llms/zai/chat/transformation.py b/litellm/llms/zai/chat/transformation.py index 4380256f0a4..fb1d67df357 100644 --- a/litellm/llms/zai/chat/transformation.py +++ b/litellm/llms/zai/chat/transformation.py @@ -1,6 +1,7 @@ -from typing import Optional, Tuple +from typing import List, Optional, Tuple from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import AllMessageValues, ChatCompletionToolParam from ...openai.chat.gpt_transformation import OpenAIGPTConfig @@ -19,6 +20,19 @@ class ZAIChatConfig(OpenAIGPTConfig): dynamic_api_key = api_key or get_secret_str("ZAI_API_KEY") return api_base, dynamic_api_key + def remove_cache_control_flag_from_messages_and_tools( + self, + model: str, + messages: List[AllMessageValues], + tools: Optional[List[ChatCompletionToolParam]] = None, + ) -> Tuple[List[AllMessageValues], Optional[List[ChatCompletionToolParam]]]: + """ + Override to preserve cache_control for GLM/ZAI. + GLM supports cache_control - don't strip it. + """ + # GLM/ZAI supports cache_control, so return messages and tools unchanged + return messages, tools + def get_supported_openai_params(self, model: str) -> list: base_params = [ "max_tokens", diff --git a/litellm/main.py b/litellm/main.py index ce84c8988e0..bca023e65ec 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -148,7 +148,7 @@ from litellm.utils import ( validate_and_fix_openai_messages, validate_and_fix_openai_tools, validate_chat_completion_tool_choice, - validate_openai_optional_params + validate_openai_optional_params, ) from ._logging import verbose_logger @@ -368,7 +368,7 @@ class AsyncCompletions: @tracer.wrap() @client -async def acompletion( # noqa: PLR0915 +async def acompletion( # noqa: PLR0915 model: str, # Optional OpenAI params: see https://platform.openai.com/docs/api-reference/chat/create messages: List = [], @@ -599,16 +599,8 @@ async def acompletion( # noqa: PLR0915 # Add the context to the function ctx = contextvars.copy_context() func_with_context = partial(ctx.run, func) - - if timeout is not None and isinstance(timeout, (int, float)): - timeout_value = float(timeout) - init_response = await asyncio.wait_for( - loop.run_in_executor(None, func_with_context), - timeout=timeout_value - ) - else: - init_response = await loop.run_in_executor(None, func_with_context) + init_response = await loop.run_in_executor(None, func_with_context) if isinstance(init_response, dict) or isinstance( init_response, ModelResponse ): ## CACHING SCENARIO @@ -616,11 +608,7 @@ async def acompletion( # noqa: PLR0915 response = ModelResponse(**init_response) response = init_response elif asyncio.iscoroutine(init_response): - if timeout is not None and isinstance(timeout, (int, float)): - timeout_value = float(timeout) - response = await asyncio.wait_for(init_response, timeout=timeout_value) - else: - response = await init_response + response = await init_response else: response = init_response # type: ignore @@ -637,14 +625,6 @@ async def acompletion( # noqa: PLR0915 loop=loop ) # sets the logging event loop if the user does sync streaming (e.g. on proxy for sagemaker calls) return response - except asyncio.TimeoutError: - custom_llm_provider = custom_llm_provider or "openai" - from litellm.exceptions import Timeout - raise Timeout( - message=f"Request timed out after {timeout} seconds", - model=model, - llm_provider=custom_llm_provider, - ) except Exception as e: custom_llm_provider = custom_llm_provider or "openai" raise exception_type( @@ -945,6 +925,7 @@ def mock_completion( def responses_api_bridge_check( model: str, custom_llm_provider: str, + web_search_options: Optional[OpenAIWebSearchOptions] = None, ) -> Tuple[dict, str]: model_info: Dict[str, Any] = {} try: @@ -958,6 +939,10 @@ def responses_api_bridge_check( model = model.replace("responses/", "") mode = "responses" model_info["mode"] = mode + + if web_search_options is not None and custom_llm_provider == "xai": + model_info["mode"] = "responses" + model = model.replace("responses/", "") except Exception as e: verbose_logger.debug("Error getting model info: {}".format(e)) @@ -1118,7 +1103,6 @@ def completion( # type: ignore # noqa: PLR0915 # validate optional params stop = validate_openai_optional_params(stop=stop) - ######### unpacking kwargs ##################### args = locals() @@ -1135,7 +1119,9 @@ def completion( # type: ignore # noqa: PLR0915 # Check if MCP tools are present (following responses pattern) # Cast tools to Optional[Iterable[ToolParam]] for type checking tools_for_mcp = cast(Optional[Iterable[ToolParam]], tools) - if LiteLLM_Proxy_MCP_Handler._should_use_litellm_mcp_gateway(tools=tools_for_mcp): + if LiteLLM_Proxy_MCP_Handler._should_use_litellm_mcp_gateway( + tools=tools_for_mcp + ): # Return coroutine - acompletion will await it # completion() can return a coroutine when MCP tools are present, which acompletion() awaits return acompletion_with_mcp( # type: ignore[return-value] @@ -1213,6 +1199,13 @@ def completion( # type: ignore # noqa: PLR0915 headers = {} if extra_headers is not None: headers.update(extra_headers) + # Inject proxy auth headers if configured + if litellm.proxy_auth is not None: + try: + proxy_headers = litellm.proxy_auth.get_auth_headers() + headers.update(proxy_headers) + except Exception as e: + verbose_logger.warning(f"Failed to get proxy auth headers: {e}") num_retries = kwargs.get( "num_retries", None ) ## alt. param for 'max_retries'. Use this to pass retries w/ instructor. @@ -1536,6 +1529,8 @@ def completion( # type: ignore # noqa: PLR0915 max_retries=max_retries, timeout=timeout, litellm_request_debug=kwargs.get("litellm_request_debug", False), + tpm=kwargs.get("tpm"), + rpm=kwargs.get("rpm"), ) cast(LiteLLMLoggingObj, logging).update_environment_variables( model=model, @@ -1563,7 +1558,7 @@ def completion( # type: ignore # noqa: PLR0915 ## RESPONSES API BRIDGE LOGIC ## - check if model has 'mode: responses' in litellm.model_cost map model_info, model = responses_api_bridge_check( - model=model, custom_llm_provider=custom_llm_provider + model=model, custom_llm_provider=custom_llm_provider, web_search_options=web_search_options ) if model_info.get("mode") == "responses": @@ -2211,6 +2206,48 @@ def completion( # type: ignore # noqa: PLR0915 logging_obj=logging, # model call logging done inside the class as we make need to modify I/O to fit aleph alpha's requirements client=client, ) + elif custom_llm_provider == "a2a": + # A2A (Agent-to-Agent) Protocol + # Resolve agent configuration from registry if model format is "a2a/" + api_base, api_key, headers = litellm.A2AConfig.resolve_agent_config_from_registry( + model=model, + api_base=api_base, + api_key=api_key, + headers=headers, + optional_params=optional_params, + ) + + # Fall back to environment variables and defaults + api_base = api_base or litellm.api_base or get_secret_str("A2A_API_BASE") + + if api_base is None: + raise Exception( + "api_base is required for A2A provider. " + "Either provide api_base parameter, set A2A_API_BASE environment variable, " + "or register the agent in the proxy with model='a2a/'." + ) + + headers = headers or litellm.headers + + response = base_llm_http_handler.completion( + model=model, + stream=stream, + messages=messages, + acompletion=acompletion, + api_base=api_base, + model_response=model_response, + optional_params=optional_params, + litellm_params=litellm_params, + shared_session=shared_session, + custom_llm_provider=custom_llm_provider, + timeout=timeout, + headers=headers, + encoding=_get_encoding(), + api_key=api_key, + logging_obj=logging, + client=client, + provider_config=provider_config, + ) elif custom_llm_provider == "gigachat": # GigaChat - Sber AI's LLM (Russia) api_key = ( @@ -2361,11 +2398,7 @@ def completion( # type: ignore # noqa: PLR0915 input=messages, api_key=api_key, original_response=response ) elif custom_llm_provider == "minimax": - api_key = ( - api_key - or get_secret_str("MINIMAX_API_KEY") - or litellm.api_key - ) + api_key = api_key or get_secret_str("MINIMAX_API_KEY") or litellm.api_key api_base = ( api_base @@ -2374,6 +2407,33 @@ def completion( # type: ignore # noqa: PLR0915 or "https://api.minimax.io/v1" ) + response = base_llm_http_handler.completion( + model=model, + messages=messages, + api_base=api_base, + custom_llm_provider=custom_llm_provider, + model_response=model_response, + encoding=_get_encoding(), + logging_obj=logging, + optional_params=optional_params, + timeout=timeout, + litellm_params=litellm_params, + shared_session=shared_session, + acompletion=acompletion, + stream=stream, + api_key=api_key, + headers=headers, + client=client, + provider_config=provider_config, + ) + logging.post_call( + input=messages, api_key=api_key, original_response=response + ) + elif custom_llm_provider == "hosted_vllm": + api_base = ( + api_base or litellm.api_base or get_secret_str("HOSTED_VLLM_API_BASE") + ) + response = base_llm_http_handler.completion( model=model, messages=messages, @@ -2413,7 +2473,9 @@ def completion( # type: ignore # noqa: PLR0915 or custom_llm_provider == "wandb" or custom_llm_provider == "clarifai" or custom_llm_provider in litellm.openai_compatible_providers - or JSONProviderRegistry.exists(custom_llm_provider) # JSON-configured providers + or JSONProviderRegistry.exists( + custom_llm_provider + ) # JSON-configured providers or "ft:gpt-3.5-turbo" in model # finetune gpt-3.5-turbo ): # allow user to make an openai call with a custom base # note: if a user sets a custom base - we should ensure this works @@ -2442,6 +2504,20 @@ def completion( # type: ignore # noqa: PLR0915 headers = headers or litellm.headers + # Add GitHub Copilot headers (same as /responses endpoint does) + if custom_llm_provider == "github_copilot": + from litellm.llms.github_copilot.common_utils import ( + get_copilot_default_headers, + ) + from litellm.llms.github_copilot.authenticator import Authenticator + + copilot_auth = Authenticator() + copilot_api_key = copilot_auth.get_api_key() + copilot_headers = get_copilot_default_headers(copilot_api_key) + if extra_headers: + copilot_headers.update(extra_headers) + extra_headers = copilot_headers + if extra_headers is not None: optional_params["extra_headers"] = extra_headers @@ -3100,8 +3176,8 @@ def completion( # type: ignore # noqa: PLR0915 api_key or litellm.api_key or litellm.openrouter_key - or get_secret("OPENROUTER_API_KEY") - or get_secret("OR_API_KEY") + or get_secret_str("OPENROUTER_API_KEY") + or get_secret_str("OR_API_KEY") ) openrouter_site_url = get_secret("OR_SITE_URL") or "https://litellm.ai" @@ -3610,9 +3686,9 @@ def completion( # type: ignore # noqa: PLR0915 "aws_region_name" not in optional_params or optional_params["aws_region_name"] is None ): - optional_params[ - "aws_region_name" - ] = aws_bedrock_client.meta.region_name + optional_params["aws_region_name"] = ( + aws_bedrock_client.meta.region_name + ) bedrock_route = BedrockModelInfo.get_bedrock_route(model) if bedrock_route == "converse": @@ -4542,6 +4618,13 @@ def embedding( # noqa: PLR0915 headers = {} if extra_headers is not None: headers.update(extra_headers) + # Inject proxy auth headers if configured + if litellm.proxy_auth is not None: + try: + proxy_headers = litellm.proxy_auth.get_auth_headers() + headers.update(proxy_headers) + except Exception as e: + verbose_logger.warning(f"Failed to get proxy auth headers: {e}") ### CUSTOM MODEL COST ### input_cost_per_token = kwargs.get("input_cost_per_token", None) output_cost_per_token = kwargs.get("output_cost_per_token", None) @@ -4696,11 +4779,11 @@ def embedding( # noqa: PLR0915 litellm_params=litellm_params_dict, ) elif ( - model in litellm.open_ai_embedding_models - or custom_llm_provider == "openai" + custom_llm_provider == "openai" or custom_llm_provider == "together_ai" or custom_llm_provider == "nvidia_nim" or custom_llm_provider == "litellm_proxy" + or (model in litellm.open_ai_embedding_models and custom_llm_provider is None) ): api_base = ( api_base @@ -4724,7 +4807,7 @@ def embedding( # noqa: PLR0915 if headers is not None and headers != {}: optional_params["extra_headers"] = headers - + if encoding_format is not None: optional_params["encoding_format"] = encoding_format else: @@ -4772,9 +4855,32 @@ def embedding( # noqa: PLR0915 client=client, aembedding=aembedding, ) + elif custom_llm_provider == "hosted_vllm": + api_base = ( + api_base or litellm.api_base or get_secret_str("HOSTED_VLLM_API_BASE") + ) + + # set API KEY + if api_key is None: + api_key = litellm.api_key or get_secret_str("HOSTED_VLLM_API_KEY") + + response = base_llm_http_handler.embedding( + model=model, + input=input, + custom_llm_provider=custom_llm_provider, + api_base=api_base, + api_key=api_key, + logging_obj=logging, + timeout=timeout, + model_response=EmbeddingResponse(), + optional_params=optional_params, + client=client, + aembedding=aembedding, + litellm_params=litellm_params_dict, + headers=headers or {}, + ) elif ( custom_llm_provider == "openai_like" - or custom_llm_provider == "hosted_vllm" or custom_llm_provider == "llamafile" or custom_llm_provider == "lm_studio" ): @@ -4848,8 +4954,8 @@ def embedding( # noqa: PLR0915 api_key or litellm.api_key or litellm.openrouter_key - or get_secret("OPENROUTER_API_KEY") - or get_secret("OR_API_KEY") + or get_secret_str("OPENROUTER_API_KEY") + or get_secret_str("OR_API_KEY") ) openrouter_site_url = get_secret("OR_SITE_URL") or "https://litellm.ai" @@ -4866,6 +4972,36 @@ def embedding( # noqa: PLR0915 headers = openrouter_headers + response = base_llm_http_handler.embedding( + model=model, + input=input, + custom_llm_provider=custom_llm_provider, + api_base=api_base, + api_key=api_key, + logging_obj=logging, + timeout=timeout, + model_response=EmbeddingResponse(), + optional_params=optional_params, + client=client, + aembedding=aembedding, + litellm_params=litellm_params_dict, + headers=headers, + ) + elif custom_llm_provider == "vercel_ai_gateway": + api_base = ( + api_base + or litellm.api_base + or get_secret_str("VERCEL_AI_GATEWAY_API_BASE") + or "https://ai-gateway.vercel.sh/v1" + ) + + api_key = ( + api_key + or litellm.api_key + or get_secret_str("VERCEL_AI_GATEWAY_API_KEY") + or get_secret_str("VERCEL_OIDC_TOKEN") + ) + response = base_llm_http_handler.embedding( model=model, input=input, @@ -5917,9 +6053,9 @@ def adapter_completion( new_kwargs = translation_obj.translate_completion_input_params(kwargs=kwargs) response: Union[ModelResponse, CustomStreamWrapper] = completion(**new_kwargs) # type: ignore - translated_response: Optional[ - Union[BaseModel, AdapterCompletionStreamWrapper] - ] = None + translated_response: Optional[Union[BaseModel, AdapterCompletionStreamWrapper]] = ( + None + ) if isinstance(response, ModelResponse): translated_response = translation_obj.translate_completion_output_params( response=response @@ -6624,9 +6760,9 @@ def speech( # noqa: PLR0915 ElevenLabsTextToSpeechConfig.ELEVENLABS_QUERY_PARAMS_KEY ] = query_params - litellm_params_dict[ - ElevenLabsTextToSpeechConfig.ELEVENLABS_VOICE_ID_KEY - ] = voice_id + litellm_params_dict[ElevenLabsTextToSpeechConfig.ELEVENLABS_VOICE_ID_KEY] = ( + voice_id + ) if api_base is not None: litellm_params_dict["api_base"] = api_base @@ -6759,9 +6895,7 @@ def speech( # noqa: PLR0915 if text_to_speech_provider_config is None: text_to_speech_provider_config = MinimaxTextToSpeechConfig() - minimax_config = cast( - MinimaxTextToSpeechConfig, text_to_speech_provider_config - ) + minimax_config = cast(MinimaxTextToSpeechConfig, text_to_speech_provider_config) if api_base is not None: litellm_params_dict["api_base"] = api_base @@ -6901,7 +7035,7 @@ async def ahealth_check( custom_llm_provider_from_params = model_params.get("custom_llm_provider", None) api_base_from_params = model_params.get("api_base", None) api_key_from_params = model_params.get("api_key", None) - + model, custom_llm_provider, _, _ = get_llm_provider( model=model, custom_llm_provider=custom_llm_provider_from_params, @@ -7134,9 +7268,9 @@ def stream_chunk_builder( # noqa: PLR0915 ] if len(content_chunks) > 0: - response["choices"][0]["message"][ - "content" - ] = processor.get_combined_content(content_chunks) + response["choices"][0]["message"]["content"] = ( + processor.get_combined_content(content_chunks) + ) thinking_blocks = [ chunk @@ -7147,9 +7281,9 @@ def stream_chunk_builder( # noqa: PLR0915 ] if len(thinking_blocks) > 0: - response["choices"][0]["message"][ - "thinking_blocks" - ] = processor.get_combined_thinking_content(thinking_blocks) + response["choices"][0]["message"]["thinking_blocks"] = ( + processor.get_combined_thinking_content(thinking_blocks) + ) reasoning_chunks = [ chunk @@ -7160,9 +7294,9 @@ def stream_chunk_builder( # noqa: PLR0915 ] if len(reasoning_chunks) > 0: - response["choices"][0]["message"][ - "reasoning_content" - ] = processor.get_combined_reasoning_content(reasoning_chunks) + response["choices"][0]["message"]["reasoning_content"] = ( + processor.get_combined_reasoning_content(reasoning_chunks) + ) annotation_chunks = [ chunk @@ -7188,6 +7322,23 @@ def stream_chunk_builder( # noqa: PLR0915 _choice = cast(Choices, response.choices[0]) _choice.message.audio = processor.get_combined_audio_content(audio_chunks) + # Handle image chunks from models like gemini-2.5-flash-image + # See: https://github.com/BerriAI/litellm/issues/19478 + image_chunks = [ + chunk + for chunk in chunks + if len(chunk["choices"]) > 0 + and "images" in chunk["choices"][0]["delta"] + and chunk["choices"][0]["delta"]["images"] is not None + ] + + if len(image_chunks) > 0: + # Images come complete in a single chunk, collect all images from all chunks + all_images = [] + for chunk in image_chunks: + all_images.extend(chunk["choices"][0]["delta"]["images"]) + response["choices"][0]["message"]["images"] = all_images + # Combine provider_specific_fields from streaming chunks (e.g., web_search_results, citations) # See: https://github.com/BerriAI/litellm/issues/17737 provider_specific_chunks = [ @@ -7271,12 +7422,16 @@ def _get_encoding(): def __getattr__(name: str) -> Any: """Lazy import handler for main module""" if name == "encoding": - # Lazy load encoding to avoid heavy tiktoken import at module load time - _encoding = tiktoken.get_encoding("cl100k_base") + # Use _get_default_encoding which properly sets TIKTOKEN_CACHE_DIR + # before loading tiktoken, ensuring the local cache is used + # instead of downloading from the internet + from litellm._lazy_imports import _get_default_encoding + _encoding = _get_default_encoding() # Cache it in the module's __dict__ for subsequent accesses import sys + sys.modules[__name__].__dict__["encoding"] = _encoding global _encoding_cache _encoding_cache = _encoding return _encoding - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") \ No newline at end of file + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index d958ea4503a..6d399d25bf6 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -354,6 +354,25 @@ "supports_video_input": true, "supports_vision": true }, + "amazon.nova-2-pro-preview-20251202-v1:0": { + "cache_read_input_token_cost": 5.46875e-07, + "input_cost_per_token": 2.1875e-06, + "input_cost_per_image_token": 2.1875e-06, + "input_cost_per_audio_token": 2.1875e-06, + "litellm_provider": "bedrock_converse", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "output_cost_per_token": 1.75e-05, + "supports_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_video_input": true, + "supports_vision": true + }, "apac.amazon.nova-2-lite-v1:0": { "cache_read_input_token_cost": 8.25e-08, "input_cost_per_token": 3.3e-07, @@ -371,6 +390,25 @@ "supports_video_input": true, "supports_vision": true }, + "apac.amazon.nova-2-pro-preview-20251202-v1:0": { + "cache_read_input_token_cost": 5.46875e-07, + "input_cost_per_token": 2.1875e-06, + "input_cost_per_image_token": 2.1875e-06, + "input_cost_per_audio_token": 2.1875e-06, + "litellm_provider": "bedrock_converse", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "output_cost_per_token": 1.75e-05, + "supports_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_video_input": true, + "supports_vision": true + }, "eu.amazon.nova-2-lite-v1:0": { "cache_read_input_token_cost": 8.25e-08, "input_cost_per_token": 3.3e-07, @@ -388,6 +426,25 @@ "supports_video_input": true, "supports_vision": true }, + "eu.amazon.nova-2-pro-preview-20251202-v1:0": { + "cache_read_input_token_cost": 5.46875e-07, + "input_cost_per_token": 2.1875e-06, + "input_cost_per_image_token": 2.1875e-06, + "input_cost_per_audio_token": 2.1875e-06, + "litellm_provider": "bedrock_converse", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "output_cost_per_token": 1.75e-05, + "supports_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_video_input": true, + "supports_vision": true + }, "us.amazon.nova-2-lite-v1:0": { "cache_read_input_token_cost": 8.25e-08, "input_cost_per_token": 3.3e-07, @@ -405,6 +462,25 @@ "supports_video_input": true, "supports_vision": true }, + "us.amazon.nova-2-pro-preview-20251202-v1:0": { + "cache_read_input_token_cost": 5.46875e-07, + "input_cost_per_token": 2.1875e-06, + "input_cost_per_image_token": 2.1875e-06, + "input_cost_per_audio_token": 2.1875e-06, + "litellm_provider": "bedrock_converse", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "output_cost_per_token": 1.75e-05, + "supports_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_video_input": true, + "supports_vision": true + }, "amazon.nova-2-multimodal-embeddings-v1:0": { "litellm_provider": "bedrock", "max_input_tokens": 8172, @@ -668,12 +744,13 @@ "supports_response_schema": true, "supports_tool_choice": true, "supports_vision": true, - "tool_use_system_prompt_tokens": 346 + "tool_use_system_prompt_tokens": 346, + "supports_native_streaming": true }, "anthropic.claude-3-5-sonnet-20240620-v1:0": { "input_cost_per_token": 3e-06, "litellm_provider": "bedrock", - "max_input_tokens": 200000, + "max_input_tokens": 1000000, "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", @@ -682,14 +759,22 @@ "supports_pdf_input": true, "supports_response_schema": true, "supports_tool_choice": true, - "supports_vision": true + "supports_vision": true, + "input_cost_per_token_above_200k_tokens": 6e-06, + "output_cost_per_token_above_200k_tokens": 3e-05, + "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "cache_creation_input_token_cost_above_1hr": 7.5e-06, + "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.5e-05, + "cache_creation_input_token_cost": 3.75e-06, + "cache_read_input_token_cost": 3e-07 }, "anthropic.claude-3-5-sonnet-20241022-v2:0": { "cache_creation_input_token_cost": 3.75e-06, "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "litellm_provider": "bedrock", - "max_input_tokens": 200000, + "max_input_tokens": 1000000, "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", @@ -701,7 +786,13 @@ "supports_prompt_caching": true, "supports_response_schema": true, "supports_tool_choice": true, - "supports_vision": true + "supports_vision": true, + "input_cost_per_token_above_200k_tokens": 6e-06, + "output_cost_per_token_above_200k_tokens": 3e-05, + "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "cache_creation_input_token_cost_above_1hr": 7.5e-06, + "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.5e-05 }, "anthropic.claude-3-7-sonnet-20240620-v1:0": { "cache_creation_input_token_cost": 4.5e-06, @@ -1441,6 +1532,14 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "azure_ai/model_router": { + "input_cost_per_token": 1.4e-07, + "output_cost_per_token": 0, + "litellm_provider": "azure_ai", + "mode": "chat", + "source": "https://azure.microsoft.com/en-us/pricing/details/ai-services/", + "comment": "Flat cost of $0.14 per M input tokens for Azure AI Foundry Model Router infrastructure. Use pattern: azure_ai/model_router/ where deployment-name is your Azure deployment (e.g., azure-model-router)" + }, "azure/eu/gpt-4o-2024-08-06": { "deprecation_date": "2026-02-27", "cache_read_input_token_cost": 1.375e-06, @@ -3130,7 +3229,7 @@ "supports_reasoning": true, "supports_response_schema": true, "supports_system_messages": true, - "supports_tool_choice": false, + "supports_tool_choice": true, "supports_vision": true }, "azure/gpt-5-chat-latest": { @@ -3162,7 +3261,7 @@ "supports_reasoning": true, "supports_response_schema": true, "supports_system_messages": true, - "supports_tool_choice": false, + "supports_tool_choice": true, "supports_vision": true }, "azure/gpt-5-codex": { @@ -3650,13 +3749,12 @@ "cache_read_input_token_cost": 1.75e-07, "input_cost_per_token": 1.75e-06, "litellm_provider": "azure", - "max_input_tokens": 128000, - "max_output_tokens": 16384, - "max_tokens": 16384, - "mode": "chat", + "max_input_tokens": 272000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", "output_cost_per_token": 1.4e-05, "supported_endpoints": [ - "/v1/chat/completions", "/v1/responses" ], "supported_modalities": [ @@ -6632,13 +6730,13 @@ "supports_tool_choice": true }, "cerebras/gpt-oss-120b": { - "input_cost_per_token": 2.5e-07, + "input_cost_per_token": 3.5e-07, "litellm_provider": "cerebras", "max_input_tokens": 131072, "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", - "output_cost_per_token": 6.9e-07, + "output_cost_per_token": 7.5e-07, "source": "https://www.cerebras.ai/blog/openai-gpt-oss-120b-runs-fastest-on-cerebras", "supports_function_calling": true, "supports_parallel_function_calling": true, @@ -6656,6 +6754,7 @@ "output_cost_per_token": 8e-07, "source": "https://inference-docs.cerebras.ai/support/pricing", "supports_function_calling": true, + "supports_reasoning": true, "supports_tool_choice": true }, "cerebras/zai-glm-4.6": { @@ -10232,6 +10331,48 @@ "mode": "completion", "output_cost_per_token": 5e-07 }, + "deepseek-v3-2-251201": { + "input_cost_per_token": 0.0, + "litellm_provider": "volcengine", + "max_input_tokens": 98304, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 0.0, + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "glm-4-7-251222": { + "input_cost_per_token": 0.0, + "litellm_provider": "volcengine", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 0.0, + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "kimi-k2-thinking-251104": { + "input_cost_per_token": 0.0, + "litellm_provider": "volcengine", + "max_input_tokens": 229376, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 0.0, + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, "doubao-embedding": { "input_cost_per_token": 0.0, "litellm_provider": "volcengine", @@ -12710,6 +12851,40 @@ "supports_vision": true, "supports_web_search": true }, + "deep-research-pro-preview-12-2025": { + "input_cost_per_image": 0.0011, + "input_cost_per_token": 2e-06, + "input_cost_per_token_batches": 1e-06, + "litellm_provider": "vertex_ai-language-models", + "max_input_tokens": 65536, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "image_generation", + "output_cost_per_image": 0.134, + "output_cost_per_image_token": 0.00012, + "output_cost_per_token": 1.2e-05, + "output_cost_per_token_batches": 6e-06, + "source": "https://ai.google.dev/gemini-api/docs/pricing", + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/completions", + "/v1/batch" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text", + "image" + ], + "supports_function_calling": false, + "supports_prompt_caching": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_vision": true, + "supports_web_search": true + }, "gemini-2.5-flash-lite": { "cache_read_input_token_cost": 1e-08, "input_cost_per_audio_token": 3e-07, @@ -13164,7 +13339,8 @@ "supports_tool_choice": true, "supports_video_input": true, "supports_vision": true, - "supports_web_search": true + "supports_web_search": true, + "supports_native_streaming": true }, "vertex_ai/gemini-3-pro-preview": { "cache_read_input_token_cost": 2e-07, @@ -13212,7 +13388,8 @@ "supports_tool_choice": true, "supports_video_input": true, "supports_vision": true, - "supports_web_search": true + "supports_web_search": true, + "supports_native_streaming": true }, "vertex_ai/gemini-3-flash-preview": { "cache_read_input_token_cost": 5e-08, @@ -13255,7 +13432,8 @@ "supports_tool_choice": true, "supports_video_input": true, "supports_vision": true, - "supports_web_search": true + "supports_web_search": true, + "supports_native_streaming": true }, "gemini-2.5-pro-exp-03-25": { "cache_read_input_token_cost": 1.25e-07, @@ -13480,6 +13658,79 @@ "supports_vision": true, "supports_web_search": true }, + "gemini-robotics-er-1.5-preview": { + "cache_read_input_token_cost": 0, + "input_cost_per_token": 3e-07, + "input_cost_per_audio_token": 1e-06, + "litellm_provider": "vertex_ai-language-models", + "max_input_tokens": 1048576, + "max_output_tokens": 65535, + "max_tokens": 65535, + "mode": "chat", + "output_cost_per_token": 2.5e-06, + "output_cost_per_reasoning_token": 2.5e-06, + "source": "https://ai.google.dev/gemini-api/docs/models#gemini-robotics-er-1-5-preview", + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/completions" + ], + "supported_modalities": [ + "text", + "image", + "video", + "audio" + ], + "supported_output_modalities": [ + "text" + ], + "supports_audio_output": false, + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": false, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_url_context": true, + "supports_vision": true + }, + "gemini/gemini-robotics-er-1.5-preview": { + "cache_read_input_token_cost": 0, + "input_cost_per_token": 3e-07, + "input_cost_per_audio_token": 1e-06, + "litellm_provider": "gemini", + "max_input_tokens": 1048576, + "max_output_tokens": 65535, + "max_tokens": 65535, + "mode": "chat", + "output_cost_per_token": 2.5e-06, + "output_cost_per_reasoning_token": 2.5e-06, + "source": "https://ai.google.dev/gemini-api/docs/models#gemini-robotics-er-1-5-preview", + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/completions" + ], + "supported_modalities": [ + "text", + "image", + "video", + "audio" + ], + "supported_output_modalities": [ + "text" + ], + "supports_audio_output": false, + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": false, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_url_context": true, + "supports_vision": true, + "supports_web_search": true + }, "gemini-2.5-computer-use-preview-10-2025": { "input_cost_per_token": 1.25e-06, "input_cost_per_token_above_200k_tokens": 2.5e-06, @@ -14549,6 +14800,42 @@ "supports_vision": true, "supports_web_search": true }, + "gemini/deep-research-pro-preview-12-2025": { + "input_cost_per_image": 0.0011, + "input_cost_per_token": 2e-06, + "input_cost_per_token_batches": 1e-06, + "litellm_provider": "gemini", + "max_input_tokens": 65536, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "image_generation", + "output_cost_per_image": 0.134, + "output_cost_per_image_token": 0.00012, + "output_cost_per_token": 1.2e-05, + "rpm": 1000, + "tpm": 4000000, + "output_cost_per_token_batches": 6e-06, + "source": "https://ai.google.dev/gemini-api/docs/pricing", + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/completions", + "/v1/batch" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text", + "image" + ], + "supports_function_calling": false, + "supports_prompt_caching": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_vision": true, + "supports_web_search": true + }, "gemini/gemini-2.5-flash-lite": { "cache_read_input_token_cost": 1e-08, "input_cost_per_audio_token": 3e-07, @@ -15133,6 +15420,7 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, + "supports_native_streaming": true, "tpm": 800000 }, "gemini-3-flash-preview": { @@ -15178,7 +15466,8 @@ "supports_tool_choice": true, "supports_url_context": true, "supports_vision": true, - "supports_web_search": true + "supports_web_search": true, + "supports_native_streaming": true }, "gemini/gemini-2.5-pro-exp-03-25": { "cache_read_input_token_cost": 0.0, @@ -18609,7 +18898,7 @@ "input_cost_per_token": 1.75e-06, "input_cost_per_token_priority": 3.5e-06, "litellm_provider": "openai", - "max_input_tokens": 400000, + "max_input_tokens": 272000, "max_output_tokens": 128000, "max_tokens": 128000, "mode": "responses", @@ -20549,6 +20838,7 @@ "supports_function_calling": true, "supports_tool_choice": true, "supports_prompt_caching": true, + "supports_reasoning": true, "supports_system_messages": true, "max_input_tokens": 1000000, "max_output_tokens": 8192 @@ -20563,6 +20853,7 @@ "supports_function_calling": true, "supports_tool_choice": true, "supports_prompt_caching": true, + "supports_reasoning": true, "supports_system_messages": true, "max_input_tokens": 1000000, "max_output_tokens": 8192 @@ -20577,6 +20868,7 @@ "supports_function_calling": true, "supports_tool_choice": true, "supports_prompt_caching": true, + "supports_reasoning": true, "supports_system_messages": true, "max_input_tokens": 200000, "max_output_tokens": 8192 @@ -21272,6 +21564,20 @@ "supports_tool_choice": true, "supports_web_search": true }, + "moonshot/kimi-k2.5": { + "cache_read_input_token_cost": 1e-07, + "input_cost_per_token": 6e-07, + "litellm_provider": "moonshot", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 3e-06, + "source": "https://platform.moonshot.ai/docs/pricing/chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_vision": true + }, "moonshot/kimi-latest": { "cache_read_input_token_cost": 1.5e-07, "input_cost_per_token": 2e-06, @@ -23461,7 +23767,7 @@ "mode": "chat", "output_cost_per_token": 1.02e-06, "supports_function_calling": true, - "supports_prompt_caching": false, + "supports_prompt_caching": true, "supports_reasoning": true, "supports_tool_choice": true }, @@ -23597,6 +23903,20 @@ "output_cost_per_token": 6.5e-07, "supports_tool_choice": true }, + "openrouter/moonshotai/kimi-k2.5": { + "cache_read_input_token_cost": 1e-07, + "input_cost_per_token": 6e-07, + "litellm_provider": "openrouter", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 3e-06, + "source": "https://openrouter.ai/moonshotai/kimi-k2.5", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_vision": true + }, "openrouter/nousresearch/nous-hermes-llama2-13b": { "input_cost_per_token": 2e-07, "litellm_provider": "openrouter", @@ -23810,11 +24130,14 @@ "cache_read_input_token_cost": 1.75e-07, "input_cost_per_token": 1.75e-06, "litellm_provider": "openrouter", - "max_input_tokens": 400000, + "max_input_tokens": 272000, "max_output_tokens": 128000, "max_tokens": 128000, - "mode": "chat", + "mode": "responses", "output_cost_per_token": 1.4e-05, + "supported_endpoints": [ + "/v1/responses" + ], "supported_modalities": [ "text", "image" @@ -24153,6 +24476,7 @@ "output_cost_per_token": 1.75e-06, "source": "https://openrouter.ai/z-ai/glm-4.6", "supports_function_calling": true, + "supports_prompt_caching": true, "supports_reasoning": true, "supports_tool_choice": true }, @@ -24166,9 +24490,76 @@ "output_cost_per_token": 1.9e-06, "source": "https://openrouter.ai/z-ai/glm-4.6:exacto", "supports_function_calling": true, + "supports_prompt_caching": true, "supports_reasoning": true, "supports_tool_choice": true }, + "openrouter/xiaomi/mimo-v2-flash": { + "input_cost_per_token": 9e-08, + "output_cost_per_token": 2.9e-07, + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 0.0, + "litellm_provider": "openrouter", + "max_input_tokens": 262144, + "max_output_tokens": 16384, + "max_tokens": 16384, + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_reasoning": true, + "supports_vision": false, + "supports_prompt_caching": false + }, + "openrouter/z-ai/glm-4.7": { + "input_cost_per_token": 4e-07, + "output_cost_per_token": 1.5e-06, + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 0.0, + "litellm_provider": "openrouter", + "max_input_tokens": 202752, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_reasoning": true, + "supports_vision": true, + "supports_prompt_caching": false, + "supports_assistant_prefill": true + }, + "openrouter/z-ai/glm-4.7-flash": { + "input_cost_per_token": 7e-08, + "output_cost_per_token": 4e-07, + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 0.0, + "litellm_provider": "openrouter", + "max_input_tokens": 200000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_reasoning": true, + "supports_vision": true, + "supports_prompt_caching": false + }, + "openrouter/minimax/minimax-m2.1": { + "input_cost_per_token": 2.7e-07, + "output_cost_per_token": 1.2e-06, + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 0.0, + "litellm_provider": "openrouter", + "max_input_tokens": 204000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_reasoning": true, + "supports_vision": true, + "supports_prompt_caching": false, + "supports_computer_use": false + }, "ovhcloud/DeepSeek-R1-Distill-Llama-70B": { "input_cost_per_token": 6.7e-07, "litellm_provider": "ovhcloud", @@ -26033,13 +26424,13 @@ "litellm_provider": "bedrock", "max_input_tokens": 77, "mode": "image_edit", - "output_cost_per_image": 0.40 + "output_cost_per_image": 0.4 }, "stability.stable-creative-upscale-v1:0": { "litellm_provider": "bedrock", "max_input_tokens": 77, "mode": "image_edit", - "output_cost_per_image": 0.60 + "output_cost_per_image": 0.6 }, "stability.stable-fast-upscale-v1:0": { "litellm_provider": "bedrock", @@ -26798,6 +27189,34 @@ "supports_reasoning": true, "supports_tool_choice": true }, + "together_ai/zai-org/GLM-4.7": { + "input_cost_per_token": 4.5e-07, + "litellm_provider": "together_ai", + "max_input_tokens": 200000, + "max_output_tokens": 200000, + "max_tokens": 200000, + "mode": "chat", + "output_cost_per_token": 2e-06, + "source": "https://www.together.ai/models/glm-4-7", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "together_ai/moonshotai/Kimi-K2.5": { + "input_cost_per_token": 5e-07, + "litellm_provider": "together_ai", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "chat", + "output_cost_per_token": 2.8e-06, + "source": "https://www.together.ai/models/kimi-k2-5", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_vision": true, + "supports_reasoning": true + }, "together_ai/moonshotai/Kimi-K2-Instruct-0905": { "input_cost_per_token": 1e-06, "litellm_provider": "together_ai", @@ -27514,7 +27933,9 @@ "max_output_tokens": 16384, "max_tokens": 16384, "mode": "chat", - "output_cost_per_token": 3e-07 + "output_cost_per_token": 3e-07, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/alibaba/qwen3-coder": { "input_cost_per_token": 4e-07, @@ -27523,7 +27944,9 @@ "max_output_tokens": 66536, "max_tokens": 66536, "mode": "chat", - "output_cost_per_token": 1.6e-06 + "output_cost_per_token": 1.6e-06, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/amazon/nova-lite": { "input_cost_per_token": 6e-08, @@ -27532,7 +27955,10 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 2.4e-07 + "output_cost_per_token": 2.4e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_response_schema": true }, "vercel_ai_gateway/amazon/nova-micro": { "input_cost_per_token": 3.5e-08, @@ -27541,7 +27967,9 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 1.4e-07 + "output_cost_per_token": 1.4e-07, + "supports_function_calling": true, + "supports_response_schema": true }, "vercel_ai_gateway/amazon/nova-pro": { "input_cost_per_token": 8e-07, @@ -27550,7 +27978,10 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 3.2e-06 + "output_cost_per_token": 3.2e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_response_schema": true }, "vercel_ai_gateway/amazon/titan-embed-text-v2": { "input_cost_per_token": 2e-08, @@ -27570,7 +28001,11 @@ "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", - "output_cost_per_token": 1.25e-06 + "output_cost_per_token": 1.25e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/anthropic/claude-3-opus": { "cache_creation_input_token_cost": 1.875e-05, @@ -27581,7 +28016,11 @@ "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", - "output_cost_per_token": 7.5e-05 + "output_cost_per_token": 7.5e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/anthropic/claude-3.5-haiku": { "cache_creation_input_token_cost": 1e-06, @@ -27592,7 +28031,11 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 4e-06 + "output_cost_per_token": 4e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/anthropic/claude-3.5-sonnet": { "cache_creation_input_token_cost": 3.75e-06, @@ -27603,7 +28046,11 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 1.5e-05 + "output_cost_per_token": 1.5e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/anthropic/claude-3.7-sonnet": { "cache_creation_input_token_cost": 3.75e-06, @@ -27614,7 +28061,11 @@ "max_output_tokens": 64000, "max_tokens": 64000, "mode": "chat", - "output_cost_per_token": 1.5e-05 + "output_cost_per_token": 1.5e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/anthropic/claude-4-opus": { "cache_creation_input_token_cost": 1.875e-05, @@ -27625,7 +28076,11 @@ "max_output_tokens": 32000, "max_tokens": 32000, "mode": "chat", - "output_cost_per_token": 7.5e-05 + "output_cost_per_token": 7.5e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/anthropic/claude-4-sonnet": { "cache_creation_input_token_cost": 3.75e-06, @@ -27636,7 +28091,9 @@ "max_output_tokens": 64000, "max_tokens": 64000, "mode": "chat", - "output_cost_per_token": 1.5e-05 + "output_cost_per_token": 1.5e-05, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/cohere/command-a": { "input_cost_per_token": 2.5e-06, @@ -27645,7 +28102,9 @@ "max_output_tokens": 8000, "max_tokens": 8000, "mode": "chat", - "output_cost_per_token": 1e-05 + "output_cost_per_token": 1e-05, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/cohere/command-r": { "input_cost_per_token": 1.5e-07, @@ -27654,7 +28113,9 @@ "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", - "output_cost_per_token": 6e-07 + "output_cost_per_token": 6e-07, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/cohere/command-r-plus": { "input_cost_per_token": 2.5e-06, @@ -27663,7 +28124,9 @@ "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", - "output_cost_per_token": 1e-05 + "output_cost_per_token": 1e-05, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/cohere/embed-v4.0": { "input_cost_per_token": 1.2e-07, @@ -27681,7 +28144,8 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 2.19e-06 + "output_cost_per_token": 2.19e-06, + "supports_tool_choice": true }, "vercel_ai_gateway/deepseek/deepseek-r1-distill-llama-70b": { "input_cost_per_token": 7.5e-07, @@ -27690,7 +28154,10 @@ "max_output_tokens": 131072, "max_tokens": 131072, "mode": "chat", - "output_cost_per_token": 9.9e-07 + "output_cost_per_token": 9.9e-07, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/deepseek/deepseek-v3": { "input_cost_per_token": 9e-07, @@ -27699,7 +28166,8 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 9e-07 + "output_cost_per_token": 9e-07, + "supports_tool_choice": true }, "vercel_ai_gateway/google/gemini-2.0-flash": { "deprecation_date": "2026-03-31", @@ -27709,7 +28177,11 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 6e-07 + "output_cost_per_token": 6e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/google/gemini-2.0-flash-lite": { "deprecation_date": "2026-03-31", @@ -27719,7 +28191,11 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 3e-07 + "output_cost_per_token": 3e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/google/gemini-2.5-flash": { "input_cost_per_token": 3e-07, @@ -27728,7 +28204,11 @@ "max_output_tokens": 65536, "max_tokens": 65536, "mode": "chat", - "output_cost_per_token": 2.5e-06 + "output_cost_per_token": 2.5e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/google/gemini-2.5-pro": { "input_cost_per_token": 2.5e-06, @@ -27737,7 +28217,11 @@ "max_output_tokens": 65536, "max_tokens": 65536, "mode": "chat", - "output_cost_per_token": 1e-05 + "output_cost_per_token": 1e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/google/gemini-embedding-001": { "input_cost_per_token": 1.5e-07, @@ -27755,7 +28239,10 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 2e-07 + "output_cost_per_token": 2e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/google/text-embedding-005": { "input_cost_per_token": 2.5e-08, @@ -27791,7 +28278,8 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 7.9e-07 + "output_cost_per_token": 7.9e-07, + "supports_tool_choice": true }, "vercel_ai_gateway/meta/llama-3-8b": { "input_cost_per_token": 5e-08, @@ -27800,7 +28288,8 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 8e-08 + "output_cost_per_token": 8e-08, + "supports_tool_choice": true }, "vercel_ai_gateway/meta/llama-3.1-70b": { "input_cost_per_token": 7.2e-07, @@ -27809,7 +28298,8 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 7.2e-07 + "output_cost_per_token": 7.2e-07, + "supports_tool_choice": true }, "vercel_ai_gateway/meta/llama-3.1-8b": { "input_cost_per_token": 5e-08, @@ -27818,7 +28308,9 @@ "max_output_tokens": 131072, "max_tokens": 131072, "mode": "chat", - "output_cost_per_token": 8e-08 + "output_cost_per_token": 8e-08, + "supports_function_calling": true, + "supports_response_schema": true }, "vercel_ai_gateway/meta/llama-3.2-11b": { "input_cost_per_token": 1.6e-07, @@ -27827,7 +28319,10 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 1.6e-07 + "output_cost_per_token": 1.6e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/meta/llama-3.2-1b": { "input_cost_per_token": 1e-07, @@ -27845,7 +28340,9 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 1.5e-07 + "output_cost_per_token": 1.5e-07, + "supports_function_calling": true, + "supports_response_schema": true }, "vercel_ai_gateway/meta/llama-3.2-90b": { "input_cost_per_token": 7.2e-07, @@ -27854,7 +28351,10 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 7.2e-07 + "output_cost_per_token": 7.2e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/meta/llama-3.3-70b": { "input_cost_per_token": 7.2e-07, @@ -27863,7 +28363,9 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 7.2e-07 + "output_cost_per_token": 7.2e-07, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/meta/llama-4-maverick": { "input_cost_per_token": 2e-07, @@ -27872,7 +28374,8 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 6e-07 + "output_cost_per_token": 6e-07, + "supports_tool_choice": true }, "vercel_ai_gateway/meta/llama-4-scout": { "input_cost_per_token": 1e-07, @@ -27881,7 +28384,10 @@ "max_output_tokens": 8192, "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 3e-07 + "output_cost_per_token": 3e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/mistral/codestral": { "input_cost_per_token": 3e-07, @@ -27890,7 +28396,9 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 9e-07 + "output_cost_per_token": 9e-07, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/mistral/codestral-embed": { "input_cost_per_token": 1.5e-07, @@ -27908,7 +28416,10 @@ "max_output_tokens": 128000, "max_tokens": 128000, "mode": "chat", - "output_cost_per_token": 2.8e-07 + "output_cost_per_token": 2.8e-07, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/mistral/magistral-medium": { "input_cost_per_token": 2e-06, @@ -27917,7 +28428,10 @@ "max_output_tokens": 64000, "max_tokens": 64000, "mode": "chat", - "output_cost_per_token": 5e-06 + "output_cost_per_token": 5e-06, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/mistral/magistral-small": { "input_cost_per_token": 5e-07, @@ -27926,7 +28440,8 @@ "max_output_tokens": 64000, "max_tokens": 64000, "mode": "chat", - "output_cost_per_token": 1.5e-06 + "output_cost_per_token": 1.5e-06, + "supports_function_calling": true }, "vercel_ai_gateway/mistral/ministral-3b": { "input_cost_per_token": 4e-08, @@ -27935,7 +28450,9 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 4e-08 + "output_cost_per_token": 4e-08, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/mistral/ministral-8b": { "input_cost_per_token": 1e-07, @@ -27944,7 +28461,10 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 1e-07 + "output_cost_per_token": 1e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/mistral/mistral-embed": { "input_cost_per_token": 1e-07, @@ -27962,7 +28482,9 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 6e-06 + "output_cost_per_token": 6e-06, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/mistral/mistral-saba-24b": { "input_cost_per_token": 7.9e-07, @@ -27980,7 +28502,10 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 3e-07 + "output_cost_per_token": 3e-07, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/mistral/mixtral-8x22b-instruct": { "input_cost_per_token": 1.2e-06, @@ -27989,7 +28514,8 @@ "max_output_tokens": 2048, "max_tokens": 2048, "mode": "chat", - "output_cost_per_token": 1.2e-06 + "output_cost_per_token": 1.2e-06, + "supports_function_calling": true }, "vercel_ai_gateway/mistral/pixtral-12b": { "input_cost_per_token": 1.5e-07, @@ -27998,7 +28524,11 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 1.5e-07 + "output_cost_per_token": 1.5e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/mistral/pixtral-large": { "input_cost_per_token": 2e-06, @@ -28007,7 +28537,11 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 6e-06 + "output_cost_per_token": 6e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/moonshotai/kimi-k2": { "input_cost_per_token": 5.5e-07, @@ -28016,7 +28550,9 @@ "max_output_tokens": 16384, "max_tokens": 16384, "mode": "chat", - "output_cost_per_token": 2.2e-06 + "output_cost_per_token": 2.2e-06, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/morph/morph-v3-fast": { "input_cost_per_token": 8e-07, @@ -28043,7 +28579,9 @@ "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", - "output_cost_per_token": 1.5e-06 + "output_cost_per_token": 1.5e-06, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/openai/gpt-3.5-turbo-instruct": { "input_cost_per_token": 1.5e-06, @@ -28061,7 +28599,10 @@ "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", - "output_cost_per_token": 3e-05 + "output_cost_per_token": 3e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/openai/gpt-4.1": { "cache_creation_input_token_cost": 0.0, @@ -28072,7 +28613,11 @@ "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", - "output_cost_per_token": 8e-06 + "output_cost_per_token": 8e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/gpt-4.1-mini": { "cache_creation_input_token_cost": 0.0, @@ -28083,7 +28628,11 @@ "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", - "output_cost_per_token": 1.6e-06 + "output_cost_per_token": 1.6e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/gpt-4.1-nano": { "cache_creation_input_token_cost": 0.0, @@ -28094,7 +28643,11 @@ "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", - "output_cost_per_token": 4e-07 + "output_cost_per_token": 4e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/gpt-4o": { "cache_creation_input_token_cost": 0.0, @@ -28105,7 +28658,11 @@ "max_output_tokens": 16384, "max_tokens": 16384, "mode": "chat", - "output_cost_per_token": 1e-05 + "output_cost_per_token": 1e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/gpt-4o-mini": { "cache_creation_input_token_cost": 0.0, @@ -28116,7 +28673,11 @@ "max_output_tokens": 16384, "max_tokens": 16384, "mode": "chat", - "output_cost_per_token": 6e-07 + "output_cost_per_token": 6e-07, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/o1": { "cache_creation_input_token_cost": 0.0, @@ -28127,7 +28688,11 @@ "max_output_tokens": 100000, "max_tokens": 100000, "mode": "chat", - "output_cost_per_token": 6e-05 + "output_cost_per_token": 6e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/o3": { "cache_creation_input_token_cost": 0.0, @@ -28138,7 +28703,11 @@ "max_output_tokens": 100000, "max_tokens": 100000, "mode": "chat", - "output_cost_per_token": 8e-06 + "output_cost_per_token": 8e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/o3-mini": { "cache_creation_input_token_cost": 0.0, @@ -28149,7 +28718,10 @@ "max_output_tokens": 100000, "max_tokens": 100000, "mode": "chat", - "output_cost_per_token": 4.4e-06 + "output_cost_per_token": 4.4e-06, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/o4-mini": { "cache_creation_input_token_cost": 0.0, @@ -28160,7 +28732,11 @@ "max_output_tokens": 100000, "max_tokens": 100000, "mode": "chat", - "output_cost_per_token": 4.4e-06 + "output_cost_per_token": 4.4e-06, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true }, "vercel_ai_gateway/openai/text-embedding-3-large": { "input_cost_per_token": 1.3e-07, @@ -28232,7 +28808,10 @@ "max_output_tokens": 32000, "max_tokens": 32000, "mode": "chat", - "output_cost_per_token": 1.5e-05 + "output_cost_per_token": 1.5e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/vercel/v0-1.5-md": { "input_cost_per_token": 3e-06, @@ -28241,7 +28820,10 @@ "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", - "output_cost_per_token": 1.5e-05 + "output_cost_per_token": 1.5e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/xai/grok-2": { "input_cost_per_token": 2e-06, @@ -28250,7 +28832,9 @@ "max_output_tokens": 4000, "max_tokens": 4000, "mode": "chat", - "output_cost_per_token": 1e-05 + "output_cost_per_token": 1e-05, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/xai/grok-2-vision": { "input_cost_per_token": 2e-06, @@ -28259,7 +28843,10 @@ "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", - "output_cost_per_token": 1e-05 + "output_cost_per_token": 1e-05, + "supports_vision": true, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/xai/grok-3": { "input_cost_per_token": 3e-06, @@ -28268,7 +28855,9 @@ "max_output_tokens": 131072, "max_tokens": 131072, "mode": "chat", - "output_cost_per_token": 1.5e-05 + "output_cost_per_token": 1.5e-05, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/xai/grok-3-fast": { "input_cost_per_token": 5e-06, @@ -28277,7 +28866,8 @@ "max_output_tokens": 131072, "max_tokens": 131072, "mode": "chat", - "output_cost_per_token": 2.5e-05 + "output_cost_per_token": 2.5e-05, + "supports_function_calling": true }, "vercel_ai_gateway/xai/grok-3-mini": { "input_cost_per_token": 3e-07, @@ -28286,7 +28876,9 @@ "max_output_tokens": 131072, "max_tokens": 131072, "mode": "chat", - "output_cost_per_token": 5e-07 + "output_cost_per_token": 5e-07, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/xai/grok-3-mini-fast": { "input_cost_per_token": 6e-07, @@ -28295,7 +28887,9 @@ "max_output_tokens": 131072, "max_tokens": 131072, "mode": "chat", - "output_cost_per_token": 4e-06 + "output_cost_per_token": 4e-06, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/xai/grok-4": { "input_cost_per_token": 3e-06, @@ -28304,7 +28898,9 @@ "max_output_tokens": 256000, "max_tokens": 256000, "mode": "chat", - "output_cost_per_token": 1.5e-05 + "output_cost_per_token": 1.5e-05, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/zai/glm-4.5": { "input_cost_per_token": 6e-07, @@ -28313,7 +28909,9 @@ "max_output_tokens": 131072, "max_tokens": 131072, "mode": "chat", - "output_cost_per_token": 2.2e-06 + "output_cost_per_token": 2.2e-06, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/zai/glm-4.5-air": { "input_cost_per_token": 2e-07, @@ -28322,7 +28920,9 @@ "max_output_tokens": 96000, "max_tokens": 96000, "mode": "chat", - "output_cost_per_token": 1.1e-06 + "output_cost_per_token": 1.1e-06, + "supports_function_calling": true, + "supports_tool_choice": true }, "vercel_ai_gateway/zai/glm-4.6": { "litellm_provider": "vercel_ai_gateway", @@ -28390,7 +28990,9 @@ "supports_prompt_caching": true, "supports_reasoning": true, "supports_response_schema": true, - "supports_tool_choice": true + "supports_tool_choice": true, + "supports_native_streaming": true, + "supports_vision": true }, "vertex_ai/claude-3-5-sonnet": { "input_cost_per_token": 3e-06, @@ -28661,7 +29263,8 @@ "supports_response_schema": true, "supports_tool_choice": true, "supports_vision": true, - "tool_use_system_prompt_tokens": 159 + "tool_use_system_prompt_tokens": 159, + "supports_native_streaming": true }, "vertex_ai/claude-sonnet-4-5": { "cache_creation_input_token_cost": 3.75e-06, @@ -28713,7 +29316,8 @@ "supports_reasoning": true, "supports_response_schema": true, "supports_tool_choice": true, - "supports_vision": true + "supports_vision": true, + "supports_native_streaming": true }, "vertex_ai/claude-opus-4@20250514": { "cache_creation_input_token_cost": 1.875e-05, @@ -28995,6 +29599,21 @@ "output_cost_per_token_batches": 6e-06, "source": "https://docs.cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/3-pro-image" }, + "vertex_ai/deep-research-pro-preview-12-2025": { + "input_cost_per_image": 0.0011, + "input_cost_per_token": 2e-06, + "input_cost_per_token_batches": 1e-06, + "litellm_provider": "vertex_ai-language-models", + "max_input_tokens": 65536, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "image_generation", + "output_cost_per_image": 0.134, + "output_cost_per_image_token": 0.00012, + "output_cost_per_token": 1.2e-05, + "output_cost_per_token_batches": 6e-06, + "source": "https://docs.cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/3-pro-image" + }, "vertex_ai/imagegeneration@006": { "litellm_provider": "vertex_ai-image-models", "mode": "image_generation", @@ -29484,6 +30103,9 @@ "mode": "chat", "output_cost_per_token": 1e-06, "source": "https://cloud.google.com/vertex-ai/generative-ai/pricing", + "supported_regions": [ + "global" + ], "supports_function_calling": true, "supports_tool_choice": true }, @@ -29496,6 +30118,9 @@ "mode": "chat", "output_cost_per_token": 4e-06, "source": "https://cloud.google.com/vertex-ai/generative-ai/pricing", + "supported_regions": [ + "global" + ], "supports_function_calling": true, "supports_tool_choice": true }, @@ -29508,6 +30133,9 @@ "mode": "chat", "output_cost_per_token": 1.2e-06, "source": "https://cloud.google.com/vertex-ai/generative-ai/pricing", + "supported_regions": [ + "global" + ], "supports_function_calling": true, "supports_tool_choice": true }, @@ -29520,6 +30148,9 @@ "mode": "chat", "output_cost_per_token": 1.2e-06, "source": "https://cloud.google.com/vertex-ai/generative-ai/pricing", + "supported_regions": [ + "global" + ], "supports_function_calling": true, "supports_tool_choice": true }, @@ -30382,6 +31013,7 @@ "supports_web_search": true }, "xai/grok-3": { + "cache_read_input_token_cost": 7.5e-07, "input_cost_per_token": 3e-06, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30396,6 +31028,7 @@ "supports_web_search": true }, "xai/grok-3-beta": { + "cache_read_input_token_cost": 7.5e-07, "input_cost_per_token": 3e-06, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30410,6 +31043,7 @@ "supports_web_search": true }, "xai/grok-3-fast-beta": { + "cache_read_input_token_cost": 1.25e-06, "input_cost_per_token": 5e-06, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30424,6 +31058,7 @@ "supports_web_search": true }, "xai/grok-3-fast-latest": { + "cache_read_input_token_cost": 1.25e-06, "input_cost_per_token": 5e-06, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30438,6 +31073,7 @@ "supports_web_search": true }, "xai/grok-3-latest": { + "cache_read_input_token_cost": 7.5e-07, "input_cost_per_token": 3e-06, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30452,6 +31088,7 @@ "supports_web_search": true }, "xai/grok-3-mini": { + "cache_read_input_token_cost": 7.5e-08, "input_cost_per_token": 3e-07, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30467,6 +31104,7 @@ "supports_web_search": true }, "xai/grok-3-mini-beta": { + "cache_read_input_token_cost": 7.5e-08, "input_cost_per_token": 3e-07, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30482,6 +31120,7 @@ "supports_web_search": true }, "xai/grok-3-mini-fast": { + "cache_read_input_token_cost": 1.5e-07, "input_cost_per_token": 6e-07, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30497,6 +31136,7 @@ "supports_web_search": true }, "xai/grok-3-mini-fast-beta": { + "cache_read_input_token_cost": 1.5e-07, "input_cost_per_token": 6e-07, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30512,6 +31152,7 @@ "supports_web_search": true }, "xai/grok-3-mini-fast-latest": { + "cache_read_input_token_cost": 1.5e-07, "input_cost_per_token": 6e-07, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30527,6 +31168,7 @@ "supports_web_search": true }, "xai/grok-3-mini-latest": { + "cache_read_input_token_cost": 7.5e-08, "input_cost_per_token": 3e-07, "litellm_provider": "xai", "max_input_tokens": 131072, @@ -30793,11 +31435,14 @@ "max_output_tokens": 128000, "mode": "chat", "supports_function_calling": true, + "supports_prompt_caching": true, "supports_reasoning": true, "supports_tool_choice": true, "source": "https://docs.z.ai/guides/overview/pricing" }, "zai/glm-4.6": { + "cache_creation_input_token_cost": 0, + "cache_read_input_token_cost": 1.1e-07, "input_cost_per_token": 6e-07, "output_cost_per_token": 2.2e-06, "litellm_provider": "zai", @@ -30805,6 +31450,8 @@ "max_output_tokens": 128000, "mode": "chat", "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, "supports_tool_choice": true, "source": "https://docs.z.ai/guides/overview/pricing" }, diff --git a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py index 49d6ac7d898..7e70b5baae4 100644 --- a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py +++ b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py @@ -387,6 +387,9 @@ class MCPRequestHandler: user_api_key_cache, ) + verbose_logger.debug( + f"MCP team permission lookup: team_id={user_api_key_auth.team_id if user_api_key_auth else None}" + ) if not user_api_key_auth or not user_api_key_auth.team_id or not prisma_client: return None diff --git a/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py b/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py index ded591a8f53..56feff548ad 100644 --- a/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py +++ b/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py @@ -387,25 +387,57 @@ async def callback(code: str, state: str): 1. Try resource_metadata from WWW-Authenticate header (if present) 2. Fall back to path-based well-known URI: /.well-known/oauth-protected-resource/{path} ( - If the resource identifier value contains a path or query component, any terminating slash (/) - following the host component MUST be removed before inserting /.well-known/ and the well-known - URI path suffix between the host component and the path(include root path) and/or query components. + If the resource identifier value contains a path or query component, any terminating slash (/) + following the host component MUST be removed before inserting /.well-known/ and the well-known + URI path suffix between the host component and the path(include root path) and/or query components. https://datatracker.ietf.org/doc/html/rfc9728#section-3.1) 3. Fall back to root-based well-known URI: /.well-known/oauth-protected-resource + + Dual Pattern Support: + - Standard MCP pattern: /mcp/{server_name} (recommended, used by mcp-inspector, VSCode Copilot) + - LiteLLM legacy pattern: /{server_name}/mcp (backward compatibility) + + The resource URL returned matches the pattern used in the discovery request. """ -@router.get(f"/.well-known/oauth-protected-resource{'' if get_server_root_path() == '/' else get_server_root_path()}/{{mcp_server_name}}/mcp") -@router.get("/.well-known/oauth-protected-resource") -async def oauth_protected_resource_mcp( - request: Request, mcp_server_name: Optional[str] = None -): + + +def _build_oauth_protected_resource_response( + request: Request, + mcp_server_name: Optional[str], + use_standard_pattern: bool, +) -> dict: + """ + Build OAuth protected resource response with the appropriate URL pattern. + + Args: + request: FastAPI Request object + mcp_server_name: Name of the MCP server + use_standard_pattern: If True, use /mcp/{server_name} pattern; + if False, use /{server_name}/mcp pattern + + Returns: + OAuth protected resource metadata dict + """ from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( global_mcp_server_manager, ) - # Get the correct base URL considering X-Forwarded-* headers + request_base_url = get_request_base_url(request) mcp_server: Optional[MCPServer] = None if mcp_server_name: mcp_server = global_mcp_server_manager.get_mcp_server_by_name(mcp_server_name) + + # Build resource URL based on the pattern + if mcp_server_name: + if use_standard_pattern: + # Standard MCP pattern: /mcp/{server_name} + resource_url = f"{request_base_url}/mcp/{mcp_server_name}" + else: + # LiteLLM legacy pattern: /{server_name}/mcp + resource_url = f"{request_base_url}/{mcp_server_name}/mcp" + else: + resource_url = f"{request_base_url}/mcp" + return { "authorization_servers": [ ( @@ -414,14 +446,55 @@ async def oauth_protected_resource_mcp( else f"{request_base_url}" ) ], - "resource": ( - f"{request_base_url}/{mcp_server_name}/mcp" - if mcp_server_name - else f"{request_base_url}/mcp" - ), # this is what Claude will call + "resource": resource_url, "scopes_supported": mcp_server.scopes if mcp_server else [], } + +# Standard MCP pattern: /.well-known/oauth-protected-resource/mcp/{server_name} +# This is the pattern expected by standard MCP clients (mcp-inspector, VSCode Copilot) +@router.get(f"/.well-known/oauth-protected-resource{'' if get_server_root_path() == '/' else get_server_root_path()}/mcp/{{mcp_server_name}}") +async def oauth_protected_resource_mcp_standard( + request: Request, mcp_server_name: str +): + """ + OAuth protected resource discovery endpoint using standard MCP URL pattern. + + Standard pattern: /mcp/{server_name} + Discovery path: /.well-known/oauth-protected-resource/mcp/{server_name} + + This endpoint is compliant with MCP specification and works with standard + MCP clients like mcp-inspector and VSCode Copilot. + """ + return _build_oauth_protected_resource_response( + request=request, + mcp_server_name=mcp_server_name, + use_standard_pattern=True, + ) + + +# LiteLLM legacy pattern: /.well-known/oauth-protected-resource/{server_name}/mcp +# Kept for backward compatibility with existing deployments +@router.get(f"/.well-known/oauth-protected-resource{'' if get_server_root_path() == '/' else get_server_root_path()}/{{mcp_server_name}}/mcp") +@router.get("/.well-known/oauth-protected-resource") +async def oauth_protected_resource_mcp( + request: Request, mcp_server_name: Optional[str] = None +): + """ + OAuth protected resource discovery endpoint using LiteLLM legacy URL pattern. + + Legacy pattern: /{server_name}/mcp + Discovery path: /.well-known/oauth-protected-resource/{server_name}/mcp + + This endpoint is kept for backward compatibility. New integrations should + use the standard MCP pattern (/mcp/{server_name}) instead. + """ + return _build_oauth_protected_resource_response( + request=request, + mcp_server_name=mcp_server_name, + use_standard_pattern=False, + ) + """ https://datatracker.ietf.org/doc/html/rfc8414#section-3.1 RFC 8414: Path-aware OAuth discovery @@ -430,15 +503,26 @@ async def oauth_protected_resource_mcp( the well-known URI suffix between the host component and the path(include root path) component. """ -@router.get(f"/.well-known/oauth-authorization-server{'' if get_server_root_path() == '/' else get_server_root_path()}/{{mcp_server_name}}") -@router.get("/.well-known/oauth-authorization-server") -async def oauth_authorization_server_mcp( - request: Request, mcp_server_name: Optional[str] = None -): + + +def _build_oauth_authorization_server_response( + request: Request, + mcp_server_name: Optional[str], +) -> dict: + """ + Build OAuth authorization server metadata response. + + Args: + request: FastAPI Request object + mcp_server_name: Name of the MCP server + + Returns: + OAuth authorization server metadata dict + """ from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( global_mcp_server_manager, ) - # Get the correct base URL considering X-Forwarded-* headers + request_base_url = get_request_base_url(request) authorization_endpoint = ( @@ -470,18 +554,58 @@ async def oauth_authorization_server_mcp( } +# Standard MCP pattern: /.well-known/oauth-authorization-server/mcp/{server_name} +@router.get(f"/.well-known/oauth-authorization-server{'' if get_server_root_path() == '/' else get_server_root_path()}/mcp/{{mcp_server_name}}") +async def oauth_authorization_server_mcp_standard( + request: Request, mcp_server_name: str +): + """ + OAuth authorization server discovery endpoint using standard MCP URL pattern. + + Standard pattern: /mcp/{server_name} + Discovery path: /.well-known/oauth-authorization-server/mcp/{server_name} + """ + return _build_oauth_authorization_server_response( + request=request, + mcp_server_name=mcp_server_name, + ) + + +# LiteLLM legacy pattern and root endpoint +@router.get(f"/.well-known/oauth-authorization-server{'' if get_server_root_path() == '/' else get_server_root_path()}/{{mcp_server_name}}") +@router.get("/.well-known/oauth-authorization-server") +async def oauth_authorization_server_mcp( + request: Request, mcp_server_name: Optional[str] = None +): + """ + OAuth authorization server discovery endpoint. + + Supports both legacy pattern (/{server_name}) and root endpoint. + """ + return _build_oauth_authorization_server_response( + request=request, + mcp_server_name=mcp_server_name, + ) + + # Alias for standard OpenID discovery @router.get("/.well-known/openid-configuration") async def openid_configuration(request: Request): return await oauth_authorization_server_mcp(request) +# Additional legacy pattern support @router.get("/.well-known/oauth-authorization-server/{mcp_server_name}/mcp") -@router.get("/.well-known/oauth-authorization-server") -async def oauth_authorization_server_root( - request: Request, mcp_server_name: Optional[str] = None +async def oauth_authorization_server_legacy( + request: Request, mcp_server_name: str ): - return await oauth_authorization_server_mcp(request, mcp_server_name) + """ + OAuth authorization server discovery for legacy /{server_name}/mcp pattern. + """ + return _build_oauth_authorization_server_response( + request=request, + mcp_server_name=mcp_server_name, + ) @router.post("/{mcp_server_name}/register") diff --git a/litellm/proxy/_experimental/mcp_server/guardrail_translation/handler.py b/litellm/proxy/_experimental/mcp_server/guardrail_translation/handler.py index 8d6d236b884..4d53ae7059d 100644 --- a/litellm/proxy/_experimental/mcp_server/guardrail_translation/handler.py +++ b/litellm/proxy/_experimental/mcp_server/guardrail_translation/handler.py @@ -46,8 +46,13 @@ class MCPGuardrailTranslationHandler(BaseTranslation): ) return data + inputs = GenericGuardrailAPIInputs(texts=[content]) + # Include model information if available + model = data.get("model") + if model: + inputs["model"] = model guardrailed_inputs = await guardrail_to_apply.apply_guardrail( - inputs=GenericGuardrailAPIInputs(texts=[content]), + inputs=inputs, request_data=data, input_type="request", logging_obj=litellm_logging_obj, diff --git a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py index e0217cd9e00..4c17a2ff3e0 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py @@ -11,7 +11,7 @@ import datetime import hashlib import json import re -from typing import Any, Dict, List, Literal, Optional, Set, Tuple, Union, cast +from typing import Any, Callable, Dict, List, Literal, Optional, Set, Tuple, Union, cast from urllib.parse import urlparse from fastapi import HTTPException @@ -30,7 +30,6 @@ from pydantic import AnyUrl import litellm from litellm._logging import verbose_logger -from litellm.types.utils import CallTypes from litellm.exceptions import BlockedPiiEntityError, GuardrailRaisedException from litellm.experimental_mcp_client.client import MCPClient from litellm.llms.custom_httpx.http_handler import get_async_httpx_client @@ -63,7 +62,23 @@ from litellm.types.mcp_server.mcp_server_manager import ( MCPOAuthMetadata, MCPServer, ) -from mcp.shared.tool_name_validation import SEP_986_URL, validate_tool_name +from litellm.types.utils import CallTypes + +try: + from mcp.shared.tool_name_validation import ( # type: ignore + SEP_986_URL, + validate_tool_name, + ) +except ImportError: + from pydantic import BaseModel + SEP_986_URL = "https://github.com/modelcontextprotocol/protocol/blob/main/proposals/0001-tool-name-validation.md" + + class ToolNameValidationResult(BaseModel): + is_valid: bool = True + warnings: list = [] + + def validate_tool_name(name: str) -> ToolNameValidationResult: # type: ignore[misc] + return ToolNameValidationResult() # Probe includes characters on both sides of the separator to mimic real prefixed tool names. @@ -90,7 +105,9 @@ def _warn_on_server_name_fields( if result.is_valid: return - warning_text = "; ".join(result.warnings) if result.warnings else "Validation failed" + warning_text = ( + "; ".join(result.warnings) if result.warnings else "Validation failed" + ) verbose_logger.warning( "MCP server '%s' has invalid %s '%s': %s", server_id, @@ -103,7 +120,6 @@ def _warn_on_server_name_fields( _warn("server_name", server_name) - def _deserialize_json_dict(data: Any) -> Optional[Dict[str, str]]: """ Deserialize optional JSON mappings stored in the database. @@ -391,10 +407,13 @@ class MCPServerManager: # Note: `extra_headers` on MCPServer is a List[str] of header names to forward # from the client request (not available in this OpenAPI tool generation step). # `static_headers` is a dict of concrete headers to always send. - headers = merge_mcp_headers( - extra_headers=headers, - static_headers=server.static_headers, - ) or {} + headers = ( + merge_mcp_headers( + extra_headers=headers, + static_headers=server.static_headers, + ) + or {} + ) verbose_logger.debug( f"Using headers for OpenAPI tools (excluding sensitive values): " @@ -1825,6 +1844,7 @@ class MCPServerManager: oauth2_headers: Optional[Dict[str, str]], raw_headers: Optional[Dict[str, str]], proxy_logging_obj: Optional[ProxyLogging], + host_progress_callback: Optional[Callable] = None, ) -> CallToolResult: """ Call a regular MCP tool using the MCP client. @@ -1909,7 +1929,7 @@ class MCPServerManager: ) async def _call_tool_via_client(client, params): - return await client.call_tool(params) + return await client.call_tool(params, host_progress_callback=host_progress_callback) tasks.append( asyncio.create_task(_call_tool_via_client(client, call_tool_params)) @@ -1946,6 +1966,8 @@ class MCPServerManager: proxy_logging_obj: Optional[ProxyLogging] = None, oauth2_headers: Optional[Dict[str, str]] = None, raw_headers: Optional[Dict[str, str]] = None, + host_progress_callback: Optional[Callable] = None, + ) -> CallToolResult: """ Call a tool with the given name and arguments @@ -2021,6 +2043,7 @@ class MCPServerManager: oauth2_headers=oauth2_headers, raw_headers=raw_headers, proxy_logging_obj=proxy_logging_obj, + host_progress_callback=host_progress_callback, ) # For OpenAPI tools, await outside the client context diff --git a/litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py b/litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py new file mode 100644 index 00000000000..e5cb6a0098d --- /dev/null +++ b/litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py @@ -0,0 +1,250 @@ +""" +Semantic MCP Tool Filtering using semantic-router + +Filters MCP tools semantically for /chat/completions and /responses endpoints. +""" +from typing import TYPE_CHECKING, Any, Dict, List, Optional + +from litellm._logging import verbose_logger + +if TYPE_CHECKING: + from semantic_router.routers import SemanticRouter + + from litellm.router import Router + + +class SemanticMCPToolFilter: + """Filters MCP tools using semantic similarity to reduce context window size.""" + + def __init__( + self, + embedding_model: str, + litellm_router_instance: "Router", + top_k: int = 10, + similarity_threshold: float = 0.3, + enabled: bool = True, + ): + """ + Initialize the semantic tool filter. + + Args: + embedding_model: Model to use for embeddings (e.g., "text-embedding-3-small") + litellm_router_instance: Router instance for embedding generation + top_k: Maximum number of tools to return + similarity_threshold: Minimum similarity score for filtering + enabled: Whether filtering is enabled + """ + self.enabled = enabled + self.top_k = top_k + self.similarity_threshold = similarity_threshold + self.embedding_model = embedding_model + self.router_instance = litellm_router_instance + self.tool_router: Optional["SemanticRouter"] = None + self._tool_map: Dict[str, Any] = {} # MCPTool objects or OpenAI function dicts + + async def build_router_from_mcp_registry(self) -> None: + """Build semantic router from all MCP tools in the registry (no auth checks).""" + from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( + global_mcp_server_manager, + ) + + try: + # Get all servers from registry without auth checks + registry = global_mcp_server_manager.get_registry() + if not registry: + verbose_logger.warning("MCP registry is empty") + self.tool_router = None + return + + # Fetch tools from all servers in parallel + all_tools = [] + for server_id, server in registry.items(): + try: + tools = await global_mcp_server_manager.get_tools_for_server(server_id) + all_tools.extend(tools) + except Exception as e: + verbose_logger.warning(f"Failed to fetch tools from server {server_id}: {e}") + continue + + if not all_tools: + verbose_logger.warning("No MCP tools found in registry") + self.tool_router = None + return + + verbose_logger.info(f"Fetched {len(all_tools)} tools from {len(registry)} MCP servers") + self._build_router(all_tools) + + except Exception as e: + verbose_logger.error(f"Failed to build router from MCP registry: {e}") + self.tool_router = None + raise + + def _extract_tool_info(self, tool) -> tuple[str, str]: + """Extract name and description from MCP tool or OpenAI function dict.""" + name: str + description: str + + if isinstance(tool, dict): + # OpenAI function format + name = tool.get("name", "") + description = tool.get("description", name) + else: + # MCPTool object + name = str(tool.name) + description = str(tool.description) if tool.description else str(tool.name) + + return name, description + + def _build_router(self, tools: List) -> None: + """Build semantic router with tools (MCPTool objects or OpenAI function dicts).""" + from semantic_router.routers import SemanticRouter + from semantic_router.routers.base import Route + + from litellm.router_strategy.auto_router.litellm_encoder import ( + LiteLLMRouterEncoder, + ) + + if not tools: + self.tool_router = None + return + + try: + # Convert tools to routes + routes = [] + self._tool_map = {} + + for tool in tools: + name, description = self._extract_tool_info(tool) + self._tool_map[name] = tool + + routes.append( + Route( + name=name, + description=description, + utterances=[description], + score_threshold=self.similarity_threshold, + ) + ) + + self.tool_router = SemanticRouter( + routes=routes, + encoder=LiteLLMRouterEncoder( + litellm_router_instance=self.router_instance, + model_name=self.embedding_model, + score_threshold=self.similarity_threshold, + ), + auto_sync="local", + ) + + verbose_logger.info( + f"Built semantic router with {len(routes)} tools" + ) + + except Exception as e: + verbose_logger.error(f"Failed to build semantic router: {e}") + self.tool_router = None + raise + + async def filter_tools( + self, + query: str, + available_tools: List[Any], + top_k: Optional[int] = None, + ) -> List[Any]: + """ + Filter tools semantically based on query. + + Args: + query: User query to match against tools + available_tools: Full list of available MCP tools + top_k: Override default top_k (optional) + + Returns: + Filtered and ordered list of tools (up to top_k) + """ + # Early returns for cases where we can't/shouldn't filter + if not self.enabled: + return available_tools + + if not available_tools: + return available_tools + + if not query or not query.strip(): + return available_tools + + # Router should be built on startup - if not, something went wrong + if self.tool_router is None: + verbose_logger.warning("Router not initialized - was build_router_from_mcp_registry() called on startup?") + return available_tools + + # Run semantic filtering + try: + limit = top_k or self.top_k + matches = self.tool_router(text=query, limit=limit) + matched_tool_names = self._extract_tool_names_from_matches(matches) + + if not matched_tool_names: + return available_tools + + return self._get_tools_by_names(matched_tool_names, available_tools) + + except Exception as e: + verbose_logger.error(f"Semantic tool filter failed: {e}", exc_info=True) + return available_tools + + def _extract_tool_names_from_matches(self, matches) -> List[str]: + """Extract tool names from semantic router match results.""" + if not matches: + return [] + + # Handle single match + if hasattr(matches, "name") and matches.name: + return [matches.name] + + # Handle list of matches + if isinstance(matches, list): + return [m.name for m in matches if hasattr(m, "name") and m.name] + + return [] + + def _get_tools_by_names( + self, tool_names: List[str], available_tools: List[Any] + ) -> List[Any]: + """Get tools from available_tools by their names, preserving order.""" + # Match tools from available_tools (preserves format - dict or MCPTool) + matched_tools = [] + for tool in available_tools: + tool_name, _ = self._extract_tool_info(tool) + if tool_name in tool_names: + matched_tools.append(tool) + + # Reorder to match semantic router's ordering + tool_map = {self._extract_tool_info(t)[0]: t for t in matched_tools} + return [tool_map[name] for name in tool_names if name in tool_map] + + def extract_user_query(self, messages: List[Dict[str, Any]]) -> str: + """ + Extract user query from messages for /chat/completions or /responses. + + Args: + messages: List of message dictionaries (from 'messages' or 'input' field) + + Returns: + Extracted query string + """ + for msg in reversed(messages): + if msg.get("role") == "user": + content = msg.get("content", "") + + if isinstance(content, str): + return content + + if isinstance(content, list): + texts = [ + block.get("text", "") if isinstance(block, dict) else str(block) + for block in content + if isinstance(block, (dict, str)) + ] + return " ".join(texts) + + return "" diff --git a/litellm/proxy/_experimental/mcp_server/server.py b/litellm/proxy/_experimental/mcp_server/server.py index 03652ae155e..79cd88227a9 100644 --- a/litellm/proxy/_experimental/mcp_server/server.py +++ b/litellm/proxy/_experimental/mcp_server/server.py @@ -8,8 +8,7 @@ import contextlib from datetime import datetime import traceback import uuid -from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union, cast - +from typing import Any, AsyncIterator, Dict, List, Optional, Tuple, Union, cast, Callable from fastapi import FastAPI, HTTPException from pydantic import AnyUrl, ConfigDict from starlette.types import Receive, Scope, Send @@ -74,7 +73,11 @@ if MCP_AVAILABLE: AuthContextMiddleware, auth_context_var, ) - from mcp.server.streamable_http_manager import StreamableHTTPSessionManager + + try: + from mcp.server.streamable_http_manager import StreamableHTTPSessionManager + except ImportError: + StreamableHTTPSessionManager = None # type: ignore from mcp.types import ( CallToolResult, EmbeddedResource, @@ -124,8 +127,8 @@ if MCP_AVAILABLE: session_manager = StreamableHTTPSessionManager( app=server, event_store=None, - json_response=True, # Use JSON responses instead of SSE by default - stateless=True, + json_response=False, # enables SSE streaming + stateless=False, # enables session state ) # Create SSE session manager @@ -278,6 +281,30 @@ if MCP_AVAILABLE: verbose_logger.debug( f"MCP mcp_server_tool_call - User API Key Auth from context: {user_api_key_auth}" ) + host_progress_callback = None + try: + host_ctx = server.request_context + if host_ctx and hasattr(host_ctx, 'meta') and host_ctx.meta: + host_token = getattr(host_ctx.meta, 'progressToken', None) + if host_token and hasattr(host_ctx, 'session') and host_ctx.session: + host_session = host_ctx.session + + async def forward_progress(progress: float, total: float | None): + """Forward progress notifications from external MCP to Host""" + try: + await host_session.send_progress_notification( + progress_token=host_token, + progress=progress, + total=total + ) + verbose_logger.debug(f"Forwarded progress {progress}/{total} to Host") + except Exception as e: + verbose_logger.error(f"Failed to forward progress to Host: {e}") + + host_progress_callback = forward_progress + verbose_logger.debug(f"Host progressToken captured: {host_token[:8]}...") + except Exception as e: + verbose_logger.warning(f"Could not capture host progress context: {e}") try: # Create a body date for logging body_data = {"name": name, "arguments": arguments} @@ -307,6 +334,7 @@ if MCP_AVAILABLE: mcp_server_auth_headers=mcp_server_auth_headers, oauth2_headers=oauth2_headers, raw_headers=raw_headers, + host_progress_callback=host_progress_callback, **data, # for logging ) except BlockedPiiEntityError as e: @@ -1341,6 +1369,7 @@ if MCP_AVAILABLE: mcp_server_auth_headers: Optional[Dict[str, Dict[str, str]]] = None, oauth2_headers: Optional[Dict[str, str]] = None, raw_headers: Optional[Dict[str, str]] = None, + host_progress_callback: Optional[Callable] = None, **kwargs: Any, ) -> CallToolResult: """ @@ -1438,6 +1467,7 @@ if MCP_AVAILABLE: oauth2_headers=oauth2_headers, raw_headers=raw_headers, litellm_logging_obj=litellm_logging_obj, + host_progress_callback=host_progress_callback, ) # Fall back to local tool registry with original name (legacy support) @@ -1685,6 +1715,7 @@ if MCP_AVAILABLE: oauth2_headers: Optional[Dict[str, str]] = None, raw_headers: Optional[Dict[str, str]] = None, litellm_logging_obj: Optional[Any] = None, + host_progress_callback: Optional[Callable] = None, ) -> CallToolResult: """Handle tool execution for managed server tools""" # Import here to avoid circular import @@ -1700,6 +1731,7 @@ if MCP_AVAILABLE: oauth2_headers=oauth2_headers, raw_headers=raw_headers, proxy_logging_obj=proxy_logging_obj, + host_progress_callback=host_progress_callback, ) verbose_logger.debug("CALL TOOL RESULT: %s", call_tool_result) return call_tool_result @@ -1808,6 +1840,43 @@ if MCP_AVAILABLE: raw_headers, ) + def _strip_stale_mcp_session_header( + scope: Scope, + mgr: "StreamableHTTPSessionManager", + ) -> None: + """ + Strip stale ``mcp-session-id`` headers so the session manager + creates a fresh session instead of returning 404 "Session not found". + + When clients like VSCode reconnect after a reload they may resend a + session id that has already been cleaned up. Rather than letting the + SDK return a 404 error loop, we detect the stale id and remove the + header so a brand-new session is created transparently. + + Fixes https://github.com/BerriAI/litellm/issues/20292 + """ + _mcp_session_header = b"mcp-session-id" + _session_id: Optional[str] = None + for header_name, header_value in scope.get("headers", []): + if header_name == _mcp_session_header: + _session_id = header_value.decode("utf-8", errors="replace") + break + + if _session_id is None: + return + + known_sessions = getattr(mgr, "_server_instances", None) + if known_sessions is not None and _session_id not in known_sessions: + verbose_logger.warning( + "MCP session ID '%s' not found in active sessions. " + "Stripping stale header to force new session creation.", + _session_id, + ) + scope["headers"] = [ + (k, v) for k, v in scope["headers"] + if k != _mcp_session_header + ] + async def handle_streamable_http_mcp( scope: Scope, receive: Receive, send: Send ) -> None: @@ -1864,6 +1933,8 @@ if MCP_AVAILABLE: # Give it a moment to start up await asyncio.sleep(0.1) + _strip_stale_mcp_session_header(scope, session_manager) + await session_manager.handle_request(scope, receive, send) except Exception as e: raise e diff --git a/litellm/proxy/_experimental/out/404.html b/litellm/proxy/_experimental/out/404/index.html similarity index 95% rename from litellm/proxy/_experimental/out/404.html rename to litellm/proxy/_experimental/out/404/index.html index de67ea14285..a8bd30680ab 100644 --- a/litellm/proxy/_experimental/out/404.html +++ b/litellm/proxy/_experimental/out/404/index.html @@ -1 +1 @@ -404: This page could not be found.LiteLLM Dashboard

404

This page could not be found.

\ No newline at end of file +404: This page could not be found.LiteLLM Dashboard

404

This page could not be found.

\ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/CLoTmxFwcBe0ryZN5lcGE/_buildManifest.js b/litellm/proxy/_experimental/out/_next/static/MkHZcSjEBwlJY7dIHtt6n/_buildManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/CLoTmxFwcBe0ryZN5lcGE/_buildManifest.js rename to litellm/proxy/_experimental/out/_next/static/MkHZcSjEBwlJY7dIHtt6n/_buildManifest.js diff --git a/litellm/proxy/_experimental/out/_next/static/CLoTmxFwcBe0ryZN5lcGE/_ssgManifest.js b/litellm/proxy/_experimental/out/_next/static/MkHZcSjEBwlJY7dIHtt6n/_ssgManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/CLoTmxFwcBe0ryZN5lcGE/_ssgManifest.js rename to litellm/proxy/_experimental/out/_next/static/MkHZcSjEBwlJY7dIHtt6n/_ssgManifest.js diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1059-26bdac09bbb12a4b.js b/litellm/proxy/_experimental/out/_next/static/chunks/1059-26bdac09bbb12a4b.js new file mode 100644 index 00000000000..cd4f5e4e326 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/1059-26bdac09bbb12a4b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1059],{83669:function(t,e,r){r.d(e,{Z:function(){return c}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"}},{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}}]},name:"check-circle",theme:"outlined"},i=r(55015),c=o.forwardRef(function(t,e){return o.createElement(i.Z,(0,n.Z)({},t,{ref:e,icon:a}))})},62670:function(t,e,r){r.d(e,{Z:function(){return c}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372zm47.7-395.2l-25.4-5.9V348.6c38 5.2 61.5 29 65.5 58.2.5 4 3.9 6.9 7.9 6.9h44.9c4.7 0 8.4-4.1 8-8.8-6.1-62.3-57.4-102.3-125.9-109.2V263c0-4.4-3.6-8-8-8h-28.1c-4.4 0-8 3.6-8 8v33c-70.8 6.9-126.2 46-126.2 119 0 67.6 49.8 100.2 102.1 112.7l24.7 6.3v142.7c-44.2-5.9-69-29.5-74.1-61.3-.6-3.8-4-6.6-7.9-6.6H363c-4.7 0-8.4 4-8 8.7 4.5 55 46.2 105.6 135.2 112.1V761c0 4.4 3.6 8 8 8h28.4c4.4 0 8-3.6 8-8.1l-.2-31.7c78.3-6.9 134.3-48.8 134.3-124-.1-69.4-44.2-100.4-109-116.4zm-68.6-16.2c-5.6-1.6-10.3-3.1-15-5-33.8-12.2-49.5-31.9-49.5-57.3 0-36.3 27.5-57 64.5-61.7v124zM534.3 677V543.3c3.1.9 5.9 1.6 8.8 2.2 47.3 14.4 63.2 34.4 63.2 65.1 0 39.1-29.4 62.6-72 66.4z"}}]},name:"dollar",theme:"outlined"},i=r(55015),c=o.forwardRef(function(t,e){return o.createElement(i.Z,(0,n.Z)({},t,{ref:e,icon:a}))})},45246:function(t,e,r){r.d(e,{Z:function(){return c}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M696 480H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"}},{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}}]},name:"minus-circle",theme:"outlined"},i=r(55015),c=o.forwardRef(function(t,e){return o.createElement(i.Z,(0,n.Z)({},t,{ref:e,icon:a}))})},89245:function(t,e,r){r.d(e,{Z:function(){return c}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M909.1 209.3l-56.4 44.1C775.8 155.1 656.2 92 521.9 92 290 92 102.3 279.5 102 511.5 101.7 743.7 289.8 932 521.9 932c181.3 0 335.8-115 394.6-276.1 1.5-4.2-.7-8.9-4.9-10.3l-56.7-19.5a8 8 0 00-10.1 4.8c-1.8 5-3.8 10-5.9 14.9-17.3 41-42.1 77.8-73.7 109.4A344.77 344.77 0 01655.9 829c-42.3 17.9-87.4 27-133.8 27-46.5 0-91.5-9.1-133.8-27A341.5 341.5 0 01279 755.2a342.16 342.16 0 01-73.7-109.4c-17.9-42.4-27-87.4-27-133.9s9.1-91.5 27-133.9c17.3-41 42.1-77.8 73.7-109.4 31.6-31.6 68.4-56.4 109.3-73.8 42.3-17.9 87.4-27 133.8-27 46.5 0 91.5 9.1 133.8 27a341.5 341.5 0 01109.3 73.8c9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47a8 8 0 003 14.1l175.6 43c5 1.2 9.9-2.6 9.9-7.7l.8-180.9c-.1-6.6-7.8-10.3-13-6.2z"}}]},name:"reload",theme:"outlined"},i=r(55015),c=o.forwardRef(function(t,e){return o.createElement(i.Z,(0,n.Z)({},t,{ref:e,icon:a}))})},77565:function(t,e,r){r.d(e,{Z:function(){return c}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"}}]},name:"right",theme:"outlined"},i=r(55015),c=o.forwardRef(function(t,e){return o.createElement(i.Z,(0,n.Z)({},t,{ref:e,icon:a}))})},69993:function(t,e,r){r.d(e,{Z:function(){return c}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M300 328a60 60 0 10120 0 60 60 0 10-120 0zM852 64H172c-17.7 0-32 14.3-32 32v660c0 17.7 14.3 32 32 32h680c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32zm-32 660H204V128h616v596zM604 328a60 60 0 10120 0 60 60 0 10-120 0zm250.2 556H169.8c-16.5 0-29.8 14.3-29.8 32v36c0 4.4 3.3 8 7.4 8h729.1c4.1 0 7.4-3.6 7.4-8v-36c.1-17.7-13.2-32-29.7-32zM664 508H360c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h304c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"}}]},name:"robot",theme:"outlined"},i=r(55015),c=o.forwardRef(function(t,e){return o.createElement(i.Z,(0,n.Z)({},t,{ref:e,icon:a}))})},58630:function(t,e,r){r.d(e,{Z:function(){return c}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M876.6 239.5c-.5-.9-1.2-1.8-2-2.5-5-5-13.1-5-18.1 0L684.2 409.3l-67.9-67.9L788.7 169c.8-.8 1.4-1.6 2-2.5 3.6-6.1 1.6-13.9-4.5-17.5-98.2-58-226.8-44.7-311.3 39.7-67 67-89.2 162-66.5 247.4l-293 293c-3 3-2.8 7.9.3 11l169.7 169.7c3.1 3.1 8.1 3.3 11 .3l292.9-292.9c85.5 22.8 180.5.7 247.6-66.4 84.4-84.5 97.7-213.1 39.7-311.3zM786 499.8c-58.1 58.1-145.3 69.3-214.6 33.6l-8.8 8.8-.1-.1-274 274.1-79.2-79.2 230.1-230.1s0 .1.1.1l52.8-52.8c-35.7-69.3-24.5-156.5 33.6-214.6a184.2 184.2 0 01144-53.5L537 318.9a32.05 32.05 0 000 45.3l124.5 124.5a32.05 32.05 0 0045.3 0l132.8-132.8c3.7 51.8-14.4 104.8-53.6 143.9z"}}]},name:"tool",theme:"outlined"},i=r(55015),c=o.forwardRef(function(t,e){return o.createElement(i.Z,(0,n.Z)({},t,{ref:e,icon:a}))})},47323:function(t,e,r){r.d(e,{Z:function(){return b}});var n=r(5853),o=r(2265),a=r(47187),i=r(7084),c=r(13241),l=r(1153),s=r(26898);let d={xs:{paddingX:"px-1.5",paddingY:"py-1.5"},sm:{paddingX:"px-1.5",paddingY:"py-1.5"},md:{paddingX:"px-2",paddingY:"py-2"},lg:{paddingX:"px-2",paddingY:"py-2"},xl:{paddingX:"px-2.5",paddingY:"py-2.5"}},u={xs:{height:"h-3",width:"w-3"},sm:{height:"h-5",width:"w-5"},md:{height:"h-5",width:"w-5"},lg:{height:"h-7",width:"w-7"},xl:{height:"h-9",width:"w-9"}},m={simple:{rounded:"",border:"",ring:"",shadow:""},light:{rounded:"rounded-tremor-default",border:"",ring:"",shadow:""},shadow:{rounded:"rounded-tremor-default",border:"border",ring:"",shadow:"shadow-tremor-card dark:shadow-dark-tremor-card"},solid:{rounded:"rounded-tremor-default",border:"border-2",ring:"ring-1",shadow:""},outlined:{rounded:"rounded-tremor-default",border:"border",ring:"ring-2",shadow:""}},g=(t,e)=>{switch(t){case"simple":return{textColor:e?(0,l.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:"",borderColor:"",ringColor:""};case"light":return{textColor:e?(0,l.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,c.q)((0,l.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand-muted dark:bg-dark-tremor-brand-muted",borderColor:"",ringColor:""};case"shadow":return{textColor:e?(0,l.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,c.q)((0,l.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:"border-tremor-border dark:border-dark-tremor-border",ringColor:""};case"solid":return{textColor:e?(0,l.bM)(e,s.K.text).textColor:"text-tremor-brand-inverted dark:text-dark-tremor-brand-inverted",bgColor:e?(0,c.q)((0,l.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand dark:bg-dark-tremor-brand",borderColor:"border-tremor-brand-inverted dark:border-dark-tremor-brand-inverted",ringColor:"ring-tremor-ring dark:ring-dark-tremor-ring"};case"outlined":return{textColor:e?(0,l.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,c.q)((0,l.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:e?(0,l.bM)(e,s.K.ring).borderColor:"border-tremor-brand-subtle dark:border-dark-tremor-brand-subtle",ringColor:e?(0,c.q)((0,l.bM)(e,s.K.ring).ringColor,"ring-opacity-40"):"ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted"}}},p=(0,l.fn)("Icon"),b=o.forwardRef((t,e)=>{let{icon:r,variant:s="simple",tooltip:b,size:f=i.u8.SM,color:h,className:v}=t,y=(0,n._T)(t,["icon","variant","tooltip","size","color","className"]),w=g(s,h),{tooltipProps:x,getReferenceProps:k}=(0,a.l)();return o.createElement("span",Object.assign({ref:(0,l.lq)([e,x.refs.setReference]),className:(0,c.q)(p("root"),"inline-flex shrink-0 items-center justify-center",w.bgColor,w.textColor,w.borderColor,w.ringColor,m[s].rounded,m[s].border,m[s].shadow,m[s].ring,d[f].paddingX,d[f].paddingY,v)},k,y),o.createElement(a.Z,Object.assign({text:b},x)),o.createElement(r,{className:(0,c.q)(p("icon"),"shrink-0",u[f].height,u[f].width)}))});b.displayName="Icon"},67101:function(t,e,r){r.d(e,{Z:function(){return d}});var n=r(5853),o=r(13241),a=r(1153),i=r(2265),c=r(9496);let l=(0,a.fn)("Grid"),s=(t,e)=>t&&Object.keys(e).includes(String(t))?e[t]:"",d=i.forwardRef((t,e)=>{let{numItems:r=1,numItemsSm:a,numItemsMd:d,numItemsLg:u,children:m,className:g}=t,p=(0,n._T)(t,["numItems","numItemsSm","numItemsMd","numItemsLg","children","className"]),b=s(r,c._m),f=s(a,c.LH),h=s(d,c.l5),v=s(u,c.N4),y=(0,o.q)(b,f,h,v);return i.createElement("div",Object.assign({ref:e,className:(0,o.q)(l("root"),"grid",y,g)},p),m)});d.displayName="Grid"},9496:function(t,e,r){r.d(e,{LH:function(){return o},N4:function(){return i},PT:function(){return c},SP:function(){return l},VS:function(){return s},_m:function(){return n},_w:function(){return d},l5:function(){return a}});let n={0:"grid-cols-none",1:"grid-cols-1",2:"grid-cols-2",3:"grid-cols-3",4:"grid-cols-4",5:"grid-cols-5",6:"grid-cols-6",7:"grid-cols-7",8:"grid-cols-8",9:"grid-cols-9",10:"grid-cols-10",11:"grid-cols-11",12:"grid-cols-12"},o={0:"sm:grid-cols-none",1:"sm:grid-cols-1",2:"sm:grid-cols-2",3:"sm:grid-cols-3",4:"sm:grid-cols-4",5:"sm:grid-cols-5",6:"sm:grid-cols-6",7:"sm:grid-cols-7",8:"sm:grid-cols-8",9:"sm:grid-cols-9",10:"sm:grid-cols-10",11:"sm:grid-cols-11",12:"sm:grid-cols-12"},a={0:"md:grid-cols-none",1:"md:grid-cols-1",2:"md:grid-cols-2",3:"md:grid-cols-3",4:"md:grid-cols-4",5:"md:grid-cols-5",6:"md:grid-cols-6",7:"md:grid-cols-7",8:"md:grid-cols-8",9:"md:grid-cols-9",10:"md:grid-cols-10",11:"md:grid-cols-11",12:"md:grid-cols-12"},i={0:"lg:grid-cols-none",1:"lg:grid-cols-1",2:"lg:grid-cols-2",3:"lg:grid-cols-3",4:"lg:grid-cols-4",5:"lg:grid-cols-5",6:"lg:grid-cols-6",7:"lg:grid-cols-7",8:"lg:grid-cols-8",9:"lg:grid-cols-9",10:"lg:grid-cols-10",11:"lg:grid-cols-11",12:"lg:grid-cols-12"},c={1:"col-span-1",2:"col-span-2",3:"col-span-3",4:"col-span-4",5:"col-span-5",6:"col-span-6",7:"col-span-7",8:"col-span-8",9:"col-span-9",10:"col-span-10",11:"col-span-11",12:"col-span-12",13:"col-span-13"},l={1:"sm:col-span-1",2:"sm:col-span-2",3:"sm:col-span-3",4:"sm:col-span-4",5:"sm:col-span-5",6:"sm:col-span-6",7:"sm:col-span-7",8:"sm:col-span-8",9:"sm:col-span-9",10:"sm:col-span-10",11:"sm:col-span-11",12:"sm:col-span-12",13:"sm:col-span-13"},s={1:"md:col-span-1",2:"md:col-span-2",3:"md:col-span-3",4:"md:col-span-4",5:"md:col-span-5",6:"md:col-span-6",7:"md:col-span-7",8:"md:col-span-8",9:"md:col-span-9",10:"md:col-span-10",11:"md:col-span-11",12:"md:col-span-12",13:"md:col-span-13"},d={1:"lg:col-span-1",2:"lg:col-span-2",3:"lg:col-span-3",4:"lg:col-span-4",5:"lg:col-span-5",6:"lg:col-span-6",7:"lg:col-span-7",8:"lg:col-span-8",9:"lg:col-span-9",10:"lg:col-span-10",11:"lg:col-span-11",12:"lg:col-span-12",13:"lg:col-span-13"}},96761:function(t,e,r){r.d(e,{Z:function(){return l}});var n=r(5853),o=r(26898),a=r(13241),i=r(1153),c=r(2265);let l=c.forwardRef((t,e)=>{let{color:r,children:l,className:s}=t,d=(0,n._T)(t,["color","children","className"]);return c.createElement("p",Object.assign({ref:e,className:(0,a.q)("font-medium text-tremor-title",r?(0,i.bM)(r,o.K.darkText).textColor:"text-tremor-content-strong dark:text-dark-tremor-content-strong",s)},d),l)});l.displayName="Title"},33866:function(t,e,r){r.d(e,{Z:function(){return I}});var n=r(2265),o=r(36760),a=r.n(o),i=r(66632),c=r(93350),l=r(19722),s=r(71744),d=r(93463),u=r(12918),m=r(18536),g=r(71140),p=r(99320);let b=new d.E4("antStatusProcessing",{"0%":{transform:"scale(0.8)",opacity:.5},"100%":{transform:"scale(2.4)",opacity:0}}),f=new d.E4("antZoomBadgeIn",{"0%":{transform:"scale(0) translate(50%, -50%)",opacity:0},"100%":{transform:"scale(1) translate(50%, -50%)"}}),h=new d.E4("antZoomBadgeOut",{"0%":{transform:"scale(1) translate(50%, -50%)"},"100%":{transform:"scale(0) translate(50%, -50%)",opacity:0}}),v=new d.E4("antNoWrapperZoomBadgeIn",{"0%":{transform:"scale(0)",opacity:0},"100%":{transform:"scale(1)"}}),y=new d.E4("antNoWrapperZoomBadgeOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0)",opacity:0}}),w=new d.E4("antBadgeLoadingCircle",{"0%":{transformOrigin:"50%"},"100%":{transform:"translate(50%, -50%) rotate(360deg)",transformOrigin:"50%"}}),x=t=>{let{componentCls:e,iconCls:r,antCls:n,badgeShadowSize:o,textFontSize:a,textFontSizeSM:i,statusSize:c,dotSize:l,textFontWeight:s,indicatorHeight:g,indicatorHeightSM:p,marginXS:x,calc:k}=t,O="".concat(n,"-scroll-number"),C=(0,m.Z)(t,(t,r)=>{let{darkColor:n}=r;return{["&".concat(e," ").concat(e,"-color-").concat(t)]:{background:n,["&:not(".concat(e,"-count)")]:{color:n},"a:hover &":{background:n}}}});return{[e]:Object.assign(Object.assign(Object.assign(Object.assign({},(0,u.Wf)(t)),{position:"relative",display:"inline-block",width:"fit-content",lineHeight:1,["".concat(e,"-count")]:{display:"inline-flex",justifyContent:"center",zIndex:t.indicatorZIndex,minWidth:g,height:g,color:t.badgeTextColor,fontWeight:s,fontSize:a,lineHeight:(0,d.bf)(g),whiteSpace:"nowrap",textAlign:"center",background:t.badgeColor,borderRadius:k(g).div(2).equal(),boxShadow:"0 0 0 ".concat((0,d.bf)(o)," ").concat(t.badgeShadowColor),transition:"background ".concat(t.motionDurationMid),a:{color:t.badgeTextColor},"a:hover":{color:t.badgeTextColor},"a:hover &":{background:t.badgeColorHover}},["".concat(e,"-count-sm")]:{minWidth:p,height:p,fontSize:i,lineHeight:(0,d.bf)(p),borderRadius:k(p).div(2).equal()},["".concat(e,"-multiple-words")]:{padding:"0 ".concat((0,d.bf)(t.paddingXS)),bdi:{unicodeBidi:"plaintext"}},["".concat(e,"-dot")]:{zIndex:t.indicatorZIndex,width:l,minWidth:l,height:l,background:t.badgeColor,borderRadius:"100%",boxShadow:"0 0 0 ".concat((0,d.bf)(o)," ").concat(t.badgeShadowColor)},["".concat(e,"-count, ").concat(e,"-dot, ").concat(O,"-custom-component")]:{position:"absolute",top:0,insetInlineEnd:0,transform:"translate(50%, -50%)",transformOrigin:"100% 0%",["&".concat(r,"-spin")]:{animationName:w,animationDuration:"1s",animationIterationCount:"infinite",animationTimingFunction:"linear"}},["&".concat(e,"-status")]:{lineHeight:"inherit",verticalAlign:"baseline",["".concat(e,"-status-dot")]:{position:"relative",top:-1,display:"inline-block",width:c,height:c,verticalAlign:"middle",borderRadius:"50%"},["".concat(e,"-status-success")]:{backgroundColor:t.colorSuccess},["".concat(e,"-status-processing")]:{overflow:"visible",color:t.colorInfo,backgroundColor:t.colorInfo,borderColor:"currentcolor","&::after":{position:"absolute",top:0,insetInlineStart:0,width:"100%",height:"100%",borderWidth:o,borderStyle:"solid",borderColor:"inherit",borderRadius:"50%",animationName:b,animationDuration:t.badgeProcessingDuration,animationIterationCount:"infinite",animationTimingFunction:"ease-in-out",content:'""'}},["".concat(e,"-status-default")]:{backgroundColor:t.colorTextPlaceholder},["".concat(e,"-status-error")]:{backgroundColor:t.colorError},["".concat(e,"-status-warning")]:{backgroundColor:t.colorWarning},["".concat(e,"-status-text")]:{marginInlineStart:x,color:t.colorText,fontSize:t.fontSize}}}),C),{["".concat(e,"-zoom-appear, ").concat(e,"-zoom-enter")]:{animationName:f,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack,animationFillMode:"both"},["".concat(e,"-zoom-leave")]:{animationName:h,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack,animationFillMode:"both"},["&".concat(e,"-not-a-wrapper")]:{["".concat(e,"-zoom-appear, ").concat(e,"-zoom-enter")]:{animationName:v,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack},["".concat(e,"-zoom-leave")]:{animationName:y,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack},["&:not(".concat(e,"-status)")]:{verticalAlign:"middle"},["".concat(O,"-custom-component, ").concat(e,"-count")]:{transform:"none"},["".concat(O,"-custom-component, ").concat(O)]:{position:"relative",top:"auto",display:"block",transformOrigin:"50% 50%"}},[O]:{overflow:"hidden",transition:"all ".concat(t.motionDurationMid," ").concat(t.motionEaseOutBack),["".concat(O,"-only")]:{position:"relative",display:"inline-block",height:g,transition:"all ".concat(t.motionDurationSlow," ").concat(t.motionEaseOutBack),WebkitTransformStyle:"preserve-3d",WebkitBackfaceVisibility:"hidden",["> p".concat(O,"-only-unit")]:{height:g,margin:0,WebkitTransformStyle:"preserve-3d",WebkitBackfaceVisibility:"hidden"}},["".concat(O,"-symbol")]:{verticalAlign:"top"}},"&-rtl":{direction:"rtl",["".concat(e,"-count, ").concat(e,"-dot, ").concat(O,"-custom-component")]:{transform:"translate(-50%, -50%)"}}})}},k=t=>{let{fontHeight:e,lineWidth:r,marginXS:n,colorBorderBg:o}=t,a=t.colorTextLightSolid,i=t.colorError,c=t.colorErrorHover;return(0,g.IX)(t,{badgeFontHeight:e,badgeShadowSize:r,badgeTextColor:a,badgeColor:i,badgeColorHover:c,badgeShadowColor:o,badgeProcessingDuration:"1.2s",badgeRibbonOffset:n,badgeRibbonCornerTransform:"scaleY(0.75)",badgeRibbonCornerFilter:"brightness(75%)"})},O=t=>{let{fontSize:e,lineHeight:r,fontSizeSM:n,lineWidth:o}=t;return{indicatorZIndex:"auto",indicatorHeight:Math.round(e*r)-2*o,indicatorHeightSM:e,dotSize:n/2,textFontSize:n,textFontSizeSM:n,textFontWeight:"normal",statusSize:n/2}};var C=(0,p.I$)("Badge",t=>x(k(t)),O);let E=t=>{let{antCls:e,badgeFontHeight:r,marginXS:n,badgeRibbonOffset:o,calc:a}=t,i="".concat(e,"-ribbon"),c=(0,m.Z)(t,(t,e)=>{let{darkColor:r}=e;return{["&".concat(i,"-color-").concat(t)]:{background:r,color:r}}});return{["".concat(e,"-ribbon-wrapper")]:{position:"relative"},[i]:Object.assign(Object.assign(Object.assign(Object.assign({},(0,u.Wf)(t)),{position:"absolute",top:n,padding:"0 ".concat((0,d.bf)(t.paddingXS)),color:t.colorPrimary,lineHeight:(0,d.bf)(r),whiteSpace:"nowrap",backgroundColor:t.colorPrimary,borderRadius:t.borderRadiusSM,["".concat(i,"-text")]:{color:t.badgeTextColor},["".concat(i,"-corner")]:{position:"absolute",top:"100%",width:o,height:o,color:"currentcolor",border:"".concat((0,d.bf)(a(o).div(2).equal())," solid"),transform:t.badgeRibbonCornerTransform,transformOrigin:"top",filter:t.badgeRibbonCornerFilter}}),c),{["&".concat(i,"-placement-end")]:{insetInlineEnd:a(o).mul(-1).equal(),borderEndEndRadius:0,["".concat(i,"-corner")]:{insetInlineEnd:0,borderInlineEndColor:"transparent",borderBlockEndColor:"transparent"}},["&".concat(i,"-placement-start")]:{insetInlineStart:a(o).mul(-1).equal(),borderEndStartRadius:0,["".concat(i,"-corner")]:{insetInlineStart:0,borderBlockEndColor:"transparent",borderInlineStartColor:"transparent"}},"&-rtl":{direction:"rtl"}})}};var S=(0,p.I$)(["Badge","Ribbon"],t=>E(k(t)),O);let N=t=>{let e;let{prefixCls:r,value:o,current:i,offset:c=0}=t;return c&&(e={position:"absolute",top:"".concat(c,"00%"),left:0}),n.createElement("span",{style:e,className:a()("".concat(r,"-only-unit"),{current:i})},o)};var j=t=>{let e,r;let{prefixCls:o,count:a,value:i}=t,c=Number(i),l=Math.abs(a),[s,d]=n.useState(c),[u,m]=n.useState(l),g=()=>{d(c),m(l)};if(n.useEffect(()=>{let t=setTimeout(g,1e3);return()=>clearTimeout(t)},[c]),s===c||Number.isNaN(c)||Number.isNaN(s))e=[n.createElement(N,Object.assign({},t,{key:c,current:!0}))],r={transition:"none"};else{e=[];let o=c+10,a=[];for(let t=c;t<=o;t+=1)a.push(t);let i=ut%10===s);e=(i<0?a.slice(0,d+1):a.slice(d)).map((e,r)=>n.createElement(N,Object.assign({},t,{key:e,value:e%10,offset:i<0?r-d:r,current:r===d}))),r={transform:"translateY(".concat(-function(t,e,r){let n=t,o=0;for(;(n+10)%10!==e;)n+=r,o+=r;return o}(s,c,i),"00%)")}}return n.createElement("span",{className:"".concat(o,"-only"),style:r,onTransitionEnd:g},e)},M=function(t,e){var r={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&0>e.indexOf(n)&&(r[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(t);oe.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(t,n[o])&&(r[n[o]]=t[n[o]]);return r};let z=n.forwardRef((t,e)=>{let{prefixCls:r,count:o,className:i,motionClassName:c,style:d,title:u,show:m,component:g="sup",children:p}=t,b=M(t,["prefixCls","count","className","motionClassName","style","title","show","component","children"]),{getPrefixCls:f}=n.useContext(s.E_),h=f("scroll-number",r),v=Object.assign(Object.assign({},b),{"data-show":m,style:d,className:a()(h,i,c),title:u}),y=o;if(o&&Number(o)%1==0){let t=String(o).split("");y=n.createElement("bdi",null,t.map((e,r)=>n.createElement(j,{prefixCls:h,count:Number(o),value:e,key:t.length-r})))}return((null==d?void 0:d.borderColor)&&(v.style=Object.assign(Object.assign({},d),{boxShadow:"0 0 0 1px ".concat(d.borderColor," inset")})),p)?(0,l.Tm)(p,t=>({className:a()("".concat(h,"-custom-component"),null==t?void 0:t.className,c)})):n.createElement(g,Object.assign({},v,{ref:e}),y)});var Z=function(t,e){var r={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&0>e.indexOf(n)&&(r[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(t);oe.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(t,n[o])&&(r[n[o]]=t[n[o]]);return r};let R=n.forwardRef((t,e)=>{var r,o,d,u,m;let{prefixCls:g,scrollNumberPrefixCls:p,children:b,status:f,text:h,color:v,count:y=null,overflowCount:w=99,dot:x=!1,size:k="default",title:O,offset:E,style:S,className:N,rootClassName:j,classNames:M,styles:R,showZero:I=!1}=t,L=Z(t,["prefixCls","scrollNumberPrefixCls","children","status","text","color","count","overflowCount","dot","size","title","offset","style","className","rootClassName","classNames","styles","showZero"]),{getPrefixCls:B,direction:T,badge:P}=n.useContext(s.E_),W=B("badge",g),[A,q,H]=C(W),G=y>w?"".concat(w,"+"):y,D="0"===G||0===G||"0"===h||0===h,K=null===y||D&&!I,V=(null!=f||null!=v)&&K,F=null!=f||!D,_=x&&!D,X=_?"":G,Y=(0,n.useMemo)(()=>((null==X||""===X)&&(null==h||""===h)||D&&!I)&&!_,[X,D,I,_,h]),$=(0,n.useRef)(y);Y||($.current=y);let U=$.current,J=(0,n.useRef)(X);Y||(J.current=X);let Q=J.current,tt=(0,n.useRef)(_);Y||(tt.current=_);let te=(0,n.useMemo)(()=>{if(!E)return Object.assign(Object.assign({},null==P?void 0:P.style),S);let t={marginTop:E[1]};return"rtl"===T?t.left=Number.parseInt(E[0],10):t.right=-Number.parseInt(E[0],10),Object.assign(Object.assign(Object.assign({},t),null==P?void 0:P.style),S)},[T,E,S,null==P?void 0:P.style]),tr=null!=O?O:"string"==typeof U||"number"==typeof U?U:void 0,tn=!Y&&(0===h?I:!!h&&!0!==h),to=tn?n.createElement("span",{className:"".concat(W,"-status-text")},h):null,ta=U&&"object"==typeof U?(0,l.Tm)(U,t=>({style:Object.assign(Object.assign({},te),t.style)})):void 0,ti=(0,c.o2)(v,!1),tc=a()(null==M?void 0:M.indicator,null===(r=null==P?void 0:P.classNames)||void 0===r?void 0:r.indicator,{["".concat(W,"-status-dot")]:V,["".concat(W,"-status-").concat(f)]:!!f,["".concat(W,"-color-").concat(v)]:ti}),tl={};v&&!ti&&(tl.color=v,tl.background=v);let ts=a()(W,{["".concat(W,"-status")]:V,["".concat(W,"-not-a-wrapper")]:!b,["".concat(W,"-rtl")]:"rtl"===T},N,j,null==P?void 0:P.className,null===(o=null==P?void 0:P.classNames)||void 0===o?void 0:o.root,null==M?void 0:M.root,q,H);if(!b&&V&&(h||F||!K)){let t=te.color;return A(n.createElement("span",Object.assign({},L,{className:ts,style:Object.assign(Object.assign(Object.assign({},null==R?void 0:R.root),null===(d=null==P?void 0:P.styles)||void 0===d?void 0:d.root),te)}),n.createElement("span",{className:tc,style:Object.assign(Object.assign(Object.assign({},null==R?void 0:R.indicator),null===(u=null==P?void 0:P.styles)||void 0===u?void 0:u.indicator),tl)}),tn&&n.createElement("span",{style:{color:t},className:"".concat(W,"-status-text")},h)))}return A(n.createElement("span",Object.assign({ref:e},L,{className:ts,style:Object.assign(Object.assign({},null===(m=null==P?void 0:P.styles)||void 0===m?void 0:m.root),null==R?void 0:R.root)}),b,n.createElement(i.ZP,{visible:!Y,motionName:"".concat(W,"-zoom"),motionAppear:!1,motionDeadline:1e3},t=>{var e,r;let{className:o}=t,i=B("scroll-number",p),c=tt.current,l=a()(null==M?void 0:M.indicator,null===(e=null==P?void 0:P.classNames)||void 0===e?void 0:e.indicator,{["".concat(W,"-dot")]:c,["".concat(W,"-count")]:!c,["".concat(W,"-count-sm")]:"small"===k,["".concat(W,"-multiple-words")]:!c&&Q&&Q.toString().length>1,["".concat(W,"-status-").concat(f)]:!!f,["".concat(W,"-color-").concat(v)]:ti}),s=Object.assign(Object.assign(Object.assign({},null==R?void 0:R.indicator),null===(r=null==P?void 0:P.styles)||void 0===r?void 0:r.indicator),te);return v&&!ti&&((s=s||{}).background=v),n.createElement(z,{prefixCls:i,show:!Y,motionClassName:o,className:l,count:Q,title:tr,style:s,key:"scrollNumber"},ta)}),to))});R.Ribbon=t=>{let{className:e,prefixCls:r,style:o,color:i,children:l,text:d,placement:u="end",rootClassName:m}=t,{getPrefixCls:g,direction:p}=n.useContext(s.E_),b=g("ribbon",r),f="".concat(b,"-wrapper"),[h,v,y]=S(b,f),w=(0,c.o2)(i,!1),x=a()(b,"".concat(b,"-placement-").concat(u),{["".concat(b,"-rtl")]:"rtl"===p,["".concat(b,"-color-").concat(i)]:w},e),k={},O={};return i&&!w&&(k.background=i,O.color=i),h(n.createElement("div",{className:a()(f,m,v,y)},l,n.createElement("div",{className:a()(x,v),style:Object.assign(Object.assign({},k),o)},n.createElement("span",{className:"".concat(b,"-text")},d),n.createElement("div",{className:"".concat(b,"-corner"),style:O}))))};var I=R},58760:function(t,e,r){r.d(e,{Z:function(){return S}});var n=r(2265),o=r(36760),a=r.n(o),i=r(45287);function c(t){return["small","middle","large"].includes(t)}function l(t){return!!t&&"number"==typeof t&&!Number.isNaN(t)}var s=r(71744),d=r(77685),u=r(17691),m=r(99320);let g=t=>{let{componentCls:e,borderRadius:r,paddingSM:n,colorBorder:o,paddingXS:a,fontSizeLG:i,fontSizeSM:c,borderRadiusLG:l,borderRadiusSM:s,colorBgContainerDisabled:d,lineWidth:m}=t;return{[e]:[{display:"inline-flex",alignItems:"center",gap:0,paddingInline:n,margin:0,background:d,borderWidth:m,borderStyle:"solid",borderColor:o,borderRadius:r,"&-large":{fontSize:i,borderRadius:l},"&-small":{paddingInline:a,borderRadius:s,fontSize:c},"&-compact-last-item":{borderEndStartRadius:0,borderStartStartRadius:0},"&-compact-first-item":{borderEndEndRadius:0,borderStartEndRadius:0},"&-compact-item:not(:first-child):not(:last-child)":{borderRadius:0},"&-compact-item:not(:last-child)":{borderInlineEndWidth:0}},(0,u.c)(t,{focus:!1})]}};var p=(0,m.I$)(["Space","Addon"],t=>[g(t)]),b=function(t,e){var r={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&0>e.indexOf(n)&&(r[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(t);oe.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(t,n[o])&&(r[n[o]]=t[n[o]]);return r};let f=n.forwardRef((t,e)=>{let{className:r,children:o,style:i,prefixCls:c}=t,l=b(t,["className","children","style","prefixCls"]),{getPrefixCls:u,direction:m}=n.useContext(s.E_),g=u("space-addon",c),[f,h,v]=p(g),{compactItemClassnames:y,compactSize:w}=(0,d.ri)(g,m),x=a()(g,h,y,v,{["".concat(g,"-").concat(w)]:w},r);return f(n.createElement("div",Object.assign({ref:e,className:x,style:i},l),o))}),h=n.createContext({latestIndex:0}),v=h.Provider;var y=t=>{let{className:e,index:r,children:o,split:a,style:i}=t,{latestIndex:c}=n.useContext(h);return null==o?null:n.createElement(n.Fragment,null,n.createElement("div",{className:e,style:i},o),r{let{componentCls:e,antCls:r}=t;return{[e]:{display:"inline-flex","&-rtl":{direction:"rtl"},"&-vertical":{flexDirection:"column"},"&-align":{flexDirection:"column","&-center":{alignItems:"center"},"&-start":{alignItems:"flex-start"},"&-end":{alignItems:"flex-end"},"&-baseline":{alignItems:"baseline"}},["".concat(e,"-item:empty")]:{display:"none"},["".concat(e,"-item > ").concat(r,"-badge-not-a-wrapper:only-child")]:{display:"block"}}}},k=t=>{let{componentCls:e}=t;return{[e]:{"&-gap-row-small":{rowGap:t.spaceGapSmallSize},"&-gap-row-middle":{rowGap:t.spaceGapMiddleSize},"&-gap-row-large":{rowGap:t.spaceGapLargeSize},"&-gap-col-small":{columnGap:t.spaceGapSmallSize},"&-gap-col-middle":{columnGap:t.spaceGapMiddleSize},"&-gap-col-large":{columnGap:t.spaceGapLargeSize}}}};var O=(0,m.I$)("Space",t=>{let e=(0,w.IX)(t,{spaceGapSmallSize:t.paddingXS,spaceGapMiddleSize:t.padding,spaceGapLargeSize:t.paddingLG});return[x(e),k(e)]},()=>({}),{resetStyle:!1}),C=function(t,e){var r={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&0>e.indexOf(n)&&(r[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(t);oe.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(t,n[o])&&(r[n[o]]=t[n[o]]);return r};let E=n.forwardRef((t,e)=>{var r;let{getPrefixCls:o,direction:d,size:u,className:m,style:g,classNames:p,styles:b}=(0,s.dj)("space"),{size:f=null!=u?u:"small",align:h,className:w,rootClassName:x,children:k,direction:E="horizontal",prefixCls:S,split:N,style:j,wrap:M=!1,classNames:z,styles:Z}=t,R=C(t,["size","align","className","rootClassName","children","direction","prefixCls","split","style","wrap","classNames","styles"]),[I,L]=Array.isArray(f)?f:[f,f],B=c(L),T=c(I),P=l(L),W=l(I),A=(0,i.Z)(k,{keepEmpty:!0}),q=void 0===h&&"horizontal"===E?"center":h,H=o("space",S),[G,D,K]=O(H),V=a()(H,m,D,"".concat(H,"-").concat(E),{["".concat(H,"-rtl")]:"rtl"===d,["".concat(H,"-align-").concat(q)]:q,["".concat(H,"-gap-row-").concat(L)]:B,["".concat(H,"-gap-col-").concat(I)]:T},w,x,K),F=a()("".concat(H,"-item"),null!==(r=null==z?void 0:z.item)&&void 0!==r?r:p.item),_=Object.assign(Object.assign({},b.item),null==Z?void 0:Z.item),X=A.map((t,e)=>{let r=(null==t?void 0:t.key)||"".concat(F,"-").concat(e);return n.createElement(y,{className:F,key:r,index:e,split:N,style:_},t)}),Y=n.useMemo(()=>({latestIndex:A.reduce((t,e,r)=>null!=e?r:t,0)}),[A]);if(0===A.length)return null;let $={};return M&&($.flexWrap="wrap"),!T&&W&&($.columnGap=I),!B&&P&&($.rowGap=L),G(n.createElement("div",Object.assign({ref:e,className:V,style:Object.assign(Object.assign(Object.assign({},$),g),j)},R),n.createElement(v,{value:Y},X)))});E.Compact=d.ZP,E.Addon=f;var S=E},79205:function(t,e,r){r.d(e,{Z:function(){return u}});var n=r(2265);let o=t=>t.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),a=t=>t.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,e,r)=>r?r.toUpperCase():e.toLowerCase()),i=t=>{let e=a(t);return e.charAt(0).toUpperCase()+e.slice(1)},c=function(){for(var t=arguments.length,e=Array(t),r=0;r!!t&&""!==t.trim()&&r.indexOf(t)===e).join(" ").trim()},l=t=>{for(let e in t)if(e.startsWith("aria-")||"role"===e||"title"===e)return!0};var s={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let d=(0,n.forwardRef)((t,e)=>{let{color:r="currentColor",size:o=24,strokeWidth:a=2,absoluteStrokeWidth:i,className:d="",children:u,iconNode:m,...g}=t;return(0,n.createElement)("svg",{ref:e,...s,width:o,height:o,stroke:r,strokeWidth:i?24*Number(a)/Number(o):a,className:c("lucide",d),...!u&&!l(g)&&{"aria-hidden":"true"},...g},[...m.map(t=>{let[e,r]=t;return(0,n.createElement)(e,r)}),...Array.isArray(u)?u:[u]])}),u=(t,e)=>{let r=(0,n.forwardRef)((r,a)=>{let{className:l,...s}=r;return(0,n.createElement)(d,{ref:a,iconNode:e,className:c("lucide-".concat(o(i(t))),"lucide-".concat(t),l),...s})});return r.displayName=i(t),r}},30401:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]])},64935:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("code",[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]])},78867:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]])},96362:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("external-link",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]])},29202:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("globe",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]])},54001:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("key",[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]])},96137:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("server",[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2",key:"ngkwjq"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2",key:"iecqi9"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6",key:"16zg32"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18",key:"nzw8ys"}]])},80221:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("terminal",[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]])},11239:function(t,e,r){r.d(e,{Z:function(){return n}});let n=(0,r(79205).Z)("zap",[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]])},10900:function(t,e,r){var n=r(2265);let o=n.forwardRef(function(t,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10 19l-7-7m0 0l7-7m-7 7h18"}))});e.Z=o},71437:function(t,e,r){var n=r(2265);let o=n.forwardRef(function(t,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"}),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"}))});e.Z=o},82376:function(t,e,r){var n=r(2265);let o=n.forwardRef(function(t,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"}))});e.Z=o},53410:function(t,e,r){var n=r(2265);let o=n.forwardRef(function(t,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"}))});e.Z=o},74998:function(t,e,r){var n=r(2265);let o=n.forwardRef(function(t,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"}))});e.Z=o},21770:function(t,e,r){r.d(e,{D:function(){return d}});var n=r(2265),o=r(2894),a=r(18238),i=r(24112),c=r(45345),l=class extends i.l{#t;#e=void 0;#r;#n;constructor(t,e){super(),this.#t=t,this.setOptions(e),this.bindMethods(),this.#o()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(t){let e=this.options;this.options=this.#t.defaultMutationOptions(t),(0,c.VS)(this.options,e)||this.#t.getMutationCache().notify({type:"observerOptionsUpdated",mutation:this.#r,observer:this}),e?.mutationKey&&this.options.mutationKey&&(0,c.Ym)(e.mutationKey)!==(0,c.Ym)(this.options.mutationKey)?this.reset():this.#r?.state.status==="pending"&&this.#r.setOptions(this.options)}onUnsubscribe(){this.hasListeners()||this.#r?.removeObserver(this)}onMutationUpdate(t){this.#o(),this.#a(t)}getCurrentResult(){return this.#e}reset(){this.#r?.removeObserver(this),this.#r=void 0,this.#o(),this.#a()}mutate(t,e){return this.#n=e,this.#r?.removeObserver(this),this.#r=this.#t.getMutationCache().build(this.#t,this.options),this.#r.addObserver(this),this.#r.execute(t)}#o(){let t=this.#r?.state??(0,o.R)();this.#e={...t,isPending:"pending"===t.status,isSuccess:"success"===t.status,isError:"error"===t.status,isIdle:"idle"===t.status,mutate:this.mutate,reset:this.reset}}#a(t){a.Vr.batch(()=>{if(this.#n&&this.hasListeners()){let e=this.#e.variables,r=this.#e.context,n={client:this.#t,meta:this.options.meta,mutationKey:this.options.mutationKey};t?.type==="success"?(this.#n.onSuccess?.(t.data,e,r,n),this.#n.onSettled?.(t.data,null,e,r,n)):t?.type==="error"&&(this.#n.onError?.(t.error,e,r,n),this.#n.onSettled?.(void 0,t.error,e,r,n))}this.listeners.forEach(t=>{t(this.#e)})})}},s=r(29827);function d(t,e){let r=(0,s.NL)(e),[o]=n.useState(()=>new l(r,t));n.useEffect(()=>{o.setOptions(t)},[o,t]);let i=n.useSyncExternalStore(n.useCallback(t=>o.subscribe(a.Vr.batchCalls(t)),[o]),()=>o.getCurrentResult(),()=>o.getCurrentResult()),d=n.useCallback((t,e)=>{o.mutate(t,e).catch(c.ZT)},[o]);if(i.error&&(0,c.L3)(o.options.throwOnError,[i.error]))throw i.error;return{...i,mutate:d,mutateAsync:i.mutate}}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1070-ab9dafb0fc6e0b85.js b/litellm/proxy/_experimental/out/_next/static/chunks/1070-ab9dafb0fc6e0b85.js new file mode 100644 index 00000000000..a35f71fe0e6 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/1070-ab9dafb0fc6e0b85.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1070],{88009:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z"}}]},name:"appstore",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},93750:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M296 250c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H296zm184 144H296c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zm-48 458H208V148h560v320c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V108c0-17.7-14.3-32-32-32H168c-17.7 0-32 14.3-32 32v784c0 17.7 14.3 32 32 32h264c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm440-88H728v-36.6c46.3-13.8 80-56.6 80-107.4 0-61.9-50.1-112-112-112s-112 50.1-112 112c0 50.7 33.7 93.6 80 107.4V764H520c-8.8 0-16 7.2-16 16v152c0 8.8 7.2 16 16 16h352c8.8 0 16-7.2 16-16V780c0-8.8-7.2-16-16-16zM646 620c0-27.6 22.4-50 50-50s50 22.4 50 50-22.4 50-50 50-50-22.4-50-50zm180 266H566v-60h260v60z"}}]},name:"audit",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},37527:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M894 462c30.9 0 43.8-39.7 18.7-58L530.8 126.2a31.81 31.81 0 00-37.6 0L111.3 404c-25.1 18.2-12.2 58 18.8 58H192v374h-72c-4.4 0-8 3.6-8 8v52c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-52c0-4.4-3.6-8-8-8h-72V462h62zM512 196.7l271.1 197.2H240.9L512 196.7zM264 462h117v374H264V462zm189 0h117v374H453V462zm307 374H642V462h118v374z"}}]},name:"bank",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},9775:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M888 792H200V168c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v688c0 4.4 3.6 8 8 8h752c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm-600-80h56c4.4 0 8-3.6 8-8V560c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v144c0 4.4 3.6 8 8 8zm152 0h56c4.4 0 8-3.6 8-8V384c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v320c0 4.4 3.6 8 8 8zm152 0h56c4.4 0 8-3.6 8-8V462c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v242c0 4.4 3.6 8 8 8zm152 0h56c4.4 0 8-3.6 8-8V304c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v400c0 4.4 3.6 8 8 8z"}}]},name:"bar-chart",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},68208:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M856 376H648V168c0-8.8-7.2-16-16-16H168c-8.8 0-16 7.2-16 16v464c0 8.8 7.2 16 16 16h208v208c0 8.8 7.2 16 16 16h464c8.8 0 16-7.2 16-16V392c0-8.8-7.2-16-16-16zm-480 16v188H220V220h360v156H392c-8.8 0-16 7.2-16 16zm204 52v136H444V444h136zm224 360H444V648h188c8.8 0 16-7.2 16-16V444h156v360z"}}]},name:"block",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},41169:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 472a40 40 0 1080 0 40 40 0 10-80 0zm367 352.9L696.3 352V178H768v-68H256v68h71.7v174L145 824.9c-2.8 7.4-4.3 15.2-4.3 23.1 0 35.3 28.7 64 64 64h614.6c7.9 0 15.7-1.5 23.1-4.3 33-12.7 49.4-49.8 36.6-82.8zM395.7 364.7V180h232.6v184.7L719.2 600c-20.7-5.3-42.1-8-63.9-8-61.2 0-119.2 21.5-165.3 60a188.78 188.78 0 01-121.3 43.9c-32.7 0-64.1-8.3-91.8-23.7l118.8-307.5zM210.5 844l41.7-107.8c35.7 18.1 75.4 27.8 116.6 27.8 61.2 0 119.2-21.5 165.3-60 33.9-28.2 76.3-43.9 121.3-43.9 35 0 68.4 9.5 97.6 27.1L813.5 844h-603z"}}]},name:"experiment",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},48231:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M888 792H200V168c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v688c0 4.4 3.6 8 8 8h752c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM305.8 637.7c3.1 3.1 8.1 3.1 11.3 0l138.3-137.6L583 628.5c3.1 3.1 8.2 3.1 11.3 0l275.4-275.3c3.1-3.1 3.1-8.2 0-11.3l-39.6-39.6a8.03 8.03 0 00-11.3 0l-230 229.9L461.4 404a8.03 8.03 0 00-11.3 0L266.3 586.7a8.03 8.03 0 000 11.3l39.5 39.7z"}}]},name:"line-chart",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},28595:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}},{tag:"path",attrs:{d:"M719.4 499.1l-296.1-215A15.9 15.9 0 00398 297v430c0 13.1 14.8 20.5 25.3 12.9l296.1-215a15.9 15.9 0 000-25.8zm-257.6 134V390.9L628.5 512 461.8 633.1z"}}]},name:"play-circle",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},41361:function(e,t,c){c.d(t,{Z:function(){return i}});var n=c(1119),a=c(2265),r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M824.2 699.9a301.55 301.55 0 00-86.4-60.4C783.1 602.8 812 546.8 812 484c0-110.8-92.4-201.7-203.2-200-109.1 1.7-197 90.6-197 200 0 62.8 29 118.8 74.2 155.5a300.95 300.95 0 00-86.4 60.4C345 754.6 314 826.8 312 903.8a8 8 0 008 8.2h56c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5A226.62 226.62 0 01612 684c60.9 0 118.2 23.7 161.3 66.8C814.5 792 838 846.3 840 904.3c.1 4.3 3.7 7.7 8 7.7h56a8 8 0 008-8.2c-2-77-33-149.2-87.8-203.9zM612 612c-34.2 0-66.4-13.3-90.5-37.5a126.86 126.86 0 01-37.5-91.8c.3-32.8 13.4-64.5 36.3-88 24-24.6 56.1-38.3 90.4-38.7 33.9-.3 66.8 12.9 91 36.6 24.8 24.3 38.4 56.8 38.4 91.4 0 34.2-13.3 66.3-37.5 90.5A127.3 127.3 0 01612 612zM361.5 510.4c-.9-8.7-1.4-17.5-1.4-26.4 0-15.9 1.5-31.4 4.3-46.5.7-3.6-1.2-7.3-4.5-8.8-13.6-6.1-26.1-14.5-36.9-25.1a127.54 127.54 0 01-38.7-95.4c.9-32.1 13.8-62.6 36.3-85.6 24.7-25.3 57.9-39.1 93.2-38.7 31.9.3 62.7 12.6 86 34.4 7.9 7.4 14.7 15.6 20.4 24.4 2 3.1 5.9 4.4 9.3 3.2 17.6-6.1 36.2-10.4 55.3-12.4 5.6-.6 8.8-6.6 6.3-11.6-32.5-64.3-98.9-108.7-175.7-109.9-110.9-1.7-203.3 89.2-203.3 199.9 0 62.8 28.9 118.8 74.2 155.5-31.8 14.7-61.1 35-86.5 60.4-54.8 54.7-85.8 126.9-87.8 204a8 8 0 008 8.2h56.1c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5 29.4-29.4 65.4-49.8 104.7-59.7 3.9-1 6.5-4.7 6-8.7z"}}]},name:"team",theme:"outlined"},o=c(55015),i=a.forwardRef(function(e,t){return a.createElement(o.Z,(0,n.Z)({},e,{ref:t,icon:r}))})},13817:function(e,t,c){c.d(t,{default:function(){return H}});var n=c(83145),a=c(2265),r=c(36760),o=c.n(r),i=c(18694),f=c(71744),l=c(80856),u=c(45287),s=c(32186),h=c(25437),d=function(e,t){var c={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&0>t.indexOf(n)&&(c[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var a=0,n=Object.getOwnPropertySymbols(e);at.indexOf(n[a])&&Object.prototype.propertyIsEnumerable.call(e,n[a])&&(c[n[a]]=e[n[a]]);return c};function m(e){let{suffixCls:t,tagName:c,displayName:n}=e;return e=>a.forwardRef((n,r)=>a.createElement(e,Object.assign({ref:r,suffixCls:t,tagName:c},n)))}let v=a.forwardRef((e,t)=>{let{prefixCls:c,suffixCls:n,className:r,tagName:i}=e,l=d(e,["prefixCls","suffixCls","className","tagName"]),{getPrefixCls:u}=a.useContext(f.E_),s=u("layout",c),[m,v,p]=(0,h.ZP)(s),g=n?"".concat(s,"-").concat(n):s;return m(a.createElement(i,Object.assign({className:o()(c||g,r,v,p),ref:t},l)))}),p=a.forwardRef((e,t)=>{let{direction:c}=a.useContext(f.E_),[r,m]=a.useState([]),{prefixCls:v,className:p,rootClassName:g,children:Z,hasSider:y,tagName:z,style:H}=e,V=d(e,["prefixCls","className","rootClassName","children","hasSider","tagName","style"]),b=(0,i.Z)(V,["suffixCls"]),{getPrefixCls:M,className:w,style:x}=(0,f.dj)("layout"),k=M("layout",v),C="boolean"==typeof y?y:!!r.length||(0,u.Z)(Z).some(e=>e.type===s.Z),[N,E,O]=(0,h.ZP)(k),L=o()(k,{["".concat(k,"-has-sider")]:C,["".concat(k,"-rtl")]:"rtl"===c},w,p,g,E,O),j=a.useMemo(()=>({siderHook:{addSider:e=>{m(t=>[].concat((0,n.Z)(t),[e]))},removeSider:e=>{m(t=>t.filter(t=>t!==e))}}}),[]);return N(a.createElement(l.V.Provider,{value:j},a.createElement(z,Object.assign({ref:t,className:L,style:Object.assign(Object.assign({},x),H)},b),Z)))}),g=m({tagName:"div",displayName:"Layout"})(p),Z=m({suffixCls:"header",tagName:"header",displayName:"Header"})(v),y=m({suffixCls:"footer",tagName:"footer",displayName:"Footer"})(v),z=m({suffixCls:"content",tagName:"main",displayName:"Content"})(v);g.Header=Z,g.Footer=y,g.Content=z,g.Sider=s.Z,g._InternalSiderContext=s.D;var H=g},40875:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("chevron-down",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]])},22135:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("chevron-up",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]])},51817:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("loader-circle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]])},21047:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("minus",[["path",{d:"M5 12h14",key:"1ays0h"}]])},70525:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("trending-up",[["path",{d:"M16 7h6v6",key:"box55l"}],["path",{d:"m22 7-8.5 8.5-5-5L2 17",key:"1t1m79"}]])},76865:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("triangle-alert",[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]])},49663:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("user-check",[["path",{d:"m16 11 2 2 4-4",key:"9rsbq5"}],["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]])},95805:function(e,t,c){c.d(t,{Z:function(){return n}});let n=(0,c(79205).Z)("users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]])}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1098-02ecd9e604bf89a1.js b/litellm/proxy/_experimental/out/_next/static/chunks/1098-02ecd9e604bf89a1.js deleted file mode 100644 index c10189fc00d..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/1098-02ecd9e604bf89a1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1098],{30280:function(e,t,l){l.d(t,{EX:function(){return c},Km:function(){return o},Tv:function(){return m}});var s=l(11713),a=l(45345),r=l(90246),i=l(19250),n=l(39760);let o=(0,r.n)("keys"),d=async function(e,t,l){let s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};try{let a=(0,i.getProxyBaseUrl)(),r=new URLSearchParams(Object.entries({team_id:s.teamID,organization_id:s.organizationID,key_alias:s.selectedKeyAlias,key_hash:s.keyHash,user_id:s.userID,page:t,size:l,sort_by:s.sortBy,sort_order:s.sortOrder,expand:s.expand,status:s.status,return_full_object:"true",include_team_keys:"true",include_created_by_keys:"true"}).filter(e=>{let[,t]=e;return null!=t}).map(e=>{let[t,l]=e;return[t,String(l)]})),n="".concat(a?"".concat(a,"/key/list"):"/key/list","?").concat(r),o=await fetch(n,{method:"GET",headers:{[(0,i.getGlobalLitellmHeaderName)()]:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!o.ok){let e=await o.json(),t=(0,i.deriveErrorMessage)(e);throw(0,i.handleError)(t),Error(t)}let d=await o.json();return console.log("/key/list API Response:",d),d}catch(e){throw console.error("Failed to list keys:",e),e}},c=function(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},{accessToken:r}=(0,n.Z)();return(0,s.a)({queryKey:o.list({page:e,limit:t,...l}),queryFn:async()=>await d(r,e,t,l),enabled:!!r,staleTime:3e4,placeholderData:a.Wk})},u=(0,r.n)("deletedKeys"),m=function(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},{accessToken:r}=(0,n.Z)();return(0,s.a)({queryKey:u.list({page:e,limit:t,...l}),queryFn:async()=>await d(r,e,t,{...l,status:"deleted"}),enabled:!!r,staleTime:3e4,placeholderData:a.Wk})}},89348:function(e,t,l){l.d(t,{$:function(){return x}});var s=l(57437),a=l(16312),r=l(42264),i=l(65869),n=l(99397),o=l(2265),d=l(37592),c=l(99981),u=l(49322),m=l(15051),h=l(32489);function g(e){let{group:t,onChange:l,availableModels:a,maxFallbacks:r}=e,i=a.filter(e=>e!==t.primaryModel),n=e=>{let s=t.fallbackModels.filter((t,l)=>l!==e);l({...t,fallbackModels:s})},o=t.fallbackModels.length{let s=[...t.fallbackModels];s.includes(e)&&(s=s.filter(t=>t!==e)),l({...t,primaryModel:e,fallbackModels:s})},showSearch:!0,filterOption:(e,t)=>{var l;return(null!==(l=null==t?void 0:t.label)&&void 0!==l?l:"").toLowerCase().includes(e.toLowerCase())},options:a.map(e=>({label:e,value:e}))}),!t.primaryModel&&(0,s.jsxs)("div",{className:"mt-2 flex items-center gap-2 text-amber-600 text-xs bg-amber-50 p-2 rounded",children:[(0,s.jsx)(u.Z,{className:"w-4 h-4"}),(0,s.jsx)("span",{children:"Select a model to begin configuring fallbacks"})]})]}),(0,s.jsx)("div",{className:"flex items-center justify-center -my-4 z-10",children:(0,s.jsxs)("div",{className:"bg-indigo-50 text-indigo-500 px-4 py-1 rounded-full text-xs font-bold border border-indigo-100 flex items-center gap-2 shadow-sm",children:[(0,s.jsx)(m.Z,{className:"w-4 h-4"}),"IF FAILS, TRY..."]})}),(0,s.jsxs)("div",{className:"transition-opacity duration-300 ".concat(t.primaryModel?"opacity-100":"opacity-50 pointer-events-none"),children:[(0,s.jsxs)("label",{className:"block text-sm font-semibold text-gray-700 mb-2",children:["Fallback Chain ",(0,s.jsx)("span",{className:"text-red-500",children:"*"}),(0,s.jsxs)("span",{className:"text-xs text-gray-500 font-normal ml-2",children:["(Max ",r," fallbacks at a time)"]})]}),(0,s.jsxs)("div",{className:"bg-gray-50 rounded-xl p-4 border border-gray-200",children:[(0,s.jsxs)("div",{className:"mb-4",children:[(0,s.jsx)(d.default,{mode:"multiple",className:"w-full",size:"large",placeholder:o?"Select fallback models to add...":"Maximum ".concat(r," fallbacks reached"),value:t.fallbackModels,onChange:e=>{let s=e.slice(0,r);l({...t,fallbackModels:s})},disabled:!t.primaryModel,options:i.map(e=>({label:e,value:e})),optionRender:(e,l)=>{let a=t.fallbackModels.includes(e.value),r=a?t.fallbackModels.indexOf(e.value)+1:null;return(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[a&&null!==r&&(0,s.jsx)("span",{className:"flex items-center justify-center w-5 h-5 rounded bg-indigo-100 text-indigo-600 text-xs font-bold",children:r}),(0,s.jsx)("span",{children:e.label})]})},maxTagCount:"responsive",maxTagPlaceholder:e=>(0,s.jsx)(c.Z,{styles:{root:{pointerEvents:"none"}},title:e.map(e=>{let{value:t}=e;return t}).join(", "),children:(0,s.jsxs)("span",{children:["+",e.length," more"]})}),showSearch:!0,filterOption:(e,t)=>{var l;return(null!==(l=null==t?void 0:t.label)&&void 0!==l?l:"").toLowerCase().includes(e.toLowerCase())}}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1 ml-1",children:o?"Search and select multiple models. Selected models will appear below in order. (".concat(t.fallbackModels.length,"/").concat(r," used)"):"Maximum ".concat(r," fallbacks reached. Remove some to add more.")})]}),(0,s.jsx)("div",{className:"space-y-2 min-h-[100px]",children:0===t.fallbackModels.length?(0,s.jsxs)("div",{className:"h-32 border-2 border-dashed border-gray-300 rounded-lg flex flex-col items-center justify-center text-gray-400",children:[(0,s.jsx)("span",{className:"text-sm",children:"No fallback models selected"}),(0,s.jsx)("span",{className:"text-xs mt-1",children:"Add models from the dropdown above"})]}):t.fallbackModels.map((e,t)=>(0,s.jsxs)("div",{className:"group flex items-center justify-between p-3 bg-white rounded-lg border border-gray-200 hover:border-indigo-300 hover:shadow-sm transition-all",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[(0,s.jsx)("div",{className:"flex items-center justify-center w-6 h-6 rounded bg-gray-100 text-gray-400 group-hover:text-indigo-500 group-hover:bg-indigo-50",children:(0,s.jsx)("span",{className:"text-xs font-bold",children:t+1})}),(0,s.jsx)("div",{children:(0,s.jsx)("span",{className:"font-medium text-gray-800",children:e})})]}),(0,s.jsx)("button",{type:"button",onClick:()=>n(t),className:"opacity-0 group-hover:opacity-100 transition-opacity text-gray-400 hover:text-red-500 p-1",children:(0,s.jsx)(h.Z,{className:"w-4 h-4"})})]},"".concat(e,"-").concat(t)))})]})]})]})}function x(e){let{groups:t,onGroupsChange:l,availableModels:d,maxFallbacks:c=5,maxGroups:u=5}=e,[m,h]=(0,o.useState)(t.length>0?t[0].id:"1");(0,o.useEffect)(()=>{t.length>0?t.some(e=>e.id===m)||h(t[0].id):h("1")},[t]);let x=()=>{if(t.length>=u)return;let e=Date.now().toString();l([...t,{id:e,primaryModel:null,fallbackModels:[]}]),h(e)},p=e=>{if(1===t.length){r.ZP.warning("At least one group is required");return}let s=t.filter(t=>t.id!==e);l(s),m===e&&s.length>0&&h(s[s.length-1].id)},y=e=>{l(t.map(t=>t.id===e.id?e:t))},f=t.map((e,l)=>{let a=e.primaryModel?e.primaryModel:"Group ".concat(l+1);return{key:e.id,label:a,closable:t.length>1,children:(0,s.jsx)(g,{group:e,onChange:y,availableModels:d,maxFallbacks:c})}});return 0===t.length?(0,s.jsxs)("div",{className:"text-center py-12 bg-gray-50 rounded-lg border border-dashed border-gray-300",children:[(0,s.jsx)("p",{className:"text-gray-500 mb-4",children:"No fallback groups configured"}),(0,s.jsx)(a.z,{variant:"primary",onClick:x,icon:()=>(0,s.jsx)(n.Z,{className:"w-4 h-4"}),children:"Create First Group"})]}):(0,s.jsx)(i.default,{type:"editable-card",activeKey:m,onChange:h,onEdit:(e,l)=>{"add"===l?x():"remove"===l&&t.length>1&&p(e)},items:f,className:"fallback-tabs",tabBarStyle:{marginBottom:0},hideAdd:t.length>=u})}},62099:function(e,t,l){var s=l(57437),a=l(2265),r=l(37592),i=l(99981),n=l(23496),o=l(63709),d=l(15424),c=l(31283);let{Option:u}=r.default;t.Z=e=>{var t;let{form:l,autoRotationEnabled:m,onAutoRotationChange:h,rotationInterval:g,onRotationIntervalChange:x}=e,p=g&&!["7d","30d","90d","180d","365d"].includes(g),[y,f]=(0,a.useState)(p),[j,b]=(0,a.useState)(p?g:""),[v,_]=(0,a.useState)((null==l?void 0:null===(t=l.getFieldValue)||void 0===t?void 0:t.call(l,"duration"))||"");return(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsx)("span",{className:"text-sm font-medium text-gray-700",children:"Key Expiry Settings"}),(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)("label",{className:"text-sm font-medium text-gray-700 flex items-center space-x-1",children:[(0,s.jsx)("span",{children:"Expire Key"}),(0,s.jsx)(i.Z,{title:"Set when this key should expire. Format: 30s (seconds), 30m (minutes), 30h (hours), 30d (days). Use -1 to never expire.",children:(0,s.jsx)(d.Z,{className:"text-gray-400 cursor-help text-xs"})})]}),(0,s.jsx)(c.o,{name:"duration",placeholder:"e.g., 30d or -1 to never expire",className:"w-full",value:v,onValueChange:e=>{_(e),l&&"function"==typeof l.setFieldValue?l.setFieldValue("duration",e):l&&"function"==typeof l.setFieldsValue&&l.setFieldsValue({duration:e})}})]})]}),(0,s.jsx)(n.Z,{}),(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsx)("span",{className:"text-sm font-medium text-gray-700",children:"Auto-Rotation Settings"}),(0,s.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)("label",{className:"text-sm font-medium text-gray-700 flex items-center space-x-1",children:[(0,s.jsx)("span",{children:"Enable Auto-Rotation"}),(0,s.jsx)(i.Z,{title:"Key will automatically regenerate at the specified interval for enhanced security.",children:(0,s.jsx)(d.Z,{className:"text-gray-400 cursor-help text-xs"})})]}),(0,s.jsx)(o.Z,{checked:m,onChange:h,size:"default",className:m?"":"bg-gray-400"})]}),m&&(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)("label",{className:"text-sm font-medium text-gray-700 flex items-center space-x-1",children:[(0,s.jsx)("span",{children:"Rotation Interval"}),(0,s.jsx)(i.Z,{title:"How often the key should be automatically rotated. Choose the interval that best fits your security requirements.",children:(0,s.jsx)(d.Z,{className:"text-gray-400 cursor-help text-xs"})})]}),(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)(r.default,{value:y?"custom":g,onChange:e=>{"custom"===e?f(!0):(f(!1),b(""),x(e))},className:"w-full",placeholder:"Select interval",children:[(0,s.jsx)(u,{value:"7d",children:"7 days"}),(0,s.jsx)(u,{value:"30d",children:"30 days"}),(0,s.jsx)(u,{value:"90d",children:"90 days"}),(0,s.jsx)(u,{value:"180d",children:"180 days"}),(0,s.jsx)(u,{value:"365d",children:"365 days"}),(0,s.jsx)(u,{value:"custom",children:"Custom interval"})]}),y&&(0,s.jsxs)("div",{className:"space-y-1",children:[(0,s.jsx)(c.o,{value:j,onChange:e=>{let t=e.target.value;b(t),x(t)},placeholder:"e.g., 1s, 5m, 2h, 14d"}),(0,s.jsx)("div",{className:"text-xs text-gray-500",children:"Supported formats: seconds (s), minutes (m), hours (h), days (d)"})]})]})]})]}),m&&(0,s.jsx)("div",{className:"bg-blue-50 p-3 rounded-md text-sm text-blue-700",children:"When rotation occurs, you'll receive a notification with the new key. The old key will be deactivated after a brief grace period."})]})]})}},72885:function(e,t,l){var s=l(57437),a=l(2265),r=l(77355),i=l(93416),n=l(74998),o=l(95704),d=l(76593),c=l(9114);t.Z=e=>{let{accessToken:t,initialModelAliases:l={},onAliasUpdate:u,showExampleConfig:m=!0}=e,[h,g]=(0,a.useState)([]),[x,p]=(0,a.useState)({aliasName:"",targetModel:""}),[y,f]=(0,a.useState)(null);(0,a.useEffect)(()=>{g(Object.entries(l).map((e,t)=>{let[l,s]=e;return{id:"".concat(t,"-").concat(l),aliasName:l,targetModel:s}}))},[l]);let j=e=>{f({...e})},b=()=>{if(!y)return;if(!y.aliasName||!y.targetModel){c.Z.fromBackend("Please provide both alias name and target model");return}if(h.some(e=>e.id!==y.id&&e.aliasName===y.aliasName)){c.Z.fromBackend("An alias with this name already exists");return}let e=h.map(e=>e.id===y.id?y:e);g(e),f(null);let t={};e.forEach(e=>{t[e.aliasName]=e.targetModel}),u&&u(t),c.Z.success("Alias updated successfully")},v=()=>{f(null)},_=e=>{let t=h.filter(t=>t.id!==e);g(t);let l={};t.forEach(e=>{l[e.aliasName]=e.targetModel}),u&&u(l),c.Z.success("Alias deleted successfully")},N=h.reduce((e,t)=>(e[t.aliasName]=t.targetModel,e),{});return(0,s.jsxs)("div",{className:"mt-4",children:[(0,s.jsxs)("div",{className:"mb-6",children:[(0,s.jsx)(o.xv,{className:"text-sm font-medium text-gray-700 mb-2",children:"Add New Alias"}),(0,s.jsxs)("div",{className:"grid grid-cols-3 gap-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"block text-xs text-gray-500 mb-1",children:"Alias Name"}),(0,s.jsx)("input",{type:"text",value:x.aliasName,onChange:e=>p({...x,aliasName:e.target.value}),placeholder:"e.g., gpt-4o",className:"w-full px-3 py-2 border border-gray-300 rounded-md text-sm"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"block text-xs text-gray-500 mb-1",children:"Target Model"}),(0,s.jsx)(d.Z,{accessToken:t,value:x.targetModel,placeholder:"Select target model",onChange:e=>p({...x,targetModel:e}),showLabel:!1})]}),(0,s.jsx)("div",{className:"flex items-end",children:(0,s.jsxs)("button",{onClick:()=>{if(!x.aliasName||!x.targetModel){c.Z.fromBackend("Please provide both alias name and target model");return}if(h.some(e=>e.aliasName===x.aliasName)){c.Z.fromBackend("An alias with this name already exists");return}let e=[...h,{id:"".concat(Date.now(),"-").concat(x.aliasName),aliasName:x.aliasName,targetModel:x.targetModel}];g(e),p({aliasName:"",targetModel:""});let t={};e.forEach(e=>{t[e.aliasName]=e.targetModel}),u&&u(t),c.Z.success("Alias added successfully")},disabled:!x.aliasName||!x.targetModel,className:"flex items-center px-4 py-2 rounded-md text-sm ".concat(x.aliasName&&x.targetModel?"bg-green-600 text-white hover:bg-green-700":"bg-gray-300 text-gray-500 cursor-not-allowed"),children:[(0,s.jsx)(r.Z,{className:"w-4 h-4 mr-1"}),"Add Alias"]})})]})]}),(0,s.jsx)(o.xv,{className:"text-sm font-medium text-gray-700 mb-2",children:"Manage Existing Aliases"}),(0,s.jsx)("div",{className:"rounded-lg custom-border relative mb-6",children:(0,s.jsx)("div",{className:"overflow-x-auto",children:(0,s.jsxs)(o.iA,{className:"[&_td]:py-0.5 [&_th]:py-1",children:[(0,s.jsx)(o.ss,{children:(0,s.jsxs)(o.SC,{children:[(0,s.jsx)(o.xs,{className:"py-1 h-8",children:"Alias Name"}),(0,s.jsx)(o.xs,{className:"py-1 h-8",children:"Target Model"}),(0,s.jsx)(o.xs,{className:"py-1 h-8",children:"Actions"})]})}),(0,s.jsxs)(o.RM,{children:[h.map(e=>(0,s.jsx)(o.SC,{className:"h-8",children:y&&y.id===e.id?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.pj,{className:"py-0.5",children:(0,s.jsx)("input",{type:"text",value:y.aliasName,onChange:e=>f({...y,aliasName:e.target.value}),className:"w-full px-2 py-1 border border-gray-300 rounded-md text-sm"})}),(0,s.jsx)(o.pj,{className:"py-0.5",children:(0,s.jsx)(d.Z,{accessToken:t,value:y.targetModel,onChange:e=>f({...y,targetModel:e}),showLabel:!1,style:{height:"32px"}})}),(0,s.jsx)(o.pj,{className:"py-0.5 whitespace-nowrap",children:(0,s.jsxs)("div",{className:"flex space-x-2",children:[(0,s.jsx)("button",{onClick:b,className:"text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100",children:"Save"}),(0,s.jsx)("button",{onClick:v,className:"text-xs bg-gray-50 text-gray-600 px-2 py-1 rounded hover:bg-gray-100",children:"Cancel"})]})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.pj,{className:"py-0.5 text-sm text-gray-900",children:e.aliasName}),(0,s.jsx)(o.pj,{className:"py-0.5 text-sm text-gray-500",children:e.targetModel}),(0,s.jsx)(o.pj,{className:"py-0.5 whitespace-nowrap",children:(0,s.jsxs)("div",{className:"flex space-x-2",children:[(0,s.jsx)("button",{onClick:()=>j(e),className:"text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100",children:(0,s.jsx)(i.Z,{className:"w-3 h-3"})}),(0,s.jsx)("button",{onClick:()=>_(e.id),className:"text-xs bg-red-50 text-red-600 px-2 py-1 rounded hover:bg-red-100",children:(0,s.jsx)(n.Z,{className:"w-3 h-3"})})]})})]})},e.id)),0===h.length&&(0,s.jsx)(o.SC,{children:(0,s.jsx)(o.pj,{colSpan:3,className:"py-0.5 text-sm text-gray-500 text-center",children:"No aliases added yet. Add a new alias above."})})]})]})})}),m&&(0,s.jsxs)(o.Zb,{children:[(0,s.jsx)(o.Dx,{className:"mb-4",children:"Configuration Example"}),(0,s.jsx)(o.xv,{className:"text-gray-600 mb-4",children:"Here's how your current aliases would look in the config:"}),(0,s.jsx)("div",{className:"bg-gray-100 rounded-lg p-4 font-mono text-sm",children:(0,s.jsxs)("div",{className:"text-gray-700",children:["model_aliases:",0===Object.keys(N).length?(0,s.jsxs)("span",{className:"text-gray-500",children:[(0,s.jsx)("br",{}),"\xa0\xa0# No aliases configured yet"]}):Object.entries(N).map(e=>{let[t,l]=e;return(0,s.jsxs)("span",{children:[(0,s.jsx)("br",{}),'\xa0\xa0"',t,'": "',l,'"']},t)})]})})]})]})}},76593:function(e,t,l){var s=l(57437),a=l(2265),r=l(56522),i=l(37592),n=l(69993),o=l(10703);t.Z=e=>{let{accessToken:t,value:l,placeholder:d="Select a Model",onChange:c,disabled:u=!1,style:m,className:h,showLabel:g=!0,labelText:x="Select Model"}=e,[p,y]=(0,a.useState)(l),[f,j]=(0,a.useState)(!1),[b,v]=(0,a.useState)([]),_=(0,a.useRef)(null);return(0,a.useEffect)(()=>{y(l)},[l]),(0,a.useEffect)(()=>{t&&(async()=>{try{let e=await (0,o.p)(t);console.log("Fetched models for selector:",e),e.length>0&&v(e)}catch(e){console.error("Error fetching model info:",e)}})()},[t]),(0,s.jsxs)("div",{children:[g&&(0,s.jsxs)(r.x,{className:"font-medium block mb-2 text-gray-700 flex items-center",children:[(0,s.jsx)(n.Z,{className:"mr-2"})," ",x]}),(0,s.jsx)(i.default,{value:p,placeholder:d,onChange:e=>{"custom"===e?(j(!0),y(void 0)):(j(!1),y(e),c&&c(e))},options:[...Array.from(new Set(b.map(e=>e.model_group))).map((e,t)=>({value:e,label:e,key:t})),{value:"custom",label:"Enter custom model",key:"custom"}],style:{width:"100%",...m},showSearch:!0,className:"rounded-md ".concat(h||""),disabled:u}),f&&(0,s.jsx)(r.o,{className:"mt-2",placeholder:"Enter custom model name",onValueChange:e=>{_.current&&clearTimeout(_.current),_.current=setTimeout(()=>{y(e),c&&c(e)},500)},disabled:u})]})}},2597:function(e,t,l){var s=l(57437);l(2265);var a=l(92280),r=l(54507);t.Z=function(e){let{value:t,onChange:l,premiumUser:i=!1,disabledCallbacks:n=[],onDisabledCallbacksChange:o}=e;return i?(0,s.jsx)(r.Z,{value:t,onChange:l,disabledCallbacks:n,onDisabledCallbacksChange:o}):(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex flex-wrap gap-2 mb-3",children:[(0,s.jsx)("div",{className:"inline-flex items-center px-3 py-1.5 rounded-lg bg-green-50 border border-green-200 text-green-800 text-sm font-medium opacity-50",children:"✨ langfuse-logging"}),(0,s.jsx)("div",{className:"inline-flex items-center px-3 py-1.5 rounded-lg bg-green-50 border border-green-200 text-green-800 text-sm font-medium opacity-50",children:"✨ datadog-logging"})]}),(0,s.jsx)("div",{className:"p-3 bg-yellow-50 border border-yellow-200 rounded-lg",children:(0,s.jsxs)(a.x,{className:"text-sm text-yellow-800",children:["Setting Key/Team logging settings is a LiteLLM Enterprise feature. Global Logging Settings are available for all free users. Get a trial key"," ",(0,s.jsx)("a",{href:"https://www.litellm.ai/#pricing",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"here"}),"."]})})]})}},65895:function(e,t,l){var s=l(57437);l(2265);var a=l(37592),r=l(10032),i=l(99981),n=l(15424);let{Option:o}=a.default;t.Z=e=>{let{type:t,name:l,showDetailedDescriptions:d=!0,className:c="",initialValue:u=null,form:m,onChange:h}=e,g=t.toUpperCase(),x=t.toLowerCase(),p="Select 'guaranteed_throughput' to prevent overallocating ".concat(g," limit when the key belongs to a Team with specific ").concat(g," limits.");return(0,s.jsx)(r.Z.Item,{label:(0,s.jsxs)("span",{children:[g," Rate Limit Type"," ",(0,s.jsx)(i.Z,{title:p,children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:l,initialValue:u,className:c,children:(0,s.jsx)(a.default,{defaultValue:d?"default":void 0,placeholder:"Select rate limit type",style:{width:"100%"},optionLabelProp:d?"label":void 0,onChange:e=>{m&&m.setFieldValue(l,e),h&&h(e)},children:d?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o,{value:"best_effort_throughput",label:"Default",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Default"}),(0,s.jsxs)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:["Best effort throughput - no error if we're overallocating ",x," (Team/Key Limits checked at runtime)."]})]})}),(0,s.jsx)(o,{value:"guaranteed_throughput",label:"Guaranteed throughput",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Guaranteed throughput"}),(0,s.jsxs)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:["Guaranteed throughput - raise an error if we're overallocating ",x," (also checks model-specific limits)"]})]})}),(0,s.jsx)(o,{value:"dynamic",label:"Dynamic",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Dynamic"}),(0,s.jsxs)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:["If the key has a set ",g," (e.g. 2 ",g,") and there are no 429 errors, it can dynamically exceed the limit when the model being called is not erroring."]})]})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o,{value:"best_effort_throughput",children:"Best effort throughput"}),(0,s.jsx)(o,{value:"guaranteed_throughput",children:"Guaranteed throughput"}),(0,s.jsx)(o,{value:"dynamic",children:"Dynamic"})]})})})}},76364:function(e,t,l){var s=l(57437),a=l(2265),r=l(58643),i=l(19250),n=l(56334),o=l(89348),d=l(10703);let c=(0,a.forwardRef)((e,t)=>{let{accessToken:l,value:c,onChange:u,modelData:m}=e,[h,g]=(0,a.useState)({routerSettings:{},selectedStrategy:null,enableTagFiltering:!1}),[x,p]=(0,a.useState)([]),[y,f]=(0,a.useState)([]),[j,b]=(0,a.useState)([]),[v,_]=(0,a.useState)([]),[N,w]=(0,a.useState)({}),[k,S]=(0,a.useState)({}),Z=(0,a.useRef)(!1),C=(0,a.useRef)(null),M=e=>e&&0!==e.length?e.map((e,t)=>{let[l,s]=Object.entries(e)[0];return{id:(t+1).toString(),primaryModel:l||null,fallbackModels:s||[]}}):[{id:"1",primaryModel:null,fallbackModels:[]}],T=e=>e.filter(e=>e.primaryModel&&e.fallbackModels.length>0).map(e=>({[e.primaryModel]:e.fallbackModels}));(0,a.useEffect)(()=>{let e=(null==c?void 0:c.router_settings)?JSON.stringify({routing_strategy:c.router_settings.routing_strategy,fallbacks:c.router_settings.fallbacks,enable_tag_filtering:c.router_settings.enable_tag_filtering}):null;if(Z.current&&e===C.current){Z.current=!1;return}if(Z.current&&e!==C.current&&(Z.current=!1),e!==C.current){if(C.current=e,null==c?void 0:c.router_settings){var t;let e=c.router_settings,{fallbacks:l,...s}=e;g({routerSettings:s,selectedStrategy:e.routing_strategy||null,enableTagFiltering:null!==(t=e.enable_tag_filtering)&&void 0!==t&&t});let a=e.fallbacks||[];p(a),f(M(a))}else g({routerSettings:{},selectedStrategy:null,enableTagFiltering:!1}),p([]),f([{id:"1",primaryModel:null,fallbackModels:[]}])}},[c]),(0,a.useEffect)(()=>{l&&(0,i.getRouterSettingsCall)(l).then(e=>{if(e.fields){let t={};e.fields.forEach(e=>{t[e.field_name]={ui_field_name:e.ui_field_name,field_description:e.field_description,options:e.options,link:e.link}}),w(t);let l=e.fields.find(e=>"routing_strategy"===e.field_name);(null==l?void 0:l.options)&&_(l.options),e.routing_strategy_descriptions&&S(e.routing_strategy_descriptions)}})},[l]),(0,a.useEffect)(()=>{l&&(async()=>{try{let e=await (0,d.p)(l);b(e)}catch(e){console.error("Error fetching model info for fallbacks:",e)}})()},[l]);let L=()=>{let e=new Set(["allowed_fails","cooldown_time","num_retries","timeout","retry_after"]),t=new Set(["model_group_alias","retry_policy"]),l=(l,s,a)=>{if(null==s)return a;let r=String(s).trim();if(""===r||"null"===r.toLowerCase())return null;if(e.has(l)){let e=Number(r);return Number.isNaN(e)?a:e}if(t.has(l)){if(""===r)return null;try{return JSON.parse(r)}catch(e){return a}}return"true"===r.toLowerCase()||"false"!==r.toLowerCase()&&r},s=Object.fromEntries(Object.entries({...h.routerSettings,enable_tag_filtering:h.enableTagFiltering,routing_strategy:h.selectedStrategy,fallbacks:x.length>0?x:null}).map(e=>{let[t,s]=e;if("routing_strategy_args"!==t&&"routing_strategy"!==t&&"enable_tag_filtering"!==t&&"fallbacks"!==t){let e=document.querySelector('input[name="'.concat(t,'"]'));if(e&&void 0!==e.value&&""!==e.value){let a=l(t,e.value,s);return[t,a]}}else if("routing_strategy"===t)return[t,h.selectedStrategy];else if("enable_tag_filtering"===t)return[t,h.enableTagFiltering];else if("fallbacks"===t)return[t,x.length>0?x:null];else if("routing_strategy_args"===t&&"latency-based-routing"===h.selectedStrategy){let e=document.querySelector('input[name="lowest_latency_buffer"]'),t=document.querySelector('input[name="ttl"]'),l={};return(null==e?void 0:e.value)&&(l.lowest_latency_buffer=Number(e.value)),(null==t?void 0:t.value)&&(l.ttl=Number(t.value)),["routing_strategy_args",Object.keys(l).length>0?l:null]}return[t,s]}).filter(e=>null!=e)),a=function(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return null==e||"object"==typeof e&&!Array.isArray(e)&&0===Object.keys(e).length||t&&("number"!=typeof e||Number.isNaN(e))?null:e};return{routing_strategy:a(s.routing_strategy),allowed_fails:a(s.allowed_fails,!0),cooldown_time:a(s.cooldown_time,!0),num_retries:a(s.num_retries,!0),timeout:a(s.timeout,!0),retry_after:a(s.retry_after,!0),fallbacks:x.length>0?x:null,context_window_fallbacks:a(s.context_window_fallbacks),retry_policy:a(s.retry_policy),model_group_alias:a(s.model_group_alias),enable_tag_filtering:h.enableTagFiltering,routing_strategy_args:a(s.routing_strategy_args)}};(0,a.useEffect)(()=>{if(!u)return;let e=setTimeout(()=>{Z.current=!0,u({router_settings:L()})},100);return()=>clearTimeout(e)},[h,x]);let P=Array.from(new Set(j.map(e=>e.model_group))).sort();return((0,a.useImperativeHandle)(t,()=>({getValue:()=>({router_settings:L()})})),l)?(0,s.jsx)("div",{className:"w-full",children:(0,s.jsxs)(r.v0,{className:"w-full",children:[(0,s.jsxs)(r.td,{variant:"line",defaultValue:"1",className:"px-8 pt-4",children:[(0,s.jsx)(r.OK,{value:"1",children:"Loadbalancing"}),(0,s.jsx)(r.OK,{value:"2",children:"Fallbacks"})]}),(0,s.jsxs)(r.nP,{className:"px-8 py-6",children:[(0,s.jsx)(r.x4,{children:(0,s.jsx)(n.Z,{value:h,onChange:g,routerFieldsMetadata:N,availableRoutingStrategies:v,routingStrategyDescriptions:k})}),(0,s.jsx)(r.x4,{children:(0,s.jsx)(o.$,{groups:y,onGroupsChange:e=>{f(e),p(T(e))},availableModels:P,maxFallbacks:5,maxGroups:5})})]})]})}):null});c.displayName="RouterSettingsAccordion",t.Z=c},71098:function(e,t,l){l.d(t,{ZP:function(){return et},wk:function(){return X},Nr:function(){return ee}});var s=l(57437),a=l(30280),r=l(39760),i=l(59872),n=l(15424),o=l(29827),d=l(87452),c=l(88829),u=l(72208),m=l(78489),h=l(49804),g=l(67101),x=l(84264),p=l(49566),y=l(96761),f=l(37592),j=l(10032),b=l(22116),v=l(99981),_=l(29967),N=l(5545),w=l(63709),k=l(4260),S=l(7310),Z=l.n(S),C=l(2265),M=l(29233),T=l(20347),L=l(82586),P=l(97434),A=l(65925),F=l(63610),E=l(62099),I=l(72885),V=l(95096),R=l(2597),O=l(65895),D=l(76364),K=l(84376),U=l(7765),q=l(46468),B=l(97492),G=l(68473),z=l(9114),J=l(19250),W=l(24199),H=l(97415);let Y=e=>{let t;if(!(t=!e||"object"!=typeof e||e instanceof Error?String(e):JSON.stringify(e)).includes("/key/generate")&&!t.includes("KeyManagementRoutes.KEY_GENERATE"))return"Error creating the key: ".concat(e);let l=t;try{if(!e||"object"!=typeof e||e instanceof Error){let e=t.match(/\{[\s\S]*\}/);if(e){let t=JSON.parse(e[0]),s=(null==t?void 0:t.error)||t;(null==s?void 0:s.message)&&(l=s.message)}}else{let t=(null==e?void 0:e.error)||e;(null==t?void 0:t.message)&&(l=t.message)}}catch(e){}return t.includes("team_member_permission_error")||l.includes("Team member does not have permissions")?"Team member does not have permission to generate key for this team. Ask your proxy admin to configure the team member permission settings.":"Error creating the key: ".concat(e)},{Option:$}=f.default,Q=e=>{let t=[];if(console.log("data:",JSON.stringify(e)),e)for(let l of e)l.metadata&&l.metadata.tags&&t.push(...l.metadata.tags);let l=Array.from(new Set(t)).map(e=>({value:e,label:e}));return console.log("uniqueTags:",l),l},X=async(e,t,l,s)=>{try{if(null===e||null===t)return[];if(null!==l){let a=(await (0,J.modelAvailableCall)(l,e,t,!0,s,!0)).data.map(e=>e.id);return console.log("available_model_names:",a),a}return[]}catch(e){return console.error("Error fetching user models:",e),[]}},ee=async(e,t,l,s)=>{try{if(null===e||null===t)return;if(null!==l){let a=(await (0,J.modelAvailableCall)(l,e,t)).data.map(e=>e.id);console.log("available_model_names:",a),s(a)}}catch(e){console.error("Error fetching user models:",e)}};var et=e=>{let{team:t,teams:l,data:S,addKey:et}=e,{accessToken:el,userId:es,userRole:ea,premiumUser:er}=(0,r.Z)(),ei=(0,o.NL)(),[en]=j.Z.useForm(),[eo,ed]=(0,C.useState)(!1),[ec,eu]=(0,C.useState)(null),[em,eh]=(0,C.useState)(null),[eg,ex]=(0,C.useState)([]),[ep,ey]=(0,C.useState)([]),[ef,ej]=(0,C.useState)("you"),[eb,ev]=(0,C.useState)(Q(S)),[e_,eN]=(0,C.useState)([]),[ew,ek]=(0,C.useState)([]),[eS,eZ]=(0,C.useState)([]),[eC,eM]=(0,C.useState)([]),[eT,eL]=(0,C.useState)(t),[eP,eA]=(0,C.useState)(!1),[eF,eE]=(0,C.useState)(null),[eI,eV]=(0,C.useState)({}),[eR,eO]=(0,C.useState)([]),[eD,eK]=(0,C.useState)(!1),[eU,eq]=(0,C.useState)([]),[eB,eG]=(0,C.useState)([]),[ez,eJ]=(0,C.useState)("default"),[eW,eH]=(0,C.useState)({}),[eY,e$]=(0,C.useState)(!1),[eQ,eX]=(0,C.useState)("30d"),[e0,e4]=(0,C.useState)(null),[e1,e2]=(0,C.useState)(0),e5=()=>{ed(!1),en.resetFields(),eM([]),eG([]),eJ("default"),eH({}),e$(!1),eX("30d"),e4(null),e2(e=>e+1)},e3=()=>{ed(!1),eu(null),eL(null),en.resetFields(),eM([]),eG([]),eJ("default"),eH({}),e$(!1),eX("30d"),e4(null),e2(e=>e+1)};(0,C.useEffect)(()=>{es&&ea&&el&&ee(es,ea,el,ex)},[el,es,ea]),(0,C.useEffect)(()=>{let e=async()=>{try{let e=(await (0,J.getPoliciesList)(el)).policies.map(e=>e.policy_name);ek(e)}catch(e){console.error("Failed to fetch policies:",e)}},t=async()=>{try{let e=await (0,J.getPromptsList)(el);eZ(e.prompts.map(e=>e.prompt_id))}catch(e){console.error("Failed to fetch prompts:",e)}};(async()=>{try{let e=(await (0,J.getGuardrailsList)(el)).guardrails.map(e=>e.guardrail_name);eN(e)}catch(e){console.error("Failed to fetch guardrails:",e)}})(),e(),t()},[el]),(0,C.useEffect)(()=>{(async()=>{try{if(el){let e=sessionStorage.getItem("possibleUserRoles");if(e)eV(JSON.parse(e));else{let e=await (0,J.getPossibleUserRoles)(el);sessionStorage.setItem("possibleUserRoles",JSON.stringify(e)),eV(e)}}}catch(e){console.error("Error fetching possible user roles:",e)}})()},[el]);let e7=ep.includes("no-default-models")&&!eT,e6=async e=>{try{var t,l,s,r,i,n,o;let d;let c=null!==(i=null==e?void 0:e.key_alias)&&void 0!==i?i:"",u=null!==(n=null==e?void 0:e.team_id)&&void 0!==n?n:null;if((null!==(o=null==S?void 0:S.filter(e=>e.team_id===u).map(e=>e.key_alias))&&void 0!==o?o:[]).includes(c))throw Error("Key alias ".concat(c," already exists for team with ID ").concat(u,", please provide another key alias"));z.Z.info("Making API Call"),ed(!0),"you"===ef&&(e.user_id=es);let m={};try{m=JSON.parse(e.metadata||"{}")}catch(e){console.error("Error parsing metadata:",e)}if("service_account"===ef&&(m.service_account_id=e.key_alias),eC.length>0&&(m={...m,logging:eC.filter(e=>e.callback_name)}),eB.length>0){let e=(0,P.Z3)(eB);m={...m,litellm_disabled_callbacks:e}}if(eY&&(e.auto_rotate=!0,e.rotation_interval=eQ),e.duration&&(e.duration=e.duration),e.metadata=JSON.stringify(m),e.allowed_vector_store_ids&&e.allowed_vector_store_ids.length>0&&(e.object_permission={vector_stores:e.allowed_vector_store_ids},delete e.allowed_vector_store_ids),e.allowed_mcp_servers_and_groups&&((null===(t=e.allowed_mcp_servers_and_groups.servers)||void 0===t?void 0:t.length)>0||(null===(l=e.allowed_mcp_servers_and_groups.accessGroups)||void 0===l?void 0:l.length)>0)){e.object_permission||(e.object_permission={});let{servers:t,accessGroups:l}=e.allowed_mcp_servers_and_groups;t&&t.length>0&&(e.object_permission.mcp_servers=t),l&&l.length>0&&(e.object_permission.mcp_access_groups=l),delete e.allowed_mcp_servers_and_groups}let h=e.mcp_tool_permissions||{};if(Object.keys(h).length>0&&(e.object_permission||(e.object_permission={}),e.object_permission.mcp_tool_permissions=h),delete e.mcp_tool_permissions,e.allowed_mcp_access_groups&&e.allowed_mcp_access_groups.length>0&&(e.object_permission||(e.object_permission={}),e.object_permission.mcp_access_groups=e.allowed_mcp_access_groups,delete e.allowed_mcp_access_groups),e.allowed_agents_and_groups&&((null===(s=e.allowed_agents_and_groups.agents)||void 0===s?void 0:s.length)>0||(null===(r=e.allowed_agents_and_groups.accessGroups)||void 0===r?void 0:r.length)>0)){e.object_permission||(e.object_permission={});let{agents:t,accessGroups:l}=e.allowed_agents_and_groups;t&&t.length>0&&(e.object_permission.agents=t),l&&l.length>0&&(e.object_permission.agent_access_groups=l),delete e.allowed_agents_and_groups}Object.keys(eW).length>0&&(e.aliases=JSON.stringify(eW)),(null==e0?void 0:e0.router_settings)&&Object.values(e0.router_settings).some(e=>null!=e&&""!==e)&&(e.router_settings=e0.router_settings),d="service_account"===ef?await (0,J.keyCreateServiceAccountCall)(el,e):await (0,J.keyCreateCall)(el,es,e),console.log("key create Response:",d),et(d),ei.invalidateQueries({queryKey:a.Km.lists()}),eu(d.key),eh(d.soft_budget),z.Z.success("Virtual Key Created"),en.resetFields(),localStorage.removeItem("userData"+es)}catch(t){console.log("error in create key:",t);let e=Y(t);z.Z.fromBackend(e)}};(0,C.useEffect)(()=>{if(es&&ea&&el){var e;X(es,ea,el,null!==(e=null==eT?void 0:eT.team_id)&&void 0!==e?e:null).then(e=>{var t;ey(Array.from(new Set([...null!==(t=null==eT?void 0:eT.models)&&void 0!==t?t:[],...e])))})}en.setFieldValue("models",[])},[eT,el,es,ea]);let e9=async e=>{if(!e){eO([]);return}eK(!0);try{let t=new URLSearchParams;if(t.append("user_email",e),null==el)return;let l=(await (0,J.userFilterUICall)(el,t)).map(e=>({label:"".concat(e.user_email," (").concat(e.user_id,")"),value:e.user_id,user:e}));eO(l)}catch(e){console.error("Error fetching users:",e),z.Z.fromBackend("Failed to search for users")}finally{eK(!1)}},e8=(0,C.useCallback)(Z()(e=>e9(e),300),[el]),te=(e,t)=>{let l=t.user;en.setFieldsValue({user_id:l.user_id})};return(0,s.jsxs)("div",{children:[ea&&T.LQ.includes(ea)&&(0,s.jsx)(m.Z,{className:"mx-auto",onClick:()=>ed(!0),children:"+ Create New Key"}),(0,s.jsx)(b.Z,{open:eo,width:1e3,footer:null,onOk:e5,onCancel:e3,children:(0,s.jsxs)(j.Z,{form:en,onFinish:e6,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,s.jsxs)("div",{className:"mb-8",children:[(0,s.jsx)(y.Z,{className:"mb-4",children:"Key Ownership"}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Owned By"," ",(0,s.jsx)(v.Z,{title:"Select who will own this Virtual Key",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),className:"mb-4",children:(0,s.jsxs)(_.ZP.Group,{onChange:e=>ej(e.target.value),value:ef,children:[(0,s.jsx)(_.ZP,{value:"you",children:"You"}),(0,s.jsx)(_.ZP,{value:"service_account",children:"Service Account"}),"Admin"===ea&&(0,s.jsx)(_.ZP,{value:"another_user",children:"Another User"})]})}),"another_user"===ef&&(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["User ID"," ",(0,s.jsx)(v.Z,{title:"The user who will own this key and be responsible for its usage",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"user_id",className:"mt-4",rules:[{required:"another_user"===ef,message:"Please input the user ID of the user you are assigning the key to"}],children:(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{style:{display:"flex",marginBottom:"8px"},children:[(0,s.jsx)(f.default,{showSearch:!0,placeholder:"Type email to search for users",filterOption:!1,onSearch:e=>{e8(e)},onSelect:(e,t)=>te(e,t),options:eR,loading:eD,allowClear:!0,style:{width:"100%"},notFoundContent:eD?"Searching...":"No users found"}),(0,s.jsx)(N.ZP,{onClick:()=>eA(!0),style:{marginLeft:"8px"},children:"Create User"})]}),(0,s.jsx)("div",{className:"text-xs text-gray-500",children:"Search by email to find users"})]})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Team"," ",(0,s.jsx)(v.Z,{title:"The team this key belongs to, which determines available models and budget limits",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"team_id",initialValue:t?t.team_id:null,className:"mt-4",rules:[{required:"service_account"===ef,message:"Please select a team for the service account"}],help:"service_account"===ef?"required":"",children:(0,s.jsx)(K.Z,{teams:l,onChange:e=>{eL((null==l?void 0:l.find(t=>t.team_id===e))||null)}})})]}),e7&&(0,s.jsx)("div",{className:"mb-8 p-4 bg-blue-50 border border-blue-200 rounded-md",children:(0,s.jsx)(x.Z,{className:"text-blue-800 text-sm",children:"Please select a team to continue configuring your Virtual Key. If you do not see any teams, please contact your Proxy Admin to either provide you with access to models or to add you to a team."})}),!e7&&(0,s.jsxs)("div",{className:"mb-8",children:[(0,s.jsx)(y.Z,{className:"mb-4",children:"Key Details"}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["you"===ef||"another_user"===ef?"Key Name":"Service Account ID"," ",(0,s.jsx)(v.Z,{title:"you"===ef||"another_user"===ef?"A descriptive name to identify this key":"Unique identifier for this service account",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"key_alias",rules:[{required:!0,message:"Please input a ".concat("you"===ef?"key name":"service account ID")}],help:"required",children:(0,s.jsx)(p.Z,{placeholder:""})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Models"," ",(0,s.jsx)(v.Z,{title:"Select which models this key can access. Choose 'All Team Models' to grant access to all models available to the team",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"models",rules:"management"===ez||"read_only"===ez?[]:[{required:!0,message:"Please select a model"}],help:"management"===ez||"read_only"===ez?"Models field is disabled for this key type":"required",className:"mt-4",children:(0,s.jsxs)(f.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},disabled:"management"===ez||"read_only"===ez,onChange:e=>{e.includes("all-team-models")&&en.setFieldsValue({models:["all-team-models"]})},children:[(0,s.jsx)($,{value:"all-team-models",children:"All Team Models"},"all-team-models"),ep.map(e=>(0,s.jsx)($,{value:e,children:(0,q.W0)(e)},e))]})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Key Type"," ",(0,s.jsx)(v.Z,{title:"Select the type of key to determine what routes and operations this key can access",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"key_type",initialValue:"default",className:"mt-4",children:(0,s.jsxs)(f.default,{defaultValue:"default",placeholder:"Select key type",style:{width:"100%"},optionLabelProp:"label",onChange:e=>{eJ(e),("management"===e||"read_only"===e)&&en.setFieldsValue({models:[]})},children:[(0,s.jsx)($,{value:"default",label:"Default",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Default"}),(0,s.jsx)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:"Can call LLM API + Management routes"})]})}),(0,s.jsx)($,{value:"llm_api",label:"LLM API",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"LLM API"}),(0,s.jsx)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:"Can call only LLM API routes (chat/completions, embeddings, etc.)"})]})}),(0,s.jsx)($,{value:"management",label:"Management",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Management"}),(0,s.jsx)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:"Can call only management routes (user/team/key management)"})]})})]})})]}),!e7&&(0,s.jsx)("div",{className:"mb-8",children:(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)(y.Z,{className:"m-0",children:"Optional Settings"})}),(0,s.jsxs)(c.Z,{children:[(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Max Budget (USD)"," ",(0,s.jsx)(v.Z,{title:"Maximum amount in USD this key can spend. When reached, the key will be blocked from making further requests",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"max_budget",help:"Budget cannot exceed team max budget: $".concat((null==t?void 0:t.max_budget)!==null&&(null==t?void 0:t.max_budget)!==void 0?null==t?void 0:t.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.max_budget&&l>t.max_budget)throw Error("Budget cannot exceed team max budget: $".concat((0,i.pw)(t.max_budget,4)))}}],children:(0,s.jsx)(W.Z,{step:.01,precision:2,width:200})}),(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Reset Budget"," ",(0,s.jsx)(v.Z,{title:"How often the budget should reset. For example, setting 'daily' will reset the budget every 24 hours",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"budget_duration",help:"Team Reset Budget: ".concat((null==t?void 0:t.budget_duration)!==null&&(null==t?void 0:t.budget_duration)!==void 0?null==t?void 0:t.budget_duration:"None"),children:(0,s.jsx)(A.Z,{onChange:e=>en.setFieldValue("budget_duration",e)})}),(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Tokens per minute Limit (TPM)"," ",(0,s.jsx)(v.Z,{title:"Maximum number of tokens this key can process per minute. Helps control usage and costs",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"tpm_limit",help:"TPM cannot exceed team TPM limit: ".concat((null==t?void 0:t.tpm_limit)!==null&&(null==t?void 0:t.tpm_limit)!==void 0?null==t?void 0:t.tpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.tpm_limit&&l>t.tpm_limit)throw Error("TPM limit cannot exceed team TPM limit: ".concat(t.tpm_limit))}}],children:(0,s.jsx)(W.Z,{step:1,width:400})}),(0,s.jsx)(O.Z,{type:"tpm",name:"tpm_limit_type",className:"mt-4",initialValue:null,form:en,showDetailedDescriptions:!0}),(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Requests per minute Limit (RPM)"," ",(0,s.jsx)(v.Z,{title:"Maximum number of API requests this key can make per minute. Helps prevent abuse and manage load",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"rpm_limit",help:"RPM cannot exceed team RPM limit: ".concat((null==t?void 0:t.rpm_limit)!==null&&(null==t?void 0:t.rpm_limit)!==void 0?null==t?void 0:t.rpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.rpm_limit&&l>t.rpm_limit)throw Error("RPM limit cannot exceed team RPM limit: ".concat(t.rpm_limit))}}],children:(0,s.jsx)(W.Z,{step:1,width:400})}),(0,s.jsx)(O.Z,{type:"rpm",name:"rpm_limit_type",className:"mt-4",initialValue:null,form:en,showDetailedDescriptions:!0}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Guardrails"," ",(0,s.jsx)(v.Z,{title:"Apply safety guardrails to this key to filter content or enforce policies",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"guardrails",className:"mt-4",help:er?"Select existing guardrails or enter new ones":"Premium feature - Upgrade to set guardrails by key",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},disabled:!er,placeholder:er?"Select or enter guardrails":"Premium feature - Upgrade to set guardrails by key",options:e_.map(e=>({value:e,label:e}))})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Disable Global Guardrails"," ",(0,s.jsx)(v.Z,{title:"When enabled, this key will bypass any guardrails configured to run on every request (global guardrails)",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"disable_global_guardrails",className:"mt-4",valuePropName:"checked",help:er?"Bypass global guardrails for this key":"Premium feature - Upgrade to disable global guardrails by key",children:(0,s.jsx)(w.Z,{disabled:!er,checkedChildren:"Yes",unCheckedChildren:"No"})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Policies"," ",(0,s.jsx)(v.Z,{title:"Apply policies to this key to control guardrails and other settings",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/guardrail_policies",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"policies",className:"mt-4",help:er?"Select existing policies or enter new ones":"Premium feature - Upgrade to set policies by key",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},disabled:!er,placeholder:er?"Select or enter policies":"Premium feature - Upgrade to set policies by key",options:ew.map(e=>({value:e,label:e}))})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Prompts"," ",(0,s.jsx)(v.Z,{title:"Allow this key to use specific prompt templates",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/prompt_management",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"prompts",className:"mt-4",help:er?"Select existing prompts or enter new ones":"Premium feature - Upgrade to set prompts by key",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},disabled:!er,placeholder:er?"Select or enter prompts":"Premium feature - Upgrade to set prompts by key",options:eS.map(e=>({value:e,label:e}))})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed Pass Through Routes"," ",(0,s.jsx)(v.Z,{title:"Allow this key to use specific pass through routes",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/pass_through",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"allowed_passthrough_routes",className:"mt-4",help:er?"Select existing pass through routes or enter new ones":"Premium feature - Upgrade to set pass through routes by key",children:(0,s.jsx)(V.Z,{onChange:e=>en.setFieldValue("allowed_passthrough_routes",e),value:en.getFieldValue("allowed_passthrough_routes"),accessToken:el,placeholder:er?"Select or enter pass through routes":"Premium feature - Upgrade to set pass through routes by key",disabled:!er,teamId:eT?eT.team_id:null})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed Vector Stores"," ",(0,s.jsx)(v.Z,{title:"Select which vector stores this key can access. If none selected, the key will have access to all available vector stores",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"allowed_vector_store_ids",className:"mt-4",help:"Select vector stores this key can access. Leave empty for access to all vector stores",children:(0,s.jsx)(H.Z,{onChange:e=>en.setFieldValue("allowed_vector_store_ids",e),value:en.getFieldValue("allowed_vector_store_ids"),accessToken:el,placeholder:"Select vector stores (optional)"})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Metadata"," ",(0,s.jsx)(v.Z,{title:"JSON object with additional information about this key. Used for tracking or custom logic",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"metadata",className:"mt-4",children:(0,s.jsx)(k.default.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Tags"," ",(0,s.jsx)(v.Z,{title:"Tags for tracking spend and/or doing tag-based routing. Used for analytics and filtering",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"tags",className:"mt-4",help:"Tags for tracking spend and/or doing tag-based routing.",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},placeholder:"Enter tags",tokenSeparators:[","],options:eb})}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)("b",{children:"MCP Settings"})}),(0,s.jsxs)(c.Z,{children:[(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed MCP Servers"," ",(0,s.jsx)(v.Z,{title:"Select which MCP servers or access groups this key can access",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"allowed_mcp_servers_and_groups",help:"Select MCP servers or access groups this key can access",children:(0,s.jsx)(B.Z,{onChange:e=>en.setFieldValue("allowed_mcp_servers_and_groups",e),value:en.getFieldValue("allowed_mcp_servers_and_groups"),accessToken:el,placeholder:"Select MCP servers or access groups (optional)"})}),(0,s.jsx)(j.Z.Item,{name:"mcp_tool_permissions",initialValue:{},hidden:!0,children:(0,s.jsx)(k.default,{type:"hidden"})}),(0,s.jsx)(j.Z.Item,{noStyle:!0,shouldUpdate:(e,t)=>e.allowed_mcp_servers_and_groups!==t.allowed_mcp_servers_and_groups||e.mcp_tool_permissions!==t.mcp_tool_permissions,children:()=>{var e;return(0,s.jsx)("div",{className:"mt-6",children:(0,s.jsx)(G.Z,{accessToken:el,selectedServers:(null===(e=en.getFieldValue("allowed_mcp_servers_and_groups"))||void 0===e?void 0:e.servers)||[],toolPermissions:en.getFieldValue("mcp_tool_permissions")||{},onChange:e=>en.setFieldsValue({mcp_tool_permissions:e})})})}})]})]}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)("b",{children:"Agent Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed Agents"," ",(0,s.jsx)(v.Z,{title:"Select which agents or access groups this key can access",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"allowed_agents_and_groups",help:"Select agents or access groups this key can access",children:(0,s.jsx)(L.Z,{onChange:e=>en.setFieldValue("allowed_agents_and_groups",e),value:en.getFieldValue("allowed_agents_and_groups"),accessToken:el,placeholder:"Select agents or access groups (optional)"})})})]}),er?(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)("b",{children:"Logging Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(R.Z,{value:eC,onChange:eM,premiumUser:!0,disabledCallbacks:eB,onDisabledCallbacksChange:eG})})})]}):(0,s.jsx)(v.Z,{title:(0,s.jsxs)("span",{children:["Key-level logging settings is an enterprise feature, get in touch -",(0,s.jsx)("a",{href:"https://www.litellm.ai/enterprise",target:"_blank",children:"https://www.litellm.ai/enterprise"})]}),placement:"top",children:(0,s.jsxs)("div",{style:{position:"relative"},children:[(0,s.jsx)("div",{style:{opacity:.5},children:(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)("b",{children:"Logging Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(R.Z,{value:eC,onChange:eM,premiumUser:!1,disabledCallbacks:eB,onDisabledCallbacksChange:eG})})})]})}),(0,s.jsx)("div",{style:{position:"absolute",inset:0,cursor:"not-allowed"}})]})}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)("b",{children:"Router Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4 w-full",children:(0,s.jsx)(D.Z,{accessToken:el||"",value:e0||void 0,onChange:e4,modelData:eg.length>0?{data:eg.map(e=>({model_name:e}))}:void 0},e1)})})]},"router-settings-accordion-".concat(e1)),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)("b",{children:"Model Aliases"})}),(0,s.jsx)(c.Z,{children:(0,s.jsxs)("div",{className:"mt-4",children:[(0,s.jsx)(x.Z,{className:"text-sm text-gray-600 mb-4",children:"Create custom aliases for models that can be used in API calls. This allows you to create shortcuts for specific models."}),(0,s.jsx)(I.Z,{accessToken:el,initialModelAliases:eW,onAliasUpdate:eH,showExampleConfig:!1})]})})]}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsx)("b",{children:"Key Lifecycle"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(E.Z,{form:en,autoRotationEnabled:eY,onAutoRotationChange:e$,rotationInterval:eQ,onRotationIntervalChange:eX})})}),(0,s.jsx)(j.Z.Item,{name:"duration",hidden:!0,initialValue:null,children:(0,s.jsx)(k.default,{})})]}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(u.Z,{children:(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("b",{children:"Advanced Settings"}),(0,s.jsx)(v.Z,{title:(0,s.jsxs)("span",{children:["Learn more about advanced settings in our"," ",(0,s.jsx)("a",{href:J.proxyBaseUrl?"".concat(J.proxyBaseUrl,"/#/key%20management/generate_key_fn_key_generate_post"):"/#/key%20management/generate_key_fn_key_generate_post",target:"_blank",rel:"noopener noreferrer",className:"text-blue-400 hover:text-blue-300",children:"documentation"})]}),children:(0,s.jsx)(n.Z,{className:"text-gray-400 hover:text-gray-300 cursor-help"})})]})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)(F.Z,{schemaComponent:"GenerateKeyRequest",form:en,excludedFields:["key_alias","team_id","models","duration","metadata","tags","guardrails","max_budget","budget_duration","tpm_limit","rpm_limit"]})})]})]})]})}),(0,s.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,s.jsx)(N.ZP,{htmlType:"submit",disabled:e7,style:{opacity:e7?.5:1},children:"Create Key"})})]})}),eP&&(0,s.jsx)(b.Z,{title:"Create New User",visible:eP,onCancel:()=>eA(!1),footer:null,width:800,children:(0,s.jsx)(U.Z,{userID:es,accessToken:el,teams:l,possibleUIRoles:eI,onUserCreated:e=>{eE(e),en.setFieldsValue({user_id:e}),eA(!1)},isEmbedded:!0})}),ec&&(0,s.jsx)(b.Z,{visible:eo,onOk:e5,onCancel:e3,footer:null,children:(0,s.jsxs)(g.Z,{numItems:1,className:"gap-2 w-full",children:[(0,s.jsx)(y.Z,{children:"Save your Key"}),(0,s.jsx)(h.Z,{numColSpan:1,children:(0,s.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons,"," ",(0,s.jsx)("b",{children:"you will not be able to view it again"})," through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,s.jsx)(h.Z,{numColSpan:1,children:null!=ec?(0,s.jsxs)("div",{children:[(0,s.jsx)(x.Z,{className:"mt-3",children:"Virtual Key:"}),(0,s.jsx)("div",{style:{background:"#f8f8f8",padding:"10px",borderRadius:"5px",marginBottom:"10px"},children:(0,s.jsx)("pre",{style:{wordWrap:"break-word",whiteSpace:"normal"},children:ec})}),(0,s.jsx)(M.CopyToClipboard,{text:ec,onCopy:()=>{z.Z.success("Virtual Key copied to clipboard")},children:(0,s.jsx)(m.Z,{className:"mt-3",children:"Copy Virtual Key"})})]}):(0,s.jsx)(x.Z,{children:"Key being created, this might take 30s"})})]})})]})}},56334:function(e,t,l){l.d(t,{Z:function(){return m}});var s=l(57437);l(2265);var a=l(31283);let r={ttl:3600,lowest_latency_buffer:0};var i=e=>{let{routingStrategyArgs:t}=e,l={ttl:"Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).",lowest_latency_buffer:"Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency)."};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"max-w-3xl",children:[(0,s.jsx)("h3",{className:"text-sm font-medium text-gray-900",children:"Latency-Based Configuration"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Fine-tune latency-based routing behavior"})]}),(0,s.jsx)("div",{className:"grid grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3",children:Object.entries(t||r).map(e=>{let[t,r]=e;return(0,s.jsx)("div",{className:"space-y-2",children:(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:t.replace(/_/g," ")}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-0.5 mb-2",children:l[t]||""}),(0,s.jsx)(a.o,{name:t,defaultValue:"object"==typeof r?JSON.stringify(r,null,2):null==r?void 0:r.toString(),className:"font-mono text-sm w-full"})]})},t)})})]}),(0,s.jsx)("div",{className:"border-t border-gray-200"})]})},n=e=>{let{routerSettings:t,routerFieldsMetadata:l}=e;return(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"max-w-3xl",children:[(0,s.jsx)("h3",{className:"text-sm font-medium text-gray-900",children:"Reliability & Retries"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Configure retry logic and failure handling"})]}),(0,s.jsx)("div",{className:"grid grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3",children:Object.entries(t).filter(e=>{let[t,l]=e;return"fallbacks"!=t&&"context_window_fallbacks"!=t&&"routing_strategy_args"!=t&&"routing_strategy"!=t&&"enable_tag_filtering"!=t}).map(e=>{var t,r;let[i,n]=e;return(0,s.jsx)("div",{className:"space-y-2",children:(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:(null===(t=l[i])||void 0===t?void 0:t.ui_field_name)||i}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-0.5 mb-2",children:(null===(r=l[i])||void 0===r?void 0:r.field_description)||""}),(0,s.jsx)(a.o,{name:i,defaultValue:null==n||"null"===n?"":"object"==typeof n?JSON.stringify(n,null,2):(null==n?void 0:n.toString())||"",placeholder:"—",className:"font-mono text-sm w-full"})]})},i)})})]})},o=l(37592),d=e=>{var t,l;let{selectedStrategy:a,availableStrategies:r,routingStrategyDescriptions:i,routerFieldsMetadata:n,onStrategyChange:d}=e;return(0,s.jsxs)("div",{className:"space-y-2 max-w-3xl",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:(null===(t=n.routing_strategy)||void 0===t?void 0:t.ui_field_name)||"Routing Strategy"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-0.5 mb-2",children:(null===(l=n.routing_strategy)||void 0===l?void 0:l.field_description)||""})]}),(0,s.jsx)("div",{className:"routing-strategy-select max-w-3xl",children:(0,s.jsx)(o.default,{value:a,onChange:d,style:{width:"100%"},size:"large",children:r.map(e=>(0,s.jsx)(o.default.Option,{value:e,label:e,children:(0,s.jsxs)("div",{className:"flex flex-col gap-0.5 py-1",children:[(0,s.jsx)("span",{className:"font-mono text-sm font-medium",children:e}),i[e]&&(0,s.jsx)("span",{className:"text-xs text-gray-500 font-normal",children:i[e]})]})},e))})})]})},c=l(59341),u=e=>{var t,l,a;let{enabled:r,routerFieldsMetadata:i,onToggle:n}=e;return(0,s.jsx)("div",{className:"space-y-3 max-w-3xl",children:(0,s.jsxs)("div",{className:"flex items-start justify-between",children:[(0,s.jsxs)("div",{className:"flex-1",children:[(0,s.jsx)("label",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:(null===(t=i.enable_tag_filtering)||void 0===t?void 0:t.ui_field_name)||"Enable Tag Filtering"}),(0,s.jsxs)("p",{className:"text-xs text-gray-500 mt-0.5",children:[(null===(l=i.enable_tag_filtering)||void 0===l?void 0:l.field_description)||"",(null===(a=i.enable_tag_filtering)||void 0===a?void 0:a.link)&&(0,s.jsxs)(s.Fragment,{children:[" ",(0,s.jsx)("a",{href:i.enable_tag_filtering.link,target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:text-blue-800 underline",children:"Learn more"})]})]})]}),(0,s.jsx)(c.Z,{checked:r,onChange:n,className:"ml-4"})]})})},m=e=>{let{value:t,onChange:l,routerFieldsMetadata:a,availableRoutingStrategies:r,routingStrategyDescriptions:o}=e;return(0,s.jsxs)("div",{className:"w-full space-y-8 py-2",children:[(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"max-w-3xl",children:[(0,s.jsx)("h3",{className:"text-sm font-medium text-gray-900",children:"Routing Settings"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Configure how requests are routed to deployments"})]}),r.length>0&&(0,s.jsx)(d,{selectedStrategy:t.selectedStrategy||t.routerSettings.routing_strategy||null,availableStrategies:r,routingStrategyDescriptions:o,routerFieldsMetadata:a,onStrategyChange:e=>{l({...t,selectedStrategy:e})}}),(0,s.jsx)(u,{enabled:t.enableTagFiltering,routerFieldsMetadata:a,onToggle:e=>{l({...t,enableTagFiltering:e})}})]}),(0,s.jsx)("div",{className:"border-t border-gray-200"}),"latency-based-routing"===t.selectedStrategy&&(0,s.jsx)(i,{routingStrategyArgs:t.routerSettings.routing_strategy_args}),(0,s.jsx)(n,{routerSettings:t.routerSettings,routerFieldsMetadata:a})]})}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1098-a1702da59647cf14.js b/litellm/proxy/_experimental/out/_next/static/chunks/1098-a1702da59647cf14.js new file mode 100644 index 00000000000..8bdb738f169 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/1098-a1702da59647cf14.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1098],{30280:function(e,t,l){l.d(t,{EX:function(){return c},Km:function(){return o},Tv:function(){return u}});var s=l(11713),a=l(45345),r=l(90246),i=l(19250),n=l(39760);let o=(0,r.n)("keys"),d=async function(e,t,l){let s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};try{let a=(0,i.getProxyBaseUrl)(),r=new URLSearchParams(Object.entries({team_id:s.teamID,organization_id:s.organizationID,key_alias:s.selectedKeyAlias,key_hash:s.keyHash,user_id:s.userID,page:t,size:l,sort_by:s.sortBy,sort_order:s.sortOrder,expand:s.expand,status:s.status,return_full_object:"true",include_team_keys:"true",include_created_by_keys:"true"}).filter(e=>{let[,t]=e;return null!=t}).map(e=>{let[t,l]=e;return[t,String(l)]})),n="".concat(a?"".concat(a,"/key/list"):"/key/list","?").concat(r),o=await fetch(n,{method:"GET",headers:{[(0,i.getGlobalLitellmHeaderName)()]:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!o.ok){let e=await o.json(),t=(0,i.deriveErrorMessage)(e);throw(0,i.handleError)(t),Error(t)}let d=await o.json();return console.log("/key/list API Response:",d),d}catch(e){throw console.error("Failed to list keys:",e),e}},c=function(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},{accessToken:r}=(0,n.Z)();return(0,s.a)({queryKey:o.list({page:e,limit:t,...l}),queryFn:async()=>await d(r,e,t,l),enabled:!!r,staleTime:3e4,placeholderData:a.Wk})},m=(0,r.n)("deletedKeys"),u=function(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},{accessToken:r}=(0,n.Z)();return(0,s.a)({queryKey:m.list({page:e,limit:t,...l}),queryFn:async()=>await d(r,e,t,{...l,status:"deleted"}),enabled:!!r,staleTime:3e4,placeholderData:a.Wk})}},89348:function(e,t,l){l.d(t,{$:function(){return x}});var s=l(57437),a=l(16312),r=l(42264),i=l(65869),n=l(99397),o=l(2265),d=l(37592),c=l(99981),m=l(49322),u=l(15051),h=l(32489);function g(e){let{group:t,onChange:l,availableModels:a,maxFallbacks:r}=e,i=a.filter(e=>e!==t.primaryModel),n=e=>{let s=t.fallbackModels.filter((t,l)=>l!==e);l({...t,fallbackModels:s})},o=t.fallbackModels.length{let s=[...t.fallbackModels];s.includes(e)&&(s=s.filter(t=>t!==e)),l({...t,primaryModel:e,fallbackModels:s})},showSearch:!0,filterOption:(e,t)=>{var l;return(null!==(l=null==t?void 0:t.label)&&void 0!==l?l:"").toLowerCase().includes(e.toLowerCase())},options:a.map(e=>({label:e,value:e}))}),!t.primaryModel&&(0,s.jsxs)("div",{className:"mt-2 flex items-center gap-2 text-amber-600 text-xs bg-amber-50 p-2 rounded",children:[(0,s.jsx)(m.Z,{className:"w-4 h-4"}),(0,s.jsx)("span",{children:"Select a model to begin configuring fallbacks"})]})]}),(0,s.jsx)("div",{className:"flex items-center justify-center -my-4 z-10",children:(0,s.jsxs)("div",{className:"bg-indigo-50 text-indigo-500 px-4 py-1 rounded-full text-xs font-bold border border-indigo-100 flex items-center gap-2 shadow-sm",children:[(0,s.jsx)(u.Z,{className:"w-4 h-4"}),"IF FAILS, TRY..."]})}),(0,s.jsxs)("div",{className:"transition-opacity duration-300 ".concat(t.primaryModel?"opacity-100":"opacity-50 pointer-events-none"),children:[(0,s.jsxs)("label",{className:"block text-sm font-semibold text-gray-700 mb-2",children:["Fallback Chain ",(0,s.jsx)("span",{className:"text-red-500",children:"*"}),(0,s.jsxs)("span",{className:"text-xs text-gray-500 font-normal ml-2",children:["(Max ",r," fallbacks at a time)"]})]}),(0,s.jsxs)("div",{className:"bg-gray-50 rounded-xl p-4 border border-gray-200",children:[(0,s.jsxs)("div",{className:"mb-4",children:[(0,s.jsx)(d.default,{mode:"multiple",className:"w-full",size:"large",placeholder:o?"Select fallback models to add...":"Maximum ".concat(r," fallbacks reached"),value:t.fallbackModels,onChange:e=>{let s=e.slice(0,r);l({...t,fallbackModels:s})},disabled:!t.primaryModel,options:i.map(e=>({label:e,value:e})),optionRender:(e,l)=>{let a=t.fallbackModels.includes(e.value),r=a?t.fallbackModels.indexOf(e.value)+1:null;return(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[a&&null!==r&&(0,s.jsx)("span",{className:"flex items-center justify-center w-5 h-5 rounded bg-indigo-100 text-indigo-600 text-xs font-bold",children:r}),(0,s.jsx)("span",{children:e.label})]})},maxTagCount:"responsive",maxTagPlaceholder:e=>(0,s.jsx)(c.Z,{styles:{root:{pointerEvents:"none"}},title:e.map(e=>{let{value:t}=e;return t}).join(", "),children:(0,s.jsxs)("span",{children:["+",e.length," more"]})}),showSearch:!0,filterOption:(e,t)=>{var l;return(null!==(l=null==t?void 0:t.label)&&void 0!==l?l:"").toLowerCase().includes(e.toLowerCase())}}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1 ml-1",children:o?"Search and select multiple models. Selected models will appear below in order. (".concat(t.fallbackModels.length,"/").concat(r," used)"):"Maximum ".concat(r," fallbacks reached. Remove some to add more.")})]}),(0,s.jsx)("div",{className:"space-y-2 min-h-[100px]",children:0===t.fallbackModels.length?(0,s.jsxs)("div",{className:"h-32 border-2 border-dashed border-gray-300 rounded-lg flex flex-col items-center justify-center text-gray-400",children:[(0,s.jsx)("span",{className:"text-sm",children:"No fallback models selected"}),(0,s.jsx)("span",{className:"text-xs mt-1",children:"Add models from the dropdown above"})]}):t.fallbackModels.map((e,t)=>(0,s.jsxs)("div",{className:"group flex items-center justify-between p-3 bg-white rounded-lg border border-gray-200 hover:border-indigo-300 hover:shadow-sm transition-all",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[(0,s.jsx)("div",{className:"flex items-center justify-center w-6 h-6 rounded bg-gray-100 text-gray-400 group-hover:text-indigo-500 group-hover:bg-indigo-50",children:(0,s.jsx)("span",{className:"text-xs font-bold",children:t+1})}),(0,s.jsx)("div",{children:(0,s.jsx)("span",{className:"font-medium text-gray-800",children:e})})]}),(0,s.jsx)("button",{type:"button",onClick:()=>n(t),className:"opacity-0 group-hover:opacity-100 transition-opacity text-gray-400 hover:text-red-500 p-1",children:(0,s.jsx)(h.Z,{className:"w-4 h-4"})})]},"".concat(e,"-").concat(t)))})]})]})]})}function x(e){let{groups:t,onGroupsChange:l,availableModels:d,maxFallbacks:c=5,maxGroups:m=5}=e,[u,h]=(0,o.useState)(t.length>0?t[0].id:"1");(0,o.useEffect)(()=>{t.length>0?t.some(e=>e.id===u)||h(t[0].id):h("1")},[t]);let x=()=>{if(t.length>=m)return;let e=Date.now().toString();l([...t,{id:e,primaryModel:null,fallbackModels:[]}]),h(e)},p=e=>{if(1===t.length){r.ZP.warning("At least one group is required");return}let s=t.filter(t=>t.id!==e);l(s),u===e&&s.length>0&&h(s[s.length-1].id)},y=e=>{l(t.map(t=>t.id===e.id?e:t))},f=t.map((e,l)=>{let a=e.primaryModel?e.primaryModel:"Group ".concat(l+1);return{key:e.id,label:a,closable:t.length>1,children:(0,s.jsx)(g,{group:e,onChange:y,availableModels:d,maxFallbacks:c})}});return 0===t.length?(0,s.jsxs)("div",{className:"text-center py-12 bg-gray-50 rounded-lg border border-dashed border-gray-300",children:[(0,s.jsx)("p",{className:"text-gray-500 mb-4",children:"No fallback groups configured"}),(0,s.jsx)(a.z,{variant:"primary",onClick:x,icon:()=>(0,s.jsx)(n.Z,{className:"w-4 h-4"}),children:"Create First Group"})]}):(0,s.jsx)(i.default,{type:"editable-card",activeKey:u,onChange:h,onEdit:(e,l)=>{"add"===l?x():"remove"===l&&t.length>1&&p(e)},items:f,className:"fallback-tabs",tabBarStyle:{marginBottom:0},hideAdd:t.length>=m})}},62099:function(e,t,l){var s=l(57437),a=l(2265),r=l(37592),i=l(99981),n=l(23496),o=l(63709),d=l(15424),c=l(31283);let{Option:m}=r.default;t.Z=e=>{var t;let{form:l,autoRotationEnabled:u,onAutoRotationChange:h,rotationInterval:g,onRotationIntervalChange:x,isCreateMode:p=!1}=e,y=g&&!["7d","30d","90d","180d","365d"].includes(g),[f,j]=(0,a.useState)(y),[b,v]=(0,a.useState)(y?g:""),[_,N]=(0,a.useState)((null==l?void 0:null===(t=l.getFieldValue)||void 0===t?void 0:t.call(l,"duration"))||"");return(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsx)("span",{className:"text-sm font-medium text-gray-700",children:"Key Expiry Settings"}),(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)("label",{className:"text-sm font-medium text-gray-700 flex items-center space-x-1",children:[(0,s.jsx)("span",{children:"Expire Key"}),(0,s.jsx)(i.Z,{title:p?"Set when this key should expire. Format: 30s (seconds), 30m (minutes), 30h (hours), 30d (days). Leave empty to never expire.":"Set when this key should expire. Format: 30s (seconds), 30m (minutes), 30h (hours), 30d (days). Use -1 to never expire.",children:(0,s.jsx)(d.Z,{className:"text-gray-400 cursor-help text-xs"})})]}),(0,s.jsx)(c.o,{name:"duration",placeholder:p?"e.g., 30d or leave empty to never expire":"e.g., 30d or -1 to never expire",className:"w-full",value:_,onValueChange:e=>{N(e),l&&"function"==typeof l.setFieldValue?l.setFieldValue("duration",e):l&&"function"==typeof l.setFieldsValue&&l.setFieldsValue({duration:e})}})]})]}),(0,s.jsx)(n.Z,{}),(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsx)("span",{className:"text-sm font-medium text-gray-700",children:"Auto-Rotation Settings"}),(0,s.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)("label",{className:"text-sm font-medium text-gray-700 flex items-center space-x-1",children:[(0,s.jsx)("span",{children:"Enable Auto-Rotation"}),(0,s.jsx)(i.Z,{title:"Key will automatically regenerate at the specified interval for enhanced security.",children:(0,s.jsx)(d.Z,{className:"text-gray-400 cursor-help text-xs"})})]}),(0,s.jsx)(o.Z,{checked:u,onChange:h,size:"default",className:u?"":"bg-gray-400"})]}),u&&(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)("label",{className:"text-sm font-medium text-gray-700 flex items-center space-x-1",children:[(0,s.jsx)("span",{children:"Rotation Interval"}),(0,s.jsx)(i.Z,{title:"How often the key should be automatically rotated. Choose the interval that best fits your security requirements.",children:(0,s.jsx)(d.Z,{className:"text-gray-400 cursor-help text-xs"})})]}),(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsxs)(r.default,{value:f?"custom":g,onChange:e=>{"custom"===e?j(!0):(j(!1),v(""),x(e))},className:"w-full",placeholder:"Select interval",children:[(0,s.jsx)(m,{value:"7d",children:"7 days"}),(0,s.jsx)(m,{value:"30d",children:"30 days"}),(0,s.jsx)(m,{value:"90d",children:"90 days"}),(0,s.jsx)(m,{value:"180d",children:"180 days"}),(0,s.jsx)(m,{value:"365d",children:"365 days"}),(0,s.jsx)(m,{value:"custom",children:"Custom interval"})]}),f&&(0,s.jsxs)("div",{className:"space-y-1",children:[(0,s.jsx)(c.o,{value:b,onChange:e=>{let t=e.target.value;v(t),x(t)},placeholder:"e.g., 1s, 5m, 2h, 14d"}),(0,s.jsx)("div",{className:"text-xs text-gray-500",children:"Supported formats: seconds (s), minutes (m), hours (h), days (d)"})]})]})]})]}),u&&(0,s.jsx)("div",{className:"bg-blue-50 p-3 rounded-md text-sm text-blue-700",children:"When rotation occurs, you'll receive a notification with the new key. The old key will be deactivated after a brief grace period."})]})]})}},72885:function(e,t,l){var s=l(57437),a=l(2265),r=l(77355),i=l(93416),n=l(74998),o=l(95704),d=l(76593),c=l(9114);t.Z=e=>{let{accessToken:t,initialModelAliases:l={},onAliasUpdate:m,showExampleConfig:u=!0}=e,[h,g]=(0,a.useState)([]),[x,p]=(0,a.useState)({aliasName:"",targetModel:""}),[y,f]=(0,a.useState)(null);(0,a.useEffect)(()=>{g(Object.entries(l).map((e,t)=>{let[l,s]=e;return{id:"".concat(t,"-").concat(l),aliasName:l,targetModel:s}}))},[l]);let j=e=>{f({...e})},b=()=>{if(!y)return;if(!y.aliasName||!y.targetModel){c.Z.fromBackend("Please provide both alias name and target model");return}if(h.some(e=>e.id!==y.id&&e.aliasName===y.aliasName)){c.Z.fromBackend("An alias with this name already exists");return}let e=h.map(e=>e.id===y.id?y:e);g(e),f(null);let t={};e.forEach(e=>{t[e.aliasName]=e.targetModel}),m&&m(t),c.Z.success("Alias updated successfully")},v=()=>{f(null)},_=e=>{let t=h.filter(t=>t.id!==e);g(t);let l={};t.forEach(e=>{l[e.aliasName]=e.targetModel}),m&&m(l),c.Z.success("Alias deleted successfully")},N=h.reduce((e,t)=>(e[t.aliasName]=t.targetModel,e),{});return(0,s.jsxs)("div",{className:"mt-4",children:[(0,s.jsxs)("div",{className:"mb-6",children:[(0,s.jsx)(o.xv,{className:"text-sm font-medium text-gray-700 mb-2",children:"Add New Alias"}),(0,s.jsxs)("div",{className:"grid grid-cols-3 gap-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"block text-xs text-gray-500 mb-1",children:"Alias Name"}),(0,s.jsx)("input",{type:"text",value:x.aliasName,onChange:e=>p({...x,aliasName:e.target.value}),placeholder:"e.g., gpt-4o",className:"w-full px-3 py-2 border border-gray-300 rounded-md text-sm"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"block text-xs text-gray-500 mb-1",children:"Target Model"}),(0,s.jsx)(d.Z,{accessToken:t,value:x.targetModel,placeholder:"Select target model",onChange:e=>p({...x,targetModel:e}),showLabel:!1})]}),(0,s.jsx)("div",{className:"flex items-end",children:(0,s.jsxs)("button",{onClick:()=>{if(!x.aliasName||!x.targetModel){c.Z.fromBackend("Please provide both alias name and target model");return}if(h.some(e=>e.aliasName===x.aliasName)){c.Z.fromBackend("An alias with this name already exists");return}let e=[...h,{id:"".concat(Date.now(),"-").concat(x.aliasName),aliasName:x.aliasName,targetModel:x.targetModel}];g(e),p({aliasName:"",targetModel:""});let t={};e.forEach(e=>{t[e.aliasName]=e.targetModel}),m&&m(t),c.Z.success("Alias added successfully")},disabled:!x.aliasName||!x.targetModel,className:"flex items-center px-4 py-2 rounded-md text-sm ".concat(x.aliasName&&x.targetModel?"bg-green-600 text-white hover:bg-green-700":"bg-gray-300 text-gray-500 cursor-not-allowed"),children:[(0,s.jsx)(r.Z,{className:"w-4 h-4 mr-1"}),"Add Alias"]})})]})]}),(0,s.jsx)(o.xv,{className:"text-sm font-medium text-gray-700 mb-2",children:"Manage Existing Aliases"}),(0,s.jsx)("div",{className:"rounded-lg custom-border relative mb-6",children:(0,s.jsx)("div",{className:"overflow-x-auto",children:(0,s.jsxs)(o.iA,{className:"[&_td]:py-0.5 [&_th]:py-1",children:[(0,s.jsx)(o.ss,{children:(0,s.jsxs)(o.SC,{children:[(0,s.jsx)(o.xs,{className:"py-1 h-8",children:"Alias Name"}),(0,s.jsx)(o.xs,{className:"py-1 h-8",children:"Target Model"}),(0,s.jsx)(o.xs,{className:"py-1 h-8",children:"Actions"})]})}),(0,s.jsxs)(o.RM,{children:[h.map(e=>(0,s.jsx)(o.SC,{className:"h-8",children:y&&y.id===e.id?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.pj,{className:"py-0.5",children:(0,s.jsx)("input",{type:"text",value:y.aliasName,onChange:e=>f({...y,aliasName:e.target.value}),className:"w-full px-2 py-1 border border-gray-300 rounded-md text-sm"})}),(0,s.jsx)(o.pj,{className:"py-0.5",children:(0,s.jsx)(d.Z,{accessToken:t,value:y.targetModel,onChange:e=>f({...y,targetModel:e}),showLabel:!1,style:{height:"32px"}})}),(0,s.jsx)(o.pj,{className:"py-0.5 whitespace-nowrap",children:(0,s.jsxs)("div",{className:"flex space-x-2",children:[(0,s.jsx)("button",{onClick:b,className:"text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100",children:"Save"}),(0,s.jsx)("button",{onClick:v,className:"text-xs bg-gray-50 text-gray-600 px-2 py-1 rounded hover:bg-gray-100",children:"Cancel"})]})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.pj,{className:"py-0.5 text-sm text-gray-900",children:e.aliasName}),(0,s.jsx)(o.pj,{className:"py-0.5 text-sm text-gray-500",children:e.targetModel}),(0,s.jsx)(o.pj,{className:"py-0.5 whitespace-nowrap",children:(0,s.jsxs)("div",{className:"flex space-x-2",children:[(0,s.jsx)("button",{onClick:()=>j(e),className:"text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100",children:(0,s.jsx)(i.Z,{className:"w-3 h-3"})}),(0,s.jsx)("button",{onClick:()=>_(e.id),className:"text-xs bg-red-50 text-red-600 px-2 py-1 rounded hover:bg-red-100",children:(0,s.jsx)(n.Z,{className:"w-3 h-3"})})]})})]})},e.id)),0===h.length&&(0,s.jsx)(o.SC,{children:(0,s.jsx)(o.pj,{colSpan:3,className:"py-0.5 text-sm text-gray-500 text-center",children:"No aliases added yet. Add a new alias above."})})]})]})})}),u&&(0,s.jsxs)(o.Zb,{children:[(0,s.jsx)(o.Dx,{className:"mb-4",children:"Configuration Example"}),(0,s.jsx)(o.xv,{className:"text-gray-600 mb-4",children:"Here's how your current aliases would look in the config:"}),(0,s.jsx)("div",{className:"bg-gray-100 rounded-lg p-4 font-mono text-sm",children:(0,s.jsxs)("div",{className:"text-gray-700",children:["model_aliases:",0===Object.keys(N).length?(0,s.jsxs)("span",{className:"text-gray-500",children:[(0,s.jsx)("br",{}),"\xa0\xa0# No aliases configured yet"]}):Object.entries(N).map(e=>{let[t,l]=e;return(0,s.jsxs)("span",{children:[(0,s.jsx)("br",{}),'\xa0\xa0"',t,'": "',l,'"']},t)})]})})]})]})}},76593:function(e,t,l){var s=l(57437),a=l(2265),r=l(56522),i=l(37592),n=l(69993),o=l(10703);t.Z=e=>{let{accessToken:t,value:l,placeholder:d="Select a Model",onChange:c,disabled:m=!1,style:u,className:h,showLabel:g=!0,labelText:x="Select Model"}=e,[p,y]=(0,a.useState)(l),[f,j]=(0,a.useState)(!1),[b,v]=(0,a.useState)([]),_=(0,a.useRef)(null);return(0,a.useEffect)(()=>{y(l)},[l]),(0,a.useEffect)(()=>{t&&(async()=>{try{let e=await (0,o.p)(t);console.log("Fetched models for selector:",e),e.length>0&&v(e)}catch(e){console.error("Error fetching model info:",e)}})()},[t]),(0,s.jsxs)("div",{children:[g&&(0,s.jsxs)(r.x,{className:"font-medium block mb-2 text-gray-700 flex items-center",children:[(0,s.jsx)(n.Z,{className:"mr-2"})," ",x]}),(0,s.jsx)(i.default,{value:p,placeholder:d,onChange:e=>{"custom"===e?(j(!0),y(void 0)):(j(!1),y(e),c&&c(e))},options:[...Array.from(new Set(b.map(e=>e.model_group))).map((e,t)=>({value:e,label:e,key:t})),{value:"custom",label:"Enter custom model",key:"custom"}],style:{width:"100%",...u},showSearch:!0,className:"rounded-md ".concat(h||""),disabled:m}),f&&(0,s.jsx)(r.o,{className:"mt-2",placeholder:"Enter custom model name",onValueChange:e=>{_.current&&clearTimeout(_.current),_.current=setTimeout(()=>{y(e),c&&c(e)},500)},disabled:m})]})}},2597:function(e,t,l){var s=l(57437);l(2265);var a=l(92280),r=l(54507);t.Z=function(e){let{value:t,onChange:l,premiumUser:i=!1,disabledCallbacks:n=[],onDisabledCallbacksChange:o}=e;return i?(0,s.jsx)(r.Z,{value:t,onChange:l,disabledCallbacks:n,onDisabledCallbacksChange:o}):(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex flex-wrap gap-2 mb-3",children:[(0,s.jsx)("div",{className:"inline-flex items-center px-3 py-1.5 rounded-lg bg-green-50 border border-green-200 text-green-800 text-sm font-medium opacity-50",children:"✨ langfuse-logging"}),(0,s.jsx)("div",{className:"inline-flex items-center px-3 py-1.5 rounded-lg bg-green-50 border border-green-200 text-green-800 text-sm font-medium opacity-50",children:"✨ datadog-logging"})]}),(0,s.jsx)("div",{className:"p-3 bg-yellow-50 border border-yellow-200 rounded-lg",children:(0,s.jsxs)(a.x,{className:"text-sm text-yellow-800",children:["Setting Key/Team logging settings is a LiteLLM Enterprise feature. Global Logging Settings are available for all free users. Get a trial key"," ",(0,s.jsx)("a",{href:"https://www.litellm.ai/#pricing",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"here"}),"."]})})]})}},65895:function(e,t,l){var s=l(57437);l(2265);var a=l(37592),r=l(10032),i=l(99981),n=l(15424);let{Option:o}=a.default;t.Z=e=>{let{type:t,name:l,showDetailedDescriptions:d=!0,className:c="",initialValue:m=null,form:u,onChange:h}=e,g=t.toUpperCase(),x=t.toLowerCase(),p="Select 'guaranteed_throughput' to prevent overallocating ".concat(g," limit when the key belongs to a Team with specific ").concat(g," limits.");return(0,s.jsx)(r.Z.Item,{label:(0,s.jsxs)("span",{children:[g," Rate Limit Type"," ",(0,s.jsx)(i.Z,{title:p,children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:l,initialValue:m,className:c,children:(0,s.jsx)(a.default,{defaultValue:d?"default":void 0,placeholder:"Select rate limit type",style:{width:"100%"},optionLabelProp:d?"label":void 0,onChange:e=>{u&&u.setFieldValue(l,e),h&&h(e)},children:d?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o,{value:"best_effort_throughput",label:"Default",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Default"}),(0,s.jsxs)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:["Best effort throughput - no error if we're overallocating ",x," (Team/Key Limits checked at runtime)."]})]})}),(0,s.jsx)(o,{value:"guaranteed_throughput",label:"Guaranteed throughput",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Guaranteed throughput"}),(0,s.jsxs)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:["Guaranteed throughput - raise an error if we're overallocating ",x," (also checks model-specific limits)"]})]})}),(0,s.jsx)(o,{value:"dynamic",label:"Dynamic",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Dynamic"}),(0,s.jsxs)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:["If the key has a set ",g," (e.g. 2 ",g,") and there are no 429 errors, it can dynamically exceed the limit when the model being called is not erroring."]})]})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o,{value:"best_effort_throughput",children:"Best effort throughput"}),(0,s.jsx)(o,{value:"guaranteed_throughput",children:"Guaranteed throughput"}),(0,s.jsx)(o,{value:"dynamic",children:"Dynamic"})]})})})}},76364:function(e,t,l){var s=l(57437),a=l(2265),r=l(58643),i=l(19250),n=l(56334),o=l(89348),d=l(10703);let c=(0,a.forwardRef)((e,t)=>{let{accessToken:l,value:c,onChange:m,modelData:u}=e,[h,g]=(0,a.useState)({routerSettings:{},selectedStrategy:null,enableTagFiltering:!1}),[x,p]=(0,a.useState)([]),[y,f]=(0,a.useState)([]),[j,b]=(0,a.useState)([]),[v,_]=(0,a.useState)([]),[N,w]=(0,a.useState)({}),[k,S]=(0,a.useState)({}),Z=(0,a.useRef)(!1),C=(0,a.useRef)(null),M=e=>e&&0!==e.length?e.map((e,t)=>{let[l,s]=Object.entries(e)[0];return{id:(t+1).toString(),primaryModel:l||null,fallbackModels:s||[]}}):[{id:"1",primaryModel:null,fallbackModels:[]}],T=e=>e.filter(e=>e.primaryModel&&e.fallbackModels.length>0).map(e=>({[e.primaryModel]:e.fallbackModels}));(0,a.useEffect)(()=>{let e=(null==c?void 0:c.router_settings)?JSON.stringify({routing_strategy:c.router_settings.routing_strategy,fallbacks:c.router_settings.fallbacks,enable_tag_filtering:c.router_settings.enable_tag_filtering}):null;if(Z.current&&e===C.current){Z.current=!1;return}if(Z.current&&e!==C.current&&(Z.current=!1),e!==C.current){if(C.current=e,null==c?void 0:c.router_settings){var t;let e=c.router_settings,{fallbacks:l,...s}=e;g({routerSettings:s,selectedStrategy:e.routing_strategy||null,enableTagFiltering:null!==(t=e.enable_tag_filtering)&&void 0!==t&&t});let a=e.fallbacks||[];p(a),f(M(a))}else g({routerSettings:{},selectedStrategy:null,enableTagFiltering:!1}),p([]),f([{id:"1",primaryModel:null,fallbackModels:[]}])}},[c]),(0,a.useEffect)(()=>{l&&(0,i.getRouterSettingsCall)(l).then(e=>{if(e.fields){let t={};e.fields.forEach(e=>{t[e.field_name]={ui_field_name:e.ui_field_name,field_description:e.field_description,options:e.options,link:e.link}}),w(t);let l=e.fields.find(e=>"routing_strategy"===e.field_name);(null==l?void 0:l.options)&&_(l.options),e.routing_strategy_descriptions&&S(e.routing_strategy_descriptions)}})},[l]),(0,a.useEffect)(()=>{l&&(async()=>{try{let e=await (0,d.p)(l);b(e)}catch(e){console.error("Error fetching model info for fallbacks:",e)}})()},[l]);let L=()=>{let e=new Set(["allowed_fails","cooldown_time","num_retries","timeout","retry_after"]),t=new Set(["model_group_alias","retry_policy"]),l=(l,s,a)=>{if(null==s)return a;let r=String(s).trim();if(""===r||"null"===r.toLowerCase())return null;if(e.has(l)){let e=Number(r);return Number.isNaN(e)?a:e}if(t.has(l)){if(""===r)return null;try{return JSON.parse(r)}catch(e){return a}}return"true"===r.toLowerCase()||"false"!==r.toLowerCase()&&r},s=Object.fromEntries(Object.entries({...h.routerSettings,enable_tag_filtering:h.enableTagFiltering,routing_strategy:h.selectedStrategy,fallbacks:x.length>0?x:null}).map(e=>{let[t,s]=e;if("routing_strategy_args"!==t&&"routing_strategy"!==t&&"enable_tag_filtering"!==t&&"fallbacks"!==t){let e=document.querySelector('input[name="'.concat(t,'"]'));if(e&&void 0!==e.value&&""!==e.value){let a=l(t,e.value,s);return[t,a]}}else if("routing_strategy"===t)return[t,h.selectedStrategy];else if("enable_tag_filtering"===t)return[t,h.enableTagFiltering];else if("fallbacks"===t)return[t,x.length>0?x:null];else if("routing_strategy_args"===t&&"latency-based-routing"===h.selectedStrategy){let e=document.querySelector('input[name="lowest_latency_buffer"]'),t=document.querySelector('input[name="ttl"]'),l={};return(null==e?void 0:e.value)&&(l.lowest_latency_buffer=Number(e.value)),(null==t?void 0:t.value)&&(l.ttl=Number(t.value)),["routing_strategy_args",Object.keys(l).length>0?l:null]}return[t,s]}).filter(e=>null!=e)),a=function(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return null==e||"object"==typeof e&&!Array.isArray(e)&&0===Object.keys(e).length||t&&("number"!=typeof e||Number.isNaN(e))?null:e};return{routing_strategy:a(s.routing_strategy),allowed_fails:a(s.allowed_fails,!0),cooldown_time:a(s.cooldown_time,!0),num_retries:a(s.num_retries,!0),timeout:a(s.timeout,!0),retry_after:a(s.retry_after,!0),fallbacks:x.length>0?x:null,context_window_fallbacks:a(s.context_window_fallbacks),retry_policy:a(s.retry_policy),model_group_alias:a(s.model_group_alias),enable_tag_filtering:h.enableTagFiltering,routing_strategy_args:a(s.routing_strategy_args)}};(0,a.useEffect)(()=>{if(!m)return;let e=setTimeout(()=>{Z.current=!0,m({router_settings:L()})},100);return()=>clearTimeout(e)},[h,x]);let F=Array.from(new Set(j.map(e=>e.model_group))).sort();return((0,a.useImperativeHandle)(t,()=>({getValue:()=>({router_settings:L()})})),l)?(0,s.jsx)("div",{className:"w-full",children:(0,s.jsxs)(r.v0,{className:"w-full",children:[(0,s.jsxs)(r.td,{variant:"line",defaultValue:"1",className:"px-8 pt-4",children:[(0,s.jsx)(r.OK,{value:"1",children:"Loadbalancing"}),(0,s.jsx)(r.OK,{value:"2",children:"Fallbacks"})]}),(0,s.jsxs)(r.nP,{className:"px-8 py-6",children:[(0,s.jsx)(r.x4,{children:(0,s.jsx)(n.Z,{value:h,onChange:g,routerFieldsMetadata:N,availableRoutingStrategies:v,routingStrategyDescriptions:k})}),(0,s.jsx)(r.x4,{children:(0,s.jsx)(o.$,{groups:y,onGroupsChange:e=>{f(e),p(T(e))},availableModels:F,maxFallbacks:5,maxGroups:5})})]})]})}):null});c.displayName="RouterSettingsAccordion",t.Z=c},71098:function(e,t,l){l.d(t,{ZP:function(){return et},wk:function(){return X},Nr:function(){return ee}});var s=l(57437),a=l(30280),r=l(39760),i=l(59872),n=l(15424),o=l(29827),d=l(87452),c=l(88829),m=l(72208),u=l(78489),h=l(49804),g=l(67101),x=l(84264),p=l(49566),y=l(96761),f=l(37592),j=l(10032),b=l(22116),v=l(99981),_=l(29967),N=l(5545),w=l(63709),k=l(4260),S=l(7310),Z=l.n(S),C=l(2265),M=l(29233),T=l(20347),L=l(82586),F=l(97434),P=l(65925),A=l(63610),E=l(62099),I=l(72885),V=l(95096),R=l(2597),O=l(65895),D=l(76364),K=l(84376),U=l(7765),q=l(46468),B=l(97492),G=l(68473),z=l(9114),J=l(19250),W=l(24199),H=l(97415);let Y=e=>{let t;if(!(t=!e||"object"!=typeof e||e instanceof Error?String(e):JSON.stringify(e)).includes("/key/generate")&&!t.includes("KeyManagementRoutes.KEY_GENERATE"))return"Error creating the key: ".concat(e);let l=t;try{if(!e||"object"!=typeof e||e instanceof Error){let e=t.match(/\{[\s\S]*\}/);if(e){let t=JSON.parse(e[0]),s=(null==t?void 0:t.error)||t;(null==s?void 0:s.message)&&(l=s.message)}}else{let t=(null==e?void 0:e.error)||e;(null==t?void 0:t.message)&&(l=t.message)}}catch(e){}return t.includes("team_member_permission_error")||l.includes("Team member does not have permissions")?"Team member does not have permission to generate key for this team. Ask your proxy admin to configure the team member permission settings.":"Error creating the key: ".concat(e)},{Option:$}=f.default,Q=e=>{let t=[];if(console.log("data:",JSON.stringify(e)),e)for(let l of e)l.metadata&&l.metadata.tags&&t.push(...l.metadata.tags);let l=Array.from(new Set(t)).map(e=>({value:e,label:e}));return console.log("uniqueTags:",l),l},X=async(e,t,l,s)=>{try{if(null===e||null===t)return[];if(null!==l){let a=(await (0,J.modelAvailableCall)(l,e,t,!0,s,!0)).data.map(e=>e.id);return console.log("available_model_names:",a),a}return[]}catch(e){return console.error("Error fetching user models:",e),[]}},ee=async(e,t,l,s)=>{try{if(null===e||null===t)return;if(null!==l){let a=(await (0,J.modelAvailableCall)(l,e,t)).data.map(e=>e.id);console.log("available_model_names:",a),s(a)}}catch(e){console.error("Error fetching user models:",e)}};var et=e=>{let{team:t,teams:l,data:S,addKey:et}=e,{accessToken:el,userId:es,userRole:ea,premiumUser:er}=(0,r.Z)(),ei=(0,o.NL)(),[en]=j.Z.useForm(),[eo,ed]=(0,C.useState)(!1),[ec,em]=(0,C.useState)(null),[eu,eh]=(0,C.useState)(null),[eg,ex]=(0,C.useState)([]),[ep,ey]=(0,C.useState)([]),[ef,ej]=(0,C.useState)("you"),[eb,ev]=(0,C.useState)(Q(S)),[e_,eN]=(0,C.useState)([]),[ew,ek]=(0,C.useState)([]),[eS,eZ]=(0,C.useState)([]),[eC,eM]=(0,C.useState)([]),[eT,eL]=(0,C.useState)(t),[eF,eP]=(0,C.useState)(!1),[eA,eE]=(0,C.useState)(null),[eI,eV]=(0,C.useState)({}),[eR,eO]=(0,C.useState)([]),[eD,eK]=(0,C.useState)(!1),[eU,eq]=(0,C.useState)([]),[eB,eG]=(0,C.useState)([]),[ez,eJ]=(0,C.useState)("llm_api"),[eW,eH]=(0,C.useState)({}),[eY,e$]=(0,C.useState)(!1),[eQ,eX]=(0,C.useState)("30d"),[e0,e4]=(0,C.useState)(null),[e1,e2]=(0,C.useState)(0),e5=()=>{ed(!1),en.resetFields(),eM([]),eG([]),eJ("llm_api"),eH({}),e$(!1),eX("30d"),e4(null),e2(e=>e+1)},e3=()=>{ed(!1),em(null),eL(null),en.resetFields(),eM([]),eG([]),eJ("llm_api"),eH({}),e$(!1),eX("30d"),e4(null),e2(e=>e+1)};(0,C.useEffect)(()=>{es&&ea&&el&&ee(es,ea,el,ex)},[el,es,ea]),(0,C.useEffect)(()=>{let e=async()=>{try{let e=(await (0,J.getPoliciesList)(el)).policies.map(e=>e.policy_name);ek(e)}catch(e){console.error("Failed to fetch policies:",e)}},t=async()=>{try{let e=await (0,J.getPromptsList)(el);eZ(e.prompts.map(e=>e.prompt_id))}catch(e){console.error("Failed to fetch prompts:",e)}};(async()=>{try{let e=(await (0,J.getGuardrailsList)(el)).guardrails.map(e=>e.guardrail_name);eN(e)}catch(e){console.error("Failed to fetch guardrails:",e)}})(),e(),t()},[el]),(0,C.useEffect)(()=>{(async()=>{try{if(el){let e=sessionStorage.getItem("possibleUserRoles");if(e)eV(JSON.parse(e));else{let e=await (0,J.getPossibleUserRoles)(el);sessionStorage.setItem("possibleUserRoles",JSON.stringify(e)),eV(e)}}}catch(e){console.error("Error fetching possible user roles:",e)}})()},[el]);let e7=ep.includes("no-default-models")&&!eT,e6=async e=>{try{var t,l,s,r,i,n,o;let d;let c=null!==(i=null==e?void 0:e.key_alias)&&void 0!==i?i:"",m=null!==(n=null==e?void 0:e.team_id)&&void 0!==n?n:null;if((null!==(o=null==S?void 0:S.filter(e=>e.team_id===m).map(e=>e.key_alias))&&void 0!==o?o:[]).includes(c))throw Error("Key alias ".concat(c," already exists for team with ID ").concat(m,", please provide another key alias"));z.Z.info("Making API Call"),ed(!0),"you"===ef&&(e.user_id=es);let u={};try{u=JSON.parse(e.metadata||"{}")}catch(e){console.error("Error parsing metadata:",e)}if("service_account"===ef&&(u.service_account_id=e.key_alias),eC.length>0&&(u={...u,logging:eC.filter(e=>e.callback_name)}),eB.length>0){let e=(0,F.Z3)(eB);u={...u,litellm_disabled_callbacks:e}}if(eY&&(e.auto_rotate=!0,e.rotation_interval=eQ),e.duration&&""!==e.duration.trim()||(e.duration=null),e.metadata=JSON.stringify(u),e.allowed_vector_store_ids&&e.allowed_vector_store_ids.length>0&&(e.object_permission={vector_stores:e.allowed_vector_store_ids},delete e.allowed_vector_store_ids),e.allowed_mcp_servers_and_groups&&((null===(t=e.allowed_mcp_servers_and_groups.servers)||void 0===t?void 0:t.length)>0||(null===(l=e.allowed_mcp_servers_and_groups.accessGroups)||void 0===l?void 0:l.length)>0)){e.object_permission||(e.object_permission={});let{servers:t,accessGroups:l}=e.allowed_mcp_servers_and_groups;t&&t.length>0&&(e.object_permission.mcp_servers=t),l&&l.length>0&&(e.object_permission.mcp_access_groups=l),delete e.allowed_mcp_servers_and_groups}let h=e.mcp_tool_permissions||{};if(Object.keys(h).length>0&&(e.object_permission||(e.object_permission={}),e.object_permission.mcp_tool_permissions=h),delete e.mcp_tool_permissions,e.allowed_mcp_access_groups&&e.allowed_mcp_access_groups.length>0&&(e.object_permission||(e.object_permission={}),e.object_permission.mcp_access_groups=e.allowed_mcp_access_groups,delete e.allowed_mcp_access_groups),e.allowed_agents_and_groups&&((null===(s=e.allowed_agents_and_groups.agents)||void 0===s?void 0:s.length)>0||(null===(r=e.allowed_agents_and_groups.accessGroups)||void 0===r?void 0:r.length)>0)){e.object_permission||(e.object_permission={});let{agents:t,accessGroups:l}=e.allowed_agents_and_groups;t&&t.length>0&&(e.object_permission.agents=t),l&&l.length>0&&(e.object_permission.agent_access_groups=l),delete e.allowed_agents_and_groups}Object.keys(eW).length>0&&(e.aliases=JSON.stringify(eW)),(null==e0?void 0:e0.router_settings)&&Object.values(e0.router_settings).some(e=>null!=e&&""!==e)&&(e.router_settings=e0.router_settings),d="service_account"===ef?await (0,J.keyCreateServiceAccountCall)(el,e):await (0,J.keyCreateCall)(el,es,e),console.log("key create Response:",d),et(d),ei.invalidateQueries({queryKey:a.Km.lists()}),em(d.key),eh(d.soft_budget),z.Z.success("Virtual Key Created"),en.resetFields(),localStorage.removeItem("userData"+es)}catch(t){console.log("error in create key:",t);let e=Y(t);z.Z.fromBackend(e)}};(0,C.useEffect)(()=>{if(es&&ea&&el){var e;X(es,ea,el,null!==(e=null==eT?void 0:eT.team_id)&&void 0!==e?e:null).then(e=>{var t;ey(Array.from(new Set([...null!==(t=null==eT?void 0:eT.models)&&void 0!==t?t:[],...e])))})}en.setFieldValue("models",[])},[eT,el,es,ea]);let e9=async e=>{if(!e){eO([]);return}eK(!0);try{let t=new URLSearchParams;if(t.append("user_email",e),null==el)return;let l=(await (0,J.userFilterUICall)(el,t)).map(e=>({label:"".concat(e.user_email," (").concat(e.user_id,")"),value:e.user_id,user:e}));eO(l)}catch(e){console.error("Error fetching users:",e),z.Z.fromBackend("Failed to search for users")}finally{eK(!1)}},e8=(0,C.useCallback)(Z()(e=>e9(e),300),[el]),te=(e,t)=>{let l=t.user;en.setFieldsValue({user_id:l.user_id})};return(0,s.jsxs)("div",{children:[ea&&T.LQ.includes(ea)&&(0,s.jsx)(u.Z,{className:"mx-auto",onClick:()=>ed(!0),children:"+ Create New Key"}),(0,s.jsx)(b.Z,{open:eo,width:1e3,footer:null,onOk:e5,onCancel:e3,children:(0,s.jsxs)(j.Z,{form:en,onFinish:e6,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,s.jsxs)("div",{className:"mb-8",children:[(0,s.jsx)(y.Z,{className:"mb-4",children:"Key Ownership"}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Owned By"," ",(0,s.jsx)(v.Z,{title:"Select who will own this Virtual Key",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),className:"mb-4",children:(0,s.jsxs)(_.ZP.Group,{onChange:e=>ej(e.target.value),value:ef,children:[(0,s.jsx)(_.ZP,{value:"you",children:"You"}),(0,s.jsx)(_.ZP,{value:"service_account",children:"Service Account"}),"Admin"===ea&&(0,s.jsx)(_.ZP,{value:"another_user",children:"Another User"})]})}),"another_user"===ef&&(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["User ID"," ",(0,s.jsx)(v.Z,{title:"The user who will own this key and be responsible for its usage",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"user_id",className:"mt-4",rules:[{required:"another_user"===ef,message:"Please input the user ID of the user you are assigning the key to"}],children:(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{style:{display:"flex",marginBottom:"8px"},children:[(0,s.jsx)(f.default,{showSearch:!0,placeholder:"Type email to search for users",filterOption:!1,onSearch:e=>{e8(e)},onSelect:(e,t)=>te(e,t),options:eR,loading:eD,allowClear:!0,style:{width:"100%"},notFoundContent:eD?"Searching...":"No users found"}),(0,s.jsx)(N.ZP,{onClick:()=>eP(!0),style:{marginLeft:"8px"},children:"Create User"})]}),(0,s.jsx)("div",{className:"text-xs text-gray-500",children:"Search by email to find users"})]})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Team"," ",(0,s.jsx)(v.Z,{title:"The team this key belongs to, which determines available models and budget limits",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"team_id",initialValue:t?t.team_id:null,className:"mt-4",rules:[{required:"service_account"===ef,message:"Please select a team for the service account"}],help:"service_account"===ef?"required":"",children:(0,s.jsx)(K.Z,{teams:l,onChange:e=>{eL((null==l?void 0:l.find(t=>t.team_id===e))||null)}})})]}),e7&&(0,s.jsx)("div",{className:"mb-8 p-4 bg-blue-50 border border-blue-200 rounded-md",children:(0,s.jsx)(x.Z,{className:"text-blue-800 text-sm",children:"Please select a team to continue configuring your Virtual Key. If you do not see any teams, please contact your Proxy Admin to either provide you with access to models or to add you to a team."})}),!e7&&(0,s.jsxs)("div",{className:"mb-8",children:[(0,s.jsx)(y.Z,{className:"mb-4",children:"Key Details"}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["you"===ef||"another_user"===ef?"Key Name":"Service Account ID"," ",(0,s.jsx)(v.Z,{title:"you"===ef||"another_user"===ef?"A descriptive name to identify this key":"Unique identifier for this service account",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"key_alias",rules:[{required:!0,message:"Please input a ".concat("you"===ef?"key name":"service account ID")}],help:"required",children:(0,s.jsx)(p.Z,{placeholder:""})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Models"," ",(0,s.jsx)(v.Z,{title:"Select which models this key can access. Choose 'All Team Models' to grant access to all models available to the team",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"models",rules:"management"===ez||"read_only"===ez?[]:[{required:!0,message:"Please select a model"}],help:"management"===ez||"read_only"===ez?"Models field is disabled for this key type":"required",className:"mt-4",children:(0,s.jsxs)(f.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},disabled:"management"===ez||"read_only"===ez,onChange:e=>{e.includes("all-team-models")&&en.setFieldsValue({models:["all-team-models"]})},children:[(0,s.jsx)($,{value:"all-team-models",children:"All Team Models"},"all-team-models"),ep.map(e=>(0,s.jsx)($,{value:e,children:(0,q.W0)(e)},e))]})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Key Type"," ",(0,s.jsx)(v.Z,{title:"Select the type of key to determine what routes and operations this key can access",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"key_type",initialValue:"llm_api",className:"mt-4",children:(0,s.jsxs)(f.default,{defaultValue:"llm_api",placeholder:"Select key type",style:{width:"100%"},optionLabelProp:"label",onChange:e=>{eJ(e),("management"===e||"read_only"===e)&&en.setFieldsValue({models:[]})},children:[(0,s.jsx)($,{value:"default",label:"Default",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Default"}),(0,s.jsx)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:"Can call LLM API + Management routes"})]})}),(0,s.jsx)($,{value:"llm_api",label:"LLM API",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"LLM API"}),(0,s.jsx)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:"Can call only LLM API routes (chat/completions, embeddings, etc.)"})]})}),(0,s.jsx)($,{value:"management",label:"Management",children:(0,s.jsxs)("div",{style:{padding:"4px 0"},children:[(0,s.jsx)("div",{style:{fontWeight:500},children:"Management"}),(0,s.jsx)("div",{style:{fontSize:"11px",color:"#6b7280",marginTop:"2px"},children:"Can call only management routes (user/team/key management)"})]})})]})})]}),!e7&&(0,s.jsx)("div",{className:"mb-8",children:(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)(y.Z,{className:"m-0",children:"Optional Settings"})}),(0,s.jsxs)(c.Z,{children:[(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Max Budget (USD)"," ",(0,s.jsx)(v.Z,{title:"Maximum amount in USD this key can spend. When reached, the key will be blocked from making further requests",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"max_budget",help:"Budget cannot exceed team max budget: $".concat((null==t?void 0:t.max_budget)!==null&&(null==t?void 0:t.max_budget)!==void 0?null==t?void 0:t.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.max_budget&&l>t.max_budget)throw Error("Budget cannot exceed team max budget: $".concat((0,i.pw)(t.max_budget,4)))}}],children:(0,s.jsx)(W.Z,{step:.01,precision:2,width:200})}),(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Reset Budget"," ",(0,s.jsx)(v.Z,{title:"How often the budget should reset. For example, setting 'daily' will reset the budget every 24 hours",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"budget_duration",help:"Team Reset Budget: ".concat((null==t?void 0:t.budget_duration)!==null&&(null==t?void 0:t.budget_duration)!==void 0?null==t?void 0:t.budget_duration:"None"),children:(0,s.jsx)(P.Z,{onChange:e=>en.setFieldValue("budget_duration",e)})}),(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Tokens per minute Limit (TPM)"," ",(0,s.jsx)(v.Z,{title:"Maximum number of tokens this key can process per minute. Helps control usage and costs",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"tpm_limit",help:"TPM cannot exceed team TPM limit: ".concat((null==t?void 0:t.tpm_limit)!==null&&(null==t?void 0:t.tpm_limit)!==void 0?null==t?void 0:t.tpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.tpm_limit&&l>t.tpm_limit)throw Error("TPM limit cannot exceed team TPM limit: ".concat(t.tpm_limit))}}],children:(0,s.jsx)(W.Z,{step:1,width:400})}),(0,s.jsx)(O.Z,{type:"tpm",name:"tpm_limit_type",className:"mt-4",initialValue:null,form:en,showDetailedDescriptions:!0}),(0,s.jsx)(j.Z.Item,{className:"mt-4",label:(0,s.jsxs)("span",{children:["Requests per minute Limit (RPM)"," ",(0,s.jsx)(v.Z,{title:"Maximum number of API requests this key can make per minute. Helps prevent abuse and manage load",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"rpm_limit",help:"RPM cannot exceed team RPM limit: ".concat((null==t?void 0:t.rpm_limit)!==null&&(null==t?void 0:t.rpm_limit)!==void 0?null==t?void 0:t.rpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.rpm_limit&&l>t.rpm_limit)throw Error("RPM limit cannot exceed team RPM limit: ".concat(t.rpm_limit))}}],children:(0,s.jsx)(W.Z,{step:1,width:400})}),(0,s.jsx)(O.Z,{type:"rpm",name:"rpm_limit_type",className:"mt-4",initialValue:null,form:en,showDetailedDescriptions:!0}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Guardrails"," ",(0,s.jsx)(v.Z,{title:"Apply safety guardrails to this key to filter content or enforce policies",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"guardrails",className:"mt-4",help:er?"Select existing guardrails or enter new ones":"Premium feature - Upgrade to set guardrails by key",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},disabled:!er,placeholder:er?"Select or enter guardrails":"Premium feature - Upgrade to set guardrails by key",options:e_.map(e=>({value:e,label:e}))})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Disable Global Guardrails"," ",(0,s.jsx)(v.Z,{title:"When enabled, this key will bypass any guardrails configured to run on every request (global guardrails)",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"disable_global_guardrails",className:"mt-4",valuePropName:"checked",help:er?"Bypass global guardrails for this key":"Premium feature - Upgrade to disable global guardrails by key",children:(0,s.jsx)(w.Z,{disabled:!er,checkedChildren:"Yes",unCheckedChildren:"No"})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Policies"," ",(0,s.jsx)(v.Z,{title:"Apply policies to this key to control guardrails and other settings",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/guardrail_policies",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"policies",className:"mt-4",help:er?"Select existing policies or enter new ones":"Premium feature - Upgrade to set policies by key",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},disabled:!er,placeholder:er?"Select or enter policies":"Premium feature - Upgrade to set policies by key",options:ew.map(e=>({value:e,label:e}))})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Prompts"," ",(0,s.jsx)(v.Z,{title:"Allow this key to use specific prompt templates",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/prompt_management",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"prompts",className:"mt-4",help:er?"Select existing prompts or enter new ones":"Premium feature - Upgrade to set prompts by key",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},disabled:!er,placeholder:er?"Select or enter prompts":"Premium feature - Upgrade to set prompts by key",options:eS.map(e=>({value:e,label:e}))})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed Pass Through Routes"," ",(0,s.jsx)(v.Z,{title:"Allow this key to use specific pass through routes",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/pass_through",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})})]}),name:"allowed_passthrough_routes",className:"mt-4",help:er?"Select existing pass through routes or enter new ones":"Premium feature - Upgrade to set pass through routes by key",children:(0,s.jsx)(V.Z,{onChange:e=>en.setFieldValue("allowed_passthrough_routes",e),value:en.getFieldValue("allowed_passthrough_routes"),accessToken:el,placeholder:er?"Select or enter pass through routes":"Premium feature - Upgrade to set pass through routes by key",disabled:!er,teamId:eT?eT.team_id:null})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed Vector Stores"," ",(0,s.jsx)(v.Z,{title:"Select which vector stores this key can access. If none selected, the key will have access to all available vector stores",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"allowed_vector_store_ids",className:"mt-4",help:"Select vector stores this key can access. Leave empty for access to all vector stores",children:(0,s.jsx)(H.Z,{onChange:e=>en.setFieldValue("allowed_vector_store_ids",e),value:en.getFieldValue("allowed_vector_store_ids"),accessToken:el,placeholder:"Select vector stores (optional)"})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Metadata"," ",(0,s.jsx)(v.Z,{title:"JSON object with additional information about this key. Used for tracking or custom logic",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"metadata",className:"mt-4",children:(0,s.jsx)(k.default.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Tags"," ",(0,s.jsx)(v.Z,{title:"Tags for tracking spend and/or doing tag-based routing. Used for analytics and filtering",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"tags",className:"mt-4",help:"Tags for tracking spend and/or doing tag-based routing.",children:(0,s.jsx)(f.default,{mode:"tags",style:{width:"100%"},placeholder:"Enter tags",tokenSeparators:[","],options:eb})}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)("b",{children:"MCP Settings"})}),(0,s.jsxs)(c.Z,{children:[(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed MCP Servers"," ",(0,s.jsx)(v.Z,{title:"Select which MCP servers or access groups this key can access",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"allowed_mcp_servers_and_groups",help:"Select MCP servers or access groups this key can access",children:(0,s.jsx)(B.Z,{onChange:e=>en.setFieldValue("allowed_mcp_servers_and_groups",e),value:en.getFieldValue("allowed_mcp_servers_and_groups"),accessToken:el,placeholder:"Select MCP servers or access groups (optional)"})}),(0,s.jsx)(j.Z.Item,{name:"mcp_tool_permissions",initialValue:{},hidden:!0,children:(0,s.jsx)(k.default,{type:"hidden"})}),(0,s.jsx)(j.Z.Item,{noStyle:!0,shouldUpdate:(e,t)=>e.allowed_mcp_servers_and_groups!==t.allowed_mcp_servers_and_groups||e.mcp_tool_permissions!==t.mcp_tool_permissions,children:()=>{var e;return(0,s.jsx)("div",{className:"mt-6",children:(0,s.jsx)(G.Z,{accessToken:el,selectedServers:(null===(e=en.getFieldValue("allowed_mcp_servers_and_groups"))||void 0===e?void 0:e.servers)||[],toolPermissions:en.getFieldValue("mcp_tool_permissions")||{},onChange:e=>en.setFieldsValue({mcp_tool_permissions:e})})})}})]})]}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)("b",{children:"Agent Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)(j.Z.Item,{label:(0,s.jsxs)("span",{children:["Allowed Agents"," ",(0,s.jsx)(v.Z,{title:"Select which agents or access groups this key can access",children:(0,s.jsx)(n.Z,{style:{marginLeft:"4px"}})})]}),name:"allowed_agents_and_groups",help:"Select agents or access groups this key can access",children:(0,s.jsx)(L.Z,{onChange:e=>en.setFieldValue("allowed_agents_and_groups",e),value:en.getFieldValue("allowed_agents_and_groups"),accessToken:el,placeholder:"Select agents or access groups (optional)"})})})]}),er?(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)("b",{children:"Logging Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(R.Z,{value:eC,onChange:eM,premiumUser:!0,disabledCallbacks:eB,onDisabledCallbacksChange:eG})})})]}):(0,s.jsx)(v.Z,{title:(0,s.jsxs)("span",{children:["Key-level logging settings is an enterprise feature, get in touch -",(0,s.jsx)("a",{href:"https://www.litellm.ai/enterprise",target:"_blank",children:"https://www.litellm.ai/enterprise"})]}),placement:"top",children:(0,s.jsxs)("div",{style:{position:"relative"},children:[(0,s.jsx)("div",{style:{opacity:.5},children:(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)("b",{children:"Logging Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(R.Z,{value:eC,onChange:eM,premiumUser:!1,disabledCallbacks:eB,onDisabledCallbacksChange:eG})})})]})}),(0,s.jsx)("div",{style:{position:"absolute",inset:0,cursor:"not-allowed"}})]})}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)("b",{children:"Router Settings"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4 w-full",children:(0,s.jsx)(D.Z,{accessToken:el||"",value:e0||void 0,onChange:e4,modelData:eg.length>0?{data:eg.map(e=>({model_name:e}))}:void 0},e1)})})]},"router-settings-accordion-".concat(e1)),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)("b",{children:"Model Aliases"})}),(0,s.jsx)(c.Z,{children:(0,s.jsxs)("div",{className:"mt-4",children:[(0,s.jsx)(x.Z,{className:"text-sm text-gray-600 mb-4",children:"Create custom aliases for models that can be used in API calls. This allows you to create shortcuts for specific models."}),(0,s.jsx)(I.Z,{accessToken:el,initialModelAliases:eW,onAliasUpdate:eH,showExampleConfig:!1})]})})]}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsx)("b",{children:"Key Lifecycle"})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(E.Z,{form:en,autoRotationEnabled:eY,onAutoRotationChange:e$,rotationInterval:eQ,onRotationIntervalChange:eX,isCreateMode:!0})})}),(0,s.jsx)(j.Z.Item,{name:"duration",hidden:!0,initialValue:null,children:(0,s.jsx)(k.default,{})})]}),(0,s.jsxs)(d.Z,{className:"mt-4 mb-4",children:[(0,s.jsx)(m.Z,{children:(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("b",{children:"Advanced Settings"}),(0,s.jsx)(v.Z,{title:(0,s.jsxs)("span",{children:["Learn more about advanced settings in our"," ",(0,s.jsx)("a",{href:J.proxyBaseUrl?"".concat(J.proxyBaseUrl,"/#/key%20management/generate_key_fn_key_generate_post"):"/#/key%20management/generate_key_fn_key_generate_post",target:"_blank",rel:"noopener noreferrer",className:"text-blue-400 hover:text-blue-300",children:"documentation"})]}),children:(0,s.jsx)(n.Z,{className:"text-gray-400 hover:text-gray-300 cursor-help"})})]})}),(0,s.jsx)(c.Z,{children:(0,s.jsx)(A.Z,{schemaComponent:"GenerateKeyRequest",form:en,excludedFields:["key_alias","team_id","models","duration","metadata","tags","guardrails","max_budget","budget_duration","tpm_limit","rpm_limit"]})})]})]})]})}),(0,s.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,s.jsx)(N.ZP,{htmlType:"submit",disabled:e7,style:{opacity:e7?.5:1},children:"Create Key"})})]})}),eF&&(0,s.jsx)(b.Z,{title:"Create New User",visible:eF,onCancel:()=>eP(!1),footer:null,width:800,children:(0,s.jsx)(U.Z,{userID:es,accessToken:el,teams:l,possibleUIRoles:eI,onUserCreated:e=>{eE(e),en.setFieldsValue({user_id:e}),eP(!1)},isEmbedded:!0})}),ec&&(0,s.jsx)(b.Z,{visible:eo,onOk:e5,onCancel:e3,footer:null,children:(0,s.jsxs)(g.Z,{numItems:1,className:"gap-2 w-full",children:[(0,s.jsx)(y.Z,{children:"Save your Key"}),(0,s.jsx)(h.Z,{numColSpan:1,children:(0,s.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons,"," ",(0,s.jsx)("b",{children:"you will not be able to view it again"})," through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,s.jsx)(h.Z,{numColSpan:1,children:null!=ec?(0,s.jsxs)("div",{children:[(0,s.jsx)(x.Z,{className:"mt-3",children:"Virtual Key:"}),(0,s.jsx)("div",{style:{background:"#f8f8f8",padding:"10px",borderRadius:"5px",marginBottom:"10px"},children:(0,s.jsx)("pre",{style:{wordWrap:"break-word",whiteSpace:"normal"},children:ec})}),(0,s.jsx)(M.CopyToClipboard,{text:ec,onCopy:()=>{z.Z.success("Virtual Key copied to clipboard")},children:(0,s.jsx)(u.Z,{className:"mt-3",children:"Copy Virtual Key"})})]}):(0,s.jsx)(x.Z,{children:"Key being created, this might take 30s"})})]})})]})}},56334:function(e,t,l){l.d(t,{Z:function(){return u}});var s=l(57437);l(2265);var a=l(31283);let r={ttl:3600,lowest_latency_buffer:0};var i=e=>{let{routingStrategyArgs:t}=e,l={ttl:"Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).",lowest_latency_buffer:"Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency)."};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"max-w-3xl",children:[(0,s.jsx)("h3",{className:"text-sm font-medium text-gray-900",children:"Latency-Based Configuration"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Fine-tune latency-based routing behavior"})]}),(0,s.jsx)("div",{className:"grid grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3",children:Object.entries(t||r).map(e=>{let[t,r]=e;return(0,s.jsx)("div",{className:"space-y-2",children:(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:t.replace(/_/g," ")}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-0.5 mb-2",children:l[t]||""}),(0,s.jsx)(a.o,{name:t,defaultValue:"object"==typeof r?JSON.stringify(r,null,2):null==r?void 0:r.toString(),className:"font-mono text-sm w-full"})]})},t)})})]}),(0,s.jsx)("div",{className:"border-t border-gray-200"})]})},n=e=>{let{routerSettings:t,routerFieldsMetadata:l}=e;return(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"max-w-3xl",children:[(0,s.jsx)("h3",{className:"text-sm font-medium text-gray-900",children:"Reliability & Retries"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Configure retry logic and failure handling"})]}),(0,s.jsx)("div",{className:"grid grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3",children:Object.entries(t).filter(e=>{let[t,l]=e;return"fallbacks"!=t&&"context_window_fallbacks"!=t&&"routing_strategy_args"!=t&&"routing_strategy"!=t&&"enable_tag_filtering"!=t}).map(e=>{var t,r;let[i,n]=e;return(0,s.jsx)("div",{className:"space-y-2",children:(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:(null===(t=l[i])||void 0===t?void 0:t.ui_field_name)||i}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-0.5 mb-2",children:(null===(r=l[i])||void 0===r?void 0:r.field_description)||""}),(0,s.jsx)(a.o,{name:i,defaultValue:null==n||"null"===n?"":"object"==typeof n?JSON.stringify(n,null,2):(null==n?void 0:n.toString())||"",placeholder:"—",className:"font-mono text-sm w-full"})]})},i)})})]})},o=l(37592),d=e=>{var t,l;let{selectedStrategy:a,availableStrategies:r,routingStrategyDescriptions:i,routerFieldsMetadata:n,onStrategyChange:d}=e;return(0,s.jsxs)("div",{className:"space-y-2 max-w-3xl",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:(null===(t=n.routing_strategy)||void 0===t?void 0:t.ui_field_name)||"Routing Strategy"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-0.5 mb-2",children:(null===(l=n.routing_strategy)||void 0===l?void 0:l.field_description)||""})]}),(0,s.jsx)("div",{className:"routing-strategy-select max-w-3xl",children:(0,s.jsx)(o.default,{value:a,onChange:d,style:{width:"100%"},size:"large",children:r.map(e=>(0,s.jsx)(o.default.Option,{value:e,label:e,children:(0,s.jsxs)("div",{className:"flex flex-col gap-0.5 py-1",children:[(0,s.jsx)("span",{className:"font-mono text-sm font-medium",children:e}),i[e]&&(0,s.jsx)("span",{className:"text-xs text-gray-500 font-normal",children:i[e]})]})},e))})})]})},c=l(59341),m=e=>{var t,l,a;let{enabled:r,routerFieldsMetadata:i,onToggle:n}=e;return(0,s.jsx)("div",{className:"space-y-3 max-w-3xl",children:(0,s.jsxs)("div",{className:"flex items-start justify-between",children:[(0,s.jsxs)("div",{className:"flex-1",children:[(0,s.jsx)("label",{className:"text-xs font-medium text-gray-700 uppercase tracking-wide",children:(null===(t=i.enable_tag_filtering)||void 0===t?void 0:t.ui_field_name)||"Enable Tag Filtering"}),(0,s.jsxs)("p",{className:"text-xs text-gray-500 mt-0.5",children:[(null===(l=i.enable_tag_filtering)||void 0===l?void 0:l.field_description)||"",(null===(a=i.enable_tag_filtering)||void 0===a?void 0:a.link)&&(0,s.jsxs)(s.Fragment,{children:[" ",(0,s.jsx)("a",{href:i.enable_tag_filtering.link,target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:text-blue-800 underline",children:"Learn more"})]})]})]}),(0,s.jsx)(c.Z,{checked:r,onChange:n,className:"ml-4"})]})})},u=e=>{let{value:t,onChange:l,routerFieldsMetadata:a,availableRoutingStrategies:r,routingStrategyDescriptions:o}=e;return(0,s.jsxs)("div",{className:"w-full space-y-8 py-2",children:[(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"max-w-3xl",children:[(0,s.jsx)("h3",{className:"text-sm font-medium text-gray-900",children:"Routing Settings"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:"Configure how requests are routed to deployments"})]}),r.length>0&&(0,s.jsx)(d,{selectedStrategy:t.selectedStrategy||t.routerSettings.routing_strategy||null,availableStrategies:r,routingStrategyDescriptions:o,routerFieldsMetadata:a,onStrategyChange:e=>{l({...t,selectedStrategy:e})}}),(0,s.jsx)(m,{enabled:t.enableTagFiltering,routerFieldsMetadata:a,onToggle:e=>{l({...t,enableTagFiltering:e})}})]}),(0,s.jsx)("div",{className:"border-t border-gray-200"}),"latency-based-routing"===t.selectedStrategy&&(0,s.jsx)(i,{routingStrategyArgs:t.routerSettings.routing_strategy_args}),(0,s.jsx)(n,{routerSettings:t.routerSettings,routerFieldsMetadata:a})]})}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1108-43b967097e41bd10.js b/litellm/proxy/_experimental/out/_next/static/chunks/1108-8b678b0704cb239b.js similarity index 98% rename from litellm/proxy/_experimental/out/_next/static/chunks/1108-43b967097e41bd10.js rename to litellm/proxy/_experimental/out/_next/static/chunks/1108-8b678b0704cb239b.js index 614c574071e..89c5291477d 100644 --- a/litellm/proxy/_experimental/out/_next/static/chunks/1108-43b967097e41bd10.js +++ b/litellm/proxy/_experimental/out/_next/static/chunks/1108-8b678b0704cb239b.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1108],{40278:function(t,e,r){"use strict";r.d(e,{Z:function(){return S}});var n=r(5853),o=r(7084),i=r(26898),a=r(13241),u=r(1153),c=r(2265),l=r(47625),s=r(93765),f=r(31699),p=r(97059),h=r(62994),d=r(25311),y=(0,s.z)({chartName:"BarChart",GraphicalChild:f.$,defaultTooltipEventType:"axis",validateTooltipEventTypes:["axis","item"],axisComponents:[{axisType:"xAxis",AxisComp:p.K},{axisType:"yAxis",AxisComp:h.B}],formatAxisMap:d.t9}),v=r(56940),m=r(26680),b=r(8147),g=r(22190),x=r(65278),w=r(98593),O=r(92666),j=r(32644);let S=c.forwardRef((t,e)=>{let{data:r=[],categories:s=[],index:d,colors:S=i.s,valueFormatter:P=u.Cj,layout:E="horizontal",stack:k=!1,relative:A=!1,startEndOnly:M=!1,animationDuration:_=900,showAnimation:T=!1,showXAxis:C=!0,showYAxis:N=!0,yAxisWidth:D=56,intervalType:I="equidistantPreserveStart",showTooltip:L=!0,showLegend:B=!0,showGridLines:R=!0,autoMinValue:z=!1,minValue:U,maxValue:F,allowDecimals:$=!0,noDataText:q,onValueChange:Z,enableLegendSlider:W=!1,customTooltip:Y,rotateLabelX:H,barCategoryGap:X,tickGap:G=5,xAxisLabel:V,yAxisLabel:K,className:Q,padding:J=C||N?{left:20,right:20}:{left:0,right:0}}=t,tt=(0,n._T)(t,["data","categories","index","colors","valueFormatter","layout","stack","relative","startEndOnly","animationDuration","showAnimation","showXAxis","showYAxis","yAxisWidth","intervalType","showTooltip","showLegend","showGridLines","autoMinValue","minValue","maxValue","allowDecimals","noDataText","onValueChange","enableLegendSlider","customTooltip","rotateLabelX","barCategoryGap","tickGap","xAxisLabel","yAxisLabel","className","padding"]),[te,tr]=(0,c.useState)(60),tn=(0,j.me)(s,S),[to,ti]=c.useState(void 0),[ta,tu]=(0,c.useState)(void 0),tc=!!Z;function tl(t,e,r){var n,o,i,a;r.stopPropagation(),Z&&((0,j.vZ)(to,Object.assign(Object.assign({},t.payload),{value:t.value}))?(tu(void 0),ti(void 0),null==Z||Z(null)):(tu(null===(o=null===(n=t.tooltipPayload)||void 0===n?void 0:n[0])||void 0===o?void 0:o.dataKey),ti(Object.assign(Object.assign({},t.payload),{value:t.value})),null==Z||Z(Object.assign({eventType:"bar",categoryClicked:null===(a=null===(i=t.tooltipPayload)||void 0===i?void 0:i[0])||void 0===a?void 0:a.dataKey},t.payload))))}let ts=(0,j.i4)(z,U,F);return c.createElement("div",Object.assign({ref:e,className:(0,a.q)("w-full h-80",Q)},tt),c.createElement(l.h,{className:"h-full w-full"},(null==r?void 0:r.length)?c.createElement(y,{barCategoryGap:X,data:r,stackOffset:k?"sign":A?"expand":"none",layout:"vertical"===E?"vertical":"horizontal",onClick:tc&&(ta||to)?()=>{ti(void 0),tu(void 0),null==Z||Z(null)}:void 0,margin:{bottom:V?30:void 0,left:K?20:void 0,right:K?5:void 0,top:5}},R?c.createElement(v.q,{className:(0,a.q)("stroke-1","stroke-tremor-border","dark:stroke-dark-tremor-border"),horizontal:"vertical"!==E,vertical:"vertical"===E}):null,"vertical"!==E?c.createElement(p.K,{padding:J,hide:!C,dataKey:d,interval:M?"preserveStartEnd":I,tick:{transform:"translate(0, 6)"},ticks:M?[r[0][d],r[r.length-1][d]]:void 0,fill:"",stroke:"",className:(0,a.q)("mt-4 text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content"),tickLine:!1,axisLine:!1,angle:null==H?void 0:H.angle,dy:null==H?void 0:H.verticalShift,height:null==H?void 0:H.xAxisHeight,minTickGap:G},V&&c.createElement(m._,{position:"insideBottom",offset:-20,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},V)):c.createElement(p.K,{hide:!C,type:"number",tick:{transform:"translate(-3, 0)"},domain:ts,fill:"",stroke:"",className:(0,a.q)("text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content"),tickLine:!1,axisLine:!1,tickFormatter:P,minTickGap:G,allowDecimals:$,angle:null==H?void 0:H.angle,dy:null==H?void 0:H.verticalShift,height:null==H?void 0:H.xAxisHeight},V&&c.createElement(m._,{position:"insideBottom",offset:-20,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},V)),"vertical"!==E?c.createElement(h.B,{width:D,hide:!N,axisLine:!1,tickLine:!1,type:"number",domain:ts,tick:{transform:"translate(-3, 0)"},fill:"",stroke:"",className:(0,a.q)("text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content"),tickFormatter:A?t=>"".concat((100*t).toString()," %"):P,allowDecimals:$},K&&c.createElement(m._,{position:"insideLeft",style:{textAnchor:"middle"},angle:-90,offset:-15,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},K)):c.createElement(h.B,{width:D,hide:!N,dataKey:d,axisLine:!1,tickLine:!1,ticks:M?[r[0][d],r[r.length-1][d]]:void 0,type:"category",interval:"preserveStartEnd",tick:{transform:"translate(0, 6)"},fill:"",stroke:"",className:(0,a.q)("text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content")},K&&c.createElement(m._,{position:"insideLeft",style:{textAnchor:"middle"},angle:-90,offset:-15,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},K)),c.createElement(b.u,{wrapperStyle:{outline:"none"},isAnimationActive:!1,cursor:{fill:"#d1d5db",opacity:"0.15"},content:L?t=>{let{active:e,payload:r,label:n}=t;return Y?c.createElement(Y,{payload:null==r?void 0:r.map(t=>{var e;return Object.assign(Object.assign({},t),{color:null!==(e=tn.get(t.dataKey))&&void 0!==e?e:o.fr.Gray})}),active:e,label:n}):c.createElement(w.ZP,{active:e,payload:r,label:n,valueFormatter:P,categoryColors:tn})}:c.createElement(c.Fragment,null),position:{y:0}}),B?c.createElement(g.D,{verticalAlign:"top",height:te,content:t=>{let{payload:e}=t;return(0,x.Z)({payload:e},tn,tr,ta,tc?t=>{tc&&(t!==ta||to?(tu(t),null==Z||Z({eventType:"category",categoryClicked:t})):(tu(void 0),null==Z||Z(null)),ti(void 0))}:void 0,W)}}):null,s.map(t=>{var e;return c.createElement(f.$,{className:(0,a.q)((0,u.bM)(null!==(e=tn.get(t))&&void 0!==e?e:o.fr.Gray,i.K.background).fillColor,Z?"cursor-pointer":""),key:t,name:t,type:"linear",stackId:k||A?"a":void 0,dataKey:t,fill:"",isAnimationActive:T,animationDuration:_,shape:t=>((t,e,r,n)=>{let{fillOpacity:o,name:i,payload:a,value:u}=t,{x:l,width:s,y:f,height:p}=t;return"horizontal"===n&&p<0?(f+=p,p=Math.abs(p)):"vertical"===n&&s<0&&(l+=s,s=Math.abs(s)),c.createElement("rect",{x:l,y:f,width:s,height:p,opacity:e||r&&r!==i?(0,j.vZ)(e,Object.assign(Object.assign({},a),{value:u}))?o:.3:o})})(t,to,ta,E),onClick:tl})})):c.createElement(O.Z,{noDataText:q})))});S.displayName="BarChart"},65278:function(t,e,r){"use strict";r.d(e,{Z:function(){return y}});var n=r(2265);let o=t=>{n.useEffect(()=>{let e=()=>{t()};return e(),window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[t])};var i=r(5853),a=r(26898),u=r(13241),c=r(1153);let l=t=>{var e=(0,i._T)(t,[]);return n.createElement("svg",Object.assign({},e,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"}),n.createElement("path",{d:"M8 12L14 6V18L8 12Z"}))},s=t=>{var e=(0,i._T)(t,[]);return n.createElement("svg",Object.assign({},e,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"}),n.createElement("path",{d:"M16 12L10 18V6L16 12Z"}))},f=(0,c.fn)("Legend"),p=t=>{let{name:e,color:r,onClick:o,activeLegend:i}=t,l=!!o;return n.createElement("li",{className:(0,u.q)(f("legendItem"),"group inline-flex items-center px-2 py-0.5 rounded-tremor-small transition whitespace-nowrap",l?"cursor-pointer":"cursor-default","text-tremor-content",l?"hover:bg-tremor-background-subtle":"","dark:text-dark-tremor-content",l?"dark:hover:bg-dark-tremor-background-subtle":""),onClick:t=>{t.stopPropagation(),null==o||o(e,r)}},n.createElement("svg",{className:(0,u.q)("flex-none h-2 w-2 mr-1.5",(0,c.bM)(r,a.K.text).textColor,i&&i!==e?"opacity-40":"opacity-100"),fill:"currentColor",viewBox:"0 0 8 8"},n.createElement("circle",{cx:4,cy:4,r:4})),n.createElement("p",{className:(0,u.q)("whitespace-nowrap truncate text-tremor-default","text-tremor-content",l?"group-hover:text-tremor-content-emphasis":"","dark:text-dark-tremor-content",i&&i!==e?"opacity-40":"opacity-100",l?"dark:group-hover:text-dark-tremor-content-emphasis":"")},e))},h=t=>{let{icon:e,onClick:r,disabled:o}=t,[i,a]=n.useState(!1),c=n.useRef(null);return n.useEffect(()=>(i?c.current=setInterval(()=>{null==r||r()},300):clearInterval(c.current),()=>clearInterval(c.current)),[i,r]),(0,n.useEffect)(()=>{o&&(clearInterval(c.current),a(!1))},[o]),n.createElement("button",{type:"button",className:(0,u.q)(f("legendSliderButton"),"w-5 group inline-flex items-center truncate rounded-tremor-small transition",o?"cursor-not-allowed":"cursor-pointer",o?"text-tremor-content-subtle":"text-tremor-content hover:text-tremor-content-emphasis hover:bg-tremor-background-subtle",o?"dark:text-dark-tremor-subtle":"dark:text-dark-tremor dark:hover:text-tremor-content-emphasis dark:hover:bg-dark-tremor-background-subtle"),disabled:o,onClick:t=>{t.stopPropagation(),null==r||r()},onMouseDown:t=>{t.stopPropagation(),a(!0)},onMouseUp:t=>{t.stopPropagation(),a(!1)}},n.createElement(e,{className:"w-full"}))},d=n.forwardRef((t,e)=>{let{categories:r,colors:o=a.s,className:c,onClickLegendItem:d,activeLegend:y,enableLegendSlider:v=!1}=t,m=(0,i._T)(t,["categories","colors","className","onClickLegendItem","activeLegend","enableLegendSlider"]),b=n.useRef(null),g=n.useRef(null),[x,w]=n.useState(null),[O,j]=n.useState(null),S=n.useRef(null),P=(0,n.useCallback)(()=>{let t=null==b?void 0:b.current;t&&w({left:t.scrollLeft>0,right:t.scrollWidth-t.clientWidth>t.scrollLeft})},[w]),E=(0,n.useCallback)(t=>{var e,r;let n=null==b?void 0:b.current,o=null==g?void 0:g.current,i=null!==(e=null==n?void 0:n.clientWidth)&&void 0!==e?e:0,a=null!==(r=null==o?void 0:o.clientWidth)&&void 0!==r?r:0;n&&v&&(n.scrollTo({left:"left"===t?n.scrollLeft-i+a:n.scrollLeft+i-a,behavior:"smooth"}),setTimeout(()=>{P()},400))},[v,P]);n.useEffect(()=>{let t=t=>{"ArrowLeft"===t?E("left"):"ArrowRight"===t&&E("right")};return O?(t(O),S.current=setInterval(()=>{t(O)},300)):clearInterval(S.current),()=>clearInterval(S.current)},[O,E]);let k=t=>{t.stopPropagation(),"ArrowLeft"!==t.key&&"ArrowRight"!==t.key||(t.preventDefault(),j(t.key))},A=t=>{t.stopPropagation(),j(null)};return n.useEffect(()=>{let t=null==b?void 0:b.current;return v&&(P(),null==t||t.addEventListener("keydown",k),null==t||t.addEventListener("keyup",A)),()=>{null==t||t.removeEventListener("keydown",k),null==t||t.removeEventListener("keyup",A)}},[P,v]),n.createElement("ol",Object.assign({ref:e,className:(0,u.q)(f("root"),"relative overflow-hidden",c)},m),n.createElement("div",{ref:b,tabIndex:0,className:(0,u.q)("h-full flex",v?(null==x?void 0:x.right)||(null==x?void 0:x.left)?"pl-4 pr-12 items-center overflow-auto snap-mandatory [&::-webkit-scrollbar]:hidden [scrollbar-width:none]":"":"flex-wrap")},r.map((t,e)=>n.createElement(p,{key:"item-".concat(e),name:t,color:o[e%o.length],onClick:d,activeLegend:y}))),v&&((null==x?void 0:x.right)||(null==x?void 0:x.left))?n.createElement(n.Fragment,null,n.createElement("div",{className:(0,u.q)("bg-tremor-background","dark:bg-dark-tremor-background","absolute flex top-0 pr-1 bottom-0 right-0 items-center justify-center h-full"),ref:g},n.createElement(h,{icon:l,onClick:()=>{j(null),E("left")},disabled:!(null==x?void 0:x.left)}),n.createElement(h,{icon:s,onClick:()=>{j(null),E("right")},disabled:!(null==x?void 0:x.right)}))):null)});d.displayName="Legend";let y=(t,e,r,i,a,u)=>{let{payload:c}=t,l=(0,n.useRef)(null);o(()=>{var t,e;r((e=null===(t=l.current)||void 0===t?void 0:t.clientHeight)?Number(e)+20:60)});let s=c.filter(t=>"none"!==t.type);return n.createElement("div",{ref:l,className:"flex items-center justify-end"},n.createElement(d,{categories:s.map(t=>t.value),colors:s.map(t=>e.get(t.value)),onClickLegendItem:a,activeLegend:i,enableLegendSlider:u}))}},98593:function(t,e,r){"use strict";r.d(e,{$B:function(){return c},ZP:function(){return s},zX:function(){return l}});var n=r(2265),o=r(7084),i=r(26898),a=r(13241),u=r(1153);let c=t=>{let{children:e}=t;return n.createElement("div",{className:(0,a.q)("rounded-tremor-default text-tremor-default border","bg-tremor-background shadow-tremor-dropdown border-tremor-border","dark:bg-dark-tremor-background dark:shadow-dark-tremor-dropdown dark:border-dark-tremor-border")},e)},l=t=>{let{value:e,name:r,color:o}=t;return n.createElement("div",{className:"flex items-center justify-between space-x-8"},n.createElement("div",{className:"flex items-center space-x-2"},n.createElement("span",{className:(0,a.q)("shrink-0 rounded-tremor-full border-2 h-3 w-3","border-tremor-background shadow-tremor-card","dark:border-dark-tremor-background dark:shadow-dark-tremor-card",(0,u.bM)(o,i.K.background).bgColor)}),n.createElement("p",{className:(0,a.q)("text-right whitespace-nowrap","text-tremor-content","dark:text-dark-tremor-content")},r)),n.createElement("p",{className:(0,a.q)("font-medium tabular-nums text-right whitespace-nowrap","text-tremor-content-emphasis","dark:text-dark-tremor-content-emphasis")},e))},s=t=>{let{active:e,payload:r,label:i,categoryColors:u,valueFormatter:s}=t;if(e&&r){let t=r.filter(t=>"none"!==t.type);return n.createElement(c,null,n.createElement("div",{className:(0,a.q)("border-tremor-border border-b px-4 py-2","dark:border-dark-tremor-border")},n.createElement("p",{className:(0,a.q)("font-medium","text-tremor-content-emphasis","dark:text-dark-tremor-content-emphasis")},i)),n.createElement("div",{className:(0,a.q)("px-4 py-2 space-y-1")},t.map((t,e)=>{var r;let{value:i,name:a}=t;return n.createElement(l,{key:"id-".concat(e),value:s(i),name:a,color:null!==(r=u.get(a))&&void 0!==r?r:o.fr.Blue})})))}return null}},92666:function(t,e,r){"use strict";r.d(e,{Z:function(){return i}});var n=r(13241),o=r(2265);let i=t=>{let{className:e,noDataText:r="No data"}=t;return o.createElement("div",{className:(0,n.q)("flex items-center justify-center w-full h-full border border-dashed rounded-tremor-default","border-tremor-border","dark:border-dark-tremor-border",e)},o.createElement("p",{className:(0,n.q)("text-tremor-content text-tremor-default","dark:text-dark-tremor-content")},r))}},32644:function(t,e,r){"use strict";r.d(e,{FB:function(){return i},i4:function(){return o},me:function(){return n},vZ:function(){return function t(e,r){if(e===r)return!0;if("object"!=typeof e||"object"!=typeof r||null===e||null===r)return!1;let n=Object.keys(e),o=Object.keys(r);if(n.length!==o.length)return!1;for(let i of n)if(!o.includes(i)||!t(e[i],r[i]))return!1;return!0}}});let n=(t,e)=>{let r=new Map;return t.forEach((t,n)=>{r.set(t,e[n%e.length])}),r},o=(t,e,r)=>[t?"auto":null!=e?e:0,null!=r?r:"auto"];function i(t,e){let r=[];for(let n of t)if(Object.prototype.hasOwnProperty.call(n,e)&&(r.push(n[e]),r.length>1))return!1;return!0}},49804:function(t,e,r){"use strict";r.d(e,{Z:function(){return l}});var n=r(5853),o=r(13241),i=r(1153),a=r(2265),u=r(9496);let c=(0,i.fn)("Col"),l=a.forwardRef((t,e)=>{let{numColSpan:r=1,numColSpanSm:i,numColSpanMd:l,numColSpanLg:s,children:f,className:p}=t,h=(0,n._T)(t,["numColSpan","numColSpanSm","numColSpanMd","numColSpanLg","children","className"]),d=(t,e)=>t&&Object.keys(e).includes(String(t))?e[t]:"";return a.createElement("div",Object.assign({ref:e,className:(0,o.q)(c("root"),(()=>{let t=d(r,u.PT),e=d(i,u.SP),n=d(l,u.VS),a=d(s,u._w);return(0,o.q)(t,e,n,a)})(),p)},h),f)});l.displayName="Col"},97765:function(t,e,r){"use strict";r.d(e,{Z:function(){return c}});var n=r(5853),o=r(26898),i=r(13241),a=r(1153),u=r(2265);let c=u.forwardRef((t,e)=>{let{color:r,children:c,className:l}=t,s=(0,n._T)(t,["color","children","className"]);return u.createElement("p",Object.assign({ref:e,className:(0,i.q)(r?(0,a.bM)(r,o.K.lightText).textColor:"text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis",l)},s),c)});c.displayName="Subtitle"},61134:function(t,e,r){var n;!function(o){"use strict";var i,a={precision:20,rounding:4,toExpNeg:-7,toExpPos:21,LN10:"2.302585092994045684017991454684364207601101488628772976033327900967572609677352480235997205089598298341967784042286"},u=!0,c="[DecimalError] ",l=c+"Invalid argument: ",s=c+"Exponent out of range: ",f=Math.floor,p=Math.pow,h=/^(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,d=f(1286742750677284.5),y={};function v(t,e){var r,n,o,i,a,c,l,s,f=t.constructor,p=f.precision;if(!t.s||!e.s)return e.s||(e=new f(t)),u?E(e,p):e;if(l=t.d,s=e.d,a=t.e,o=e.e,l=l.slice(),i=a-o){for(i<0?(n=l,i=-i,c=s.length):(n=s,o=a,c=l.length),i>(c=(a=Math.ceil(p/7))>c?a+1:c+1)&&(i=c,n.length=1),n.reverse();i--;)n.push(0);n.reverse()}for((c=l.length)-(i=s.length)<0&&(i=c,n=s,s=l,l=n),r=0;i;)r=(l[--i]=l[i]+s[i]+r)/1e7|0,l[i]%=1e7;for(r&&(l.unshift(r),++o),c=l.length;0==l[--c];)l.pop();return e.d=l,e.e=o,u?E(e,p):e}function m(t,e,r){if(t!==~~t||tr)throw Error(l+t)}function b(t){var e,r,n,o=t.length-1,i="",a=t[0];if(o>0){for(i+=a,e=1;et.e^this.s<0?1:-1;for(e=0,r=(n=this.d.length)<(o=t.d.length)?n:o;et.d[e]^this.s<0?1:-1;return n===o?0:n>o^this.s<0?1:-1},y.decimalPlaces=y.dp=function(){var t=this.d.length-1,e=(t-this.e)*7;if(t=this.d[t])for(;t%10==0;t/=10)e--;return e<0?0:e},y.dividedBy=y.div=function(t){return g(this,new this.constructor(t))},y.dividedToIntegerBy=y.idiv=function(t){var e=this.constructor;return E(g(this,new e(t),0,1),e.precision)},y.equals=y.eq=function(t){return!this.cmp(t)},y.exponent=function(){return w(this)},y.greaterThan=y.gt=function(t){return this.cmp(t)>0},y.greaterThanOrEqualTo=y.gte=function(t){return this.cmp(t)>=0},y.isInteger=y.isint=function(){return this.e>this.d.length-2},y.isNegative=y.isneg=function(){return this.s<0},y.isPositive=y.ispos=function(){return this.s>0},y.isZero=function(){return 0===this.s},y.lessThan=y.lt=function(t){return 0>this.cmp(t)},y.lessThanOrEqualTo=y.lte=function(t){return 1>this.cmp(t)},y.logarithm=y.log=function(t){var e,r=this.constructor,n=r.precision,o=n+5;if(void 0===t)t=new r(10);else if((t=new r(t)).s<1||t.eq(i))throw Error(c+"NaN");if(this.s<1)throw Error(c+(this.s?"NaN":"-Infinity"));return this.eq(i)?new r(0):(u=!1,e=g(S(this,o),S(t,o),o),u=!0,E(e,n))},y.minus=y.sub=function(t){return t=new this.constructor(t),this.s==t.s?k(this,t):v(this,(t.s=-t.s,t))},y.modulo=y.mod=function(t){var e,r=this.constructor,n=r.precision;if(!(t=new r(t)).s)throw Error(c+"NaN");return this.s?(u=!1,e=g(this,t,0,1).times(t),u=!0,this.minus(e)):E(new r(this),n)},y.naturalExponential=y.exp=function(){return x(this)},y.naturalLogarithm=y.ln=function(){return S(this)},y.negated=y.neg=function(){var t=new this.constructor(this);return t.s=-t.s||0,t},y.plus=y.add=function(t){return t=new this.constructor(t),this.s==t.s?v(this,t):k(this,(t.s=-t.s,t))},y.precision=y.sd=function(t){var e,r,n;if(void 0!==t&&!!t!==t&&1!==t&&0!==t)throw Error(l+t);if(e=w(this)+1,r=7*(n=this.d.length-1)+1,n=this.d[n]){for(;n%10==0;n/=10)r--;for(n=this.d[0];n>=10;n/=10)r++}return t&&e>r?e:r},y.squareRoot=y.sqrt=function(){var t,e,r,n,o,i,a,l=this.constructor;if(this.s<1){if(!this.s)return new l(0);throw Error(c+"NaN")}for(t=w(this),u=!1,0==(o=Math.sqrt(+this))||o==1/0?(((e=b(this.d)).length+t)%2==0&&(e+="0"),o=Math.sqrt(e),t=f((t+1)/2)-(t<0||t%2),n=new l(e=o==1/0?"5e"+t:(e=o.toExponential()).slice(0,e.indexOf("e")+1)+t)):n=new l(o.toString()),o=a=(r=l.precision)+3;;)if(n=(i=n).plus(g(this,i,a+2)).times(.5),b(i.d).slice(0,a)===(e=b(n.d)).slice(0,a)){if(e=e.slice(a-3,a+1),o==a&&"4999"==e){if(E(i,r+1,0),i.times(i).eq(this)){n=i;break}}else if("9999"!=e)break;a+=4}return u=!0,E(n,r)},y.times=y.mul=function(t){var e,r,n,o,i,a,c,l,s,f=this.constructor,p=this.d,h=(t=new f(t)).d;if(!this.s||!t.s)return new f(0);for(t.s*=this.s,r=this.e+t.e,(l=p.length)<(s=h.length)&&(i=p,p=h,h=i,a=l,l=s,s=a),i=[],n=a=l+s;n--;)i.push(0);for(n=s;--n>=0;){for(e=0,o=l+n;o>n;)c=i[o]+h[n]*p[o-n-1]+e,i[o--]=c%1e7|0,e=c/1e7|0;i[o]=(i[o]+e)%1e7|0}for(;!i[--a];)i.pop();return e?++r:i.shift(),t.d=i,t.e=r,u?E(t,f.precision):t},y.toDecimalPlaces=y.todp=function(t,e){var r=this,n=r.constructor;return(r=new n(r),void 0===t)?r:(m(t,0,1e9),void 0===e?e=n.rounding:m(e,0,8),E(r,t+w(r)+1,e))},y.toExponential=function(t,e){var r,n=this,o=n.constructor;return void 0===t?r=A(n,!0):(m(t,0,1e9),void 0===e?e=o.rounding:m(e,0,8),r=A(n=E(new o(n),t+1,e),!0,t+1)),r},y.toFixed=function(t,e){var r,n,o=this.constructor;return void 0===t?A(this):(m(t,0,1e9),void 0===e?e=o.rounding:m(e,0,8),r=A((n=E(new o(this),t+w(this)+1,e)).abs(),!1,t+w(n)+1),this.isneg()&&!this.isZero()?"-"+r:r)},y.toInteger=y.toint=function(){var t=this.constructor;return E(new t(this),w(this)+1,t.rounding)},y.toNumber=function(){return+this},y.toPower=y.pow=function(t){var e,r,n,o,a,l,s=this,p=s.constructor,h=+(t=new p(t));if(!t.s)return new p(i);if(!(s=new p(s)).s){if(t.s<1)throw Error(c+"Infinity");return s}if(s.eq(i))return s;if(n=p.precision,t.eq(i))return E(s,n);if(l=(e=t.e)>=(r=t.d.length-1),a=s.s,l){if((r=h<0?-h:h)<=9007199254740991){for(o=new p(i),e=Math.ceil(n/7+4),u=!1;r%2&&M((o=o.times(s)).d,e),0!==(r=f(r/2));)M((s=s.times(s)).d,e);return u=!0,t.s<0?new p(i).div(o):E(o,n)}}else if(a<0)throw Error(c+"NaN");return a=a<0&&1&t.d[Math.max(e,r)]?-1:1,s.s=1,u=!1,o=t.times(S(s,n+12)),u=!0,(o=x(o)).s=a,o},y.toPrecision=function(t,e){var r,n,o=this,i=o.constructor;return void 0===t?(r=w(o),n=A(o,r<=i.toExpNeg||r>=i.toExpPos)):(m(t,1,1e9),void 0===e?e=i.rounding:m(e,0,8),r=w(o=E(new i(o),t,e)),n=A(o,t<=r||r<=i.toExpNeg,t)),n},y.toSignificantDigits=y.tosd=function(t,e){var r=this.constructor;return void 0===t?(t=r.precision,e=r.rounding):(m(t,1,1e9),void 0===e?e=r.rounding:m(e,0,8)),E(new r(this),t,e)},y.toString=y.valueOf=y.val=y.toJSON=function(){var t=w(this),e=this.constructor;return A(this,t<=e.toExpNeg||t>=e.toExpPos)};var g=function(){function t(t,e){var r,n=0,o=t.length;for(t=t.slice();o--;)r=t[o]*e+n,t[o]=r%1e7|0,n=r/1e7|0;return n&&t.unshift(n),t}function e(t,e,r,n){var o,i;if(r!=n)i=r>n?1:-1;else for(o=i=0;oe[o]?1:-1;break}return i}function r(t,e,r){for(var n=0;r--;)t[r]-=n,n=t[r]1;)t.shift()}return function(n,o,i,a){var u,l,s,f,p,h,d,y,v,m,b,g,x,O,j,S,P,k,A=n.constructor,M=n.s==o.s?1:-1,_=n.d,T=o.d;if(!n.s)return new A(n);if(!o.s)throw Error(c+"Division by zero");for(s=0,l=n.e-o.e,P=T.length,j=_.length,y=(d=new A(M)).d=[];T[s]==(_[s]||0);)++s;if(T[s]>(_[s]||0)&&--l,(g=null==i?i=A.precision:a?i+(w(n)-w(o))+1:i)<0)return new A(0);if(g=g/7+2|0,s=0,1==P)for(f=0,T=T[0],g++;(s1&&(T=t(T,f),_=t(_,f),P=T.length,j=_.length),O=P,m=(v=_.slice(0,P)).length;m=1e7/2&&++S;do f=0,(u=e(T,v,P,m))<0?(b=v[0],P!=m&&(b=1e7*b+(v[1]||0)),(f=b/S|0)>1?(f>=1e7&&(f=1e7-1),h=(p=t(T,f)).length,m=v.length,1==(u=e(p,v,h,m))&&(f--,r(p,P16)throw Error(s+w(t));if(!t.s)return new h(i);for(null==e?(u=!1,c=d):c=e,a=new h(.03125);t.abs().gte(.1);)t=t.times(a),f+=5;for(c+=Math.log(p(2,f))/Math.LN10*2+5|0,r=n=o=new h(i),h.precision=c;;){if(n=E(n.times(t),c),r=r.times(++l),b((a=o.plus(g(n,r,c))).d).slice(0,c)===b(o.d).slice(0,c)){for(;f--;)o=E(o.times(o),c);return h.precision=d,null==e?(u=!0,E(o,d)):o}o=a}}function w(t){for(var e=7*t.e,r=t.d[0];r>=10;r/=10)e++;return e}function O(t,e,r){if(e>t.LN10.sd())throw u=!0,r&&(t.precision=r),Error(c+"LN10 precision limit exceeded");return E(new t(t.LN10),e)}function j(t){for(var e="";t--;)e+="0";return e}function S(t,e){var r,n,o,a,l,s,f,p,h,d=1,y=t,v=y.d,m=y.constructor,x=m.precision;if(y.s<1)throw Error(c+(y.s?"NaN":"-Infinity"));if(y.eq(i))return new m(0);if(null==e?(u=!1,p=x):p=e,y.eq(10))return null==e&&(u=!0),O(m,p);if(p+=10,m.precision=p,n=(r=b(v)).charAt(0),!(15e14>Math.abs(a=w(y))))return f=O(m,p+2,x).times(a+""),y=S(new m(n+"."+r.slice(1)),p-10).plus(f),m.precision=x,null==e?(u=!0,E(y,x)):y;for(;n<7&&1!=n||1==n&&r.charAt(1)>3;)n=(r=b((y=y.times(t)).d)).charAt(0),d++;for(a=w(y),n>1?(y=new m("0."+r),a++):y=new m(n+"."+r.slice(1)),s=l=y=g(y.minus(i),y.plus(i),p),h=E(y.times(y),p),o=3;;){if(l=E(l.times(h),p),b((f=s.plus(g(l,new m(o),p))).d).slice(0,p)===b(s.d).slice(0,p))return s=s.times(2),0!==a&&(s=s.plus(O(m,p+2,x).times(a+""))),s=g(s,new m(d),p),m.precision=x,null==e?(u=!0,E(s,x)):s;s=f,o+=2}}function P(t,e){var r,n,o;for((r=e.indexOf("."))>-1&&(e=e.replace(".","")),(n=e.search(/e/i))>0?(r<0&&(r=n),r+=+e.slice(n+1),e=e.substring(0,n)):r<0&&(r=e.length),n=0;48===e.charCodeAt(n);)++n;for(o=e.length;48===e.charCodeAt(o-1);)--o;if(e=e.slice(n,o)){if(o-=n,r=r-n-1,t.e=f(r/7),t.d=[],n=(r+1)%7,r<0&&(n+=7),nd||t.e<-d))throw Error(s+r)}else t.s=0,t.e=0,t.d=[0];return t}function E(t,e,r){var n,o,i,a,c,l,h,y,v=t.d;for(a=1,i=v[0];i>=10;i/=10)a++;if((n=e-a)<0)n+=7,o=e,h=v[y=0];else{if((y=Math.ceil((n+1)/7))>=(i=v.length))return t;for(a=1,h=i=v[y];i>=10;i/=10)a++;n%=7,o=n-7+a}if(void 0!==r&&(c=h/(i=p(10,a-o-1))%10|0,l=e<0||void 0!==v[y+1]||h%i,l=r<4?(c||l)&&(0==r||r==(t.s<0?3:2)):c>5||5==c&&(4==r||l||6==r&&(n>0?o>0?h/p(10,a-o):0:v[y-1])%10&1||r==(t.s<0?8:7))),e<1||!v[0])return l?(i=w(t),v.length=1,e=e-i-1,v[0]=p(10,(7-e%7)%7),t.e=f(-e/7)||0):(v.length=1,v[0]=t.e=t.s=0),t;if(0==n?(v.length=y,i=1,y--):(v.length=y+1,i=p(10,7-n),v[y]=o>0?(h/p(10,a-o)%p(10,o)|0)*i:0),l)for(;;){if(0==y){1e7==(v[0]+=i)&&(v[0]=1,++t.e);break}if(v[y]+=i,1e7!=v[y])break;v[y--]=0,i=1}for(n=v.length;0===v[--n];)v.pop();if(u&&(t.e>d||t.e<-d))throw Error(s+w(t));return t}function k(t,e){var r,n,o,i,a,c,l,s,f,p,h=t.constructor,d=h.precision;if(!t.s||!e.s)return e.s?e.s=-e.s:e=new h(t),u?E(e,d):e;if(l=t.d,p=e.d,n=e.e,s=t.e,l=l.slice(),a=s-n){for((f=a<0)?(r=l,a=-a,c=p.length):(r=p,n=s,c=l.length),a>(o=Math.max(Math.ceil(d/7),c)+2)&&(a=o,r.length=1),r.reverse(),o=a;o--;)r.push(0);r.reverse()}else{for((f=(o=l.length)<(c=p.length))&&(c=o),o=0;o0;--o)l[c++]=0;for(o=p.length;o>a;){if(l[--o]0?i=i.charAt(0)+"."+i.slice(1)+j(n):a>1&&(i=i.charAt(0)+"."+i.slice(1)),i=i+(o<0?"e":"e+")+o):o<0?(i="0."+j(-o-1)+i,r&&(n=r-a)>0&&(i+=j(n))):o>=a?(i+=j(o+1-a),r&&(n=r-o-1)>0&&(i=i+"."+j(n))):((n=o+1)0&&(o+1===a&&(i+="."),i+=j(n))),t.s<0?"-"+i:i}function M(t,e){if(t.length>e)return t.length=e,!0}function _(t){if(!t||"object"!=typeof t)throw Error(c+"Object expected");var e,r,n,o=["precision",1,1e9,"rounding",0,8,"toExpNeg",-1/0,0,"toExpPos",0,1/0];for(e=0;e=o[e+1]&&n<=o[e+2])this[r]=n;else throw Error(l+r+": "+n)}if(void 0!==(n=t[r="LN10"])){if(n==Math.LN10)this[r]=new this(n);else throw Error(l+r+": "+n)}return this}(a=function t(e){var r,n,o;function i(t){if(!(this instanceof i))return new i(t);if(this.constructor=i,t instanceof i){this.s=t.s,this.e=t.e,this.d=(t=t.d)?t.slice():t;return}if("number"==typeof t){if(0*t!=0)throw Error(l+t);if(t>0)this.s=1;else if(t<0)t=-t,this.s=-1;else{this.s=0,this.e=0,this.d=[0];return}if(t===~~t&&t<1e7){this.e=0,this.d=[t];return}return P(this,t.toString())}if("string"!=typeof t)throw Error(l+t);if(45===t.charCodeAt(0)?(t=t.slice(1),this.s=-1):this.s=1,h.test(t))P(this,t);else throw Error(l+t)}if(i.prototype=y,i.ROUND_UP=0,i.ROUND_DOWN=1,i.ROUND_CEIL=2,i.ROUND_FLOOR=3,i.ROUND_HALF_UP=4,i.ROUND_HALF_DOWN=5,i.ROUND_HALF_EVEN=6,i.ROUND_HALF_CEIL=7,i.ROUND_HALF_FLOOR=8,i.clone=t,i.config=i.set=_,void 0===e&&(e={}),e)for(r=0,o=["precision","rounding","toExpNeg","toExpPos","LN10"];r-1}},56883:function(t){t.exports=function(t,e,r){for(var n=-1,o=null==t?0:t.length;++n0&&i(s)?r>1?t(s,r-1,i,a,u):n(u,s):a||(u[u.length]=s)}return u}},63321:function(t,e,r){var n=r(33023)();t.exports=n},98060:function(t,e,r){var n=r(63321),o=r(43228);t.exports=function(t,e){return t&&n(t,e,o)}},92167:function(t,e,r){var n=r(67906),o=r(70235);t.exports=function(t,e){e=n(e,t);for(var r=0,i=e.length;null!=t&&re}},93012:function(t){t.exports=function(t,e){return null!=t&&e in Object(t)}},47909:function(t,e,r){var n=r(8235),o=r(31953),i=r(35281);t.exports=function(t,e,r){return e==e?i(t,e,r):n(t,o,r)}},90370:function(t,e,r){var n=r(54506),o=r(10303);t.exports=function(t){return o(t)&&"[object Arguments]"==n(t)}},56318:function(t,e,r){var n=r(6791),o=r(10303);t.exports=function t(e,r,i,a,u){return e===r||(null!=e&&null!=r&&(o(e)||o(r))?n(e,r,i,a,t,u):e!=e&&r!=r)}},6791:function(t,e,r){var n=r(85885),o=r(97638),i=r(88030),a=r(64974),u=r(81690),c=r(25614),l=r(98051),s=r(9792),f="[object Arguments]",p="[object Array]",h="[object Object]",d=Object.prototype.hasOwnProperty;t.exports=function(t,e,r,y,v,m){var b=c(t),g=c(e),x=b?p:u(t),w=g?p:u(e);x=x==f?h:x,w=w==f?h:w;var O=x==h,j=w==h,S=x==w;if(S&&l(t)){if(!l(e))return!1;b=!0,O=!1}if(S&&!O)return m||(m=new n),b||s(t)?o(t,e,r,y,v,m):i(t,e,x,r,y,v,m);if(!(1&r)){var P=O&&d.call(t,"__wrapped__"),E=j&&d.call(e,"__wrapped__");if(P||E){var k=P?t.value():t,A=E?e.value():e;return m||(m=new n),v(k,A,r,y,m)}}return!!S&&(m||(m=new n),a(t,e,r,y,v,m))}},62538:function(t,e,r){var n=r(85885),o=r(56318);t.exports=function(t,e,r,i){var a=r.length,u=a,c=!i;if(null==t)return!u;for(t=Object(t);a--;){var l=r[a];if(c&&l[2]?l[1]!==t[l[0]]:!(l[0]in t))return!1}for(;++ao?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var i=Array(o);++n=200){var y=e?null:u(t);if(y)return c(y);p=!1,s=a,d=new n}else d=e?[]:h;t:for(;++l=o?t:n(t,e,r)}},1536:function(t,e,r){var n=r(78371);t.exports=function(t,e){if(t!==e){var r=void 0!==t,o=null===t,i=t==t,a=n(t),u=void 0!==e,c=null===e,l=e==e,s=n(e);if(!c&&!s&&!a&&t>e||a&&u&&l&&!c&&!s||o&&u&&l||!r&&l||!i)return 1;if(!o&&!a&&!s&&t=c)return l;return l*("desc"==r[o]?-1:1)}}return t.index-e.index}},92077:function(t,e,r){var n=r(74288)["__core-js_shared__"];t.exports=n},97930:function(t,e,r){var n=r(5629);t.exports=function(t,e){return function(r,o){if(null==r)return r;if(!n(r))return t(r,o);for(var i=r.length,a=e?i:-1,u=Object(r);(e?a--:++a-1?u[c?e[l]:l]:void 0}}},35464:function(t,e,r){var n=r(19608),o=r(49639),i=r(175);t.exports=function(t){return function(e,r,a){return a&&"number"!=typeof a&&o(e,r,a)&&(r=a=void 0),e=i(e),void 0===r?(r=e,e=0):r=i(r),a=void 0===a?es))return!1;var p=c.get(t),h=c.get(e);if(p&&h)return p==e&&h==t;var d=-1,y=!0,v=2&r?new n:void 0;for(c.set(t,e),c.set(e,t);++d-1&&t%1==0&&t-1}},13368:function(t,e,r){var n=r(24457);t.exports=function(t,e){var r=this.__data__,o=n(r,t);return o<0?(++this.size,r.push([t,e])):r[o][1]=e,this}},38764:function(t,e,r){var n=r(9855),o=r(99078),i=r(88675);t.exports=function(){this.size=0,this.__data__={hash:new n,map:new(i||o),string:new n}}},78615:function(t,e,r){var n=r(1507);t.exports=function(t){var e=n(this,t).delete(t);return this.size-=e?1:0,e}},83391:function(t,e,r){var n=r(1507);t.exports=function(t){return n(this,t).get(t)}},53483:function(t,e,r){var n=r(1507);t.exports=function(t){return n(this,t).has(t)}},74724:function(t,e,r){var n=r(1507);t.exports=function(t,e){var r=n(this,t),o=r.size;return r.set(t,e),this.size+=r.size==o?0:1,this}},22523:function(t){t.exports=function(t){var e=-1,r=Array(t.size);return t.forEach(function(t,n){r[++e]=[n,t]}),r}},47073:function(t){t.exports=function(t,e){return function(r){return null!=r&&r[t]===e&&(void 0!==e||t in Object(r))}}},23787:function(t,e,r){var n=r(50967);t.exports=function(t){var e=n(t,function(t){return 500===r.size&&r.clear(),t}),r=e.cache;return e}},20453:function(t,e,r){var n=r(39866)(Object,"create");t.exports=n},77184:function(t,e,r){var n=r(45070)(Object.keys,Object);t.exports=n},39931:function(t,e,r){t=r.nmd(t);var n=r(17071),o=e&&!e.nodeType&&e,i=o&&t&&!t.nodeType&&t,a=i&&i.exports===o&&n.process,u=function(){try{var t=i&&i.require&&i.require("util").types;if(t)return t;return a&&a.binding&&a.binding("util")}catch(t){}}();t.exports=u},45070:function(t){t.exports=function(t,e){return function(r){return t(e(r))}}},49478:function(t,e,r){var n=r(68680),o=Math.max;t.exports=function(t,e,r){return e=o(void 0===e?t.length-1:e,0),function(){for(var i=arguments,a=-1,u=o(i.length-e,0),c=Array(u);++a0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}},84092:function(t,e,r){var n=r(99078);t.exports=function(){this.__data__=new n,this.size=0}},31663:function(t){t.exports=function(t){var e=this.__data__,r=e.delete(t);return this.size=e.size,r}},69135:function(t){t.exports=function(t){return this.__data__.get(t)}},39552:function(t){t.exports=function(t){return this.__data__.has(t)}},63960:function(t,e,r){var n=r(99078),o=r(88675),i=r(76219);t.exports=function(t,e){var r=this.__data__;if(r instanceof n){var a=r.__data__;if(!o||a.length<199)return a.push([t,e]),this.size=++r.size,this;r=this.__data__=new i(a)}return r.set(t,e),this.size=r.size,this}},35281:function(t){t.exports=function(t,e,r){for(var n=r-1,o=t.length;++n-1&&t%1==0&&t<=9007199254740991}},82559:function(t,e,r){var n=r(22345);t.exports=function(t){return n(t)&&t!=+t}},77571:function(t){t.exports=function(t){return null==t}},22345:function(t,e,r){var n=r(54506),o=r(10303);t.exports=function(t){return"number"==typeof t||o(t)&&"[object Number]"==n(t)}},90231:function(t,e,r){var n=r(54506),o=r(62602),i=r(10303),a=Object.prototype,u=Function.prototype.toString,c=a.hasOwnProperty,l=u.call(Object);t.exports=function(t){if(!i(t)||"[object Object]"!=n(t))return!1;var e=o(t);if(null===e)return!0;var r=c.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&u.call(r)==l}},42715:function(t,e,r){var n=r(54506),o=r(25614),i=r(10303);t.exports=function(t){return"string"==typeof t||!o(t)&&i(t)&&"[object String]"==n(t)}},9792:function(t,e,r){var n=r(59332),o=r(23305),i=r(39931),a=i&&i.isTypedArray,u=a?o(a):n;t.exports=u},43228:function(t,e,r){var n=r(28579),o=r(4578),i=r(5629);t.exports=function(t){return i(t)?n(t):o(t)}},86185:function(t){t.exports=function(t){var e=null==t?0:t.length;return e?t[e-1]:void 0}},89238:function(t,e,r){var n=r(73819),o=r(88157),i=r(24240),a=r(25614);t.exports=function(t,e){return(a(t)?n:i)(t,o(e,3))}},41443:function(t,e,r){var n=r(83023),o=r(98060),i=r(88157);t.exports=function(t,e){var r={};return e=i(e,3),o(t,function(t,o,i){n(r,o,e(t,o,i))}),r}},95645:function(t,e,r){var n=r(67646),o=r(58905),i=r(79586);t.exports=function(t){return t&&t.length?n(t,i,o):void 0}},50967:function(t,e,r){var n=r(76219);function o(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw TypeError("Expected a function");var r=function(){var n=arguments,o=e?e.apply(this,n):n[0],i=r.cache;if(i.has(o))return i.get(o);var a=t.apply(this,n);return r.cache=i.set(o,a)||i,a};return r.cache=new(o.Cache||n),r}o.Cache=n,t.exports=o},99008:function(t,e,r){var n=r(67646),o=r(20121),i=r(79586);t.exports=function(t){return t&&t.length?n(t,i,o):void 0}},93810:function(t){t.exports=function(){}},22350:function(t,e,r){var n=r(18155),o=r(73584),i=r(67352),a=r(70235);t.exports=function(t){return i(t)?n(a(t)):o(t)}},99676:function(t,e,r){var n=r(35464)();t.exports=n},33645:function(t,e,r){var n=r(25253),o=r(88157),i=r(12327),a=r(25614),u=r(49639);t.exports=function(t,e,r){var c=a(t)?n:i;return r&&u(t,e,r)&&(e=void 0),c(t,o(e,3))}},34935:function(t,e,r){var n=r(72569),o=r(84046),i=r(44843),a=r(49639),u=i(function(t,e){if(null==t)return[];var r=e.length;return r>1&&a(t,e[0],e[1])?e=[]:r>2&&a(e[0],e[1],e[2])&&(e=[e[0]]),o(t,n(e,1),[])});t.exports=u},55716:function(t){t.exports=function(){return[]}},7406:function(t){t.exports=function(){return!1}},37065:function(t,e,r){var n=r(7310),o=r(28302);t.exports=function(t,e,r){var i=!0,a=!0;if("function"!=typeof t)throw TypeError("Expected a function");return o(r)&&(i="leading"in r?!!r.leading:i,a="trailing"in r?!!r.trailing:a),n(t,e,{leading:i,maxWait:e,trailing:a})}},175:function(t,e,r){var n=r(6660),o=1/0;t.exports=function(t){return t?(t=n(t))===o||t===-o?(t<0?-1:1)*17976931348623157e292:t==t?t:0:0===t?t:0}},85759:function(t,e,r){var n=r(175);t.exports=function(t){var e=n(t),r=e%1;return e==e?r?e-r:e:0}},3641:function(t,e,r){var n=r(65020);t.exports=function(t){return null==t?"":n(t)}},47230:function(t,e,r){var n=r(88157),o=r(13826);t.exports=function(t,e){return t&&t.length?o(t,n(e,2)):[]}},75551:function(t,e,r){var n=r(80675)("toUpperCase");t.exports=n},48049:function(t,e,r){"use strict";var n=r(14397);function o(){}function i(){}i.resetWarningCache=o,t.exports=function(){function t(t,e,r,o,i,a){if(a!==n){var u=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw u.name="Invariant Violation",u}}function e(){return t}t.isRequired=t;var r={array:t,bigint:t,bool:t,func:t,number:t,object:t,string:t,symbol:t,any:t,arrayOf:e,element:t,elementType:t,instanceOf:e,node:t,objectOf:e,oneOf:e,oneOfType:e,shape:e,exact:e,checkPropTypes:i,resetWarningCache:o};return r.PropTypes=r,r}},40718:function(t,e,r){t.exports=r(48049)()},14397:function(t){"use strict";t.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},84735:function(t,e,r){"use strict";r.d(e,{ZP:function(){return tS}});var n=r(2265),o=r(40718),i=r.n(o),a=Object.getOwnPropertyNames,u=Object.getOwnPropertySymbols,c=Object.prototype.hasOwnProperty;function l(t,e){return function(r,n,o){return t(r,n,o)&&e(r,n,o)}}function s(t){return function(e,r,n){if(!e||!r||"object"!=typeof e||"object"!=typeof r)return t(e,r,n);var o=n.cache,i=o.get(e),a=o.get(r);if(i&&a)return i===r&&a===e;o.set(e,r),o.set(r,e);var u=t(e,r,n);return o.delete(e),o.delete(r),u}}function f(t){return a(t).concat(u(t))}var p=Object.hasOwn||function(t,e){return c.call(t,e)};function h(t,e){return t===e||!t&&!e&&t!=t&&e!=e}var d=Object.getOwnPropertyDescriptor,y=Object.keys;function v(t,e,r){var n=t.length;if(e.length!==n)return!1;for(;n-- >0;)if(!r.equals(t[n],e[n],n,n,t,e,r))return!1;return!0}function m(t,e){return h(t.getTime(),e.getTime())}function b(t,e){return t.name===e.name&&t.message===e.message&&t.cause===e.cause&&t.stack===e.stack}function g(t,e){return t===e}function x(t,e,r){var n,o,i=t.size;if(i!==e.size)return!1;if(!i)return!0;for(var a=Array(i),u=t.entries(),c=0;(n=u.next())&&!n.done;){for(var l=e.entries(),s=!1,f=0;(o=l.next())&&!o.done;){if(a[f]){f++;continue}var p=n.value,h=o.value;if(r.equals(p[0],h[0],c,f,t,e,r)&&r.equals(p[1],h[1],p[0],h[0],t,e,r)){s=a[f]=!0;break}f++}if(!s)return!1;c++}return!0}function w(t,e,r){var n=y(t),o=n.length;if(y(e).length!==o)return!1;for(;o-- >0;)if(!A(t,e,r,n[o]))return!1;return!0}function O(t,e,r){var n,o,i,a=f(t),u=a.length;if(f(e).length!==u)return!1;for(;u-- >0;)if(!A(t,e,r,n=a[u])||(o=d(t,n),i=d(e,n),(o||i)&&(!o||!i||o.configurable!==i.configurable||o.enumerable!==i.enumerable||o.writable!==i.writable)))return!1;return!0}function j(t,e){return h(t.valueOf(),e.valueOf())}function S(t,e){return t.source===e.source&&t.flags===e.flags}function P(t,e,r){var n,o,i=t.size;if(i!==e.size)return!1;if(!i)return!0;for(var a=Array(i),u=t.values();(n=u.next())&&!n.done;){for(var c=e.values(),l=!1,s=0;(o=c.next())&&!o.done;){if(!a[s]&&r.equals(n.value,o.value,n.value,o.value,t,e,r)){l=a[s]=!0;break}s++}if(!l)return!1}return!0}function E(t,e){var r=t.length;if(e.length!==r)return!1;for(;r-- >0;)if(t[r]!==e[r])return!1;return!0}function k(t,e){return t.hostname===e.hostname&&t.pathname===e.pathname&&t.protocol===e.protocol&&t.port===e.port&&t.hash===e.hash&&t.username===e.username&&t.password===e.password}function A(t,e,r,n){return("_owner"===n||"__o"===n||"__v"===n)&&(!!t.$$typeof||!!e.$$typeof)||p(e,n)&&r.equals(t[n],e[n],n,n,t,e,r)}var M=Array.isArray,_="undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView:null,T=Object.assign,C=Object.prototype.toString.call.bind(Object.prototype.toString),N=D();function D(t){void 0===t&&(t={});var e,r,n,o,i,a,u,c,f,p,d,y,A,N,D=t.circular,I=t.createInternalComparator,L=t.createState,B=t.strict,R=(r=(e=function(t){var e=t.circular,r=t.createCustomConfig,n=t.strict,o={areArraysEqual:n?O:v,areDatesEqual:m,areErrorsEqual:b,areFunctionsEqual:g,areMapsEqual:n?l(x,O):x,areNumbersEqual:h,areObjectsEqual:n?O:w,arePrimitiveWrappersEqual:j,areRegExpsEqual:S,areSetsEqual:n?l(P,O):P,areTypedArraysEqual:n?O:E,areUrlsEqual:k,unknownTagComparators:void 0};if(r&&(o=T({},o,r(o))),e){var i=s(o.areArraysEqual),a=s(o.areMapsEqual),u=s(o.areObjectsEqual),c=s(o.areSetsEqual);o=T({},o,{areArraysEqual:i,areMapsEqual:a,areObjectsEqual:u,areSetsEqual:c})}return o}(t)).areArraysEqual,n=e.areDatesEqual,o=e.areErrorsEqual,i=e.areFunctionsEqual,a=e.areMapsEqual,u=e.areNumbersEqual,c=e.areObjectsEqual,f=e.arePrimitiveWrappersEqual,p=e.areRegExpsEqual,d=e.areSetsEqual,y=e.areTypedArraysEqual,A=e.areUrlsEqual,N=e.unknownTagComparators,function(t,e,l){if(t===e)return!0;if(null==t||null==e)return!1;var s=typeof t;if(s!==typeof e)return!1;if("object"!==s)return"number"===s?u(t,e,l):"function"===s&&i(t,e,l);var h=t.constructor;if(h!==e.constructor)return!1;if(h===Object)return c(t,e,l);if(M(t))return r(t,e,l);if(null!=_&&_(t))return y(t,e,l);if(h===Date)return n(t,e,l);if(h===RegExp)return p(t,e,l);if(h===Map)return a(t,e,l);if(h===Set)return d(t,e,l);var v=C(t);if("[object Date]"===v)return n(t,e,l);if("[object RegExp]"===v)return p(t,e,l);if("[object Map]"===v)return a(t,e,l);if("[object Set]"===v)return d(t,e,l);if("[object Object]"===v)return"function"!=typeof t.then&&"function"!=typeof e.then&&c(t,e,l);if("[object URL]"===v)return A(t,e,l);if("[object Error]"===v)return o(t,e,l);if("[object Arguments]"===v)return c(t,e,l);if("[object Boolean]"===v||"[object Number]"===v||"[object String]"===v)return f(t,e,l);if(N){var m=N[v];if(!m){var b=null!=t?t[Symbol.toStringTag]:void 0;b&&(m=N[b])}if(m)return m(t,e,l)}return!1}),z=I?I(R):function(t,e,r,n,o,i,a){return R(t,e,a)};return function(t){var e=t.circular,r=t.comparator,n=t.createState,o=t.equals,i=t.strict;if(n)return function(t,a){var u=n(),c=u.cache;return r(t,a,{cache:void 0===c?e?new WeakMap:void 0:c,equals:o,meta:u.meta,strict:i})};if(e)return function(t,e){return r(t,e,{cache:new WeakMap,equals:o,meta:void 0,strict:i})};var a={cache:void 0,equals:o,meta:void 0,strict:i};return function(t,e){return r(t,e,a)}}({circular:void 0!==D&&D,comparator:R,createState:L,equals:z,strict:void 0!==B&&B})}function I(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=-1;requestAnimationFrame(function n(o){if(r<0&&(r=o),o-r>e)t(o),r=-1;else{var i;i=n,"undefined"!=typeof requestAnimationFrame&&requestAnimationFrame(i)}})}function L(t){return(L="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function B(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);rt.length)&&(e=t.length);for(var r=0,n=Array(e);r=0&&t<=1}),"[configBezier]: arguments should be x1, y1, x2, y2 of [0, 1] instead received %s",n);var p=V(i,u),h=V(a,c),d=(t=i,e=u,function(r){var n;return G([].concat(function(t){if(Array.isArray(t))return H(t)}(n=X(t,e).map(function(t,e){return t*e}).slice(1))||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(n)||Y(n)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),[0]),r)}),y=function(t){for(var e=t>1?1:t,r=e,n=0;n<8;++n){var o,i=p(r)-e,a=d(r);if(1e-4>Math.abs(i-e)||a<1e-4)break;r=(o=r-i/a)>1?1:o<0?0:o}return h(r)};return y.isStepper=!1,y},Q=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.stiff,r=void 0===e?100:e,n=t.damping,o=void 0===n?8:n,i=t.dt,a=void 0===i?17:i,u=function(t,e,n){var i=n+(-(t-e)*r-n*o)*a/1e3,u=n*a/1e3+t;return 1e-4>Math.abs(u-e)&&1e-4>Math.abs(i)?[e,0]:[u,i]};return u.isStepper=!0,u.dt=a,u},J=function(){for(var t=arguments.length,e=Array(t),r=0;rt.length)&&(e=t.length);for(var r=0,n=Array(e);rt.length)&&(e=t.length);for(var r=0,n=Array(e);r0?r[o-1]:n,p=l||Object.keys(c);if("function"==typeof u||"spring"===u)return[].concat(th(t),[e.runJSAnimation.bind(e,{from:f.style,to:c,duration:i,easing:u}),i]);var h=Z(p,i,u),d=tv(tv(tv({},f.style),c),{},{transition:h});return[].concat(th(t),[d,i,s]).filter($)},[a,Math.max(void 0===u?0:u,n)])),[t.onAnimationEnd]))}},{key:"runAnimation",value:function(t){if(!this.manager){var e,r,n;this.manager=(e=function(){return null},r=!1,n=function t(n){if(!r){if(Array.isArray(n)){if(!n.length)return;var o=function(t){if(Array.isArray(t))return t}(n)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(n)||function(t,e){if(t){if("string"==typeof t)return B(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return B(t,void 0)}}(n)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),i=o[0],a=o.slice(1);if("number"==typeof i){I(t.bind(null,a),i);return}t(i),I(t.bind(null,a));return}"object"===L(n)&&e(n),"function"==typeof n&&n()}},{stop:function(){r=!0},start:function(t){r=!1,n(t)},subscribe:function(t){return e=t,function(){e=function(){return null}}}})}var o=t.begin,i=t.duration,a=t.attributeName,u=t.to,c=t.easing,l=t.onAnimationStart,s=t.onAnimationEnd,f=t.steps,p=t.children,h=this.manager;if(this.unSubscribe=h.subscribe(this.handleStyleChange),"function"==typeof c||"function"==typeof p||"spring"===c){this.runJSAnimation(t);return}if(f.length>1){this.runStepAnimation(t);return}var d=a?tm({},a,u):u,y=Z(Object.keys(d),i,c);h.start([l,o,tv(tv({},d),{},{transition:y}),i,s])}},{key:"render",value:function(){var t=this.props,e=t.children,r=(t.begin,t.duration),o=(t.attributeName,t.easing,t.isActive),i=(t.steps,t.from,t.to,t.canBegin,t.onAnimationEnd,t.shouldReAnimate,t.onAnimationReStart,function(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r,n,o={},i=Object.keys(t);for(n=0;n=0||(o[r]=t[r]);return o}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,tp)),a=n.Children.count(e),u=this.state.style;if("function"==typeof e)return e(u);if(!o||0===a||r<=0)return e;var c=function(t){var e=t.props,r=e.style,o=e.className;return(0,n.cloneElement)(t,tv(tv({},i),{},{style:tv(tv({},void 0===r?{}:r),u),className:o}))};return 1===a?c(n.Children.only(e)):n.createElement("div",null,n.Children.map(e,function(t){return c(t)}))}}],function(t,e){for(var r=0;r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,w),i=parseInt("".concat(r),10),a=parseInt("".concat(n),10),u=parseInt("".concat(e.height||o.height),10),c=parseInt("".concat(e.width||o.width),10);return P(P(P(P(P({},e),o),i?{x:i}:{}),a?{y:a}:{}),{},{height:u,width:c,name:e.name,radius:e.radius})}function k(t){return n.createElement(x.bn,j({shapeType:"rectangle",propTransformer:E,activeClassName:"recharts-active-bar"},t))}var A=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return function(r,n){if("number"==typeof t)return t;var o=(0,d.hj)(r)||(0,d.Rw)(r);return o?t(r,n):(o||(0,g.Z)(!1),e)}},M=["value","background"];function _(t){return(_="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function T(){return(T=Object.assign?Object.assign.bind():function(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(e,M);if(!u)return null;var l=N(N(N(N(N({},c),{},{fill:"#eee"},u),a),(0,b.bw)(t.props,e,r)),{},{onAnimationStart:t.handleAnimationStart,onAnimationEnd:t.handleAnimationEnd,dataKey:o,index:r,className:"recharts-bar-background-rectangle"});return n.createElement(k,T({key:"background-bar-".concat(r),option:t.props.background,isActive:r===i},l))})}},{key:"renderErrorBar",value:function(t,e){if(this.props.isAnimationActive&&!this.state.isAnimationFinished)return null;var r=this.props,o=r.data,i=r.xAxis,a=r.yAxis,u=r.layout,c=r.children,l=(0,y.NN)(c,f.W);if(!l)return null;var p="vertical"===u?o[0].height/2:o[0].width/2,h=function(t,e){var r=Array.isArray(t.value)?t.value[1]:t.value;return{x:t.x,y:t.y,value:r,errorVal:(0,m.F$)(t,e)}};return n.createElement(s.m,{clipPath:t?"url(#clipPath-".concat(e,")"):null},l.map(function(t){return n.cloneElement(t,{key:"error-bar-".concat(e,"-").concat(t.props.dataKey),data:o,xAxis:i,yAxis:a,layout:u,offset:p,dataPointFormatter:h})}))}},{key:"render",value:function(){var t=this.props,e=t.hide,r=t.data,i=t.className,a=t.xAxis,u=t.yAxis,c=t.left,f=t.top,p=t.width,d=t.height,y=t.isAnimationActive,v=t.background,m=t.id;if(e||!r||!r.length)return null;var b=this.state.isAnimationFinished,g=(0,o.Z)("recharts-bar",i),x=a&&a.allowDataOverflow,w=u&&u.allowDataOverflow,O=x||w,j=l()(m)?this.id:m;return n.createElement(s.m,{className:g},x||w?n.createElement("defs",null,n.createElement("clipPath",{id:"clipPath-".concat(j)},n.createElement("rect",{x:x?c:c-p/2,y:w?f:f-d/2,width:x?p:2*p,height:w?d:2*d}))):null,n.createElement(s.m,{className:"recharts-bar-rectangles",clipPath:O?"url(#clipPath-".concat(j,")"):null},v?this.renderBackground():null,this.renderRectangles()),this.renderErrorBar(O,j),(!y||b)&&h.e.renderCallByParent(this.props,r))}}],r=[{key:"getDerivedStateFromProps",value:function(t,e){return t.animationId!==e.prevAnimationId?{prevAnimationId:t.animationId,curData:t.data,prevData:e.curData}:t.data!==e.curData?{curData:t.data}:null}}],e&&D(a.prototype,e),r&&D(a,r),Object.defineProperty(a,"prototype",{writable:!1}),a}(n.PureComponent);R(U,"displayName","Bar"),R(U,"defaultProps",{xAxisId:0,yAxisId:0,legendType:"rect",minPointSize:0,hide:!1,data:[],layout:"vertical",activeBar:!1,isAnimationActive:!v.x.isSsr,animationBegin:0,animationDuration:400,animationEasing:"ease"}),R(U,"getComposedData",function(t){var e=t.props,r=t.item,n=t.barPosition,o=t.bandSize,i=t.xAxis,a=t.yAxis,u=t.xAxisTicks,c=t.yAxisTicks,l=t.stackedData,s=t.dataStartIndex,f=t.displayedData,h=t.offset,v=(0,m.Bu)(n,r);if(!v)return null;var b=e.layout,g=r.type.defaultProps,x=void 0!==g?N(N({},g),r.props):r.props,w=x.dataKey,O=x.children,j=x.minPointSize,S="horizontal"===b?a:i,P=l?S.scale.domain():null,E=(0,m.Yj)({numericAxis:S}),k=(0,y.NN)(O,p.b),M=f.map(function(t,e){l?f=(0,m.Vv)(l[s+e],P):Array.isArray(f=(0,m.F$)(t,w))||(f=[E,f]);var n=A(j,U.defaultProps.minPointSize)(f[1],e);if("horizontal"===b){var f,p,h,y,g,x,O,S=[a.scale(f[0]),a.scale(f[1])],M=S[0],_=S[1];p=(0,m.Fy)({axis:i,ticks:u,bandSize:o,offset:v.offset,entry:t,index:e}),h=null!==(O=null!=_?_:M)&&void 0!==O?O:void 0,y=v.size;var T=M-_;if(g=Number.isNaN(T)?0:T,x={x:p,y:a.y,width:y,height:a.height},Math.abs(n)>0&&Math.abs(g)0&&Math.abs(y)=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function P(t,e){for(var r=0;r0?this.props:d)),o<=0||a<=0||!y||!y.length)?null:n.createElement(s.m,{className:(0,c.Z)("recharts-cartesian-axis",l),ref:function(e){t.layerReference=e}},r&&this.renderAxisLine(),this.renderTicks(y,this.state.fontSize,this.state.letterSpacing),p._.renderCallByParent(this.props))}}],r=[{key:"renderTickItem",value:function(t,e,r){var o=(0,c.Z)(e.className,"recharts-cartesian-axis-tick-value");return n.isValidElement(t)?n.cloneElement(t,j(j({},e),{},{className:o})):i()(t)?t(j(j({},e),{},{className:o})):n.createElement(f.x,w({},e,{className:"recharts-cartesian-axis-tick-value"}),r)}}],e&&P(o.prototype,e),r&&P(o,r),Object.defineProperty(o,"prototype",{writable:!1}),o}(n.Component);M(T,"displayName","CartesianAxis"),M(T,"defaultProps",{x:0,y:0,width:0,height:0,viewBox:{x:0,y:0,width:0,height:0},orientation:"bottom",ticks:[],stroke:"#666",tickLine:!0,axisLine:!0,tick:!0,mirror:!1,minTickGap:5,tickSize:6,tickMargin:2,interval:"preserveEnd"})},56940:function(t,e,r){"use strict";r.d(e,{q:function(){return M}});var n=r(2265),o=r(86757),i=r.n(o),a=r(1175),u=r(16630),c=r(82944),l=r(85355),s=r(78242),f=r(80285),p=r(25739),h=["x1","y1","x2","y2","key"],d=["offset"];function y(t){return(y="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function v(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function m(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}var x=function(t){var e=t.fill;if(!e||"none"===e)return null;var r=t.fillOpacity,o=t.x,i=t.y,a=t.width,u=t.height,c=t.ry;return n.createElement("rect",{x:o,y:i,ry:c,width:a,height:u,stroke:"none",fill:e,fillOpacity:r,className:"recharts-cartesian-grid-bg"})};function w(t,e){var r;if(n.isValidElement(t))r=n.cloneElement(t,e);else if(i()(t))r=t(e);else{var o=e.x1,a=e.y1,u=e.x2,l=e.y2,s=e.key,f=g(e,h),p=(0,c.L6)(f,!1),y=(p.offset,g(p,d));r=n.createElement("line",b({},y,{x1:o,y1:a,x2:u,y2:l,fill:"none",key:s}))}return r}function O(t){var e=t.x,r=t.width,o=t.horizontal,i=void 0===o||o,a=t.horizontalPoints;if(!i||!a||!a.length)return null;var u=a.map(function(n,o){return w(i,m(m({},t),{},{x1:e,y1:n,x2:e+r,y2:n,key:"line-".concat(o),index:o}))});return n.createElement("g",{className:"recharts-cartesian-grid-horizontal"},u)}function j(t){var e=t.y,r=t.height,o=t.vertical,i=void 0===o||o,a=t.verticalPoints;if(!i||!a||!a.length)return null;var u=a.map(function(n,o){return w(i,m(m({},t),{},{x1:n,y1:e,x2:n,y2:e+r,key:"line-".concat(o),index:o}))});return n.createElement("g",{className:"recharts-cartesian-grid-vertical"},u)}function S(t){var e=t.horizontalFill,r=t.fillOpacity,o=t.x,i=t.y,a=t.width,u=t.height,c=t.horizontalPoints,l=t.horizontal;if(!(void 0===l||l)||!e||!e.length)return null;var s=c.map(function(t){return Math.round(t+i-i)}).sort(function(t,e){return t-e});i!==s[0]&&s.unshift(0);var f=s.map(function(t,c){var l=s[c+1]?s[c+1]-t:i+u-t;if(l<=0)return null;var f=c%e.length;return n.createElement("rect",{key:"react-".concat(c),y:t,x:o,height:l,width:a,stroke:"none",fill:e[f],fillOpacity:r,className:"recharts-cartesian-grid-bg"})});return n.createElement("g",{className:"recharts-cartesian-gridstripes-horizontal"},f)}function P(t){var e=t.vertical,r=t.verticalFill,o=t.fillOpacity,i=t.x,a=t.y,u=t.width,c=t.height,l=t.verticalPoints;if(!(void 0===e||e)||!r||!r.length)return null;var s=l.map(function(t){return Math.round(t+i-i)}).sort(function(t,e){return t-e});i!==s[0]&&s.unshift(0);var f=s.map(function(t,e){var l=s[e+1]?s[e+1]-t:i+u-t;if(l<=0)return null;var f=e%r.length;return n.createElement("rect",{key:"react-".concat(e),x:t,y:a,width:l,height:c,stroke:"none",fill:r[f],fillOpacity:o,className:"recharts-cartesian-grid-bg"})});return n.createElement("g",{className:"recharts-cartesian-gridstripes-vertical"},f)}var E=function(t,e){var r=t.xAxis,n=t.width,o=t.height,i=t.offset;return(0,l.Rf)((0,s.f)(m(m(m({},f.O.defaultProps),r),{},{ticks:(0,l.uY)(r,!0),viewBox:{x:0,y:0,width:n,height:o}})),i.left,i.left+i.width,e)},k=function(t,e){var r=t.yAxis,n=t.width,o=t.height,i=t.offset;return(0,l.Rf)((0,s.f)(m(m(m({},f.O.defaultProps),r),{},{ticks:(0,l.uY)(r,!0),viewBox:{x:0,y:0,width:n,height:o}})),i.top,i.top+i.height,e)},A={horizontal:!0,vertical:!0,stroke:"#ccc",fill:"none",verticalFill:[],horizontalFill:[]};function M(t){var e,r,o,c,l,s,f=(0,p.zn)(),h=(0,p.Mw)(),d=(0,p.qD)(),v=m(m({},t),{},{stroke:null!==(e=t.stroke)&&void 0!==e?e:A.stroke,fill:null!==(r=t.fill)&&void 0!==r?r:A.fill,horizontal:null!==(o=t.horizontal)&&void 0!==o?o:A.horizontal,horizontalFill:null!==(c=t.horizontalFill)&&void 0!==c?c:A.horizontalFill,vertical:null!==(l=t.vertical)&&void 0!==l?l:A.vertical,verticalFill:null!==(s=t.verticalFill)&&void 0!==s?s:A.verticalFill,x:(0,u.hj)(t.x)?t.x:d.left,y:(0,u.hj)(t.y)?t.y:d.top,width:(0,u.hj)(t.width)?t.width:d.width,height:(0,u.hj)(t.height)?t.height:d.height}),g=v.x,w=v.y,M=v.width,_=v.height,T=v.syncWithTicks,C=v.horizontalValues,N=v.verticalValues,D=(0,p.CW)(),I=(0,p.Nf)();if(!(0,u.hj)(M)||M<=0||!(0,u.hj)(_)||_<=0||!(0,u.hj)(g)||g!==+g||!(0,u.hj)(w)||w!==+w)return null;var L=v.verticalCoordinatesGenerator||E,B=v.horizontalCoordinatesGenerator||k,R=v.horizontalPoints,z=v.verticalPoints;if((!R||!R.length)&&i()(B)){var U=C&&C.length,F=B({yAxis:I?m(m({},I),{},{ticks:U?C:I.ticks}):void 0,width:f,height:h,offset:d},!!U||T);(0,a.Z)(Array.isArray(F),"horizontalCoordinatesGenerator should return Array but instead it returned [".concat(y(F),"]")),Array.isArray(F)&&(R=F)}if((!z||!z.length)&&i()(L)){var $=N&&N.length,q=L({xAxis:D?m(m({},D),{},{ticks:$?N:D.ticks}):void 0,width:f,height:h,offset:d},!!$||T);(0,a.Z)(Array.isArray(q),"verticalCoordinatesGenerator should return Array but instead it returned [".concat(y(q),"]")),Array.isArray(q)&&(z=q)}return n.createElement("g",{className:"recharts-cartesian-grid"},n.createElement(x,{fill:v.fill,fillOpacity:v.fillOpacity,x:v.x,y:v.y,width:v.width,height:v.height,ry:v.ry}),n.createElement(O,b({},v,{offset:d,horizontalPoints:R,xAxis:D,yAxis:I})),n.createElement(j,b({},v,{offset:d,verticalPoints:z,xAxis:D,yAxis:I})),n.createElement(S,b({},v,{horizontalPoints:R})),n.createElement(P,b({},v,{verticalPoints:z})))}M.displayName="CartesianGrid"},13137:function(t,e,r){"use strict";r.d(e,{W:function(){return v}});var n=r(2265),o=r(69398),i=r(9841),a=r(82944),u=["offset","layout","width","dataKey","data","dataPointFormatter","xAxis","yAxis"];function c(t){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function l(){return(l=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,u),m=(0,a.L6)(v,!1);"x"===this.props.direction&&"number"!==d.type&&(0,o.Z)(!1);var b=p.map(function(t){var o,a,u=h(t,f),p=u.x,v=u.y,b=u.value,g=u.errorVal;if(!g)return null;var x=[];if(Array.isArray(g)){var w=function(t){if(Array.isArray(t))return t}(g)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{for(i=(r=r.call(t)).next;!(c=(n=i.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(g,2)||function(t,e){if(t){if("string"==typeof t)return s(t,2);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return s(t,2)}}(g,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}();o=w[0],a=w[1]}else o=a=g;if("vertical"===r){var O=d.scale,j=v+e,S=j+c,P=j-c,E=O(b-o),k=O(b+a);x.push({x1:k,y1:S,x2:k,y2:P}),x.push({x1:E,y1:j,x2:k,y2:j}),x.push({x1:E,y1:S,x2:E,y2:P})}else if("horizontal"===r){var A=y.scale,M=p+e,_=M-c,T=M+c,C=A(b-o),N=A(b+a);x.push({x1:_,y1:N,x2:T,y2:N}),x.push({x1:M,y1:C,x2:M,y2:N}),x.push({x1:_,y1:C,x2:T,y2:C})}return n.createElement(i.m,l({className:"recharts-errorBar",key:"bar-".concat(x.map(function(t){return"".concat(t.x1,"-").concat(t.x2,"-").concat(t.y1,"-").concat(t.y2)}))},m),x.map(function(t){return n.createElement("line",l({},t,{key:"line-".concat(t.x1,"-").concat(t.x2,"-").concat(t.y1,"-").concat(t.y2)}))}))});return n.createElement(i.m,{className:"recharts-errorBars"},b)}}],function(t,e){for(var r=0;rt*o)return!1;var i=r();return t*(e-t*i/2-n)>=0&&t*(e+t*i/2-o)<=0}function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function h(t){for(var e=1;e=2?(0,i.uY)(m[1].coordinate-m[0].coordinate):1,M=(n="width"===P,f=b.x,p=b.y,d=b.width,y=b.height,1===A?{start:n?f:p,end:n?f+d:p+y}:{start:n?f+d:p+y,end:n?f:p});return"equidistantPreserveStart"===w?function(t,e,r,n,o){for(var i,a=(n||[]).slice(),u=e.start,c=e.end,f=0,p=1,h=u;p<=a.length;)if(i=function(){var e,i=null==n?void 0:n[f];if(void 0===i)return{v:l(n,p)};var a=f,d=function(){return void 0===e&&(e=r(i,a)),e},y=i.coordinate,v=0===f||s(t,y,d,h,c);v||(f=0,h=u,p+=1),v&&(h=y+t*(d()/2+o),f+=p)}())return i.v;return[]}(A,M,k,m,g):("preserveStart"===w||"preserveStartEnd"===w?function(t,e,r,n,o,i){var a=(n||[]).slice(),u=a.length,c=e.start,l=e.end;if(i){var f=n[u-1],p=r(f,u-1),d=t*(f.coordinate+t*p/2-l);a[u-1]=f=h(h({},f),{},{tickCoord:d>0?f.coordinate-d*t:f.coordinate}),s(t,f.tickCoord,function(){return p},c,l)&&(l=f.tickCoord-t*(p/2+o),a[u-1]=h(h({},f),{},{isShow:!0}))}for(var y=i?u-1:u,v=function(e){var n,i=a[e],u=function(){return void 0===n&&(n=r(i,e)),n};if(0===e){var f=t*(i.coordinate-t*u()/2-c);a[e]=i=h(h({},i),{},{tickCoord:f<0?i.coordinate-f*t:i.coordinate})}else a[e]=i=h(h({},i),{},{tickCoord:i.coordinate});s(t,i.tickCoord,u,c,l)&&(c=i.tickCoord+t*(u()/2+o),a[e]=h(h({},i),{},{isShow:!0}))},m=0;m0?l.coordinate-p*t:l.coordinate})}else i[e]=l=h(h({},l),{},{tickCoord:l.coordinate});s(t,l.tickCoord,f,u,c)&&(c=l.tickCoord-t*(f()/2+o),i[e]=h(h({},l),{},{isShow:!0}))},f=a-1;f>=0;f--)l(f);return i}(A,M,k,m,g)).filter(function(t){return t.isShow})}},93765:function(t,e,r){"use strict";r.d(e,{z:function(){return eD}});var n,o,i=r(2265),a=r(77571),u=r.n(a),c=r(86757),l=r.n(c),s=r(99676),f=r.n(s),p=r(13735),h=r.n(p),d=r(34935),y=r.n(d),v=r(37065),m=r.n(v),b=r(87602),g=r(69398),x=r(48777),w=r(9841),O=r(8147),j=r(22190),S=r(81889),P=r(73649),E=r(82944),k=r(55284),A=r(58811),M=r(85355),_=r(16630);function T(t){return(T="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function C(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function N(t){for(var e=1;e0&&e.handleDrag(t.changedTouches[0])}),W(e,"handleDragEnd",function(){e.setState({isTravellerMoving:!1,isSlideMoving:!1},function(){var t=e.props,r=t.endIndex,n=t.onDragEnd,o=t.startIndex;null==n||n({endIndex:r,startIndex:o})}),e.detachDragEndListener()}),W(e,"handleLeaveWrapper",function(){(e.state.isTravellerMoving||e.state.isSlideMoving)&&(e.leaveTimer=window.setTimeout(e.handleDragEnd,e.props.leaveTimeOut))}),W(e,"handleEnterSlideOrTraveller",function(){e.setState({isTextActive:!0})}),W(e,"handleLeaveSlideOrTraveller",function(){e.setState({isTextActive:!1})}),W(e,"handleSlideDragStart",function(t){var r=X(t)?t.changedTouches[0]:t;e.setState({isTravellerMoving:!1,isSlideMoving:!0,slideMoveStartX:r.pageX}),e.attachDragEndListener()}),e.travellerDragStartHandlers={startX:e.handleTravellerDragStart.bind(e,"startX"),endX:e.handleTravellerDragStart.bind(e,"endX")},e.state={},e}return!function(t,e){if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&Z(t,e)}(n,t),e=[{key:"componentWillUnmount",value:function(){this.leaveTimer&&(clearTimeout(this.leaveTimer),this.leaveTimer=null),this.detachDragEndListener()}},{key:"getIndex",value:function(t){var e=t.startX,r=t.endX,o=this.state.scaleValues,i=this.props,a=i.gap,u=i.data.length-1,c=n.getIndexInRange(o,Math.min(e,r)),l=n.getIndexInRange(o,Math.max(e,r));return{startIndex:c-c%a,endIndex:l===u?u:l-l%a}}},{key:"getTextOfTick",value:function(t){var e=this.props,r=e.data,n=e.tickFormatter,o=e.dataKey,i=(0,M.F$)(r[t],o,t);return l()(n)?n(i,t):i}},{key:"attachDragEndListener",value:function(){window.addEventListener("mouseup",this.handleDragEnd,!0),window.addEventListener("touchend",this.handleDragEnd,!0),window.addEventListener("mousemove",this.handleDrag,!0)}},{key:"detachDragEndListener",value:function(){window.removeEventListener("mouseup",this.handleDragEnd,!0),window.removeEventListener("touchend",this.handleDragEnd,!0),window.removeEventListener("mousemove",this.handleDrag,!0)}},{key:"handleSlideDrag",value:function(t){var e=this.state,r=e.slideMoveStartX,n=e.startX,o=e.endX,i=this.props,a=i.x,u=i.width,c=i.travellerWidth,l=i.startIndex,s=i.endIndex,f=i.onChange,p=t.pageX-r;p>0?p=Math.min(p,a+u-c-o,a+u-c-n):p<0&&(p=Math.max(p,a-n,a-o));var h=this.getIndex({startX:n+p,endX:o+p});(h.startIndex!==l||h.endIndex!==s)&&f&&f(h),this.setState({startX:n+p,endX:o+p,slideMoveStartX:t.pageX})}},{key:"handleTravellerDragStart",value:function(t,e){var r=X(e)?e.changedTouches[0]:e;this.setState({isSlideMoving:!1,isTravellerMoving:!0,movingTravellerId:t,brushMoveStartX:r.pageX}),this.attachDragEndListener()}},{key:"handleTravellerMove",value:function(t){var e=this.state,r=e.brushMoveStartX,n=e.movingTravellerId,o=e.endX,i=e.startX,a=this.state[n],u=this.props,c=u.x,l=u.width,s=u.travellerWidth,f=u.onChange,p=u.gap,h=u.data,d={startX:this.state.startX,endX:this.state.endX},y=t.pageX-r;y>0?y=Math.min(y,c+l-s-a):y<0&&(y=Math.max(y,c-a)),d[n]=a+y;var v=this.getIndex(d),m=v.startIndex,b=v.endIndex,g=function(){var t=h.length-1;return"startX"===n&&(o>i?m%p==0:b%p==0)||oi?b%p==0:m%p==0)||o>i&&b===t};this.setState(W(W({},n,a+y),"brushMoveStartX",t.pageX),function(){f&&g()&&f(v)})}},{key:"handleTravellerMoveKeyboard",value:function(t,e){var r=this,n=this.state,o=n.scaleValues,i=n.startX,a=n.endX,u=this.state[e],c=o.indexOf(u);if(-1!==c){var l=c+t;if(-1!==l&&!(l>=o.length)){var s=o[l];"startX"===e&&s>=a||"endX"===e&&s<=i||this.setState(W({},e,s),function(){r.props.onChange(r.getIndex({startX:r.state.startX,endX:r.state.endX}))})}}}},{key:"renderBackground",value:function(){var t=this.props,e=t.x,r=t.y,n=t.width,o=t.height,a=t.fill,u=t.stroke;return i.createElement("rect",{stroke:u,fill:a,x:e,y:r,width:n,height:o})}},{key:"renderPanorama",value:function(){var t=this.props,e=t.x,r=t.y,n=t.width,o=t.height,a=t.data,u=t.children,c=t.padding,l=i.Children.only(u);return l?i.cloneElement(l,{x:e,y:r,width:n,height:o,margin:c,compact:!0,data:a}):null}},{key:"renderTravellerLayer",value:function(t,e){var r,o,a=this,u=this.props,c=u.y,l=u.travellerWidth,s=u.height,f=u.traveller,p=u.ariaLabel,h=u.data,d=u.startIndex,y=u.endIndex,v=Math.max(t,this.props.x),m=U(U({},(0,E.L6)(this.props,!1)),{},{x:v,y:c,width:l,height:s}),b=p||"Min value: ".concat(null===(r=h[d])||void 0===r?void 0:r.name,", Max value: ").concat(null===(o=h[y])||void 0===o?void 0:o.name);return i.createElement(w.m,{tabIndex:0,role:"slider","aria-label":b,"aria-valuenow":t,className:"recharts-brush-traveller",onMouseEnter:this.handleEnterSlideOrTraveller,onMouseLeave:this.handleLeaveSlideOrTraveller,onMouseDown:this.travellerDragStartHandlers[e],onTouchStart:this.travellerDragStartHandlers[e],onKeyDown:function(t){["ArrowLeft","ArrowRight"].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),a.handleTravellerMoveKeyboard("ArrowRight"===t.key?1:-1,e))},onFocus:function(){a.setState({isTravellerFocused:!0})},onBlur:function(){a.setState({isTravellerFocused:!1})},style:{cursor:"col-resize"}},n.renderTraveller(f,m))}},{key:"renderSlide",value:function(t,e){var r=this.props,n=r.y,o=r.height,a=r.stroke,u=r.travellerWidth;return i.createElement("rect",{className:"recharts-brush-slide",onMouseEnter:this.handleEnterSlideOrTraveller,onMouseLeave:this.handleLeaveSlideOrTraveller,onMouseDown:this.handleSlideDragStart,onTouchStart:this.handleSlideDragStart,style:{cursor:"move"},stroke:"none",fill:a,fillOpacity:.2,x:Math.min(t,e)+u,y:n,width:Math.max(Math.abs(e-t)-u,0),height:o})}},{key:"renderText",value:function(){var t=this.props,e=t.startIndex,r=t.endIndex,n=t.y,o=t.height,a=t.travellerWidth,u=t.stroke,c=this.state,l=c.startX,s=c.endX,f={pointerEvents:"none",fill:u};return i.createElement(w.m,{className:"recharts-brush-texts"},i.createElement(A.x,R({textAnchor:"end",verticalAnchor:"middle",x:Math.min(l,s)-5,y:n+o/2},f),this.getTextOfTick(e)),i.createElement(A.x,R({textAnchor:"start",verticalAnchor:"middle",x:Math.max(l,s)+a+5,y:n+o/2},f),this.getTextOfTick(r)))}},{key:"render",value:function(){var t=this.props,e=t.data,r=t.className,n=t.children,o=t.x,a=t.y,u=t.width,c=t.height,l=t.alwaysShowText,s=this.state,f=s.startX,p=s.endX,h=s.isTextActive,d=s.isSlideMoving,y=s.isTravellerMoving,v=s.isTravellerFocused;if(!e||!e.length||!(0,_.hj)(o)||!(0,_.hj)(a)||!(0,_.hj)(u)||!(0,_.hj)(c)||u<=0||c<=0)return null;var m=(0,b.Z)("recharts-brush",r),g=1===i.Children.count(n),x=L("userSelect","none");return i.createElement(w.m,{className:m,onMouseLeave:this.handleLeaveWrapper,onTouchMove:this.handleTouchMove,style:x},this.renderBackground(),g&&this.renderPanorama(),this.renderSlide(f,p),this.renderTravellerLayer(f,"startX"),this.renderTravellerLayer(p,"endX"),(h||d||y||v||l)&&this.renderText())}}],r=[{key:"renderDefaultTraveller",value:function(t){var e=t.x,r=t.y,n=t.width,o=t.height,a=t.stroke,u=Math.floor(r+o/2)-1;return i.createElement(i.Fragment,null,i.createElement("rect",{x:e,y:r,width:n,height:o,fill:a,stroke:"none"}),i.createElement("line",{x1:e+1,y1:u,x2:e+n-1,y2:u,fill:"none",stroke:"#fff"}),i.createElement("line",{x1:e+1,y1:u+2,x2:e+n-1,y2:u+2,fill:"none",stroke:"#fff"}))}},{key:"renderTraveller",value:function(t,e){return i.isValidElement(t)?i.cloneElement(t,e):l()(t)?t(e):n.renderDefaultTraveller(e)}},{key:"getDerivedStateFromProps",value:function(t,e){var r=t.data,n=t.width,o=t.x,i=t.travellerWidth,a=t.updateId,u=t.startIndex,c=t.endIndex;if(r!==e.prevData||a!==e.prevUpdateId)return U({prevData:r,prevTravellerWidth:i,prevUpdateId:a,prevX:o,prevWidth:n},r&&r.length?H({data:r,width:n,x:o,travellerWidth:i,startIndex:u,endIndex:c}):{scale:null,scaleValues:null});if(e.scale&&(n!==e.prevWidth||o!==e.prevX||i!==e.prevTravellerWidth)){e.scale.range([o,o+n-i]);var l=e.scale.domain().map(function(t){return e.scale(t)});return{prevData:r,prevTravellerWidth:i,prevUpdateId:a,prevX:o,prevWidth:n,startX:e.scale(t.startIndex),endX:e.scale(t.endIndex),scaleValues:l}}return null}},{key:"getIndexInRange",value:function(t,e){for(var r=t.length,n=0,o=r-1;o-n>1;){var i=Math.floor((n+o)/2);t[i]>e?o=i:n=i}return e>=t[o]?o:n}}],e&&F(n.prototype,e),r&&F(n,r),Object.defineProperty(n,"prototype",{writable:!1}),n}(i.PureComponent);W(G,"displayName","Brush"),W(G,"defaultProps",{height:40,travellerWidth:5,gap:1,fill:"#fff",stroke:"#666",padding:{top:1,right:1,bottom:1,left:1},leaveTimeOut:1e3,alwaysShowText:!1});var V=r(4094),K=r(38569),Q=r(26680),J=function(t,e){var r=t.alwaysShow,n=t.ifOverflow;return r&&(n="extendDomain"),n===e},tt=r(25311),te=r(1175);function tr(){return(tr=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);rt.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,t2));return(0,_.hj)(r)&&(0,_.hj)(o)&&(0,_.hj)(f)&&(0,_.hj)(h)&&(0,_.hj)(u)&&(0,_.hj)(l)?i.createElement("path",t5({},(0,E.L6)(y,!0),{className:(0,b.Z)("recharts-cross",d),d:"M".concat(r,",").concat(u,"v").concat(h,"M").concat(l,",").concat(o,"h").concat(f)})):null};function t7(t){var e=t.cx,r=t.cy,n=t.radius,o=t.startAngle,i=t.endAngle;return{points:[(0,tq.op)(e,r,n,o),(0,tq.op)(e,r,n,i)],cx:e,cy:r,radius:n,startAngle:o,endAngle:i}}var t8=r(60474);function t4(t){return(t4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function t9(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function et(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function ec(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(ec=function(){return!!t})()}function el(t){return(el=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function es(t,e){return(es=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function ef(t){return function(t){if(Array.isArray(t))return eh(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||ep(t)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function ep(t,e){if(t){if("string"==typeof t)return eh(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return eh(t,e)}}function eh(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r0?i:t&&t.length&&(0,_.hj)(n)&&(0,_.hj)(o)?t.slice(n,o+1):[]};function eS(t){return"number"===t?[0,"auto"]:void 0}var eP=function(t,e,r,n){var o=t.graphicalItems,i=t.tooltipAxis,a=ej(e,t);return r<0||!o||!o.length||r>=a.length?null:o.reduce(function(o,u){var c,l,s=null!==(c=u.props.data)&&void 0!==c?c:e;if(s&&t.dataStartIndex+t.dataEndIndex!==0&&t.dataEndIndex-t.dataStartIndex>=r&&(s=s.slice(t.dataStartIndex,t.dataEndIndex+1)),i.dataKey&&!i.allowDuplicatedCategory){var f=void 0===s?a:s;l=(0,_.Ap)(f,i.dataKey,n)}else l=s&&s[r]||a[r];return l?[].concat(ef(o),[(0,M.Qo)(u,l)]):o},[])},eE=function(t,e,r,n){var o=n||{x:t.chartX,y:t.chartY},i="horizontal"===r?o.x:"vertical"===r?o.y:"centric"===r?o.angle:o.radius,a=t.orderedTooltipTicks,u=t.tooltipAxis,c=t.tooltipTicks,l=(0,M.VO)(i,a,c,u);if(l>=0&&c){var s=c[l]&&c[l].value,f=eP(t,e,l,s),p=eO(r,a,l,o);return{activeTooltipIndex:l,activeLabel:s,activePayload:f,activeCoordinate:p}}return null},ek=function(t,e){var r=e.axes,n=e.graphicalItems,o=e.axisType,i=e.axisIdKey,a=e.stackGroups,c=e.dataStartIndex,l=e.dataEndIndex,s=t.layout,p=t.children,h=t.stackOffset,d=(0,M.NA)(s,o);return r.reduce(function(e,r){var y=void 0!==r.type.defaultProps?ey(ey({},r.type.defaultProps),r.props):r.props,v=y.type,m=y.dataKey,b=y.allowDataOverflow,g=y.allowDuplicatedCategory,x=y.scale,w=y.ticks,O=y.includeHidden,j=y[i];if(e[j])return e;var S=ej(t.data,{graphicalItems:n.filter(function(t){var e;return(i in t.props?t.props[i]:null===(e=t.type.defaultProps)||void 0===e?void 0:e[i])===j}),dataStartIndex:c,dataEndIndex:l}),P=S.length;(function(t,e,r){if("number"===r&&!0===e&&Array.isArray(t)){var n=null==t?void 0:t[0],o=null==t?void 0:t[1];if(n&&o&&(0,_.hj)(n)&&(0,_.hj)(o))return!0}return!1})(y.domain,b,v)&&(A=(0,M.LG)(y.domain,null,b),d&&("number"===v||"auto"!==x)&&(C=(0,M.gF)(S,m,"category")));var E=eS(v);if(!A||0===A.length){var k,A,T,C,N,D=null!==(N=y.domain)&&void 0!==N?N:E;if(m){if(A=(0,M.gF)(S,m,v),"category"===v&&d){var I=(0,_.bv)(A);g&&I?(T=A,A=f()(0,P)):g||(A=(0,M.ko)(D,A,r).reduce(function(t,e){return t.indexOf(e)>=0?t:[].concat(ef(t),[e])},[]))}else if("category"===v)A=g?A.filter(function(t){return""!==t&&!u()(t)}):(0,M.ko)(D,A,r).reduce(function(t,e){return t.indexOf(e)>=0||""===e||u()(e)?t:[].concat(ef(t),[e])},[]);else if("number"===v){var L=(0,M.ZI)(S,n.filter(function(t){var e,r,n=i in t.props?t.props[i]:null===(e=t.type.defaultProps)||void 0===e?void 0:e[i],o="hide"in t.props?t.props.hide:null===(r=t.type.defaultProps)||void 0===r?void 0:r.hide;return n===j&&(O||!o)}),m,o,s);L&&(A=L)}d&&("number"===v||"auto"!==x)&&(C=(0,M.gF)(S,m,"category"))}else A=d?f()(0,P):a&&a[j]&&a[j].hasStack&&"number"===v?"expand"===h?[0,1]:(0,M.EB)(a[j].stackGroups,c,l):(0,M.s6)(S,n.filter(function(t){var e=i in t.props?t.props[i]:t.type.defaultProps[i],r="hide"in t.props?t.props.hide:t.type.defaultProps.hide;return e===j&&(O||!r)}),v,s,!0);"number"===v?(A=t$(p,A,j,o,w),D&&(A=(0,M.LG)(D,A,b))):"category"===v&&D&&A.every(function(t){return D.indexOf(t)>=0})&&(A=D)}return ey(ey({},e),{},ev({},j,ey(ey({},y),{},{axisType:o,domain:A,categoricalDomain:C,duplicateDomain:T,originalDomain:null!==(k=y.domain)&&void 0!==k?k:E,isCategorical:d,layout:s})))},{})},eA=function(t,e){var r=e.graphicalItems,n=e.Axis,o=e.axisType,i=e.axisIdKey,a=e.stackGroups,u=e.dataStartIndex,c=e.dataEndIndex,l=t.layout,s=t.children,p=ej(t.data,{graphicalItems:r,dataStartIndex:u,dataEndIndex:c}),d=p.length,y=(0,M.NA)(l,o),v=-1;return r.reduce(function(t,e){var m,b=(void 0!==e.type.defaultProps?ey(ey({},e.type.defaultProps),e.props):e.props)[i],g=eS("number");return t[b]?t:(v++,m=y?f()(0,d):a&&a[b]&&a[b].hasStack?t$(s,m=(0,M.EB)(a[b].stackGroups,u,c),b,o):t$(s,m=(0,M.LG)(g,(0,M.s6)(p,r.filter(function(t){var e,r,n=i in t.props?t.props[i]:null===(e=t.type.defaultProps)||void 0===e?void 0:e[i],o="hide"in t.props?t.props.hide:null===(r=t.type.defaultProps)||void 0===r?void 0:r.hide;return n===b&&!o}),"number",l),n.defaultProps.allowDataOverflow),b,o),ey(ey({},t),{},ev({},b,ey(ey({axisType:o},n.defaultProps),{},{hide:!0,orientation:h()(eb,"".concat(o,".").concat(v%2),null),domain:m,originalDomain:g,isCategorical:y,layout:l}))))},{})},eM=function(t,e){var r=e.axisType,n=void 0===r?"xAxis":r,o=e.AxisComp,i=e.graphicalItems,a=e.stackGroups,u=e.dataStartIndex,c=e.dataEndIndex,l=t.children,s="".concat(n,"Id"),f=(0,E.NN)(l,o),p={};return f&&f.length?p=ek(t,{axes:f,graphicalItems:i,axisType:n,axisIdKey:s,stackGroups:a,dataStartIndex:u,dataEndIndex:c}):i&&i.length&&(p=eA(t,{Axis:o,graphicalItems:i,axisType:n,axisIdKey:s,stackGroups:a,dataStartIndex:u,dataEndIndex:c})),p},e_=function(t){var e=(0,_.Kt)(t),r=(0,M.uY)(e,!1,!0);return{tooltipTicks:r,orderedTooltipTicks:y()(r,function(t){return t.coordinate}),tooltipAxis:e,tooltipAxisBandSize:(0,M.zT)(e,r)}},eT=function(t){var e=t.children,r=t.defaultShowTooltip,n=(0,E.sP)(e,G),o=0,i=0;return t.data&&0!==t.data.length&&(i=t.data.length-1),n&&n.props&&(n.props.startIndex>=0&&(o=n.props.startIndex),n.props.endIndex>=0&&(i=n.props.endIndex)),{chartX:0,chartY:0,dataStartIndex:o,dataEndIndex:i,activeTooltipIndex:-1,isTooltipActive:!!r}},eC=function(t){return"horizontal"===t?{numericAxisName:"yAxis",cateAxisName:"xAxis"}:"vertical"===t?{numericAxisName:"xAxis",cateAxisName:"yAxis"}:"centric"===t?{numericAxisName:"radiusAxis",cateAxisName:"angleAxis"}:{numericAxisName:"angleAxis",cateAxisName:"radiusAxis"}},eN=function(t,e){var r=t.props,n=t.graphicalItems,o=t.xAxisMap,i=void 0===o?{}:o,a=t.yAxisMap,u=void 0===a?{}:a,c=r.width,l=r.height,s=r.children,f=r.margin||{},p=(0,E.sP)(s,G),d=(0,E.sP)(s,j.D),y=Object.keys(u).reduce(function(t,e){var r=u[e],n=r.orientation;return r.mirror||r.hide?t:ey(ey({},t),{},ev({},n,t[n]+r.width))},{left:f.left||0,right:f.right||0}),v=Object.keys(i).reduce(function(t,e){var r=i[e],n=r.orientation;return r.mirror||r.hide?t:ey(ey({},t),{},ev({},n,h()(t,"".concat(n))+r.height))},{top:f.top||0,bottom:f.bottom||0}),m=ey(ey({},v),y),b=m.bottom;p&&(m.bottom+=p.props.height||G.defaultProps.height),d&&e&&(m=(0,M.By)(m,n,r,e));var g=c-m.left-m.right,x=l-m.top-m.bottom;return ey(ey({brushBottom:b},m),{},{width:Math.max(g,0),height:Math.max(x,0)})},eD=function(t){var e=t.chartName,r=t.GraphicalChild,n=t.defaultTooltipEventType,o=void 0===n?"axis":n,a=t.validateTooltipEventTypes,c=void 0===a?["axis"]:a,s=t.axisComponents,f=t.legendContent,p=t.formatAxisMap,d=t.defaultProps,y=function(t,e){var r=e.graphicalItems,n=e.stackGroups,o=e.offset,i=e.updateId,a=e.dataStartIndex,c=e.dataEndIndex,l=t.barSize,f=t.layout,p=t.barGap,h=t.barCategoryGap,d=t.maxBarSize,y=eC(f),v=y.numericAxisName,m=y.cateAxisName,b=!!r&&!!r.length&&r.some(function(t){var e=(0,E.Gf)(t&&t.type);return e&&e.indexOf("Bar")>=0}),x=[];return r.forEach(function(r,y){var w=ej(t.data,{graphicalItems:[r],dataStartIndex:a,dataEndIndex:c}),O=void 0!==r.type.defaultProps?ey(ey({},r.type.defaultProps),r.props):r.props,j=O.dataKey,S=O.maxBarSize,P=O["".concat(v,"Id")],k=O["".concat(m,"Id")],A=s.reduce(function(t,r){var n=e["".concat(r.axisType,"Map")],o=O["".concat(r.axisType,"Id")];n&&n[o]||"zAxis"===r.axisType||(0,g.Z)(!1);var i=n[o];return ey(ey({},t),{},ev(ev({},r.axisType,i),"".concat(r.axisType,"Ticks"),(0,M.uY)(i)))},{}),_=A[m],T=A["".concat(m,"Ticks")],C=n&&n[P]&&n[P].hasStack&&(0,M.O3)(r,n[P].stackGroups),N=(0,E.Gf)(r.type).indexOf("Bar")>=0,D=(0,M.zT)(_,T),I=[],L=b&&(0,M.pt)({barSize:l,stackGroups:n,totalSize:"xAxis"===m?A[m].width:"yAxis"===m?A[m].height:void 0});if(N){var B,R,z=u()(S)?d:S,U=null!==(B=null!==(R=(0,M.zT)(_,T,!0))&&void 0!==R?R:z)&&void 0!==B?B:0;I=(0,M.qz)({barGap:p,barCategoryGap:h,bandSize:U!==D?U:D,sizeList:L[k],maxBarSize:z}),U!==D&&(I=I.map(function(t){return ey(ey({},t),{},{position:ey(ey({},t.position),{},{offset:t.position.offset-U/2})})}))}var F=r&&r.type&&r.type.getComposedData;F&&x.push({props:ey(ey({},F(ey(ey({},A),{},{displayedData:w,props:t,dataKey:j,item:r,bandSize:D,barPosition:I,offset:o,stackedData:C,layout:f,dataStartIndex:a,dataEndIndex:c}))),{},ev(ev(ev({key:r.key||"item-".concat(y)},v,A[v]),m,A[m]),"animationId",i)),childIndex:(0,E.$R)(r,t.children),item:r})}),x},v=function(t,n){var o=t.props,i=t.dataStartIndex,a=t.dataEndIndex,u=t.updateId;if(!(0,E.TT)({props:o}))return null;var c=o.children,l=o.layout,f=o.stackOffset,h=o.data,d=o.reverseStackOrder,v=eC(l),m=v.numericAxisName,b=v.cateAxisName,g=(0,E.NN)(c,r),x=(0,M.wh)(h,g,"".concat(m,"Id"),"".concat(b,"Id"),f,d),w=s.reduce(function(t,e){var r="".concat(e.axisType,"Map");return ey(ey({},t),{},ev({},r,eM(o,ey(ey({},e),{},{graphicalItems:g,stackGroups:e.axisType===m&&x,dataStartIndex:i,dataEndIndex:a}))))},{}),O=eN(ey(ey({},w),{},{props:o,graphicalItems:g}),null==n?void 0:n.legendBBox);Object.keys(w).forEach(function(t){w[t]=p(o,w[t],O,t.replace("Map",""),e)});var j=e_(w["".concat(b,"Map")]),S=y(o,ey(ey({},w),{},{dataStartIndex:i,dataEndIndex:a,updateId:u,graphicalItems:g,stackGroups:x,offset:O}));return ey(ey({formattedGraphicalItems:S,graphicalItems:g,offset:O,stackGroups:x},j),w)},j=function(t){var r;function n(t){var r,o,a,c,s;return!function(t,e){if(!(t instanceof e))throw TypeError("Cannot call a class as a function")}(this,n),c=n,s=[t],c=el(c),ev(a=function(t,e){if(e&&("object"===eo(e)||"function"==typeof e))return e;if(void 0!==e)throw TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t)}(this,ec()?Reflect.construct(c,s||[],el(this).constructor):c.apply(this,s)),"eventEmitterSymbol",Symbol("rechartsEventEmitter")),ev(a,"accessibilityManager",new tQ),ev(a,"handleLegendBBoxUpdate",function(t){if(t){var e=a.state,r=e.dataStartIndex,n=e.dataEndIndex,o=e.updateId;a.setState(ey({legendBBox:t},v({props:a.props,dataStartIndex:r,dataEndIndex:n,updateId:o},ey(ey({},a.state),{},{legendBBox:t}))))}}),ev(a,"handleReceiveSyncEvent",function(t,e,r){a.props.syncId===t&&(r!==a.eventEmitterSymbol||"function"==typeof a.props.syncMethod)&&a.applySyncEvent(e)}),ev(a,"handleBrushChange",function(t){var e=t.startIndex,r=t.endIndex;if(e!==a.state.dataStartIndex||r!==a.state.dataEndIndex){var n=a.state.updateId;a.setState(function(){return ey({dataStartIndex:e,dataEndIndex:r},v({props:a.props,dataStartIndex:e,dataEndIndex:r,updateId:n},a.state))}),a.triggerSyncEvent({dataStartIndex:e,dataEndIndex:r})}}),ev(a,"handleMouseEnter",function(t){var e=a.getMouseInfo(t);if(e){var r=ey(ey({},e),{},{isTooltipActive:!0});a.setState(r),a.triggerSyncEvent(r);var n=a.props.onMouseEnter;l()(n)&&n(r,t)}}),ev(a,"triggeredAfterMouseMove",function(t){var e=a.getMouseInfo(t),r=e?ey(ey({},e),{},{isTooltipActive:!0}):{isTooltipActive:!1};a.setState(r),a.triggerSyncEvent(r);var n=a.props.onMouseMove;l()(n)&&n(r,t)}),ev(a,"handleItemMouseEnter",function(t){a.setState(function(){return{isTooltipActive:!0,activeItem:t,activePayload:t.tooltipPayload,activeCoordinate:t.tooltipPosition||{x:t.cx,y:t.cy}}})}),ev(a,"handleItemMouseLeave",function(){a.setState(function(){return{isTooltipActive:!1}})}),ev(a,"handleMouseMove",function(t){t.persist(),a.throttleTriggeredAfterMouseMove(t)}),ev(a,"handleMouseLeave",function(t){a.throttleTriggeredAfterMouseMove.cancel();var e={isTooltipActive:!1};a.setState(e),a.triggerSyncEvent(e);var r=a.props.onMouseLeave;l()(r)&&r(e,t)}),ev(a,"handleOuterEvent",function(t){var e,r=(0,E.Bh)(t),n=h()(a.props,"".concat(r));r&&l()(n)&&n(null!==(e=/.*touch.*/i.test(r)?a.getMouseInfo(t.changedTouches[0]):a.getMouseInfo(t))&&void 0!==e?e:{},t)}),ev(a,"handleClick",function(t){var e=a.getMouseInfo(t);if(e){var r=ey(ey({},e),{},{isTooltipActive:!0});a.setState(r),a.triggerSyncEvent(r);var n=a.props.onClick;l()(n)&&n(r,t)}}),ev(a,"handleMouseDown",function(t){var e=a.props.onMouseDown;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"handleMouseUp",function(t){var e=a.props.onMouseUp;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"handleTouchMove",function(t){null!=t.changedTouches&&t.changedTouches.length>0&&a.throttleTriggeredAfterMouseMove(t.changedTouches[0])}),ev(a,"handleTouchStart",function(t){null!=t.changedTouches&&t.changedTouches.length>0&&a.handleMouseDown(t.changedTouches[0])}),ev(a,"handleTouchEnd",function(t){null!=t.changedTouches&&t.changedTouches.length>0&&a.handleMouseUp(t.changedTouches[0])}),ev(a,"handleDoubleClick",function(t){var e=a.props.onDoubleClick;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"handleContextMenu",function(t){var e=a.props.onContextMenu;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"triggerSyncEvent",function(t){void 0!==a.props.syncId&&tY.emit(tH,a.props.syncId,t,a.eventEmitterSymbol)}),ev(a,"applySyncEvent",function(t){var e=a.props,r=e.layout,n=e.syncMethod,o=a.state.updateId,i=t.dataStartIndex,u=t.dataEndIndex;if(void 0!==t.dataStartIndex||void 0!==t.dataEndIndex)a.setState(ey({dataStartIndex:i,dataEndIndex:u},v({props:a.props,dataStartIndex:i,dataEndIndex:u,updateId:o},a.state)));else if(void 0!==t.activeTooltipIndex){var c=t.chartX,l=t.chartY,s=t.activeTooltipIndex,f=a.state,p=f.offset,h=f.tooltipTicks;if(!p)return;if("function"==typeof n)s=n(h,t);else if("value"===n){s=-1;for(var d=0;d=0){if(s.dataKey&&!s.allowDuplicatedCategory){var A="function"==typeof s.dataKey?function(t){return"function"==typeof s.dataKey?s.dataKey(t.payload):null}:"payload.".concat(s.dataKey.toString());C=(0,_.Ap)(v,A,p),N=m&&b&&(0,_.Ap)(b,A,p)}else C=null==v?void 0:v[f],N=m&&b&&b[f];if(S||j){var T=void 0!==t.props.activeIndex?t.props.activeIndex:f;return[(0,i.cloneElement)(t,ey(ey(ey({},n.props),P),{},{activeIndex:T})),null,null]}if(!u()(C))return[k].concat(ef(a.renderActivePoints({item:n,activePoint:C,basePoint:N,childIndex:f,isRange:m})))}else{var C,N,D,I=(null!==(D=a.getItemByXY(a.state.activeCoordinate))&&void 0!==D?D:{graphicalItem:k}).graphicalItem,L=I.item,B=void 0===L?t:L,R=I.childIndex,z=ey(ey(ey({},n.props),P),{},{activeIndex:R});return[(0,i.cloneElement)(B,z),null,null]}}return m?[k,null,null]:[k,null]}),ev(a,"renderCustomized",function(t,e,r){return(0,i.cloneElement)(t,ey(ey({key:"recharts-customized-".concat(r)},a.props),a.state))}),ev(a,"renderMap",{CartesianGrid:{handler:ew,once:!0},ReferenceArea:{handler:a.renderReferenceElement},ReferenceLine:{handler:ew},ReferenceDot:{handler:a.renderReferenceElement},XAxis:{handler:ew},YAxis:{handler:ew},Brush:{handler:a.renderBrush,once:!0},Bar:{handler:a.renderGraphicChild},Line:{handler:a.renderGraphicChild},Area:{handler:a.renderGraphicChild},Radar:{handler:a.renderGraphicChild},RadialBar:{handler:a.renderGraphicChild},Scatter:{handler:a.renderGraphicChild},Pie:{handler:a.renderGraphicChild},Funnel:{handler:a.renderGraphicChild},Tooltip:{handler:a.renderCursor,once:!0},PolarGrid:{handler:a.renderPolarGrid,once:!0},PolarAngleAxis:{handler:a.renderPolarAxis},PolarRadiusAxis:{handler:a.renderPolarAxis},Customized:{handler:a.renderCustomized}}),a.clipPathId="".concat(null!==(r=t.id)&&void 0!==r?r:(0,_.EL)("recharts"),"-clip"),a.throttleTriggeredAfterMouseMove=m()(a.triggeredAfterMouseMove,null!==(o=t.throttleDelay)&&void 0!==o?o:1e3/60),a.state={},a}return!function(t,e){if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&es(t,e)}(n,t),r=[{key:"componentDidMount",value:function(){var t,e;this.addListener(),this.accessibilityManager.setDetails({container:this.container,offset:{left:null!==(t=this.props.margin.left)&&void 0!==t?t:0,top:null!==(e=this.props.margin.top)&&void 0!==e?e:0},coordinateList:this.state.tooltipTicks,mouseHandlerCallback:this.triggeredAfterMouseMove,layout:this.props.layout}),this.displayDefaultTooltip()}},{key:"displayDefaultTooltip",value:function(){var t=this.props,e=t.children,r=t.data,n=t.height,o=t.layout,i=(0,E.sP)(e,O.u);if(i){var a=i.props.defaultIndex;if("number"==typeof a&&!(a<0)&&!(a>this.state.tooltipTicks.length-1)){var u=this.state.tooltipTicks[a]&&this.state.tooltipTicks[a].value,c=eP(this.state,r,a,u),l=this.state.tooltipTicks[a].coordinate,s=(this.state.offset.top+n)/2,f="horizontal"===o?{x:l,y:s}:{y:l,x:s},p=this.state.formattedGraphicalItems.find(function(t){return"Scatter"===t.item.type.name});p&&(f=ey(ey({},f),p.props.points[a].tooltipPosition),c=p.props.points[a].tooltipPayload);var h={activeTooltipIndex:a,isTooltipActive:!0,activeLabel:u,activePayload:c,activeCoordinate:f};this.setState(h),this.renderCursor(i),this.accessibilityManager.setIndex(a)}}}},{key:"getSnapshotBeforeUpdate",value:function(t,e){if(!this.props.accessibilityLayer)return null;if(this.state.tooltipTicks!==e.tooltipTicks&&this.accessibilityManager.setDetails({coordinateList:this.state.tooltipTicks}),this.props.layout!==t.layout&&this.accessibilityManager.setDetails({layout:this.props.layout}),this.props.margin!==t.margin){var r,n;this.accessibilityManager.setDetails({offset:{left:null!==(r=this.props.margin.left)&&void 0!==r?r:0,top:null!==(n=this.props.margin.top)&&void 0!==n?n:0}})}return null}},{key:"componentDidUpdate",value:function(t){(0,E.rL)([(0,E.sP)(t.children,O.u)],[(0,E.sP)(this.props.children,O.u)])||this.displayDefaultTooltip()}},{key:"componentWillUnmount",value:function(){this.removeListener(),this.throttleTriggeredAfterMouseMove.cancel()}},{key:"getTooltipEventType",value:function(){var t=(0,E.sP)(this.props.children,O.u);if(t&&"boolean"==typeof t.props.shared){var e=t.props.shared?"axis":"item";return c.indexOf(e)>=0?e:o}return o}},{key:"getMouseInfo",value:function(t){if(!this.container)return null;var e=this.container,r=e.getBoundingClientRect(),n=(0,V.os)(r),o={chartX:Math.round(t.pageX-n.left),chartY:Math.round(t.pageY-n.top)},i=r.width/e.offsetWidth||1,a=this.inRange(o.chartX,o.chartY,i);if(!a)return null;var u=this.state,c=u.xAxisMap,l=u.yAxisMap,s=this.getTooltipEventType(),f=eE(this.state,this.props.data,this.props.layout,a);if("axis"!==s&&c&&l){var p=(0,_.Kt)(c).scale,h=(0,_.Kt)(l).scale,d=p&&p.invert?p.invert(o.chartX):null,y=h&&h.invert?h.invert(o.chartY):null;return ey(ey({},o),{},{xValue:d,yValue:y},f)}return f?ey(ey({},o),f):null}},{key:"inRange",value:function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,n=this.props.layout,o=t/r,i=e/r;if("horizontal"===n||"vertical"===n){var a=this.state.offset;return o>=a.left&&o<=a.left+a.width&&i>=a.top&&i<=a.top+a.height?{x:o,y:i}:null}var u=this.state,c=u.angleAxisMap,l=u.radiusAxisMap;if(c&&l){var s=(0,_.Kt)(c);return(0,tq.z3)({x:o,y:i},s)}return null}},{key:"parseEventsOfWrapper",value:function(){var t=this.props.children,e=this.getTooltipEventType(),r=(0,E.sP)(t,O.u),n={};return r&&"axis"===e&&(n="click"===r.props.trigger?{onClick:this.handleClick}:{onMouseEnter:this.handleMouseEnter,onDoubleClick:this.handleDoubleClick,onMouseMove:this.handleMouseMove,onMouseLeave:this.handleMouseLeave,onTouchMove:this.handleTouchMove,onTouchStart:this.handleTouchStart,onTouchEnd:this.handleTouchEnd,onContextMenu:this.handleContextMenu}),ey(ey({},(0,tX.Ym)(this.props,this.handleOuterEvent)),n)}},{key:"addListener",value:function(){tY.on(tH,this.handleReceiveSyncEvent)}},{key:"removeListener",value:function(){tY.removeListener(tH,this.handleReceiveSyncEvent)}},{key:"filterFormatItem",value:function(t,e,r){for(var n=this.state.formattedGraphicalItems,o=0,i=n.length;ot.length)&&(e=t.length);for(var r=0,n=Array(e);r=0?1:-1;"insideStart"===u?(o=b+S*l,a=w):"insideEnd"===u?(o=g-S*l,a=!w):"end"===u&&(o=g+S*l,a=w),a=j<=0?a:!a;var P=(0,d.op)(p,y,O,o),E=(0,d.op)(p,y,O,o+(a?1:-1)*359),k="M".concat(P.x,",").concat(P.y,"\n A").concat(O,",").concat(O,",0,1,").concat(a?0:1,",\n ").concat(E.x,",").concat(E.y),A=i()(t.id)?(0,h.EL)("recharts-radial-line-"):t.id;return n.createElement("text",x({},r,{dominantBaseline:"central",className:(0,s.Z)("recharts-radial-bar-label",f)}),n.createElement("defs",null,n.createElement("path",{id:A,d:k})),n.createElement("textPath",{xlinkHref:"#".concat(A)},e))},j=function(t){var e=t.viewBox,r=t.offset,n=t.position,o=e.cx,i=e.cy,a=e.innerRadius,u=e.outerRadius,c=(e.startAngle+e.endAngle)/2;if("outside"===n){var l=(0,d.op)(o,i,u+r,c),s=l.x;return{x:s,y:l.y,textAnchor:s>=o?"start":"end",verticalAnchor:"middle"}}if("center"===n)return{x:o,y:i,textAnchor:"middle",verticalAnchor:"middle"};if("centerTop"===n)return{x:o,y:i,textAnchor:"middle",verticalAnchor:"start"};if("centerBottom"===n)return{x:o,y:i,textAnchor:"middle",verticalAnchor:"end"};var f=(0,d.op)(o,i,(a+u)/2,c);return{x:f.x,y:f.y,textAnchor:"middle",verticalAnchor:"middle"}},S=function(t){var e=t.viewBox,r=t.parentViewBox,n=t.offset,o=t.position,i=e.x,a=e.y,u=e.width,c=e.height,s=c>=0?1:-1,f=s*n,p=s>0?"end":"start",d=s>0?"start":"end",y=u>=0?1:-1,v=y*n,m=y>0?"end":"start",b=y>0?"start":"end";if("top"===o)return g(g({},{x:i+u/2,y:a-s*n,textAnchor:"middle",verticalAnchor:p}),r?{height:Math.max(a-r.y,0),width:u}:{});if("bottom"===o)return g(g({},{x:i+u/2,y:a+c+f,textAnchor:"middle",verticalAnchor:d}),r?{height:Math.max(r.y+r.height-(a+c),0),width:u}:{});if("left"===o){var x={x:i-v,y:a+c/2,textAnchor:m,verticalAnchor:"middle"};return g(g({},x),r?{width:Math.max(x.x-r.x,0),height:c}:{})}if("right"===o){var w={x:i+u+v,y:a+c/2,textAnchor:b,verticalAnchor:"middle"};return g(g({},w),r?{width:Math.max(r.x+r.width-w.x,0),height:c}:{})}var O=r?{width:u,height:c}:{};return"insideLeft"===o?g({x:i+v,y:a+c/2,textAnchor:b,verticalAnchor:"middle"},O):"insideRight"===o?g({x:i+u-v,y:a+c/2,textAnchor:m,verticalAnchor:"middle"},O):"insideTop"===o?g({x:i+u/2,y:a+f,textAnchor:"middle",verticalAnchor:d},O):"insideBottom"===o?g({x:i+u/2,y:a+c-f,textAnchor:"middle",verticalAnchor:p},O):"insideTopLeft"===o?g({x:i+v,y:a+f,textAnchor:b,verticalAnchor:d},O):"insideTopRight"===o?g({x:i+u-v,y:a+f,textAnchor:m,verticalAnchor:d},O):"insideBottomLeft"===o?g({x:i+v,y:a+c-f,textAnchor:b,verticalAnchor:p},O):"insideBottomRight"===o?g({x:i+u-v,y:a+c-f,textAnchor:m,verticalAnchor:p},O):l()(o)&&((0,h.hj)(o.x)||(0,h.hU)(o.x))&&((0,h.hj)(o.y)||(0,h.hU)(o.y))?g({x:i+(0,h.h1)(o.x,u),y:a+(0,h.h1)(o.y,c),textAnchor:"end",verticalAnchor:"end"},O):g({x:i+u/2,y:a+c/2,textAnchor:"middle",verticalAnchor:"middle"},O)};function P(t){var e,r=t.offset,o=g({offset:void 0===r?5:r},function(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r={};for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){if(e.indexOf(n)>=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,v)),a=o.viewBox,c=o.position,l=o.value,d=o.children,y=o.content,m=o.className,b=o.textBreakAll;if(!a||i()(l)&&i()(d)&&!(0,n.isValidElement)(y)&&!u()(y))return null;if((0,n.isValidElement)(y))return(0,n.cloneElement)(y,o);if(u()(y)){if(e=(0,n.createElement)(y,o),(0,n.isValidElement)(e))return e}else e=w(o);var P="cx"in a&&(0,h.hj)(a.cx),E=(0,p.L6)(o,!0);if(P&&("insideStart"===c||"insideEnd"===c||"end"===c))return O(o,e,E);var k=P?j(o):S(o);return n.createElement(f.x,x({className:(0,s.Z)("recharts-label",void 0===m?"":m)},E,k,{breakAll:b}),e)}P.displayName="Label";var E=function(t){var e=t.cx,r=t.cy,n=t.angle,o=t.startAngle,i=t.endAngle,a=t.r,u=t.radius,c=t.innerRadius,l=t.outerRadius,s=t.x,f=t.y,p=t.top,d=t.left,y=t.width,v=t.height,m=t.clockWise,b=t.labelViewBox;if(b)return b;if((0,h.hj)(y)&&(0,h.hj)(v)){if((0,h.hj)(s)&&(0,h.hj)(f))return{x:s,y:f,width:y,height:v};if((0,h.hj)(p)&&(0,h.hj)(d))return{x:p,y:d,width:y,height:v}}return(0,h.hj)(s)&&(0,h.hj)(f)?{x:s,y:f,width:0,height:0}:(0,h.hj)(e)&&(0,h.hj)(r)?{cx:e,cy:r,startAngle:o||n||0,endAngle:i||n||0,innerRadius:c||0,outerRadius:l||u||a||0,clockWise:m}:t.viewBox?t.viewBox:{}};P.parseViewBox=E,P.renderCallByParent=function(t,e){var r,o,i=!(arguments.length>2)||void 0===arguments[2]||arguments[2];if(!t||!t.children&&i&&!t.label)return null;var a=t.children,c=E(t),s=(0,p.NN)(a,P).map(function(t,r){return(0,n.cloneElement)(t,{viewBox:e||c,key:"label-".concat(r)})});return i?[(r=t.label,o=e||c,r?!0===r?n.createElement(P,{key:"label-implicit",viewBox:o}):(0,h.P2)(r)?n.createElement(P,{key:"label-implicit",viewBox:o,value:r}):(0,n.isValidElement)(r)?r.type===P?(0,n.cloneElement)(r,{key:"label-implicit",viewBox:o}):n.createElement(P,{key:"label-implicit",content:r,viewBox:o}):u()(r)?n.createElement(P,{key:"label-implicit",content:r,viewBox:o}):l()(r)?n.createElement(P,x({viewBox:o},r,{key:"label-implicit"})):null:null)].concat(function(t){if(Array.isArray(t))return m(t)}(s)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(s)||function(t,e){if(t){if("string"==typeof t)return m(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return m(t,void 0)}}(s)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()):s}},58772:function(t,e,r){"use strict";r.d(e,{e:function(){return P}});var n=r(2265),o=r(77571),i=r.n(o),a=r(28302),u=r.n(a),c=r(86757),l=r.n(c),s=r(86185),f=r.n(s),p=r(26680),h=r(9841),d=r(82944),y=r(85355);function v(t){return(v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var m=["valueAccessor"],b=["data","dataKey","clockWise","id","textBreakAll"];function g(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}var S=function(t){return Array.isArray(t.value)?f()(t.value):t.value};function P(t){var e=t.valueAccessor,r=void 0===e?S:e,o=j(t,m),a=o.data,u=o.dataKey,c=o.clockWise,l=o.id,s=o.textBreakAll,f=j(o,b);return a&&a.length?n.createElement(h.m,{className:"recharts-label-list"},a.map(function(t,e){var o=i()(u)?r(t,e):(0,y.F$)(t&&t.payload,u),a=i()(l)?{}:{id:"".concat(l,"-").concat(e)};return n.createElement(p._,x({},(0,d.L6)(t,!0),f,a,{parentViewBox:t.parentViewBox,value:o,textBreakAll:s,viewBox:p._.parseViewBox(i()(c)?t:O(O({},t),{},{clockWise:c})),key:"label-".concat(e),index:e}))})):null}P.displayName="LabelList",P.renderCallByParent=function(t,e){var r,o=!(arguments.length>2)||void 0===arguments[2]||arguments[2];if(!t||!t.children&&o&&!t.label)return null;var i=t.children,a=(0,d.NN)(i,P).map(function(t,r){return(0,n.cloneElement)(t,{data:e,key:"labelList-".concat(r)})});return o?[(r=t.label)?!0===r?n.createElement(P,{key:"labelList-implicit",data:e}):n.isValidElement(r)||l()(r)?n.createElement(P,{key:"labelList-implicit",data:e,content:r}):u()(r)?n.createElement(P,x({data:e},r,{key:"labelList-implicit"})):null:null].concat(function(t){if(Array.isArray(t))return g(t)}(a)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(a)||function(t,e){if(t){if("string"==typeof t)return g(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return g(t,void 0)}}(a)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()):a}},22190:function(t,e,r){"use strict";r.d(e,{D:function(){return N}});var n=r(2265),o=r(86757),i=r.n(o),a=r(87602),u=r(1175),c=r(48777),l=r(14870),s=r(41637);function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(){return(p=Object.assign?Object.assign.bind():function(t){for(var e=1;e');var x=e.inactive?h:e.color;return n.createElement("li",p({className:b,style:y,key:"legend-item-".concat(r)},(0,s.bw)(t.props,e,r)),n.createElement(c.T,{width:o,height:o,viewBox:d,style:v},t.renderIcon(e)),n.createElement("span",{className:"recharts-legend-item-text",style:{color:x}},l?l(g,e,r):g))})}},{key:"render",value:function(){var t=this.props,e=t.payload,r=t.layout,o=t.align;return e&&e.length?n.createElement("ul",{className:"recharts-default-legend",style:{padding:0,margin:0,textAlign:"horizontal"===r?o:"left"}},this.renderItems()):null}}],function(t,e){for(var r=0;r1||Math.abs(e.height-this.lastBoundingBox.height)>1)&&(this.lastBoundingBox.width=e.width,this.lastBoundingBox.height=e.height,t&&t(e)):(-1!==this.lastBoundingBox.width||-1!==this.lastBoundingBox.height)&&(this.lastBoundingBox.width=-1,this.lastBoundingBox.height=-1,t&&t(null))}},{key:"getBBoxSnapshot",value:function(){return this.lastBoundingBox.width>=0&&this.lastBoundingBox.height>=0?P({},this.lastBoundingBox):{width:0,height:0}}},{key:"getDefaultPosition",value:function(t){var e,r,n=this.props,o=n.layout,i=n.align,a=n.verticalAlign,u=n.margin,c=n.chartWidth,l=n.chartHeight;return t&&(void 0!==t.left&&null!==t.left||void 0!==t.right&&null!==t.right)||(e="center"===i&&"vertical"===o?{left:((c||0)-this.getBBoxSnapshot().width)/2}:"right"===i?{right:u&&u.right||0}:{left:u&&u.left||0}),t&&(void 0!==t.top&&null!==t.top||void 0!==t.bottom&&null!==t.bottom)||(r="middle"===a?{top:((l||0)-this.getBBoxSnapshot().height)/2}:"bottom"===a?{bottom:u&&u.bottom||0}:{top:u&&u.top||0}),P(P({},e),r)}},{key:"render",value:function(){var t=this,e=this.props,r=e.content,o=e.width,i=e.height,a=e.wrapperStyle,u=e.payloadUniqBy,c=e.payload,l=P(P({position:"absolute",width:o||"auto",height:i||"auto"},this.getDefaultPosition(a)),a);return n.createElement("div",{className:"recharts-legend-wrapper",style:l,ref:function(e){t.wrapperNode=e}},function(t,e){if(n.isValidElement(t))return n.cloneElement(t,e);if("function"==typeof t)return n.createElement(t,e);e.ref;var r=function(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r={};for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){if(e.indexOf(n)>=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(e,j);return n.createElement(g,r)}(r,P(P({},this.props),{},{payload:(0,w.z)(c,u,C)})))}}],r=[{key:"getWithHeight",value:function(t,e){var r=P(P({},this.defaultProps),t.props).layout;return"vertical"===r&&(0,x.hj)(t.props.height)?{height:t.props.height}:"horizontal"===r?{width:t.props.width||e}:null}}],e&&E(o.prototype,e),r&&E(o,r),Object.defineProperty(o,"prototype",{writable:!1}),o}(n.PureComponent);_(N,"displayName","Legend"),_(N,"defaultProps",{iconSize:14,layout:"horizontal",align:"center",verticalAlign:"bottom"})},47625:function(t,e,r){"use strict";r.d(e,{h:function(){return d}});var n=r(87602),o=r(2265),i=r(37065),a=r.n(i),u=r(16630),c=r(1175),l=r(82944);function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function f(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function p(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r0&&(t=a()(t,S,{trailing:!0,leading:!1}));var e=new ResizeObserver(t),r=M.current.getBoundingClientRect();return D(r.width,r.height),e.observe(M.current),function(){e.disconnect()}},[D,S]);var I=(0,o.useMemo)(function(){var t=C.containerWidth,e=C.containerHeight;if(t<0||e<0)return null;(0,c.Z)((0,u.hU)(y)||(0,u.hU)(m),"The width(%s) and height(%s) are both fixed numbers,\n maybe you don't need to use a ResponsiveContainer.",y,m),(0,c.Z)(!i||i>0,"The aspect(%s) must be greater than zero.",i);var r=(0,u.hU)(y)?t:y,n=(0,u.hU)(m)?e:m;i&&i>0&&(r?n=r/i:n&&(r=n*i),w&&n>w&&(n=w)),(0,c.Z)(r>0||n>0,"The width(%s) and height(%s) of chart should be greater than 0,\n please check the style of container, or the props width(%s) and height(%s),\n or add a minWidth(%s) or minHeight(%s) or use aspect(%s) to control the\n height and width.",r,n,y,m,g,x,i);var a=!Array.isArray(O)&&(0,l.Gf)(O.type).endsWith("Chart");return o.Children.map(O,function(t){return o.isValidElement(t)?(0,o.cloneElement)(t,p({width:r,height:n},a?{style:p({height:"100%",width:"100%",maxHeight:n,maxWidth:r},t.props.style)}:{})):t})},[i,O,m,w,x,g,C,y]);return o.createElement("div",{id:P?"".concat(P):void 0,className:(0,n.Z)("recharts-responsive-container",E),style:p(p({},void 0===A?{}:A),{},{width:y,height:m,minWidth:g,minHeight:x,maxHeight:w}),ref:M},I)})},58811:function(t,e,r){"use strict";r.d(e,{x:function(){return B}});var n=r(2265),o=r(77571),i=r.n(o),a=r(87602),u=r(16630),c=r(34067),l=r(82944),s=r(4094);function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;c=!1}else for(;!(c=(n=i.call(r)).done)&&(u.push(n.value),u.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(t,e)||function(t,e){if(t){if("string"==typeof t)return h(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return h(t,e)}}(t,e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function M(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;c=!1}else for(;!(c=(n=i.call(r)).done)&&(u.push(n.value),u.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(t,e)||function(t,e){if(t){if("string"==typeof t)return _(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return _(t,e)}}(t,e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function _(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r0&&void 0!==arguments[0]?arguments[0]:[];return t.reduce(function(t,e){var i=e.word,a=e.width,u=t[t.length-1];return u&&(null==n||o||u.width+a+ra||e.reduce(function(t,e){return t.width>e.width?t:e}).width>Number(n),e]},y=0,v=c.length-1,m=0;y<=v&&m<=c.length-1;){var b=Math.floor((y+v)/2),g=M(d(b-1),2),x=g[0],w=g[1],O=M(d(b),1)[0];if(x||O||(y=b+1),x&&O&&(v=b-1),!x&&O){i=w;break}m++}return i||h},D=function(t){return[{words:i()(t)?[]:t.toString().split(T)}]},I=function(t){var e=t.width,r=t.scaleToFit,n=t.children,o=t.style,i=t.breakAll,a=t.maxLines;if((e||r)&&!c.x.isSsr){var u=C({breakAll:i,children:n,style:o});return u?N({breakAll:i,children:n,maxLines:a,style:o},u.wordsWithComputedWidth,u.spaceWidth,e,r):D(n)}return D(n)},L="#808080",B=function(t){var e,r=t.x,o=void 0===r?0:r,i=t.y,c=void 0===i?0:i,s=t.lineHeight,f=void 0===s?"1em":s,p=t.capHeight,h=void 0===p?"0.71em":p,d=t.scaleToFit,y=void 0!==d&&d,v=t.textAnchor,m=t.verticalAnchor,b=t.fill,g=void 0===b?L:b,x=A(t,P),w=(0,n.useMemo)(function(){return I({breakAll:x.breakAll,children:x.children,maxLines:x.maxLines,scaleToFit:y,style:x.style,width:x.width})},[x.breakAll,x.children,x.maxLines,y,x.style,x.width]),O=x.dx,j=x.dy,M=x.angle,_=x.className,T=x.breakAll,C=A(x,E);if(!(0,u.P2)(o)||!(0,u.P2)(c))return null;var N=o+((0,u.hj)(O)?O:0),D=c+((0,u.hj)(j)?j:0);switch(void 0===m?"end":m){case"start":e=S("calc(".concat(h,")"));break;case"middle":e=S("calc(".concat((w.length-1)/2," * -").concat(f," + (").concat(h," / 2))"));break;default:e=S("calc(".concat(w.length-1," * -").concat(f,")"))}var B=[];if(y){var R=w[0].width,z=x.width;B.push("scale(".concat(((0,u.hj)(z)?z/R:1)/R,")"))}return M&&B.push("rotate(".concat(M,", ").concat(N,", ").concat(D,")")),B.length&&(C.transform=B.join(" ")),n.createElement("text",k({},(0,l.L6)(C,!0),{x:N,y:D,className:(0,a.Z)("recharts-text",_),textAnchor:void 0===v?"start":v,fill:g.includes("url")?L:g}),w.map(function(t,r){var o=t.words.join(T?"":" ");return n.createElement("tspan",{x:N,dy:0===r?e:f,key:"".concat(o,"-").concat(r)},o)}))}},8147:function(t,e,r){"use strict";r.d(e,{u:function(){return $}});var n=r(2265),o=r(34935),i=r.n(o),a=r(77571),u=r.n(a),c=r(87602),l=r(16630);function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function f(){return(f=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);rc[n]+s?Math.max(f,c[n]):Math.max(p,c[n])}function O(t){return(O="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function j(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function S(t){for(var e=1;e1||Math.abs(t.height-this.state.lastBoundingBox.height)>1)&&this.setState({lastBoundingBox:{width:t.width,height:t.height}})}else(-1!==this.state.lastBoundingBox.width||-1!==this.state.lastBoundingBox.height)&&this.setState({lastBoundingBox:{width:-1,height:-1}})}},{key:"componentDidMount",value:function(){document.addEventListener("keydown",this.handleKeyDown),this.updateBBox()}},{key:"componentWillUnmount",value:function(){document.removeEventListener("keydown",this.handleKeyDown)}},{key:"componentDidUpdate",value:function(){var t,e;this.props.active&&this.updateBBox(),this.state.dismissed&&((null===(t=this.props.coordinate)||void 0===t?void 0:t.x)!==this.state.dismissedAtCoordinate.x||(null===(e=this.props.coordinate)||void 0===e?void 0:e.y)!==this.state.dismissedAtCoordinate.y)&&(this.state.dismissed=!1)}},{key:"render",value:function(){var t,e,r,o,i,a,u,s,f,p,h,d,y,v,m,O,j,P,E,k=this,A=this.props,M=A.active,_=A.allowEscapeViewBox,T=A.animationDuration,C=A.animationEasing,N=A.children,D=A.coordinate,I=A.hasPayload,L=A.isAnimationActive,B=A.offset,R=A.position,z=A.reverseDirection,U=A.useTranslate3d,F=A.viewBox,$=A.wrapperStyle,q=(d=(t={allowEscapeViewBox:_,coordinate:D,offsetTopLeft:B,position:R,reverseDirection:z,tooltipBox:this.state.lastBoundingBox,useTranslate3d:U,viewBox:F}).allowEscapeViewBox,y=t.coordinate,v=t.offsetTopLeft,m=t.position,O=t.reverseDirection,j=t.tooltipBox,P=t.useTranslate3d,E=t.viewBox,j.height>0&&j.width>0&&y?(r=(e={translateX:p=w({allowEscapeViewBox:d,coordinate:y,key:"x",offsetTopLeft:v,position:m,reverseDirection:O,tooltipDimension:j.width,viewBox:E,viewBoxDimension:E.width}),translateY:h=w({allowEscapeViewBox:d,coordinate:y,key:"y",offsetTopLeft:v,position:m,reverseDirection:O,tooltipDimension:j.height,viewBox:E,viewBoxDimension:E.height}),useTranslate3d:P}).translateX,o=e.translateY,f={transform:e.useTranslate3d?"translate3d(".concat(r,"px, ").concat(o,"px, 0)"):"translate(".concat(r,"px, ").concat(o,"px)")}):f=x,{cssProperties:f,cssClasses:(a=(i={translateX:p,translateY:h,coordinate:y}).coordinate,u=i.translateX,s=i.translateY,(0,c.Z)(g,b(b(b(b({},"".concat(g,"-right"),(0,l.hj)(u)&&a&&(0,l.hj)(a.x)&&u>=a.x),"".concat(g,"-left"),(0,l.hj)(u)&&a&&(0,l.hj)(a.x)&&u=a.y),"".concat(g,"-top"),(0,l.hj)(s)&&a&&(0,l.hj)(a.y)&&s0;return n.createElement(_,{allowEscapeViewBox:i,animationDuration:a,animationEasing:u,isAnimationActive:f,active:o,coordinate:l,hasPayload:O,offset:p,position:y,reverseDirection:m,useTranslate3d:b,viewBox:g,wrapperStyle:x},(t=I(I({},this.props),{},{payload:w}),n.isValidElement(c)?n.cloneElement(c,t):"function"==typeof c?n.createElement(c,t):n.createElement(v,t)))}}],function(t,e){for(var r=0;r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,a),s=(0,o.Z)("recharts-layer",c);return n.createElement("g",u({className:s},(0,i.L6)(l,!0),{ref:e}),r)})},48777:function(t,e,r){"use strict";r.d(e,{T:function(){return c}});var n=r(2265),o=r(87602),i=r(82944),a=["children","width","height","viewBox","className","style","title","desc"];function u(){return(u=Object.assign?Object.assign.bind():function(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,a),y=l||{width:r,height:c,x:0,y:0},v=(0,o.Z)("recharts-surface",s);return n.createElement("svg",u({},(0,i.L6)(d,!0,"svg"),{className:v,width:r,height:c,style:f,viewBox:"".concat(y.x," ").concat(y.y," ").concat(y.width," ").concat(y.height)}),n.createElement("title",null,p),n.createElement("desc",null,h),e)}},25739:function(t,e,r){"use strict";r.d(e,{br:function(){return g},CW:function(){return O},Mw:function(){return A},zn:function(){return k},sp:function(){return x},qD:function(){return E},d2:function(){return P},bH:function(){return w},Ud:function(){return S},Nf:function(){return j}});var n=r(2265),o=r(69398),i=r(84173),a=r.n(i),u=r(32242),c=r.n(u),l=r(50967),s=r.n(l)()(function(t){return{x:t.left,y:t.top,width:t.width,height:t.height}},function(t){return["l",t.left,"t",t.top,"w",t.width,"h",t.height].join("")}),f=r(16630),p=(0,n.createContext)(void 0),h=(0,n.createContext)(void 0),d=(0,n.createContext)(void 0),y=(0,n.createContext)({}),v=(0,n.createContext)(void 0),m=(0,n.createContext)(0),b=(0,n.createContext)(0),g=function(t){var e=t.state,r=e.xAxisMap,o=e.yAxisMap,i=e.offset,a=t.clipPathId,u=t.children,c=t.width,l=t.height,f=s(i);return n.createElement(p.Provider,{value:r},n.createElement(h.Provider,{value:o},n.createElement(y.Provider,{value:i},n.createElement(d.Provider,{value:f},n.createElement(v.Provider,{value:a},n.createElement(m.Provider,{value:l},n.createElement(b.Provider,{value:c},u)))))))},x=function(){return(0,n.useContext)(v)},w=function(t){var e=(0,n.useContext)(p);null!=e||(0,o.Z)(!1);var r=e[t];return null!=r||(0,o.Z)(!1),r},O=function(){var t=(0,n.useContext)(p);return(0,f.Kt)(t)},j=function(){var t=(0,n.useContext)(h);return a()(t,function(t){return c()(t.domain,Number.isFinite)})||(0,f.Kt)(t)},S=function(t){var e=(0,n.useContext)(h);null!=e||(0,o.Z)(!1);var r=e[t];return null!=r||(0,o.Z)(!1),r},P=function(){return(0,n.useContext)(d)},E=function(){return(0,n.useContext)(y)},k=function(){return(0,n.useContext)(b)},A=function(){return(0,n.useContext)(m)}},57165:function(t,e,r){"use strict";r.d(e,{H:function(){return H}});var n=r(2265);function o(){}function i(t,e,r){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+r)/6)}function a(t){this._context=t}function u(t){this._context=t}function c(t){this._context=t}a.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:i(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:i(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},u.prototype={areaStart:o,areaEnd:o,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x2=t,this._y2=e;break;case 1:this._point=2,this._x3=t,this._y3=e;break;case 2:this._point=3,this._x4=t,this._y4=e,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+e)/6);break;default:i(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},c.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var r=(this._x0+4*this._x1+t)/6,n=(this._y0+4*this._y1+e)/6;this._line?this._context.lineTo(r,n):this._context.moveTo(r,n);break;case 3:this._point=4;default:i(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}};class l{constructor(t,e){this._context=t,this._x=e}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line}point(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+t)/2,this._y0,this._x0,e,t,e):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+e)/2,t,this._y0,t,e)}this._x0=t,this._y0=e}}function s(t){this._context=t}function f(t){this._context=t}function p(t){return new f(t)}function h(t,e,r){var n=t._x1-t._x0,o=e-t._x1,i=(t._y1-t._y0)/(n||o<0&&-0),a=(r-t._y1)/(o||n<0&&-0);return((i<0?-1:1)+(a<0?-1:1))*Math.min(Math.abs(i),Math.abs(a),.5*Math.abs((i*o+a*n)/(n+o)))||0}function d(t,e){var r=t._x1-t._x0;return r?(3*(t._y1-t._y0)/r-e)/2:e}function y(t,e,r){var n=t._x0,o=t._y0,i=t._x1,a=t._y1,u=(i-n)/3;t._context.bezierCurveTo(n+u,o+u*e,i-u,a-u*r,i,a)}function v(t){this._context=t}function m(t){this._context=new b(t)}function b(t){this._context=t}function g(t){this._context=t}function x(t){var e,r,n=t.length-1,o=Array(n),i=Array(n),a=Array(n);for(o[0]=0,i[0]=2,a[0]=t[0]+2*t[1],e=1;e=0;--e)o[e]=(a[e]-o[e+1])/i[e];for(e=0,i[n-1]=(t[n]+o[n-1])/2;e=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var r=this._x*(1-this._t)+t*this._t;this._context.lineTo(r,this._y),this._context.lineTo(r,e)}}this._x=t,this._y=e}};var O=r(22516),j=r(76115),S=r(67790);function P(t){return t[0]}function E(t){return t[1]}function k(t,e){var r=(0,j.Z)(!0),n=null,o=p,i=null,a=(0,S.d)(u);function u(u){var c,l,s,f=(u=(0,O.Z)(u)).length,p=!1;for(null==n&&(i=o(s=a())),c=0;c<=f;++c)!(c=f;--p)u.point(m[p],b[p]);u.lineEnd(),u.areaEnd()}}v&&(m[s]=+t(h,s,l),b[s]=+e(h,s,l),u.point(n?+n(h,s,l):m[s],r?+r(h,s,l):b[s]))}if(d)return u=null,d+""||null}function s(){return k().defined(o).curve(a).context(i)}return t="function"==typeof t?t:void 0===t?P:(0,j.Z)(+t),e="function"==typeof e?e:void 0===e?(0,j.Z)(0):(0,j.Z)(+e),r="function"==typeof r?r:void 0===r?E:(0,j.Z)(+r),l.x=function(e){return arguments.length?(t="function"==typeof e?e:(0,j.Z)(+e),n=null,l):t},l.x0=function(e){return arguments.length?(t="function"==typeof e?e:(0,j.Z)(+e),l):t},l.x1=function(t){return arguments.length?(n=null==t?null:"function"==typeof t?t:(0,j.Z)(+t),l):n},l.y=function(t){return arguments.length?(e="function"==typeof t?t:(0,j.Z)(+t),r=null,l):e},l.y0=function(t){return arguments.length?(e="function"==typeof t?t:(0,j.Z)(+t),l):e},l.y1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:(0,j.Z)(+t),l):r},l.lineX0=l.lineY0=function(){return s().x(t).y(e)},l.lineY1=function(){return s().x(t).y(r)},l.lineX1=function(){return s().x(n).y(e)},l.defined=function(t){return arguments.length?(o="function"==typeof t?t:(0,j.Z)(!!t),l):o},l.curve=function(t){return arguments.length?(a=t,null!=i&&(u=a(i)),l):a},l.context=function(t){return arguments.length?(null==t?i=u=null:u=a(i=t),l):i},l}var M=r(75551),_=r.n(M),T=r(86757),C=r.n(T),N=r(87602),D=r(41637),I=r(82944),L=r(16630);function B(t){return(B="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function R(){return(R=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r=0?1:-1,c=r>=0?1:-1,l=n>=0&&r>=0||n<0&&r<0?1:0;if(a>0&&o instanceof Array){for(var s=[0,0,0,0],f=0;f<4;f++)s[f]=o[f]>a?a:o[f];i="M".concat(t,",").concat(e+u*s[0]),s[0]>0&&(i+="A ".concat(s[0],",").concat(s[0],",0,0,").concat(l,",").concat(t+c*s[0],",").concat(e)),i+="L ".concat(t+r-c*s[1],",").concat(e),s[1]>0&&(i+="A ".concat(s[1],",").concat(s[1],",0,0,").concat(l,",\n ").concat(t+r,",").concat(e+u*s[1])),i+="L ".concat(t+r,",").concat(e+n-u*s[2]),s[2]>0&&(i+="A ".concat(s[2],",").concat(s[2],",0,0,").concat(l,",\n ").concat(t+r-c*s[2],",").concat(e+n)),i+="L ".concat(t+c*s[3],",").concat(e+n),s[3]>0&&(i+="A ".concat(s[3],",").concat(s[3],",0,0,").concat(l,",\n ").concat(t,",").concat(e+n-u*s[3])),i+="Z"}else if(a>0&&o===+o&&o>0){var p=Math.min(a,o);i="M ".concat(t,",").concat(e+u*p,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t+c*p,",").concat(e,"\n L ").concat(t+r-c*p,",").concat(e,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t+r,",").concat(e+u*p,"\n L ").concat(t+r,",").concat(e+n-u*p,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t+r-c*p,",").concat(e+n,"\n L ").concat(t+c*p,",").concat(e+n,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t,",").concat(e+n-u*p," Z")}else i="M ".concat(t,",").concat(e," h ").concat(r," v ").concat(n," h ").concat(-r," Z");return i},h=function(t,e){if(!t||!e)return!1;var r=t.x,n=t.y,o=e.x,i=e.y,a=e.width,u=e.height;return!!(Math.abs(a)>0&&Math.abs(u)>0)&&r>=Math.min(o,o+a)&&r<=Math.max(o,o+a)&&n>=Math.min(i,i+u)&&n<=Math.max(i,i+u)},d={x:0,y:0,width:0,height:0,radius:0,isAnimationActive:!1,isUpdateAnimationActive:!1,animationBegin:0,animationDuration:1500,animationEasing:"ease"},y=function(t){var e,r=f(f({},d),t),u=(0,n.useRef)(),s=function(t){if(Array.isArray(t))return t}(e=(0,n.useState)(-1))||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{for(i=(r=r.call(t)).next;!(c=(n=i.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(e,2)||function(t,e){if(t){if("string"==typeof t)return l(t,2);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return l(t,2)}}(e,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),h=s[0],y=s[1];(0,n.useEffect)(function(){if(u.current&&u.current.getTotalLength)try{var t=u.current.getTotalLength();t&&y(t)}catch(t){}},[]);var v=r.x,m=r.y,b=r.width,g=r.height,x=r.radius,w=r.className,O=r.animationEasing,j=r.animationDuration,S=r.animationBegin,P=r.isAnimationActive,E=r.isUpdateAnimationActive;if(v!==+v||m!==+m||b!==+b||g!==+g||0===b||0===g)return null;var k=(0,o.Z)("recharts-rectangle",w);return E?n.createElement(i.ZP,{canBegin:h>0,from:{width:b,height:g,x:v,y:m},to:{width:b,height:g,x:v,y:m},duration:j,animationEasing:O,isActive:E},function(t){var e=t.width,o=t.height,l=t.x,s=t.y;return n.createElement(i.ZP,{canBegin:h>0,from:"0px ".concat(-1===h?1:h,"px"),to:"".concat(h,"px 0px"),attributeName:"strokeDasharray",begin:S,duration:j,isActive:P,easing:O},n.createElement("path",c({},(0,a.L6)(r,!0),{className:k,d:p(l,s,e,o,x),ref:u})))}):n.createElement("path",c({},(0,a.L6)(r,!0),{className:k,d:p(v,m,b,g,x)}))}},60474:function(t,e,r){"use strict";r.d(e,{L:function(){return v}});var n=r(2265),o=r(87602),i=r(82944),a=r(39206),u=r(16630);function c(t){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function l(){return(l=Object.assign?Object.assign.bind():function(t){for(var e=1;e180),",").concat(+(c>s),",\n ").concat(p.x,",").concat(p.y,"\n ");if(o>0){var d=(0,a.op)(r,n,o,c),y=(0,a.op)(r,n,o,s);h+="L ".concat(y.x,",").concat(y.y,"\n A ").concat(o,",").concat(o,",0,\n ").concat(+(Math.abs(l)>180),",").concat(+(c<=s),",\n ").concat(d.x,",").concat(d.y," Z")}else h+="L ".concat(r,",").concat(n," Z");return h},d=function(t){var e=t.cx,r=t.cy,n=t.innerRadius,o=t.outerRadius,i=t.cornerRadius,a=t.forceCornerRadius,c=t.cornerIsExternal,l=t.startAngle,s=t.endAngle,f=(0,u.uY)(s-l),d=p({cx:e,cy:r,radius:o,angle:l,sign:f,cornerRadius:i,cornerIsExternal:c}),y=d.circleTangency,v=d.lineTangency,m=d.theta,b=p({cx:e,cy:r,radius:o,angle:s,sign:-f,cornerRadius:i,cornerIsExternal:c}),g=b.circleTangency,x=b.lineTangency,w=b.theta,O=c?Math.abs(l-s):Math.abs(l-s)-m-w;if(O<0)return a?"M ".concat(v.x,",").concat(v.y,"\n a").concat(i,",").concat(i,",0,0,1,").concat(2*i,",0\n a").concat(i,",").concat(i,",0,0,1,").concat(-(2*i),",0\n "):h({cx:e,cy:r,innerRadius:n,outerRadius:o,startAngle:l,endAngle:s});var j="M ".concat(v.x,",").concat(v.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(y.x,",").concat(y.y,"\n A").concat(o,",").concat(o,",0,").concat(+(O>180),",").concat(+(f<0),",").concat(g.x,",").concat(g.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(x.x,",").concat(x.y,"\n ");if(n>0){var S=p({cx:e,cy:r,radius:n,angle:l,sign:f,isExternal:!0,cornerRadius:i,cornerIsExternal:c}),P=S.circleTangency,E=S.lineTangency,k=S.theta,A=p({cx:e,cy:r,radius:n,angle:s,sign:-f,isExternal:!0,cornerRadius:i,cornerIsExternal:c}),M=A.circleTangency,_=A.lineTangency,T=A.theta,C=c?Math.abs(l-s):Math.abs(l-s)-k-T;if(C<0&&0===i)return"".concat(j,"L").concat(e,",").concat(r,"Z");j+="L".concat(_.x,",").concat(_.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(M.x,",").concat(M.y,"\n A").concat(n,",").concat(n,",0,").concat(+(C>180),",").concat(+(f>0),",").concat(P.x,",").concat(P.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(E.x,",").concat(E.y,"Z")}else j+="L".concat(e,",").concat(r,"Z");return j},y={cx:0,cy:0,innerRadius:0,outerRadius:0,startAngle:0,endAngle:0,cornerRadius:0,forceCornerRadius:!1,cornerIsExternal:!1},v=function(t){var e,r=f(f({},y),t),a=r.cx,c=r.cy,s=r.innerRadius,p=r.outerRadius,v=r.cornerRadius,m=r.forceCornerRadius,b=r.cornerIsExternal,g=r.startAngle,x=r.endAngle,w=r.className;if(p0&&360>Math.abs(g-x)?d({cx:a,cy:c,innerRadius:s,outerRadius:p,cornerRadius:Math.min(S,j/2),forceCornerRadius:m,cornerIsExternal:b,startAngle:g,endAngle:x}):h({cx:a,cy:c,innerRadius:s,outerRadius:p,startAngle:g,endAngle:x}),n.createElement("path",l({},(0,i.L6)(r,!0),{className:O,d:e,role:"img"}))}},14870:function(t,e,r){"use strict";r.d(e,{v:function(){return N}});var n=r(2265),o=r(75551),i=r.n(o);let a=Math.cos,u=Math.sin,c=Math.sqrt,l=Math.PI,s=2*l;var f={draw(t,e){let r=c(e/l);t.moveTo(r,0),t.arc(0,0,r,0,s)}};let p=c(1/3),h=2*p,d=u(l/10)/u(7*l/10),y=u(s/10)*d,v=-a(s/10)*d,m=c(3),b=c(3)/2,g=1/c(12),x=(g/2+1)*3;var w=r(76115),O=r(67790);c(3),c(3);var j=r(87602),S=r(82944);function P(t){return(P="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var E=["type","size","sizeType"];function k(){return(k=Object.assign?Object.assign.bind():function(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,E)),{},{type:o,size:u,sizeType:l}),p=s.className,h=s.cx,d=s.cy,y=(0,S.L6)(s,!0);return h===+h&&d===+d&&u===+u?n.createElement("path",k({},y,{className:(0,j.Z)("recharts-symbols",p),transform:"translate(".concat(h,", ").concat(d,")"),d:(e=_["symbol".concat(i()(o))]||f,(function(t,e){let r=null,n=(0,O.d)(o);function o(){let o;if(r||(r=o=n()),t.apply(this,arguments).draw(r,+e.apply(this,arguments)),o)return r=null,o+""||null}return t="function"==typeof t?t:(0,w.Z)(t||f),e="function"==typeof e?e:(0,w.Z)(void 0===e?64:+e),o.type=function(e){return arguments.length?(t="function"==typeof e?e:(0,w.Z)(e),o):t},o.size=function(t){return arguments.length?(e="function"==typeof t?t:(0,w.Z)(+t),o):e},o.context=function(t){return arguments.length?(r=null==t?null:t,o):r},o})().type(e).size(C(u,l,o))())})):null};N.registerSymbol=function(t,e){_["symbol".concat(i()(t))]=e}},11638:function(t,e,r){"use strict";r.d(e,{bn:function(){return C},a3:function(){return z},lT:function(){return N},V$:function(){return D},w7:function(){return I}});var n=r(2265),o=r(86757),i=r.n(o),a=r(90231),u=r.n(a),c=r(24342),l=r.n(c),s=r(21652),f=r.n(s),p=r(73649),h=r(87602),d=r(84735),y=r(82944);function v(t){return(v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function m(){return(m=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r0,from:{upperWidth:0,lowerWidth:0,height:p,x:c,y:l},to:{upperWidth:s,lowerWidth:f,height:p,x:c,y:l},duration:j,animationEasing:g,isActive:P},function(t){var e=t.upperWidth,i=t.lowerWidth,u=t.height,c=t.x,l=t.y;return n.createElement(d.ZP,{canBegin:a>0,from:"0px ".concat(-1===a?1:a,"px"),to:"".concat(a,"px 0px"),attributeName:"strokeDasharray",begin:S,duration:j,easing:g},n.createElement("path",m({},(0,y.L6)(r,!0),{className:E,d:w(c,l,e,i,u),ref:o})))}):n.createElement("g",null,n.createElement("path",m({},(0,y.L6)(r,!0),{className:E,d:w(c,l,s,f,p)})))},S=r(60474),P=r(9841),E=r(14870),k=["option","shapeType","propTransformer","activeClassName","isActive"];function A(t){return(A="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function M(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function _(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,k);if((0,n.isValidElement)(r))e=(0,n.cloneElement)(r,_(_({},f),(0,n.isValidElement)(r)?r.props:r));else if(i()(r))e=r(f);else if(u()(r)&&!l()(r)){var p=(void 0===a?function(t,e){return _(_({},e),t)}:a)(r,f);e=n.createElement(T,{shapeType:o,elementProps:p})}else e=n.createElement(T,{shapeType:o,elementProps:f});return s?n.createElement(P.m,{className:void 0===c?"recharts-active-shape":c},e):e}function N(t,e){return null!=e&&"trapezoids"in t.props}function D(t,e){return null!=e&&"sectors"in t.props}function I(t,e){return null!=e&&"points"in t.props}function L(t,e){var r,n,o=t.x===(null==e||null===(r=e.labelViewBox)||void 0===r?void 0:r.x)||t.x===e.x,i=t.y===(null==e||null===(n=e.labelViewBox)||void 0===n?void 0:n.y)||t.y===e.y;return o&&i}function B(t,e){var r=t.endAngle===e.endAngle,n=t.startAngle===e.startAngle;return r&&n}function R(t,e){var r=t.x===e.x,n=t.y===e.y,o=t.z===e.z;return r&&n&&o}function z(t){var e,r,n,o=t.activeTooltipItem,i=t.graphicalItem,a=t.itemData,u=(N(i,o)?e="trapezoids":D(i,o)?e="sectors":I(i,o)&&(e="points"),e),c=N(i,o)?null===(r=o.tooltipPayload)||void 0===r||null===(r=r[0])||void 0===r||null===(r=r.payload)||void 0===r?void 0:r.payload:D(i,o)?null===(n=o.tooltipPayload)||void 0===n||null===(n=n[0])||void 0===n||null===(n=n.payload)||void 0===n?void 0:n.payload:I(i,o)?o.payload:{},l=a.filter(function(t,e){var r=f()(c,t),n=i.props[u].filter(function(t){var e;return(N(i,o)?e=L:D(i,o)?e=B:I(i,o)&&(e=R),e)(t,o)}),a=i.props[u].indexOf(n[n.length-1]);return r&&e===a});return a.indexOf(l[l.length-1])}},25311:function(t,e,r){"use strict";r.d(e,{Ky:function(){return w},O1:function(){return b},_b:function(){return g},t9:function(){return m},xE:function(){return O}});var n=r(41443),o=r.n(n),i=r(32242),a=r.n(i),u=r(85355),c=r(82944),l=r(16630),s=r(31699);function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(t,e){for(var r=0;r0&&(A=Math.min((t||0)-(M[e-1]||0),A))}),Number.isFinite(A)){var _=A/k,T="vertical"===g.layout?r.height:r.width;if("gap"===g.padding&&(c=_*T/2),"no-gap"===g.padding){var C=(0,l.h1)(t.barCategoryGap,_*T),N=_*T/2;c=N-C-(N-C)/T*C}}}s="xAxis"===n?[r.left+(j.left||0)+(c||0),r.left+r.width-(j.right||0)-(c||0)]:"yAxis"===n?"horizontal"===f?[r.top+r.height-(j.bottom||0),r.top+(j.top||0)]:[r.top+(j.top||0)+(c||0),r.top+r.height-(j.bottom||0)-(c||0)]:g.range,P&&(s=[s[1],s[0]]);var D=(0,u.Hq)(g,o,m),I=D.scale,L=D.realScaleType;I.domain(w).range(s),(0,u.zF)(I);var B=(0,u.g$)(I,d(d({},g),{},{realScaleType:L}));"xAxis"===n?(b="top"===x&&!S||"bottom"===x&&S,p=r.left,h=v[E]-b*g.height):"yAxis"===n&&(b="left"===x&&!S||"right"===x&&S,p=v[E]-b*g.width,h=r.top);var R=d(d(d({},g),B),{},{realScaleType:L,x:p,y:h,scale:I,width:"xAxis"===n?r.width:g.width,height:"yAxis"===n?r.height:g.height});return R.bandSize=(0,u.zT)(R,B),g.hide||"xAxis"!==n?g.hide||(v[E]+=(b?-1:1)*R.width):v[E]+=(b?-1:1)*R.height,d(d({},i),{},y({},a,R))},{})},b=function(t,e){var r=t.x,n=t.y,o=e.x,i=e.y;return{x:Math.min(r,o),y:Math.min(n,i),width:Math.abs(o-r),height:Math.abs(i-n)}},g=function(t){return b({x:t.x1,y:t.y1},{x:t.x2,y:t.y2})},x=function(){var t,e;function r(t){!function(t,e){if(!(t instanceof e))throw TypeError("Cannot call a class as a function")}(this,r),this.scale=t}return t=[{key:"domain",get:function(){return this.scale.domain}},{key:"range",get:function(){return this.scale.range}},{key:"rangeMin",get:function(){return this.range()[0]}},{key:"rangeMax",get:function(){return this.range()[1]}},{key:"bandwidth",get:function(){return this.scale.bandwidth}},{key:"apply",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=e.bandAware,n=e.position;if(void 0!==t){if(n)switch(n){case"start":default:return this.scale(t);case"middle":var o=this.bandwidth?this.bandwidth()/2:0;return this.scale(t)+o;case"end":var i=this.bandwidth?this.bandwidth():0;return this.scale(t)+i}if(r){var a=this.bandwidth?this.bandwidth()/2:0;return this.scale(t)+a}return this.scale(t)}}},{key:"isInRange",value:function(t){var e=this.range(),r=e[0],n=e[e.length-1];return r<=n?t>=r&&t<=n:t>=n&&t<=r}}],e=[{key:"create",value:function(t){return new r(t)}}],t&&p(r.prototype,t),e&&p(r,e),Object.defineProperty(r,"prototype",{writable:!1}),r}();y(x,"EPS",1e-4);var w=function(t){var e=Object.keys(t).reduce(function(e,r){return d(d({},e),{},y({},r,x.create(t[r])))},{});return d(d({},e),{},{apply:function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.bandAware,i=r.position;return o()(t,function(t,r){return e[r].apply(t,{bandAware:n,position:i})})},isInRange:function(t){return a()(t,function(t,r){return e[r].isInRange(t)})}})},O=function(t){var e=t.width,r=t.height,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=(n%180+180)%180*Math.PI/180,i=Math.atan(r/e);return Math.abs(o>i&&otx(e,t()).base(e.base()),tj.o.apply(e,arguments),e}},scaleOrdinal:function(){return tX.Z},scalePoint:function(){return f.x},scalePow:function(){return tJ},scaleQuantile:function(){return function t(){var e,r=[],n=[],o=[];function i(){var t=0,e=Math.max(1,n.length);for(o=Array(e-1);++t=1)return+r(t[n-1],n-1,t);var n,o=(n-1)*e,i=Math.floor(o),a=+r(t[i],i,t);return a+(+r(t[i+1],i+1,t)-a)*(o-i)}}(r,t/e);return a}function a(t){return null==t||isNaN(t=+t)?e:n[P(o,t)]}return a.invertExtent=function(t){var e=n.indexOf(t);return e<0?[NaN,NaN]:[e>0?o[e-1]:r[0],e=o?[i[o-1],n]:[i[e-1],i[e]]},u.unknown=function(t){return arguments.length&&(e=t),u},u.thresholds=function(){return i.slice()},u.copy=function(){return t().domain([r,n]).range(a).unknown(e)},tj.o.apply(tI(u),arguments)}},scaleRadial:function(){return function t(){var e,r=tO(),n=[0,1],o=!1;function i(t){var n,i=Math.sign(n=r(t))*Math.sqrt(Math.abs(n));return isNaN(i)?e:o?Math.round(i):i}return i.invert=function(t){return r.invert(t1(t))},i.domain=function(t){return arguments.length?(r.domain(t),i):r.domain()},i.range=function(t){return arguments.length?(r.range((n=Array.from(t,td)).map(t1)),i):n.slice()},i.rangeRound=function(t){return i.range(t).round(!0)},i.round=function(t){return arguments.length?(o=!!t,i):o},i.clamp=function(t){return arguments.length?(r.clamp(t),i):r.clamp()},i.unknown=function(t){return arguments.length?(e=t,i):e},i.copy=function(){return t(r.domain(),n).round(o).clamp(r.clamp()).unknown(e)},tj.o.apply(i,arguments),tI(i)}},scaleSequential:function(){return function t(){var e=tI(rX()(tv));return e.copy=function(){return rG(e,t())},tj.O.apply(e,arguments)}},scaleSequentialLog:function(){return function t(){var e=tZ(rX()).domain([1,10]);return e.copy=function(){return rG(e,t()).base(e.base())},tj.O.apply(e,arguments)}},scaleSequentialPow:function(){return rV},scaleSequentialQuantile:function(){return function t(){var e=[],r=tv;function n(t){if(null!=t&&!isNaN(t=+t))return r((P(e,t,1)-1)/(e.length-1))}return n.domain=function(t){if(!arguments.length)return e.slice();for(let r of(e=[],t))null==r||isNaN(r=+r)||e.push(r);return e.sort(g),n},n.interpolator=function(t){return arguments.length?(r=t,n):r},n.range=function(){return e.map((t,n)=>r(n/(e.length-1)))},n.quantiles=function(t){return Array.from({length:t+1},(r,n)=>(function(t,e,r){if(!(!(n=(t=Float64Array.from(function*(t,e){if(void 0===e)for(let e of t)null!=e&&(e=+e)>=e&&(yield e);else{let r=-1;for(let n of t)null!=(n=e(n,++r,t))&&(n=+n)>=n&&(yield n)}}(t,void 0))).length)||isNaN(e=+e))){if(e<=0||n<2)return t5(t);if(e>=1)return t2(t);var n,o=(n-1)*e,i=Math.floor(o),a=t2((function t(e,r,n=0,o=1/0,i){if(r=Math.floor(r),n=Math.floor(Math.max(0,n)),o=Math.floor(Math.min(e.length-1,o)),!(n<=r&&r<=o))return e;for(i=void 0===i?t6:function(t=g){if(t===g)return t6;if("function"!=typeof t)throw TypeError("compare is not a function");return(e,r)=>{let n=t(e,r);return n||0===n?n:(0===t(r,r))-(0===t(e,e))}}(i);o>n;){if(o-n>600){let a=o-n+1,u=r-n+1,c=Math.log(a),l=.5*Math.exp(2*c/3),s=.5*Math.sqrt(c*l*(a-l)/a)*(u-a/2<0?-1:1),f=Math.max(n,Math.floor(r-u*l/a+s)),p=Math.min(o,Math.floor(r+(a-u)*l/a+s));t(e,r,f,p,i)}let a=e[r],u=n,c=o;for(t3(e,n,r),i(e[o],a)>0&&t3(e,n,o);ui(e[u],a);)++u;for(;i(e[c],a)>0;)--c}0===i(e[n],a)?t3(e,n,c):t3(e,++c,o),c<=r&&(n=c+1),r<=c&&(o=c-1)}return e})(t,i).subarray(0,i+1));return a+(t5(t.subarray(i+1))-a)*(o-i)}})(e,n/t))},n.copy=function(){return t(r).domain(e)},tj.O.apply(n,arguments)}},scaleSequentialSqrt:function(){return rK},scaleSequentialSymlog:function(){return function t(){var e=tH(rX());return e.copy=function(){return rG(e,t()).constant(e.constant())},tj.O.apply(e,arguments)}},scaleSqrt:function(){return t0},scaleSymlog:function(){return function t(){var e=tH(tw());return e.copy=function(){return tx(e,t()).constant(e.constant())},tj.o.apply(e,arguments)}},scaleThreshold:function(){return function t(){var e,r=[.5],n=[0,1],o=1;function i(t){return null!=t&&t<=t?n[P(r,t,0,o)]:e}return i.domain=function(t){return arguments.length?(o=Math.min((r=Array.from(t)).length,n.length-1),i):r.slice()},i.range=function(t){return arguments.length?(n=Array.from(t),o=Math.min(r.length,n.length-1),i):n.slice()},i.invertExtent=function(t){var e=n.indexOf(t);return[r[e-1],r[e]]},i.unknown=function(t){return arguments.length?(e=t,i):e},i.copy=function(){return t().domain(r).range(n).unknown(e)},tj.o.apply(i,arguments)}},scaleTime:function(){return rY},scaleUtc:function(){return rH},tickFormat:function(){return tD}});var f=r(55284);let p=Math.sqrt(50),h=Math.sqrt(10),d=Math.sqrt(2);function y(t,e,r){let n,o,i;let a=(e-t)/Math.max(0,r),u=Math.floor(Math.log10(a)),c=a/Math.pow(10,u),l=c>=p?10:c>=h?5:c>=d?2:1;return(u<0?(n=Math.round(t*(i=Math.pow(10,-u)/l)),o=Math.round(e*i),n/ie&&--o,i=-i):(n=Math.round(t/(i=Math.pow(10,u)*l)),o=Math.round(e/i),n*ie&&--o),o0))return[];if(t===e)return[t];let n=e=o))return[];let u=i-o+1,c=Array(u);if(n){if(a<0)for(let t=0;te?1:t>=e?0:NaN}function x(t,e){return null==t||null==e?NaN:et?1:e>=t?0:NaN}function w(t){let e,r,n;function o(t,n,o=0,i=t.length){if(o>>1;0>r(t[e],n)?o=e+1:i=e}while(og(t(e),r),n=(e,r)=>t(e)-r):(e=t===g||t===x?t:O,r=t,n=t),{left:o,center:function(t,e,r=0,i=t.length){let a=o(t,e,r,i-1);return a>r&&n(t[a-1],e)>-n(t[a],e)?a-1:a},right:function(t,n,o=0,i=t.length){if(o>>1;0>=r(t[e],n)?o=e+1:i=e}while(o>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===r?Z(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===r?Z(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=N.exec(t))?new Y(e[1],e[2],e[3],1):(e=D.exec(t))?new Y(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=I.exec(t))?Z(e[1],e[2],e[3],e[4]):(e=L.exec(t))?Z(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=B.exec(t))?Q(e[1],e[2]/100,e[3]/100,1):(e=R.exec(t))?Q(e[1],e[2]/100,e[3]/100,e[4]):z.hasOwnProperty(t)?q(z[t]):"transparent"===t?new Y(NaN,NaN,NaN,0):null}function q(t){return new Y(t>>16&255,t>>8&255,255&t,1)}function Z(t,e,r,n){return n<=0&&(t=e=r=NaN),new Y(t,e,r,n)}function W(t,e,r,n){var o;return 1==arguments.length?((o=t)instanceof A||(o=$(o)),o)?new Y((o=o.rgb()).r,o.g,o.b,o.opacity):new Y:new Y(t,e,r,null==n?1:n)}function Y(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}function H(){return`#${K(this.r)}${K(this.g)}${K(this.b)}`}function X(){let t=G(this.opacity);return`${1===t?"rgb(":"rgba("}${V(this.r)}, ${V(this.g)}, ${V(this.b)}${1===t?")":`, ${t})`}`}function G(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function V(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function K(t){return((t=V(t))<16?"0":"")+t.toString(16)}function Q(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new tt(t,e,r,n)}function J(t){if(t instanceof tt)return new tt(t.h,t.s,t.l,t.opacity);if(t instanceof A||(t=$(t)),!t)return new tt;if(t instanceof tt)return t;var e=(t=t.rgb()).r/255,r=t.g/255,n=t.b/255,o=Math.min(e,r,n),i=Math.max(e,r,n),a=NaN,u=i-o,c=(i+o)/2;return u?(a=e===i?(r-n)/u+(r0&&c<1?0:a,new tt(a,u,c,t.opacity)}function tt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}function te(t){return(t=(t||0)%360)<0?t+360:t}function tr(t){return Math.max(0,Math.min(1,t||0))}function tn(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}function to(t,e,r,n,o){var i=t*t,a=i*t;return((1-3*t+3*i-a)*e+(4-6*i+3*a)*r+(1+3*t+3*i-3*a)*n+a*o)/6}E(A,$,{copy(t){return Object.assign(new this.constructor,this,t)},displayable(){return this.rgb().displayable()},hex:U,formatHex:U,formatHex8:function(){return this.rgb().formatHex8()},formatHsl:function(){return J(this).formatHsl()},formatRgb:F,toString:F}),E(Y,W,k(A,{brighter(t){return t=null==t?1.4285714285714286:Math.pow(1.4285714285714286,t),new Y(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=null==t?.7:Math.pow(.7,t),new Y(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new Y(V(this.r),V(this.g),V(this.b),G(this.opacity))},displayable(){return -.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:H,formatHex:H,formatHex8:function(){return`#${K(this.r)}${K(this.g)}${K(this.b)}${K((isNaN(this.opacity)?1:this.opacity)*255)}`},formatRgb:X,toString:X})),E(tt,function(t,e,r,n){return 1==arguments.length?J(t):new tt(t,e,r,null==n?1:n)},k(A,{brighter(t){return t=null==t?1.4285714285714286:Math.pow(1.4285714285714286,t),new tt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=null==t?.7:Math.pow(.7,t),new tt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,o=2*r-n;return new Y(tn(t>=240?t-240:t+120,o,n),tn(t,o,n),tn(t<120?t+240:t-120,o,n),this.opacity)},clamp(){return new tt(te(this.h),tr(this.s),tr(this.l),G(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){let t=G(this.opacity);return`${1===t?"hsl(":"hsla("}${te(this.h)}, ${100*tr(this.s)}%, ${100*tr(this.l)}%${1===t?")":`, ${t})`}`}}));var ti=t=>()=>t;function ta(t,e){var r=e-t;return r?function(e){return t+e*r}:ti(isNaN(t)?e:t)}var tu=function t(e){var r,n=1==(r=+(r=e))?ta:function(t,e){var n,o,i;return e-t?(n=t,o=e,n=Math.pow(n,i=r),o=Math.pow(o,i)-n,i=1/i,function(t){return Math.pow(n+t*o,i)}):ti(isNaN(t)?e:t)};function o(t,e){var r=n((t=W(t)).r,(e=W(e)).r),o=n(t.g,e.g),i=n(t.b,e.b),a=ta(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=o(e),t.b=i(e),t.opacity=a(e),t+""}}return o.gamma=t,o}(1);function tc(t){return function(e){var r,n,o=e.length,i=Array(o),a=Array(o),u=Array(o);for(r=0;r=1?(r=1,e-1):Math.floor(r*e),o=t[n],i=t[n+1],a=n>0?t[n-1]:2*o-i,u=nu&&(a=e.slice(u,a),l[c]?l[c]+=a:l[++c]=a),(o=o[0])===(i=i[0])?l[c]?l[c]+=i:l[++c]=i:(l[++c]=null,s.push({i:c,x:tl(o,i)})),u=tf.lastIndex;return ue&&(r=t,t=e,e=r),l=function(r){return Math.max(t,Math.min(e,r))}),n=c>2?tg:tb,o=i=null,f}function f(e){return null==e||isNaN(e=+e)?r:(o||(o=n(a.map(t),u,c)))(t(l(e)))}return f.invert=function(r){return l(e((i||(i=n(u,a.map(t),tl)))(r)))},f.domain=function(t){return arguments.length?(a=Array.from(t,td),s()):a.slice()},f.range=function(t){return arguments.length?(u=Array.from(t),s()):u.slice()},f.rangeRound=function(t){return u=Array.from(t),c=th,s()},f.clamp=function(t){return arguments.length?(l=!!t||tv,s()):l!==tv},f.interpolate=function(t){return arguments.length?(c=t,s()):c},f.unknown=function(t){return arguments.length?(r=t,f):r},function(r,n){return t=r,e=n,s()}}function tO(){return tw()(tv,tv)}var tj=r(89999),tS=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function tP(t){var e;if(!(e=tS.exec(t)))throw Error("invalid format: "+t);return new tE({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function tE(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function tk(t,e){if((r=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var r,n=t.slice(0,r);return[n.length>1?n[0]+n.slice(2):n,+t.slice(r+1)]}function tA(t){return(t=tk(Math.abs(t)))?t[1]:NaN}function tM(t,e){var r=tk(t,e);if(!r)return t+"";var n=r[0],o=r[1];return o<0?"0."+Array(-o).join("0")+n:n.length>o+1?n.slice(0,o+1)+"."+n.slice(o+1):n+Array(o-n.length+2).join("0")}tP.prototype=tE.prototype,tE.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};var t_={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>tM(100*t,e),r:tM,s:function(t,e){var r=tk(t,e);if(!r)return t+"";var o=r[0],i=r[1],a=i-(n=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=o.length;return a===u?o:a>u?o+Array(a-u+1).join("0"):a>0?o.slice(0,a)+"."+o.slice(a):"0."+Array(1-a).join("0")+tk(t,Math.max(0,e+a-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function tT(t){return t}var tC=Array.prototype.map,tN=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"];function tD(t,e,r,n){var o,u,c=b(t,e,r);switch((n=tP(null==n?",f":n)).type){case"s":var l=Math.max(Math.abs(t),Math.abs(e));return null!=n.precision||isNaN(u=Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(tA(l)/3)))-tA(Math.abs(c))))||(n.precision=u),a(n,l);case"":case"e":case"g":case"p":case"r":null!=n.precision||isNaN(u=Math.max(0,tA(Math.abs(Math.max(Math.abs(t),Math.abs(e)))-(o=Math.abs(o=c)))-tA(o))+1)||(n.precision=u-("e"===n.type));break;case"f":case"%":null!=n.precision||isNaN(u=Math.max(0,-tA(Math.abs(c))))||(n.precision=u-("%"===n.type)*2)}return i(n)}function tI(t){var e=t.domain;return t.ticks=function(t){var r=e();return v(r[0],r[r.length-1],null==t?10:t)},t.tickFormat=function(t,r){var n=e();return tD(n[0],n[n.length-1],null==t?10:t,r)},t.nice=function(r){null==r&&(r=10);var n,o,i=e(),a=0,u=i.length-1,c=i[a],l=i[u],s=10;for(l0;){if((o=m(c,l,r))===n)return i[a]=c,i[u]=l,e(i);if(o>0)c=Math.floor(c/o)*o,l=Math.ceil(l/o)*o;else if(o<0)c=Math.ceil(c*o)/o,l=Math.floor(l*o)/o;else break;n=o}return t},t}function tL(){var t=tO();return t.copy=function(){return tx(t,tL())},tj.o.apply(t,arguments),tI(t)}function tB(t,e){t=t.slice();var r,n=0,o=t.length-1,i=t[n],a=t[o];return a-t(-e,r)}function tZ(t){let e,r;let n=t(tR,tz),o=n.domain,a=10;function u(){var i,u;return e=(i=a)===Math.E?Math.log:10===i&&Math.log10||2===i&&Math.log2||(i=Math.log(i),t=>Math.log(t)/i),r=10===(u=a)?t$:u===Math.E?Math.exp:t=>Math.pow(u,t),o()[0]<0?(e=tq(e),r=tq(r),t(tU,tF)):t(tR,tz),n}return n.base=function(t){return arguments.length?(a=+t,u()):a},n.domain=function(t){return arguments.length?(o(t),u()):o()},n.ticks=t=>{let n,i;let u=o(),c=u[0],l=u[u.length-1],s=l0){for(;f<=p;++f)for(n=1;nl)break;d.push(i)}}else for(;f<=p;++f)for(n=a-1;n>=1;--n)if(!((i=f>0?n/r(-f):n*r(f))l)break;d.push(i)}2*d.length{if(null==t&&(t=10),null==o&&(o=10===a?"s":","),"function"!=typeof o&&(a%1||null!=(o=tP(o)).precision||(o.trim=!0),o=i(o)),t===1/0)return o;let u=Math.max(1,a*t/n.ticks().length);return t=>{let n=t/r(Math.round(e(t)));return n*ao(tB(o(),{floor:t=>r(Math.floor(e(t))),ceil:t=>r(Math.ceil(e(t)))})),n}function tW(t){return function(e){return Math.sign(e)*Math.log1p(Math.abs(e/t))}}function tY(t){return function(e){return Math.sign(e)*Math.expm1(Math.abs(e))*t}}function tH(t){var e=1,r=t(tW(1),tY(e));return r.constant=function(r){return arguments.length?t(tW(e=+r),tY(e)):e},tI(r)}i=(o=function(t){var e,r,o,i=void 0===t.grouping||void 0===t.thousands?tT:(e=tC.call(t.grouping,Number),r=t.thousands+"",function(t,n){for(var o=t.length,i=[],a=0,u=e[0],c=0;o>0&&u>0&&(c+u+1>n&&(u=Math.max(1,n-c)),i.push(t.substring(o-=u,o+u)),!((c+=u+1)>n));)u=e[a=(a+1)%e.length];return i.reverse().join(r)}),a=void 0===t.currency?"":t.currency[0]+"",u=void 0===t.currency?"":t.currency[1]+"",c=void 0===t.decimal?".":t.decimal+"",l=void 0===t.numerals?tT:(o=tC.call(t.numerals,String),function(t){return t.replace(/[0-9]/g,function(t){return o[+t]})}),s=void 0===t.percent?"%":t.percent+"",f=void 0===t.minus?"āˆ’":t.minus+"",p=void 0===t.nan?"NaN":t.nan+"";function h(t){var e=(t=tP(t)).fill,r=t.align,o=t.sign,h=t.symbol,d=t.zero,y=t.width,v=t.comma,m=t.precision,b=t.trim,g=t.type;"n"===g?(v=!0,g="g"):t_[g]||(void 0===m&&(m=12),b=!0,g="g"),(d||"0"===e&&"="===r)&&(d=!0,e="0",r="=");var x="$"===h?a:"#"===h&&/[boxX]/.test(g)?"0"+g.toLowerCase():"",w="$"===h?u:/[%p]/.test(g)?s:"",O=t_[g],j=/[defgprs%]/.test(g);function S(t){var a,u,s,h=x,S=w;if("c"===g)S=O(t)+S,t="";else{var P=(t=+t)<0||1/t<0;if(t=isNaN(t)?p:O(Math.abs(t),m),b&&(t=function(t){e:for(var e,r=t.length,n=1,o=-1;n0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t}(t)),P&&0==+t&&"+"!==o&&(P=!1),h=(P?"("===o?o:f:"-"===o||"("===o?"":o)+h,S=("s"===g?tN[8+n/3]:"")+S+(P&&"("===o?")":""),j){for(a=-1,u=t.length;++a(s=t.charCodeAt(a))||s>57){S=(46===s?c+t.slice(a+1):t.slice(a))+S,t=t.slice(0,a);break}}}v&&!d&&(t=i(t,1/0));var E=h.length+t.length+S.length,k=E>1)+h+t+S+k.slice(E);break;default:t=k+h+t+S}return l(t)}return m=void 0===m?6:/[gprs]/.test(g)?Math.max(1,Math.min(21,m)):Math.max(0,Math.min(20,m)),S.toString=function(){return t+""},S}return{format:h,formatPrefix:function(t,e){var r=h(((t=tP(t)).type="f",t)),n=3*Math.max(-8,Math.min(8,Math.floor(tA(e)/3))),o=Math.pow(10,-n),i=tN[8+n/3];return function(t){return r(o*t)+i}}}}({thousands:",",grouping:[3],currency:["$",""]})).format,a=o.formatPrefix;var tX=r(36967);function tG(t){return function(e){return e<0?-Math.pow(-e,t):Math.pow(e,t)}}function tV(t){return t<0?-Math.sqrt(-t):Math.sqrt(t)}function tK(t){return t<0?-t*t:t*t}function tQ(t){var e=t(tv,tv),r=1;return e.exponent=function(e){return arguments.length?1==(r=+e)?t(tv,tv):.5===r?t(tV,tK):t(tG(r),tG(1/r)):r},tI(e)}function tJ(){var t=tQ(tw());return t.copy=function(){return tx(t,tJ()).exponent(t.exponent())},tj.o.apply(t,arguments),t}function t0(){return tJ.apply(null,arguments).exponent(.5)}function t1(t){return Math.sign(t)*t*t}function t2(t,e){let r;if(void 0===e)for(let e of t)null!=e&&(r=e)&&(r=e);else{let n=-1;for(let o of t)null!=(o=e(o,++n,t))&&(r=o)&&(r=o)}return r}function t5(t,e){let r;if(void 0===e)for(let e of t)null!=e&&(r>e||void 0===r&&e>=e)&&(r=e);else{let n=-1;for(let o of t)null!=(o=e(o,++n,t))&&(r>o||void 0===r&&o>=o)&&(r=o)}return r}function t6(t,e){return(null==t||!(t>=t))-(null==e||!(e>=e))||(te?1:0)}function t3(t,e,r){let n=t[e];t[e]=t[r],t[r]=n}let t7=new Date,t8=new Date;function t4(t,e,r,n){function o(e){return t(e=0==arguments.length?new Date:new Date(+e)),e}return o.floor=e=>(t(e=new Date(+e)),e),o.ceil=r=>(t(r=new Date(r-1)),e(r,1),t(r),r),o.round=t=>{let e=o(t),r=o.ceil(t);return t-e(e(t=new Date(+t),null==r?1:Math.floor(r)),t),o.range=(r,n,i)=>{let a;let u=[];if(r=o.ceil(r),i=null==i?1:Math.floor(i),!(r0))return u;do u.push(a=new Date(+r)),e(r,i),t(r);while(at4(e=>{if(e>=e)for(;t(e),!r(e);)e.setTime(e-1)},(t,n)=>{if(t>=t){if(n<0)for(;++n<=0;)for(;e(t,-1),!r(t););else for(;--n>=0;)for(;e(t,1),!r(t););}}),r&&(o.count=(e,n)=>(t7.setTime(+e),t8.setTime(+n),t(t7),t(t8),Math.floor(r(t7,t8))),o.every=t=>isFinite(t=Math.floor(t))&&t>0?t>1?o.filter(n?e=>n(e)%t==0:e=>o.count(0,e)%t==0):o:null),o}let t9=t4(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);t9.every=t=>isFinite(t=Math.floor(t))&&t>0?t>1?t4(e=>{e.setTime(Math.floor(e/t)*t)},(e,r)=>{e.setTime(+e+r*t)},(e,r)=>(r-e)/t):t9:null,t9.range;let et=t4(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+1e3*e)},(t,e)=>(e-t)/1e3,t=>t.getUTCSeconds());et.range;let ee=t4(t=>{t.setTime(t-t.getMilliseconds()-1e3*t.getSeconds())},(t,e)=>{t.setTime(+t+6e4*e)},(t,e)=>(e-t)/6e4,t=>t.getMinutes());ee.range;let er=t4(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+6e4*e)},(t,e)=>(e-t)/6e4,t=>t.getUTCMinutes());er.range;let en=t4(t=>{t.setTime(t-t.getMilliseconds()-1e3*t.getSeconds()-6e4*t.getMinutes())},(t,e)=>{t.setTime(+t+36e5*e)},(t,e)=>(e-t)/36e5,t=>t.getHours());en.range;let eo=t4(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+36e5*e)},(t,e)=>(e-t)/36e5,t=>t.getUTCHours());eo.range;let ei=t4(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5,t=>t.getDate()-1);ei.range;let ea=t4(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>t.getUTCDate()-1);ea.range;let eu=t4(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>Math.floor(t/864e5));function ec(t){return t4(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(t,e)=>{t.setDate(t.getDate()+7*e)},(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/6048e5)}eu.range;let el=ec(0),es=ec(1),ef=ec(2),ep=ec(3),eh=ec(4),ed=ec(5),ey=ec(6);function ev(t){return t4(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+7*e)},(t,e)=>(e-t)/6048e5)}el.range,es.range,ef.range,ep.range,eh.range,ed.range,ey.range;let em=ev(0),eb=ev(1),eg=ev(2),ex=ev(3),ew=ev(4),eO=ev(5),ej=ev(6);em.range,eb.range,eg.range,ex.range,ew.range,eO.range,ej.range;let eS=t4(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth());eS.range;let eP=t4(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth());eP.range;let eE=t4(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());eE.every=t=>isFinite(t=Math.floor(t))&&t>0?t4(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,r)=>{e.setFullYear(e.getFullYear()+r*t)}):null,eE.range;let ek=t4(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());function eA(t,e,r,n,o,i){let a=[[et,1,1e3],[et,5,5e3],[et,15,15e3],[et,30,3e4],[i,1,6e4],[i,5,3e5],[i,15,9e5],[i,30,18e5],[o,1,36e5],[o,3,108e5],[o,6,216e5],[o,12,432e5],[n,1,864e5],[n,2,1728e5],[r,1,6048e5],[e,1,2592e6],[e,3,7776e6],[t,1,31536e6]];function u(e,r,n){let o=Math.abs(r-e)/n,i=w(([,,t])=>t).right(a,o);if(i===a.length)return t.every(b(e/31536e6,r/31536e6,n));if(0===i)return t9.every(Math.max(b(e,r,n),1));let[u,c]=a[o/a[i-1][2]isFinite(t=Math.floor(t))&&t>0?t4(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCFullYear(e.getUTCFullYear()+r*t)}):null,ek.range;let[eM,e_]=eA(ek,eP,em,eu,eo,er),[eT,eC]=eA(eE,eS,el,ei,en,ee);function eN(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function eD(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function eI(t,e,r){return{y:t,m:e,d:r,H:0,M:0,S:0,L:0}}var eL={"-":"",_:" ",0:"0"},eB=/^\s*\d+/,eR=/^%/,ez=/[\\^$*+?|[\]().{}]/g;function eU(t,e,r){var n=t<0?"-":"",o=(n?-t:t)+"",i=o.length;return n+(i[t.toLowerCase(),e]))}function eZ(t,e,r){var n=eB.exec(e.slice(r,r+1));return n?(t.w=+n[0],r+n[0].length):-1}function eW(t,e,r){var n=eB.exec(e.slice(r,r+1));return n?(t.u=+n[0],r+n[0].length):-1}function eY(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.U=+n[0],r+n[0].length):-1}function eH(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.V=+n[0],r+n[0].length):-1}function eX(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.W=+n[0],r+n[0].length):-1}function eG(t,e,r){var n=eB.exec(e.slice(r,r+4));return n?(t.y=+n[0],r+n[0].length):-1}function eV(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.y=+n[0]+(+n[0]>68?1900:2e3),r+n[0].length):-1}function eK(t,e,r){var n=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(r,r+6));return n?(t.Z=n[1]?0:-(n[2]+(n[3]||"00")),r+n[0].length):-1}function eQ(t,e,r){var n=eB.exec(e.slice(r,r+1));return n?(t.q=3*n[0]-3,r+n[0].length):-1}function eJ(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function e0(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function e1(t,e,r){var n=eB.exec(e.slice(r,r+3));return n?(t.m=0,t.d=+n[0],r+n[0].length):-1}function e2(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function e5(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function e6(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function e3(t,e,r){var n=eB.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function e7(t,e,r){var n=eB.exec(e.slice(r,r+6));return n?(t.L=Math.floor(n[0]/1e3),r+n[0].length):-1}function e8(t,e,r){var n=eR.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function e4(t,e,r){var n=eB.exec(e.slice(r));return n?(t.Q=+n[0],r+n[0].length):-1}function e9(t,e,r){var n=eB.exec(e.slice(r));return n?(t.s=+n[0],r+n[0].length):-1}function rt(t,e){return eU(t.getDate(),e,2)}function re(t,e){return eU(t.getHours(),e,2)}function rr(t,e){return eU(t.getHours()%12||12,e,2)}function rn(t,e){return eU(1+ei.count(eE(t),t),e,3)}function ro(t,e){return eU(t.getMilliseconds(),e,3)}function ri(t,e){return ro(t,e)+"000"}function ra(t,e){return eU(t.getMonth()+1,e,2)}function ru(t,e){return eU(t.getMinutes(),e,2)}function rc(t,e){return eU(t.getSeconds(),e,2)}function rl(t){var e=t.getDay();return 0===e?7:e}function rs(t,e){return eU(el.count(eE(t)-1,t),e,2)}function rf(t){var e=t.getDay();return e>=4||0===e?eh(t):eh.ceil(t)}function rp(t,e){return t=rf(t),eU(eh.count(eE(t),t)+(4===eE(t).getDay()),e,2)}function rh(t){return t.getDay()}function rd(t,e){return eU(es.count(eE(t)-1,t),e,2)}function ry(t,e){return eU(t.getFullYear()%100,e,2)}function rv(t,e){return eU((t=rf(t)).getFullYear()%100,e,2)}function rm(t,e){return eU(t.getFullYear()%1e4,e,4)}function rb(t,e){var r=t.getDay();return eU((t=r>=4||0===r?eh(t):eh.ceil(t)).getFullYear()%1e4,e,4)}function rg(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+eU(e/60|0,"0",2)+eU(e%60,"0",2)}function rx(t,e){return eU(t.getUTCDate(),e,2)}function rw(t,e){return eU(t.getUTCHours(),e,2)}function rO(t,e){return eU(t.getUTCHours()%12||12,e,2)}function rj(t,e){return eU(1+ea.count(ek(t),t),e,3)}function rS(t,e){return eU(t.getUTCMilliseconds(),e,3)}function rP(t,e){return rS(t,e)+"000"}function rE(t,e){return eU(t.getUTCMonth()+1,e,2)}function rk(t,e){return eU(t.getUTCMinutes(),e,2)}function rA(t,e){return eU(t.getUTCSeconds(),e,2)}function rM(t){var e=t.getUTCDay();return 0===e?7:e}function r_(t,e){return eU(em.count(ek(t)-1,t),e,2)}function rT(t){var e=t.getUTCDay();return e>=4||0===e?ew(t):ew.ceil(t)}function rC(t,e){return t=rT(t),eU(ew.count(ek(t),t)+(4===ek(t).getUTCDay()),e,2)}function rN(t){return t.getUTCDay()}function rD(t,e){return eU(eb.count(ek(t)-1,t),e,2)}function rI(t,e){return eU(t.getUTCFullYear()%100,e,2)}function rL(t,e){return eU((t=rT(t)).getUTCFullYear()%100,e,2)}function rB(t,e){return eU(t.getUTCFullYear()%1e4,e,4)}function rR(t,e){var r=t.getUTCDay();return eU((t=r>=4||0===r?ew(t):ew.ceil(t)).getUTCFullYear()%1e4,e,4)}function rz(){return"+0000"}function rU(){return"%"}function rF(t){return+t}function r$(t){return Math.floor(+t/1e3)}function rq(t){return new Date(t)}function rZ(t){return t instanceof Date?+t:+new Date(+t)}function rW(t,e,r,n,o,i,a,u,c,l){var s=tO(),f=s.invert,p=s.domain,h=l(".%L"),d=l(":%S"),y=l("%I:%M"),v=l("%I %p"),m=l("%a %d"),b=l("%b %d"),g=l("%B"),x=l("%Y");function w(t){return(c(t)1)for(var r,n,o,i=1,a=t[e[0]],u=a.length;i=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:rF,s:r$,S:rc,u:rl,U:rs,V:rp,w:rh,W:rd,x:null,X:null,y:ry,Y:rm,Z:rg,"%":rU},x={a:function(t){return a[t.getUTCDay()]},A:function(t){return i[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return u[t.getUTCMonth()]},c:null,d:rx,e:rx,f:rP,g:rL,G:rR,H:rw,I:rO,j:rj,L:rS,m:rE,M:rk,p:function(t){return o[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:rF,s:r$,S:rA,u:rM,U:r_,V:rC,w:rN,W:rD,x:null,X:null,y:rI,Y:rB,Z:rz,"%":rU},w={a:function(t,e,r){var n=h.exec(e.slice(r));return n?(t.w=d.get(n[0].toLowerCase()),r+n[0].length):-1},A:function(t,e,r){var n=f.exec(e.slice(r));return n?(t.w=p.get(n[0].toLowerCase()),r+n[0].length):-1},b:function(t,e,r){var n=m.exec(e.slice(r));return n?(t.m=b.get(n[0].toLowerCase()),r+n[0].length):-1},B:function(t,e,r){var n=y.exec(e.slice(r));return n?(t.m=v.get(n[0].toLowerCase()),r+n[0].length):-1},c:function(t,r,n){return S(t,e,r,n)},d:e0,e:e0,f:e7,g:eV,G:eG,H:e2,I:e2,j:e1,L:e3,m:eJ,M:e5,p:function(t,e,r){var n=l.exec(e.slice(r));return n?(t.p=s.get(n[0].toLowerCase()),r+n[0].length):-1},q:eQ,Q:e4,s:e9,S:e6,u:eW,U:eY,V:eH,w:eZ,W:eX,x:function(t,e,n){return S(t,r,e,n)},X:function(t,e,r){return S(t,n,e,r)},y:eV,Y:eG,Z:eK,"%":e8};function O(t,e){return function(r){var n,o,i,a=[],u=-1,c=0,l=t.length;for(r instanceof Date||(r=new Date(+r));++u53)return null;"w"in i||(i.w=1),"Z"in i?(n=(o=(n=eD(eI(i.y,0,1))).getUTCDay())>4||0===o?eb.ceil(n):eb(n),n=ea.offset(n,(i.V-1)*7),i.y=n.getUTCFullYear(),i.m=n.getUTCMonth(),i.d=n.getUTCDate()+(i.w+6)%7):(n=(o=(n=eN(eI(i.y,0,1))).getDay())>4||0===o?es.ceil(n):es(n),n=ei.offset(n,(i.V-1)*7),i.y=n.getFullYear(),i.m=n.getMonth(),i.d=n.getDate()+(i.w+6)%7)}else("W"in i||"U"in i)&&("w"in i||(i.w="u"in i?i.u%7:"W"in i?1:0),o="Z"in i?eD(eI(i.y,0,1)).getUTCDay():eN(eI(i.y,0,1)).getDay(),i.m=0,i.d="W"in i?(i.w+6)%7+7*i.W-(o+5)%7:i.w+7*i.U-(o+6)%7);return"Z"in i?(i.H+=i.Z/100|0,i.M+=i.Z%100,eD(i)):eN(i)}}function S(t,e,r,n){for(var o,i,a=0,u=e.length,c=r.length;a=c)return -1;if(37===(o=e.charCodeAt(a++))){if(!(i=w[(o=e.charAt(a++))in eL?e.charAt(a++):o])||(n=i(t,r,n))<0)return -1}else if(o!=r.charCodeAt(n++))return -1}return n}return g.x=O(r,g),g.X=O(n,g),g.c=O(e,g),x.x=O(r,x),x.X=O(n,x),x.c=O(e,x),{format:function(t){var e=O(t+="",g);return e.toString=function(){return t},e},parse:function(t){var e=j(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=O(t+="",x);return e.toString=function(){return t},e},utcParse:function(t){var e=j(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]})).format,u.parse,l=u.utcFormat,u.utcParse;var r2=r(22516),r5=r(76115);function r6(t){for(var e=t.length,r=Array(e);--e>=0;)r[e]=e;return r}function r3(t,e){return t[e]}function r7(t){let e=[];return e.key=t,e}var r8=r(95645),r4=r.n(r8),r9=r(99008),nt=r.n(r9),ne=r(77571),nr=r.n(ne),nn=r(86757),no=r.n(nn),ni=r(42715),na=r.n(ni),nu=r(13735),nc=r.n(nu),nl=r(11314),ns=r.n(nl),nf=r(82559),np=r.n(nf),nh=r(75551),nd=r.n(nh),ny=r(21652),nv=r.n(ny),nm=r(34935),nb=r.n(nm),ng=r(61134),nx=r.n(ng);function nw(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r=e?r.apply(void 0,o):t(e-a,nP(function(){for(var t=arguments.length,e=Array(t),n=0;nt.length)&&(e=t.length);for(var r=0,n=Array(e);rn&&(o=n,i=r),[o,i]}function nR(t,e,r){if(t.lte(0))return new(nx())(0);var n=nC.getDigitCount(t.toNumber()),o=new(nx())(10).pow(n),i=t.div(o),a=1!==n?.05:.1,u=new(nx())(Math.ceil(i.div(a).toNumber())).add(r).mul(a).mul(o);return e?u:new(nx())(Math.ceil(u))}function nz(t,e,r){var n=1,o=new(nx())(t);if(!o.isint()&&r){var i=Math.abs(t);i<1?(n=new(nx())(10).pow(nC.getDigitCount(t)-1),o=new(nx())(Math.floor(o.div(n).toNumber())).mul(n)):i>1&&(o=new(nx())(Math.floor(t)))}else 0===t?o=new(nx())(Math.floor((e-1)/2)):r||(o=new(nx())(Math.floor(t)));var a=Math.floor((e-1)/2);return nM(nA(function(t){return o.add(new(nx())(t-a).mul(n)).toNumber()}),nk)(0,e)}var nU=nT(function(t){var e=nD(t,2),r=e[0],n=e[1],o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:6,i=!(arguments.length>2)||void 0===arguments[2]||arguments[2],a=Math.max(o,2),u=nD(nB([r,n]),2),c=u[0],l=u[1];if(c===-1/0||l===1/0){var s=l===1/0?[c].concat(nN(nk(0,o-1).map(function(){return 1/0}))):[].concat(nN(nk(0,o-1).map(function(){return-1/0})),[l]);return r>n?n_(s):s}if(c===l)return nz(c,o,i);var f=function t(e,r,n,o){var i,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0;if(!Number.isFinite((r-e)/(n-1)))return{step:new(nx())(0),tickMin:new(nx())(0),tickMax:new(nx())(0)};var u=nR(new(nx())(r).sub(e).div(n-1),o,a),c=Math.ceil((i=e<=0&&r>=0?new(nx())(0):(i=new(nx())(e).add(r).div(2)).sub(new(nx())(i).mod(u))).sub(e).div(u).toNumber()),l=Math.ceil(new(nx())(r).sub(i).div(u).toNumber()),s=c+l+1;return s>n?t(e,r,n,o,a+1):(s0?l+(n-s):l,c=r>0?c:c+(n-s)),{step:u,tickMin:i.sub(new(nx())(c).mul(u)),tickMax:i.add(new(nx())(l).mul(u))})}(c,l,a,i),p=f.step,h=f.tickMin,d=f.tickMax,y=nC.rangeStep(h,d.add(new(nx())(.1).mul(p)),p);return r>n?n_(y):y});nT(function(t){var e=nD(t,2),r=e[0],n=e[1],o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:6,i=!(arguments.length>2)||void 0===arguments[2]||arguments[2],a=Math.max(o,2),u=nD(nB([r,n]),2),c=u[0],l=u[1];if(c===-1/0||l===1/0)return[r,n];if(c===l)return nz(c,o,i);var s=nR(new(nx())(l).sub(c).div(a-1),i,0),f=nM(nA(function(t){return new(nx())(c).add(new(nx())(t).mul(s)).toNumber()}),nk)(0,a).filter(function(t){return t>=c&&t<=l});return r>n?n_(f):f});var nF=nT(function(t,e){var r=nD(t,2),n=r[0],o=r[1],i=!(arguments.length>2)||void 0===arguments[2]||arguments[2],a=nD(nB([n,o]),2),u=a[0],c=a[1];if(u===-1/0||c===1/0)return[n,o];if(u===c)return[u];var l=nR(new(nx())(c).sub(u).div(Math.max(e,2)-1),i,0),s=[].concat(nN(nC.rangeStep(new(nx())(u),new(nx())(c).sub(new(nx())(.99).mul(l)),l)),[c]);return n>o?n_(s):s}),n$=r(13137),nq=r(16630),nZ=r(82944),nW=r(38569);function nY(t){return(nY="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function nH(t){return function(t){if(Array.isArray(t))return nX(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return nX(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return nX(t,void 0)}}(t)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function nX(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2?arguments[2]:void 0,o=arguments.length>3?arguments[3]:void 0,i=-1,a=null!==(e=null==r?void 0:r.length)&&void 0!==e?e:0;if(a<=1)return 0;if(o&&"angleAxis"===o.axisType&&1e-6>=Math.abs(Math.abs(o.range[1]-o.range[0])-360))for(var u=o.range,c=0;c0?n[c-1].coordinate:n[a-1].coordinate,s=n[c].coordinate,f=c>=a-1?n[0].coordinate:n[c+1].coordinate,p=void 0;if((0,nq.uY)(s-l)!==(0,nq.uY)(f-s)){var h=[];if((0,nq.uY)(f-s)===(0,nq.uY)(u[1]-u[0])){p=f;var d=s+u[1]-u[0];h[0]=Math.min(d,(d+l)/2),h[1]=Math.max(d,(d+l)/2)}else{p=l;var y=f+u[1]-u[0];h[0]=Math.min(s,(y+s)/2),h[1]=Math.max(s,(y+s)/2)}var v=[Math.min(s,(p+s)/2),Math.max(s,(p+s)/2)];if(t>v[0]&&t<=v[1]||t>=h[0]&&t<=h[1]){i=n[c].index;break}}else{var m=Math.min(l,f),b=Math.max(l,f);if(t>(m+s)/2&&t<=(b+s)/2){i=n[c].index;break}}}else for(var g=0;g0&&g(r[g].coordinate+r[g-1].coordinate)/2&&t<=(r[g].coordinate+r[g+1].coordinate)/2||g===a-1&&t>(r[g].coordinate+r[g-1].coordinate)/2){i=r[g].index;break}return i},n1=function(t){var e,r,n=t.type.displayName,o=null!==(e=t.type)&&void 0!==e&&e.defaultProps?nV(nV({},t.type.defaultProps),t.props):t.props,i=o.stroke,a=o.fill;switch(n){case"Line":r=i;break;case"Area":case"Radar":r=i&&"none"!==i?i:a;break;default:r=a}return r},n2=function(t){var e=t.barSize,r=t.totalSize,n=t.stackGroups,o=void 0===n?{}:n;if(!o)return{};for(var i={},a=Object.keys(o),u=0,c=a.length;u=0});if(v&&v.length){var m=v[0].type.defaultProps,b=void 0!==m?nV(nV({},m),v[0].props):v[0].props,g=b.barSize,x=b[y];i[x]||(i[x]=[]);var w=nr()(g)?e:g;i[x].push({item:v[0],stackList:v.slice(1),barSize:nr()(w)?void 0:(0,nq.h1)(w,r,0)})}}return i},n5=function(t){var e,r=t.barGap,n=t.barCategoryGap,o=t.bandSize,i=t.sizeList,a=void 0===i?[]:i,u=t.maxBarSize,c=a.length;if(c<1)return null;var l=(0,nq.h1)(r,o,0,!0),s=[];if(a[0].barSize===+a[0].barSize){var f=!1,p=o/c,h=a.reduce(function(t,e){return t+e.barSize||0},0);(h+=(c-1)*l)>=o&&(h-=(c-1)*l,l=0),h>=o&&p>0&&(f=!0,p*=.9,h=c*p);var d={offset:((o-h)/2>>0)-l,size:0};e=a.reduce(function(t,e){var r={item:e.item,position:{offset:d.offset+d.size+l,size:f?p:e.barSize}},n=[].concat(nH(t),[r]);return d=n[n.length-1].position,e.stackList&&e.stackList.length&&e.stackList.forEach(function(t){n.push({item:t,position:d})}),n},s)}else{var y=(0,nq.h1)(n,o,0,!0);o-2*y-(c-1)*l<=0&&(l=0);var v=(o-2*y-(c-1)*l)/c;v>1&&(v>>=0);var m=u===+u?Math.min(v,u):v;e=a.reduce(function(t,e,r){var n=[].concat(nH(t),[{item:e.item,position:{offset:y+(v+l)*r+(v-m)/2,size:m}}]);return e.stackList&&e.stackList.length&&e.stackList.forEach(function(t){n.push({item:t,position:n[n.length-1].position})}),n},s)}return e},n6=function(t,e,r,n){var o=r.children,i=r.width,a=r.margin,u=i-(a.left||0)-(a.right||0),c=(0,nW.z)({children:o,legendWidth:u});if(c){var l=n||{},s=l.width,f=l.height,p=c.align,h=c.verticalAlign,d=c.layout;if(("vertical"===d||"horizontal"===d&&"middle"===h)&&"center"!==p&&(0,nq.hj)(t[p]))return nV(nV({},t),{},nK({},p,t[p]+(s||0)));if(("horizontal"===d||"vertical"===d&&"center"===p)&&"middle"!==h&&(0,nq.hj)(t[h]))return nV(nV({},t),{},nK({},h,t[h]+(f||0)))}return t},n3=function(t,e,r,n,o){var i=e.props.children,a=(0,nZ.NN)(i,n$.W).filter(function(t){var e;return e=t.props.direction,!!nr()(o)||("horizontal"===n?"yAxis"===o:"vertical"===n||"x"===e?"xAxis"===o:"y"!==e||"yAxis"===o)});if(a&&a.length){var u=a.map(function(t){return t.props.dataKey});return t.reduce(function(t,e){var n=nQ(e,r);if(nr()(n))return t;var o=Array.isArray(n)?[nt()(n),r4()(n)]:[n,n],i=u.reduce(function(t,r){var n=nQ(e,r,0),i=o[0]-Math.abs(Array.isArray(n)?n[0]:n),a=o[1]+Math.abs(Array.isArray(n)?n[1]:n);return[Math.min(i,t[0]),Math.max(a,t[1])]},[1/0,-1/0]);return[Math.min(i[0],t[0]),Math.max(i[1],t[1])]},[1/0,-1/0])}return null},n7=function(t,e,r,n,o){var i=e.map(function(e){return n3(t,e,r,o,n)}).filter(function(t){return!nr()(t)});return i&&i.length?i.reduce(function(t,e){return[Math.min(t[0],e[0]),Math.max(t[1],e[1])]},[1/0,-1/0]):null},n8=function(t,e,r,n,o){var i=e.map(function(e){var i=e.props.dataKey;return"number"===r&&i&&n3(t,e,i,n)||nJ(t,i,r,o)});if("number"===r)return i.reduce(function(t,e){return[Math.min(t[0],e[0]),Math.max(t[1],e[1])]},[1/0,-1/0]);var a={};return i.reduce(function(t,e){for(var r=0,n=e.length;r=2?2*(0,nq.uY)(a[0]-a[1])*c:c,e&&(t.ticks||t.niceTicks))?(t.ticks||t.niceTicks).map(function(t){return{coordinate:n(o?o.indexOf(t):t)+c,value:t,offset:c}}).filter(function(t){return!np()(t.coordinate)}):t.isCategorical&&t.categoricalDomain?t.categoricalDomain.map(function(t,e){return{coordinate:n(t)+c,value:t,index:e,offset:c}}):n.ticks&&!r?n.ticks(t.tickCount).map(function(t){return{coordinate:n(t)+c,value:t,offset:c}}):n.domain().map(function(t,e){return{coordinate:n(t)+c,value:o?o[t]:t,index:e,offset:c}})},oe=new WeakMap,or=function(t,e){if("function"!=typeof e)return t;oe.has(t)||oe.set(t,new WeakMap);var r=oe.get(t);if(r.has(e))return r.get(e);var n=function(){t.apply(void 0,arguments),e.apply(void 0,arguments)};return r.set(e,n),n},on=function(t,e,r){var n=t.scale,o=t.type,i=t.layout,a=t.axisType;if("auto"===n)return"radial"===i&&"radiusAxis"===a?{scale:f.Z(),realScaleType:"band"}:"radial"===i&&"angleAxis"===a?{scale:tL(),realScaleType:"linear"}:"category"===o&&e&&(e.indexOf("LineChart")>=0||e.indexOf("AreaChart")>=0||e.indexOf("ComposedChart")>=0&&!r)?{scale:f.x(),realScaleType:"point"}:"category"===o?{scale:f.Z(),realScaleType:"band"}:{scale:tL(),realScaleType:"linear"};if(na()(n)){var u="scale".concat(nd()(n));return{scale:(s[u]||f.x)(),realScaleType:s[u]?u:"point"}}return no()(n)?{scale:n}:{scale:f.x(),realScaleType:"point"}},oo=function(t){var e=t.domain();if(e&&!(e.length<=2)){var r=e.length,n=t.range(),o=Math.min(n[0],n[1])-1e-4,i=Math.max(n[0],n[1])+1e-4,a=t(e[0]),u=t(e[r-1]);(ai||ui)&&t.domain([e[0],e[r-1]])}},oi=function(t,e){if(!t)return null;for(var r=0,n=t.length;rn)&&(o[1]=n),o[0]>n&&(o[0]=n),o[1]=0?(t[a][r][0]=o,t[a][r][1]=o+u,o=t[a][r][1]):(t[a][r][0]=i,t[a][r][1]=i+u,i=t[a][r][1])}},expand:function(t,e){if((n=t.length)>0){for(var r,n,o,i=0,a=t[0].length;i0){for(var r,n=0,o=t[e[0]],i=o.length;n0&&(n=(r=t[e[0]]).length)>0){for(var r,n,o,i=0,a=1;a=0?(t[i][r][0]=o,t[i][r][1]=o+a,o=t[i][r][1]):(t[i][r][0]=0,t[i][r][1]=0)}}},oc=function(t,e,r){var n=e.map(function(t){return t.props.dataKey}),o=ou[r];return(function(){var t=(0,r5.Z)([]),e=r6,r=r1,n=r3;function o(o){var i,a,u=Array.from(t.apply(this,arguments),r7),c=u.length,l=-1;for(let t of o)for(i=0,++l;i=0?0:o<0?o:n}return r[0]},od=function(t,e){var r,n=(null!==(r=t.type)&&void 0!==r&&r.defaultProps?nV(nV({},t.type.defaultProps),t.props):t.props).stackId;if((0,nq.P2)(n)){var o=e[n];if(o){var i=o.items.indexOf(t);return i>=0?o.stackedData[i]:null}}return null},oy=function(t,e,r){return Object.keys(t).reduce(function(n,o){var i=t[o].stackedData.reduce(function(t,n){var o=n.slice(e,r+1).reduce(function(t,e){return[nt()(e.concat([t[0]]).filter(nq.hj)),r4()(e.concat([t[1]]).filter(nq.hj))]},[1/0,-1/0]);return[Math.min(t[0],o[0]),Math.max(t[1],o[1])]},[1/0,-1/0]);return[Math.min(i[0],n[0]),Math.max(i[1],n[1])]},[1/0,-1/0]).map(function(t){return t===1/0||t===-1/0?0:t})},ov=/^dataMin[\s]*-[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/,om=/^dataMax[\s]*\+[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/,ob=function(t,e,r){if(no()(t))return t(e,r);if(!Array.isArray(t))return e;var n=[];if((0,nq.hj)(t[0]))n[0]=r?t[0]:Math.min(t[0],e[0]);else if(ov.test(t[0])){var o=+ov.exec(t[0])[1];n[0]=e[0]-o}else no()(t[0])?n[0]=t[0](e[0]):n[0]=e[0];if((0,nq.hj)(t[1]))n[1]=r?t[1]:Math.max(t[1],e[1]);else if(om.test(t[1])){var i=+om.exec(t[1])[1];n[1]=e[1]+i}else no()(t[1])?n[1]=t[1](e[1]):n[1]=e[1];return n},og=function(t,e,r){if(t&&t.scale&&t.scale.bandwidth){var n=t.scale.bandwidth();if(!r||n>0)return n}if(t&&e&&e.length>=2){for(var o=nb()(e,function(t){return t.coordinate}),i=1/0,a=1,u=o.length;a1&&void 0!==arguments[1]?arguments[1]:{};if(null==t||n.x.isSsr)return{width:0,height:0};var o=(Object.keys(e=a({},r)).forEach(function(t){e[t]||delete e[t]}),e),i=JSON.stringify({text:t,copyStyle:o});if(u.widthCache[i])return u.widthCache[i];try{var s=document.getElementById(l);s||((s=document.createElement("span")).setAttribute("id",l),s.setAttribute("aria-hidden","true"),document.body.appendChild(s));var f=a(a({},c),o);Object.assign(s.style,f),s.textContent="".concat(t);var p=s.getBoundingClientRect(),h={width:p.width,height:p.height};return u.widthCache[i]=h,++u.cacheCount>2e3&&(u.cacheCount=0,u.widthCache={}),h}catch(t){return{width:0,height:0}}},f=function(t){return{top:t.top+window.scrollY-document.documentElement.clientTop,left:t.left+window.scrollX-document.documentElement.clientLeft}}},16630:function(t,e,r){"use strict";r.d(e,{Ap:function(){return S},EL:function(){return g},Kt:function(){return w},P2:function(){return m},Rw:function(){return v},bv:function(){return O},fC:function(){return P},h1:function(){return x},hU:function(){return d},hj:function(){return y},k4:function(){return j},uY:function(){return h}});var n=r(42715),o=r.n(n),i=r(82559),a=r.n(i),u=r(13735),c=r.n(u),l=r(22345),s=r.n(l),f=r(77571),p=r.n(f),h=function(t){return 0===t?0:t>0?1:-1},d=function(t){return o()(t)&&t.indexOf("%")===t.length-1},y=function(t){return s()(t)&&!a()(t)},v=function(t){return p()(t)},m=function(t){return y(t)||o()(t)},b=0,g=function(t){var e=++b;return"".concat(t||"").concat(e)},x=function(t,e){var r,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(!y(t)&&!o()(t))return n;if(d(t)){var u=t.indexOf("%");r=e*parseFloat(t.slice(0,u))/100}else r=+t;return a()(r)&&(r=n),i&&r>e&&(r=e),r},w=function(t){if(!t)return null;var e=Object.keys(t);return e&&e.length?t[e[0]]:null},O=function(t){if(!Array.isArray(t))return!1;for(var e=t.length,r={},n=0;n2?r-2:0),o=2;ot.length)&&(e=t.length);for(var r=0,n=Array(e);r2&&void 0!==arguments[2]?arguments[2]:{top:0,right:0,bottom:0,left:0};return Math.min(Math.abs(t-(r.left||0)-(r.right||0)),Math.abs(e-(r.top||0)-(r.bottom||0)))/2},b=function(t,e,r,n,i){var a=t.width,u=t.height,s=t.startAngle,f=t.endAngle,y=(0,c.h1)(t.cx,a,a/2),v=(0,c.h1)(t.cy,u,u/2),b=m(a,u,r),g=(0,c.h1)(t.innerRadius,b,0),x=(0,c.h1)(t.outerRadius,b,.8*b);return Object.keys(e).reduce(function(t,r){var a,u=e[r],c=u.domain,m=u.reversed;if(o()(u.range))"angleAxis"===n?a=[s,f]:"radiusAxis"===n&&(a=[g,x]),m&&(a=[a[1],a[0]]);else{var b,w=function(t){if(Array.isArray(t))return t}(b=a=u.range)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{for(i=(r=r.call(t)).next;!(c=(n=i.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(b,2)||function(t,e){if(t){if("string"==typeof t)return d(t,2);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return d(t,2)}}(b,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}();s=w[0],f=w[1]}var O=(0,l.Hq)(u,i),j=O.realScaleType,S=O.scale;S.domain(c).range(a),(0,l.zF)(S);var P=(0,l.g$)(S,p(p({},u),{},{realScaleType:j})),E=p(p(p({},u),P),{},{range:a,radius:x,realScaleType:j,scale:S,cx:y,cy:v,innerRadius:g,outerRadius:x,startAngle:s,endAngle:f});return p(p({},t),{},h({},r,E))},{})},g=function(t,e){var r=t.x,n=t.y;return Math.sqrt(Math.pow(r-e.x,2)+Math.pow(n-e.y,2))},x=function(t,e){var r=t.x,n=t.y,o=e.cx,i=e.cy,a=g({x:r,y:n},{x:o,y:i});if(a<=0)return{radius:a};var u=Math.acos((r-o)/a);return n>i&&(u=2*Math.PI-u),{radius:a,angle:180*u/Math.PI,angleInRadian:u}},w=function(t){var e=t.startAngle,r=t.endAngle,n=Math.min(Math.floor(e/360),Math.floor(r/360));return{startAngle:e-360*n,endAngle:r-360*n}},O=function(t,e){var r,n=x({x:t.x,y:t.y},e),o=n.radius,i=n.angle,a=e.innerRadius,u=e.outerRadius;if(ou)return!1;if(0===o)return!0;var c=w(e),l=c.startAngle,s=c.endAngle,f=i;if(l<=s){for(;f>s;)f-=360;for(;f=l&&f<=s}else{for(;f>l;)f-=360;for(;f=s&&f<=l}return r?p(p({},e),{},{radius:o,angle:f+360*Math.min(Math.floor(e.startAngle/360),Math.floor(e.endAngle/360))}):null},j=function(t){return(0,i.isValidElement)(t)||u()(t)||"boolean"==typeof t?"":t.className}},82944:function(t,e,r){"use strict";r.d(e,{$R:function(){return R},Bh:function(){return B},Gf:function(){return j},L6:function(){return N},NN:function(){return k},TT:function(){return M},eu:function(){return L},jf:function(){return T},rL:function(){return D},sP:function(){return A}});var n=r(13735),o=r.n(n),i=r(77571),a=r.n(i),u=r(42715),c=r.n(u),l=r(86757),s=r.n(l),f=r(28302),p=r.n(f),h=r(2265),d=r(14326),y=r(16630),v=r(46485),m=r(41637),b=["children"],g=["children"];function x(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r={};for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){if(e.indexOf(n)>=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function w(t){return(w="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var O={click:"onClick",mousedown:"onMouseDown",mouseup:"onMouseUp",mouseover:"onMouseOver",mousemove:"onMouseMove",mouseout:"onMouseOut",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",touchcancel:"onTouchCancel",touchend:"onTouchEnd",touchmove:"onTouchMove",touchstart:"onTouchStart",contextmenu:"onContextMenu",dblclick:"onDoubleClick"},j=function(t){return"string"==typeof t?t:t?t.displayName||t.name||"Component":""},S=null,P=null,E=function t(e){if(e===S&&Array.isArray(P))return P;var r=[];return h.Children.forEach(e,function(e){a()(e)||((0,d.isFragment)(e)?r=r.concat(t(e.props.children)):r.push(e))}),P=r,S=e,r};function k(t,e){var r=[],n=[];return n=Array.isArray(e)?e.map(function(t){return j(t)}):[j(e)],E(t).forEach(function(t){var e=o()(t,"type.displayName")||o()(t,"type.name");-1!==n.indexOf(e)&&r.push(t)}),r}function A(t,e){var r=k(t,e);return r&&r[0]}var M=function(t){if(!t||!t.props)return!1;var e=t.props,r=e.width,n=e.height;return!!(0,y.hj)(r)&&!(r<=0)&&!!(0,y.hj)(n)&&!(n<=0)},_=["a","altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","ellipse","feBlend","feColormatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-url","foreignObject","g","glyph","glyphRef","hkern","image","line","lineGradient","marker","mask","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","svg","switch","symbol","text","textPath","title","tref","tspan","use","view","vkern"],T=function(t){return t&&"object"===w(t)&&"clipDot"in t},C=function(t,e,r,n){var o,i=null!==(o=null===m.ry||void 0===m.ry?void 0:m.ry[n])&&void 0!==o?o:[];return e.startsWith("data-")||!s()(t)&&(n&&i.includes(e)||m.Yh.includes(e))||r&&m.nv.includes(e)},N=function(t,e,r){if(!t||"function"==typeof t||"boolean"==typeof t)return null;var n=t;if((0,h.isValidElement)(t)&&(n=t.props),!p()(n))return null;var o={};return Object.keys(n).forEach(function(t){var i;C(null===(i=n)||void 0===i?void 0:i[t],t,e,r)&&(o[t]=n[t])}),o},D=function t(e,r){if(e===r)return!0;var n=h.Children.count(e);if(n!==h.Children.count(r))return!1;if(0===n)return!0;if(1===n)return I(Array.isArray(e)?e[0]:e,Array.isArray(r)?r[0]:r);for(var o=0;o=0)r.push(t);else if(t){var i=j(t.type),a=e[i]||{},u=a.handler,l=a.once;if(u&&(!l||!n[i])){var s=u(t,i,o);r.push(s),n[i]=!0}}}),r},B=function(t){var e=t&&t.type;return e&&O[e]?O[e]:null},R=function(t,e){return E(e).indexOf(t)}},46485:function(t,e,r){"use strict";function n(t,e){for(var r in t)if(({}).hasOwnProperty.call(t,r)&&(!({}).hasOwnProperty.call(e,r)||t[r]!==e[r]))return!1;for(var n in e)if(({}).hasOwnProperty.call(e,n)&&!({}).hasOwnProperty.call(t,n))return!1;return!0}r.d(e,{w:function(){return n}})},38569:function(t,e,r){"use strict";r.d(e,{z:function(){return l}});var n=r(22190),o=r(85355),i=r(82944);function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function u(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function c(t){for(var e=1;e=0))throw Error(`invalid digits: ${t}`);if(e>15)return a;let r=10**e;return function(t){this._+=t[0];for(let e=1,n=t.length;e1e-6){if(Math.abs(f*c-l*s)>1e-6&&i){let h=r-a,d=o-u,y=c*c+l*l,v=Math.sqrt(y),m=Math.sqrt(p),b=i*Math.tan((n-Math.acos((y+p-(h*h+d*d))/(2*v*m)))/2),g=b/m,x=b/v;Math.abs(g-1)>1e-6&&this._append`L${t+g*s},${e+g*f}`,this._append`A${i},${i},0,0,${+(f*h>s*d)},${this._x1=t+x*c},${this._y1=e+x*l}`}else this._append`L${this._x1=t},${this._y1=e}`}}arc(t,e,r,a,u,c){if(t=+t,e=+e,c=!!c,(r=+r)<0)throw Error(`negative radius: ${r}`);let l=r*Math.cos(a),s=r*Math.sin(a),f=t+l,p=e+s,h=1^c,d=c?a-u:u-a;null===this._x1?this._append`M${f},${p}`:(Math.abs(this._x1-f)>1e-6||Math.abs(this._y1-p)>1e-6)&&this._append`L${f},${p}`,r&&(d<0&&(d=d%o+o),d>i?this._append`A${r},${r},0,1,${h},${t-l},${e-s}A${r},${r},0,1,${h},${this._x1=f},${this._y1=p}`:d>1e-6&&this._append`A${r},${r},0,${+(d>=n)},${h},${this._x1=t+r*Math.cos(u)},${this._y1=e+r*Math.sin(u)}`)}rect(t,e,r,n){this._append`M${this._x0=this._x1=+t},${this._y0=this._y1=+e}h${r=+r}v${+n}h${-r}Z`}toString(){return this._}}function c(t){let e=3;return t.digits=function(r){if(!arguments.length)return e;if(null==r)e=null;else{let t=Math.floor(r);if(!(t>=0))throw RangeError(`invalid digits: ${r}`);e=t}return t},()=>new u(e)}u.prototype},59121:function(t,e,r){"use strict";r.d(e,{E:function(){return i}});var n=r(99649),o=r(63497);function i(t,e){let r=(0,n.Q)(t);return isNaN(e)?(0,o.L)(t,NaN):(e&&r.setDate(r.getDate()+e),r)}},31091:function(t,e,r){"use strict";r.d(e,{z:function(){return i}});var n=r(99649),o=r(63497);function i(t,e){let r=(0,n.Q)(t);if(isNaN(e))return(0,o.L)(t,NaN);if(!e)return r;let i=r.getDate(),a=(0,o.L)(t,r.getTime());return(a.setMonth(r.getMonth()+e+1,0),i>=a.getDate())?a:(r.setFullYear(a.getFullYear(),a.getMonth(),i),r)}},63497:function(t,e,r){"use strict";function n(t,e){return t instanceof Date?new t.constructor(e):new Date(e)}r.d(e,{L:function(){return n}})},99649:function(t,e,r){"use strict";function n(t){let e=Object.prototype.toString.call(t);return t instanceof Date||"object"==typeof t&&"[object Date]"===e?new t.constructor(+t):new Date("number"==typeof t||"[object Number]"===e||"string"==typeof t||"[object String]"===e?t:NaN)}r.d(e,{Q:function(){return n}})},69398:function(t,e,r){"use strict";function n(t,e){if(!t)throw Error("Invariant failed")}r.d(e,{Z:function(){return n}})}}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1108],{40278:function(t,e,r){"use strict";r.d(e,{Z:function(){return S}});var n=r(5853),o=r(7084),i=r(26898),a=r(13241),u=r(1153),c=r(2265),l=r(47625),s=r(93765),f=r(31699),p=r(97059),h=r(62994),d=r(25311),y=(0,s.z)({chartName:"BarChart",GraphicalChild:f.$,defaultTooltipEventType:"axis",validateTooltipEventTypes:["axis","item"],axisComponents:[{axisType:"xAxis",AxisComp:p.K},{axisType:"yAxis",AxisComp:h.B}],formatAxisMap:d.t9}),v=r(56940),m=r(26680),b=r(8147),g=r(22190),x=r(65278),w=r(98593),O=r(92666),j=r(32644);let S=c.forwardRef((t,e)=>{let{data:r=[],categories:s=[],index:d,colors:S=i.s,valueFormatter:P=u.Cj,layout:E="horizontal",stack:k=!1,relative:A=!1,startEndOnly:M=!1,animationDuration:_=900,showAnimation:T=!1,showXAxis:C=!0,showYAxis:N=!0,yAxisWidth:D=56,intervalType:I="equidistantPreserveStart",showTooltip:L=!0,showLegend:B=!0,showGridLines:R=!0,autoMinValue:z=!1,minValue:U,maxValue:F,allowDecimals:$=!0,noDataText:q,onValueChange:Z,enableLegendSlider:W=!1,customTooltip:Y,rotateLabelX:H,barCategoryGap:X,tickGap:G=5,xAxisLabel:V,yAxisLabel:K,className:Q,padding:J=C||N?{left:20,right:20}:{left:0,right:0}}=t,tt=(0,n._T)(t,["data","categories","index","colors","valueFormatter","layout","stack","relative","startEndOnly","animationDuration","showAnimation","showXAxis","showYAxis","yAxisWidth","intervalType","showTooltip","showLegend","showGridLines","autoMinValue","minValue","maxValue","allowDecimals","noDataText","onValueChange","enableLegendSlider","customTooltip","rotateLabelX","barCategoryGap","tickGap","xAxisLabel","yAxisLabel","className","padding"]),[te,tr]=(0,c.useState)(60),tn=(0,j.me)(s,S),[to,ti]=c.useState(void 0),[ta,tu]=(0,c.useState)(void 0),tc=!!Z;function tl(t,e,r){var n,o,i,a;r.stopPropagation(),Z&&((0,j.vZ)(to,Object.assign(Object.assign({},t.payload),{value:t.value}))?(tu(void 0),ti(void 0),null==Z||Z(null)):(tu(null===(o=null===(n=t.tooltipPayload)||void 0===n?void 0:n[0])||void 0===o?void 0:o.dataKey),ti(Object.assign(Object.assign({},t.payload),{value:t.value})),null==Z||Z(Object.assign({eventType:"bar",categoryClicked:null===(a=null===(i=t.tooltipPayload)||void 0===i?void 0:i[0])||void 0===a?void 0:a.dataKey},t.payload))))}let ts=(0,j.i4)(z,U,F);return c.createElement("div",Object.assign({ref:e,className:(0,a.q)("w-full h-80",Q)},tt),c.createElement(l.h,{className:"h-full w-full"},(null==r?void 0:r.length)?c.createElement(y,{barCategoryGap:X,data:r,stackOffset:k?"sign":A?"expand":"none",layout:"vertical"===E?"vertical":"horizontal",onClick:tc&&(ta||to)?()=>{ti(void 0),tu(void 0),null==Z||Z(null)}:void 0,margin:{bottom:V?30:void 0,left:K?20:void 0,right:K?5:void 0,top:5}},R?c.createElement(v.q,{className:(0,a.q)("stroke-1","stroke-tremor-border","dark:stroke-dark-tremor-border"),horizontal:"vertical"!==E,vertical:"vertical"===E}):null,"vertical"!==E?c.createElement(p.K,{padding:J,hide:!C,dataKey:d,interval:M?"preserveStartEnd":I,tick:{transform:"translate(0, 6)"},ticks:M?[r[0][d],r[r.length-1][d]]:void 0,fill:"",stroke:"",className:(0,a.q)("mt-4 text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content"),tickLine:!1,axisLine:!1,angle:null==H?void 0:H.angle,dy:null==H?void 0:H.verticalShift,height:null==H?void 0:H.xAxisHeight,minTickGap:G},V&&c.createElement(m._,{position:"insideBottom",offset:-20,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},V)):c.createElement(p.K,{hide:!C,type:"number",tick:{transform:"translate(-3, 0)"},domain:ts,fill:"",stroke:"",className:(0,a.q)("text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content"),tickLine:!1,axisLine:!1,tickFormatter:P,minTickGap:G,allowDecimals:$,angle:null==H?void 0:H.angle,dy:null==H?void 0:H.verticalShift,height:null==H?void 0:H.xAxisHeight},V&&c.createElement(m._,{position:"insideBottom",offset:-20,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},V)),"vertical"!==E?c.createElement(h.B,{width:D,hide:!N,axisLine:!1,tickLine:!1,type:"number",domain:ts,tick:{transform:"translate(-3, 0)"},fill:"",stroke:"",className:(0,a.q)("text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content"),tickFormatter:A?t=>"".concat((100*t).toString()," %"):P,allowDecimals:$},K&&c.createElement(m._,{position:"insideLeft",style:{textAnchor:"middle"},angle:-90,offset:-15,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},K)):c.createElement(h.B,{width:D,hide:!N,dataKey:d,axisLine:!1,tickLine:!1,ticks:M?[r[0][d],r[r.length-1][d]]:void 0,type:"category",interval:"preserveStartEnd",tick:{transform:"translate(0, 6)"},fill:"",stroke:"",className:(0,a.q)("text-tremor-label","fill-tremor-content","dark:fill-dark-tremor-content")},K&&c.createElement(m._,{position:"insideLeft",style:{textAnchor:"middle"},angle:-90,offset:-15,className:"fill-tremor-content-emphasis text-tremor-default font-medium dark:fill-dark-tremor-content-emphasis"},K)),c.createElement(b.u,{wrapperStyle:{outline:"none"},isAnimationActive:!1,cursor:{fill:"#d1d5db",opacity:"0.15"},content:L?t=>{let{active:e,payload:r,label:n}=t;return Y?c.createElement(Y,{payload:null==r?void 0:r.map(t=>{var e;return Object.assign(Object.assign({},t),{color:null!==(e=tn.get(t.dataKey))&&void 0!==e?e:o.fr.Gray})}),active:e,label:n}):c.createElement(w.ZP,{active:e,payload:r,label:n,valueFormatter:P,categoryColors:tn})}:c.createElement(c.Fragment,null),position:{y:0}}),B?c.createElement(g.D,{verticalAlign:"top",height:te,content:t=>{let{payload:e}=t;return(0,x.Z)({payload:e},tn,tr,ta,tc?t=>{tc&&(t!==ta||to?(tu(t),null==Z||Z({eventType:"category",categoryClicked:t})):(tu(void 0),null==Z||Z(null)),ti(void 0))}:void 0,W)}}):null,s.map(t=>{var e;return c.createElement(f.$,{className:(0,a.q)((0,u.bM)(null!==(e=tn.get(t))&&void 0!==e?e:o.fr.Gray,i.K.background).fillColor,Z?"cursor-pointer":""),key:t,name:t,type:"linear",stackId:k||A?"a":void 0,dataKey:t,fill:"",isAnimationActive:T,animationDuration:_,shape:t=>((t,e,r,n)=>{let{fillOpacity:o,name:i,payload:a,value:u}=t,{x:l,width:s,y:f,height:p}=t;return"horizontal"===n&&p<0?(f+=p,p=Math.abs(p)):"vertical"===n&&s<0&&(l+=s,s=Math.abs(s)),c.createElement("rect",{x:l,y:f,width:s,height:p,opacity:e||r&&r!==i?(0,j.vZ)(e,Object.assign(Object.assign({},a),{value:u}))?o:.3:o})})(t,to,ta,E),onClick:tl})})):c.createElement(O.Z,{noDataText:q})))});S.displayName="BarChart"},65278:function(t,e,r){"use strict";r.d(e,{Z:function(){return y}});var n=r(2265);let o=t=>{n.useEffect(()=>{let e=()=>{t()};return e(),window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[t])};var i=r(5853),a=r(26898),u=r(13241),c=r(1153);let l=t=>{var e=(0,i._T)(t,[]);return n.createElement("svg",Object.assign({},e,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"}),n.createElement("path",{d:"M8 12L14 6V18L8 12Z"}))},s=t=>{var e=(0,i._T)(t,[]);return n.createElement("svg",Object.assign({},e,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"}),n.createElement("path",{d:"M16 12L10 18V6L16 12Z"}))},f=(0,c.fn)("Legend"),p=t=>{let{name:e,color:r,onClick:o,activeLegend:i}=t,l=!!o;return n.createElement("li",{className:(0,u.q)(f("legendItem"),"group inline-flex items-center px-2 py-0.5 rounded-tremor-small transition whitespace-nowrap",l?"cursor-pointer":"cursor-default","text-tremor-content",l?"hover:bg-tremor-background-subtle":"","dark:text-dark-tremor-content",l?"dark:hover:bg-dark-tremor-background-subtle":""),onClick:t=>{t.stopPropagation(),null==o||o(e,r)}},n.createElement("svg",{className:(0,u.q)("flex-none h-2 w-2 mr-1.5",(0,c.bM)(r,a.K.text).textColor,i&&i!==e?"opacity-40":"opacity-100"),fill:"currentColor",viewBox:"0 0 8 8"},n.createElement("circle",{cx:4,cy:4,r:4})),n.createElement("p",{className:(0,u.q)("whitespace-nowrap truncate text-tremor-default","text-tremor-content",l?"group-hover:text-tremor-content-emphasis":"","dark:text-dark-tremor-content",i&&i!==e?"opacity-40":"opacity-100",l?"dark:group-hover:text-dark-tremor-content-emphasis":"")},e))},h=t=>{let{icon:e,onClick:r,disabled:o}=t,[i,a]=n.useState(!1),c=n.useRef(null);return n.useEffect(()=>(i?c.current=setInterval(()=>{null==r||r()},300):clearInterval(c.current),()=>clearInterval(c.current)),[i,r]),(0,n.useEffect)(()=>{o&&(clearInterval(c.current),a(!1))},[o]),n.createElement("button",{type:"button",className:(0,u.q)(f("legendSliderButton"),"w-5 group inline-flex items-center truncate rounded-tremor-small transition",o?"cursor-not-allowed":"cursor-pointer",o?"text-tremor-content-subtle":"text-tremor-content hover:text-tremor-content-emphasis hover:bg-tremor-background-subtle",o?"dark:text-dark-tremor-subtle":"dark:text-dark-tremor dark:hover:text-tremor-content-emphasis dark:hover:bg-dark-tremor-background-subtle"),disabled:o,onClick:t=>{t.stopPropagation(),null==r||r()},onMouseDown:t=>{t.stopPropagation(),a(!0)},onMouseUp:t=>{t.stopPropagation(),a(!1)}},n.createElement(e,{className:"w-full"}))},d=n.forwardRef((t,e)=>{let{categories:r,colors:o=a.s,className:c,onClickLegendItem:d,activeLegend:y,enableLegendSlider:v=!1}=t,m=(0,i._T)(t,["categories","colors","className","onClickLegendItem","activeLegend","enableLegendSlider"]),b=n.useRef(null),g=n.useRef(null),[x,w]=n.useState(null),[O,j]=n.useState(null),S=n.useRef(null),P=(0,n.useCallback)(()=>{let t=null==b?void 0:b.current;t&&w({left:t.scrollLeft>0,right:t.scrollWidth-t.clientWidth>t.scrollLeft})},[w]),E=(0,n.useCallback)(t=>{var e,r;let n=null==b?void 0:b.current,o=null==g?void 0:g.current,i=null!==(e=null==n?void 0:n.clientWidth)&&void 0!==e?e:0,a=null!==(r=null==o?void 0:o.clientWidth)&&void 0!==r?r:0;n&&v&&(n.scrollTo({left:"left"===t?n.scrollLeft-i+a:n.scrollLeft+i-a,behavior:"smooth"}),setTimeout(()=>{P()},400))},[v,P]);n.useEffect(()=>{let t=t=>{"ArrowLeft"===t?E("left"):"ArrowRight"===t&&E("right")};return O?(t(O),S.current=setInterval(()=>{t(O)},300)):clearInterval(S.current),()=>clearInterval(S.current)},[O,E]);let k=t=>{t.stopPropagation(),"ArrowLeft"!==t.key&&"ArrowRight"!==t.key||(t.preventDefault(),j(t.key))},A=t=>{t.stopPropagation(),j(null)};return n.useEffect(()=>{let t=null==b?void 0:b.current;return v&&(P(),null==t||t.addEventListener("keydown",k),null==t||t.addEventListener("keyup",A)),()=>{null==t||t.removeEventListener("keydown",k),null==t||t.removeEventListener("keyup",A)}},[P,v]),n.createElement("ol",Object.assign({ref:e,className:(0,u.q)(f("root"),"relative overflow-hidden",c)},m),n.createElement("div",{ref:b,tabIndex:0,className:(0,u.q)("h-full flex",v?(null==x?void 0:x.right)||(null==x?void 0:x.left)?"pl-4 pr-12 items-center overflow-auto snap-mandatory [&::-webkit-scrollbar]:hidden [scrollbar-width:none]":"":"flex-wrap")},r.map((t,e)=>n.createElement(p,{key:"item-".concat(e),name:t,color:o[e%o.length],onClick:d,activeLegend:y}))),v&&((null==x?void 0:x.right)||(null==x?void 0:x.left))?n.createElement(n.Fragment,null,n.createElement("div",{className:(0,u.q)("bg-tremor-background","dark:bg-dark-tremor-background","absolute flex top-0 pr-1 bottom-0 right-0 items-center justify-center h-full"),ref:g},n.createElement(h,{icon:l,onClick:()=>{j(null),E("left")},disabled:!(null==x?void 0:x.left)}),n.createElement(h,{icon:s,onClick:()=>{j(null),E("right")},disabled:!(null==x?void 0:x.right)}))):null)});d.displayName="Legend";let y=(t,e,r,i,a,u)=>{let{payload:c}=t,l=(0,n.useRef)(null);o(()=>{var t,e;r((e=null===(t=l.current)||void 0===t?void 0:t.clientHeight)?Number(e)+20:60)});let s=c.filter(t=>"none"!==t.type);return n.createElement("div",{ref:l,className:"flex items-center justify-end"},n.createElement(d,{categories:s.map(t=>t.value),colors:s.map(t=>e.get(t.value)),onClickLegendItem:a,activeLegend:i,enableLegendSlider:u}))}},98593:function(t,e,r){"use strict";r.d(e,{$B:function(){return c},ZP:function(){return s},zX:function(){return l}});var n=r(2265),o=r(7084),i=r(26898),a=r(13241),u=r(1153);let c=t=>{let{children:e}=t;return n.createElement("div",{className:(0,a.q)("rounded-tremor-default text-tremor-default border","bg-tremor-background shadow-tremor-dropdown border-tremor-border","dark:bg-dark-tremor-background dark:shadow-dark-tremor-dropdown dark:border-dark-tremor-border")},e)},l=t=>{let{value:e,name:r,color:o}=t;return n.createElement("div",{className:"flex items-center justify-between space-x-8"},n.createElement("div",{className:"flex items-center space-x-2"},n.createElement("span",{className:(0,a.q)("shrink-0 rounded-tremor-full border-2 h-3 w-3","border-tremor-background shadow-tremor-card","dark:border-dark-tremor-background dark:shadow-dark-tremor-card",(0,u.bM)(o,i.K.background).bgColor)}),n.createElement("p",{className:(0,a.q)("text-right whitespace-nowrap","text-tremor-content","dark:text-dark-tremor-content")},r)),n.createElement("p",{className:(0,a.q)("font-medium tabular-nums text-right whitespace-nowrap","text-tremor-content-emphasis","dark:text-dark-tremor-content-emphasis")},e))},s=t=>{let{active:e,payload:r,label:i,categoryColors:u,valueFormatter:s}=t;if(e&&r){let t=r.filter(t=>"none"!==t.type);return n.createElement(c,null,n.createElement("div",{className:(0,a.q)("border-tremor-border border-b px-4 py-2","dark:border-dark-tremor-border")},n.createElement("p",{className:(0,a.q)("font-medium","text-tremor-content-emphasis","dark:text-dark-tremor-content-emphasis")},i)),n.createElement("div",{className:(0,a.q)("px-4 py-2 space-y-1")},t.map((t,e)=>{var r;let{value:i,name:a}=t;return n.createElement(l,{key:"id-".concat(e),value:s(i),name:a,color:null!==(r=u.get(a))&&void 0!==r?r:o.fr.Blue})})))}return null}},92666:function(t,e,r){"use strict";r.d(e,{Z:function(){return i}});var n=r(13241),o=r(2265);let i=t=>{let{className:e,noDataText:r="No data"}=t;return o.createElement("div",{className:(0,n.q)("flex items-center justify-center w-full h-full border border-dashed rounded-tremor-default","border-tremor-border","dark:border-dark-tremor-border",e)},o.createElement("p",{className:(0,n.q)("text-tremor-content text-tremor-default","dark:text-dark-tremor-content")},r))}},32644:function(t,e,r){"use strict";r.d(e,{FB:function(){return i},i4:function(){return o},me:function(){return n},vZ:function(){return function t(e,r){if(e===r)return!0;if("object"!=typeof e||"object"!=typeof r||null===e||null===r)return!1;let n=Object.keys(e),o=Object.keys(r);if(n.length!==o.length)return!1;for(let i of n)if(!o.includes(i)||!t(e[i],r[i]))return!1;return!0}}});let n=(t,e)=>{let r=new Map;return t.forEach((t,n)=>{r.set(t,e[n%e.length])}),r},o=(t,e,r)=>[t?"auto":null!=e?e:0,null!=r?r:"auto"];function i(t,e){let r=[];for(let n of t)if(Object.prototype.hasOwnProperty.call(n,e)&&(r.push(n[e]),r.length>1))return!1;return!0}},49804:function(t,e,r){"use strict";r.d(e,{Z:function(){return l}});var n=r(5853),o=r(13241),i=r(1153),a=r(2265),u=r(9496);let c=(0,i.fn)("Col"),l=a.forwardRef((t,e)=>{let{numColSpan:r=1,numColSpanSm:i,numColSpanMd:l,numColSpanLg:s,children:f,className:p}=t,h=(0,n._T)(t,["numColSpan","numColSpanSm","numColSpanMd","numColSpanLg","children","className"]),d=(t,e)=>t&&Object.keys(e).includes(String(t))?e[t]:"";return a.createElement("div",Object.assign({ref:e,className:(0,o.q)(c("root"),(()=>{let t=d(r,u.PT),e=d(i,u.SP),n=d(l,u.VS),a=d(s,u._w);return(0,o.q)(t,e,n,a)})(),p)},h),f)});l.displayName="Col"},97765:function(t,e,r){"use strict";r.d(e,{Z:function(){return c}});var n=r(5853),o=r(26898),i=r(13241),a=r(1153),u=r(2265);let c=u.forwardRef((t,e)=>{let{color:r,children:c,className:l}=t,s=(0,n._T)(t,["color","children","className"]);return u.createElement("p",Object.assign({ref:e,className:(0,i.q)(r?(0,a.bM)(r,o.K.lightText).textColor:"text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis",l)},s),c)});c.displayName="Subtitle"},61134:function(t,e,r){var n;!function(o){"use strict";var i,a={precision:20,rounding:4,toExpNeg:-7,toExpPos:21,LN10:"2.302585092994045684017991454684364207601101488628772976033327900967572609677352480235997205089598298341967784042286"},u=!0,c="[DecimalError] ",l=c+"Invalid argument: ",s=c+"Exponent out of range: ",f=Math.floor,p=Math.pow,h=/^(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,d=f(1286742750677284.5),y={};function v(t,e){var r,n,o,i,a,c,l,s,f=t.constructor,p=f.precision;if(!t.s||!e.s)return e.s||(e=new f(t)),u?E(e,p):e;if(l=t.d,s=e.d,a=t.e,o=e.e,l=l.slice(),i=a-o){for(i<0?(n=l,i=-i,c=s.length):(n=s,o=a,c=l.length),i>(c=(a=Math.ceil(p/7))>c?a+1:c+1)&&(i=c,n.length=1),n.reverse();i--;)n.push(0);n.reverse()}for((c=l.length)-(i=s.length)<0&&(i=c,n=s,s=l,l=n),r=0;i;)r=(l[--i]=l[i]+s[i]+r)/1e7|0,l[i]%=1e7;for(r&&(l.unshift(r),++o),c=l.length;0==l[--c];)l.pop();return e.d=l,e.e=o,u?E(e,p):e}function m(t,e,r){if(t!==~~t||tr)throw Error(l+t)}function b(t){var e,r,n,o=t.length-1,i="",a=t[0];if(o>0){for(i+=a,e=1;et.e^this.s<0?1:-1;for(e=0,r=(n=this.d.length)<(o=t.d.length)?n:o;et.d[e]^this.s<0?1:-1;return n===o?0:n>o^this.s<0?1:-1},y.decimalPlaces=y.dp=function(){var t=this.d.length-1,e=(t-this.e)*7;if(t=this.d[t])for(;t%10==0;t/=10)e--;return e<0?0:e},y.dividedBy=y.div=function(t){return g(this,new this.constructor(t))},y.dividedToIntegerBy=y.idiv=function(t){var e=this.constructor;return E(g(this,new e(t),0,1),e.precision)},y.equals=y.eq=function(t){return!this.cmp(t)},y.exponent=function(){return w(this)},y.greaterThan=y.gt=function(t){return this.cmp(t)>0},y.greaterThanOrEqualTo=y.gte=function(t){return this.cmp(t)>=0},y.isInteger=y.isint=function(){return this.e>this.d.length-2},y.isNegative=y.isneg=function(){return this.s<0},y.isPositive=y.ispos=function(){return this.s>0},y.isZero=function(){return 0===this.s},y.lessThan=y.lt=function(t){return 0>this.cmp(t)},y.lessThanOrEqualTo=y.lte=function(t){return 1>this.cmp(t)},y.logarithm=y.log=function(t){var e,r=this.constructor,n=r.precision,o=n+5;if(void 0===t)t=new r(10);else if((t=new r(t)).s<1||t.eq(i))throw Error(c+"NaN");if(this.s<1)throw Error(c+(this.s?"NaN":"-Infinity"));return this.eq(i)?new r(0):(u=!1,e=g(S(this,o),S(t,o),o),u=!0,E(e,n))},y.minus=y.sub=function(t){return t=new this.constructor(t),this.s==t.s?k(this,t):v(this,(t.s=-t.s,t))},y.modulo=y.mod=function(t){var e,r=this.constructor,n=r.precision;if(!(t=new r(t)).s)throw Error(c+"NaN");return this.s?(u=!1,e=g(this,t,0,1).times(t),u=!0,this.minus(e)):E(new r(this),n)},y.naturalExponential=y.exp=function(){return x(this)},y.naturalLogarithm=y.ln=function(){return S(this)},y.negated=y.neg=function(){var t=new this.constructor(this);return t.s=-t.s||0,t},y.plus=y.add=function(t){return t=new this.constructor(t),this.s==t.s?v(this,t):k(this,(t.s=-t.s,t))},y.precision=y.sd=function(t){var e,r,n;if(void 0!==t&&!!t!==t&&1!==t&&0!==t)throw Error(l+t);if(e=w(this)+1,r=7*(n=this.d.length-1)+1,n=this.d[n]){for(;n%10==0;n/=10)r--;for(n=this.d[0];n>=10;n/=10)r++}return t&&e>r?e:r},y.squareRoot=y.sqrt=function(){var t,e,r,n,o,i,a,l=this.constructor;if(this.s<1){if(!this.s)return new l(0);throw Error(c+"NaN")}for(t=w(this),u=!1,0==(o=Math.sqrt(+this))||o==1/0?(((e=b(this.d)).length+t)%2==0&&(e+="0"),o=Math.sqrt(e),t=f((t+1)/2)-(t<0||t%2),n=new l(e=o==1/0?"5e"+t:(e=o.toExponential()).slice(0,e.indexOf("e")+1)+t)):n=new l(o.toString()),o=a=(r=l.precision)+3;;)if(n=(i=n).plus(g(this,i,a+2)).times(.5),b(i.d).slice(0,a)===(e=b(n.d)).slice(0,a)){if(e=e.slice(a-3,a+1),o==a&&"4999"==e){if(E(i,r+1,0),i.times(i).eq(this)){n=i;break}}else if("9999"!=e)break;a+=4}return u=!0,E(n,r)},y.times=y.mul=function(t){var e,r,n,o,i,a,c,l,s,f=this.constructor,p=this.d,h=(t=new f(t)).d;if(!this.s||!t.s)return new f(0);for(t.s*=this.s,r=this.e+t.e,(l=p.length)<(s=h.length)&&(i=p,p=h,h=i,a=l,l=s,s=a),i=[],n=a=l+s;n--;)i.push(0);for(n=s;--n>=0;){for(e=0,o=l+n;o>n;)c=i[o]+h[n]*p[o-n-1]+e,i[o--]=c%1e7|0,e=c/1e7|0;i[o]=(i[o]+e)%1e7|0}for(;!i[--a];)i.pop();return e?++r:i.shift(),t.d=i,t.e=r,u?E(t,f.precision):t},y.toDecimalPlaces=y.todp=function(t,e){var r=this,n=r.constructor;return(r=new n(r),void 0===t)?r:(m(t,0,1e9),void 0===e?e=n.rounding:m(e,0,8),E(r,t+w(r)+1,e))},y.toExponential=function(t,e){var r,n=this,o=n.constructor;return void 0===t?r=A(n,!0):(m(t,0,1e9),void 0===e?e=o.rounding:m(e,0,8),r=A(n=E(new o(n),t+1,e),!0,t+1)),r},y.toFixed=function(t,e){var r,n,o=this.constructor;return void 0===t?A(this):(m(t,0,1e9),void 0===e?e=o.rounding:m(e,0,8),r=A((n=E(new o(this),t+w(this)+1,e)).abs(),!1,t+w(n)+1),this.isneg()&&!this.isZero()?"-"+r:r)},y.toInteger=y.toint=function(){var t=this.constructor;return E(new t(this),w(this)+1,t.rounding)},y.toNumber=function(){return+this},y.toPower=y.pow=function(t){var e,r,n,o,a,l,s=this,p=s.constructor,h=+(t=new p(t));if(!t.s)return new p(i);if(!(s=new p(s)).s){if(t.s<1)throw Error(c+"Infinity");return s}if(s.eq(i))return s;if(n=p.precision,t.eq(i))return E(s,n);if(l=(e=t.e)>=(r=t.d.length-1),a=s.s,l){if((r=h<0?-h:h)<=9007199254740991){for(o=new p(i),e=Math.ceil(n/7+4),u=!1;r%2&&M((o=o.times(s)).d,e),0!==(r=f(r/2));)M((s=s.times(s)).d,e);return u=!0,t.s<0?new p(i).div(o):E(o,n)}}else if(a<0)throw Error(c+"NaN");return a=a<0&&1&t.d[Math.max(e,r)]?-1:1,s.s=1,u=!1,o=t.times(S(s,n+12)),u=!0,(o=x(o)).s=a,o},y.toPrecision=function(t,e){var r,n,o=this,i=o.constructor;return void 0===t?(r=w(o),n=A(o,r<=i.toExpNeg||r>=i.toExpPos)):(m(t,1,1e9),void 0===e?e=i.rounding:m(e,0,8),r=w(o=E(new i(o),t,e)),n=A(o,t<=r||r<=i.toExpNeg,t)),n},y.toSignificantDigits=y.tosd=function(t,e){var r=this.constructor;return void 0===t?(t=r.precision,e=r.rounding):(m(t,1,1e9),void 0===e?e=r.rounding:m(e,0,8)),E(new r(this),t,e)},y.toString=y.valueOf=y.val=y.toJSON=function(){var t=w(this),e=this.constructor;return A(this,t<=e.toExpNeg||t>=e.toExpPos)};var g=function(){function t(t,e){var r,n=0,o=t.length;for(t=t.slice();o--;)r=t[o]*e+n,t[o]=r%1e7|0,n=r/1e7|0;return n&&t.unshift(n),t}function e(t,e,r,n){var o,i;if(r!=n)i=r>n?1:-1;else for(o=i=0;oe[o]?1:-1;break}return i}function r(t,e,r){for(var n=0;r--;)t[r]-=n,n=t[r]1;)t.shift()}return function(n,o,i,a){var u,l,s,f,p,h,d,y,v,m,b,g,x,O,j,S,P,k,A=n.constructor,M=n.s==o.s?1:-1,_=n.d,T=o.d;if(!n.s)return new A(n);if(!o.s)throw Error(c+"Division by zero");for(s=0,l=n.e-o.e,P=T.length,j=_.length,y=(d=new A(M)).d=[];T[s]==(_[s]||0);)++s;if(T[s]>(_[s]||0)&&--l,(g=null==i?i=A.precision:a?i+(w(n)-w(o))+1:i)<0)return new A(0);if(g=g/7+2|0,s=0,1==P)for(f=0,T=T[0],g++;(s1&&(T=t(T,f),_=t(_,f),P=T.length,j=_.length),O=P,m=(v=_.slice(0,P)).length;m=1e7/2&&++S;do f=0,(u=e(T,v,P,m))<0?(b=v[0],P!=m&&(b=1e7*b+(v[1]||0)),(f=b/S|0)>1?(f>=1e7&&(f=1e7-1),h=(p=t(T,f)).length,m=v.length,1==(u=e(p,v,h,m))&&(f--,r(p,P16)throw Error(s+w(t));if(!t.s)return new h(i);for(null==e?(u=!1,c=d):c=e,a=new h(.03125);t.abs().gte(.1);)t=t.times(a),f+=5;for(c+=Math.log(p(2,f))/Math.LN10*2+5|0,r=n=o=new h(i),h.precision=c;;){if(n=E(n.times(t),c),r=r.times(++l),b((a=o.plus(g(n,r,c))).d).slice(0,c)===b(o.d).slice(0,c)){for(;f--;)o=E(o.times(o),c);return h.precision=d,null==e?(u=!0,E(o,d)):o}o=a}}function w(t){for(var e=7*t.e,r=t.d[0];r>=10;r/=10)e++;return e}function O(t,e,r){if(e>t.LN10.sd())throw u=!0,r&&(t.precision=r),Error(c+"LN10 precision limit exceeded");return E(new t(t.LN10),e)}function j(t){for(var e="";t--;)e+="0";return e}function S(t,e){var r,n,o,a,l,s,f,p,h,d=1,y=t,v=y.d,m=y.constructor,x=m.precision;if(y.s<1)throw Error(c+(y.s?"NaN":"-Infinity"));if(y.eq(i))return new m(0);if(null==e?(u=!1,p=x):p=e,y.eq(10))return null==e&&(u=!0),O(m,p);if(p+=10,m.precision=p,n=(r=b(v)).charAt(0),!(15e14>Math.abs(a=w(y))))return f=O(m,p+2,x).times(a+""),y=S(new m(n+"."+r.slice(1)),p-10).plus(f),m.precision=x,null==e?(u=!0,E(y,x)):y;for(;n<7&&1!=n||1==n&&r.charAt(1)>3;)n=(r=b((y=y.times(t)).d)).charAt(0),d++;for(a=w(y),n>1?(y=new m("0."+r),a++):y=new m(n+"."+r.slice(1)),s=l=y=g(y.minus(i),y.plus(i),p),h=E(y.times(y),p),o=3;;){if(l=E(l.times(h),p),b((f=s.plus(g(l,new m(o),p))).d).slice(0,p)===b(s.d).slice(0,p))return s=s.times(2),0!==a&&(s=s.plus(O(m,p+2,x).times(a+""))),s=g(s,new m(d),p),m.precision=x,null==e?(u=!0,E(s,x)):s;s=f,o+=2}}function P(t,e){var r,n,o;for((r=e.indexOf("."))>-1&&(e=e.replace(".","")),(n=e.search(/e/i))>0?(r<0&&(r=n),r+=+e.slice(n+1),e=e.substring(0,n)):r<0&&(r=e.length),n=0;48===e.charCodeAt(n);)++n;for(o=e.length;48===e.charCodeAt(o-1);)--o;if(e=e.slice(n,o)){if(o-=n,r=r-n-1,t.e=f(r/7),t.d=[],n=(r+1)%7,r<0&&(n+=7),nd||t.e<-d))throw Error(s+r)}else t.s=0,t.e=0,t.d=[0];return t}function E(t,e,r){var n,o,i,a,c,l,h,y,v=t.d;for(a=1,i=v[0];i>=10;i/=10)a++;if((n=e-a)<0)n+=7,o=e,h=v[y=0];else{if((y=Math.ceil((n+1)/7))>=(i=v.length))return t;for(a=1,h=i=v[y];i>=10;i/=10)a++;n%=7,o=n-7+a}if(void 0!==r&&(c=h/(i=p(10,a-o-1))%10|0,l=e<0||void 0!==v[y+1]||h%i,l=r<4?(c||l)&&(0==r||r==(t.s<0?3:2)):c>5||5==c&&(4==r||l||6==r&&(n>0?o>0?h/p(10,a-o):0:v[y-1])%10&1||r==(t.s<0?8:7))),e<1||!v[0])return l?(i=w(t),v.length=1,e=e-i-1,v[0]=p(10,(7-e%7)%7),t.e=f(-e/7)||0):(v.length=1,v[0]=t.e=t.s=0),t;if(0==n?(v.length=y,i=1,y--):(v.length=y+1,i=p(10,7-n),v[y]=o>0?(h/p(10,a-o)%p(10,o)|0)*i:0),l)for(;;){if(0==y){1e7==(v[0]+=i)&&(v[0]=1,++t.e);break}if(v[y]+=i,1e7!=v[y])break;v[y--]=0,i=1}for(n=v.length;0===v[--n];)v.pop();if(u&&(t.e>d||t.e<-d))throw Error(s+w(t));return t}function k(t,e){var r,n,o,i,a,c,l,s,f,p,h=t.constructor,d=h.precision;if(!t.s||!e.s)return e.s?e.s=-e.s:e=new h(t),u?E(e,d):e;if(l=t.d,p=e.d,n=e.e,s=t.e,l=l.slice(),a=s-n){for((f=a<0)?(r=l,a=-a,c=p.length):(r=p,n=s,c=l.length),a>(o=Math.max(Math.ceil(d/7),c)+2)&&(a=o,r.length=1),r.reverse(),o=a;o--;)r.push(0);r.reverse()}else{for((f=(o=l.length)<(c=p.length))&&(c=o),o=0;o0;--o)l[c++]=0;for(o=p.length;o>a;){if(l[--o]0?i=i.charAt(0)+"."+i.slice(1)+j(n):a>1&&(i=i.charAt(0)+"."+i.slice(1)),i=i+(o<0?"e":"e+")+o):o<0?(i="0."+j(-o-1)+i,r&&(n=r-a)>0&&(i+=j(n))):o>=a?(i+=j(o+1-a),r&&(n=r-o-1)>0&&(i=i+"."+j(n))):((n=o+1)0&&(o+1===a&&(i+="."),i+=j(n))),t.s<0?"-"+i:i}function M(t,e){if(t.length>e)return t.length=e,!0}function _(t){if(!t||"object"!=typeof t)throw Error(c+"Object expected");var e,r,n,o=["precision",1,1e9,"rounding",0,8,"toExpNeg",-1/0,0,"toExpPos",0,1/0];for(e=0;e=o[e+1]&&n<=o[e+2])this[r]=n;else throw Error(l+r+": "+n)}if(void 0!==(n=t[r="LN10"])){if(n==Math.LN10)this[r]=new this(n);else throw Error(l+r+": "+n)}return this}(a=function t(e){var r,n,o;function i(t){if(!(this instanceof i))return new i(t);if(this.constructor=i,t instanceof i){this.s=t.s,this.e=t.e,this.d=(t=t.d)?t.slice():t;return}if("number"==typeof t){if(0*t!=0)throw Error(l+t);if(t>0)this.s=1;else if(t<0)t=-t,this.s=-1;else{this.s=0,this.e=0,this.d=[0];return}if(t===~~t&&t<1e7){this.e=0,this.d=[t];return}return P(this,t.toString())}if("string"!=typeof t)throw Error(l+t);if(45===t.charCodeAt(0)?(t=t.slice(1),this.s=-1):this.s=1,h.test(t))P(this,t);else throw Error(l+t)}if(i.prototype=y,i.ROUND_UP=0,i.ROUND_DOWN=1,i.ROUND_CEIL=2,i.ROUND_FLOOR=3,i.ROUND_HALF_UP=4,i.ROUND_HALF_DOWN=5,i.ROUND_HALF_EVEN=6,i.ROUND_HALF_CEIL=7,i.ROUND_HALF_FLOOR=8,i.clone=t,i.config=i.set=_,void 0===e&&(e={}),e)for(r=0,o=["precision","rounding","toExpNeg","toExpPos","LN10"];r-1}},56883:function(t){t.exports=function(t,e,r){for(var n=-1,o=null==t?0:t.length;++n0&&i(s)?r>1?t(s,r-1,i,a,u):n(u,s):a||(u[u.length]=s)}return u}},63321:function(t,e,r){var n=r(33023)();t.exports=n},98060:function(t,e,r){var n=r(63321),o=r(43228);t.exports=function(t,e){return t&&n(t,e,o)}},92167:function(t,e,r){var n=r(67906),o=r(70235);t.exports=function(t,e){e=n(e,t);for(var r=0,i=e.length;null!=t&&re}},93012:function(t){t.exports=function(t,e){return null!=t&&e in Object(t)}},47909:function(t,e,r){var n=r(8235),o=r(31953),i=r(35281);t.exports=function(t,e,r){return e==e?i(t,e,r):n(t,o,r)}},90370:function(t,e,r){var n=r(54506),o=r(10303);t.exports=function(t){return o(t)&&"[object Arguments]"==n(t)}},56318:function(t,e,r){var n=r(6791),o=r(10303);t.exports=function t(e,r,i,a,u){return e===r||(null!=e&&null!=r&&(o(e)||o(r))?n(e,r,i,a,t,u):e!=e&&r!=r)}},6791:function(t,e,r){var n=r(85885),o=r(97638),i=r(88030),a=r(64974),u=r(81690),c=r(25614),l=r(98051),s=r(9792),f="[object Arguments]",p="[object Array]",h="[object Object]",d=Object.prototype.hasOwnProperty;t.exports=function(t,e,r,y,v,m){var b=c(t),g=c(e),x=b?p:u(t),w=g?p:u(e);x=x==f?h:x,w=w==f?h:w;var O=x==h,j=w==h,S=x==w;if(S&&l(t)){if(!l(e))return!1;b=!0,O=!1}if(S&&!O)return m||(m=new n),b||s(t)?o(t,e,r,y,v,m):i(t,e,x,r,y,v,m);if(!(1&r)){var P=O&&d.call(t,"__wrapped__"),E=j&&d.call(e,"__wrapped__");if(P||E){var k=P?t.value():t,A=E?e.value():e;return m||(m=new n),v(k,A,r,y,m)}}return!!S&&(m||(m=new n),a(t,e,r,y,v,m))}},62538:function(t,e,r){var n=r(85885),o=r(56318);t.exports=function(t,e,r,i){var a=r.length,u=a,c=!i;if(null==t)return!u;for(t=Object(t);a--;){var l=r[a];if(c&&l[2]?l[1]!==t[l[0]]:!(l[0]in t))return!1}for(;++ao?0:o+e),(r=r>o?o:r)<0&&(r+=o),o=e>r?0:r-e>>>0,e>>>=0;for(var i=Array(o);++n=200){var y=e?null:u(t);if(y)return c(y);p=!1,s=a,d=new n}else d=e?[]:h;t:for(;++l=o?t:n(t,e,r)}},1536:function(t,e,r){var n=r(78371);t.exports=function(t,e){if(t!==e){var r=void 0!==t,o=null===t,i=t==t,a=n(t),u=void 0!==e,c=null===e,l=e==e,s=n(e);if(!c&&!s&&!a&&t>e||a&&u&&l&&!c&&!s||o&&u&&l||!r&&l||!i)return 1;if(!o&&!a&&!s&&t=c)return l;return l*("desc"==r[o]?-1:1)}}return t.index-e.index}},92077:function(t,e,r){var n=r(74288)["__core-js_shared__"];t.exports=n},97930:function(t,e,r){var n=r(5629);t.exports=function(t,e){return function(r,o){if(null==r)return r;if(!n(r))return t(r,o);for(var i=r.length,a=e?i:-1,u=Object(r);(e?a--:++a-1?u[c?e[l]:l]:void 0}}},35464:function(t,e,r){var n=r(19608),o=r(49639),i=r(175);t.exports=function(t){return function(e,r,a){return a&&"number"!=typeof a&&o(e,r,a)&&(r=a=void 0),e=i(e),void 0===r?(r=e,e=0):r=i(r),a=void 0===a?es))return!1;var p=c.get(t),h=c.get(e);if(p&&h)return p==e&&h==t;var d=-1,y=!0,v=2&r?new n:void 0;for(c.set(t,e),c.set(e,t);++d-1&&t%1==0&&t-1}},13368:function(t,e,r){var n=r(24457);t.exports=function(t,e){var r=this.__data__,o=n(r,t);return o<0?(++this.size,r.push([t,e])):r[o][1]=e,this}},38764:function(t,e,r){var n=r(9855),o=r(99078),i=r(88675);t.exports=function(){this.size=0,this.__data__={hash:new n,map:new(i||o),string:new n}}},78615:function(t,e,r){var n=r(1507);t.exports=function(t){var e=n(this,t).delete(t);return this.size-=e?1:0,e}},83391:function(t,e,r){var n=r(1507);t.exports=function(t){return n(this,t).get(t)}},53483:function(t,e,r){var n=r(1507);t.exports=function(t){return n(this,t).has(t)}},74724:function(t,e,r){var n=r(1507);t.exports=function(t,e){var r=n(this,t),o=r.size;return r.set(t,e),this.size+=r.size==o?0:1,this}},22523:function(t){t.exports=function(t){var e=-1,r=Array(t.size);return t.forEach(function(t,n){r[++e]=[n,t]}),r}},47073:function(t){t.exports=function(t,e){return function(r){return null!=r&&r[t]===e&&(void 0!==e||t in Object(r))}}},23787:function(t,e,r){var n=r(50967);t.exports=function(t){var e=n(t,function(t){return 500===r.size&&r.clear(),t}),r=e.cache;return e}},20453:function(t,e,r){var n=r(39866)(Object,"create");t.exports=n},77184:function(t,e,r){var n=r(45070)(Object.keys,Object);t.exports=n},39931:function(t,e,r){t=r.nmd(t);var n=r(17071),o=e&&!e.nodeType&&e,i=o&&t&&!t.nodeType&&t,a=i&&i.exports===o&&n.process,u=function(){try{var t=i&&i.require&&i.require("util").types;if(t)return t;return a&&a.binding&&a.binding("util")}catch(t){}}();t.exports=u},45070:function(t){t.exports=function(t,e){return function(r){return t(e(r))}}},49478:function(t,e,r){var n=r(60493),o=Math.max;t.exports=function(t,e,r){return e=o(void 0===e?t.length-1:e,0),function(){for(var i=arguments,a=-1,u=o(i.length-e,0),c=Array(u);++a0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}},84092:function(t,e,r){var n=r(99078);t.exports=function(){this.__data__=new n,this.size=0}},31663:function(t){t.exports=function(t){var e=this.__data__,r=e.delete(t);return this.size=e.size,r}},69135:function(t){t.exports=function(t){return this.__data__.get(t)}},39552:function(t){t.exports=function(t){return this.__data__.has(t)}},63960:function(t,e,r){var n=r(99078),o=r(88675),i=r(76219);t.exports=function(t,e){var r=this.__data__;if(r instanceof n){var a=r.__data__;if(!o||a.length<199)return a.push([t,e]),this.size=++r.size,this;r=this.__data__=new i(a)}return r.set(t,e),this.size=r.size,this}},35281:function(t){t.exports=function(t,e,r){for(var n=r-1,o=t.length;++n-1&&t%1==0&&t<=9007199254740991}},82559:function(t,e,r){var n=r(22345);t.exports=function(t){return n(t)&&t!=+t}},77571:function(t){t.exports=function(t){return null==t}},22345:function(t,e,r){var n=r(54506),o=r(10303);t.exports=function(t){return"number"==typeof t||o(t)&&"[object Number]"==n(t)}},90231:function(t,e,r){var n=r(54506),o=r(62602),i=r(10303),a=Object.prototype,u=Function.prototype.toString,c=a.hasOwnProperty,l=u.call(Object);t.exports=function(t){if(!i(t)||"[object Object]"!=n(t))return!1;var e=o(t);if(null===e)return!0;var r=c.call(e,"constructor")&&e.constructor;return"function"==typeof r&&r instanceof r&&u.call(r)==l}},42715:function(t,e,r){var n=r(54506),o=r(25614),i=r(10303);t.exports=function(t){return"string"==typeof t||!o(t)&&i(t)&&"[object String]"==n(t)}},9792:function(t,e,r){var n=r(59332),o=r(23305),i=r(39931),a=i&&i.isTypedArray,u=a?o(a):n;t.exports=u},43228:function(t,e,r){var n=r(28579),o=r(4578),i=r(5629);t.exports=function(t){return i(t)?n(t):o(t)}},86185:function(t){t.exports=function(t){var e=null==t?0:t.length;return e?t[e-1]:void 0}},89238:function(t,e,r){var n=r(73819),o=r(88157),i=r(24240),a=r(25614);t.exports=function(t,e){return(a(t)?n:i)(t,o(e,3))}},41443:function(t,e,r){var n=r(83023),o=r(98060),i=r(88157);t.exports=function(t,e){var r={};return e=i(e,3),o(t,function(t,o,i){n(r,o,e(t,o,i))}),r}},95645:function(t,e,r){var n=r(67646),o=r(58905),i=r(79586);t.exports=function(t){return t&&t.length?n(t,i,o):void 0}},50967:function(t,e,r){var n=r(76219);function o(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw TypeError("Expected a function");var r=function(){var n=arguments,o=e?e.apply(this,n):n[0],i=r.cache;if(i.has(o))return i.get(o);var a=t.apply(this,n);return r.cache=i.set(o,a)||i,a};return r.cache=new(o.Cache||n),r}o.Cache=n,t.exports=o},99008:function(t,e,r){var n=r(67646),o=r(20121),i=r(79586);t.exports=function(t){return t&&t.length?n(t,i,o):void 0}},93810:function(t){t.exports=function(){}},22350:function(t,e,r){var n=r(18155),o=r(73584),i=r(67352),a=r(70235);t.exports=function(t){return i(t)?n(a(t)):o(t)}},99676:function(t,e,r){var n=r(35464)();t.exports=n},33645:function(t,e,r){var n=r(25253),o=r(88157),i=r(12327),a=r(25614),u=r(49639);t.exports=function(t,e,r){var c=a(t)?n:i;return r&&u(t,e,r)&&(e=void 0),c(t,o(e,3))}},34935:function(t,e,r){var n=r(72569),o=r(84046),i=r(44843),a=r(49639),u=i(function(t,e){if(null==t)return[];var r=e.length;return r>1&&a(t,e[0],e[1])?e=[]:r>2&&a(e[0],e[1],e[2])&&(e=[e[0]]),o(t,n(e,1),[])});t.exports=u},55716:function(t){t.exports=function(){return[]}},7406:function(t){t.exports=function(){return!1}},37065:function(t,e,r){var n=r(7310),o=r(28302);t.exports=function(t,e,r){var i=!0,a=!0;if("function"!=typeof t)throw TypeError("Expected a function");return o(r)&&(i="leading"in r?!!r.leading:i,a="trailing"in r?!!r.trailing:a),n(t,e,{leading:i,maxWait:e,trailing:a})}},175:function(t,e,r){var n=r(6660),o=1/0;t.exports=function(t){return t?(t=n(t))===o||t===-o?(t<0?-1:1)*17976931348623157e292:t==t?t:0:0===t?t:0}},85759:function(t,e,r){var n=r(175);t.exports=function(t){var e=n(t),r=e%1;return e==e?r?e-r:e:0}},3641:function(t,e,r){var n=r(65020);t.exports=function(t){return null==t?"":n(t)}},47230:function(t,e,r){var n=r(88157),o=r(13826);t.exports=function(t,e){return t&&t.length?o(t,n(e,2)):[]}},75551:function(t,e,r){var n=r(80675)("toUpperCase");t.exports=n},48049:function(t,e,r){"use strict";var n=r(14397);function o(){}function i(){}i.resetWarningCache=o,t.exports=function(){function t(t,e,r,o,i,a){if(a!==n){var u=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw u.name="Invariant Violation",u}}function e(){return t}t.isRequired=t;var r={array:t,bigint:t,bool:t,func:t,number:t,object:t,string:t,symbol:t,any:t,arrayOf:e,element:t,elementType:t,instanceOf:e,node:t,objectOf:e,oneOf:e,oneOfType:e,shape:e,exact:e,checkPropTypes:i,resetWarningCache:o};return r.PropTypes=r,r}},40718:function(t,e,r){t.exports=r(48049)()},14397:function(t){"use strict";t.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},84735:function(t,e,r){"use strict";r.d(e,{ZP:function(){return tS}});var n=r(2265),o=r(40718),i=r.n(o),a=Object.getOwnPropertyNames,u=Object.getOwnPropertySymbols,c=Object.prototype.hasOwnProperty;function l(t,e){return function(r,n,o){return t(r,n,o)&&e(r,n,o)}}function s(t){return function(e,r,n){if(!e||!r||"object"!=typeof e||"object"!=typeof r)return t(e,r,n);var o=n.cache,i=o.get(e),a=o.get(r);if(i&&a)return i===r&&a===e;o.set(e,r),o.set(r,e);var u=t(e,r,n);return o.delete(e),o.delete(r),u}}function f(t){return a(t).concat(u(t))}var p=Object.hasOwn||function(t,e){return c.call(t,e)};function h(t,e){return t===e||!t&&!e&&t!=t&&e!=e}var d=Object.getOwnPropertyDescriptor,y=Object.keys;function v(t,e,r){var n=t.length;if(e.length!==n)return!1;for(;n-- >0;)if(!r.equals(t[n],e[n],n,n,t,e,r))return!1;return!0}function m(t,e){return h(t.getTime(),e.getTime())}function b(t,e){return t.name===e.name&&t.message===e.message&&t.cause===e.cause&&t.stack===e.stack}function g(t,e){return t===e}function x(t,e,r){var n,o,i=t.size;if(i!==e.size)return!1;if(!i)return!0;for(var a=Array(i),u=t.entries(),c=0;(n=u.next())&&!n.done;){for(var l=e.entries(),s=!1,f=0;(o=l.next())&&!o.done;){if(a[f]){f++;continue}var p=n.value,h=o.value;if(r.equals(p[0],h[0],c,f,t,e,r)&&r.equals(p[1],h[1],p[0],h[0],t,e,r)){s=a[f]=!0;break}f++}if(!s)return!1;c++}return!0}function w(t,e,r){var n=y(t),o=n.length;if(y(e).length!==o)return!1;for(;o-- >0;)if(!A(t,e,r,n[o]))return!1;return!0}function O(t,e,r){var n,o,i,a=f(t),u=a.length;if(f(e).length!==u)return!1;for(;u-- >0;)if(!A(t,e,r,n=a[u])||(o=d(t,n),i=d(e,n),(o||i)&&(!o||!i||o.configurable!==i.configurable||o.enumerable!==i.enumerable||o.writable!==i.writable)))return!1;return!0}function j(t,e){return h(t.valueOf(),e.valueOf())}function S(t,e){return t.source===e.source&&t.flags===e.flags}function P(t,e,r){var n,o,i=t.size;if(i!==e.size)return!1;if(!i)return!0;for(var a=Array(i),u=t.values();(n=u.next())&&!n.done;){for(var c=e.values(),l=!1,s=0;(o=c.next())&&!o.done;){if(!a[s]&&r.equals(n.value,o.value,n.value,o.value,t,e,r)){l=a[s]=!0;break}s++}if(!l)return!1}return!0}function E(t,e){var r=t.length;if(e.length!==r)return!1;for(;r-- >0;)if(t[r]!==e[r])return!1;return!0}function k(t,e){return t.hostname===e.hostname&&t.pathname===e.pathname&&t.protocol===e.protocol&&t.port===e.port&&t.hash===e.hash&&t.username===e.username&&t.password===e.password}function A(t,e,r,n){return("_owner"===n||"__o"===n||"__v"===n)&&(!!t.$$typeof||!!e.$$typeof)||p(e,n)&&r.equals(t[n],e[n],n,n,t,e,r)}var M=Array.isArray,_="undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView:null,T=Object.assign,C=Object.prototype.toString.call.bind(Object.prototype.toString),N=D();function D(t){void 0===t&&(t={});var e,r,n,o,i,a,u,c,f,p,d,y,A,N,D=t.circular,I=t.createInternalComparator,L=t.createState,B=t.strict,R=(r=(e=function(t){var e=t.circular,r=t.createCustomConfig,n=t.strict,o={areArraysEqual:n?O:v,areDatesEqual:m,areErrorsEqual:b,areFunctionsEqual:g,areMapsEqual:n?l(x,O):x,areNumbersEqual:h,areObjectsEqual:n?O:w,arePrimitiveWrappersEqual:j,areRegExpsEqual:S,areSetsEqual:n?l(P,O):P,areTypedArraysEqual:n?O:E,areUrlsEqual:k,unknownTagComparators:void 0};if(r&&(o=T({},o,r(o))),e){var i=s(o.areArraysEqual),a=s(o.areMapsEqual),u=s(o.areObjectsEqual),c=s(o.areSetsEqual);o=T({},o,{areArraysEqual:i,areMapsEqual:a,areObjectsEqual:u,areSetsEqual:c})}return o}(t)).areArraysEqual,n=e.areDatesEqual,o=e.areErrorsEqual,i=e.areFunctionsEqual,a=e.areMapsEqual,u=e.areNumbersEqual,c=e.areObjectsEqual,f=e.arePrimitiveWrappersEqual,p=e.areRegExpsEqual,d=e.areSetsEqual,y=e.areTypedArraysEqual,A=e.areUrlsEqual,N=e.unknownTagComparators,function(t,e,l){if(t===e)return!0;if(null==t||null==e)return!1;var s=typeof t;if(s!==typeof e)return!1;if("object"!==s)return"number"===s?u(t,e,l):"function"===s&&i(t,e,l);var h=t.constructor;if(h!==e.constructor)return!1;if(h===Object)return c(t,e,l);if(M(t))return r(t,e,l);if(null!=_&&_(t))return y(t,e,l);if(h===Date)return n(t,e,l);if(h===RegExp)return p(t,e,l);if(h===Map)return a(t,e,l);if(h===Set)return d(t,e,l);var v=C(t);if("[object Date]"===v)return n(t,e,l);if("[object RegExp]"===v)return p(t,e,l);if("[object Map]"===v)return a(t,e,l);if("[object Set]"===v)return d(t,e,l);if("[object Object]"===v)return"function"!=typeof t.then&&"function"!=typeof e.then&&c(t,e,l);if("[object URL]"===v)return A(t,e,l);if("[object Error]"===v)return o(t,e,l);if("[object Arguments]"===v)return c(t,e,l);if("[object Boolean]"===v||"[object Number]"===v||"[object String]"===v)return f(t,e,l);if(N){var m=N[v];if(!m){var b=null!=t?t[Symbol.toStringTag]:void 0;b&&(m=N[b])}if(m)return m(t,e,l)}return!1}),z=I?I(R):function(t,e,r,n,o,i,a){return R(t,e,a)};return function(t){var e=t.circular,r=t.comparator,n=t.createState,o=t.equals,i=t.strict;if(n)return function(t,a){var u=n(),c=u.cache;return r(t,a,{cache:void 0===c?e?new WeakMap:void 0:c,equals:o,meta:u.meta,strict:i})};if(e)return function(t,e){return r(t,e,{cache:new WeakMap,equals:o,meta:void 0,strict:i})};var a={cache:void 0,equals:o,meta:void 0,strict:i};return function(t,e){return r(t,e,a)}}({circular:void 0!==D&&D,comparator:R,createState:L,equals:z,strict:void 0!==B&&B})}function I(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=-1;requestAnimationFrame(function n(o){if(r<0&&(r=o),o-r>e)t(o),r=-1;else{var i;i=n,"undefined"!=typeof requestAnimationFrame&&requestAnimationFrame(i)}})}function L(t){return(L="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function B(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);rt.length)&&(e=t.length);for(var r=0,n=Array(e);r=0&&t<=1}),"[configBezier]: arguments should be x1, y1, x2, y2 of [0, 1] instead received %s",n);var p=V(i,u),h=V(a,c),d=(t=i,e=u,function(r){var n;return G([].concat(function(t){if(Array.isArray(t))return H(t)}(n=X(t,e).map(function(t,e){return t*e}).slice(1))||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(n)||Y(n)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),[0]),r)}),y=function(t){for(var e=t>1?1:t,r=e,n=0;n<8;++n){var o,i=p(r)-e,a=d(r);if(1e-4>Math.abs(i-e)||a<1e-4)break;r=(o=r-i/a)>1?1:o<0?0:o}return h(r)};return y.isStepper=!1,y},Q=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.stiff,r=void 0===e?100:e,n=t.damping,o=void 0===n?8:n,i=t.dt,a=void 0===i?17:i,u=function(t,e,n){var i=n+(-(t-e)*r-n*o)*a/1e3,u=n*a/1e3+t;return 1e-4>Math.abs(u-e)&&1e-4>Math.abs(i)?[e,0]:[u,i]};return u.isStepper=!0,u.dt=a,u},J=function(){for(var t=arguments.length,e=Array(t),r=0;rt.length)&&(e=t.length);for(var r=0,n=Array(e);rt.length)&&(e=t.length);for(var r=0,n=Array(e);r0?r[o-1]:n,p=l||Object.keys(c);if("function"==typeof u||"spring"===u)return[].concat(th(t),[e.runJSAnimation.bind(e,{from:f.style,to:c,duration:i,easing:u}),i]);var h=Z(p,i,u),d=tv(tv(tv({},f.style),c),{},{transition:h});return[].concat(th(t),[d,i,s]).filter($)},[a,Math.max(void 0===u?0:u,n)])),[t.onAnimationEnd]))}},{key:"runAnimation",value:function(t){if(!this.manager){var e,r,n;this.manager=(e=function(){return null},r=!1,n=function t(n){if(!r){if(Array.isArray(n)){if(!n.length)return;var o=function(t){if(Array.isArray(t))return t}(n)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(n)||function(t,e){if(t){if("string"==typeof t)return B(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return B(t,void 0)}}(n)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),i=o[0],a=o.slice(1);if("number"==typeof i){I(t.bind(null,a),i);return}t(i),I(t.bind(null,a));return}"object"===L(n)&&e(n),"function"==typeof n&&n()}},{stop:function(){r=!0},start:function(t){r=!1,n(t)},subscribe:function(t){return e=t,function(){e=function(){return null}}}})}var o=t.begin,i=t.duration,a=t.attributeName,u=t.to,c=t.easing,l=t.onAnimationStart,s=t.onAnimationEnd,f=t.steps,p=t.children,h=this.manager;if(this.unSubscribe=h.subscribe(this.handleStyleChange),"function"==typeof c||"function"==typeof p||"spring"===c){this.runJSAnimation(t);return}if(f.length>1){this.runStepAnimation(t);return}var d=a?tm({},a,u):u,y=Z(Object.keys(d),i,c);h.start([l,o,tv(tv({},d),{},{transition:y}),i,s])}},{key:"render",value:function(){var t=this.props,e=t.children,r=(t.begin,t.duration),o=(t.attributeName,t.easing,t.isActive),i=(t.steps,t.from,t.to,t.canBegin,t.onAnimationEnd,t.shouldReAnimate,t.onAnimationReStart,function(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r,n,o={},i=Object.keys(t);for(n=0;n=0||(o[r]=t[r]);return o}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,tp)),a=n.Children.count(e),u=this.state.style;if("function"==typeof e)return e(u);if(!o||0===a||r<=0)return e;var c=function(t){var e=t.props,r=e.style,o=e.className;return(0,n.cloneElement)(t,tv(tv({},i),{},{style:tv(tv({},void 0===r?{}:r),u),className:o}))};return 1===a?c(n.Children.only(e)):n.createElement("div",null,n.Children.map(e,function(t){return c(t)}))}}],function(t,e){for(var r=0;r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,w),i=parseInt("".concat(r),10),a=parseInt("".concat(n),10),u=parseInt("".concat(e.height||o.height),10),c=parseInt("".concat(e.width||o.width),10);return P(P(P(P(P({},e),o),i?{x:i}:{}),a?{y:a}:{}),{},{height:u,width:c,name:e.name,radius:e.radius})}function k(t){return n.createElement(x.bn,j({shapeType:"rectangle",propTransformer:E,activeClassName:"recharts-active-bar"},t))}var A=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return function(r,n){if("number"==typeof t)return t;var o=(0,d.hj)(r)||(0,d.Rw)(r);return o?t(r,n):(o||(0,g.Z)(!1),e)}},M=["value","background"];function _(t){return(_="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function T(){return(T=Object.assign?Object.assign.bind():function(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(e,M);if(!u)return null;var l=N(N(N(N(N({},c),{},{fill:"#eee"},u),a),(0,b.bw)(t.props,e,r)),{},{onAnimationStart:t.handleAnimationStart,onAnimationEnd:t.handleAnimationEnd,dataKey:o,index:r,className:"recharts-bar-background-rectangle"});return n.createElement(k,T({key:"background-bar-".concat(r),option:t.props.background,isActive:r===i},l))})}},{key:"renderErrorBar",value:function(t,e){if(this.props.isAnimationActive&&!this.state.isAnimationFinished)return null;var r=this.props,o=r.data,i=r.xAxis,a=r.yAxis,u=r.layout,c=r.children,l=(0,y.NN)(c,f.W);if(!l)return null;var p="vertical"===u?o[0].height/2:o[0].width/2,h=function(t,e){var r=Array.isArray(t.value)?t.value[1]:t.value;return{x:t.x,y:t.y,value:r,errorVal:(0,m.F$)(t,e)}};return n.createElement(s.m,{clipPath:t?"url(#clipPath-".concat(e,")"):null},l.map(function(t){return n.cloneElement(t,{key:"error-bar-".concat(e,"-").concat(t.props.dataKey),data:o,xAxis:i,yAxis:a,layout:u,offset:p,dataPointFormatter:h})}))}},{key:"render",value:function(){var t=this.props,e=t.hide,r=t.data,i=t.className,a=t.xAxis,u=t.yAxis,c=t.left,f=t.top,p=t.width,d=t.height,y=t.isAnimationActive,v=t.background,m=t.id;if(e||!r||!r.length)return null;var b=this.state.isAnimationFinished,g=(0,o.Z)("recharts-bar",i),x=a&&a.allowDataOverflow,w=u&&u.allowDataOverflow,O=x||w,j=l()(m)?this.id:m;return n.createElement(s.m,{className:g},x||w?n.createElement("defs",null,n.createElement("clipPath",{id:"clipPath-".concat(j)},n.createElement("rect",{x:x?c:c-p/2,y:w?f:f-d/2,width:x?p:2*p,height:w?d:2*d}))):null,n.createElement(s.m,{className:"recharts-bar-rectangles",clipPath:O?"url(#clipPath-".concat(j,")"):null},v?this.renderBackground():null,this.renderRectangles()),this.renderErrorBar(O,j),(!y||b)&&h.e.renderCallByParent(this.props,r))}}],r=[{key:"getDerivedStateFromProps",value:function(t,e){return t.animationId!==e.prevAnimationId?{prevAnimationId:t.animationId,curData:t.data,prevData:e.curData}:t.data!==e.curData?{curData:t.data}:null}}],e&&D(a.prototype,e),r&&D(a,r),Object.defineProperty(a,"prototype",{writable:!1}),a}(n.PureComponent);R(U,"displayName","Bar"),R(U,"defaultProps",{xAxisId:0,yAxisId:0,legendType:"rect",minPointSize:0,hide:!1,data:[],layout:"vertical",activeBar:!1,isAnimationActive:!v.x.isSsr,animationBegin:0,animationDuration:400,animationEasing:"ease"}),R(U,"getComposedData",function(t){var e=t.props,r=t.item,n=t.barPosition,o=t.bandSize,i=t.xAxis,a=t.yAxis,u=t.xAxisTicks,c=t.yAxisTicks,l=t.stackedData,s=t.dataStartIndex,f=t.displayedData,h=t.offset,v=(0,m.Bu)(n,r);if(!v)return null;var b=e.layout,g=r.type.defaultProps,x=void 0!==g?N(N({},g),r.props):r.props,w=x.dataKey,O=x.children,j=x.minPointSize,S="horizontal"===b?a:i,P=l?S.scale.domain():null,E=(0,m.Yj)({numericAxis:S}),k=(0,y.NN)(O,p.b),M=f.map(function(t,e){l?f=(0,m.Vv)(l[s+e],P):Array.isArray(f=(0,m.F$)(t,w))||(f=[E,f]);var n=A(j,U.defaultProps.minPointSize)(f[1],e);if("horizontal"===b){var f,p,h,y,g,x,O,S=[a.scale(f[0]),a.scale(f[1])],M=S[0],_=S[1];p=(0,m.Fy)({axis:i,ticks:u,bandSize:o,offset:v.offset,entry:t,index:e}),h=null!==(O=null!=_?_:M)&&void 0!==O?O:void 0,y=v.size;var T=M-_;if(g=Number.isNaN(T)?0:T,x={x:p,y:a.y,width:y,height:a.height},Math.abs(n)>0&&Math.abs(g)0&&Math.abs(y)=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function P(t,e){for(var r=0;r0?this.props:d)),o<=0||a<=0||!y||!y.length)?null:n.createElement(s.m,{className:(0,c.Z)("recharts-cartesian-axis",l),ref:function(e){t.layerReference=e}},r&&this.renderAxisLine(),this.renderTicks(y,this.state.fontSize,this.state.letterSpacing),p._.renderCallByParent(this.props))}}],r=[{key:"renderTickItem",value:function(t,e,r){var o=(0,c.Z)(e.className,"recharts-cartesian-axis-tick-value");return n.isValidElement(t)?n.cloneElement(t,j(j({},e),{},{className:o})):i()(t)?t(j(j({},e),{},{className:o})):n.createElement(f.x,w({},e,{className:"recharts-cartesian-axis-tick-value"}),r)}}],e&&P(o.prototype,e),r&&P(o,r),Object.defineProperty(o,"prototype",{writable:!1}),o}(n.Component);M(T,"displayName","CartesianAxis"),M(T,"defaultProps",{x:0,y:0,width:0,height:0,viewBox:{x:0,y:0,width:0,height:0},orientation:"bottom",ticks:[],stroke:"#666",tickLine:!0,axisLine:!0,tick:!0,mirror:!1,minTickGap:5,tickSize:6,tickMargin:2,interval:"preserveEnd"})},56940:function(t,e,r){"use strict";r.d(e,{q:function(){return M}});var n=r(2265),o=r(86757),i=r.n(o),a=r(1175),u=r(16630),c=r(82944),l=r(85355),s=r(78242),f=r(80285),p=r(25739),h=["x1","y1","x2","y2","key"],d=["offset"];function y(t){return(y="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function v(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function m(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}var x=function(t){var e=t.fill;if(!e||"none"===e)return null;var r=t.fillOpacity,o=t.x,i=t.y,a=t.width,u=t.height,c=t.ry;return n.createElement("rect",{x:o,y:i,ry:c,width:a,height:u,stroke:"none",fill:e,fillOpacity:r,className:"recharts-cartesian-grid-bg"})};function w(t,e){var r;if(n.isValidElement(t))r=n.cloneElement(t,e);else if(i()(t))r=t(e);else{var o=e.x1,a=e.y1,u=e.x2,l=e.y2,s=e.key,f=g(e,h),p=(0,c.L6)(f,!1),y=(p.offset,g(p,d));r=n.createElement("line",b({},y,{x1:o,y1:a,x2:u,y2:l,fill:"none",key:s}))}return r}function O(t){var e=t.x,r=t.width,o=t.horizontal,i=void 0===o||o,a=t.horizontalPoints;if(!i||!a||!a.length)return null;var u=a.map(function(n,o){return w(i,m(m({},t),{},{x1:e,y1:n,x2:e+r,y2:n,key:"line-".concat(o),index:o}))});return n.createElement("g",{className:"recharts-cartesian-grid-horizontal"},u)}function j(t){var e=t.y,r=t.height,o=t.vertical,i=void 0===o||o,a=t.verticalPoints;if(!i||!a||!a.length)return null;var u=a.map(function(n,o){return w(i,m(m({},t),{},{x1:n,y1:e,x2:n,y2:e+r,key:"line-".concat(o),index:o}))});return n.createElement("g",{className:"recharts-cartesian-grid-vertical"},u)}function S(t){var e=t.horizontalFill,r=t.fillOpacity,o=t.x,i=t.y,a=t.width,u=t.height,c=t.horizontalPoints,l=t.horizontal;if(!(void 0===l||l)||!e||!e.length)return null;var s=c.map(function(t){return Math.round(t+i-i)}).sort(function(t,e){return t-e});i!==s[0]&&s.unshift(0);var f=s.map(function(t,c){var l=s[c+1]?s[c+1]-t:i+u-t;if(l<=0)return null;var f=c%e.length;return n.createElement("rect",{key:"react-".concat(c),y:t,x:o,height:l,width:a,stroke:"none",fill:e[f],fillOpacity:r,className:"recharts-cartesian-grid-bg"})});return n.createElement("g",{className:"recharts-cartesian-gridstripes-horizontal"},f)}function P(t){var e=t.vertical,r=t.verticalFill,o=t.fillOpacity,i=t.x,a=t.y,u=t.width,c=t.height,l=t.verticalPoints;if(!(void 0===e||e)||!r||!r.length)return null;var s=l.map(function(t){return Math.round(t+i-i)}).sort(function(t,e){return t-e});i!==s[0]&&s.unshift(0);var f=s.map(function(t,e){var l=s[e+1]?s[e+1]-t:i+u-t;if(l<=0)return null;var f=e%r.length;return n.createElement("rect",{key:"react-".concat(e),x:t,y:a,width:l,height:c,stroke:"none",fill:r[f],fillOpacity:o,className:"recharts-cartesian-grid-bg"})});return n.createElement("g",{className:"recharts-cartesian-gridstripes-vertical"},f)}var E=function(t,e){var r=t.xAxis,n=t.width,o=t.height,i=t.offset;return(0,l.Rf)((0,s.f)(m(m(m({},f.O.defaultProps),r),{},{ticks:(0,l.uY)(r,!0),viewBox:{x:0,y:0,width:n,height:o}})),i.left,i.left+i.width,e)},k=function(t,e){var r=t.yAxis,n=t.width,o=t.height,i=t.offset;return(0,l.Rf)((0,s.f)(m(m(m({},f.O.defaultProps),r),{},{ticks:(0,l.uY)(r,!0),viewBox:{x:0,y:0,width:n,height:o}})),i.top,i.top+i.height,e)},A={horizontal:!0,vertical:!0,stroke:"#ccc",fill:"none",verticalFill:[],horizontalFill:[]};function M(t){var e,r,o,c,l,s,f=(0,p.zn)(),h=(0,p.Mw)(),d=(0,p.qD)(),v=m(m({},t),{},{stroke:null!==(e=t.stroke)&&void 0!==e?e:A.stroke,fill:null!==(r=t.fill)&&void 0!==r?r:A.fill,horizontal:null!==(o=t.horizontal)&&void 0!==o?o:A.horizontal,horizontalFill:null!==(c=t.horizontalFill)&&void 0!==c?c:A.horizontalFill,vertical:null!==(l=t.vertical)&&void 0!==l?l:A.vertical,verticalFill:null!==(s=t.verticalFill)&&void 0!==s?s:A.verticalFill,x:(0,u.hj)(t.x)?t.x:d.left,y:(0,u.hj)(t.y)?t.y:d.top,width:(0,u.hj)(t.width)?t.width:d.width,height:(0,u.hj)(t.height)?t.height:d.height}),g=v.x,w=v.y,M=v.width,_=v.height,T=v.syncWithTicks,C=v.horizontalValues,N=v.verticalValues,D=(0,p.CW)(),I=(0,p.Nf)();if(!(0,u.hj)(M)||M<=0||!(0,u.hj)(_)||_<=0||!(0,u.hj)(g)||g!==+g||!(0,u.hj)(w)||w!==+w)return null;var L=v.verticalCoordinatesGenerator||E,B=v.horizontalCoordinatesGenerator||k,R=v.horizontalPoints,z=v.verticalPoints;if((!R||!R.length)&&i()(B)){var U=C&&C.length,F=B({yAxis:I?m(m({},I),{},{ticks:U?C:I.ticks}):void 0,width:f,height:h,offset:d},!!U||T);(0,a.Z)(Array.isArray(F),"horizontalCoordinatesGenerator should return Array but instead it returned [".concat(y(F),"]")),Array.isArray(F)&&(R=F)}if((!z||!z.length)&&i()(L)){var $=N&&N.length,q=L({xAxis:D?m(m({},D),{},{ticks:$?N:D.ticks}):void 0,width:f,height:h,offset:d},!!$||T);(0,a.Z)(Array.isArray(q),"verticalCoordinatesGenerator should return Array but instead it returned [".concat(y(q),"]")),Array.isArray(q)&&(z=q)}return n.createElement("g",{className:"recharts-cartesian-grid"},n.createElement(x,{fill:v.fill,fillOpacity:v.fillOpacity,x:v.x,y:v.y,width:v.width,height:v.height,ry:v.ry}),n.createElement(O,b({},v,{offset:d,horizontalPoints:R,xAxis:D,yAxis:I})),n.createElement(j,b({},v,{offset:d,verticalPoints:z,xAxis:D,yAxis:I})),n.createElement(S,b({},v,{horizontalPoints:R})),n.createElement(P,b({},v,{verticalPoints:z})))}M.displayName="CartesianGrid"},13137:function(t,e,r){"use strict";r.d(e,{W:function(){return v}});var n=r(2265),o=r(69398),i=r(9841),a=r(82944),u=["offset","layout","width","dataKey","data","dataPointFormatter","xAxis","yAxis"];function c(t){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function l(){return(l=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,u),m=(0,a.L6)(v,!1);"x"===this.props.direction&&"number"!==d.type&&(0,o.Z)(!1);var b=p.map(function(t){var o,a,u=h(t,f),p=u.x,v=u.y,b=u.value,g=u.errorVal;if(!g)return null;var x=[];if(Array.isArray(g)){var w=function(t){if(Array.isArray(t))return t}(g)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{for(i=(r=r.call(t)).next;!(c=(n=i.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(g,2)||function(t,e){if(t){if("string"==typeof t)return s(t,2);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return s(t,2)}}(g,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}();o=w[0],a=w[1]}else o=a=g;if("vertical"===r){var O=d.scale,j=v+e,S=j+c,P=j-c,E=O(b-o),k=O(b+a);x.push({x1:k,y1:S,x2:k,y2:P}),x.push({x1:E,y1:j,x2:k,y2:j}),x.push({x1:E,y1:S,x2:E,y2:P})}else if("horizontal"===r){var A=y.scale,M=p+e,_=M-c,T=M+c,C=A(b-o),N=A(b+a);x.push({x1:_,y1:N,x2:T,y2:N}),x.push({x1:M,y1:C,x2:M,y2:N}),x.push({x1:_,y1:C,x2:T,y2:C})}return n.createElement(i.m,l({className:"recharts-errorBar",key:"bar-".concat(x.map(function(t){return"".concat(t.x1,"-").concat(t.x2,"-").concat(t.y1,"-").concat(t.y2)}))},m),x.map(function(t){return n.createElement("line",l({},t,{key:"line-".concat(t.x1,"-").concat(t.x2,"-").concat(t.y1,"-").concat(t.y2)}))}))});return n.createElement(i.m,{className:"recharts-errorBars"},b)}}],function(t,e){for(var r=0;rt*o)return!1;var i=r();return t*(e-t*i/2-n)>=0&&t*(e+t*i/2-o)<=0}function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function h(t){for(var e=1;e=2?(0,i.uY)(m[1].coordinate-m[0].coordinate):1,M=(n="width"===P,f=b.x,p=b.y,d=b.width,y=b.height,1===A?{start:n?f:p,end:n?f+d:p+y}:{start:n?f+d:p+y,end:n?f:p});return"equidistantPreserveStart"===w?function(t,e,r,n,o){for(var i,a=(n||[]).slice(),u=e.start,c=e.end,f=0,p=1,h=u;p<=a.length;)if(i=function(){var e,i=null==n?void 0:n[f];if(void 0===i)return{v:l(n,p)};var a=f,d=function(){return void 0===e&&(e=r(i,a)),e},y=i.coordinate,v=0===f||s(t,y,d,h,c);v||(f=0,h=u,p+=1),v&&(h=y+t*(d()/2+o),f+=p)}())return i.v;return[]}(A,M,k,m,g):("preserveStart"===w||"preserveStartEnd"===w?function(t,e,r,n,o,i){var a=(n||[]).slice(),u=a.length,c=e.start,l=e.end;if(i){var f=n[u-1],p=r(f,u-1),d=t*(f.coordinate+t*p/2-l);a[u-1]=f=h(h({},f),{},{tickCoord:d>0?f.coordinate-d*t:f.coordinate}),s(t,f.tickCoord,function(){return p},c,l)&&(l=f.tickCoord-t*(p/2+o),a[u-1]=h(h({},f),{},{isShow:!0}))}for(var y=i?u-1:u,v=function(e){var n,i=a[e],u=function(){return void 0===n&&(n=r(i,e)),n};if(0===e){var f=t*(i.coordinate-t*u()/2-c);a[e]=i=h(h({},i),{},{tickCoord:f<0?i.coordinate-f*t:i.coordinate})}else a[e]=i=h(h({},i),{},{tickCoord:i.coordinate});s(t,i.tickCoord,u,c,l)&&(c=i.tickCoord+t*(u()/2+o),a[e]=h(h({},i),{},{isShow:!0}))},m=0;m0?l.coordinate-p*t:l.coordinate})}else i[e]=l=h(h({},l),{},{tickCoord:l.coordinate});s(t,l.tickCoord,f,u,c)&&(c=l.tickCoord-t*(f()/2+o),i[e]=h(h({},l),{},{isShow:!0}))},f=a-1;f>=0;f--)l(f);return i}(A,M,k,m,g)).filter(function(t){return t.isShow})}},93765:function(t,e,r){"use strict";r.d(e,{z:function(){return eD}});var n,o,i=r(2265),a=r(77571),u=r.n(a),c=r(86757),l=r.n(c),s=r(99676),f=r.n(s),p=r(13735),h=r.n(p),d=r(34935),y=r.n(d),v=r(37065),m=r.n(v),b=r(61994),g=r(69398),x=r(48777),w=r(9841),O=r(8147),j=r(22190),S=r(81889),P=r(73649),E=r(82944),k=r(55284),A=r(58811),M=r(85355),_=r(16630);function T(t){return(T="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function C(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function N(t){for(var e=1;e0&&e.handleDrag(t.changedTouches[0])}),W(e,"handleDragEnd",function(){e.setState({isTravellerMoving:!1,isSlideMoving:!1},function(){var t=e.props,r=t.endIndex,n=t.onDragEnd,o=t.startIndex;null==n||n({endIndex:r,startIndex:o})}),e.detachDragEndListener()}),W(e,"handleLeaveWrapper",function(){(e.state.isTravellerMoving||e.state.isSlideMoving)&&(e.leaveTimer=window.setTimeout(e.handleDragEnd,e.props.leaveTimeOut))}),W(e,"handleEnterSlideOrTraveller",function(){e.setState({isTextActive:!0})}),W(e,"handleLeaveSlideOrTraveller",function(){e.setState({isTextActive:!1})}),W(e,"handleSlideDragStart",function(t){var r=X(t)?t.changedTouches[0]:t;e.setState({isTravellerMoving:!1,isSlideMoving:!0,slideMoveStartX:r.pageX}),e.attachDragEndListener()}),e.travellerDragStartHandlers={startX:e.handleTravellerDragStart.bind(e,"startX"),endX:e.handleTravellerDragStart.bind(e,"endX")},e.state={},e}return!function(t,e){if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&Z(t,e)}(n,t),e=[{key:"componentWillUnmount",value:function(){this.leaveTimer&&(clearTimeout(this.leaveTimer),this.leaveTimer=null),this.detachDragEndListener()}},{key:"getIndex",value:function(t){var e=t.startX,r=t.endX,o=this.state.scaleValues,i=this.props,a=i.gap,u=i.data.length-1,c=n.getIndexInRange(o,Math.min(e,r)),l=n.getIndexInRange(o,Math.max(e,r));return{startIndex:c-c%a,endIndex:l===u?u:l-l%a}}},{key:"getTextOfTick",value:function(t){var e=this.props,r=e.data,n=e.tickFormatter,o=e.dataKey,i=(0,M.F$)(r[t],o,t);return l()(n)?n(i,t):i}},{key:"attachDragEndListener",value:function(){window.addEventListener("mouseup",this.handleDragEnd,!0),window.addEventListener("touchend",this.handleDragEnd,!0),window.addEventListener("mousemove",this.handleDrag,!0)}},{key:"detachDragEndListener",value:function(){window.removeEventListener("mouseup",this.handleDragEnd,!0),window.removeEventListener("touchend",this.handleDragEnd,!0),window.removeEventListener("mousemove",this.handleDrag,!0)}},{key:"handleSlideDrag",value:function(t){var e=this.state,r=e.slideMoveStartX,n=e.startX,o=e.endX,i=this.props,a=i.x,u=i.width,c=i.travellerWidth,l=i.startIndex,s=i.endIndex,f=i.onChange,p=t.pageX-r;p>0?p=Math.min(p,a+u-c-o,a+u-c-n):p<0&&(p=Math.max(p,a-n,a-o));var h=this.getIndex({startX:n+p,endX:o+p});(h.startIndex!==l||h.endIndex!==s)&&f&&f(h),this.setState({startX:n+p,endX:o+p,slideMoveStartX:t.pageX})}},{key:"handleTravellerDragStart",value:function(t,e){var r=X(e)?e.changedTouches[0]:e;this.setState({isSlideMoving:!1,isTravellerMoving:!0,movingTravellerId:t,brushMoveStartX:r.pageX}),this.attachDragEndListener()}},{key:"handleTravellerMove",value:function(t){var e=this.state,r=e.brushMoveStartX,n=e.movingTravellerId,o=e.endX,i=e.startX,a=this.state[n],u=this.props,c=u.x,l=u.width,s=u.travellerWidth,f=u.onChange,p=u.gap,h=u.data,d={startX:this.state.startX,endX:this.state.endX},y=t.pageX-r;y>0?y=Math.min(y,c+l-s-a):y<0&&(y=Math.max(y,c-a)),d[n]=a+y;var v=this.getIndex(d),m=v.startIndex,b=v.endIndex,g=function(){var t=h.length-1;return"startX"===n&&(o>i?m%p==0:b%p==0)||oi?b%p==0:m%p==0)||o>i&&b===t};this.setState(W(W({},n,a+y),"brushMoveStartX",t.pageX),function(){f&&g()&&f(v)})}},{key:"handleTravellerMoveKeyboard",value:function(t,e){var r=this,n=this.state,o=n.scaleValues,i=n.startX,a=n.endX,u=this.state[e],c=o.indexOf(u);if(-1!==c){var l=c+t;if(-1!==l&&!(l>=o.length)){var s=o[l];"startX"===e&&s>=a||"endX"===e&&s<=i||this.setState(W({},e,s),function(){r.props.onChange(r.getIndex({startX:r.state.startX,endX:r.state.endX}))})}}}},{key:"renderBackground",value:function(){var t=this.props,e=t.x,r=t.y,n=t.width,o=t.height,a=t.fill,u=t.stroke;return i.createElement("rect",{stroke:u,fill:a,x:e,y:r,width:n,height:o})}},{key:"renderPanorama",value:function(){var t=this.props,e=t.x,r=t.y,n=t.width,o=t.height,a=t.data,u=t.children,c=t.padding,l=i.Children.only(u);return l?i.cloneElement(l,{x:e,y:r,width:n,height:o,margin:c,compact:!0,data:a}):null}},{key:"renderTravellerLayer",value:function(t,e){var r,o,a=this,u=this.props,c=u.y,l=u.travellerWidth,s=u.height,f=u.traveller,p=u.ariaLabel,h=u.data,d=u.startIndex,y=u.endIndex,v=Math.max(t,this.props.x),m=U(U({},(0,E.L6)(this.props,!1)),{},{x:v,y:c,width:l,height:s}),b=p||"Min value: ".concat(null===(r=h[d])||void 0===r?void 0:r.name,", Max value: ").concat(null===(o=h[y])||void 0===o?void 0:o.name);return i.createElement(w.m,{tabIndex:0,role:"slider","aria-label":b,"aria-valuenow":t,className:"recharts-brush-traveller",onMouseEnter:this.handleEnterSlideOrTraveller,onMouseLeave:this.handleLeaveSlideOrTraveller,onMouseDown:this.travellerDragStartHandlers[e],onTouchStart:this.travellerDragStartHandlers[e],onKeyDown:function(t){["ArrowLeft","ArrowRight"].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),a.handleTravellerMoveKeyboard("ArrowRight"===t.key?1:-1,e))},onFocus:function(){a.setState({isTravellerFocused:!0})},onBlur:function(){a.setState({isTravellerFocused:!1})},style:{cursor:"col-resize"}},n.renderTraveller(f,m))}},{key:"renderSlide",value:function(t,e){var r=this.props,n=r.y,o=r.height,a=r.stroke,u=r.travellerWidth;return i.createElement("rect",{className:"recharts-brush-slide",onMouseEnter:this.handleEnterSlideOrTraveller,onMouseLeave:this.handleLeaveSlideOrTraveller,onMouseDown:this.handleSlideDragStart,onTouchStart:this.handleSlideDragStart,style:{cursor:"move"},stroke:"none",fill:a,fillOpacity:.2,x:Math.min(t,e)+u,y:n,width:Math.max(Math.abs(e-t)-u,0),height:o})}},{key:"renderText",value:function(){var t=this.props,e=t.startIndex,r=t.endIndex,n=t.y,o=t.height,a=t.travellerWidth,u=t.stroke,c=this.state,l=c.startX,s=c.endX,f={pointerEvents:"none",fill:u};return i.createElement(w.m,{className:"recharts-brush-texts"},i.createElement(A.x,R({textAnchor:"end",verticalAnchor:"middle",x:Math.min(l,s)-5,y:n+o/2},f),this.getTextOfTick(e)),i.createElement(A.x,R({textAnchor:"start",verticalAnchor:"middle",x:Math.max(l,s)+a+5,y:n+o/2},f),this.getTextOfTick(r)))}},{key:"render",value:function(){var t=this.props,e=t.data,r=t.className,n=t.children,o=t.x,a=t.y,u=t.width,c=t.height,l=t.alwaysShowText,s=this.state,f=s.startX,p=s.endX,h=s.isTextActive,d=s.isSlideMoving,y=s.isTravellerMoving,v=s.isTravellerFocused;if(!e||!e.length||!(0,_.hj)(o)||!(0,_.hj)(a)||!(0,_.hj)(u)||!(0,_.hj)(c)||u<=0||c<=0)return null;var m=(0,b.Z)("recharts-brush",r),g=1===i.Children.count(n),x=L("userSelect","none");return i.createElement(w.m,{className:m,onMouseLeave:this.handleLeaveWrapper,onTouchMove:this.handleTouchMove,style:x},this.renderBackground(),g&&this.renderPanorama(),this.renderSlide(f,p),this.renderTravellerLayer(f,"startX"),this.renderTravellerLayer(p,"endX"),(h||d||y||v||l)&&this.renderText())}}],r=[{key:"renderDefaultTraveller",value:function(t){var e=t.x,r=t.y,n=t.width,o=t.height,a=t.stroke,u=Math.floor(r+o/2)-1;return i.createElement(i.Fragment,null,i.createElement("rect",{x:e,y:r,width:n,height:o,fill:a,stroke:"none"}),i.createElement("line",{x1:e+1,y1:u,x2:e+n-1,y2:u,fill:"none",stroke:"#fff"}),i.createElement("line",{x1:e+1,y1:u+2,x2:e+n-1,y2:u+2,fill:"none",stroke:"#fff"}))}},{key:"renderTraveller",value:function(t,e){return i.isValidElement(t)?i.cloneElement(t,e):l()(t)?t(e):n.renderDefaultTraveller(e)}},{key:"getDerivedStateFromProps",value:function(t,e){var r=t.data,n=t.width,o=t.x,i=t.travellerWidth,a=t.updateId,u=t.startIndex,c=t.endIndex;if(r!==e.prevData||a!==e.prevUpdateId)return U({prevData:r,prevTravellerWidth:i,prevUpdateId:a,prevX:o,prevWidth:n},r&&r.length?H({data:r,width:n,x:o,travellerWidth:i,startIndex:u,endIndex:c}):{scale:null,scaleValues:null});if(e.scale&&(n!==e.prevWidth||o!==e.prevX||i!==e.prevTravellerWidth)){e.scale.range([o,o+n-i]);var l=e.scale.domain().map(function(t){return e.scale(t)});return{prevData:r,prevTravellerWidth:i,prevUpdateId:a,prevX:o,prevWidth:n,startX:e.scale(t.startIndex),endX:e.scale(t.endIndex),scaleValues:l}}return null}},{key:"getIndexInRange",value:function(t,e){for(var r=t.length,n=0,o=r-1;o-n>1;){var i=Math.floor((n+o)/2);t[i]>e?o=i:n=i}return e>=t[o]?o:n}}],e&&F(n.prototype,e),r&&F(n,r),Object.defineProperty(n,"prototype",{writable:!1}),n}(i.PureComponent);W(G,"displayName","Brush"),W(G,"defaultProps",{height:40,travellerWidth:5,gap:1,fill:"#fff",stroke:"#666",padding:{top:1,right:1,bottom:1,left:1},leaveTimeOut:1e3,alwaysShowText:!1});var V=r(4094),K=r(38569),Q=r(26680),J=function(t,e){var r=t.alwaysShow,n=t.ifOverflow;return r&&(n="extendDomain"),n===e},tt=r(25311),te=r(1175);function tr(){return(tr=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);rt.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,t2));return(0,_.hj)(r)&&(0,_.hj)(o)&&(0,_.hj)(f)&&(0,_.hj)(h)&&(0,_.hj)(u)&&(0,_.hj)(l)?i.createElement("path",t5({},(0,E.L6)(y,!0),{className:(0,b.Z)("recharts-cross",d),d:"M".concat(r,",").concat(u,"v").concat(h,"M").concat(l,",").concat(o,"h").concat(f)})):null};function t7(t){var e=t.cx,r=t.cy,n=t.radius,o=t.startAngle,i=t.endAngle;return{points:[(0,tq.op)(e,r,n,o),(0,tq.op)(e,r,n,i)],cx:e,cy:r,radius:n,startAngle:o,endAngle:i}}var t4=r(60474);function t8(t){return(t8="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function t9(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function et(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function ec(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(ec=function(){return!!t})()}function el(t){return(el=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function es(t,e){return(es=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function ef(t){return function(t){if(Array.isArray(t))return eh(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||ep(t)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function ep(t,e){if(t){if("string"==typeof t)return eh(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return eh(t,e)}}function eh(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r0?i:t&&t.length&&(0,_.hj)(n)&&(0,_.hj)(o)?t.slice(n,o+1):[]};function eS(t){return"number"===t?[0,"auto"]:void 0}var eP=function(t,e,r,n){var o=t.graphicalItems,i=t.tooltipAxis,a=ej(e,t);return r<0||!o||!o.length||r>=a.length?null:o.reduce(function(o,u){var c,l,s=null!==(c=u.props.data)&&void 0!==c?c:e;if(s&&t.dataStartIndex+t.dataEndIndex!==0&&t.dataEndIndex-t.dataStartIndex>=r&&(s=s.slice(t.dataStartIndex,t.dataEndIndex+1)),i.dataKey&&!i.allowDuplicatedCategory){var f=void 0===s?a:s;l=(0,_.Ap)(f,i.dataKey,n)}else l=s&&s[r]||a[r];return l?[].concat(ef(o),[(0,M.Qo)(u,l)]):o},[])},eE=function(t,e,r,n){var o=n||{x:t.chartX,y:t.chartY},i="horizontal"===r?o.x:"vertical"===r?o.y:"centric"===r?o.angle:o.radius,a=t.orderedTooltipTicks,u=t.tooltipAxis,c=t.tooltipTicks,l=(0,M.VO)(i,a,c,u);if(l>=0&&c){var s=c[l]&&c[l].value,f=eP(t,e,l,s),p=eO(r,a,l,o);return{activeTooltipIndex:l,activeLabel:s,activePayload:f,activeCoordinate:p}}return null},ek=function(t,e){var r=e.axes,n=e.graphicalItems,o=e.axisType,i=e.axisIdKey,a=e.stackGroups,c=e.dataStartIndex,l=e.dataEndIndex,s=t.layout,p=t.children,h=t.stackOffset,d=(0,M.NA)(s,o);return r.reduce(function(e,r){var y=void 0!==r.type.defaultProps?ey(ey({},r.type.defaultProps),r.props):r.props,v=y.type,m=y.dataKey,b=y.allowDataOverflow,g=y.allowDuplicatedCategory,x=y.scale,w=y.ticks,O=y.includeHidden,j=y[i];if(e[j])return e;var S=ej(t.data,{graphicalItems:n.filter(function(t){var e;return(i in t.props?t.props[i]:null===(e=t.type.defaultProps)||void 0===e?void 0:e[i])===j}),dataStartIndex:c,dataEndIndex:l}),P=S.length;(function(t,e,r){if("number"===r&&!0===e&&Array.isArray(t)){var n=null==t?void 0:t[0],o=null==t?void 0:t[1];if(n&&o&&(0,_.hj)(n)&&(0,_.hj)(o))return!0}return!1})(y.domain,b,v)&&(A=(0,M.LG)(y.domain,null,b),d&&("number"===v||"auto"!==x)&&(C=(0,M.gF)(S,m,"category")));var E=eS(v);if(!A||0===A.length){var k,A,T,C,N,D=null!==(N=y.domain)&&void 0!==N?N:E;if(m){if(A=(0,M.gF)(S,m,v),"category"===v&&d){var I=(0,_.bv)(A);g&&I?(T=A,A=f()(0,P)):g||(A=(0,M.ko)(D,A,r).reduce(function(t,e){return t.indexOf(e)>=0?t:[].concat(ef(t),[e])},[]))}else if("category"===v)A=g?A.filter(function(t){return""!==t&&!u()(t)}):(0,M.ko)(D,A,r).reduce(function(t,e){return t.indexOf(e)>=0||""===e||u()(e)?t:[].concat(ef(t),[e])},[]);else if("number"===v){var L=(0,M.ZI)(S,n.filter(function(t){var e,r,n=i in t.props?t.props[i]:null===(e=t.type.defaultProps)||void 0===e?void 0:e[i],o="hide"in t.props?t.props.hide:null===(r=t.type.defaultProps)||void 0===r?void 0:r.hide;return n===j&&(O||!o)}),m,o,s);L&&(A=L)}d&&("number"===v||"auto"!==x)&&(C=(0,M.gF)(S,m,"category"))}else A=d?f()(0,P):a&&a[j]&&a[j].hasStack&&"number"===v?"expand"===h?[0,1]:(0,M.EB)(a[j].stackGroups,c,l):(0,M.s6)(S,n.filter(function(t){var e=i in t.props?t.props[i]:t.type.defaultProps[i],r="hide"in t.props?t.props.hide:t.type.defaultProps.hide;return e===j&&(O||!r)}),v,s,!0);"number"===v?(A=t$(p,A,j,o,w),D&&(A=(0,M.LG)(D,A,b))):"category"===v&&D&&A.every(function(t){return D.indexOf(t)>=0})&&(A=D)}return ey(ey({},e),{},ev({},j,ey(ey({},y),{},{axisType:o,domain:A,categoricalDomain:C,duplicateDomain:T,originalDomain:null!==(k=y.domain)&&void 0!==k?k:E,isCategorical:d,layout:s})))},{})},eA=function(t,e){var r=e.graphicalItems,n=e.Axis,o=e.axisType,i=e.axisIdKey,a=e.stackGroups,u=e.dataStartIndex,c=e.dataEndIndex,l=t.layout,s=t.children,p=ej(t.data,{graphicalItems:r,dataStartIndex:u,dataEndIndex:c}),d=p.length,y=(0,M.NA)(l,o),v=-1;return r.reduce(function(t,e){var m,b=(void 0!==e.type.defaultProps?ey(ey({},e.type.defaultProps),e.props):e.props)[i],g=eS("number");return t[b]?t:(v++,m=y?f()(0,d):a&&a[b]&&a[b].hasStack?t$(s,m=(0,M.EB)(a[b].stackGroups,u,c),b,o):t$(s,m=(0,M.LG)(g,(0,M.s6)(p,r.filter(function(t){var e,r,n=i in t.props?t.props[i]:null===(e=t.type.defaultProps)||void 0===e?void 0:e[i],o="hide"in t.props?t.props.hide:null===(r=t.type.defaultProps)||void 0===r?void 0:r.hide;return n===b&&!o}),"number",l),n.defaultProps.allowDataOverflow),b,o),ey(ey({},t),{},ev({},b,ey(ey({axisType:o},n.defaultProps),{},{hide:!0,orientation:h()(eb,"".concat(o,".").concat(v%2),null),domain:m,originalDomain:g,isCategorical:y,layout:l}))))},{})},eM=function(t,e){var r=e.axisType,n=void 0===r?"xAxis":r,o=e.AxisComp,i=e.graphicalItems,a=e.stackGroups,u=e.dataStartIndex,c=e.dataEndIndex,l=t.children,s="".concat(n,"Id"),f=(0,E.NN)(l,o),p={};return f&&f.length?p=ek(t,{axes:f,graphicalItems:i,axisType:n,axisIdKey:s,stackGroups:a,dataStartIndex:u,dataEndIndex:c}):i&&i.length&&(p=eA(t,{Axis:o,graphicalItems:i,axisType:n,axisIdKey:s,stackGroups:a,dataStartIndex:u,dataEndIndex:c})),p},e_=function(t){var e=(0,_.Kt)(t),r=(0,M.uY)(e,!1,!0);return{tooltipTicks:r,orderedTooltipTicks:y()(r,function(t){return t.coordinate}),tooltipAxis:e,tooltipAxisBandSize:(0,M.zT)(e,r)}},eT=function(t){var e=t.children,r=t.defaultShowTooltip,n=(0,E.sP)(e,G),o=0,i=0;return t.data&&0!==t.data.length&&(i=t.data.length-1),n&&n.props&&(n.props.startIndex>=0&&(o=n.props.startIndex),n.props.endIndex>=0&&(i=n.props.endIndex)),{chartX:0,chartY:0,dataStartIndex:o,dataEndIndex:i,activeTooltipIndex:-1,isTooltipActive:!!r}},eC=function(t){return"horizontal"===t?{numericAxisName:"yAxis",cateAxisName:"xAxis"}:"vertical"===t?{numericAxisName:"xAxis",cateAxisName:"yAxis"}:"centric"===t?{numericAxisName:"radiusAxis",cateAxisName:"angleAxis"}:{numericAxisName:"angleAxis",cateAxisName:"radiusAxis"}},eN=function(t,e){var r=t.props,n=t.graphicalItems,o=t.xAxisMap,i=void 0===o?{}:o,a=t.yAxisMap,u=void 0===a?{}:a,c=r.width,l=r.height,s=r.children,f=r.margin||{},p=(0,E.sP)(s,G),d=(0,E.sP)(s,j.D),y=Object.keys(u).reduce(function(t,e){var r=u[e],n=r.orientation;return r.mirror||r.hide?t:ey(ey({},t),{},ev({},n,t[n]+r.width))},{left:f.left||0,right:f.right||0}),v=Object.keys(i).reduce(function(t,e){var r=i[e],n=r.orientation;return r.mirror||r.hide?t:ey(ey({},t),{},ev({},n,h()(t,"".concat(n))+r.height))},{top:f.top||0,bottom:f.bottom||0}),m=ey(ey({},v),y),b=m.bottom;p&&(m.bottom+=p.props.height||G.defaultProps.height),d&&e&&(m=(0,M.By)(m,n,r,e));var g=c-m.left-m.right,x=l-m.top-m.bottom;return ey(ey({brushBottom:b},m),{},{width:Math.max(g,0),height:Math.max(x,0)})},eD=function(t){var e=t.chartName,r=t.GraphicalChild,n=t.defaultTooltipEventType,o=void 0===n?"axis":n,a=t.validateTooltipEventTypes,c=void 0===a?["axis"]:a,s=t.axisComponents,f=t.legendContent,p=t.formatAxisMap,d=t.defaultProps,y=function(t,e){var r=e.graphicalItems,n=e.stackGroups,o=e.offset,i=e.updateId,a=e.dataStartIndex,c=e.dataEndIndex,l=t.barSize,f=t.layout,p=t.barGap,h=t.barCategoryGap,d=t.maxBarSize,y=eC(f),v=y.numericAxisName,m=y.cateAxisName,b=!!r&&!!r.length&&r.some(function(t){var e=(0,E.Gf)(t&&t.type);return e&&e.indexOf("Bar")>=0}),x=[];return r.forEach(function(r,y){var w=ej(t.data,{graphicalItems:[r],dataStartIndex:a,dataEndIndex:c}),O=void 0!==r.type.defaultProps?ey(ey({},r.type.defaultProps),r.props):r.props,j=O.dataKey,S=O.maxBarSize,P=O["".concat(v,"Id")],k=O["".concat(m,"Id")],A=s.reduce(function(t,r){var n=e["".concat(r.axisType,"Map")],o=O["".concat(r.axisType,"Id")];n&&n[o]||"zAxis"===r.axisType||(0,g.Z)(!1);var i=n[o];return ey(ey({},t),{},ev(ev({},r.axisType,i),"".concat(r.axisType,"Ticks"),(0,M.uY)(i)))},{}),_=A[m],T=A["".concat(m,"Ticks")],C=n&&n[P]&&n[P].hasStack&&(0,M.O3)(r,n[P].stackGroups),N=(0,E.Gf)(r.type).indexOf("Bar")>=0,D=(0,M.zT)(_,T),I=[],L=b&&(0,M.pt)({barSize:l,stackGroups:n,totalSize:"xAxis"===m?A[m].width:"yAxis"===m?A[m].height:void 0});if(N){var B,R,z=u()(S)?d:S,U=null!==(B=null!==(R=(0,M.zT)(_,T,!0))&&void 0!==R?R:z)&&void 0!==B?B:0;I=(0,M.qz)({barGap:p,barCategoryGap:h,bandSize:U!==D?U:D,sizeList:L[k],maxBarSize:z}),U!==D&&(I=I.map(function(t){return ey(ey({},t),{},{position:ey(ey({},t.position),{},{offset:t.position.offset-U/2})})}))}var F=r&&r.type&&r.type.getComposedData;F&&x.push({props:ey(ey({},F(ey(ey({},A),{},{displayedData:w,props:t,dataKey:j,item:r,bandSize:D,barPosition:I,offset:o,stackedData:C,layout:f,dataStartIndex:a,dataEndIndex:c}))),{},ev(ev(ev({key:r.key||"item-".concat(y)},v,A[v]),m,A[m]),"animationId",i)),childIndex:(0,E.$R)(r,t.children),item:r})}),x},v=function(t,n){var o=t.props,i=t.dataStartIndex,a=t.dataEndIndex,u=t.updateId;if(!(0,E.TT)({props:o}))return null;var c=o.children,l=o.layout,f=o.stackOffset,h=o.data,d=o.reverseStackOrder,v=eC(l),m=v.numericAxisName,b=v.cateAxisName,g=(0,E.NN)(c,r),x=(0,M.wh)(h,g,"".concat(m,"Id"),"".concat(b,"Id"),f,d),w=s.reduce(function(t,e){var r="".concat(e.axisType,"Map");return ey(ey({},t),{},ev({},r,eM(o,ey(ey({},e),{},{graphicalItems:g,stackGroups:e.axisType===m&&x,dataStartIndex:i,dataEndIndex:a}))))},{}),O=eN(ey(ey({},w),{},{props:o,graphicalItems:g}),null==n?void 0:n.legendBBox);Object.keys(w).forEach(function(t){w[t]=p(o,w[t],O,t.replace("Map",""),e)});var j=e_(w["".concat(b,"Map")]),S=y(o,ey(ey({},w),{},{dataStartIndex:i,dataEndIndex:a,updateId:u,graphicalItems:g,stackGroups:x,offset:O}));return ey(ey({formattedGraphicalItems:S,graphicalItems:g,offset:O,stackGroups:x},j),w)},j=function(t){var r;function n(t){var r,o,a,c,s;return!function(t,e){if(!(t instanceof e))throw TypeError("Cannot call a class as a function")}(this,n),c=n,s=[t],c=el(c),ev(a=function(t,e){if(e&&("object"===eo(e)||"function"==typeof e))return e;if(void 0!==e)throw TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t)}(this,ec()?Reflect.construct(c,s||[],el(this).constructor):c.apply(this,s)),"eventEmitterSymbol",Symbol("rechartsEventEmitter")),ev(a,"accessibilityManager",new tQ),ev(a,"handleLegendBBoxUpdate",function(t){if(t){var e=a.state,r=e.dataStartIndex,n=e.dataEndIndex,o=e.updateId;a.setState(ey({legendBBox:t},v({props:a.props,dataStartIndex:r,dataEndIndex:n,updateId:o},ey(ey({},a.state),{},{legendBBox:t}))))}}),ev(a,"handleReceiveSyncEvent",function(t,e,r){a.props.syncId===t&&(r!==a.eventEmitterSymbol||"function"==typeof a.props.syncMethod)&&a.applySyncEvent(e)}),ev(a,"handleBrushChange",function(t){var e=t.startIndex,r=t.endIndex;if(e!==a.state.dataStartIndex||r!==a.state.dataEndIndex){var n=a.state.updateId;a.setState(function(){return ey({dataStartIndex:e,dataEndIndex:r},v({props:a.props,dataStartIndex:e,dataEndIndex:r,updateId:n},a.state))}),a.triggerSyncEvent({dataStartIndex:e,dataEndIndex:r})}}),ev(a,"handleMouseEnter",function(t){var e=a.getMouseInfo(t);if(e){var r=ey(ey({},e),{},{isTooltipActive:!0});a.setState(r),a.triggerSyncEvent(r);var n=a.props.onMouseEnter;l()(n)&&n(r,t)}}),ev(a,"triggeredAfterMouseMove",function(t){var e=a.getMouseInfo(t),r=e?ey(ey({},e),{},{isTooltipActive:!0}):{isTooltipActive:!1};a.setState(r),a.triggerSyncEvent(r);var n=a.props.onMouseMove;l()(n)&&n(r,t)}),ev(a,"handleItemMouseEnter",function(t){a.setState(function(){return{isTooltipActive:!0,activeItem:t,activePayload:t.tooltipPayload,activeCoordinate:t.tooltipPosition||{x:t.cx,y:t.cy}}})}),ev(a,"handleItemMouseLeave",function(){a.setState(function(){return{isTooltipActive:!1}})}),ev(a,"handleMouseMove",function(t){t.persist(),a.throttleTriggeredAfterMouseMove(t)}),ev(a,"handleMouseLeave",function(t){a.throttleTriggeredAfterMouseMove.cancel();var e={isTooltipActive:!1};a.setState(e),a.triggerSyncEvent(e);var r=a.props.onMouseLeave;l()(r)&&r(e,t)}),ev(a,"handleOuterEvent",function(t){var e,r=(0,E.Bh)(t),n=h()(a.props,"".concat(r));r&&l()(n)&&n(null!==(e=/.*touch.*/i.test(r)?a.getMouseInfo(t.changedTouches[0]):a.getMouseInfo(t))&&void 0!==e?e:{},t)}),ev(a,"handleClick",function(t){var e=a.getMouseInfo(t);if(e){var r=ey(ey({},e),{},{isTooltipActive:!0});a.setState(r),a.triggerSyncEvent(r);var n=a.props.onClick;l()(n)&&n(r,t)}}),ev(a,"handleMouseDown",function(t){var e=a.props.onMouseDown;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"handleMouseUp",function(t){var e=a.props.onMouseUp;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"handleTouchMove",function(t){null!=t.changedTouches&&t.changedTouches.length>0&&a.throttleTriggeredAfterMouseMove(t.changedTouches[0])}),ev(a,"handleTouchStart",function(t){null!=t.changedTouches&&t.changedTouches.length>0&&a.handleMouseDown(t.changedTouches[0])}),ev(a,"handleTouchEnd",function(t){null!=t.changedTouches&&t.changedTouches.length>0&&a.handleMouseUp(t.changedTouches[0])}),ev(a,"handleDoubleClick",function(t){var e=a.props.onDoubleClick;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"handleContextMenu",function(t){var e=a.props.onContextMenu;l()(e)&&e(a.getMouseInfo(t),t)}),ev(a,"triggerSyncEvent",function(t){void 0!==a.props.syncId&&tY.emit(tH,a.props.syncId,t,a.eventEmitterSymbol)}),ev(a,"applySyncEvent",function(t){var e=a.props,r=e.layout,n=e.syncMethod,o=a.state.updateId,i=t.dataStartIndex,u=t.dataEndIndex;if(void 0!==t.dataStartIndex||void 0!==t.dataEndIndex)a.setState(ey({dataStartIndex:i,dataEndIndex:u},v({props:a.props,dataStartIndex:i,dataEndIndex:u,updateId:o},a.state)));else if(void 0!==t.activeTooltipIndex){var c=t.chartX,l=t.chartY,s=t.activeTooltipIndex,f=a.state,p=f.offset,h=f.tooltipTicks;if(!p)return;if("function"==typeof n)s=n(h,t);else if("value"===n){s=-1;for(var d=0;d=0){if(s.dataKey&&!s.allowDuplicatedCategory){var A="function"==typeof s.dataKey?function(t){return"function"==typeof s.dataKey?s.dataKey(t.payload):null}:"payload.".concat(s.dataKey.toString());C=(0,_.Ap)(v,A,p),N=m&&b&&(0,_.Ap)(b,A,p)}else C=null==v?void 0:v[f],N=m&&b&&b[f];if(S||j){var T=void 0!==t.props.activeIndex?t.props.activeIndex:f;return[(0,i.cloneElement)(t,ey(ey(ey({},n.props),P),{},{activeIndex:T})),null,null]}if(!u()(C))return[k].concat(ef(a.renderActivePoints({item:n,activePoint:C,basePoint:N,childIndex:f,isRange:m})))}else{var C,N,D,I=(null!==(D=a.getItemByXY(a.state.activeCoordinate))&&void 0!==D?D:{graphicalItem:k}).graphicalItem,L=I.item,B=void 0===L?t:L,R=I.childIndex,z=ey(ey(ey({},n.props),P),{},{activeIndex:R});return[(0,i.cloneElement)(B,z),null,null]}}return m?[k,null,null]:[k,null]}),ev(a,"renderCustomized",function(t,e,r){return(0,i.cloneElement)(t,ey(ey({key:"recharts-customized-".concat(r)},a.props),a.state))}),ev(a,"renderMap",{CartesianGrid:{handler:ew,once:!0},ReferenceArea:{handler:a.renderReferenceElement},ReferenceLine:{handler:ew},ReferenceDot:{handler:a.renderReferenceElement},XAxis:{handler:ew},YAxis:{handler:ew},Brush:{handler:a.renderBrush,once:!0},Bar:{handler:a.renderGraphicChild},Line:{handler:a.renderGraphicChild},Area:{handler:a.renderGraphicChild},Radar:{handler:a.renderGraphicChild},RadialBar:{handler:a.renderGraphicChild},Scatter:{handler:a.renderGraphicChild},Pie:{handler:a.renderGraphicChild},Funnel:{handler:a.renderGraphicChild},Tooltip:{handler:a.renderCursor,once:!0},PolarGrid:{handler:a.renderPolarGrid,once:!0},PolarAngleAxis:{handler:a.renderPolarAxis},PolarRadiusAxis:{handler:a.renderPolarAxis},Customized:{handler:a.renderCustomized}}),a.clipPathId="".concat(null!==(r=t.id)&&void 0!==r?r:(0,_.EL)("recharts"),"-clip"),a.throttleTriggeredAfterMouseMove=m()(a.triggeredAfterMouseMove,null!==(o=t.throttleDelay)&&void 0!==o?o:1e3/60),a.state={},a}return!function(t,e){if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&es(t,e)}(n,t),r=[{key:"componentDidMount",value:function(){var t,e;this.addListener(),this.accessibilityManager.setDetails({container:this.container,offset:{left:null!==(t=this.props.margin.left)&&void 0!==t?t:0,top:null!==(e=this.props.margin.top)&&void 0!==e?e:0},coordinateList:this.state.tooltipTicks,mouseHandlerCallback:this.triggeredAfterMouseMove,layout:this.props.layout}),this.displayDefaultTooltip()}},{key:"displayDefaultTooltip",value:function(){var t=this.props,e=t.children,r=t.data,n=t.height,o=t.layout,i=(0,E.sP)(e,O.u);if(i){var a=i.props.defaultIndex;if("number"==typeof a&&!(a<0)&&!(a>this.state.tooltipTicks.length-1)){var u=this.state.tooltipTicks[a]&&this.state.tooltipTicks[a].value,c=eP(this.state,r,a,u),l=this.state.tooltipTicks[a].coordinate,s=(this.state.offset.top+n)/2,f="horizontal"===o?{x:l,y:s}:{y:l,x:s},p=this.state.formattedGraphicalItems.find(function(t){return"Scatter"===t.item.type.name});p&&(f=ey(ey({},f),p.props.points[a].tooltipPosition),c=p.props.points[a].tooltipPayload);var h={activeTooltipIndex:a,isTooltipActive:!0,activeLabel:u,activePayload:c,activeCoordinate:f};this.setState(h),this.renderCursor(i),this.accessibilityManager.setIndex(a)}}}},{key:"getSnapshotBeforeUpdate",value:function(t,e){if(!this.props.accessibilityLayer)return null;if(this.state.tooltipTicks!==e.tooltipTicks&&this.accessibilityManager.setDetails({coordinateList:this.state.tooltipTicks}),this.props.layout!==t.layout&&this.accessibilityManager.setDetails({layout:this.props.layout}),this.props.margin!==t.margin){var r,n;this.accessibilityManager.setDetails({offset:{left:null!==(r=this.props.margin.left)&&void 0!==r?r:0,top:null!==(n=this.props.margin.top)&&void 0!==n?n:0}})}return null}},{key:"componentDidUpdate",value:function(t){(0,E.rL)([(0,E.sP)(t.children,O.u)],[(0,E.sP)(this.props.children,O.u)])||this.displayDefaultTooltip()}},{key:"componentWillUnmount",value:function(){this.removeListener(),this.throttleTriggeredAfterMouseMove.cancel()}},{key:"getTooltipEventType",value:function(){var t=(0,E.sP)(this.props.children,O.u);if(t&&"boolean"==typeof t.props.shared){var e=t.props.shared?"axis":"item";return c.indexOf(e)>=0?e:o}return o}},{key:"getMouseInfo",value:function(t){if(!this.container)return null;var e=this.container,r=e.getBoundingClientRect(),n=(0,V.os)(r),o={chartX:Math.round(t.pageX-n.left),chartY:Math.round(t.pageY-n.top)},i=r.width/e.offsetWidth||1,a=this.inRange(o.chartX,o.chartY,i);if(!a)return null;var u=this.state,c=u.xAxisMap,l=u.yAxisMap,s=this.getTooltipEventType(),f=eE(this.state,this.props.data,this.props.layout,a);if("axis"!==s&&c&&l){var p=(0,_.Kt)(c).scale,h=(0,_.Kt)(l).scale,d=p&&p.invert?p.invert(o.chartX):null,y=h&&h.invert?h.invert(o.chartY):null;return ey(ey({},o),{},{xValue:d,yValue:y},f)}return f?ey(ey({},o),f):null}},{key:"inRange",value:function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,n=this.props.layout,o=t/r,i=e/r;if("horizontal"===n||"vertical"===n){var a=this.state.offset;return o>=a.left&&o<=a.left+a.width&&i>=a.top&&i<=a.top+a.height?{x:o,y:i}:null}var u=this.state,c=u.angleAxisMap,l=u.radiusAxisMap;if(c&&l){var s=(0,_.Kt)(c);return(0,tq.z3)({x:o,y:i},s)}return null}},{key:"parseEventsOfWrapper",value:function(){var t=this.props.children,e=this.getTooltipEventType(),r=(0,E.sP)(t,O.u),n={};return r&&"axis"===e&&(n="click"===r.props.trigger?{onClick:this.handleClick}:{onMouseEnter:this.handleMouseEnter,onDoubleClick:this.handleDoubleClick,onMouseMove:this.handleMouseMove,onMouseLeave:this.handleMouseLeave,onTouchMove:this.handleTouchMove,onTouchStart:this.handleTouchStart,onTouchEnd:this.handleTouchEnd,onContextMenu:this.handleContextMenu}),ey(ey({},(0,tX.Ym)(this.props,this.handleOuterEvent)),n)}},{key:"addListener",value:function(){tY.on(tH,this.handleReceiveSyncEvent)}},{key:"removeListener",value:function(){tY.removeListener(tH,this.handleReceiveSyncEvent)}},{key:"filterFormatItem",value:function(t,e,r){for(var n=this.state.formattedGraphicalItems,o=0,i=n.length;ot.length)&&(e=t.length);for(var r=0,n=Array(e);r=0?1:-1;"insideStart"===u?(o=b+S*l,a=w):"insideEnd"===u?(o=g-S*l,a=!w):"end"===u&&(o=g+S*l,a=w),a=j<=0?a:!a;var P=(0,d.op)(p,y,O,o),E=(0,d.op)(p,y,O,o+(a?1:-1)*359),k="M".concat(P.x,",").concat(P.y,"\n A").concat(O,",").concat(O,",0,1,").concat(a?0:1,",\n ").concat(E.x,",").concat(E.y),A=i()(t.id)?(0,h.EL)("recharts-radial-line-"):t.id;return n.createElement("text",x({},r,{dominantBaseline:"central",className:(0,s.Z)("recharts-radial-bar-label",f)}),n.createElement("defs",null,n.createElement("path",{id:A,d:k})),n.createElement("textPath",{xlinkHref:"#".concat(A)},e))},j=function(t){var e=t.viewBox,r=t.offset,n=t.position,o=e.cx,i=e.cy,a=e.innerRadius,u=e.outerRadius,c=(e.startAngle+e.endAngle)/2;if("outside"===n){var l=(0,d.op)(o,i,u+r,c),s=l.x;return{x:s,y:l.y,textAnchor:s>=o?"start":"end",verticalAnchor:"middle"}}if("center"===n)return{x:o,y:i,textAnchor:"middle",verticalAnchor:"middle"};if("centerTop"===n)return{x:o,y:i,textAnchor:"middle",verticalAnchor:"start"};if("centerBottom"===n)return{x:o,y:i,textAnchor:"middle",verticalAnchor:"end"};var f=(0,d.op)(o,i,(a+u)/2,c);return{x:f.x,y:f.y,textAnchor:"middle",verticalAnchor:"middle"}},S=function(t){var e=t.viewBox,r=t.parentViewBox,n=t.offset,o=t.position,i=e.x,a=e.y,u=e.width,c=e.height,s=c>=0?1:-1,f=s*n,p=s>0?"end":"start",d=s>0?"start":"end",y=u>=0?1:-1,v=y*n,m=y>0?"end":"start",b=y>0?"start":"end";if("top"===o)return g(g({},{x:i+u/2,y:a-s*n,textAnchor:"middle",verticalAnchor:p}),r?{height:Math.max(a-r.y,0),width:u}:{});if("bottom"===o)return g(g({},{x:i+u/2,y:a+c+f,textAnchor:"middle",verticalAnchor:d}),r?{height:Math.max(r.y+r.height-(a+c),0),width:u}:{});if("left"===o){var x={x:i-v,y:a+c/2,textAnchor:m,verticalAnchor:"middle"};return g(g({},x),r?{width:Math.max(x.x-r.x,0),height:c}:{})}if("right"===o){var w={x:i+u+v,y:a+c/2,textAnchor:b,verticalAnchor:"middle"};return g(g({},w),r?{width:Math.max(r.x+r.width-w.x,0),height:c}:{})}var O=r?{width:u,height:c}:{};return"insideLeft"===o?g({x:i+v,y:a+c/2,textAnchor:b,verticalAnchor:"middle"},O):"insideRight"===o?g({x:i+u-v,y:a+c/2,textAnchor:m,verticalAnchor:"middle"},O):"insideTop"===o?g({x:i+u/2,y:a+f,textAnchor:"middle",verticalAnchor:d},O):"insideBottom"===o?g({x:i+u/2,y:a+c-f,textAnchor:"middle",verticalAnchor:p},O):"insideTopLeft"===o?g({x:i+v,y:a+f,textAnchor:b,verticalAnchor:d},O):"insideTopRight"===o?g({x:i+u-v,y:a+f,textAnchor:m,verticalAnchor:d},O):"insideBottomLeft"===o?g({x:i+v,y:a+c-f,textAnchor:b,verticalAnchor:p},O):"insideBottomRight"===o?g({x:i+u-v,y:a+c-f,textAnchor:m,verticalAnchor:p},O):l()(o)&&((0,h.hj)(o.x)||(0,h.hU)(o.x))&&((0,h.hj)(o.y)||(0,h.hU)(o.y))?g({x:i+(0,h.h1)(o.x,u),y:a+(0,h.h1)(o.y,c),textAnchor:"end",verticalAnchor:"end"},O):g({x:i+u/2,y:a+c/2,textAnchor:"middle",verticalAnchor:"middle"},O)};function P(t){var e,r=t.offset,o=g({offset:void 0===r?5:r},function(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r={};for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){if(e.indexOf(n)>=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,v)),a=o.viewBox,c=o.position,l=o.value,d=o.children,y=o.content,m=o.className,b=o.textBreakAll;if(!a||i()(l)&&i()(d)&&!(0,n.isValidElement)(y)&&!u()(y))return null;if((0,n.isValidElement)(y))return(0,n.cloneElement)(y,o);if(u()(y)){if(e=(0,n.createElement)(y,o),(0,n.isValidElement)(e))return e}else e=w(o);var P="cx"in a&&(0,h.hj)(a.cx),E=(0,p.L6)(o,!0);if(P&&("insideStart"===c||"insideEnd"===c||"end"===c))return O(o,e,E);var k=P?j(o):S(o);return n.createElement(f.x,x({className:(0,s.Z)("recharts-label",void 0===m?"":m)},E,k,{breakAll:b}),e)}P.displayName="Label";var E=function(t){var e=t.cx,r=t.cy,n=t.angle,o=t.startAngle,i=t.endAngle,a=t.r,u=t.radius,c=t.innerRadius,l=t.outerRadius,s=t.x,f=t.y,p=t.top,d=t.left,y=t.width,v=t.height,m=t.clockWise,b=t.labelViewBox;if(b)return b;if((0,h.hj)(y)&&(0,h.hj)(v)){if((0,h.hj)(s)&&(0,h.hj)(f))return{x:s,y:f,width:y,height:v};if((0,h.hj)(p)&&(0,h.hj)(d))return{x:p,y:d,width:y,height:v}}return(0,h.hj)(s)&&(0,h.hj)(f)?{x:s,y:f,width:0,height:0}:(0,h.hj)(e)&&(0,h.hj)(r)?{cx:e,cy:r,startAngle:o||n||0,endAngle:i||n||0,innerRadius:c||0,outerRadius:l||u||a||0,clockWise:m}:t.viewBox?t.viewBox:{}};P.parseViewBox=E,P.renderCallByParent=function(t,e){var r,o,i=!(arguments.length>2)||void 0===arguments[2]||arguments[2];if(!t||!t.children&&i&&!t.label)return null;var a=t.children,c=E(t),s=(0,p.NN)(a,P).map(function(t,r){return(0,n.cloneElement)(t,{viewBox:e||c,key:"label-".concat(r)})});return i?[(r=t.label,o=e||c,r?!0===r?n.createElement(P,{key:"label-implicit",viewBox:o}):(0,h.P2)(r)?n.createElement(P,{key:"label-implicit",viewBox:o,value:r}):(0,n.isValidElement)(r)?r.type===P?(0,n.cloneElement)(r,{key:"label-implicit",viewBox:o}):n.createElement(P,{key:"label-implicit",content:r,viewBox:o}):u()(r)?n.createElement(P,{key:"label-implicit",content:r,viewBox:o}):l()(r)?n.createElement(P,x({viewBox:o},r,{key:"label-implicit"})):null:null)].concat(function(t){if(Array.isArray(t))return m(t)}(s)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(s)||function(t,e){if(t){if("string"==typeof t)return m(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return m(t,void 0)}}(s)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()):s}},58772:function(t,e,r){"use strict";r.d(e,{e:function(){return P}});var n=r(2265),o=r(77571),i=r.n(o),a=r(28302),u=r.n(a),c=r(86757),l=r.n(c),s=r(86185),f=r.n(s),p=r(26680),h=r(9841),d=r(82944),y=r(85355);function v(t){return(v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var m=["valueAccessor"],b=["data","dataKey","clockWise","id","textBreakAll"];function g(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}var S=function(t){return Array.isArray(t.value)?f()(t.value):t.value};function P(t){var e=t.valueAccessor,r=void 0===e?S:e,o=j(t,m),a=o.data,u=o.dataKey,c=o.clockWise,l=o.id,s=o.textBreakAll,f=j(o,b);return a&&a.length?n.createElement(h.m,{className:"recharts-label-list"},a.map(function(t,e){var o=i()(u)?r(t,e):(0,y.F$)(t&&t.payload,u),a=i()(l)?{}:{id:"".concat(l,"-").concat(e)};return n.createElement(p._,x({},(0,d.L6)(t,!0),f,a,{parentViewBox:t.parentViewBox,value:o,textBreakAll:s,viewBox:p._.parseViewBox(i()(c)?t:O(O({},t),{},{clockWise:c})),key:"label-".concat(e),index:e}))})):null}P.displayName="LabelList",P.renderCallByParent=function(t,e){var r,o=!(arguments.length>2)||void 0===arguments[2]||arguments[2];if(!t||!t.children&&o&&!t.label)return null;var i=t.children,a=(0,d.NN)(i,P).map(function(t,r){return(0,n.cloneElement)(t,{data:e,key:"labelList-".concat(r)})});return o?[(r=t.label)?!0===r?n.createElement(P,{key:"labelList-implicit",data:e}):n.isValidElement(r)||l()(r)?n.createElement(P,{key:"labelList-implicit",data:e,content:r}):u()(r)?n.createElement(P,x({data:e},r,{key:"labelList-implicit"})):null:null].concat(function(t){if(Array.isArray(t))return g(t)}(a)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(a)||function(t,e){if(t){if("string"==typeof t)return g(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return g(t,void 0)}}(a)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()):a}},22190:function(t,e,r){"use strict";r.d(e,{D:function(){return N}});var n=r(2265),o=r(86757),i=r.n(o),a=r(61994),u=r(1175),c=r(48777),l=r(14870),s=r(41637);function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(){return(p=Object.assign?Object.assign.bind():function(t){for(var e=1;e');var x=e.inactive?h:e.color;return n.createElement("li",p({className:b,style:y,key:"legend-item-".concat(r)},(0,s.bw)(t.props,e,r)),n.createElement(c.T,{width:o,height:o,viewBox:d,style:v},t.renderIcon(e)),n.createElement("span",{className:"recharts-legend-item-text",style:{color:x}},l?l(g,e,r):g))})}},{key:"render",value:function(){var t=this.props,e=t.payload,r=t.layout,o=t.align;return e&&e.length?n.createElement("ul",{className:"recharts-default-legend",style:{padding:0,margin:0,textAlign:"horizontal"===r?o:"left"}},this.renderItems()):null}}],function(t,e){for(var r=0;r1||Math.abs(e.height-this.lastBoundingBox.height)>1)&&(this.lastBoundingBox.width=e.width,this.lastBoundingBox.height=e.height,t&&t(e)):(-1!==this.lastBoundingBox.width||-1!==this.lastBoundingBox.height)&&(this.lastBoundingBox.width=-1,this.lastBoundingBox.height=-1,t&&t(null))}},{key:"getBBoxSnapshot",value:function(){return this.lastBoundingBox.width>=0&&this.lastBoundingBox.height>=0?P({},this.lastBoundingBox):{width:0,height:0}}},{key:"getDefaultPosition",value:function(t){var e,r,n=this.props,o=n.layout,i=n.align,a=n.verticalAlign,u=n.margin,c=n.chartWidth,l=n.chartHeight;return t&&(void 0!==t.left&&null!==t.left||void 0!==t.right&&null!==t.right)||(e="center"===i&&"vertical"===o?{left:((c||0)-this.getBBoxSnapshot().width)/2}:"right"===i?{right:u&&u.right||0}:{left:u&&u.left||0}),t&&(void 0!==t.top&&null!==t.top||void 0!==t.bottom&&null!==t.bottom)||(r="middle"===a?{top:((l||0)-this.getBBoxSnapshot().height)/2}:"bottom"===a?{bottom:u&&u.bottom||0}:{top:u&&u.top||0}),P(P({},e),r)}},{key:"render",value:function(){var t=this,e=this.props,r=e.content,o=e.width,i=e.height,a=e.wrapperStyle,u=e.payloadUniqBy,c=e.payload,l=P(P({position:"absolute",width:o||"auto",height:i||"auto"},this.getDefaultPosition(a)),a);return n.createElement("div",{className:"recharts-legend-wrapper",style:l,ref:function(e){t.wrapperNode=e}},function(t,e){if(n.isValidElement(t))return n.cloneElement(t,e);if("function"==typeof t)return n.createElement(t,e);e.ref;var r=function(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r={};for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){if(e.indexOf(n)>=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(e,j);return n.createElement(g,r)}(r,P(P({},this.props),{},{payload:(0,w.z)(c,u,C)})))}}],r=[{key:"getWithHeight",value:function(t,e){var r=P(P({},this.defaultProps),t.props).layout;return"vertical"===r&&(0,x.hj)(t.props.height)?{height:t.props.height}:"horizontal"===r?{width:t.props.width||e}:null}}],e&&E(o.prototype,e),r&&E(o,r),Object.defineProperty(o,"prototype",{writable:!1}),o}(n.PureComponent);_(N,"displayName","Legend"),_(N,"defaultProps",{iconSize:14,layout:"horizontal",align:"center",verticalAlign:"bottom"})},47625:function(t,e,r){"use strict";r.d(e,{h:function(){return d}});var n=r(61994),o=r(2265),i=r(37065),a=r.n(i),u=r(16630),c=r(1175),l=r(82944);function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function f(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function p(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r0&&(t=a()(t,S,{trailing:!0,leading:!1}));var e=new ResizeObserver(t),r=M.current.getBoundingClientRect();return D(r.width,r.height),e.observe(M.current),function(){e.disconnect()}},[D,S]);var I=(0,o.useMemo)(function(){var t=C.containerWidth,e=C.containerHeight;if(t<0||e<0)return null;(0,c.Z)((0,u.hU)(y)||(0,u.hU)(m),"The width(%s) and height(%s) are both fixed numbers,\n maybe you don't need to use a ResponsiveContainer.",y,m),(0,c.Z)(!i||i>0,"The aspect(%s) must be greater than zero.",i);var r=(0,u.hU)(y)?t:y,n=(0,u.hU)(m)?e:m;i&&i>0&&(r?n=r/i:n&&(r=n*i),w&&n>w&&(n=w)),(0,c.Z)(r>0||n>0,"The width(%s) and height(%s) of chart should be greater than 0,\n please check the style of container, or the props width(%s) and height(%s),\n or add a minWidth(%s) or minHeight(%s) or use aspect(%s) to control the\n height and width.",r,n,y,m,g,x,i);var a=!Array.isArray(O)&&(0,l.Gf)(O.type).endsWith("Chart");return o.Children.map(O,function(t){return o.isValidElement(t)?(0,o.cloneElement)(t,p({width:r,height:n},a?{style:p({height:"100%",width:"100%",maxHeight:n,maxWidth:r},t.props.style)}:{})):t})},[i,O,m,w,x,g,C,y]);return o.createElement("div",{id:P?"".concat(P):void 0,className:(0,n.Z)("recharts-responsive-container",E),style:p(p({},void 0===A?{}:A),{},{width:y,height:m,minWidth:g,minHeight:x,maxHeight:w}),ref:M},I)})},58811:function(t,e,r){"use strict";r.d(e,{x:function(){return B}});var n=r(2265),o=r(77571),i=r.n(o),a=r(61994),u=r(16630),c=r(34067),l=r(82944),s=r(4094);function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;c=!1}else for(;!(c=(n=i.call(r)).done)&&(u.push(n.value),u.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(t,e)||function(t,e){if(t){if("string"==typeof t)return h(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return h(t,e)}}(t,e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function M(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;c=!1}else for(;!(c=(n=i.call(r)).done)&&(u.push(n.value),u.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(t,e)||function(t,e){if(t){if("string"==typeof t)return _(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return _(t,e)}}(t,e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function _(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r0&&void 0!==arguments[0]?arguments[0]:[];return t.reduce(function(t,e){var i=e.word,a=e.width,u=t[t.length-1];return u&&(null==n||o||u.width+a+ra||e.reduce(function(t,e){return t.width>e.width?t:e}).width>Number(n),e]},y=0,v=c.length-1,m=0;y<=v&&m<=c.length-1;){var b=Math.floor((y+v)/2),g=M(d(b-1),2),x=g[0],w=g[1],O=M(d(b),1)[0];if(x||O||(y=b+1),x&&O&&(v=b-1),!x&&O){i=w;break}m++}return i||h},D=function(t){return[{words:i()(t)?[]:t.toString().split(T)}]},I=function(t){var e=t.width,r=t.scaleToFit,n=t.children,o=t.style,i=t.breakAll,a=t.maxLines;if((e||r)&&!c.x.isSsr){var u=C({breakAll:i,children:n,style:o});return u?N({breakAll:i,children:n,maxLines:a,style:o},u.wordsWithComputedWidth,u.spaceWidth,e,r):D(n)}return D(n)},L="#808080",B=function(t){var e,r=t.x,o=void 0===r?0:r,i=t.y,c=void 0===i?0:i,s=t.lineHeight,f=void 0===s?"1em":s,p=t.capHeight,h=void 0===p?"0.71em":p,d=t.scaleToFit,y=void 0!==d&&d,v=t.textAnchor,m=t.verticalAnchor,b=t.fill,g=void 0===b?L:b,x=A(t,P),w=(0,n.useMemo)(function(){return I({breakAll:x.breakAll,children:x.children,maxLines:x.maxLines,scaleToFit:y,style:x.style,width:x.width})},[x.breakAll,x.children,x.maxLines,y,x.style,x.width]),O=x.dx,j=x.dy,M=x.angle,_=x.className,T=x.breakAll,C=A(x,E);if(!(0,u.P2)(o)||!(0,u.P2)(c))return null;var N=o+((0,u.hj)(O)?O:0),D=c+((0,u.hj)(j)?j:0);switch(void 0===m?"end":m){case"start":e=S("calc(".concat(h,")"));break;case"middle":e=S("calc(".concat((w.length-1)/2," * -").concat(f," + (").concat(h," / 2))"));break;default:e=S("calc(".concat(w.length-1," * -").concat(f,")"))}var B=[];if(y){var R=w[0].width,z=x.width;B.push("scale(".concat(((0,u.hj)(z)?z/R:1)/R,")"))}return M&&B.push("rotate(".concat(M,", ").concat(N,", ").concat(D,")")),B.length&&(C.transform=B.join(" ")),n.createElement("text",k({},(0,l.L6)(C,!0),{x:N,y:D,className:(0,a.Z)("recharts-text",_),textAnchor:void 0===v?"start":v,fill:g.includes("url")?L:g}),w.map(function(t,r){var o=t.words.join(T?"":" ");return n.createElement("tspan",{x:N,dy:0===r?e:f,key:"".concat(o,"-").concat(r)},o)}))}},8147:function(t,e,r){"use strict";r.d(e,{u:function(){return $}});var n=r(2265),o=r(34935),i=r.n(o),a=r(77571),u=r.n(a),c=r(61994),l=r(16630);function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function f(){return(f=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);rc[n]+s?Math.max(f,c[n]):Math.max(p,c[n])}function O(t){return(O="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function j(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function S(t){for(var e=1;e1||Math.abs(t.height-this.state.lastBoundingBox.height)>1)&&this.setState({lastBoundingBox:{width:t.width,height:t.height}})}else(-1!==this.state.lastBoundingBox.width||-1!==this.state.lastBoundingBox.height)&&this.setState({lastBoundingBox:{width:-1,height:-1}})}},{key:"componentDidMount",value:function(){document.addEventListener("keydown",this.handleKeyDown),this.updateBBox()}},{key:"componentWillUnmount",value:function(){document.removeEventListener("keydown",this.handleKeyDown)}},{key:"componentDidUpdate",value:function(){var t,e;this.props.active&&this.updateBBox(),this.state.dismissed&&((null===(t=this.props.coordinate)||void 0===t?void 0:t.x)!==this.state.dismissedAtCoordinate.x||(null===(e=this.props.coordinate)||void 0===e?void 0:e.y)!==this.state.dismissedAtCoordinate.y)&&(this.state.dismissed=!1)}},{key:"render",value:function(){var t,e,r,o,i,a,u,s,f,p,h,d,y,v,m,O,j,P,E,k=this,A=this.props,M=A.active,_=A.allowEscapeViewBox,T=A.animationDuration,C=A.animationEasing,N=A.children,D=A.coordinate,I=A.hasPayload,L=A.isAnimationActive,B=A.offset,R=A.position,z=A.reverseDirection,U=A.useTranslate3d,F=A.viewBox,$=A.wrapperStyle,q=(d=(t={allowEscapeViewBox:_,coordinate:D,offsetTopLeft:B,position:R,reverseDirection:z,tooltipBox:this.state.lastBoundingBox,useTranslate3d:U,viewBox:F}).allowEscapeViewBox,y=t.coordinate,v=t.offsetTopLeft,m=t.position,O=t.reverseDirection,j=t.tooltipBox,P=t.useTranslate3d,E=t.viewBox,j.height>0&&j.width>0&&y?(r=(e={translateX:p=w({allowEscapeViewBox:d,coordinate:y,key:"x",offsetTopLeft:v,position:m,reverseDirection:O,tooltipDimension:j.width,viewBox:E,viewBoxDimension:E.width}),translateY:h=w({allowEscapeViewBox:d,coordinate:y,key:"y",offsetTopLeft:v,position:m,reverseDirection:O,tooltipDimension:j.height,viewBox:E,viewBoxDimension:E.height}),useTranslate3d:P}).translateX,o=e.translateY,f={transform:e.useTranslate3d?"translate3d(".concat(r,"px, ").concat(o,"px, 0)"):"translate(".concat(r,"px, ").concat(o,"px)")}):f=x,{cssProperties:f,cssClasses:(a=(i={translateX:p,translateY:h,coordinate:y}).coordinate,u=i.translateX,s=i.translateY,(0,c.Z)(g,b(b(b(b({},"".concat(g,"-right"),(0,l.hj)(u)&&a&&(0,l.hj)(a.x)&&u>=a.x),"".concat(g,"-left"),(0,l.hj)(u)&&a&&(0,l.hj)(a.x)&&u=a.y),"".concat(g,"-top"),(0,l.hj)(s)&&a&&(0,l.hj)(a.y)&&s0;return n.createElement(_,{allowEscapeViewBox:i,animationDuration:a,animationEasing:u,isAnimationActive:f,active:o,coordinate:l,hasPayload:O,offset:p,position:y,reverseDirection:m,useTranslate3d:b,viewBox:g,wrapperStyle:x},(t=I(I({},this.props),{},{payload:w}),n.isValidElement(c)?n.cloneElement(c,t):"function"==typeof c?n.createElement(c,t):n.createElement(v,t)))}}],function(t,e){for(var r=0;r=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,a),s=(0,o.Z)("recharts-layer",c);return n.createElement("g",u({className:s},(0,i.L6)(l,!0),{ref:e}),r)})},48777:function(t,e,r){"use strict";r.d(e,{T:function(){return c}});var n=r(2265),o=r(61994),i=r(82944),a=["children","width","height","viewBox","className","style","title","desc"];function u(){return(u=Object.assign?Object.assign.bind():function(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,a),y=l||{width:r,height:c,x:0,y:0},v=(0,o.Z)("recharts-surface",s);return n.createElement("svg",u({},(0,i.L6)(d,!0,"svg"),{className:v,width:r,height:c,style:f,viewBox:"".concat(y.x," ").concat(y.y," ").concat(y.width," ").concat(y.height)}),n.createElement("title",null,p),n.createElement("desc",null,h),e)}},25739:function(t,e,r){"use strict";r.d(e,{br:function(){return g},CW:function(){return O},Mw:function(){return A},zn:function(){return k},sp:function(){return x},qD:function(){return E},d2:function(){return P},bH:function(){return w},Ud:function(){return S},Nf:function(){return j}});var n=r(2265),o=r(69398),i=r(84173),a=r.n(i),u=r(32242),c=r.n(u),l=r(50967),s=r.n(l)()(function(t){return{x:t.left,y:t.top,width:t.width,height:t.height}},function(t){return["l",t.left,"t",t.top,"w",t.width,"h",t.height].join("")}),f=r(16630),p=(0,n.createContext)(void 0),h=(0,n.createContext)(void 0),d=(0,n.createContext)(void 0),y=(0,n.createContext)({}),v=(0,n.createContext)(void 0),m=(0,n.createContext)(0),b=(0,n.createContext)(0),g=function(t){var e=t.state,r=e.xAxisMap,o=e.yAxisMap,i=e.offset,a=t.clipPathId,u=t.children,c=t.width,l=t.height,f=s(i);return n.createElement(p.Provider,{value:r},n.createElement(h.Provider,{value:o},n.createElement(y.Provider,{value:i},n.createElement(d.Provider,{value:f},n.createElement(v.Provider,{value:a},n.createElement(m.Provider,{value:l},n.createElement(b.Provider,{value:c},u)))))))},x=function(){return(0,n.useContext)(v)},w=function(t){var e=(0,n.useContext)(p);null!=e||(0,o.Z)(!1);var r=e[t];return null!=r||(0,o.Z)(!1),r},O=function(){var t=(0,n.useContext)(p);return(0,f.Kt)(t)},j=function(){var t=(0,n.useContext)(h);return a()(t,function(t){return c()(t.domain,Number.isFinite)})||(0,f.Kt)(t)},S=function(t){var e=(0,n.useContext)(h);null!=e||(0,o.Z)(!1);var r=e[t];return null!=r||(0,o.Z)(!1),r},P=function(){return(0,n.useContext)(d)},E=function(){return(0,n.useContext)(y)},k=function(){return(0,n.useContext)(b)},A=function(){return(0,n.useContext)(m)}},57165:function(t,e,r){"use strict";r.d(e,{H:function(){return H}});var n=r(2265);function o(){}function i(t,e,r){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+r)/6)}function a(t){this._context=t}function u(t){this._context=t}function c(t){this._context=t}a.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:i(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:i(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},u.prototype={areaStart:o,areaEnd:o,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x2=t,this._y2=e;break;case 1:this._point=2,this._x3=t,this._y3=e;break;case 2:this._point=3,this._x4=t,this._y4=e,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+e)/6);break;default:i(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},c.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var r=(this._x0+4*this._x1+t)/6,n=(this._y0+4*this._y1+e)/6;this._line?this._context.lineTo(r,n):this._context.moveTo(r,n);break;case 3:this._point=4;default:i(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}};class l{constructor(t,e){this._context=t,this._x=e}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line}point(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+t)/2,this._y0,this._x0,e,t,e):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+e)/2,t,this._y0,t,e)}this._x0=t,this._y0=e}}function s(t){this._context=t}function f(t){this._context=t}function p(t){return new f(t)}function h(t,e,r){var n=t._x1-t._x0,o=e-t._x1,i=(t._y1-t._y0)/(n||o<0&&-0),a=(r-t._y1)/(o||n<0&&-0);return((i<0?-1:1)+(a<0?-1:1))*Math.min(Math.abs(i),Math.abs(a),.5*Math.abs((i*o+a*n)/(n+o)))||0}function d(t,e){var r=t._x1-t._x0;return r?(3*(t._y1-t._y0)/r-e)/2:e}function y(t,e,r){var n=t._x0,o=t._y0,i=t._x1,a=t._y1,u=(i-n)/3;t._context.bezierCurveTo(n+u,o+u*e,i-u,a-u*r,i,a)}function v(t){this._context=t}function m(t){this._context=new b(t)}function b(t){this._context=t}function g(t){this._context=t}function x(t){var e,r,n=t.length-1,o=Array(n),i=Array(n),a=Array(n);for(o[0]=0,i[0]=2,a[0]=t[0]+2*t[1],e=1;e=0;--e)o[e]=(a[e]-o[e+1])/i[e];for(e=0,i[n-1]=(t[n]+o[n-1])/2;e=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var r=this._x*(1-this._t)+t*this._t;this._context.lineTo(r,this._y),this._context.lineTo(r,e)}}this._x=t,this._y=e}};var O=r(22516),j=r(76115),S=r(67790);function P(t){return t[0]}function E(t){return t[1]}function k(t,e){var r=(0,j.Z)(!0),n=null,o=p,i=null,a=(0,S.d)(u);function u(u){var c,l,s,f=(u=(0,O.Z)(u)).length,p=!1;for(null==n&&(i=o(s=a())),c=0;c<=f;++c)!(c=f;--p)u.point(m[p],b[p]);u.lineEnd(),u.areaEnd()}}v&&(m[s]=+t(h,s,l),b[s]=+e(h,s,l),u.point(n?+n(h,s,l):m[s],r?+r(h,s,l):b[s]))}if(d)return u=null,d+""||null}function s(){return k().defined(o).curve(a).context(i)}return t="function"==typeof t?t:void 0===t?P:(0,j.Z)(+t),e="function"==typeof e?e:void 0===e?(0,j.Z)(0):(0,j.Z)(+e),r="function"==typeof r?r:void 0===r?E:(0,j.Z)(+r),l.x=function(e){return arguments.length?(t="function"==typeof e?e:(0,j.Z)(+e),n=null,l):t},l.x0=function(e){return arguments.length?(t="function"==typeof e?e:(0,j.Z)(+e),l):t},l.x1=function(t){return arguments.length?(n=null==t?null:"function"==typeof t?t:(0,j.Z)(+t),l):n},l.y=function(t){return arguments.length?(e="function"==typeof t?t:(0,j.Z)(+t),r=null,l):e},l.y0=function(t){return arguments.length?(e="function"==typeof t?t:(0,j.Z)(+t),l):e},l.y1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:(0,j.Z)(+t),l):r},l.lineX0=l.lineY0=function(){return s().x(t).y(e)},l.lineY1=function(){return s().x(t).y(r)},l.lineX1=function(){return s().x(n).y(e)},l.defined=function(t){return arguments.length?(o="function"==typeof t?t:(0,j.Z)(!!t),l):o},l.curve=function(t){return arguments.length?(a=t,null!=i&&(u=a(i)),l):a},l.context=function(t){return arguments.length?(null==t?i=u=null:u=a(i=t),l):i},l}var M=r(75551),_=r.n(M),T=r(86757),C=r.n(T),N=r(61994),D=r(41637),I=r(82944),L=r(16630);function B(t){return(B="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function R(){return(R=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r=0?1:-1,c=r>=0?1:-1,l=n>=0&&r>=0||n<0&&r<0?1:0;if(a>0&&o instanceof Array){for(var s=[0,0,0,0],f=0;f<4;f++)s[f]=o[f]>a?a:o[f];i="M".concat(t,",").concat(e+u*s[0]),s[0]>0&&(i+="A ".concat(s[0],",").concat(s[0],",0,0,").concat(l,",").concat(t+c*s[0],",").concat(e)),i+="L ".concat(t+r-c*s[1],",").concat(e),s[1]>0&&(i+="A ".concat(s[1],",").concat(s[1],",0,0,").concat(l,",\n ").concat(t+r,",").concat(e+u*s[1])),i+="L ".concat(t+r,",").concat(e+n-u*s[2]),s[2]>0&&(i+="A ".concat(s[2],",").concat(s[2],",0,0,").concat(l,",\n ").concat(t+r-c*s[2],",").concat(e+n)),i+="L ".concat(t+c*s[3],",").concat(e+n),s[3]>0&&(i+="A ".concat(s[3],",").concat(s[3],",0,0,").concat(l,",\n ").concat(t,",").concat(e+n-u*s[3])),i+="Z"}else if(a>0&&o===+o&&o>0){var p=Math.min(a,o);i="M ".concat(t,",").concat(e+u*p,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t+c*p,",").concat(e,"\n L ").concat(t+r-c*p,",").concat(e,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t+r,",").concat(e+u*p,"\n L ").concat(t+r,",").concat(e+n-u*p,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t+r-c*p,",").concat(e+n,"\n L ").concat(t+c*p,",").concat(e+n,"\n A ").concat(p,",").concat(p,",0,0,").concat(l,",").concat(t,",").concat(e+n-u*p," Z")}else i="M ".concat(t,",").concat(e," h ").concat(r," v ").concat(n," h ").concat(-r," Z");return i},h=function(t,e){if(!t||!e)return!1;var r=t.x,n=t.y,o=e.x,i=e.y,a=e.width,u=e.height;return!!(Math.abs(a)>0&&Math.abs(u)>0)&&r>=Math.min(o,o+a)&&r<=Math.max(o,o+a)&&n>=Math.min(i,i+u)&&n<=Math.max(i,i+u)},d={x:0,y:0,width:0,height:0,radius:0,isAnimationActive:!1,isUpdateAnimationActive:!1,animationBegin:0,animationDuration:1500,animationEasing:"ease"},y=function(t){var e,r=f(f({},d),t),u=(0,n.useRef)(),s=function(t){if(Array.isArray(t))return t}(e=(0,n.useState)(-1))||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{for(i=(r=r.call(t)).next;!(c=(n=i.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(e,2)||function(t,e){if(t){if("string"==typeof t)return l(t,2);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return l(t,2)}}(e,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),h=s[0],y=s[1];(0,n.useEffect)(function(){if(u.current&&u.current.getTotalLength)try{var t=u.current.getTotalLength();t&&y(t)}catch(t){}},[]);var v=r.x,m=r.y,b=r.width,g=r.height,x=r.radius,w=r.className,O=r.animationEasing,j=r.animationDuration,S=r.animationBegin,P=r.isAnimationActive,E=r.isUpdateAnimationActive;if(v!==+v||m!==+m||b!==+b||g!==+g||0===b||0===g)return null;var k=(0,o.Z)("recharts-rectangle",w);return E?n.createElement(i.ZP,{canBegin:h>0,from:{width:b,height:g,x:v,y:m},to:{width:b,height:g,x:v,y:m},duration:j,animationEasing:O,isActive:E},function(t){var e=t.width,o=t.height,l=t.x,s=t.y;return n.createElement(i.ZP,{canBegin:h>0,from:"0px ".concat(-1===h?1:h,"px"),to:"".concat(h,"px 0px"),attributeName:"strokeDasharray",begin:S,duration:j,isActive:P,easing:O},n.createElement("path",c({},(0,a.L6)(r,!0),{className:k,d:p(l,s,e,o,x),ref:u})))}):n.createElement("path",c({},(0,a.L6)(r,!0),{className:k,d:p(v,m,b,g,x)}))}},60474:function(t,e,r){"use strict";r.d(e,{L:function(){return v}});var n=r(2265),o=r(61994),i=r(82944),a=r(39206),u=r(16630);function c(t){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function l(){return(l=Object.assign?Object.assign.bind():function(t){for(var e=1;e180),",").concat(+(c>s),",\n ").concat(p.x,",").concat(p.y,"\n ");if(o>0){var d=(0,a.op)(r,n,o,c),y=(0,a.op)(r,n,o,s);h+="L ".concat(y.x,",").concat(y.y,"\n A ").concat(o,",").concat(o,",0,\n ").concat(+(Math.abs(l)>180),",").concat(+(c<=s),",\n ").concat(d.x,",").concat(d.y," Z")}else h+="L ".concat(r,",").concat(n," Z");return h},d=function(t){var e=t.cx,r=t.cy,n=t.innerRadius,o=t.outerRadius,i=t.cornerRadius,a=t.forceCornerRadius,c=t.cornerIsExternal,l=t.startAngle,s=t.endAngle,f=(0,u.uY)(s-l),d=p({cx:e,cy:r,radius:o,angle:l,sign:f,cornerRadius:i,cornerIsExternal:c}),y=d.circleTangency,v=d.lineTangency,m=d.theta,b=p({cx:e,cy:r,radius:o,angle:s,sign:-f,cornerRadius:i,cornerIsExternal:c}),g=b.circleTangency,x=b.lineTangency,w=b.theta,O=c?Math.abs(l-s):Math.abs(l-s)-m-w;if(O<0)return a?"M ".concat(v.x,",").concat(v.y,"\n a").concat(i,",").concat(i,",0,0,1,").concat(2*i,",0\n a").concat(i,",").concat(i,",0,0,1,").concat(-(2*i),",0\n "):h({cx:e,cy:r,innerRadius:n,outerRadius:o,startAngle:l,endAngle:s});var j="M ".concat(v.x,",").concat(v.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(y.x,",").concat(y.y,"\n A").concat(o,",").concat(o,",0,").concat(+(O>180),",").concat(+(f<0),",").concat(g.x,",").concat(g.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(x.x,",").concat(x.y,"\n ");if(n>0){var S=p({cx:e,cy:r,radius:n,angle:l,sign:f,isExternal:!0,cornerRadius:i,cornerIsExternal:c}),P=S.circleTangency,E=S.lineTangency,k=S.theta,A=p({cx:e,cy:r,radius:n,angle:s,sign:-f,isExternal:!0,cornerRadius:i,cornerIsExternal:c}),M=A.circleTangency,_=A.lineTangency,T=A.theta,C=c?Math.abs(l-s):Math.abs(l-s)-k-T;if(C<0&&0===i)return"".concat(j,"L").concat(e,",").concat(r,"Z");j+="L".concat(_.x,",").concat(_.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(M.x,",").concat(M.y,"\n A").concat(n,",").concat(n,",0,").concat(+(C>180),",").concat(+(f>0),",").concat(P.x,",").concat(P.y,"\n A").concat(i,",").concat(i,",0,0,").concat(+(f<0),",").concat(E.x,",").concat(E.y,"Z")}else j+="L".concat(e,",").concat(r,"Z");return j},y={cx:0,cy:0,innerRadius:0,outerRadius:0,startAngle:0,endAngle:0,cornerRadius:0,forceCornerRadius:!1,cornerIsExternal:!1},v=function(t){var e,r=f(f({},y),t),a=r.cx,c=r.cy,s=r.innerRadius,p=r.outerRadius,v=r.cornerRadius,m=r.forceCornerRadius,b=r.cornerIsExternal,g=r.startAngle,x=r.endAngle,w=r.className;if(p0&&360>Math.abs(g-x)?d({cx:a,cy:c,innerRadius:s,outerRadius:p,cornerRadius:Math.min(S,j/2),forceCornerRadius:m,cornerIsExternal:b,startAngle:g,endAngle:x}):h({cx:a,cy:c,innerRadius:s,outerRadius:p,startAngle:g,endAngle:x}),n.createElement("path",l({},(0,i.L6)(r,!0),{className:O,d:e,role:"img"}))}},14870:function(t,e,r){"use strict";r.d(e,{v:function(){return N}});var n=r(2265),o=r(75551),i=r.n(o);let a=Math.cos,u=Math.sin,c=Math.sqrt,l=Math.PI,s=2*l;var f={draw(t,e){let r=c(e/l);t.moveTo(r,0),t.arc(0,0,r,0,s)}};let p=c(1/3),h=2*p,d=u(l/10)/u(7*l/10),y=u(s/10)*d,v=-a(s/10)*d,m=c(3),b=c(3)/2,g=1/c(12),x=(g/2+1)*3;var w=r(76115),O=r(67790);c(3),c(3);var j=r(61994),S=r(82944);function P(t){return(P="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var E=["type","size","sizeType"];function k(){return(k=Object.assign?Object.assign.bind():function(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,E)),{},{type:o,size:u,sizeType:l}),p=s.className,h=s.cx,d=s.cy,y=(0,S.L6)(s,!0);return h===+h&&d===+d&&u===+u?n.createElement("path",k({},y,{className:(0,j.Z)("recharts-symbols",p),transform:"translate(".concat(h,", ").concat(d,")"),d:(e=_["symbol".concat(i()(o))]||f,(function(t,e){let r=null,n=(0,O.d)(o);function o(){let o;if(r||(r=o=n()),t.apply(this,arguments).draw(r,+e.apply(this,arguments)),o)return r=null,o+""||null}return t="function"==typeof t?t:(0,w.Z)(t||f),e="function"==typeof e?e:(0,w.Z)(void 0===e?64:+e),o.type=function(e){return arguments.length?(t="function"==typeof e?e:(0,w.Z)(e),o):t},o.size=function(t){return arguments.length?(e="function"==typeof t?t:(0,w.Z)(+t),o):e},o.context=function(t){return arguments.length?(r=null==t?null:t,o):r},o})().type(e).size(C(u,l,o))())})):null};N.registerSymbol=function(t,e){_["symbol".concat(i()(t))]=e}},11638:function(t,e,r){"use strict";r.d(e,{bn:function(){return C},a3:function(){return z},lT:function(){return N},V$:function(){return D},w7:function(){return I}});var n=r(2265),o=r(86757),i=r.n(o),a=r(90231),u=r.n(a),c=r(24342),l=r.n(c),s=r(21652),f=r.n(s),p=r(73649),h=r(61994),d=r(84735),y=r(82944);function v(t){return(v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function m(){return(m=Object.assign?Object.assign.bind():function(t){for(var e=1;et.length)&&(e=t.length);for(var r=0,n=Array(e);r0,from:{upperWidth:0,lowerWidth:0,height:p,x:c,y:l},to:{upperWidth:s,lowerWidth:f,height:p,x:c,y:l},duration:j,animationEasing:g,isActive:P},function(t){var e=t.upperWidth,i=t.lowerWidth,u=t.height,c=t.x,l=t.y;return n.createElement(d.ZP,{canBegin:a>0,from:"0px ".concat(-1===a?1:a,"px"),to:"".concat(a,"px 0px"),attributeName:"strokeDasharray",begin:S,duration:j,easing:g},n.createElement("path",m({},(0,y.L6)(r,!0),{className:E,d:w(c,l,e,i,u),ref:o})))}):n.createElement("g",null,n.createElement("path",m({},(0,y.L6)(r,!0),{className:E,d:w(c,l,s,f,p)})))},S=r(60474),P=r(9841),E=r(14870),k=["option","shapeType","propTransformer","activeClassName","isActive"];function A(t){return(A="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function M(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function _(t){for(var e=1;e=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}(t,k);if((0,n.isValidElement)(r))e=(0,n.cloneElement)(r,_(_({},f),(0,n.isValidElement)(r)?r.props:r));else if(i()(r))e=r(f);else if(u()(r)&&!l()(r)){var p=(void 0===a?function(t,e){return _(_({},e),t)}:a)(r,f);e=n.createElement(T,{shapeType:o,elementProps:p})}else e=n.createElement(T,{shapeType:o,elementProps:f});return s?n.createElement(P.m,{className:void 0===c?"recharts-active-shape":c},e):e}function N(t,e){return null!=e&&"trapezoids"in t.props}function D(t,e){return null!=e&&"sectors"in t.props}function I(t,e){return null!=e&&"points"in t.props}function L(t,e){var r,n,o=t.x===(null==e||null===(r=e.labelViewBox)||void 0===r?void 0:r.x)||t.x===e.x,i=t.y===(null==e||null===(n=e.labelViewBox)||void 0===n?void 0:n.y)||t.y===e.y;return o&&i}function B(t,e){var r=t.endAngle===e.endAngle,n=t.startAngle===e.startAngle;return r&&n}function R(t,e){var r=t.x===e.x,n=t.y===e.y,o=t.z===e.z;return r&&n&&o}function z(t){var e,r,n,o=t.activeTooltipItem,i=t.graphicalItem,a=t.itemData,u=(N(i,o)?e="trapezoids":D(i,o)?e="sectors":I(i,o)&&(e="points"),e),c=N(i,o)?null===(r=o.tooltipPayload)||void 0===r||null===(r=r[0])||void 0===r||null===(r=r.payload)||void 0===r?void 0:r.payload:D(i,o)?null===(n=o.tooltipPayload)||void 0===n||null===(n=n[0])||void 0===n||null===(n=n.payload)||void 0===n?void 0:n.payload:I(i,o)?o.payload:{},l=a.filter(function(t,e){var r=f()(c,t),n=i.props[u].filter(function(t){var e;return(N(i,o)?e=L:D(i,o)?e=B:I(i,o)&&(e=R),e)(t,o)}),a=i.props[u].indexOf(n[n.length-1]);return r&&e===a});return a.indexOf(l[l.length-1])}},25311:function(t,e,r){"use strict";r.d(e,{Ky:function(){return w},O1:function(){return b},_b:function(){return g},t9:function(){return m},xE:function(){return O}});var n=r(41443),o=r.n(n),i=r(32242),a=r.n(i),u=r(85355),c=r(82944),l=r(16630),s=r(31699);function f(t){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(t,e){for(var r=0;r0&&(A=Math.min((t||0)-(M[e-1]||0),A))}),Number.isFinite(A)){var _=A/k,T="vertical"===g.layout?r.height:r.width;if("gap"===g.padding&&(c=_*T/2),"no-gap"===g.padding){var C=(0,l.h1)(t.barCategoryGap,_*T),N=_*T/2;c=N-C-(N-C)/T*C}}}s="xAxis"===n?[r.left+(j.left||0)+(c||0),r.left+r.width-(j.right||0)-(c||0)]:"yAxis"===n?"horizontal"===f?[r.top+r.height-(j.bottom||0),r.top+(j.top||0)]:[r.top+(j.top||0)+(c||0),r.top+r.height-(j.bottom||0)-(c||0)]:g.range,P&&(s=[s[1],s[0]]);var D=(0,u.Hq)(g,o,m),I=D.scale,L=D.realScaleType;I.domain(w).range(s),(0,u.zF)(I);var B=(0,u.g$)(I,d(d({},g),{},{realScaleType:L}));"xAxis"===n?(b="top"===x&&!S||"bottom"===x&&S,p=r.left,h=v[E]-b*g.height):"yAxis"===n&&(b="left"===x&&!S||"right"===x&&S,p=v[E]-b*g.width,h=r.top);var R=d(d(d({},g),B),{},{realScaleType:L,x:p,y:h,scale:I,width:"xAxis"===n?r.width:g.width,height:"yAxis"===n?r.height:g.height});return R.bandSize=(0,u.zT)(R,B),g.hide||"xAxis"!==n?g.hide||(v[E]+=(b?-1:1)*R.width):v[E]+=(b?-1:1)*R.height,d(d({},i),{},y({},a,R))},{})},b=function(t,e){var r=t.x,n=t.y,o=e.x,i=e.y;return{x:Math.min(r,o),y:Math.min(n,i),width:Math.abs(o-r),height:Math.abs(i-n)}},g=function(t){return b({x:t.x1,y:t.y1},{x:t.x2,y:t.y2})},x=function(){var t,e;function r(t){!function(t,e){if(!(t instanceof e))throw TypeError("Cannot call a class as a function")}(this,r),this.scale=t}return t=[{key:"domain",get:function(){return this.scale.domain}},{key:"range",get:function(){return this.scale.range}},{key:"rangeMin",get:function(){return this.range()[0]}},{key:"rangeMax",get:function(){return this.range()[1]}},{key:"bandwidth",get:function(){return this.scale.bandwidth}},{key:"apply",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=e.bandAware,n=e.position;if(void 0!==t){if(n)switch(n){case"start":default:return this.scale(t);case"middle":var o=this.bandwidth?this.bandwidth()/2:0;return this.scale(t)+o;case"end":var i=this.bandwidth?this.bandwidth():0;return this.scale(t)+i}if(r){var a=this.bandwidth?this.bandwidth()/2:0;return this.scale(t)+a}return this.scale(t)}}},{key:"isInRange",value:function(t){var e=this.range(),r=e[0],n=e[e.length-1];return r<=n?t>=r&&t<=n:t>=n&&t<=r}}],e=[{key:"create",value:function(t){return new r(t)}}],t&&p(r.prototype,t),e&&p(r,e),Object.defineProperty(r,"prototype",{writable:!1}),r}();y(x,"EPS",1e-4);var w=function(t){var e=Object.keys(t).reduce(function(e,r){return d(d({},e),{},y({},r,x.create(t[r])))},{});return d(d({},e),{},{apply:function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.bandAware,i=r.position;return o()(t,function(t,r){return e[r].apply(t,{bandAware:n,position:i})})},isInRange:function(t){return a()(t,function(t,r){return e[r].isInRange(t)})}})},O=function(t){var e=t.width,r=t.height,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=(n%180+180)%180*Math.PI/180,i=Math.atan(r/e);return Math.abs(o>i&&otx(e,t()).base(e.base()),tj.o.apply(e,arguments),e}},scaleOrdinal:function(){return tX.Z},scalePoint:function(){return f.x},scalePow:function(){return tJ},scaleQuantile:function(){return function t(){var e,r=[],n=[],o=[];function i(){var t=0,e=Math.max(1,n.length);for(o=Array(e-1);++t=1)return+r(t[n-1],n-1,t);var n,o=(n-1)*e,i=Math.floor(o),a=+r(t[i],i,t);return a+(+r(t[i+1],i+1,t)-a)*(o-i)}}(r,t/e);return a}function a(t){return null==t||isNaN(t=+t)?e:n[P(o,t)]}return a.invertExtent=function(t){var e=n.indexOf(t);return e<0?[NaN,NaN]:[e>0?o[e-1]:r[0],e=o?[i[o-1],n]:[i[e-1],i[e]]},u.unknown=function(t){return arguments.length&&(e=t),u},u.thresholds=function(){return i.slice()},u.copy=function(){return t().domain([r,n]).range(a).unknown(e)},tj.o.apply(tI(u),arguments)}},scaleRadial:function(){return function t(){var e,r=tO(),n=[0,1],o=!1;function i(t){var n,i=Math.sign(n=r(t))*Math.sqrt(Math.abs(n));return isNaN(i)?e:o?Math.round(i):i}return i.invert=function(t){return r.invert(t1(t))},i.domain=function(t){return arguments.length?(r.domain(t),i):r.domain()},i.range=function(t){return arguments.length?(r.range((n=Array.from(t,td)).map(t1)),i):n.slice()},i.rangeRound=function(t){return i.range(t).round(!0)},i.round=function(t){return arguments.length?(o=!!t,i):o},i.clamp=function(t){return arguments.length?(r.clamp(t),i):r.clamp()},i.unknown=function(t){return arguments.length?(e=t,i):e},i.copy=function(){return t(r.domain(),n).round(o).clamp(r.clamp()).unknown(e)},tj.o.apply(i,arguments),tI(i)}},scaleSequential:function(){return function t(){var e=tI(rX()(tv));return e.copy=function(){return rG(e,t())},tj.O.apply(e,arguments)}},scaleSequentialLog:function(){return function t(){var e=tZ(rX()).domain([1,10]);return e.copy=function(){return rG(e,t()).base(e.base())},tj.O.apply(e,arguments)}},scaleSequentialPow:function(){return rV},scaleSequentialQuantile:function(){return function t(){var e=[],r=tv;function n(t){if(null!=t&&!isNaN(t=+t))return r((P(e,t,1)-1)/(e.length-1))}return n.domain=function(t){if(!arguments.length)return e.slice();for(let r of(e=[],t))null==r||isNaN(r=+r)||e.push(r);return e.sort(g),n},n.interpolator=function(t){return arguments.length?(r=t,n):r},n.range=function(){return e.map((t,n)=>r(n/(e.length-1)))},n.quantiles=function(t){return Array.from({length:t+1},(r,n)=>(function(t,e,r){if(!(!(n=(t=Float64Array.from(function*(t,e){if(void 0===e)for(let e of t)null!=e&&(e=+e)>=e&&(yield e);else{let r=-1;for(let n of t)null!=(n=e(n,++r,t))&&(n=+n)>=n&&(yield n)}}(t,void 0))).length)||isNaN(e=+e))){if(e<=0||n<2)return t5(t);if(e>=1)return t2(t);var n,o=(n-1)*e,i=Math.floor(o),a=t2((function t(e,r,n=0,o=1/0,i){if(r=Math.floor(r),n=Math.floor(Math.max(0,n)),o=Math.floor(Math.min(e.length-1,o)),!(n<=r&&r<=o))return e;for(i=void 0===i?t6:function(t=g){if(t===g)return t6;if("function"!=typeof t)throw TypeError("compare is not a function");return(e,r)=>{let n=t(e,r);return n||0===n?n:(0===t(r,r))-(0===t(e,e))}}(i);o>n;){if(o-n>600){let a=o-n+1,u=r-n+1,c=Math.log(a),l=.5*Math.exp(2*c/3),s=.5*Math.sqrt(c*l*(a-l)/a)*(u-a/2<0?-1:1),f=Math.max(n,Math.floor(r-u*l/a+s)),p=Math.min(o,Math.floor(r+(a-u)*l/a+s));t(e,r,f,p,i)}let a=e[r],u=n,c=o;for(t3(e,n,r),i(e[o],a)>0&&t3(e,n,o);ui(e[u],a);)++u;for(;i(e[c],a)>0;)--c}0===i(e[n],a)?t3(e,n,c):t3(e,++c,o),c<=r&&(n=c+1),r<=c&&(o=c-1)}return e})(t,i).subarray(0,i+1));return a+(t5(t.subarray(i+1))-a)*(o-i)}})(e,n/t))},n.copy=function(){return t(r).domain(e)},tj.O.apply(n,arguments)}},scaleSequentialSqrt:function(){return rK},scaleSequentialSymlog:function(){return function t(){var e=tH(rX());return e.copy=function(){return rG(e,t()).constant(e.constant())},tj.O.apply(e,arguments)}},scaleSqrt:function(){return t0},scaleSymlog:function(){return function t(){var e=tH(tw());return e.copy=function(){return tx(e,t()).constant(e.constant())},tj.o.apply(e,arguments)}},scaleThreshold:function(){return function t(){var e,r=[.5],n=[0,1],o=1;function i(t){return null!=t&&t<=t?n[P(r,t,0,o)]:e}return i.domain=function(t){return arguments.length?(o=Math.min((r=Array.from(t)).length,n.length-1),i):r.slice()},i.range=function(t){return arguments.length?(n=Array.from(t),o=Math.min(r.length,n.length-1),i):n.slice()},i.invertExtent=function(t){var e=n.indexOf(t);return[r[e-1],r[e]]},i.unknown=function(t){return arguments.length?(e=t,i):e},i.copy=function(){return t().domain(r).range(n).unknown(e)},tj.o.apply(i,arguments)}},scaleTime:function(){return rY},scaleUtc:function(){return rH},tickFormat:function(){return tD}});var f=r(55284);let p=Math.sqrt(50),h=Math.sqrt(10),d=Math.sqrt(2);function y(t,e,r){let n,o,i;let a=(e-t)/Math.max(0,r),u=Math.floor(Math.log10(a)),c=a/Math.pow(10,u),l=c>=p?10:c>=h?5:c>=d?2:1;return(u<0?(n=Math.round(t*(i=Math.pow(10,-u)/l)),o=Math.round(e*i),n/ie&&--o,i=-i):(n=Math.round(t/(i=Math.pow(10,u)*l)),o=Math.round(e/i),n*ie&&--o),o0))return[];if(t===e)return[t];let n=e=o))return[];let u=i-o+1,c=Array(u);if(n){if(a<0)for(let t=0;te?1:t>=e?0:NaN}function x(t,e){return null==t||null==e?NaN:et?1:e>=t?0:NaN}function w(t){let e,r,n;function o(t,n,o=0,i=t.length){if(o>>1;0>r(t[e],n)?o=e+1:i=e}while(og(t(e),r),n=(e,r)=>t(e)-r):(e=t===g||t===x?t:O,r=t,n=t),{left:o,center:function(t,e,r=0,i=t.length){let a=o(t,e,r,i-1);return a>r&&n(t[a-1],e)>-n(t[a],e)?a-1:a},right:function(t,n,o=0,i=t.length){if(o>>1;0>=r(t[e],n)?o=e+1:i=e}while(o>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===r?Z(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===r?Z(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=N.exec(t))?new Y(e[1],e[2],e[3],1):(e=D.exec(t))?new Y(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=I.exec(t))?Z(e[1],e[2],e[3],e[4]):(e=L.exec(t))?Z(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=B.exec(t))?Q(e[1],e[2]/100,e[3]/100,1):(e=R.exec(t))?Q(e[1],e[2]/100,e[3]/100,e[4]):z.hasOwnProperty(t)?q(z[t]):"transparent"===t?new Y(NaN,NaN,NaN,0):null}function q(t){return new Y(t>>16&255,t>>8&255,255&t,1)}function Z(t,e,r,n){return n<=0&&(t=e=r=NaN),new Y(t,e,r,n)}function W(t,e,r,n){var o;return 1==arguments.length?((o=t)instanceof A||(o=$(o)),o)?new Y((o=o.rgb()).r,o.g,o.b,o.opacity):new Y:new Y(t,e,r,null==n?1:n)}function Y(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}function H(){return`#${K(this.r)}${K(this.g)}${K(this.b)}`}function X(){let t=G(this.opacity);return`${1===t?"rgb(":"rgba("}${V(this.r)}, ${V(this.g)}, ${V(this.b)}${1===t?")":`, ${t})`}`}function G(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function V(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function K(t){return((t=V(t))<16?"0":"")+t.toString(16)}function Q(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new tt(t,e,r,n)}function J(t){if(t instanceof tt)return new tt(t.h,t.s,t.l,t.opacity);if(t instanceof A||(t=$(t)),!t)return new tt;if(t instanceof tt)return t;var e=(t=t.rgb()).r/255,r=t.g/255,n=t.b/255,o=Math.min(e,r,n),i=Math.max(e,r,n),a=NaN,u=i-o,c=(i+o)/2;return u?(a=e===i?(r-n)/u+(r0&&c<1?0:a,new tt(a,u,c,t.opacity)}function tt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}function te(t){return(t=(t||0)%360)<0?t+360:t}function tr(t){return Math.max(0,Math.min(1,t||0))}function tn(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}function to(t,e,r,n,o){var i=t*t,a=i*t;return((1-3*t+3*i-a)*e+(4-6*i+3*a)*r+(1+3*t+3*i-3*a)*n+a*o)/6}E(A,$,{copy(t){return Object.assign(new this.constructor,this,t)},displayable(){return this.rgb().displayable()},hex:U,formatHex:U,formatHex8:function(){return this.rgb().formatHex8()},formatHsl:function(){return J(this).formatHsl()},formatRgb:F,toString:F}),E(Y,W,k(A,{brighter(t){return t=null==t?1.4285714285714286:Math.pow(1.4285714285714286,t),new Y(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=null==t?.7:Math.pow(.7,t),new Y(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new Y(V(this.r),V(this.g),V(this.b),G(this.opacity))},displayable(){return -.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:H,formatHex:H,formatHex8:function(){return`#${K(this.r)}${K(this.g)}${K(this.b)}${K((isNaN(this.opacity)?1:this.opacity)*255)}`},formatRgb:X,toString:X})),E(tt,function(t,e,r,n){return 1==arguments.length?J(t):new tt(t,e,r,null==n?1:n)},k(A,{brighter(t){return t=null==t?1.4285714285714286:Math.pow(1.4285714285714286,t),new tt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=null==t?.7:Math.pow(.7,t),new tt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,o=2*r-n;return new Y(tn(t>=240?t-240:t+120,o,n),tn(t,o,n),tn(t<120?t+240:t-120,o,n),this.opacity)},clamp(){return new tt(te(this.h),tr(this.s),tr(this.l),G(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){let t=G(this.opacity);return`${1===t?"hsl(":"hsla("}${te(this.h)}, ${100*tr(this.s)}%, ${100*tr(this.l)}%${1===t?")":`, ${t})`}`}}));var ti=t=>()=>t;function ta(t,e){var r=e-t;return r?function(e){return t+e*r}:ti(isNaN(t)?e:t)}var tu=function t(e){var r,n=1==(r=+(r=e))?ta:function(t,e){var n,o,i;return e-t?(n=t,o=e,n=Math.pow(n,i=r),o=Math.pow(o,i)-n,i=1/i,function(t){return Math.pow(n+t*o,i)}):ti(isNaN(t)?e:t)};function o(t,e){var r=n((t=W(t)).r,(e=W(e)).r),o=n(t.g,e.g),i=n(t.b,e.b),a=ta(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=o(e),t.b=i(e),t.opacity=a(e),t+""}}return o.gamma=t,o}(1);function tc(t){return function(e){var r,n,o=e.length,i=Array(o),a=Array(o),u=Array(o);for(r=0;r=1?(r=1,e-1):Math.floor(r*e),o=t[n],i=t[n+1],a=n>0?t[n-1]:2*o-i,u=nu&&(a=e.slice(u,a),l[c]?l[c]+=a:l[++c]=a),(o=o[0])===(i=i[0])?l[c]?l[c]+=i:l[++c]=i:(l[++c]=null,s.push({i:c,x:tl(o,i)})),u=tf.lastIndex;return ue&&(r=t,t=e,e=r),l=function(r){return Math.max(t,Math.min(e,r))}),n=c>2?tg:tb,o=i=null,f}function f(e){return null==e||isNaN(e=+e)?r:(o||(o=n(a.map(t),u,c)))(t(l(e)))}return f.invert=function(r){return l(e((i||(i=n(u,a.map(t),tl)))(r)))},f.domain=function(t){return arguments.length?(a=Array.from(t,td),s()):a.slice()},f.range=function(t){return arguments.length?(u=Array.from(t),s()):u.slice()},f.rangeRound=function(t){return u=Array.from(t),c=th,s()},f.clamp=function(t){return arguments.length?(l=!!t||tv,s()):l!==tv},f.interpolate=function(t){return arguments.length?(c=t,s()):c},f.unknown=function(t){return arguments.length?(r=t,f):r},function(r,n){return t=r,e=n,s()}}function tO(){return tw()(tv,tv)}var tj=r(89999),tS=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function tP(t){var e;if(!(e=tS.exec(t)))throw Error("invalid format: "+t);return new tE({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function tE(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function tk(t,e){if((r=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var r,n=t.slice(0,r);return[n.length>1?n[0]+n.slice(2):n,+t.slice(r+1)]}function tA(t){return(t=tk(Math.abs(t)))?t[1]:NaN}function tM(t,e){var r=tk(t,e);if(!r)return t+"";var n=r[0],o=r[1];return o<0?"0."+Array(-o).join("0")+n:n.length>o+1?n.slice(0,o+1)+"."+n.slice(o+1):n+Array(o-n.length+2).join("0")}tP.prototype=tE.prototype,tE.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};var t_={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>tM(100*t,e),r:tM,s:function(t,e){var r=tk(t,e);if(!r)return t+"";var o=r[0],i=r[1],a=i-(n=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=o.length;return a===u?o:a>u?o+Array(a-u+1).join("0"):a>0?o.slice(0,a)+"."+o.slice(a):"0."+Array(1-a).join("0")+tk(t,Math.max(0,e+a-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function tT(t){return t}var tC=Array.prototype.map,tN=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"];function tD(t,e,r,n){var o,u,c=b(t,e,r);switch((n=tP(null==n?",f":n)).type){case"s":var l=Math.max(Math.abs(t),Math.abs(e));return null!=n.precision||isNaN(u=Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(tA(l)/3)))-tA(Math.abs(c))))||(n.precision=u),a(n,l);case"":case"e":case"g":case"p":case"r":null!=n.precision||isNaN(u=Math.max(0,tA(Math.abs(Math.max(Math.abs(t),Math.abs(e)))-(o=Math.abs(o=c)))-tA(o))+1)||(n.precision=u-("e"===n.type));break;case"f":case"%":null!=n.precision||isNaN(u=Math.max(0,-tA(Math.abs(c))))||(n.precision=u-("%"===n.type)*2)}return i(n)}function tI(t){var e=t.domain;return t.ticks=function(t){var r=e();return v(r[0],r[r.length-1],null==t?10:t)},t.tickFormat=function(t,r){var n=e();return tD(n[0],n[n.length-1],null==t?10:t,r)},t.nice=function(r){null==r&&(r=10);var n,o,i=e(),a=0,u=i.length-1,c=i[a],l=i[u],s=10;for(l0;){if((o=m(c,l,r))===n)return i[a]=c,i[u]=l,e(i);if(o>0)c=Math.floor(c/o)*o,l=Math.ceil(l/o)*o;else if(o<0)c=Math.ceil(c*o)/o,l=Math.floor(l*o)/o;else break;n=o}return t},t}function tL(){var t=tO();return t.copy=function(){return tx(t,tL())},tj.o.apply(t,arguments),tI(t)}function tB(t,e){t=t.slice();var r,n=0,o=t.length-1,i=t[n],a=t[o];return a-t(-e,r)}function tZ(t){let e,r;let n=t(tR,tz),o=n.domain,a=10;function u(){var i,u;return e=(i=a)===Math.E?Math.log:10===i&&Math.log10||2===i&&Math.log2||(i=Math.log(i),t=>Math.log(t)/i),r=10===(u=a)?t$:u===Math.E?Math.exp:t=>Math.pow(u,t),o()[0]<0?(e=tq(e),r=tq(r),t(tU,tF)):t(tR,tz),n}return n.base=function(t){return arguments.length?(a=+t,u()):a},n.domain=function(t){return arguments.length?(o(t),u()):o()},n.ticks=t=>{let n,i;let u=o(),c=u[0],l=u[u.length-1],s=l0){for(;f<=p;++f)for(n=1;nl)break;d.push(i)}}else for(;f<=p;++f)for(n=a-1;n>=1;--n)if(!((i=f>0?n/r(-f):n*r(f))l)break;d.push(i)}2*d.length{if(null==t&&(t=10),null==o&&(o=10===a?"s":","),"function"!=typeof o&&(a%1||null!=(o=tP(o)).precision||(o.trim=!0),o=i(o)),t===1/0)return o;let u=Math.max(1,a*t/n.ticks().length);return t=>{let n=t/r(Math.round(e(t)));return n*ao(tB(o(),{floor:t=>r(Math.floor(e(t))),ceil:t=>r(Math.ceil(e(t)))})),n}function tW(t){return function(e){return Math.sign(e)*Math.log1p(Math.abs(e/t))}}function tY(t){return function(e){return Math.sign(e)*Math.expm1(Math.abs(e))*t}}function tH(t){var e=1,r=t(tW(1),tY(e));return r.constant=function(r){return arguments.length?t(tW(e=+r),tY(e)):e},tI(r)}i=(o=function(t){var e,r,o,i=void 0===t.grouping||void 0===t.thousands?tT:(e=tC.call(t.grouping,Number),r=t.thousands+"",function(t,n){for(var o=t.length,i=[],a=0,u=e[0],c=0;o>0&&u>0&&(c+u+1>n&&(u=Math.max(1,n-c)),i.push(t.substring(o-=u,o+u)),!((c+=u+1)>n));)u=e[a=(a+1)%e.length];return i.reverse().join(r)}),a=void 0===t.currency?"":t.currency[0]+"",u=void 0===t.currency?"":t.currency[1]+"",c=void 0===t.decimal?".":t.decimal+"",l=void 0===t.numerals?tT:(o=tC.call(t.numerals,String),function(t){return t.replace(/[0-9]/g,function(t){return o[+t]})}),s=void 0===t.percent?"%":t.percent+"",f=void 0===t.minus?"āˆ’":t.minus+"",p=void 0===t.nan?"NaN":t.nan+"";function h(t){var e=(t=tP(t)).fill,r=t.align,o=t.sign,h=t.symbol,d=t.zero,y=t.width,v=t.comma,m=t.precision,b=t.trim,g=t.type;"n"===g?(v=!0,g="g"):t_[g]||(void 0===m&&(m=12),b=!0,g="g"),(d||"0"===e&&"="===r)&&(d=!0,e="0",r="=");var x="$"===h?a:"#"===h&&/[boxX]/.test(g)?"0"+g.toLowerCase():"",w="$"===h?u:/[%p]/.test(g)?s:"",O=t_[g],j=/[defgprs%]/.test(g);function S(t){var a,u,s,h=x,S=w;if("c"===g)S=O(t)+S,t="";else{var P=(t=+t)<0||1/t<0;if(t=isNaN(t)?p:O(Math.abs(t),m),b&&(t=function(t){e:for(var e,r=t.length,n=1,o=-1;n0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t}(t)),P&&0==+t&&"+"!==o&&(P=!1),h=(P?"("===o?o:f:"-"===o||"("===o?"":o)+h,S=("s"===g?tN[8+n/3]:"")+S+(P&&"("===o?")":""),j){for(a=-1,u=t.length;++a(s=t.charCodeAt(a))||s>57){S=(46===s?c+t.slice(a+1):t.slice(a))+S,t=t.slice(0,a);break}}}v&&!d&&(t=i(t,1/0));var E=h.length+t.length+S.length,k=E>1)+h+t+S+k.slice(E);break;default:t=k+h+t+S}return l(t)}return m=void 0===m?6:/[gprs]/.test(g)?Math.max(1,Math.min(21,m)):Math.max(0,Math.min(20,m)),S.toString=function(){return t+""},S}return{format:h,formatPrefix:function(t,e){var r=h(((t=tP(t)).type="f",t)),n=3*Math.max(-8,Math.min(8,Math.floor(tA(e)/3))),o=Math.pow(10,-n),i=tN[8+n/3];return function(t){return r(o*t)+i}}}}({thousands:",",grouping:[3],currency:["$",""]})).format,a=o.formatPrefix;var tX=r(36967);function tG(t){return function(e){return e<0?-Math.pow(-e,t):Math.pow(e,t)}}function tV(t){return t<0?-Math.sqrt(-t):Math.sqrt(t)}function tK(t){return t<0?-t*t:t*t}function tQ(t){var e=t(tv,tv),r=1;return e.exponent=function(e){return arguments.length?1==(r=+e)?t(tv,tv):.5===r?t(tV,tK):t(tG(r),tG(1/r)):r},tI(e)}function tJ(){var t=tQ(tw());return t.copy=function(){return tx(t,tJ()).exponent(t.exponent())},tj.o.apply(t,arguments),t}function t0(){return tJ.apply(null,arguments).exponent(.5)}function t1(t){return Math.sign(t)*t*t}function t2(t,e){let r;if(void 0===e)for(let e of t)null!=e&&(r=e)&&(r=e);else{let n=-1;for(let o of t)null!=(o=e(o,++n,t))&&(r=o)&&(r=o)}return r}function t5(t,e){let r;if(void 0===e)for(let e of t)null!=e&&(r>e||void 0===r&&e>=e)&&(r=e);else{let n=-1;for(let o of t)null!=(o=e(o,++n,t))&&(r>o||void 0===r&&o>=o)&&(r=o)}return r}function t6(t,e){return(null==t||!(t>=t))-(null==e||!(e>=e))||(te?1:0)}function t3(t,e,r){let n=t[e];t[e]=t[r],t[r]=n}let t7=new Date,t4=new Date;function t8(t,e,r,n){function o(e){return t(e=0==arguments.length?new Date:new Date(+e)),e}return o.floor=e=>(t(e=new Date(+e)),e),o.ceil=r=>(t(r=new Date(r-1)),e(r,1),t(r),r),o.round=t=>{let e=o(t),r=o.ceil(t);return t-e(e(t=new Date(+t),null==r?1:Math.floor(r)),t),o.range=(r,n,i)=>{let a;let u=[];if(r=o.ceil(r),i=null==i?1:Math.floor(i),!(r0))return u;do u.push(a=new Date(+r)),e(r,i),t(r);while(at8(e=>{if(e>=e)for(;t(e),!r(e);)e.setTime(e-1)},(t,n)=>{if(t>=t){if(n<0)for(;++n<=0;)for(;e(t,-1),!r(t););else for(;--n>=0;)for(;e(t,1),!r(t););}}),r&&(o.count=(e,n)=>(t7.setTime(+e),t4.setTime(+n),t(t7),t(t4),Math.floor(r(t7,t4))),o.every=t=>isFinite(t=Math.floor(t))&&t>0?t>1?o.filter(n?e=>n(e)%t==0:e=>o.count(0,e)%t==0):o:null),o}let t9=t8(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);t9.every=t=>isFinite(t=Math.floor(t))&&t>0?t>1?t8(e=>{e.setTime(Math.floor(e/t)*t)},(e,r)=>{e.setTime(+e+r*t)},(e,r)=>(r-e)/t):t9:null,t9.range;let et=t8(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+1e3*e)},(t,e)=>(e-t)/1e3,t=>t.getUTCSeconds());et.range;let ee=t8(t=>{t.setTime(t-t.getMilliseconds()-1e3*t.getSeconds())},(t,e)=>{t.setTime(+t+6e4*e)},(t,e)=>(e-t)/6e4,t=>t.getMinutes());ee.range;let er=t8(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+6e4*e)},(t,e)=>(e-t)/6e4,t=>t.getUTCMinutes());er.range;let en=t8(t=>{t.setTime(t-t.getMilliseconds()-1e3*t.getSeconds()-6e4*t.getMinutes())},(t,e)=>{t.setTime(+t+36e5*e)},(t,e)=>(e-t)/36e5,t=>t.getHours());en.range;let eo=t8(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+36e5*e)},(t,e)=>(e-t)/36e5,t=>t.getUTCHours());eo.range;let ei=t8(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5,t=>t.getDate()-1);ei.range;let ea=t8(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>t.getUTCDate()-1);ea.range;let eu=t8(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/864e5,t=>Math.floor(t/864e5));function ec(t){return t8(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(t,e)=>{t.setDate(t.getDate()+7*e)},(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/6048e5)}eu.range;let el=ec(0),es=ec(1),ef=ec(2),ep=ec(3),eh=ec(4),ed=ec(5),ey=ec(6);function ev(t){return t8(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+7*e)},(t,e)=>(e-t)/6048e5)}el.range,es.range,ef.range,ep.range,eh.range,ed.range,ey.range;let em=ev(0),eb=ev(1),eg=ev(2),ex=ev(3),ew=ev(4),eO=ev(5),ej=ev(6);em.range,eb.range,eg.range,ex.range,ew.range,eO.range,ej.range;let eS=t8(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth());eS.range;let eP=t8(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth());eP.range;let eE=t8(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());eE.every=t=>isFinite(t=Math.floor(t))&&t>0?t8(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,r)=>{e.setFullYear(e.getFullYear()+r*t)}):null,eE.range;let ek=t8(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());function eA(t,e,r,n,o,i){let a=[[et,1,1e3],[et,5,5e3],[et,15,15e3],[et,30,3e4],[i,1,6e4],[i,5,3e5],[i,15,9e5],[i,30,18e5],[o,1,36e5],[o,3,108e5],[o,6,216e5],[o,12,432e5],[n,1,864e5],[n,2,1728e5],[r,1,6048e5],[e,1,2592e6],[e,3,7776e6],[t,1,31536e6]];function u(e,r,n){let o=Math.abs(r-e)/n,i=w(([,,t])=>t).right(a,o);if(i===a.length)return t.every(b(e/31536e6,r/31536e6,n));if(0===i)return t9.every(Math.max(b(e,r,n),1));let[u,c]=a[o/a[i-1][2]isFinite(t=Math.floor(t))&&t>0?t8(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,r)=>{e.setUTCFullYear(e.getUTCFullYear()+r*t)}):null,ek.range;let[eM,e_]=eA(ek,eP,em,eu,eo,er),[eT,eC]=eA(eE,eS,el,ei,en,ee);function eN(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function eD(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function eI(t,e,r){return{y:t,m:e,d:r,H:0,M:0,S:0,L:0}}var eL={"-":"",_:" ",0:"0"},eB=/^\s*\d+/,eR=/^%/,ez=/[\\^$*+?|[\]().{}]/g;function eU(t,e,r){var n=t<0?"-":"",o=(n?-t:t)+"",i=o.length;return n+(i[t.toLowerCase(),e]))}function eZ(t,e,r){var n=eB.exec(e.slice(r,r+1));return n?(t.w=+n[0],r+n[0].length):-1}function eW(t,e,r){var n=eB.exec(e.slice(r,r+1));return n?(t.u=+n[0],r+n[0].length):-1}function eY(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.U=+n[0],r+n[0].length):-1}function eH(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.V=+n[0],r+n[0].length):-1}function eX(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.W=+n[0],r+n[0].length):-1}function eG(t,e,r){var n=eB.exec(e.slice(r,r+4));return n?(t.y=+n[0],r+n[0].length):-1}function eV(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.y=+n[0]+(+n[0]>68?1900:2e3),r+n[0].length):-1}function eK(t,e,r){var n=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(r,r+6));return n?(t.Z=n[1]?0:-(n[2]+(n[3]||"00")),r+n[0].length):-1}function eQ(t,e,r){var n=eB.exec(e.slice(r,r+1));return n?(t.q=3*n[0]-3,r+n[0].length):-1}function eJ(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function e0(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function e1(t,e,r){var n=eB.exec(e.slice(r,r+3));return n?(t.m=0,t.d=+n[0],r+n[0].length):-1}function e2(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function e5(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function e6(t,e,r){var n=eB.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function e3(t,e,r){var n=eB.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function e7(t,e,r){var n=eB.exec(e.slice(r,r+6));return n?(t.L=Math.floor(n[0]/1e3),r+n[0].length):-1}function e4(t,e,r){var n=eR.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function e8(t,e,r){var n=eB.exec(e.slice(r));return n?(t.Q=+n[0],r+n[0].length):-1}function e9(t,e,r){var n=eB.exec(e.slice(r));return n?(t.s=+n[0],r+n[0].length):-1}function rt(t,e){return eU(t.getDate(),e,2)}function re(t,e){return eU(t.getHours(),e,2)}function rr(t,e){return eU(t.getHours()%12||12,e,2)}function rn(t,e){return eU(1+ei.count(eE(t),t),e,3)}function ro(t,e){return eU(t.getMilliseconds(),e,3)}function ri(t,e){return ro(t,e)+"000"}function ra(t,e){return eU(t.getMonth()+1,e,2)}function ru(t,e){return eU(t.getMinutes(),e,2)}function rc(t,e){return eU(t.getSeconds(),e,2)}function rl(t){var e=t.getDay();return 0===e?7:e}function rs(t,e){return eU(el.count(eE(t)-1,t),e,2)}function rf(t){var e=t.getDay();return e>=4||0===e?eh(t):eh.ceil(t)}function rp(t,e){return t=rf(t),eU(eh.count(eE(t),t)+(4===eE(t).getDay()),e,2)}function rh(t){return t.getDay()}function rd(t,e){return eU(es.count(eE(t)-1,t),e,2)}function ry(t,e){return eU(t.getFullYear()%100,e,2)}function rv(t,e){return eU((t=rf(t)).getFullYear()%100,e,2)}function rm(t,e){return eU(t.getFullYear()%1e4,e,4)}function rb(t,e){var r=t.getDay();return eU((t=r>=4||0===r?eh(t):eh.ceil(t)).getFullYear()%1e4,e,4)}function rg(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+eU(e/60|0,"0",2)+eU(e%60,"0",2)}function rx(t,e){return eU(t.getUTCDate(),e,2)}function rw(t,e){return eU(t.getUTCHours(),e,2)}function rO(t,e){return eU(t.getUTCHours()%12||12,e,2)}function rj(t,e){return eU(1+ea.count(ek(t),t),e,3)}function rS(t,e){return eU(t.getUTCMilliseconds(),e,3)}function rP(t,e){return rS(t,e)+"000"}function rE(t,e){return eU(t.getUTCMonth()+1,e,2)}function rk(t,e){return eU(t.getUTCMinutes(),e,2)}function rA(t,e){return eU(t.getUTCSeconds(),e,2)}function rM(t){var e=t.getUTCDay();return 0===e?7:e}function r_(t,e){return eU(em.count(ek(t)-1,t),e,2)}function rT(t){var e=t.getUTCDay();return e>=4||0===e?ew(t):ew.ceil(t)}function rC(t,e){return t=rT(t),eU(ew.count(ek(t),t)+(4===ek(t).getUTCDay()),e,2)}function rN(t){return t.getUTCDay()}function rD(t,e){return eU(eb.count(ek(t)-1,t),e,2)}function rI(t,e){return eU(t.getUTCFullYear()%100,e,2)}function rL(t,e){return eU((t=rT(t)).getUTCFullYear()%100,e,2)}function rB(t,e){return eU(t.getUTCFullYear()%1e4,e,4)}function rR(t,e){var r=t.getUTCDay();return eU((t=r>=4||0===r?ew(t):ew.ceil(t)).getUTCFullYear()%1e4,e,4)}function rz(){return"+0000"}function rU(){return"%"}function rF(t){return+t}function r$(t){return Math.floor(+t/1e3)}function rq(t){return new Date(t)}function rZ(t){return t instanceof Date?+t:+new Date(+t)}function rW(t,e,r,n,o,i,a,u,c,l){var s=tO(),f=s.invert,p=s.domain,h=l(".%L"),d=l(":%S"),y=l("%I:%M"),v=l("%I %p"),m=l("%a %d"),b=l("%b %d"),g=l("%B"),x=l("%Y");function w(t){return(c(t)1)for(var r,n,o,i=1,a=t[e[0]],u=a.length;i=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:rF,s:r$,S:rc,u:rl,U:rs,V:rp,w:rh,W:rd,x:null,X:null,y:ry,Y:rm,Z:rg,"%":rU},x={a:function(t){return a[t.getUTCDay()]},A:function(t){return i[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return u[t.getUTCMonth()]},c:null,d:rx,e:rx,f:rP,g:rL,G:rR,H:rw,I:rO,j:rj,L:rS,m:rE,M:rk,p:function(t){return o[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:rF,s:r$,S:rA,u:rM,U:r_,V:rC,w:rN,W:rD,x:null,X:null,y:rI,Y:rB,Z:rz,"%":rU},w={a:function(t,e,r){var n=h.exec(e.slice(r));return n?(t.w=d.get(n[0].toLowerCase()),r+n[0].length):-1},A:function(t,e,r){var n=f.exec(e.slice(r));return n?(t.w=p.get(n[0].toLowerCase()),r+n[0].length):-1},b:function(t,e,r){var n=m.exec(e.slice(r));return n?(t.m=b.get(n[0].toLowerCase()),r+n[0].length):-1},B:function(t,e,r){var n=y.exec(e.slice(r));return n?(t.m=v.get(n[0].toLowerCase()),r+n[0].length):-1},c:function(t,r,n){return S(t,e,r,n)},d:e0,e:e0,f:e7,g:eV,G:eG,H:e2,I:e2,j:e1,L:e3,m:eJ,M:e5,p:function(t,e,r){var n=l.exec(e.slice(r));return n?(t.p=s.get(n[0].toLowerCase()),r+n[0].length):-1},q:eQ,Q:e8,s:e9,S:e6,u:eW,U:eY,V:eH,w:eZ,W:eX,x:function(t,e,n){return S(t,r,e,n)},X:function(t,e,r){return S(t,n,e,r)},y:eV,Y:eG,Z:eK,"%":e4};function O(t,e){return function(r){var n,o,i,a=[],u=-1,c=0,l=t.length;for(r instanceof Date||(r=new Date(+r));++u53)return null;"w"in i||(i.w=1),"Z"in i?(n=(o=(n=eD(eI(i.y,0,1))).getUTCDay())>4||0===o?eb.ceil(n):eb(n),n=ea.offset(n,(i.V-1)*7),i.y=n.getUTCFullYear(),i.m=n.getUTCMonth(),i.d=n.getUTCDate()+(i.w+6)%7):(n=(o=(n=eN(eI(i.y,0,1))).getDay())>4||0===o?es.ceil(n):es(n),n=ei.offset(n,(i.V-1)*7),i.y=n.getFullYear(),i.m=n.getMonth(),i.d=n.getDate()+(i.w+6)%7)}else("W"in i||"U"in i)&&("w"in i||(i.w="u"in i?i.u%7:"W"in i?1:0),o="Z"in i?eD(eI(i.y,0,1)).getUTCDay():eN(eI(i.y,0,1)).getDay(),i.m=0,i.d="W"in i?(i.w+6)%7+7*i.W-(o+5)%7:i.w+7*i.U-(o+6)%7);return"Z"in i?(i.H+=i.Z/100|0,i.M+=i.Z%100,eD(i)):eN(i)}}function S(t,e,r,n){for(var o,i,a=0,u=e.length,c=r.length;a=c)return -1;if(37===(o=e.charCodeAt(a++))){if(!(i=w[(o=e.charAt(a++))in eL?e.charAt(a++):o])||(n=i(t,r,n))<0)return -1}else if(o!=r.charCodeAt(n++))return -1}return n}return g.x=O(r,g),g.X=O(n,g),g.c=O(e,g),x.x=O(r,x),x.X=O(n,x),x.c=O(e,x),{format:function(t){var e=O(t+="",g);return e.toString=function(){return t},e},parse:function(t){var e=j(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=O(t+="",x);return e.toString=function(){return t},e},utcParse:function(t){var e=j(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]})).format,u.parse,l=u.utcFormat,u.utcParse;var r2=r(22516),r5=r(76115);function r6(t){for(var e=t.length,r=Array(e);--e>=0;)r[e]=e;return r}function r3(t,e){return t[e]}function r7(t){let e=[];return e.key=t,e}var r4=r(95645),r8=r.n(r4),r9=r(99008),nt=r.n(r9),ne=r(77571),nr=r.n(ne),nn=r(86757),no=r.n(nn),ni=r(42715),na=r.n(ni),nu=r(13735),nc=r.n(nu),nl=r(11314),ns=r.n(nl),nf=r(82559),np=r.n(nf),nh=r(75551),nd=r.n(nh),ny=r(21652),nv=r.n(ny),nm=r(34935),nb=r.n(nm),ng=r(61134),nx=r.n(ng);function nw(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r=e?r.apply(void 0,o):t(e-a,nP(function(){for(var t=arguments.length,e=Array(t),n=0;nt.length)&&(e=t.length);for(var r=0,n=Array(e);rn&&(o=n,i=r),[o,i]}function nR(t,e,r){if(t.lte(0))return new(nx())(0);var n=nC.getDigitCount(t.toNumber()),o=new(nx())(10).pow(n),i=t.div(o),a=1!==n?.05:.1,u=new(nx())(Math.ceil(i.div(a).toNumber())).add(r).mul(a).mul(o);return e?u:new(nx())(Math.ceil(u))}function nz(t,e,r){var n=1,o=new(nx())(t);if(!o.isint()&&r){var i=Math.abs(t);i<1?(n=new(nx())(10).pow(nC.getDigitCount(t)-1),o=new(nx())(Math.floor(o.div(n).toNumber())).mul(n)):i>1&&(o=new(nx())(Math.floor(t)))}else 0===t?o=new(nx())(Math.floor((e-1)/2)):r||(o=new(nx())(Math.floor(t)));var a=Math.floor((e-1)/2);return nM(nA(function(t){return o.add(new(nx())(t-a).mul(n)).toNumber()}),nk)(0,e)}var nU=nT(function(t){var e=nD(t,2),r=e[0],n=e[1],o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:6,i=!(arguments.length>2)||void 0===arguments[2]||arguments[2],a=Math.max(o,2),u=nD(nB([r,n]),2),c=u[0],l=u[1];if(c===-1/0||l===1/0){var s=l===1/0?[c].concat(nN(nk(0,o-1).map(function(){return 1/0}))):[].concat(nN(nk(0,o-1).map(function(){return-1/0})),[l]);return r>n?n_(s):s}if(c===l)return nz(c,o,i);var f=function t(e,r,n,o){var i,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0;if(!Number.isFinite((r-e)/(n-1)))return{step:new(nx())(0),tickMin:new(nx())(0),tickMax:new(nx())(0)};var u=nR(new(nx())(r).sub(e).div(n-1),o,a),c=Math.ceil((i=e<=0&&r>=0?new(nx())(0):(i=new(nx())(e).add(r).div(2)).sub(new(nx())(i).mod(u))).sub(e).div(u).toNumber()),l=Math.ceil(new(nx())(r).sub(i).div(u).toNumber()),s=c+l+1;return s>n?t(e,r,n,o,a+1):(s0?l+(n-s):l,c=r>0?c:c+(n-s)),{step:u,tickMin:i.sub(new(nx())(c).mul(u)),tickMax:i.add(new(nx())(l).mul(u))})}(c,l,a,i),p=f.step,h=f.tickMin,d=f.tickMax,y=nC.rangeStep(h,d.add(new(nx())(.1).mul(p)),p);return r>n?n_(y):y});nT(function(t){var e=nD(t,2),r=e[0],n=e[1],o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:6,i=!(arguments.length>2)||void 0===arguments[2]||arguments[2],a=Math.max(o,2),u=nD(nB([r,n]),2),c=u[0],l=u[1];if(c===-1/0||l===1/0)return[r,n];if(c===l)return nz(c,o,i);var s=nR(new(nx())(l).sub(c).div(a-1),i,0),f=nM(nA(function(t){return new(nx())(c).add(new(nx())(t).mul(s)).toNumber()}),nk)(0,a).filter(function(t){return t>=c&&t<=l});return r>n?n_(f):f});var nF=nT(function(t,e){var r=nD(t,2),n=r[0],o=r[1],i=!(arguments.length>2)||void 0===arguments[2]||arguments[2],a=nD(nB([n,o]),2),u=a[0],c=a[1];if(u===-1/0||c===1/0)return[n,o];if(u===c)return[u];var l=nR(new(nx())(c).sub(u).div(Math.max(e,2)-1),i,0),s=[].concat(nN(nC.rangeStep(new(nx())(u),new(nx())(c).sub(new(nx())(.99).mul(l)),l)),[c]);return n>o?n_(s):s}),n$=r(13137),nq=r(16630),nZ=r(82944),nW=r(38569);function nY(t){return(nY="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function nH(t){return function(t){if(Array.isArray(t))return nX(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return nX(t,void 0);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return nX(t,void 0)}}(t)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function nX(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2?arguments[2]:void 0,o=arguments.length>3?arguments[3]:void 0,i=-1,a=null!==(e=null==r?void 0:r.length)&&void 0!==e?e:0;if(a<=1)return 0;if(o&&"angleAxis"===o.axisType&&1e-6>=Math.abs(Math.abs(o.range[1]-o.range[0])-360))for(var u=o.range,c=0;c0?n[c-1].coordinate:n[a-1].coordinate,s=n[c].coordinate,f=c>=a-1?n[0].coordinate:n[c+1].coordinate,p=void 0;if((0,nq.uY)(s-l)!==(0,nq.uY)(f-s)){var h=[];if((0,nq.uY)(f-s)===(0,nq.uY)(u[1]-u[0])){p=f;var d=s+u[1]-u[0];h[0]=Math.min(d,(d+l)/2),h[1]=Math.max(d,(d+l)/2)}else{p=l;var y=f+u[1]-u[0];h[0]=Math.min(s,(y+s)/2),h[1]=Math.max(s,(y+s)/2)}var v=[Math.min(s,(p+s)/2),Math.max(s,(p+s)/2)];if(t>v[0]&&t<=v[1]||t>=h[0]&&t<=h[1]){i=n[c].index;break}}else{var m=Math.min(l,f),b=Math.max(l,f);if(t>(m+s)/2&&t<=(b+s)/2){i=n[c].index;break}}}else for(var g=0;g0&&g(r[g].coordinate+r[g-1].coordinate)/2&&t<=(r[g].coordinate+r[g+1].coordinate)/2||g===a-1&&t>(r[g].coordinate+r[g-1].coordinate)/2){i=r[g].index;break}return i},n1=function(t){var e,r,n=t.type.displayName,o=null!==(e=t.type)&&void 0!==e&&e.defaultProps?nV(nV({},t.type.defaultProps),t.props):t.props,i=o.stroke,a=o.fill;switch(n){case"Line":r=i;break;case"Area":case"Radar":r=i&&"none"!==i?i:a;break;default:r=a}return r},n2=function(t){var e=t.barSize,r=t.totalSize,n=t.stackGroups,o=void 0===n?{}:n;if(!o)return{};for(var i={},a=Object.keys(o),u=0,c=a.length;u=0});if(v&&v.length){var m=v[0].type.defaultProps,b=void 0!==m?nV(nV({},m),v[0].props):v[0].props,g=b.barSize,x=b[y];i[x]||(i[x]=[]);var w=nr()(g)?e:g;i[x].push({item:v[0],stackList:v.slice(1),barSize:nr()(w)?void 0:(0,nq.h1)(w,r,0)})}}return i},n5=function(t){var e,r=t.barGap,n=t.barCategoryGap,o=t.bandSize,i=t.sizeList,a=void 0===i?[]:i,u=t.maxBarSize,c=a.length;if(c<1)return null;var l=(0,nq.h1)(r,o,0,!0),s=[];if(a[0].barSize===+a[0].barSize){var f=!1,p=o/c,h=a.reduce(function(t,e){return t+e.barSize||0},0);(h+=(c-1)*l)>=o&&(h-=(c-1)*l,l=0),h>=o&&p>0&&(f=!0,p*=.9,h=c*p);var d={offset:((o-h)/2>>0)-l,size:0};e=a.reduce(function(t,e){var r={item:e.item,position:{offset:d.offset+d.size+l,size:f?p:e.barSize}},n=[].concat(nH(t),[r]);return d=n[n.length-1].position,e.stackList&&e.stackList.length&&e.stackList.forEach(function(t){n.push({item:t,position:d})}),n},s)}else{var y=(0,nq.h1)(n,o,0,!0);o-2*y-(c-1)*l<=0&&(l=0);var v=(o-2*y-(c-1)*l)/c;v>1&&(v>>=0);var m=u===+u?Math.min(v,u):v;e=a.reduce(function(t,e,r){var n=[].concat(nH(t),[{item:e.item,position:{offset:y+(v+l)*r+(v-m)/2,size:m}}]);return e.stackList&&e.stackList.length&&e.stackList.forEach(function(t){n.push({item:t,position:n[n.length-1].position})}),n},s)}return e},n6=function(t,e,r,n){var o=r.children,i=r.width,a=r.margin,u=i-(a.left||0)-(a.right||0),c=(0,nW.z)({children:o,legendWidth:u});if(c){var l=n||{},s=l.width,f=l.height,p=c.align,h=c.verticalAlign,d=c.layout;if(("vertical"===d||"horizontal"===d&&"middle"===h)&&"center"!==p&&(0,nq.hj)(t[p]))return nV(nV({},t),{},nK({},p,t[p]+(s||0)));if(("horizontal"===d||"vertical"===d&&"center"===p)&&"middle"!==h&&(0,nq.hj)(t[h]))return nV(nV({},t),{},nK({},h,t[h]+(f||0)))}return t},n3=function(t,e,r,n,o){var i=e.props.children,a=(0,nZ.NN)(i,n$.W).filter(function(t){var e;return e=t.props.direction,!!nr()(o)||("horizontal"===n?"yAxis"===o:"vertical"===n||"x"===e?"xAxis"===o:"y"!==e||"yAxis"===o)});if(a&&a.length){var u=a.map(function(t){return t.props.dataKey});return t.reduce(function(t,e){var n=nQ(e,r);if(nr()(n))return t;var o=Array.isArray(n)?[nt()(n),r8()(n)]:[n,n],i=u.reduce(function(t,r){var n=nQ(e,r,0),i=o[0]-Math.abs(Array.isArray(n)?n[0]:n),a=o[1]+Math.abs(Array.isArray(n)?n[1]:n);return[Math.min(i,t[0]),Math.max(a,t[1])]},[1/0,-1/0]);return[Math.min(i[0],t[0]),Math.max(i[1],t[1])]},[1/0,-1/0])}return null},n7=function(t,e,r,n,o){var i=e.map(function(e){return n3(t,e,r,o,n)}).filter(function(t){return!nr()(t)});return i&&i.length?i.reduce(function(t,e){return[Math.min(t[0],e[0]),Math.max(t[1],e[1])]},[1/0,-1/0]):null},n4=function(t,e,r,n,o){var i=e.map(function(e){var i=e.props.dataKey;return"number"===r&&i&&n3(t,e,i,n)||nJ(t,i,r,o)});if("number"===r)return i.reduce(function(t,e){return[Math.min(t[0],e[0]),Math.max(t[1],e[1])]},[1/0,-1/0]);var a={};return i.reduce(function(t,e){for(var r=0,n=e.length;r=2?2*(0,nq.uY)(a[0]-a[1])*c:c,e&&(t.ticks||t.niceTicks))?(t.ticks||t.niceTicks).map(function(t){return{coordinate:n(o?o.indexOf(t):t)+c,value:t,offset:c}}).filter(function(t){return!np()(t.coordinate)}):t.isCategorical&&t.categoricalDomain?t.categoricalDomain.map(function(t,e){return{coordinate:n(t)+c,value:t,index:e,offset:c}}):n.ticks&&!r?n.ticks(t.tickCount).map(function(t){return{coordinate:n(t)+c,value:t,offset:c}}):n.domain().map(function(t,e){return{coordinate:n(t)+c,value:o?o[t]:t,index:e,offset:c}})},oe=new WeakMap,or=function(t,e){if("function"!=typeof e)return t;oe.has(t)||oe.set(t,new WeakMap);var r=oe.get(t);if(r.has(e))return r.get(e);var n=function(){t.apply(void 0,arguments),e.apply(void 0,arguments)};return r.set(e,n),n},on=function(t,e,r){var n=t.scale,o=t.type,i=t.layout,a=t.axisType;if("auto"===n)return"radial"===i&&"radiusAxis"===a?{scale:f.Z(),realScaleType:"band"}:"radial"===i&&"angleAxis"===a?{scale:tL(),realScaleType:"linear"}:"category"===o&&e&&(e.indexOf("LineChart")>=0||e.indexOf("AreaChart")>=0||e.indexOf("ComposedChart")>=0&&!r)?{scale:f.x(),realScaleType:"point"}:"category"===o?{scale:f.Z(),realScaleType:"band"}:{scale:tL(),realScaleType:"linear"};if(na()(n)){var u="scale".concat(nd()(n));return{scale:(s[u]||f.x)(),realScaleType:s[u]?u:"point"}}return no()(n)?{scale:n}:{scale:f.x(),realScaleType:"point"}},oo=function(t){var e=t.domain();if(e&&!(e.length<=2)){var r=e.length,n=t.range(),o=Math.min(n[0],n[1])-1e-4,i=Math.max(n[0],n[1])+1e-4,a=t(e[0]),u=t(e[r-1]);(ai||ui)&&t.domain([e[0],e[r-1]])}},oi=function(t,e){if(!t)return null;for(var r=0,n=t.length;rn)&&(o[1]=n),o[0]>n&&(o[0]=n),o[1]=0?(t[a][r][0]=o,t[a][r][1]=o+u,o=t[a][r][1]):(t[a][r][0]=i,t[a][r][1]=i+u,i=t[a][r][1])}},expand:function(t,e){if((n=t.length)>0){for(var r,n,o,i=0,a=t[0].length;i0){for(var r,n=0,o=t[e[0]],i=o.length;n0&&(n=(r=t[e[0]]).length)>0){for(var r,n,o,i=0,a=1;a=0?(t[i][r][0]=o,t[i][r][1]=o+a,o=t[i][r][1]):(t[i][r][0]=0,t[i][r][1]=0)}}},oc=function(t,e,r){var n=e.map(function(t){return t.props.dataKey}),o=ou[r];return(function(){var t=(0,r5.Z)([]),e=r6,r=r1,n=r3;function o(o){var i,a,u=Array.from(t.apply(this,arguments),r7),c=u.length,l=-1;for(let t of o)for(i=0,++l;i=0?0:o<0?o:n}return r[0]},od=function(t,e){var r,n=(null!==(r=t.type)&&void 0!==r&&r.defaultProps?nV(nV({},t.type.defaultProps),t.props):t.props).stackId;if((0,nq.P2)(n)){var o=e[n];if(o){var i=o.items.indexOf(t);return i>=0?o.stackedData[i]:null}}return null},oy=function(t,e,r){return Object.keys(t).reduce(function(n,o){var i=t[o].stackedData.reduce(function(t,n){var o=n.slice(e,r+1).reduce(function(t,e){return[nt()(e.concat([t[0]]).filter(nq.hj)),r8()(e.concat([t[1]]).filter(nq.hj))]},[1/0,-1/0]);return[Math.min(t[0],o[0]),Math.max(t[1],o[1])]},[1/0,-1/0]);return[Math.min(i[0],n[0]),Math.max(i[1],n[1])]},[1/0,-1/0]).map(function(t){return t===1/0||t===-1/0?0:t})},ov=/^dataMin[\s]*-[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/,om=/^dataMax[\s]*\+[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/,ob=function(t,e,r){if(no()(t))return t(e,r);if(!Array.isArray(t))return e;var n=[];if((0,nq.hj)(t[0]))n[0]=r?t[0]:Math.min(t[0],e[0]);else if(ov.test(t[0])){var o=+ov.exec(t[0])[1];n[0]=e[0]-o}else no()(t[0])?n[0]=t[0](e[0]):n[0]=e[0];if((0,nq.hj)(t[1]))n[1]=r?t[1]:Math.max(t[1],e[1]);else if(om.test(t[1])){var i=+om.exec(t[1])[1];n[1]=e[1]+i}else no()(t[1])?n[1]=t[1](e[1]):n[1]=e[1];return n},og=function(t,e,r){if(t&&t.scale&&t.scale.bandwidth){var n=t.scale.bandwidth();if(!r||n>0)return n}if(t&&e&&e.length>=2){for(var o=nb()(e,function(t){return t.coordinate}),i=1/0,a=1,u=o.length;a1&&void 0!==arguments[1]?arguments[1]:{};if(null==t||n.x.isSsr)return{width:0,height:0};var o=(Object.keys(e=a({},r)).forEach(function(t){e[t]||delete e[t]}),e),i=JSON.stringify({text:t,copyStyle:o});if(u.widthCache[i])return u.widthCache[i];try{var s=document.getElementById(l);s||((s=document.createElement("span")).setAttribute("id",l),s.setAttribute("aria-hidden","true"),document.body.appendChild(s));var f=a(a({},c),o);Object.assign(s.style,f),s.textContent="".concat(t);var p=s.getBoundingClientRect(),h={width:p.width,height:p.height};return u.widthCache[i]=h,++u.cacheCount>2e3&&(u.cacheCount=0,u.widthCache={}),h}catch(t){return{width:0,height:0}}},f=function(t){return{top:t.top+window.scrollY-document.documentElement.clientTop,left:t.left+window.scrollX-document.documentElement.clientLeft}}},16630:function(t,e,r){"use strict";r.d(e,{Ap:function(){return S},EL:function(){return g},Kt:function(){return w},P2:function(){return m},Rw:function(){return v},bv:function(){return O},fC:function(){return P},h1:function(){return x},hU:function(){return d},hj:function(){return y},k4:function(){return j},uY:function(){return h}});var n=r(42715),o=r.n(n),i=r(82559),a=r.n(i),u=r(13735),c=r.n(u),l=r(22345),s=r.n(l),f=r(77571),p=r.n(f),h=function(t){return 0===t?0:t>0?1:-1},d=function(t){return o()(t)&&t.indexOf("%")===t.length-1},y=function(t){return s()(t)&&!a()(t)},v=function(t){return p()(t)},m=function(t){return y(t)||o()(t)},b=0,g=function(t){var e=++b;return"".concat(t||"").concat(e)},x=function(t,e){var r,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(!y(t)&&!o()(t))return n;if(d(t)){var u=t.indexOf("%");r=e*parseFloat(t.slice(0,u))/100}else r=+t;return a()(r)&&(r=n),i&&r>e&&(r=e),r},w=function(t){if(!t)return null;var e=Object.keys(t);return e&&e.length?t[e[0]]:null},O=function(t){if(!Array.isArray(t))return!1;for(var e=t.length,r={},n=0;n2?r-2:0),o=2;ot.length)&&(e=t.length);for(var r=0,n=Array(e);r2&&void 0!==arguments[2]?arguments[2]:{top:0,right:0,bottom:0,left:0};return Math.min(Math.abs(t-(r.left||0)-(r.right||0)),Math.abs(e-(r.top||0)-(r.bottom||0)))/2},b=function(t,e,r,n,i){var a=t.width,u=t.height,s=t.startAngle,f=t.endAngle,y=(0,c.h1)(t.cx,a,a/2),v=(0,c.h1)(t.cy,u,u/2),b=m(a,u,r),g=(0,c.h1)(t.innerRadius,b,0),x=(0,c.h1)(t.outerRadius,b,.8*b);return Object.keys(e).reduce(function(t,r){var a,u=e[r],c=u.domain,m=u.reversed;if(o()(u.range))"angleAxis"===n?a=[s,f]:"radiusAxis"===n&&(a=[g,x]),m&&(a=[a[1],a[0]]);else{var b,w=function(t){if(Array.isArray(t))return t}(b=a=u.range)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,l=!1;try{for(i=(r=r.call(t)).next;!(c=(n=i.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(l)throw o}}return u}}(b,2)||function(t,e){if(t){if("string"==typeof t)return d(t,2);var r=Object.prototype.toString.call(t).slice(8,-1);if("Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return d(t,2)}}(b,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}();s=w[0],f=w[1]}var O=(0,l.Hq)(u,i),j=O.realScaleType,S=O.scale;S.domain(c).range(a),(0,l.zF)(S);var P=(0,l.g$)(S,p(p({},u),{},{realScaleType:j})),E=p(p(p({},u),P),{},{range:a,radius:x,realScaleType:j,scale:S,cx:y,cy:v,innerRadius:g,outerRadius:x,startAngle:s,endAngle:f});return p(p({},t),{},h({},r,E))},{})},g=function(t,e){var r=t.x,n=t.y;return Math.sqrt(Math.pow(r-e.x,2)+Math.pow(n-e.y,2))},x=function(t,e){var r=t.x,n=t.y,o=e.cx,i=e.cy,a=g({x:r,y:n},{x:o,y:i});if(a<=0)return{radius:a};var u=Math.acos((r-o)/a);return n>i&&(u=2*Math.PI-u),{radius:a,angle:180*u/Math.PI,angleInRadian:u}},w=function(t){var e=t.startAngle,r=t.endAngle,n=Math.min(Math.floor(e/360),Math.floor(r/360));return{startAngle:e-360*n,endAngle:r-360*n}},O=function(t,e){var r,n=x({x:t.x,y:t.y},e),o=n.radius,i=n.angle,a=e.innerRadius,u=e.outerRadius;if(ou)return!1;if(0===o)return!0;var c=w(e),l=c.startAngle,s=c.endAngle,f=i;if(l<=s){for(;f>s;)f-=360;for(;f=l&&f<=s}else{for(;f>l;)f-=360;for(;f=s&&f<=l}return r?p(p({},e),{},{radius:o,angle:f+360*Math.min(Math.floor(e.startAngle/360),Math.floor(e.endAngle/360))}):null},j=function(t){return(0,i.isValidElement)(t)||u()(t)||"boolean"==typeof t?"":t.className}},82944:function(t,e,r){"use strict";r.d(e,{$R:function(){return R},Bh:function(){return B},Gf:function(){return j},L6:function(){return N},NN:function(){return k},TT:function(){return M},eu:function(){return L},jf:function(){return T},rL:function(){return D},sP:function(){return A}});var n=r(13735),o=r.n(n),i=r(77571),a=r.n(i),u=r(42715),c=r.n(u),l=r(86757),s=r.n(l),f=r(28302),p=r.n(f),h=r(2265),d=r(14326),y=r(16630),v=r(46485),m=r(41637),b=["children"],g=["children"];function x(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r={};for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){if(e.indexOf(n)>=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0)&&Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function w(t){return(w="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var O={click:"onClick",mousedown:"onMouseDown",mouseup:"onMouseUp",mouseover:"onMouseOver",mousemove:"onMouseMove",mouseout:"onMouseOut",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",touchcancel:"onTouchCancel",touchend:"onTouchEnd",touchmove:"onTouchMove",touchstart:"onTouchStart",contextmenu:"onContextMenu",dblclick:"onDoubleClick"},j=function(t){return"string"==typeof t?t:t?t.displayName||t.name||"Component":""},S=null,P=null,E=function t(e){if(e===S&&Array.isArray(P))return P;var r=[];return h.Children.forEach(e,function(e){a()(e)||((0,d.isFragment)(e)?r=r.concat(t(e.props.children)):r.push(e))}),P=r,S=e,r};function k(t,e){var r=[],n=[];return n=Array.isArray(e)?e.map(function(t){return j(t)}):[j(e)],E(t).forEach(function(t){var e=o()(t,"type.displayName")||o()(t,"type.name");-1!==n.indexOf(e)&&r.push(t)}),r}function A(t,e){var r=k(t,e);return r&&r[0]}var M=function(t){if(!t||!t.props)return!1;var e=t.props,r=e.width,n=e.height;return!!(0,y.hj)(r)&&!(r<=0)&&!!(0,y.hj)(n)&&!(n<=0)},_=["a","altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","ellipse","feBlend","feColormatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-url","foreignObject","g","glyph","glyphRef","hkern","image","line","lineGradient","marker","mask","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","svg","switch","symbol","text","textPath","title","tref","tspan","use","view","vkern"],T=function(t){return t&&"object"===w(t)&&"clipDot"in t},C=function(t,e,r,n){var o,i=null!==(o=null===m.ry||void 0===m.ry?void 0:m.ry[n])&&void 0!==o?o:[];return e.startsWith("data-")||!s()(t)&&(n&&i.includes(e)||m.Yh.includes(e))||r&&m.nv.includes(e)},N=function(t,e,r){if(!t||"function"==typeof t||"boolean"==typeof t)return null;var n=t;if((0,h.isValidElement)(t)&&(n=t.props),!p()(n))return null;var o={};return Object.keys(n).forEach(function(t){var i;C(null===(i=n)||void 0===i?void 0:i[t],t,e,r)&&(o[t]=n[t])}),o},D=function t(e,r){if(e===r)return!0;var n=h.Children.count(e);if(n!==h.Children.count(r))return!1;if(0===n)return!0;if(1===n)return I(Array.isArray(e)?e[0]:e,Array.isArray(r)?r[0]:r);for(var o=0;o=0)r.push(t);else if(t){var i=j(t.type),a=e[i]||{},u=a.handler,l=a.once;if(u&&(!l||!n[i])){var s=u(t,i,o);r.push(s),n[i]=!0}}}),r},B=function(t){var e=t&&t.type;return e&&O[e]?O[e]:null},R=function(t,e){return E(e).indexOf(t)}},46485:function(t,e,r){"use strict";function n(t,e){for(var r in t)if(({}).hasOwnProperty.call(t,r)&&(!({}).hasOwnProperty.call(e,r)||t[r]!==e[r]))return!1;for(var n in e)if(({}).hasOwnProperty.call(e,n)&&!({}).hasOwnProperty.call(t,n))return!1;return!0}r.d(e,{w:function(){return n}})},38569:function(t,e,r){"use strict";r.d(e,{z:function(){return l}});var n=r(22190),o=r(85355),i=r(82944);function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function u(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,n)}return r}function c(t){for(var e=1;e=0))throw Error(`invalid digits: ${t}`);if(e>15)return a;let r=10**e;return function(t){this._+=t[0];for(let e=1,n=t.length;e1e-6){if(Math.abs(f*c-l*s)>1e-6&&i){let h=r-a,d=o-u,y=c*c+l*l,v=Math.sqrt(y),m=Math.sqrt(p),b=i*Math.tan((n-Math.acos((y+p-(h*h+d*d))/(2*v*m)))/2),g=b/m,x=b/v;Math.abs(g-1)>1e-6&&this._append`L${t+g*s},${e+g*f}`,this._append`A${i},${i},0,0,${+(f*h>s*d)},${this._x1=t+x*c},${this._y1=e+x*l}`}else this._append`L${this._x1=t},${this._y1=e}`}}arc(t,e,r,a,u,c){if(t=+t,e=+e,c=!!c,(r=+r)<0)throw Error(`negative radius: ${r}`);let l=r*Math.cos(a),s=r*Math.sin(a),f=t+l,p=e+s,h=1^c,d=c?a-u:u-a;null===this._x1?this._append`M${f},${p}`:(Math.abs(this._x1-f)>1e-6||Math.abs(this._y1-p)>1e-6)&&this._append`L${f},${p}`,r&&(d<0&&(d=d%o+o),d>i?this._append`A${r},${r},0,1,${h},${t-l},${e-s}A${r},${r},0,1,${h},${this._x1=f},${this._y1=p}`:d>1e-6&&this._append`A${r},${r},0,${+(d>=n)},${h},${this._x1=t+r*Math.cos(u)},${this._y1=e+r*Math.sin(u)}`)}rect(t,e,r,n){this._append`M${this._x0=this._x1=+t},${this._y0=this._y1=+e}h${r=+r}v${+n}h${-r}Z`}toString(){return this._}}function c(t){let e=3;return t.digits=function(r){if(!arguments.length)return e;if(null==r)e=null;else{let t=Math.floor(r);if(!(t>=0))throw RangeError(`invalid digits: ${r}`);e=t}return t},()=>new u(e)}u.prototype},59121:function(t,e,r){"use strict";r.d(e,{E:function(){return i}});var n=r(99649),o=r(63497);function i(t,e){let r=(0,n.Q)(t);return isNaN(e)?(0,o.L)(t,NaN):(e&&r.setDate(r.getDate()+e),r)}},31091:function(t,e,r){"use strict";r.d(e,{z:function(){return i}});var n=r(99649),o=r(63497);function i(t,e){let r=(0,n.Q)(t);if(isNaN(e))return(0,o.L)(t,NaN);if(!e)return r;let i=r.getDate(),a=(0,o.L)(t,r.getTime());return(a.setMonth(r.getMonth()+e+1,0),i>=a.getDate())?a:(r.setFullYear(a.getFullYear(),a.getMonth(),i),r)}},63497:function(t,e,r){"use strict";function n(t,e){return t instanceof Date?new t.constructor(e):new Date(e)}r.d(e,{L:function(){return n}})},99649:function(t,e,r){"use strict";function n(t){let e=Object.prototype.toString.call(t);return t instanceof Date||"object"==typeof t&&"[object Date]"===e?new t.constructor(+t):new Date("number"==typeof t||"[object Number]"===e||"string"==typeof t||"[object String]"===e?t:NaN)}r.d(e,{Q:function(){return n}})},69398:function(t,e,r){"use strict";function n(t,e){if(!t)throw Error("Invariant failed")}r.d(e,{Z:function(){return n}})}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1112-8d095bb73a8ed62a.js b/litellm/proxy/_experimental/out/_next/static/chunks/1112-0b9bd4ebde18e77b.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/chunks/1112-8d095bb73a8ed62a.js rename to litellm/proxy/_experimental/out/_next/static/chunks/1112-0b9bd4ebde18e77b.js diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1208-5caf6d9856cc3f13.js b/litellm/proxy/_experimental/out/_next/static/chunks/1208-5caf6d9856cc3f13.js new file mode 100644 index 00000000000..de5590f1965 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/1208-5caf6d9856cc3f13.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1208],{44625:function(t,e,o){o.d(e,{Z:function(){return l}});var r=o(1119),n=o(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M832 64H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32zm-600 72h560v208H232V136zm560 480H232V408h560v208zm0 272H232V680h560v208zM304 240a40 40 0 1080 0 40 40 0 10-80 0zm0 272a40 40 0 1080 0 40 40 0 10-80 0zm0 272a40 40 0 1080 0 40 40 0 10-80 0z"}}]},name:"database",theme:"outlined"},i=o(55015),l=n.forwardRef(function(t,e){return n.createElement(i.Z,(0,r.Z)({},t,{ref:e,icon:a}))})},46783:function(t,e,o){o.d(e,{Z:function(){return l}});var r=o(1119),n=o(2265),a={icon:{tag:"svg",attrs:{viewBox:"0 0 1024 1024",focusable:"false"},children:[{tag:"path",attrs:{d:"M885.2 446.3l-.2-.8-112.2-285.1c-5-16.1-19.9-27.2-36.8-27.2H281.2c-17 0-32.1 11.3-36.9 27.6L139.4 443l-.3.7-.2.8c-1.3 4.9-1.7 9.9-1 14.8-.1 1.6-.2 3.2-.2 4.8V830a60.9 60.9 0 0060.8 60.8h627.2c33.5 0 60.8-27.3 60.9-60.8V464.1c0-1.3 0-2.6-.1-3.7.4-4.9 0-9.6-1.3-14.1zm-295.8-43l-.3 15.7c-.8 44.9-31.8 75.1-77.1 75.1-22.1 0-41.1-7.1-54.8-20.6S436 441.2 435.6 419l-.3-15.7H229.5L309 210h399.2l81.7 193.3H589.4zm-375 76.8h157.3c24.3 57.1 76 90.8 140.4 90.8 33.7 0 65-9.4 90.3-27.2 22.2-15.6 39.5-37.4 50.7-63.6h156.5V814H214.4V480.1z"}}]},name:"inbox",theme:"outlined"},i=o(55015),l=n.forwardRef(function(t,e){return n.createElement(i.Z,(0,r.Z)({},t,{ref:e,icon:a}))})},23907:function(t,e,o){o.d(e,{Z:function(){return l}});var r=o(1119),n=o(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"defs",attrs:{},children:[{tag:"style",attrs:{}}]},{tag:"path",attrs:{d:"M931.4 498.9L94.9 79.5c-3.4-1.7-7.3-2.1-11-1.2a15.99 15.99 0 00-11.7 19.3l86.2 352.2c1.3 5.3 5.2 9.6 10.4 11.3l147.7 50.7-147.6 50.7c-5.2 1.8-9.1 6-10.3 11.3L72.2 926.5c-.9 3.7-.5 7.6 1.2 10.9 3.9 7.9 13.5 11.1 21.5 7.2l836.5-417c3.1-1.5 5.6-4.1 7.2-7.1 3.9-8 .7-17.6-7.2-21.6zM170.8 826.3l50.3-205.6 295.2-101.3c2.3-.8 4.2-2.6 5-5 1.4-4.2-.8-8.7-5-10.2L221.1 403 171 198.2l628 314.9-628.2 313.2z"}}]},name:"send",theme:"outlined"},i=o(55015),l=n.forwardRef(function(t,e){return n.createElement(i.Z,(0,r.Z)({},t,{ref:e,icon:a}))})},47323:function(t,e,o){o.d(e,{Z:function(){return f}});var r=o(5853),n=o(2265),a=o(47187),i=o(7084),l=o(13241),c=o(1153),s=o(26898);let d={xs:{paddingX:"px-1.5",paddingY:"py-1.5"},sm:{paddingX:"px-1.5",paddingY:"py-1.5"},md:{paddingX:"px-2",paddingY:"py-2"},lg:{paddingX:"px-2",paddingY:"py-2"},xl:{paddingX:"px-2.5",paddingY:"py-2.5"}},u={xs:{height:"h-3",width:"w-3"},sm:{height:"h-5",width:"w-5"},md:{height:"h-5",width:"w-5"},lg:{height:"h-7",width:"w-7"},xl:{height:"h-9",width:"w-9"}},m={simple:{rounded:"",border:"",ring:"",shadow:""},light:{rounded:"rounded-tremor-default",border:"",ring:"",shadow:""},shadow:{rounded:"rounded-tremor-default",border:"border",ring:"",shadow:"shadow-tremor-card dark:shadow-dark-tremor-card"},solid:{rounded:"rounded-tremor-default",border:"border-2",ring:"ring-1",shadow:""},outlined:{rounded:"rounded-tremor-default",border:"border",ring:"ring-2",shadow:""}},g=(t,e)=>{switch(t){case"simple":return{textColor:e?(0,c.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:"",borderColor:"",ringColor:""};case"light":return{textColor:e?(0,c.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,l.q)((0,c.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand-muted dark:bg-dark-tremor-brand-muted",borderColor:"",ringColor:""};case"shadow":return{textColor:e?(0,c.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,l.q)((0,c.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:"border-tremor-border dark:border-dark-tremor-border",ringColor:""};case"solid":return{textColor:e?(0,c.bM)(e,s.K.text).textColor:"text-tremor-brand-inverted dark:text-dark-tremor-brand-inverted",bgColor:e?(0,l.q)((0,c.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand dark:bg-dark-tremor-brand",borderColor:"border-tremor-brand-inverted dark:border-dark-tremor-brand-inverted",ringColor:"ring-tremor-ring dark:ring-dark-tremor-ring"};case"outlined":return{textColor:e?(0,c.bM)(e,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,l.q)((0,c.bM)(e,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:e?(0,c.bM)(e,s.K.ring).borderColor:"border-tremor-brand-subtle dark:border-dark-tremor-brand-subtle",ringColor:e?(0,l.q)((0,c.bM)(e,s.K.ring).ringColor,"ring-opacity-40"):"ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted"}}},b=(0,c.fn)("Icon"),f=n.forwardRef((t,e)=>{let{icon:o,variant:s="simple",tooltip:f,size:p=i.u8.SM,color:h,className:v}=t,w=(0,r._T)(t,["icon","variant","tooltip","size","color","className"]),k=g(s,h),{tooltipProps:x,getReferenceProps:C}=(0,a.l)();return n.createElement("span",Object.assign({ref:(0,c.lq)([e,x.refs.setReference]),className:(0,l.q)(b("root"),"inline-flex shrink-0 items-center justify-center",k.bgColor,k.textColor,k.borderColor,k.ringColor,m[s].rounded,m[s].border,m[s].shadow,m[s].ring,d[p].paddingX,d[p].paddingY,v)},C,w),n.createElement(a.Z,Object.assign({text:f},x)),n.createElement(o,{className:(0,l.q)(b("icon"),"shrink-0",u[p].height,u[p].width)}))});f.displayName="Icon"},49804:function(t,e,o){o.d(e,{Z:function(){return s}});var r=o(5853),n=o(13241),a=o(1153),i=o(2265),l=o(9496);let c=(0,a.fn)("Col"),s=i.forwardRef((t,e)=>{let{numColSpan:o=1,numColSpanSm:a,numColSpanMd:s,numColSpanLg:d,children:u,className:m}=t,g=(0,r._T)(t,["numColSpan","numColSpanSm","numColSpanMd","numColSpanLg","children","className"]),b=(t,e)=>t&&Object.keys(e).includes(String(t))?e[t]:"";return i.createElement("div",Object.assign({ref:e,className:(0,n.q)(c("root"),(()=>{let t=b(o,l.PT),e=b(a,l.SP),r=b(s,l.VS),i=b(d,l._w);return(0,n.q)(t,e,r,i)})(),m)},g),u)});s.displayName="Col"},33866:function(t,e,o){o.d(e,{Z:function(){return R}});var r=o(2265),n=o(36760),a=o.n(n),i=o(66632),l=o(93350),c=o(19722),s=o(71744),d=o(93463),u=o(12918),m=o(18536),g=o(71140),b=o(99320);let f=new d.E4("antStatusProcessing",{"0%":{transform:"scale(0.8)",opacity:.5},"100%":{transform:"scale(2.4)",opacity:0}}),p=new d.E4("antZoomBadgeIn",{"0%":{transform:"scale(0) translate(50%, -50%)",opacity:0},"100%":{transform:"scale(1) translate(50%, -50%)"}}),h=new d.E4("antZoomBadgeOut",{"0%":{transform:"scale(1) translate(50%, -50%)"},"100%":{transform:"scale(0) translate(50%, -50%)",opacity:0}}),v=new d.E4("antNoWrapperZoomBadgeIn",{"0%":{transform:"scale(0)",opacity:0},"100%":{transform:"scale(1)"}}),w=new d.E4("antNoWrapperZoomBadgeOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0)",opacity:0}}),k=new d.E4("antBadgeLoadingCircle",{"0%":{transformOrigin:"50%"},"100%":{transform:"translate(50%, -50%) rotate(360deg)",transformOrigin:"50%"}}),x=t=>{let{componentCls:e,iconCls:o,antCls:r,badgeShadowSize:n,textFontSize:a,textFontSizeSM:i,statusSize:l,dotSize:c,textFontWeight:s,indicatorHeight:g,indicatorHeightSM:b,marginXS:x,calc:C}=t,y="".concat(r,"-scroll-number"),O=(0,m.Z)(t,(t,o)=>{let{darkColor:r}=o;return{["&".concat(e," ").concat(e,"-color-").concat(t)]:{background:r,["&:not(".concat(e,"-count)")]:{color:r},"a:hover &":{background:r}}}});return{[e]:Object.assign(Object.assign(Object.assign(Object.assign({},(0,u.Wf)(t)),{position:"relative",display:"inline-block",width:"fit-content",lineHeight:1,["".concat(e,"-count")]:{display:"inline-flex",justifyContent:"center",zIndex:t.indicatorZIndex,minWidth:g,height:g,color:t.badgeTextColor,fontWeight:s,fontSize:a,lineHeight:(0,d.bf)(g),whiteSpace:"nowrap",textAlign:"center",background:t.badgeColor,borderRadius:C(g).div(2).equal(),boxShadow:"0 0 0 ".concat((0,d.bf)(n)," ").concat(t.badgeShadowColor),transition:"background ".concat(t.motionDurationMid),a:{color:t.badgeTextColor},"a:hover":{color:t.badgeTextColor},"a:hover &":{background:t.badgeColorHover}},["".concat(e,"-count-sm")]:{minWidth:b,height:b,fontSize:i,lineHeight:(0,d.bf)(b),borderRadius:C(b).div(2).equal()},["".concat(e,"-multiple-words")]:{padding:"0 ".concat((0,d.bf)(t.paddingXS)),bdi:{unicodeBidi:"plaintext"}},["".concat(e,"-dot")]:{zIndex:t.indicatorZIndex,width:c,minWidth:c,height:c,background:t.badgeColor,borderRadius:"100%",boxShadow:"0 0 0 ".concat((0,d.bf)(n)," ").concat(t.badgeShadowColor)},["".concat(e,"-count, ").concat(e,"-dot, ").concat(y,"-custom-component")]:{position:"absolute",top:0,insetInlineEnd:0,transform:"translate(50%, -50%)",transformOrigin:"100% 0%",["&".concat(o,"-spin")]:{animationName:k,animationDuration:"1s",animationIterationCount:"infinite",animationTimingFunction:"linear"}},["&".concat(e,"-status")]:{lineHeight:"inherit",verticalAlign:"baseline",["".concat(e,"-status-dot")]:{position:"relative",top:-1,display:"inline-block",width:l,height:l,verticalAlign:"middle",borderRadius:"50%"},["".concat(e,"-status-success")]:{backgroundColor:t.colorSuccess},["".concat(e,"-status-processing")]:{overflow:"visible",color:t.colorInfo,backgroundColor:t.colorInfo,borderColor:"currentcolor","&::after":{position:"absolute",top:0,insetInlineStart:0,width:"100%",height:"100%",borderWidth:n,borderStyle:"solid",borderColor:"inherit",borderRadius:"50%",animationName:f,animationDuration:t.badgeProcessingDuration,animationIterationCount:"infinite",animationTimingFunction:"ease-in-out",content:'""'}},["".concat(e,"-status-default")]:{backgroundColor:t.colorTextPlaceholder},["".concat(e,"-status-error")]:{backgroundColor:t.colorError},["".concat(e,"-status-warning")]:{backgroundColor:t.colorWarning},["".concat(e,"-status-text")]:{marginInlineStart:x,color:t.colorText,fontSize:t.fontSize}}}),O),{["".concat(e,"-zoom-appear, ").concat(e,"-zoom-enter")]:{animationName:p,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack,animationFillMode:"both"},["".concat(e,"-zoom-leave")]:{animationName:h,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack,animationFillMode:"both"},["&".concat(e,"-not-a-wrapper")]:{["".concat(e,"-zoom-appear, ").concat(e,"-zoom-enter")]:{animationName:v,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack},["".concat(e,"-zoom-leave")]:{animationName:w,animationDuration:t.motionDurationSlow,animationTimingFunction:t.motionEaseOutBack},["&:not(".concat(e,"-status)")]:{verticalAlign:"middle"},["".concat(y,"-custom-component, ").concat(e,"-count")]:{transform:"none"},["".concat(y,"-custom-component, ").concat(y)]:{position:"relative",top:"auto",display:"block",transformOrigin:"50% 50%"}},[y]:{overflow:"hidden",transition:"all ".concat(t.motionDurationMid," ").concat(t.motionEaseOutBack),["".concat(y,"-only")]:{position:"relative",display:"inline-block",height:g,transition:"all ".concat(t.motionDurationSlow," ").concat(t.motionEaseOutBack),WebkitTransformStyle:"preserve-3d",WebkitBackfaceVisibility:"hidden",["> p".concat(y,"-only-unit")]:{height:g,margin:0,WebkitTransformStyle:"preserve-3d",WebkitBackfaceVisibility:"hidden"}},["".concat(y,"-symbol")]:{verticalAlign:"top"}},"&-rtl":{direction:"rtl",["".concat(e,"-count, ").concat(e,"-dot, ").concat(y,"-custom-component")]:{transform:"translate(-50%, -50%)"}}})}},C=t=>{let{fontHeight:e,lineWidth:o,marginXS:r,colorBorderBg:n}=t,a=t.colorTextLightSolid,i=t.colorError,l=t.colorErrorHover;return(0,g.IX)(t,{badgeFontHeight:e,badgeShadowSize:o,badgeTextColor:a,badgeColor:i,badgeColorHover:l,badgeShadowColor:n,badgeProcessingDuration:"1.2s",badgeRibbonOffset:r,badgeRibbonCornerTransform:"scaleY(0.75)",badgeRibbonCornerFilter:"brightness(75%)"})},y=t=>{let{fontSize:e,lineHeight:o,fontSizeSM:r,lineWidth:n}=t;return{indicatorZIndex:"auto",indicatorHeight:Math.round(e*o)-2*n,indicatorHeightSM:e,dotSize:r/2,textFontSize:r,textFontSizeSM:r,textFontWeight:"normal",statusSize:r/2}};var O=(0,b.I$)("Badge",t=>x(C(t)),y);let j=t=>{let{antCls:e,badgeFontHeight:o,marginXS:r,badgeRibbonOffset:n,calc:a}=t,i="".concat(e,"-ribbon"),l=(0,m.Z)(t,(t,e)=>{let{darkColor:o}=e;return{["&".concat(i,"-color-").concat(t)]:{background:o,color:o}}});return{["".concat(e,"-ribbon-wrapper")]:{position:"relative"},[i]:Object.assign(Object.assign(Object.assign(Object.assign({},(0,u.Wf)(t)),{position:"absolute",top:r,padding:"0 ".concat((0,d.bf)(t.paddingXS)),color:t.colorPrimary,lineHeight:(0,d.bf)(o),whiteSpace:"nowrap",backgroundColor:t.colorPrimary,borderRadius:t.borderRadiusSM,["".concat(i,"-text")]:{color:t.badgeTextColor},["".concat(i,"-corner")]:{position:"absolute",top:"100%",width:n,height:n,color:"currentcolor",border:"".concat((0,d.bf)(a(n).div(2).equal())," solid"),transform:t.badgeRibbonCornerTransform,transformOrigin:"top",filter:t.badgeRibbonCornerFilter}}),l),{["&".concat(i,"-placement-end")]:{insetInlineEnd:a(n).mul(-1).equal(),borderEndEndRadius:0,["".concat(i,"-corner")]:{insetInlineEnd:0,borderInlineEndColor:"transparent",borderBlockEndColor:"transparent"}},["&".concat(i,"-placement-start")]:{insetInlineStart:a(n).mul(-1).equal(),borderEndStartRadius:0,["".concat(i,"-corner")]:{insetInlineStart:0,borderBlockEndColor:"transparent",borderInlineStartColor:"transparent"}},"&-rtl":{direction:"rtl"}})}};var S=(0,b.I$)(["Badge","Ribbon"],t=>j(C(t)),y);let E=t=>{let e;let{prefixCls:o,value:n,current:i,offset:l=0}=t;return l&&(e={position:"absolute",top:"".concat(l,"00%"),left:0}),r.createElement("span",{style:e,className:a()("".concat(o,"-only-unit"),{current:i})},n)};var N=t=>{let e,o;let{prefixCls:n,count:a,value:i}=t,l=Number(i),c=Math.abs(a),[s,d]=r.useState(l),[u,m]=r.useState(c),g=()=>{d(l),m(c)};if(r.useEffect(()=>{let t=setTimeout(g,1e3);return()=>clearTimeout(t)},[l]),s===l||Number.isNaN(l)||Number.isNaN(s))e=[r.createElement(E,Object.assign({},t,{key:l,current:!0}))],o={transition:"none"};else{e=[];let n=l+10,a=[];for(let t=l;t<=n;t+=1)a.push(t);let i=ut%10===s);e=(i<0?a.slice(0,d+1):a.slice(d)).map((e,o)=>r.createElement(E,Object.assign({},t,{key:e,value:e%10,offset:i<0?o-d:o,current:o===d}))),o={transform:"translateY(".concat(-function(t,e,o){let r=t,n=0;for(;(r+10)%10!==e;)r+=o,n+=o;return n}(s,l,i),"00%)")}}return r.createElement("span",{className:"".concat(n,"-only"),style:o,onTransitionEnd:g},e)},M=function(t,e){var o={};for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&0>e.indexOf(r)&&(o[r]=t[r]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(t);ne.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(t,r[n])&&(o[r[n]]=t[r[n]]);return o};let z=r.forwardRef((t,e)=>{let{prefixCls:o,count:n,className:i,motionClassName:l,style:d,title:u,show:m,component:g="sup",children:b}=t,f=M(t,["prefixCls","count","className","motionClassName","style","title","show","component","children"]),{getPrefixCls:p}=r.useContext(s.E_),h=p("scroll-number",o),v=Object.assign(Object.assign({},f),{"data-show":m,style:d,className:a()(h,i,l),title:u}),w=n;if(n&&Number(n)%1==0){let t=String(n).split("");w=r.createElement("bdi",null,t.map((e,o)=>r.createElement(N,{prefixCls:h,count:Number(n),value:e,key:t.length-o})))}return((null==d?void 0:d.borderColor)&&(v.style=Object.assign(Object.assign({},d),{boxShadow:"0 0 0 1px ".concat(d.borderColor," inset")})),b)?(0,c.Tm)(b,t=>({className:a()("".concat(h,"-custom-component"),null==t?void 0:t.className,l)})):r.createElement(g,Object.assign({},v,{ref:e}),w)});var B=function(t,e){var o={};for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&0>e.indexOf(r)&&(o[r]=t[r]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(t);ne.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(t,r[n])&&(o[r[n]]=t[r[n]]);return o};let Z=r.forwardRef((t,e)=>{var o,n,d,u,m;let{prefixCls:g,scrollNumberPrefixCls:b,children:f,status:p,text:h,color:v,count:w=null,overflowCount:k=99,dot:x=!1,size:C="default",title:y,offset:j,style:S,className:E,rootClassName:N,classNames:M,styles:Z,showZero:R=!1}=t,L=B(t,["prefixCls","scrollNumberPrefixCls","children","status","text","color","count","overflowCount","dot","size","title","offset","style","className","rootClassName","classNames","styles","showZero"]),{getPrefixCls:T,direction:I,badge:H}=r.useContext(s.E_),P=T("badge",g),[W,D,F]=O(P),q=w>k?"".concat(k,"+"):w,A="0"===q||0===q||"0"===h||0===h,X=null===w||A&&!R,_=(null!=p||null!=v)&&X,V=null!=p||!A,K=x&&!A,Y=K?"":q,G=(0,r.useMemo)(()=>((null==Y||""===Y)&&(null==h||""===h)||A&&!R)&&!K,[Y,A,R,K,h]),Q=(0,r.useRef)(w);G||(Q.current=w);let $=Q.current,J=(0,r.useRef)(Y);G||(J.current=Y);let U=J.current,tt=(0,r.useRef)(K);G||(tt.current=K);let te=(0,r.useMemo)(()=>{if(!j)return Object.assign(Object.assign({},null==H?void 0:H.style),S);let t={marginTop:j[1]};return"rtl"===I?t.left=Number.parseInt(j[0],10):t.right=-Number.parseInt(j[0],10),Object.assign(Object.assign(Object.assign({},t),null==H?void 0:H.style),S)},[I,j,S,null==H?void 0:H.style]),to=null!=y?y:"string"==typeof $||"number"==typeof $?$:void 0,tr=!G&&(0===h?R:!!h&&!0!==h),tn=tr?r.createElement("span",{className:"".concat(P,"-status-text")},h):null,ta=$&&"object"==typeof $?(0,c.Tm)($,t=>({style:Object.assign(Object.assign({},te),t.style)})):void 0,ti=(0,l.o2)(v,!1),tl=a()(null==M?void 0:M.indicator,null===(o=null==H?void 0:H.classNames)||void 0===o?void 0:o.indicator,{["".concat(P,"-status-dot")]:_,["".concat(P,"-status-").concat(p)]:!!p,["".concat(P,"-color-").concat(v)]:ti}),tc={};v&&!ti&&(tc.color=v,tc.background=v);let ts=a()(P,{["".concat(P,"-status")]:_,["".concat(P,"-not-a-wrapper")]:!f,["".concat(P,"-rtl")]:"rtl"===I},E,N,null==H?void 0:H.className,null===(n=null==H?void 0:H.classNames)||void 0===n?void 0:n.root,null==M?void 0:M.root,D,F);if(!f&&_&&(h||V||!X)){let t=te.color;return W(r.createElement("span",Object.assign({},L,{className:ts,style:Object.assign(Object.assign(Object.assign({},null==Z?void 0:Z.root),null===(d=null==H?void 0:H.styles)||void 0===d?void 0:d.root),te)}),r.createElement("span",{className:tl,style:Object.assign(Object.assign(Object.assign({},null==Z?void 0:Z.indicator),null===(u=null==H?void 0:H.styles)||void 0===u?void 0:u.indicator),tc)}),tr&&r.createElement("span",{style:{color:t},className:"".concat(P,"-status-text")},h)))}return W(r.createElement("span",Object.assign({ref:e},L,{className:ts,style:Object.assign(Object.assign({},null===(m=null==H?void 0:H.styles)||void 0===m?void 0:m.root),null==Z?void 0:Z.root)}),f,r.createElement(i.ZP,{visible:!G,motionName:"".concat(P,"-zoom"),motionAppear:!1,motionDeadline:1e3},t=>{var e,o;let{className:n}=t,i=T("scroll-number",b),l=tt.current,c=a()(null==M?void 0:M.indicator,null===(e=null==H?void 0:H.classNames)||void 0===e?void 0:e.indicator,{["".concat(P,"-dot")]:l,["".concat(P,"-count")]:!l,["".concat(P,"-count-sm")]:"small"===C,["".concat(P,"-multiple-words")]:!l&&U&&U.toString().length>1,["".concat(P,"-status-").concat(p)]:!!p,["".concat(P,"-color-").concat(v)]:ti}),s=Object.assign(Object.assign(Object.assign({},null==Z?void 0:Z.indicator),null===(o=null==H?void 0:H.styles)||void 0===o?void 0:o.indicator),te);return v&&!ti&&((s=s||{}).background=v),r.createElement(z,{prefixCls:i,show:!G,motionClassName:n,className:c,count:U,title:to,style:s,key:"scrollNumber"},ta)}),tn))});Z.Ribbon=t=>{let{className:e,prefixCls:o,style:n,color:i,children:c,text:d,placement:u="end",rootClassName:m}=t,{getPrefixCls:g,direction:b}=r.useContext(s.E_),f=g("ribbon",o),p="".concat(f,"-wrapper"),[h,v,w]=S(f,p),k=(0,l.o2)(i,!1),x=a()(f,"".concat(f,"-placement-").concat(u),{["".concat(f,"-rtl")]:"rtl"===b,["".concat(f,"-color-").concat(i)]:k},e),C={},y={};return i&&!k&&(C.background=i,y.color=i),h(r.createElement("div",{className:a()(p,m,v,w)},c,r.createElement("div",{className:a()(x,v),style:Object.assign(Object.assign({},C),n)},r.createElement("span",{className:"".concat(f,"-text")},d),r.createElement("div",{className:"".concat(f,"-corner"),style:y}))))};var R=Z},2651:function(t,e,o){o.d(e,{Z:function(){return w}});var r=o(93463),n=o(11938),a=o(70774),i=o(73602),l=o(91691),c=o(25119),s=o(37628),d=o(32417),u=o(4877),m=o(57943),g=o(12789),b=o(54558);let f=(t,e)=>new b.t(t).setA(e).toRgbString(),p=(t,e)=>new b.t(t).lighten(e).toHexString(),h=t=>{let e=(0,m.R_)(t,{theme:"dark"});return{1:e[0],2:e[1],3:e[2],4:e[3],5:e[6],6:e[5],7:e[4],8:e[6],9:e[5],10:e[4]}},v=(t,e)=>{let o=t||"#000",r=e||"#fff";return{colorBgBase:o,colorTextBase:r,colorText:f(r,.85),colorTextSecondary:f(r,.65),colorTextTertiary:f(r,.45),colorTextQuaternary:f(r,.25),colorFill:f(r,.18),colorFillSecondary:f(r,.12),colorFillTertiary:f(r,.08),colorFillQuaternary:f(r,.04),colorBgSolid:f(r,.95),colorBgSolidHover:f(r,1),colorBgSolidActive:f(r,.9),colorBgElevated:p(o,12),colorBgContainer:p(o,8),colorBgLayout:p(o,0),colorBgSpotlight:p(o,26),colorBgBlur:f(r,.04),colorBorder:p(o,26),colorBorderSecondary:p(o,19)}};var w={defaultSeed:c.u_.token,useToken:function(){let[t,e,o]=(0,l.ZP)();return{theme:t,token:e,hashId:o}},defaultAlgorithm:s.Z,darkAlgorithm:(t,e)=>{let o=Object.keys(a.M).map(e=>{let o=(0,m.R_)(t[e],{theme:"dark"});return Array.from({length:10},()=>1).reduce((t,r,n)=>(t["".concat(e,"-").concat(n+1)]=o[n],t["".concat(e).concat(n+1)]=o[n],t),{})}).reduce((t,e)=>t=Object.assign(Object.assign({},t),e),{}),r=null!=e?e:(0,s.Z)(t),n=(0,g.Z)(t,{generateColorPalettes:h,generateNeutralColorPalettes:v});return Object.assign(Object.assign(Object.assign(Object.assign({},r),o),n),{colorPrimaryBg:n.colorPrimaryBorder,colorPrimaryBgHover:n.colorPrimaryBorderHover})},compactAlgorithm:(t,e)=>{let o=null!=e?e:(0,s.Z)(t),r=o.fontSizeSM,n=o.controlHeight-4;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},o),function(t){let{sizeUnit:e,sizeStep:o}=t,r=o-2;return{sizeXXL:e*(r+10),sizeXL:e*(r+6),sizeLG:e*(r+2),sizeMD:e*(r+2),sizeMS:e*(r+1),size:e*r,sizeSM:e*r,sizeXS:e*(r-1),sizeXXS:e*(r-1)}}(null!=e?e:t)),(0,u.Z)(r)),{controlHeight:n}),(0,d.Z)(Object.assign(Object.assign({},o),{controlHeight:n})))},getDesignToken:t=>{let e=(null==t?void 0:t.algorithm)?(0,r.jG)(t.algorithm):n.Z,o=Object.assign(Object.assign({},a.Z),null==t?void 0:t.token);return(0,r.t2)(o,{override:null==t?void 0:t.token},e,i.Z)},defaultConfig:c.u_,_internalContext:c.Mj}},10900:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10 19l-7-7m0 0l7-7m-7 7h18"}))});e.Z=n},86462:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"}))});e.Z=n},44633:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 15l7-7 7 7"}))});e.Z=n},3477:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"}))});e.Z=n},53410:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"}))});e.Z=n},91126:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"}),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M21 12a9 9 0 11-18 0 9 9 0 0118 0z"}))});e.Z=n},23628:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"}))});e.Z=n},49084:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"}))});e.Z=n},74998:function(t,e,o){var r=o(2265);let n=r.forwardRef(function(t,e){return r.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},t),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"}))});e.Z=n}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1567-872f98a963ad6892.js b/litellm/proxy/_experimental/out/_next/static/chunks/1567-872f98a963ad6892.js deleted file mode 100644 index 8d4d2674db1..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/1567-872f98a963ad6892.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1567],{83669:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"}},{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}}]},name:"check-circle",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},62670:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372zm47.7-395.2l-25.4-5.9V348.6c38 5.2 61.5 29 65.5 58.2.5 4 3.9 6.9 7.9 6.9h44.9c4.7 0 8.4-4.1 8-8.8-6.1-62.3-57.4-102.3-125.9-109.2V263c0-4.4-3.6-8-8-8h-28.1c-4.4 0-8 3.6-8 8v33c-70.8 6.9-126.2 46-126.2 119 0 67.6 49.8 100.2 102.1 112.7l24.7 6.3v142.7c-44.2-5.9-69-29.5-74.1-61.3-.6-3.8-4-6.6-7.9-6.6H363c-4.7 0-8.4 4-8 8.7 4.5 55 46.2 105.6 135.2 112.1V761c0 4.4 3.6 8 8 8h28.4c4.4 0 8-3.6 8-8.1l-.2-31.7c78.3-6.9 134.3-48.8 134.3-124-.1-69.4-44.2-100.4-109-116.4zm-68.6-16.2c-5.6-1.6-10.3-3.1-15-5-33.8-12.2-49.5-31.9-49.5-57.3 0-36.3 27.5-57 64.5-61.7v124zM534.3 677V543.3c3.1.9 5.9 1.6 8.8 2.2 47.3 14.4 63.2 34.4 63.2 65.1 0 39.1-29.4 62.6-72 66.4z"}}]},name:"dollar",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},29271:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}},{tag:"path",attrs:{d:"M464 688a48 48 0 1096 0 48 48 0 10-96 0zm24-112h48c4.4 0 8-3.6 8-8V296c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8z"}}]},name:"exclamation-circle",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},45246:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M696 480H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"}},{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}}]},name:"minus-circle",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},89245:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M909.1 209.3l-56.4 44.1C775.8 155.1 656.2 92 521.9 92 290 92 102.3 279.5 102 511.5 101.7 743.7 289.8 932 521.9 932c181.3 0 335.8-115 394.6-276.1 1.5-4.2-.7-8.9-4.9-10.3l-56.7-19.5a8 8 0 00-10.1 4.8c-1.8 5-3.8 10-5.9 14.9-17.3 41-42.1 77.8-73.7 109.4A344.77 344.77 0 01655.9 829c-42.3 17.9-87.4 27-133.8 27-46.5 0-91.5-9.1-133.8-27A341.5 341.5 0 01279 755.2a342.16 342.16 0 01-73.7-109.4c-17.9-42.4-27-87.4-27-133.9s9.1-91.5 27-133.9c17.3-41 42.1-77.8 73.7-109.4 31.6-31.6 68.4-56.4 109.3-73.8 42.3-17.9 87.4-27 133.8-27 46.5 0 91.5 9.1 133.8 27a341.5 341.5 0 01109.3 73.8c9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47a8 8 0 003 14.1l175.6 43c5 1.2 9.9-2.6 9.9-7.7l.8-180.9c-.1-6.6-7.8-10.3-13-6.2z"}}]},name:"reload",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},77565:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"}}]},name:"right",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},69993:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M300 328a60 60 0 10120 0 60 60 0 10-120 0zM852 64H172c-17.7 0-32 14.3-32 32v660c0 17.7 14.3 32 32 32h680c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32zm-32 660H204V128h616v596zM604 328a60 60 0 10120 0 60 60 0 10-120 0zm250.2 556H169.8c-16.5 0-29.8 14.3-29.8 32v36c0 4.4 3.3 8 7.4 8h729.1c4.1 0 7.4-3.6 7.4-8v-36c.1-17.7-13.2-32-29.7-32zM664 508H360c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h304c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"}}]},name:"robot",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},58630:function(e,t,r){r.d(t,{Z:function(){return l}});var n=r(1119),o=r(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M876.6 239.5c-.5-.9-1.2-1.8-2-2.5-5-5-13.1-5-18.1 0L684.2 409.3l-67.9-67.9L788.7 169c.8-.8 1.4-1.6 2-2.5 3.6-6.1 1.6-13.9-4.5-17.5-98.2-58-226.8-44.7-311.3 39.7-67 67-89.2 162-66.5 247.4l-293 293c-3 3-2.8 7.9.3 11l169.7 169.7c3.1 3.1 8.1 3.3 11 .3l292.9-292.9c85.5 22.8 180.5.7 247.6-66.4 84.4-84.5 97.7-213.1 39.7-311.3zM786 499.8c-58.1 58.1-145.3 69.3-214.6 33.6l-8.8 8.8-.1-.1-274 274.1-79.2-79.2 230.1-230.1s0 .1.1.1l52.8-52.8c-35.7-69.3-24.5-156.5 33.6-214.6a184.2 184.2 0 01144-53.5L537 318.9a32.05 32.05 0 000 45.3l124.5 124.5a32.05 32.05 0 0045.3 0l132.8-132.8c3.7 51.8-14.4 104.8-53.6 143.9z"}}]},name:"tool",theme:"outlined"},c=r(55015),l=o.forwardRef(function(e,t){return o.createElement(c.Z,(0,n.Z)({},e,{ref:t,icon:a}))})},47323:function(e,t,r){r.d(t,{Z:function(){return f}});var n=r(5853),o=r(2265),a=r(47187),c=r(7084),l=r(13241),i=r(1153),s=r(26898);let d={xs:{paddingX:"px-1.5",paddingY:"py-1.5"},sm:{paddingX:"px-1.5",paddingY:"py-1.5"},md:{paddingX:"px-2",paddingY:"py-2"},lg:{paddingX:"px-2",paddingY:"py-2"},xl:{paddingX:"px-2.5",paddingY:"py-2.5"}},u={xs:{height:"h-3",width:"w-3"},sm:{height:"h-5",width:"w-5"},md:{height:"h-5",width:"w-5"},lg:{height:"h-7",width:"w-7"},xl:{height:"h-9",width:"w-9"}},p={simple:{rounded:"",border:"",ring:"",shadow:""},light:{rounded:"rounded-tremor-default",border:"",ring:"",shadow:""},shadow:{rounded:"rounded-tremor-default",border:"border",ring:"",shadow:"shadow-tremor-card dark:shadow-dark-tremor-card"},solid:{rounded:"rounded-tremor-default",border:"border-2",ring:"ring-1",shadow:""},outlined:{rounded:"rounded-tremor-default",border:"border",ring:"ring-2",shadow:""}},m=(e,t)=>{switch(e){case"simple":return{textColor:t?(0,i.bM)(t,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:"",borderColor:"",ringColor:""};case"light":return{textColor:t?(0,i.bM)(t,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:t?(0,l.q)((0,i.bM)(t,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand-muted dark:bg-dark-tremor-brand-muted",borderColor:"",ringColor:""};case"shadow":return{textColor:t?(0,i.bM)(t,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:t?(0,l.q)((0,i.bM)(t,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:"border-tremor-border dark:border-dark-tremor-border",ringColor:""};case"solid":return{textColor:t?(0,i.bM)(t,s.K.text).textColor:"text-tremor-brand-inverted dark:text-dark-tremor-brand-inverted",bgColor:t?(0,l.q)((0,i.bM)(t,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand dark:bg-dark-tremor-brand",borderColor:"border-tremor-brand-inverted dark:border-dark-tremor-brand-inverted",ringColor:"ring-tremor-ring dark:ring-dark-tremor-ring"};case"outlined":return{textColor:t?(0,i.bM)(t,s.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:t?(0,l.q)((0,i.bM)(t,s.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:t?(0,i.bM)(t,s.K.ring).borderColor:"border-tremor-brand-subtle dark:border-dark-tremor-brand-subtle",ringColor:t?(0,l.q)((0,i.bM)(t,s.K.ring).ringColor,"ring-opacity-40"):"ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted"}}},g=(0,i.fn)("Icon"),f=o.forwardRef((e,t)=>{let{icon:r,variant:s="simple",tooltip:f,size:h=c.u8.SM,color:b,className:v}=e,y=(0,n._T)(e,["icon","variant","tooltip","size","color","className"]),x=m(s,b),{tooltipProps:k,getReferenceProps:w}=(0,a.l)();return o.createElement("span",Object.assign({ref:(0,i.lq)([t,k.refs.setReference]),className:(0,l.q)(g("root"),"inline-flex shrink-0 items-center justify-center",x.bgColor,x.textColor,x.borderColor,x.ringColor,p[s].rounded,p[s].border,p[s].shadow,p[s].ring,d[h].paddingX,d[h].paddingY,v)},w,y),o.createElement(a.Z,Object.assign({text:f},k)),o.createElement(r,{className:(0,l.q)(g("icon"),"shrink-0",u[h].height,u[h].width)}))});f.displayName="Icon"},67101:function(e,t,r){r.d(t,{Z:function(){return d}});var n=r(5853),o=r(13241),a=r(1153),c=r(2265),l=r(9496);let i=(0,a.fn)("Grid"),s=(e,t)=>e&&Object.keys(t).includes(String(e))?t[e]:"",d=c.forwardRef((e,t)=>{let{numItems:r=1,numItemsSm:a,numItemsMd:d,numItemsLg:u,children:p,className:m}=e,g=(0,n._T)(e,["numItems","numItemsSm","numItemsMd","numItemsLg","children","className"]),f=s(r,l._m),h=s(a,l.LH),b=s(d,l.l5),v=s(u,l.N4),y=(0,o.q)(f,h,b,v);return c.createElement("div",Object.assign({ref:t,className:(0,o.q)(i("root"),"grid",y,m)},g),p)});d.displayName="Grid"},9496:function(e,t,r){r.d(t,{LH:function(){return o},N4:function(){return c},PT:function(){return l},SP:function(){return i},VS:function(){return s},_m:function(){return n},_w:function(){return d},l5:function(){return a}});let n={0:"grid-cols-none",1:"grid-cols-1",2:"grid-cols-2",3:"grid-cols-3",4:"grid-cols-4",5:"grid-cols-5",6:"grid-cols-6",7:"grid-cols-7",8:"grid-cols-8",9:"grid-cols-9",10:"grid-cols-10",11:"grid-cols-11",12:"grid-cols-12"},o={0:"sm:grid-cols-none",1:"sm:grid-cols-1",2:"sm:grid-cols-2",3:"sm:grid-cols-3",4:"sm:grid-cols-4",5:"sm:grid-cols-5",6:"sm:grid-cols-6",7:"sm:grid-cols-7",8:"sm:grid-cols-8",9:"sm:grid-cols-9",10:"sm:grid-cols-10",11:"sm:grid-cols-11",12:"sm:grid-cols-12"},a={0:"md:grid-cols-none",1:"md:grid-cols-1",2:"md:grid-cols-2",3:"md:grid-cols-3",4:"md:grid-cols-4",5:"md:grid-cols-5",6:"md:grid-cols-6",7:"md:grid-cols-7",8:"md:grid-cols-8",9:"md:grid-cols-9",10:"md:grid-cols-10",11:"md:grid-cols-11",12:"md:grid-cols-12"},c={0:"lg:grid-cols-none",1:"lg:grid-cols-1",2:"lg:grid-cols-2",3:"lg:grid-cols-3",4:"lg:grid-cols-4",5:"lg:grid-cols-5",6:"lg:grid-cols-6",7:"lg:grid-cols-7",8:"lg:grid-cols-8",9:"lg:grid-cols-9",10:"lg:grid-cols-10",11:"lg:grid-cols-11",12:"lg:grid-cols-12"},l={1:"col-span-1",2:"col-span-2",3:"col-span-3",4:"col-span-4",5:"col-span-5",6:"col-span-6",7:"col-span-7",8:"col-span-8",9:"col-span-9",10:"col-span-10",11:"col-span-11",12:"col-span-12",13:"col-span-13"},i={1:"sm:col-span-1",2:"sm:col-span-2",3:"sm:col-span-3",4:"sm:col-span-4",5:"sm:col-span-5",6:"sm:col-span-6",7:"sm:col-span-7",8:"sm:col-span-8",9:"sm:col-span-9",10:"sm:col-span-10",11:"sm:col-span-11",12:"sm:col-span-12",13:"sm:col-span-13"},s={1:"md:col-span-1",2:"md:col-span-2",3:"md:col-span-3",4:"md:col-span-4",5:"md:col-span-5",6:"md:col-span-6",7:"md:col-span-7",8:"md:col-span-8",9:"md:col-span-9",10:"md:col-span-10",11:"md:col-span-11",12:"md:col-span-12",13:"md:col-span-13"},d={1:"lg:col-span-1",2:"lg:col-span-2",3:"lg:col-span-3",4:"lg:col-span-4",5:"lg:col-span-5",6:"lg:col-span-6",7:"lg:col-span-7",8:"lg:col-span-8",9:"lg:col-span-9",10:"lg:col-span-10",11:"lg:col-span-11",12:"lg:col-span-12",13:"lg:col-span-13"}},96761:function(e,t,r){r.d(t,{Z:function(){return i}});var n=r(5853),o=r(26898),a=r(13241),c=r(1153),l=r(2265);let i=l.forwardRef((e,t)=>{let{color:r,children:i,className:s}=e,d=(0,n._T)(e,["color","children","className"]);return l.createElement("p",Object.assign({ref:t,className:(0,a.q)("font-medium text-tremor-title",r?(0,c.bM)(r,o.K.darkText).textColor:"text-tremor-content-strong dark:text-dark-tremor-content-strong",s)},d),i)});i.displayName="Title"},44851:function(e,t,r){r.d(t,{default:function(){return _}});var n=r(2265),o=r(77565),a=r(36760),c=r.n(a),l=r(1119),i=r(83145),s=r(26365),d=r(41154),u=r(50506),p=r(32559),m=r(6989),g=r(45287),f=r(31686),h=r(11993),b=r(66632),v=r(95814),y=n.forwardRef(function(e,t){var r=e.prefixCls,o=e.forceRender,a=e.className,l=e.style,i=e.children,d=e.isActive,u=e.role,p=e.classNames,m=e.styles,g=n.useState(d||o),f=(0,s.Z)(g,2),b=f[0],v=f[1];return(n.useEffect(function(){(o||d)&&v(!0)},[o,d]),b)?n.createElement("div",{ref:t,className:c()("".concat(r,"-content"),(0,h.Z)((0,h.Z)({},"".concat(r,"-content-active"),d),"".concat(r,"-content-inactive"),!d),a),style:l,role:u},n.createElement("div",{className:c()("".concat(r,"-content-box"),null==p?void 0:p.body),style:null==m?void 0:m.body},i)):null});y.displayName="PanelContent";var x=["showArrow","headerClass","isActive","onItemClick","forceRender","className","classNames","styles","prefixCls","collapsible","accordion","panelKey","extra","header","expandIcon","openMotion","destroyInactivePanel","children"],k=n.forwardRef(function(e,t){var r=e.showArrow,o=e.headerClass,a=e.isActive,i=e.onItemClick,s=e.forceRender,d=e.className,u=e.classNames,p=void 0===u?{}:u,g=e.styles,k=void 0===g?{}:g,w=e.prefixCls,C=e.collapsible,Z=e.accordion,M=e.panelKey,E=e.extra,O=e.header,I=e.expandIcon,N=e.openMotion,S=e.destroyInactivePanel,R=e.children,j=(0,m.Z)(e,x),z="disabled"===C,L=(0,h.Z)((0,h.Z)((0,h.Z)({onClick:function(){null==i||i(M)},onKeyDown:function(e){("Enter"===e.key||e.keyCode===v.Z.ENTER||e.which===v.Z.ENTER)&&(null==i||i(M))},role:Z?"tab":"button"},"aria-expanded",a),"aria-disabled",z),"tabIndex",z?-1:0),P="function"==typeof I?I(e):n.createElement("i",{className:"arrow"}),A=P&&n.createElement("div",(0,l.Z)({className:"".concat(w,"-expand-icon")},["header","icon"].includes(C)?L:{}),P),K=c()("".concat(w,"-item"),(0,h.Z)((0,h.Z)({},"".concat(w,"-item-active"),a),"".concat(w,"-item-disabled"),z),d),B=c()(o,"".concat(w,"-header"),(0,h.Z)({},"".concat(w,"-collapsible-").concat(C),!!C),p.header),G=(0,f.Z)({className:B,style:k.header},["header","icon"].includes(C)?{}:L);return n.createElement("div",(0,l.Z)({},j,{ref:t,className:K}),n.createElement("div",G,(void 0===r||r)&&A,n.createElement("span",(0,l.Z)({className:"".concat(w,"-header-text")},"header"===C?L:{}),O),null!=E&&"boolean"!=typeof E&&n.createElement("div",{className:"".concat(w,"-extra")},E)),n.createElement(b.ZP,(0,l.Z)({visible:a,leavedClassName:"".concat(w,"-content-hidden")},N,{forceRender:s,removeOnLeave:S}),function(e,t){var r=e.className,o=e.style;return n.createElement(y,{ref:t,prefixCls:w,className:r,classNames:p,style:o,styles:k,isActive:a,forceRender:s,role:Z?"tabpanel":void 0},R)}))}),w=["children","label","key","collapsible","onItemClick","destroyInactivePanel"],C=function(e,t){var r=t.prefixCls,o=t.accordion,a=t.collapsible,c=t.destroyInactivePanel,i=t.onItemClick,s=t.activeKey,d=t.openMotion,u=t.expandIcon;return e.map(function(e,t){var p=e.children,g=e.label,f=e.key,h=e.collapsible,b=e.onItemClick,v=e.destroyInactivePanel,y=(0,m.Z)(e,w),x=String(null!=f?f:t),C=null!=h?h:a,Z=!1;return Z=o?s[0]===x:s.indexOf(x)>-1,n.createElement(k,(0,l.Z)({},y,{prefixCls:r,key:x,panelKey:x,isActive:Z,accordion:o,openMotion:d,expandIcon:u,header:g,collapsible:C,onItemClick:function(e){"disabled"!==C&&(i(e),null==b||b(e))},destroyInactivePanel:null!=v?v:c}),p)})},Z=function(e,t,r){if(!e)return null;var o=r.prefixCls,a=r.accordion,c=r.collapsible,l=r.destroyInactivePanel,i=r.onItemClick,s=r.activeKey,d=r.openMotion,u=r.expandIcon,p=e.key||String(t),m=e.props,g=m.header,f=m.headerClass,h=m.destroyInactivePanel,b=m.collapsible,v=m.onItemClick,y=!1;y=a?s[0]===p:s.indexOf(p)>-1;var x=null!=b?b:c,k={key:p,panelKey:p,header:g,headerClass:f,isActive:y,prefixCls:o,destroyInactivePanel:null!=h?h:l,openMotion:d,accordion:a,children:e.props.children,onItemClick:function(e){"disabled"!==x&&(i(e),null==v||v(e))},expandIcon:u,collapsible:x};return"string"==typeof e.type?e:(Object.keys(k).forEach(function(e){void 0===k[e]&&delete k[e]}),n.cloneElement(e,k))},M=r(18242);function E(e){var t=e;if(!Array.isArray(t)){var r=(0,d.Z)(t);t="number"===r||"string"===r?[t]:[]}return t.map(function(e){return String(e)})}var O=Object.assign(n.forwardRef(function(e,t){var r,o=e.prefixCls,a=void 0===o?"rc-collapse":o,d=e.destroyInactivePanel,m=e.style,f=e.accordion,h=e.className,b=e.children,v=e.collapsible,y=e.openMotion,x=e.expandIcon,k=e.activeKey,w=e.defaultActiveKey,O=e.onChange,I=e.items,N=c()(a,h),S=(0,u.Z)([],{value:k,onChange:function(e){return null==O?void 0:O(e)},defaultValue:w,postState:E}),R=(0,s.Z)(S,2),j=R[0],z=R[1];(0,p.ZP)(!b,"[rc-collapse] `children` will be removed in next major version. Please use `items` instead.");var L=(r={prefixCls:a,accordion:f,openMotion:y,expandIcon:x,collapsible:v,destroyInactivePanel:void 0!==d&&d,onItemClick:function(e){return z(function(){return f?j[0]===e?[]:[e]:j.indexOf(e)>-1?j.filter(function(t){return t!==e}):[].concat((0,i.Z)(j),[e])})},activeKey:j},Array.isArray(I)?C(I,r):(0,g.Z)(b).map(function(e,t){return Z(e,t,r)}));return n.createElement("div",(0,l.Z)({ref:t,className:N,style:m,role:f?"tablist":void 0},(0,M.Z)(e,{aria:!0,data:!0})),L)}),{Panel:k});O.Panel;var I=r(18694),N=r(68710),S=r(19722),R=r(71744),j=r(33759);let z=n.forwardRef((e,t)=>{let{getPrefixCls:r}=n.useContext(R.E_),{prefixCls:o,className:a,showArrow:l=!0}=e,i=r("collapse",o),s=c()({["".concat(i,"-no-arrow")]:!l},a);return n.createElement(O.Panel,Object.assign({ref:t},e,{prefixCls:i,className:s}))});var L=r(93463),P=r(12918),A=r(63074),K=r(99320),B=r(71140);let G=e=>{let{componentCls:t,contentBg:r,padding:n,headerBg:o,headerPadding:a,collapseHeaderPaddingSM:c,collapseHeaderPaddingLG:l,collapsePanelBorderRadius:i,lineWidth:s,lineType:d,colorBorder:u,colorText:p,colorTextHeading:m,colorTextDisabled:g,fontSizeLG:f,lineHeight:h,lineHeightLG:b,marginSM:v,paddingSM:y,paddingLG:x,paddingXS:k,motionDurationSlow:w,fontSizeIcon:C,contentPadding:Z,fontHeight:M,fontHeightLG:E}=e,O="".concat((0,L.bf)(s)," ").concat(d," ").concat(u);return{[t]:Object.assign(Object.assign({},(0,P.Wf)(e)),{backgroundColor:o,border:O,borderRadius:i,"&-rtl":{direction:"rtl"},["& > ".concat(t,"-item")]:{borderBottom:O,"&:first-child":{["\n &,\n & > ".concat(t,"-header")]:{borderRadius:"".concat((0,L.bf)(i)," ").concat((0,L.bf)(i)," 0 0")}},"&:last-child":{["\n &,\n & > ".concat(t,"-header")]:{borderRadius:"0 0 ".concat((0,L.bf)(i)," ").concat((0,L.bf)(i))}},["> ".concat(t,"-header")]:Object.assign(Object.assign({position:"relative",display:"flex",flexWrap:"nowrap",alignItems:"flex-start",padding:a,color:m,lineHeight:h,cursor:"pointer",transition:"all ".concat(w,", visibility 0s")},(0,P.Qy)(e)),{["> ".concat(t,"-header-text")]:{flex:"auto"},["".concat(t,"-expand-icon")]:{height:M,display:"flex",alignItems:"center",paddingInlineEnd:v},["".concat(t,"-arrow")]:Object.assign(Object.assign({},(0,P.Ro)()),{fontSize:C,transition:"transform ".concat(w),svg:{transition:"transform ".concat(w)}}),["".concat(t,"-header-text")]:{marginInlineEnd:"auto"}}),["".concat(t,"-collapsible-header")]:{cursor:"default",["".concat(t,"-header-text")]:{flex:"none",cursor:"pointer"},["".concat(t,"-expand-icon")]:{cursor:"pointer"}},["".concat(t,"-collapsible-icon")]:{cursor:"unset",["".concat(t,"-expand-icon")]:{cursor:"pointer"}}},["".concat(t,"-content")]:{color:p,backgroundColor:r,borderTop:O,["& > ".concat(t,"-content-box")]:{padding:Z},"&-hidden":{display:"none"}},"&-small":{["> ".concat(t,"-item")]:{["> ".concat(t,"-header")]:{padding:c,paddingInlineStart:k,["> ".concat(t,"-expand-icon")]:{marginInlineStart:e.calc(y).sub(k).equal()}},["> ".concat(t,"-content > ").concat(t,"-content-box")]:{padding:y}}},"&-large":{["> ".concat(t,"-item")]:{fontSize:f,lineHeight:b,["> ".concat(t,"-header")]:{padding:l,paddingInlineStart:n,["> ".concat(t,"-expand-icon")]:{height:E,marginInlineStart:e.calc(x).sub(n).equal()}},["> ".concat(t,"-content > ").concat(t,"-content-box")]:{padding:x}}},["".concat(t,"-item:last-child")]:{borderBottom:0,["> ".concat(t,"-content")]:{borderRadius:"0 0 ".concat((0,L.bf)(i)," ").concat((0,L.bf)(i))}},["& ".concat(t,"-item-disabled > ").concat(t,"-header")]:{"\n &,\n & > .arrow\n ":{color:g,cursor:"not-allowed"}},["&".concat(t,"-icon-position-end")]:{["& > ".concat(t,"-item")]:{["> ".concat(t,"-header")]:{["".concat(t,"-expand-icon")]:{order:1,paddingInlineEnd:0,paddingInlineStart:v}}}}})}},q=e=>{let{componentCls:t}=e,r="> ".concat(t,"-item > ").concat(t,"-header ").concat(t,"-arrow");return{["".concat(t,"-rtl")]:{[r]:{transform:"rotate(180deg)"}}}},H=e=>{let{componentCls:t,headerBg:r,borderlessContentPadding:n,borderlessContentBg:o,colorBorder:a}=e;return{["".concat(t,"-borderless")]:{backgroundColor:r,border:0,["> ".concat(t,"-item")]:{borderBottom:"1px solid ".concat(a)},["\n > ".concat(t,"-item:last-child,\n > ").concat(t,"-item:last-child ").concat(t,"-header\n ")]:{borderRadius:0},["> ".concat(t,"-item:last-child")]:{borderBottom:0},["> ".concat(t,"-item > ").concat(t,"-content")]:{backgroundColor:o,borderTop:0},["> ".concat(t,"-item > ").concat(t,"-content > ").concat(t,"-content-box")]:{padding:n}}}},V=e=>{let{componentCls:t,paddingSM:r}=e;return{["".concat(t,"-ghost")]:{backgroundColor:"transparent",border:0,["> ".concat(t,"-item")]:{borderBottom:0,["> ".concat(t,"-content")]:{backgroundColor:"transparent",border:0,["> ".concat(t,"-content-box")]:{paddingBlock:r}}}}}};var T=(0,K.I$)("Collapse",e=>{let t=(0,B.IX)(e,{collapseHeaderPaddingSM:"".concat((0,L.bf)(e.paddingXS)," ").concat((0,L.bf)(e.paddingSM)),collapseHeaderPaddingLG:"".concat((0,L.bf)(e.padding)," ").concat((0,L.bf)(e.paddingLG)),collapsePanelBorderRadius:e.borderRadiusLG});return[G(t),H(t),V(t),q(t),(0,A.Z)(t)]},e=>({headerPadding:"".concat(e.paddingSM,"px ").concat(e.padding,"px"),headerBg:e.colorFillAlter,contentPadding:"".concat(e.padding,"px 16px"),contentBg:e.colorBgContainer,borderlessContentPadding:"".concat(e.paddingXXS,"px 16px ").concat(e.padding,"px"),borderlessContentBg:"transparent"})),_=Object.assign(n.forwardRef((e,t)=>{let{getPrefixCls:r,direction:a,expandIcon:l,className:i,style:s}=(0,R.dj)("collapse"),{prefixCls:d,className:u,rootClassName:p,style:m,bordered:f=!0,ghost:h,size:b,expandIconPosition:v="start",children:y,destroyInactivePanel:x,destroyOnHidden:k,expandIcon:w}=e,C=(0,j.Z)(e=>{var t;return null!==(t=null!=b?b:e)&&void 0!==t?t:"middle"}),Z=r("collapse",d),M=r(),[E,z,L]=T(Z),P=n.useMemo(()=>"left"===v?"start":"right"===v?"end":v,[v]),A=null!=w?w:l,K=n.useCallback(function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t="function"==typeof A?A(e):n.createElement(o.Z,{rotate:e.isActive?"rtl"===a?-90:90:void 0,"aria-label":e.isActive?"expanded":"collapsed"});return(0,S.Tm)(t,()=>{var e;return{className:c()(null===(e=t.props)||void 0===e?void 0:e.className,"".concat(Z,"-arrow"))}})},[A,Z,a]),B=c()("".concat(Z,"-icon-position-").concat(P),{["".concat(Z,"-borderless")]:!f,["".concat(Z,"-rtl")]:"rtl"===a,["".concat(Z,"-ghost")]:!!h,["".concat(Z,"-").concat(C)]:"middle"!==C},i,u,p,z,L),G=n.useMemo(()=>Object.assign(Object.assign({},(0,N.Z)(M)),{motionAppear:!1,leavedClassName:"".concat(Z,"-content-hidden")}),[M,Z]),q=n.useMemo(()=>y?(0,g.Z)(y).map((e,t)=>{var r,n;let o=e.props;if(null==o?void 0:o.disabled){let a=null!==(r=e.key)&&void 0!==r?r:String(t),c=Object.assign(Object.assign({},(0,I.Z)(e.props,["disabled"])),{key:a,collapsible:null!==(n=o.collapsible)&&void 0!==n?n:"disabled"});return(0,S.Tm)(e,c)}return e}):null,[y]);return E(n.createElement(O,Object.assign({ref:t,openMotion:G},(0,I.Z)(e,["rootClassName"]),{expandIcon:K,prefixCls:Z,className:B,style:Object.assign(Object.assign({},s),m),destroyInactivePanel:null!=k?k:x}),q))}),{Panel:z})},58760:function(e,t,r){r.d(t,{Z:function(){return E}});var n=r(2265),o=r(36760),a=r.n(o),c=r(45287);function l(e){return["small","middle","large"].includes(e)}function i(e){return!!e&&"number"==typeof e&&!Number.isNaN(e)}var s=r(71744),d=r(77685),u=r(17691),p=r(99320);let m=e=>{let{componentCls:t,borderRadius:r,paddingSM:n,colorBorder:o,paddingXS:a,fontSizeLG:c,fontSizeSM:l,borderRadiusLG:i,borderRadiusSM:s,colorBgContainerDisabled:d,lineWidth:p}=e;return{[t]:[{display:"inline-flex",alignItems:"center",gap:0,paddingInline:n,margin:0,background:d,borderWidth:p,borderStyle:"solid",borderColor:o,borderRadius:r,"&-large":{fontSize:c,borderRadius:i},"&-small":{paddingInline:a,borderRadius:s,fontSize:l},"&-compact-last-item":{borderEndStartRadius:0,borderStartStartRadius:0},"&-compact-first-item":{borderEndEndRadius:0,borderStartEndRadius:0},"&-compact-item:not(:first-child):not(:last-child)":{borderRadius:0},"&-compact-item:not(:last-child)":{borderInlineEndWidth:0}},(0,u.c)(e,{focus:!1})]}};var g=(0,p.I$)(["Space","Addon"],e=>[m(e)]),f=function(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&0>t.indexOf(n)&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(e);ot.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]]);return r};let h=n.forwardRef((e,t)=>{let{className:r,children:o,style:c,prefixCls:l}=e,i=f(e,["className","children","style","prefixCls"]),{getPrefixCls:u,direction:p}=n.useContext(s.E_),m=u("space-addon",l),[h,b,v]=g(m),{compactItemClassnames:y,compactSize:x}=(0,d.ri)(m,p),k=a()(m,b,y,v,{["".concat(m,"-").concat(x)]:x},r);return h(n.createElement("div",Object.assign({ref:t,className:k,style:c},i),o))}),b=n.createContext({latestIndex:0}),v=b.Provider;var y=e=>{let{className:t,index:r,children:o,split:a,style:c}=e,{latestIndex:l}=n.useContext(b);return null==o?null:n.createElement(n.Fragment,null,n.createElement("div",{className:t,style:c},o),r{let{componentCls:t,antCls:r}=e;return{[t]:{display:"inline-flex","&-rtl":{direction:"rtl"},"&-vertical":{flexDirection:"column"},"&-align":{flexDirection:"column","&-center":{alignItems:"center"},"&-start":{alignItems:"flex-start"},"&-end":{alignItems:"flex-end"},"&-baseline":{alignItems:"baseline"}},["".concat(t,"-item:empty")]:{display:"none"},["".concat(t,"-item > ").concat(r,"-badge-not-a-wrapper:only-child")]:{display:"block"}}}},w=e=>{let{componentCls:t}=e;return{[t]:{"&-gap-row-small":{rowGap:e.spaceGapSmallSize},"&-gap-row-middle":{rowGap:e.spaceGapMiddleSize},"&-gap-row-large":{rowGap:e.spaceGapLargeSize},"&-gap-col-small":{columnGap:e.spaceGapSmallSize},"&-gap-col-middle":{columnGap:e.spaceGapMiddleSize},"&-gap-col-large":{columnGap:e.spaceGapLargeSize}}}};var C=(0,p.I$)("Space",e=>{let t=(0,x.IX)(e,{spaceGapSmallSize:e.paddingXS,spaceGapMiddleSize:e.padding,spaceGapLargeSize:e.paddingLG});return[k(t),w(t)]},()=>({}),{resetStyle:!1}),Z=function(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&0>t.indexOf(n)&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(e);ot.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]]);return r};let M=n.forwardRef((e,t)=>{var r;let{getPrefixCls:o,direction:d,size:u,className:p,style:m,classNames:g,styles:f}=(0,s.dj)("space"),{size:h=null!=u?u:"small",align:b,className:x,rootClassName:k,children:w,direction:M="horizontal",prefixCls:E,split:O,style:I,wrap:N=!1,classNames:S,styles:R}=e,j=Z(e,["size","align","className","rootClassName","children","direction","prefixCls","split","style","wrap","classNames","styles"]),[z,L]=Array.isArray(h)?h:[h,h],P=l(L),A=l(z),K=i(L),B=i(z),G=(0,c.Z)(w,{keepEmpty:!0}),q=void 0===b&&"horizontal"===M?"center":b,H=o("space",E),[V,T,_]=C(H),W=a()(H,p,T,"".concat(H,"-").concat(M),{["".concat(H,"-rtl")]:"rtl"===d,["".concat(H,"-align-").concat(q)]:q,["".concat(H,"-gap-row-").concat(L)]:P,["".concat(H,"-gap-col-").concat(z)]:A},x,k,_),X=a()("".concat(H,"-item"),null!==(r=null==S?void 0:S.item)&&void 0!==r?r:g.item),Y=Object.assign(Object.assign({},f.item),null==R?void 0:R.item),U=G.map((e,t)=>{let r=(null==e?void 0:e.key)||"".concat(X,"-").concat(t);return n.createElement(y,{className:X,key:r,index:t,split:O,style:Y},e)}),$=n.useMemo(()=>({latestIndex:G.reduce((e,t,r)=>null!=t?r:e,0)}),[G]);if(0===G.length)return null;let D={};return N&&(D.flexWrap="wrap"),!A&&B&&(D.columnGap=z),!P&&K&&(D.rowGap=L),V(n.createElement("div",Object.assign({ref:t,className:W,style:Object.assign(Object.assign(Object.assign({},D),m),I)},j),n.createElement(v,{value:$},U)))});M.Compact=d.ZP,M.Addon=h;var E=M},79205:function(e,t,r){r.d(t,{Z:function(){return u}});var n=r(2265);let o=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),a=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,r)=>r?r.toUpperCase():t.toLowerCase()),c=e=>{let t=a(e);return t.charAt(0).toUpperCase()+t.slice(1)},l=function(){for(var e=arguments.length,t=Array(e),r=0;r!!e&&""!==e.trim()&&r.indexOf(e)===t).join(" ").trim()},i=e=>{for(let t in e)if(t.startsWith("aria-")||"role"===t||"title"===t)return!0};var s={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let d=(0,n.forwardRef)((e,t)=>{let{color:r="currentColor",size:o=24,strokeWidth:a=2,absoluteStrokeWidth:c,className:d="",children:u,iconNode:p,...m}=e;return(0,n.createElement)("svg",{ref:t,...s,width:o,height:o,stroke:r,strokeWidth:c?24*Number(a)/Number(o):a,className:l("lucide",d),...!u&&!i(m)&&{"aria-hidden":"true"},...m},[...p.map(e=>{let[t,r]=e;return(0,n.createElement)(t,r)}),...Array.isArray(u)?u:[u]])}),u=(e,t)=>{let r=(0,n.forwardRef)((r,a)=>{let{className:i,...s}=r;return(0,n.createElement)(d,{ref:a,iconNode:t,className:l("lucide-".concat(o(c(e))),"lucide-".concat(e),i),...s})});return r.displayName=c(e),r}},30401:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]])},64935:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("code",[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]])},78867:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]])},96362:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("external-link",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]])},29202:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("globe",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]])},54001:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("key",[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]])},96137:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("server",[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2",key:"ngkwjq"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2",key:"iecqi9"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6",key:"16zg32"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18",key:"nzw8ys"}]])},80221:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("terminal",[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]])},11239:function(e,t,r){r.d(t,{Z:function(){return n}});let n=(0,r(79205).Z)("zap",[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]])},71437:function(e,t,r){var n=r(2265);let o=n.forwardRef(function(e,t){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:t},e),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"}),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"}))});t.Z=o},82376:function(e,t,r){var n=r(2265);let o=n.forwardRef(function(e,t){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:t},e),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"}))});t.Z=o},53410:function(e,t,r){var n=r(2265);let o=n.forwardRef(function(e,t){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:t},e),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"}))});t.Z=o},74998:function(e,t,r){var n=r(2265);let o=n.forwardRef(function(e,t){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:t},e),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"}))});t.Z=o},21770:function(e,t,r){r.d(t,{D:function(){return d}});var n=r(2265),o=r(2894),a=r(18238),c=r(24112),l=r(45345),i=class extends c.l{#e;#t=void 0;#r;#n;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#o()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),(0,l.VS)(this.options,t)||this.#e.getMutationCache().notify({type:"observerOptionsUpdated",mutation:this.#r,observer:this}),t?.mutationKey&&this.options.mutationKey&&(0,l.Ym)(t.mutationKey)!==(0,l.Ym)(this.options.mutationKey)?this.reset():this.#r?.state.status==="pending"&&this.#r.setOptions(this.options)}onUnsubscribe(){this.hasListeners()||this.#r?.removeObserver(this)}onMutationUpdate(e){this.#o(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#r?.removeObserver(this),this.#r=void 0,this.#o(),this.#a()}mutate(e,t){return this.#n=t,this.#r?.removeObserver(this),this.#r=this.#e.getMutationCache().build(this.#e,this.options),this.#r.addObserver(this),this.#r.execute(e)}#o(){let e=this.#r?.state??(0,o.R)();this.#t={...e,isPending:"pending"===e.status,isSuccess:"success"===e.status,isError:"error"===e.status,isIdle:"idle"===e.status,mutate:this.mutate,reset:this.reset}}#a(e){a.Vr.batch(()=>{if(this.#n&&this.hasListeners()){let t=this.#t.variables,r=this.#t.context,n={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};e?.type==="success"?(this.#n.onSuccess?.(e.data,t,r,n),this.#n.onSettled?.(e.data,null,t,r,n)):e?.type==="error"&&(this.#n.onError?.(e.error,t,r,n),this.#n.onSettled?.(void 0,e.error,t,r,n))}this.listeners.forEach(e=>{e(this.#t)})})}},s=r(29827);function d(e,t){let r=(0,s.NL)(t),[o]=n.useState(()=>new i(r,e));n.useEffect(()=>{o.setOptions(e)},[o,e]);let c=n.useSyncExternalStore(n.useCallback(e=>o.subscribe(a.Vr.batchCalls(e)),[o]),()=>o.getCurrentResult(),()=>o.getCurrentResult()),d=n.useCallback((e,t)=>{o.mutate(e,t).catch(l.ZT)},[o]);if(c.error&&(0,l.L3)(o.options.throwOnError,[c.error]))throw c.error;return{...c,mutate:d,mutateAsync:c.mutate}}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1572-d039561b5597b5d5.js b/litellm/proxy/_experimental/out/_next/static/chunks/1572-d039561b5597b5d5.js deleted file mode 100644 index ba6b168e2bc..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/1572-d039561b5597b5d5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1572],{44625:function(r,e,t){t.d(e,{Z:function(){return d}});var n=t(1119),o=t(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M832 64H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32zm-600 72h560v208H232V136zm560 480H232V408h560v208zm0 272H232V680h560v208zM304 240a40 40 0 1080 0 40 40 0 10-80 0zm0 272a40 40 0 1080 0 40 40 0 10-80 0zm0 272a40 40 0 1080 0 40 40 0 10-80 0z"}}]},name:"database",theme:"outlined"},i=t(55015),d=o.forwardRef(function(r,e){return o.createElement(i.Z,(0,n.Z)({},r,{ref:e,icon:a}))})},77565:function(r,e,t){t.d(e,{Z:function(){return d}});var n=t(1119),o=t(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"}}]},name:"right",theme:"outlined"},i=t(55015),d=o.forwardRef(function(r,e){return o.createElement(i.Z,(0,n.Z)({},r,{ref:e,icon:a}))})},23907:function(r,e,t){t.d(e,{Z:function(){return d}});var n=t(1119),o=t(2265),a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"defs",attrs:{},children:[{tag:"style",attrs:{}}]},{tag:"path",attrs:{d:"M931.4 498.9L94.9 79.5c-3.4-1.7-7.3-2.1-11-1.2a15.99 15.99 0 00-11.7 19.3l86.2 352.2c1.3 5.3 5.2 9.6 10.4 11.3l147.7 50.7-147.6 50.7c-5.2 1.8-9.1 6-10.3 11.3L72.2 926.5c-.9 3.7-.5 7.6 1.2 10.9 3.9 7.9 13.5 11.1 21.5 7.2l836.5-417c3.1-1.5 5.6-4.1 7.2-7.1 3.9-8 .7-17.6-7.2-21.6zM170.8 826.3l50.3-205.6 295.2-101.3c2.3-.8 4.2-2.6 5-5 1.4-4.2-.8-8.7-5-10.2L221.1 403 171 198.2l628 314.9-628.2 313.2z"}}]},name:"send",theme:"outlined"},i=t(55015),d=o.forwardRef(function(r,e){return o.createElement(i.Z,(0,n.Z)({},r,{ref:e,icon:a}))})},41649:function(r,e,t){t.d(e,{Z:function(){return u}});var n=t(5853),o=t(2265),a=t(47187),i=t(7084),d=t(26898),l=t(13241),c=t(1153);let s={xs:{paddingX:"px-2",paddingY:"py-0.5",fontSize:"text-xs"},sm:{paddingX:"px-2.5",paddingY:"py-0.5",fontSize:"text-sm"},md:{paddingX:"px-3",paddingY:"py-0.5",fontSize:"text-md"},lg:{paddingX:"px-3.5",paddingY:"py-0.5",fontSize:"text-lg"},xl:{paddingX:"px-4",paddingY:"py-1",fontSize:"text-xl"}},g={xs:{height:"h-4",width:"w-4"},sm:{height:"h-4",width:"w-4"},md:{height:"h-4",width:"w-4"},lg:{height:"h-5",width:"w-5"},xl:{height:"h-6",width:"w-6"}},m=(0,c.fn)("Badge"),u=o.forwardRef((r,e)=>{let{color:t,icon:u,size:p=i.u8.SM,tooltip:f,className:h,children:b}=r,w=(0,n._T)(r,["color","icon","size","tooltip","className","children"]),x=u||null,{tooltipProps:k,getReferenceProps:v}=(0,a.l)();return o.createElement("span",Object.assign({ref:(0,c.lq)([e,k.refs.setReference]),className:(0,l.q)(m("root"),"w-max shrink-0 inline-flex justify-center items-center cursor-default rounded-tremor-small ring-1 ring-inset",t?(0,l.q)((0,c.bM)(t,d.K.background).bgColor,(0,c.bM)(t,d.K.iconText).textColor,(0,c.bM)(t,d.K.iconRing).ringColor,"bg-opacity-10 ring-opacity-20","dark:bg-opacity-5 dark:ring-opacity-60"):(0,l.q)("bg-tremor-brand-faint text-tremor-brand-emphasis ring-tremor-brand/20","dark:bg-dark-tremor-brand-muted/50 dark:text-dark-tremor-brand dark:ring-dark-tremor-subtle/20"),s[p].paddingX,s[p].paddingY,s[p].fontSize,h)},v,w),o.createElement(a.Z,Object.assign({text:f},k)),x?o.createElement(x,{className:(0,l.q)(m("icon"),"shrink-0 -ml-1 mr-1.5",g[p].height,g[p].width)}):null,o.createElement("span",{className:(0,l.q)(m("text"),"whitespace-nowrap")},b))});u.displayName="Badge"},47323:function(r,e,t){t.d(e,{Z:function(){return f}});var n=t(5853),o=t(2265),a=t(47187),i=t(7084),d=t(13241),l=t(1153),c=t(26898);let s={xs:{paddingX:"px-1.5",paddingY:"py-1.5"},sm:{paddingX:"px-1.5",paddingY:"py-1.5"},md:{paddingX:"px-2",paddingY:"py-2"},lg:{paddingX:"px-2",paddingY:"py-2"},xl:{paddingX:"px-2.5",paddingY:"py-2.5"}},g={xs:{height:"h-3",width:"w-3"},sm:{height:"h-5",width:"w-5"},md:{height:"h-5",width:"w-5"},lg:{height:"h-7",width:"w-7"},xl:{height:"h-9",width:"w-9"}},m={simple:{rounded:"",border:"",ring:"",shadow:""},light:{rounded:"rounded-tremor-default",border:"",ring:"",shadow:""},shadow:{rounded:"rounded-tremor-default",border:"border",ring:"",shadow:"shadow-tremor-card dark:shadow-dark-tremor-card"},solid:{rounded:"rounded-tremor-default",border:"border-2",ring:"ring-1",shadow:""},outlined:{rounded:"rounded-tremor-default",border:"border",ring:"ring-2",shadow:""}},u=(r,e)=>{switch(r){case"simple":return{textColor:e?(0,l.bM)(e,c.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:"",borderColor:"",ringColor:""};case"light":return{textColor:e?(0,l.bM)(e,c.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,d.q)((0,l.bM)(e,c.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand-muted dark:bg-dark-tremor-brand-muted",borderColor:"",ringColor:""};case"shadow":return{textColor:e?(0,l.bM)(e,c.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,d.q)((0,l.bM)(e,c.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:"border-tremor-border dark:border-dark-tremor-border",ringColor:""};case"solid":return{textColor:e?(0,l.bM)(e,c.K.text).textColor:"text-tremor-brand-inverted dark:text-dark-tremor-brand-inverted",bgColor:e?(0,d.q)((0,l.bM)(e,c.K.background).bgColor,"bg-opacity-20"):"bg-tremor-brand dark:bg-dark-tremor-brand",borderColor:"border-tremor-brand-inverted dark:border-dark-tremor-brand-inverted",ringColor:"ring-tremor-ring dark:ring-dark-tremor-ring"};case"outlined":return{textColor:e?(0,l.bM)(e,c.K.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:e?(0,d.q)((0,l.bM)(e,c.K.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:e?(0,l.bM)(e,c.K.ring).borderColor:"border-tremor-brand-subtle dark:border-dark-tremor-brand-subtle",ringColor:e?(0,d.q)((0,l.bM)(e,c.K.ring).ringColor,"ring-opacity-40"):"ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted"}}},p=(0,l.fn)("Icon"),f=o.forwardRef((r,e)=>{let{icon:t,variant:c="simple",tooltip:f,size:h=i.u8.SM,color:b,className:w}=r,x=(0,n._T)(r,["icon","variant","tooltip","size","color","className"]),k=u(c,b),{tooltipProps:v,getReferenceProps:C}=(0,a.l)();return o.createElement("span",Object.assign({ref:(0,l.lq)([e,v.refs.setReference]),className:(0,d.q)(p("root"),"inline-flex shrink-0 items-center justify-center",k.bgColor,k.textColor,k.borderColor,k.ringColor,m[c].rounded,m[c].border,m[c].shadow,m[c].ring,s[h].paddingX,s[h].paddingY,w)},C,x),o.createElement(a.Z,Object.assign({text:f},v)),o.createElement(t,{className:(0,d.q)(p("icon"),"shrink-0",g[h].height,g[h].width)}))});f.displayName="Icon"},49804:function(r,e,t){t.d(e,{Z:function(){return c}});var n=t(5853),o=t(13241),a=t(1153),i=t(2265),d=t(9496);let l=(0,a.fn)("Col"),c=i.forwardRef((r,e)=>{let{numColSpan:t=1,numColSpanSm:a,numColSpanMd:c,numColSpanLg:s,children:g,className:m}=r,u=(0,n._T)(r,["numColSpan","numColSpanSm","numColSpanMd","numColSpanLg","children","className"]),p=(r,e)=>r&&Object.keys(e).includes(String(r))?e[r]:"";return i.createElement("div",Object.assign({ref:e,className:(0,o.q)(l("root"),(()=>{let r=p(t,d.PT),e=p(a,d.SP),n=p(c,d.VS),i=p(s,d._w);return(0,o.q)(r,e,n,i)})(),m)},u),g)});c.displayName="Col"},67101:function(r,e,t){t.d(e,{Z:function(){return s}});var n=t(5853),o=t(13241),a=t(1153),i=t(2265),d=t(9496);let l=(0,a.fn)("Grid"),c=(r,e)=>r&&Object.keys(e).includes(String(r))?e[r]:"",s=i.forwardRef((r,e)=>{let{numItems:t=1,numItemsSm:a,numItemsMd:s,numItemsLg:g,children:m,className:u}=r,p=(0,n._T)(r,["numItems","numItemsSm","numItemsMd","numItemsLg","children","className"]),f=c(t,d._m),h=c(a,d.LH),b=c(s,d.l5),w=c(g,d.N4),x=(0,o.q)(f,h,b,w);return i.createElement("div",Object.assign({ref:e,className:(0,o.q)(l("root"),"grid",x,u)},p),m)});s.displayName="Grid"},9496:function(r,e,t){t.d(e,{LH:function(){return o},N4:function(){return i},PT:function(){return d},SP:function(){return l},VS:function(){return c},_m:function(){return n},_w:function(){return s},l5:function(){return a}});let n={0:"grid-cols-none",1:"grid-cols-1",2:"grid-cols-2",3:"grid-cols-3",4:"grid-cols-4",5:"grid-cols-5",6:"grid-cols-6",7:"grid-cols-7",8:"grid-cols-8",9:"grid-cols-9",10:"grid-cols-10",11:"grid-cols-11",12:"grid-cols-12"},o={0:"sm:grid-cols-none",1:"sm:grid-cols-1",2:"sm:grid-cols-2",3:"sm:grid-cols-3",4:"sm:grid-cols-4",5:"sm:grid-cols-5",6:"sm:grid-cols-6",7:"sm:grid-cols-7",8:"sm:grid-cols-8",9:"sm:grid-cols-9",10:"sm:grid-cols-10",11:"sm:grid-cols-11",12:"sm:grid-cols-12"},a={0:"md:grid-cols-none",1:"md:grid-cols-1",2:"md:grid-cols-2",3:"md:grid-cols-3",4:"md:grid-cols-4",5:"md:grid-cols-5",6:"md:grid-cols-6",7:"md:grid-cols-7",8:"md:grid-cols-8",9:"md:grid-cols-9",10:"md:grid-cols-10",11:"md:grid-cols-11",12:"md:grid-cols-12"},i={0:"lg:grid-cols-none",1:"lg:grid-cols-1",2:"lg:grid-cols-2",3:"lg:grid-cols-3",4:"lg:grid-cols-4",5:"lg:grid-cols-5",6:"lg:grid-cols-6",7:"lg:grid-cols-7",8:"lg:grid-cols-8",9:"lg:grid-cols-9",10:"lg:grid-cols-10",11:"lg:grid-cols-11",12:"lg:grid-cols-12"},d={1:"col-span-1",2:"col-span-2",3:"col-span-3",4:"col-span-4",5:"col-span-5",6:"col-span-6",7:"col-span-7",8:"col-span-8",9:"col-span-9",10:"col-span-10",11:"col-span-11",12:"col-span-12",13:"col-span-13"},l={1:"sm:col-span-1",2:"sm:col-span-2",3:"sm:col-span-3",4:"sm:col-span-4",5:"sm:col-span-5",6:"sm:col-span-6",7:"sm:col-span-7",8:"sm:col-span-8",9:"sm:col-span-9",10:"sm:col-span-10",11:"sm:col-span-11",12:"sm:col-span-12",13:"sm:col-span-13"},c={1:"md:col-span-1",2:"md:col-span-2",3:"md:col-span-3",4:"md:col-span-4",5:"md:col-span-5",6:"md:col-span-6",7:"md:col-span-7",8:"md:col-span-8",9:"md:col-span-9",10:"md:col-span-10",11:"md:col-span-11",12:"md:col-span-12",13:"md:col-span-13"},s={1:"lg:col-span-1",2:"lg:col-span-2",3:"lg:col-span-3",4:"lg:col-span-4",5:"lg:col-span-5",6:"lg:col-span-6",7:"lg:col-span-7",8:"lg:col-span-8",9:"lg:col-span-9",10:"lg:col-span-10",11:"lg:col-span-11",12:"lg:col-span-12",13:"lg:col-span-13"}},84264:function(r,e,t){t.d(e,{Z:function(){return d}});var n=t(26898),o=t(13241),a=t(1153),i=t(2265);let d=i.forwardRef((r,e)=>{let{color:t,className:d,children:l}=r;return i.createElement("p",{ref:e,className:(0,o.q)("text-tremor-default",t?(0,a.bM)(t,n.K.text).textColor:(0,o.q)("text-tremor-content","dark:text-dark-tremor-content"),d)},l)});d.displayName="Text"},96761:function(r,e,t){t.d(e,{Z:function(){return l}});var n=t(5853),o=t(26898),a=t(13241),i=t(1153),d=t(2265);let l=d.forwardRef((r,e)=>{let{color:t,children:l,className:c}=r,s=(0,n._T)(r,["color","children","className"]);return d.createElement("p",Object.assign({ref:e,className:(0,a.q)("font-medium text-tremor-title",t?(0,i.bM)(t,o.K.darkText).textColor:"text-tremor-content-strong dark:text-dark-tremor-content-strong",c)},s),l)});l.displayName="Title"},23496:function(r,e,t){t.d(e,{Z:function(){return b}});var n=t(2265),o=t(36760),a=t.n(o),i=t(71744),d=t(33759),l=t(93463),c=t(12918),s=t(99320),g=t(71140);let m=r=>{let{componentCls:e}=r;return{[e]:{"&-horizontal":{["&".concat(e)]:{"&-sm":{marginBlock:r.marginXS},"&-md":{marginBlock:r.margin}}}}}},u=r=>{let{componentCls:e,sizePaddingEdgeHorizontal:t,colorSplit:n,lineWidth:o,textPaddingInline:a,orientationMargin:i,verticalMarginInline:d}=r;return{[e]:Object.assign(Object.assign({},(0,c.Wf)(r)),{borderBlockStart:"".concat((0,l.bf)(o)," solid ").concat(n),"&-vertical":{position:"relative",top:"-0.06em",display:"inline-block",height:"0.9em",marginInline:d,marginBlock:0,verticalAlign:"middle",borderTop:0,borderInlineStart:"".concat((0,l.bf)(o)," solid ").concat(n)},"&-horizontal":{display:"flex",clear:"both",width:"100%",minWidth:"100%",margin:"".concat((0,l.bf)(r.marginLG)," 0")},["&-horizontal".concat(e,"-with-text")]:{display:"flex",alignItems:"center",margin:"".concat((0,l.bf)(r.dividerHorizontalWithTextGutterMargin)," 0"),color:r.colorTextHeading,fontWeight:500,fontSize:r.fontSizeLG,whiteSpace:"nowrap",textAlign:"center",borderBlockStart:"0 ".concat(n),"&::before, &::after":{position:"relative",width:"50%",borderBlockStart:"".concat((0,l.bf)(o)," solid transparent"),borderBlockStartColor:"inherit",borderBlockEnd:0,transform:"translateY(50%)",content:"''"}},["&-horizontal".concat(e,"-with-text-start")]:{"&::before":{width:"calc(".concat(i," * 100%)")},"&::after":{width:"calc(100% - ".concat(i," * 100%)")}},["&-horizontal".concat(e,"-with-text-end")]:{"&::before":{width:"calc(100% - ".concat(i," * 100%)")},"&::after":{width:"calc(".concat(i," * 100%)")}},["".concat(e,"-inner-text")]:{display:"inline-block",paddingBlock:0,paddingInline:a},"&-dashed":{background:"none",borderColor:n,borderStyle:"dashed",borderWidth:"".concat((0,l.bf)(o)," 0 0")},["&-horizontal".concat(e,"-with-text").concat(e,"-dashed")]:{"&::before, &::after":{borderStyle:"dashed none none"}},["&-vertical".concat(e,"-dashed")]:{borderInlineStartWidth:o,borderInlineEnd:0,borderBlockStart:0,borderBlockEnd:0},"&-dotted":{background:"none",borderColor:n,borderStyle:"dotted",borderWidth:"".concat((0,l.bf)(o)," 0 0")},["&-horizontal".concat(e,"-with-text").concat(e,"-dotted")]:{"&::before, &::after":{borderStyle:"dotted none none"}},["&-vertical".concat(e,"-dotted")]:{borderInlineStartWidth:o,borderInlineEnd:0,borderBlockStart:0,borderBlockEnd:0},["&-plain".concat(e,"-with-text")]:{color:r.colorText,fontWeight:"normal",fontSize:r.fontSize},["&-horizontal".concat(e,"-with-text-start").concat(e,"-no-default-orientation-margin-start")]:{"&::before":{width:0},"&::after":{width:"100%"},["".concat(e,"-inner-text")]:{paddingInlineStart:t}},["&-horizontal".concat(e,"-with-text-end").concat(e,"-no-default-orientation-margin-end")]:{"&::before":{width:"100%"},"&::after":{width:0},["".concat(e,"-inner-text")]:{paddingInlineEnd:t}}})}};var p=(0,s.I$)("Divider",r=>{let e=(0,g.IX)(r,{dividerHorizontalWithTextGutterMargin:r.margin,sizePaddingEdgeHorizontal:0});return[u(e),m(e)]},r=>({textPaddingInline:"1em",orientationMargin:.05,verticalMarginInline:r.marginXS}),{unitless:{orientationMargin:!0}}),f=function(r,e){var t={};for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&0>e.indexOf(n)&&(t[n]=r[n]);if(null!=r&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(r);oe.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(r,n[o])&&(t[n[o]]=r[n[o]]);return t};let h={small:"sm",middle:"md"};var b=r=>{let{getPrefixCls:e,direction:t,className:o,style:l}=(0,i.dj)("divider"),{prefixCls:c,type:s="horizontal",orientation:g="center",orientationMargin:m,className:u,rootClassName:b,children:w,dashed:x,variant:k="solid",plain:v,style:C,size:y}=r,S=f(r,["prefixCls","type","orientation","orientationMargin","className","rootClassName","children","dashed","variant","plain","style","size"]),M=e("divider",c),[E,z,j]=p(M),L=h[(0,d.Z)(y)],N=!!w,O=n.useMemo(()=>"left"===g?"rtl"===t?"end":"start":"right"===g?"rtl"===t?"start":"end":g,[t,g]),Z="start"===O&&null!=m,B="end"===O&&null!=m,I=a()(M,o,z,j,"".concat(M,"-").concat(s),{["".concat(M,"-with-text")]:N,["".concat(M,"-with-text-").concat(O)]:N,["".concat(M,"-dashed")]:!!x,["".concat(M,"-").concat(k)]:"solid"!==k,["".concat(M,"-plain")]:!!v,["".concat(M,"-rtl")]:"rtl"===t,["".concat(M,"-no-default-orientation-margin-start")]:Z,["".concat(M,"-no-default-orientation-margin-end")]:B,["".concat(M,"-").concat(L)]:!!L},u,b),R=n.useMemo(()=>"number"==typeof m?m:/^\d+$/.test(m)?Number(m):m,[m]);return E(n.createElement("div",Object.assign({className:I,style:Object.assign(Object.assign({},l),C)},S,{role:"separator"}),w&&"vertical"!==s&&n.createElement("span",{className:"".concat(M,"-inner-text"),style:{marginInlineStart:Z?R:void 0,marginInlineEnd:B?R:void 0}},w)))}},10900:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10 19l-7-7m0 0l7-7m-7 7h18"}))});e.Z=o},86462:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"}))});e.Z=o},44633:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 15l7-7 7 7"}))});e.Z=o},3477:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"}))});e.Z=o},53410:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"}))});e.Z=o},91126:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"}),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M21 12a9 9 0 11-18 0 9 9 0 0118 0z"}))});e.Z=o},23628:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"}))});e.Z=o},49084:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"}))});e.Z=o},74998:function(r,e,t){var n=t(2265);let o=n.forwardRef(function(r,e){return n.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor","aria-hidden":"true",ref:e},r),n.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"}))});e.Z=o}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1658-c301cddaf7772753.js b/litellm/proxy/_experimental/out/_next/static/chunks/1658-c301cddaf7772753.js new file mode 100644 index 00000000000..730804d53de --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/1658-c301cddaf7772753.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1658],{71658:function(e,l,t){t.d(l,{Z:function(){return l1}});var s=t(57437),a=t(19250),r=t(11713),i=t(90246),n=t(39760);let o=(0,i.n)("credentials"),d=()=>{let{accessToken:e}=(0,n.Z)();return(0,r.a)({queryKey:o.list({}),queryFn:async()=>await (0,a.credentialListCall)(e),enabled:!!e})},c=(0,i.n)("modelCostMap"),m=()=>(0,r.a)({queryKey:c.list({}),queryFn:async()=>await (0,a.modelCostMap)(),staleTime:6e4,gcTime:6e4});var u=t(52178),h=t(55584),x=t(47359),p=t(71594),g=t(24525),f=t(2265),j=t(19130),v=t(73705),_=t(5545),b=t(44633),y=t(86462),N=t(3837),w=t(49084);let Z=e=>{let{sortState:l,onSortChange:t}=e,a=[{key:"asc",label:"Ascending",icon:(0,s.jsx)(b.Z,{className:"h-4 w-4"})},{key:"desc",label:"Descending",icon:(0,s.jsx)(y.Z,{className:"h-4 w-4"})},{key:"reset",label:"Reset",icon:(0,s.jsx)(N.Z,{className:"h-4 w-4"})}];return(0,s.jsx)(v.Z,{menu:{items:a,onClick:e=>{let{key:l}=e;"asc"===l?t("asc"):"desc"===l?t("desc"):"reset"===l&&t(!1)},selectable:!0,selectedKeys:l?[l]:[]},trigger:["click"],autoAdjustOverflow:!0,children:(0,s.jsx)(_.ZP,{type:"text",onClick:e=>e.stopPropagation(),icon:"asc"===l?(0,s.jsx)(b.Z,{className:"h-4 w-4"}):"desc"===l?(0,s.jsx)(y.Z,{className:"h-4 w-4"}):(0,s.jsx)(w.Z,{className:"h-4 w-4"}),className:l?"text-blue-500 hover:text-blue-600":"text-gray-400 hover:text-blue-500"})})};function C(e){let{data:l=[],columns:t,isLoading:a=!1,sorting:r=[],onSortingChange:i,pagination:n,onPaginationChange:o,enablePagination:d=!1}=e,[c]=f.useState("onChange"),[m,u]=f.useState({}),[h,x]=f.useState({}),v=(0,p.b7)({data:l,columns:t,state:{sorting:r,columnSizing:m,columnVisibility:h,...d&&n?{pagination:n}:{}},columnResizeMode:c,onSortingChange:i,onColumnSizingChange:u,onColumnVisibilityChange:x,...d&&o?{onPaginationChange:o}:{},getCoreRowModel:(0,g.sC)(),...d?{getPaginationRowModel:(0,g.G_)()}:{},enableSorting:!0,enableColumnResizing:!0,manualSorting:!0,defaultColumn:{minSize:40,maxSize:500}});return(0,s.jsx)("div",{className:"rounded-lg custom-border relative",children:(0,s.jsx)("div",{className:"overflow-x-auto",children:(0,s.jsx)("div",{className:"relative min-w-full",children:(0,s.jsxs)(j.iA,{className:"[&_td]:py-2 [&_th]:py-2 w-full",children:[(0,s.jsx)(j.ss,{children:v.getHeaderGroups().map(e=>(0,s.jsx)(j.SC,{children:e.headers.map(e=>{var l;return(0,s.jsxs)(j.xs,{className:"py-1 h-8 relative ".concat("actions"===e.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)] w-[120px] ml-8":""," ").concat((null===(l=e.column.columnDef.meta)||void 0===l?void 0:l.className)||""),style:{width:"actions"===e.id?120:e.getSize(),position:"actions"===e.id?"sticky":"relative",right:"actions"===e.id?0:"auto"},children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,s.jsx)("div",{className:"flex items-center",children:e.isPlaceholder?null:(0,p.ie)(e.column.columnDef.header,e.getContext())}),"actions"!==e.id&&e.column.getCanSort()&&i&&(0,s.jsx)(Z,{sortState:!1!==e.column.getIsSorted()&&e.column.getIsSorted(),onSortChange:l=>{!1===l?i([]):i([{id:e.column.id,desc:"desc"===l}])},columnId:e.column.id})]}),e.column.getCanResize()&&(0,s.jsx)("div",{onMouseDown:e.getResizeHandler(),onTouchStart:e.getResizeHandler(),className:"absolute right-0 top-0 h-full w-2 cursor-col-resize select-none touch-none ".concat(e.column.getIsResizing()?"bg-blue-500":"hover:bg-blue-200")})]},e.id)})},e.id))}),(0,s.jsx)(j.RM,{children:a?(0,s.jsx)(j.SC,{children:(0,s.jsx)(j.pj,{colSpan:t.length,className:"h-8 text-center",children:(0,s.jsx)("div",{className:"text-center text-gray-500",children:(0,s.jsx)("p",{children:"\uD83D\uDE85 Loading models..."})})})}):v.getRowModel().rows.length>0?v.getRowModel().rows.map(e=>(0,s.jsx)(j.SC,{children:e.getVisibleCells().map(e=>{var l;return(0,s.jsx)(j.pj,{className:"py-0.5 ".concat("actions"===e.column.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)] w-[120px] ml-8":""," ").concat((null===(l=e.column.columnDef.meta)||void 0===l?void 0:l.className)||""),style:{width:"actions"===e.column.id?120:e.column.getSize(),position:"actions"===e.column.id?"sticky":"relative",right:"actions"===e.column.id?0:"auto"},children:(0,p.ie)(e.column.columnDef.cell,e.getContext())},e.id)})},e.id)):(0,s.jsx)(j.SC,{children:(0,s.jsx)(j.pj,{colSpan:t.length,className:"h-8 text-center",children:(0,s.jsx)("div",{className:"text-center text-gray-500",children:(0,s.jsx)("p",{children:"No models found"})})})})})]})})})})}var k=t(45589),S=t(74998),A=t(41649),E=t(78489),P=t(47323),M=t(99981),L=t(42673);let F=e=>{let{provider:l,className:t="w-4 h-4"}=e,[a,r]=(0,f.useState)(!1),{logo:i}=(0,L.dr)(l);return a||!i?(0,s.jsx)("div",{className:"".concat(t," rounded-full bg-gray-200 flex items-center justify-center text-xs"),children:(null==l?void 0:l.charAt(0))||"-"}):(0,s.jsx)("img",{src:i,alt:"".concat(l," logo"),className:t,onError:()=>r(!0)})},I=(e,l,t,a,r,i,n,o,d,c)=>[{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Model ID"}),accessorKey:"model_info.id",enableSorting:!1,cell:e=>{let{row:l}=e,t=l.original;return(0,s.jsx)(M.Z,{title:t.model_info.id,children:(0,s.jsx)("div",{className:"font-mono text-blue-500 bg-blue-50 hover:bg-blue-100 text-xs font-normal px-2 py-0.5 text-left w-full truncate whitespace-nowrap cursor-pointer max-w-[15ch]",onClick:()=>a(t.model_info.id),children:t.model_info.id})})}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Model Information"}),accessorKey:"model_name",size:250,cell:e=>{let{row:l}=e,t=l.original,a=i(l.original)||"-",r=(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("strong",{children:"Provider:"})," ",t.provider||"-"]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("strong",{children:"Public Model Name:"})," ",a]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("strong",{children:"LiteLLM Model Name:"})," ",t.litellm_model_name||"-"]})]});return(0,s.jsx)(M.Z,{title:r,children:(0,s.jsxs)("div",{className:"flex items-start space-x-2 min-w-0 w-full max-w-[250px]",children:[(0,s.jsx)("div",{className:"flex-shrink-0 mt-0.5",children:t.provider?(0,s.jsx)(F,{provider:t.provider}):(0,s.jsx)("div",{className:"w-4 h-4 rounded-full bg-gray-200 flex items-center justify-center text-xs",children:"-"})}),(0,s.jsxs)("div",{className:"flex flex-col min-w-0 flex-1",children:[(0,s.jsx)("div",{className:"text-xs font-medium text-gray-900 truncate max-w-[210px]",children:a}),(0,s.jsx)("div",{className:"text-xs text-gray-500 truncate mt-0.5 max-w-[210px]",children:t.litellm_model_name||"-"})]})]})})}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Credentials"}),accessorKey:"litellm_credential_name",enableSorting:!1,size:180,cell:e=>{var l;let{row:t}=e,a=null===(l=t.original.litellm_params)||void 0===l?void 0:l.litellm_credential_name;return a?(0,s.jsx)(M.Z,{title:"Credential: ".concat(a),children:(0,s.jsxs)("div",{className:"flex items-center space-x-2 max-w-[180px]",children:[(0,s.jsx)(k.Z,{className:"w-4 h-4 text-blue-500 flex-shrink-0"}),(0,s.jsx)("span",{className:"text-xs truncate",title:a,children:a})]})}):(0,s.jsxs)("div",{className:"flex items-center space-x-2 max-w-[180px]",children:[(0,s.jsx)(k.Z,{className:"w-4 h-4 text-gray-300 flex-shrink-0"}),(0,s.jsx)("span",{className:"text-xs text-gray-400",children:"No credentials"})]})}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Created By"}),accessorKey:"model_info.created_by",sortingFn:"datetime",size:160,cell:e=>{var l;let{row:t}=e,a=t.original,r=!(null===(l=a.model_info)||void 0===l?void 0:l.db_model),i=a.model_info.created_by,n=a.model_info.created_at?new Date(a.model_info.created_at).toLocaleDateString():null;return(0,s.jsxs)("div",{className:"flex flex-col min-w-0 max-w-[160px]",children:[(0,s.jsx)("div",{className:"text-xs font-medium text-gray-900 truncate",title:r?"Defined in config":i||"Unknown",children:r?"Defined in config":i||"Unknown"}),(0,s.jsx)("div",{className:"text-xs text-gray-500 truncate mt-0.5",title:r?"Config file":n||"Unknown date",children:r?"-":n||"Unknown date"})]})}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Updated At"}),accessorKey:"model_info.updated_at",sortingFn:"datetime",cell:e=>{let{row:l}=e,t=l.original;return(0,s.jsx)("span",{className:"text-xs",children:t.model_info.updated_at?new Date(t.model_info.updated_at).toLocaleDateString():"-"})}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Costs"}),accessorKey:"input_cost",size:120,cell:e=>{let{row:l}=e,t=l.original,a=t.input_cost,r=t.output_cost;return a||r?(0,s.jsx)(M.Z,{title:"Cost per 1M tokens",children:(0,s.jsxs)("div",{className:"flex flex-col min-w-0 max-w-[120px]",children:[a&&(0,s.jsxs)("div",{className:"text-xs font-medium text-gray-900 truncate",children:["In: $",a]}),r&&(0,s.jsxs)("div",{className:"text-xs text-gray-500 truncate mt-0.5",children:["Out: $",r]})]})}):(0,s.jsx)("div",{className:"max-w-[120px]",children:(0,s.jsx)("span",{className:"text-xs text-gray-400",children:"-"})})}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Team ID"}),accessorKey:"model_info.team_id",enableSorting:!1,cell:e=>{let{row:l}=e,t=l.original;return t.model_info.team_id?(0,s.jsx)("div",{className:"overflow-hidden",children:(0,s.jsx)(M.Z,{title:t.model_info.team_id,children:(0,s.jsxs)(E.Z,{size:"xs",variant:"light",className:"font-mono text-blue-500 bg-blue-50 hover:bg-blue-100 text-xs font-normal px-2 py-0.5 text-left overflow-hidden truncate max-w-[200px]",onClick:()=>r(t.model_info.team_id),children:[t.model_info.team_id.slice(0,7),"..."]})})}):"-"}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Model Access Group"}),accessorKey:"model_info.model_access_group",enableSorting:!1,cell:e=>{let{row:l}=e,t=l.original,a=t.model_info.access_groups;if(!a||0===a.length)return"-";let r=t.model_info.id,i=d.has(r),n=a.length>1,o=()=>{let e=new Set(d);i?e.delete(r):e.add(r),c(e)};return(0,s.jsxs)("div",{className:"flex items-center gap-1 overflow-hidden",children:[(0,s.jsx)(A.Z,{size:"xs",color:"blue",className:"text-xs px-1.5 py-0.5 h-5 leading-tight flex-shrink-0",children:a[0]}),(i||!n&&2===a.length)&&a.slice(1).map((e,l)=>(0,s.jsx)(A.Z,{size:"xs",color:"blue",className:"text-xs px-1.5 py-0.5 h-5 leading-tight flex-shrink-0",children:e},l+1)),n&&(0,s.jsx)("button",{onClick:e=>{e.stopPropagation(),o()},className:"text-xs text-blue-600 hover:text-blue-800 px-1 py-0.5 rounded hover:bg-blue-50 h-5 leading-tight flex-shrink-0 whitespace-nowrap",children:i?"āˆ’":"+".concat(a.length-1)})]})}},{header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Status"}),accessorKey:"model_info.db_model",cell:e=>{let{row:l}=e,t=l.original;return(0,s.jsx)("div",{className:"\n inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium\n ".concat(t.model_info.db_model?"bg-blue-50 text-blue-600":"bg-gray-100 text-gray-600","\n "),children:t.model_info.db_model?"DB Model":"Config Model"})}},{id:"actions",header:()=>(0,s.jsx)("span",{className:"text-sm font-semibold",children:"Actions"}),cell:t=>{var r,i;let{row:n}=t,o=n.original,d="Admin"===e||(null===(r=o.model_info)||void 0===r?void 0:r.created_by)===l,c=!(null===(i=o.model_info)||void 0===i?void 0:i.db_model);return(0,s.jsx)("div",{className:"flex items-center justify-end gap-2 pr-4",children:c?(0,s.jsx)(M.Z,{title:"Config model cannot be deleted on the dashboard. Please delete it from the config file.",children:(0,s.jsx)(P.Z,{icon:S.Z,size:"sm",className:"opacity-50 cursor-not-allowed"})}):(0,s.jsx)(M.Z,{title:"Delete model",children:(0,s.jsx)(P.Z,{icon:S.Z,size:"sm",onClick:()=>{d&&a(o.model_info.id)},className:d?"cursor-pointer hover:text-red-600":"opacity-50 cursor-not-allowed"})})})}}],T=e=>{var l;return(null==e?void 0:null===(l=e.model_info)||void 0===l?void 0:l.team_public_model_name)?e.model_info.team_public_model_name:(null==e?void 0:e.model_name)||"-"};var R=t(15424),O=t(67101),V=t(27281),q=t(57365),z=t(29706),D=t(84264),B=t(50337),G=t(10353),U=t(7310),H=t.n(U);let K=(e,l)=>{if(!(null==e?void 0:e.data))return{data:[]};let t=JSON.parse(JSON.stringify(e.data));for(let e=0;e{let[l]=e;return"model"!==l&&"api_base"!==l}))),t[e].provider=c,t[e].input_cost=m,t[e].output_cost=u,t[e].litellm_model_name=n,t[e].input_cost&&(t[e].input_cost=(1e6*Number(t[e].input_cost)).toFixed(2)),t[e].output_cost&&(t[e].output_cost=(1e6*Number(t[e].output_cost)).toFixed(2)),t[e].max_tokens=h,t[e].max_input_tokens=x,t[e].api_base=null==i?void 0:null===(r=i.litellm_params)||void 0===r?void 0:r.api_base,t[e].cleanedLitellmParams=p}return{data:t}};var J=e=>{let{selectedModelGroup:l,setSelectedModelGroup:t,availableModelGroups:a,availableModelAccessGroups:r,setSelectedModelId:i,setSelectedTeamId:o}=e,{data:d,isLoading:c}=m(),{userId:h,userRole:p,premiumUser:g}=(0,n.Z)(),{data:j,isLoading:v}=(0,x.y2)(),[_,b]=(0,f.useState)(""),[y,N]=(0,f.useState)(""),[w,Z]=(0,f.useState)("current_team"),[k,S]=(0,f.useState)("personal"),[A,E]=(0,f.useState)(!1),[P,M]=(0,f.useState)(null),[L,F]=(0,f.useState)(new Set),[U,J]=(0,f.useState)(1),[W]=(0,f.useState)(50),[Y,$]=(0,f.useState)({pageIndex:0,pageSize:50}),[X,Q]=(0,f.useState)([]),ee=(0,f.useMemo)(()=>H()(e=>{N(e),J(1),$(e=>({...e,pageIndex:0}))},200),[]);(0,f.useEffect)(()=>(ee(_),()=>{ee.cancel()}),[_,ee]);let el="personal"===k?void 0:k.team_id,et=(0,f.useMemo)(()=>{if(0===X.length)return;let e=X[0];return({input_cost:"costs",model_info_db_model:"status",model_info_created_by:"created_at",model_info_updated_at:"updated_at"})[e.id]||e.id},[X]),es=(0,f.useMemo)(()=>{if(0!==X.length)return X[0].desc?"desc":"asc"},[X]),{data:ea,isLoading:er}=(0,u.XP)(U,W,y||void 0,void 0,el,et,es),ei=er||c,en=e=>null!=d&&"object"==typeof d&&e in d?d[e].litellm_provider:"openai",eo=(0,f.useMemo)(()=>ea?K(ea,en):{data:[]},[ea,d]),ed=(0,f.useMemo)(()=>{var e,l,t,s;return ea?{total_count:null!==(e=ea.total_count)&&void 0!==e?e:0,current_page:null!==(l=ea.current_page)&&void 0!==l?l:1,total_pages:null!==(t=ea.total_pages)&&void 0!==t?t:1,size:null!==(s=ea.size)&&void 0!==s?s:W}:{total_count:0,current_page:1,total_pages:1,size:W}},[ea,W]),ec=(0,f.useMemo)(()=>eo&&eo.data&&0!==eo.data.length?eo.data.filter(e=>{var t,s;let a="all"===l||e.model_name===l||!l||"wildcard"===l&&(null===(t=e.model_name)||void 0===t?void 0:t.includes("*")),r="all"===P||(null===(s=e.model_info.access_groups)||void 0===s?void 0:s.includes(P))||!P;return a&&r}):[],[eo,l,P]);return(0,f.useEffect)(()=>{$(e=>({...e,pageIndex:0})),J(1)},[l,P]),(0,f.useEffect)(()=>{J(1),$(e=>({...e,pageIndex:0}))},[el]),(0,f.useEffect)(()=>{J(1),$(e=>({...e,pageIndex:0}))},[X]),(0,s.jsx)(z.Z,{children:(0,s.jsx)(O.Z,{children:(0,s.jsx)("div",{className:"flex flex-col space-y-4",children:(0,s.jsxs)("div",{className:"bg-white rounded-lg shadow",children:[(0,s.jsxs)("div",{className:"border-b px-6 py-4 bg-gray-50",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between",children:[(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[(0,s.jsx)(D.Z,{className:"text-lg font-semibold text-gray-900",children:"Current Team:"}),ei?(0,s.jsx)(B.Z.Input,{active:!0,style:{width:320,height:36}}):(0,s.jsxs)(V.Z,{className:"w-80",defaultValue:"personal",value:"personal"===k?"personal":k.team_id,onValueChange:e=>{if("personal"===e)S("personal"),J(1),$(e=>({...e,pageIndex:0}));else{let l=null==j?void 0:j.find(l=>l.team_id===e);l&&(S(l),J(1),$(e=>({...e,pageIndex:0})))}},children:[(0,s.jsx)(q.Z,{value:"personal",children:(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("div",{className:"w-2 h-2 bg-blue-500 rounded-full"}),(0,s.jsx)("span",{className:"font-medium",children:"Personal"})]})}),v?(0,s.jsx)(q.Z,{value:"loading",children:(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)(G.Z,{size:"small"}),(0,s.jsx)("span",{className:"font-medium text-gray-500",children:"Loading teams..."})]})}):null==j?void 0:j.filter(e=>e.team_id).map(e=>(0,s.jsx)(q.Z,{value:e.team_id,children:(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("div",{className:"w-2 h-2 bg-green-500 rounded-full"}),(0,s.jsx)("span",{className:"font-medium",children:e.team_alias?"".concat(e.team_alias.slice(0,30),"..."):"Team ".concat(e.team_id.slice(0,30),"...")})]})},e.team_id))]})]}),(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[(0,s.jsx)(D.Z,{className:"text-lg font-semibold text-gray-900",children:"View:"}),ei?(0,s.jsx)(B.Z.Input,{active:!0,style:{width:256,height:36}}):(0,s.jsxs)(V.Z,{className:"w-64",defaultValue:"current_team",value:w,onValueChange:e=>Z(e),children:[(0,s.jsx)(q.Z,{value:"current_team",children:(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("div",{className:"w-2 h-2 bg-purple-500 rounded-full"}),(0,s.jsx)("span",{className:"font-medium",children:"Current Team Models"})]})}),(0,s.jsx)(q.Z,{value:"all",children:(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("div",{className:"w-2 h-2 bg-gray-500 rounded-full"}),(0,s.jsx)("span",{className:"font-medium",children:"All Available Models"})]})})]})]})]}),"current_team"===w&&(0,s.jsxs)("div",{className:"flex items-start gap-2 mt-3",children:[(0,s.jsx)(R.Z,{className:"text-gray-400 mt-0.5 flex-shrink-0 text-xs"}),(0,s.jsx)("div",{className:"text-xs text-gray-500",children:"personal"===k?(0,s.jsxs)("span",{children:["To access these models: Create a Virtual Key without selecting a team on the"," ",(0,s.jsx)("a",{href:"/public?login=success&page=api-keys",className:"text-gray-600 hover:text-gray-800 underline",children:"Virtual Keys page"})]}):(0,s.jsxs)("span",{children:['To access these models: Create a Virtual Key and select Team as "',"string"!=typeof k?k.team_alias||k.team_id:"",'" on the'," ",(0,s.jsx)("a",{href:"/public?login=success&page=api-keys",className:"text-gray-600 hover:text-gray-800 underline",children:"Virtual Keys page"})]})})]})]}),(0,s.jsx)("div",{className:"border-b px-6 py-4",children:(0,s.jsxs)("div",{className:"flex flex-col space-y-4",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,s.jsxs)("div",{className:"relative w-64",children:[(0,s.jsx)("input",{type:"text",placeholder:"Search model names...",className:"w-full px-3 py-2 pl-8 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",value:_,onChange:e=>b(e.target.value)}),(0,s.jsx)("svg",{className:"absolute left-2.5 top-2.5 h-4 w-4 text-gray-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})})]}),(0,s.jsxs)("button",{className:"px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2 ".concat(A?"bg-gray-100":""),onClick:()=>E(!A),children:[(0,s.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"})}),"Filters"]}),(0,s.jsxs)("button",{className:"px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2",onClick:()=>{b(""),t("all"),M(null),S("personal"),Z("current_team"),J(1),$({pageIndex:0,pageSize:50}),Q([])},children:[(0,s.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),"Reset Filters"]})]}),A&&(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-3 mt-3",children:[(0,s.jsx)("div",{className:"w-64",children:(0,s.jsxs)(V.Z,{value:null!=l?l:"all",onValueChange:e=>t("all"===e?"all":e),placeholder:"Filter by Public Model Name",children:[(0,s.jsx)(q.Z,{value:"all",children:"All Models"}),(0,s.jsx)(q.Z,{value:"wildcard",children:"Wildcard Models (*)"}),a.map((e,l)=>(0,s.jsx)(q.Z,{value:e,children:e},l))]})}),(0,s.jsx)("div",{className:"w-64",children:(0,s.jsxs)(V.Z,{value:null!=P?P:"all",onValueChange:e=>M("all"===e?null:e),placeholder:"Filter by Model Access Group",children:[(0,s.jsx)(q.Z,{value:"all",children:"All Model Access Groups"}),r.map((e,l)=>(0,s.jsx)(q.Z,{value:e,children:e},l))]})})]}),(0,s.jsxs)("div",{className:"flex justify-between items-center",children:[ei?(0,s.jsx)(B.Z.Input,{active:!0,style:{width:184,height:20}}):(0,s.jsx)("span",{className:"text-sm text-gray-700",children:ed.total_count>0?"Showing ".concat((U-1)*W+1," - ").concat(Math.min(U*W,ed.total_count)," of ").concat(ed.total_count," results"):"Showing 0 results"}),(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[ei?(0,s.jsx)(B.Z.Button,{active:!0,style:{width:84,height:30}}):(0,s.jsx)("button",{onClick:()=>{J(U-1),$(e=>({...e,pageIndex:0}))},disabled:1===U,className:"px-3 py-1 text-sm border rounded-md ".concat(1===U?"bg-gray-100 text-gray-400 cursor-not-allowed":"hover:bg-gray-50"),children:"Previous"}),ei?(0,s.jsx)(B.Z.Button,{active:!0,style:{width:56,height:30}}):(0,s.jsx)("button",{onClick:()=>{J(U+1),$(e=>({...e,pageIndex:0}))},disabled:U>=ed.total_pages,className:"px-3 py-1 text-sm border rounded-md ".concat(U>=ed.total_pages?"bg-gray-100 text-gray-400 cursor-not-allowed":"hover:bg-gray-50"),children:"Next"})]})]})]})}),(0,s.jsx)(C,{columns:I(p,h,g,i,o,T,()=>{},()=>{},L,F),data:ec,isLoading:er,sorting:X,onSortingChange:Q,pagination:Y,onPaginationChange:$,enablePagination:!0})]})})})})},W=t(96761),Y=t(12221);let $={"BadRequestError (400)":"BadRequestErrorRetries","AuthenticationError (401)":"AuthenticationErrorRetries","TimeoutError (408)":"TimeoutErrorRetries","RateLimitError (429)":"RateLimitErrorRetries","ContentPolicyViolationError (400)":"ContentPolicyViolationErrorRetries","InternalServerError (500)":"InternalServerErrorRetries"};var X=e=>{let{selectedModelGroup:l,setSelectedModelGroup:t,availableModelGroups:a,globalRetryPolicy:r,setGlobalRetryPolicy:i,defaultRetry:n,modelGroupRetryPolicy:o,setModelGroupRetryPolicy:d,handleSaveRetrySettings:c}=e;return(0,s.jsxs)(z.Z,{children:[(0,s.jsx)("div",{className:"flex items-center gap-4 mb-6",children:(0,s.jsxs)("div",{className:"flex items-center",children:[(0,s.jsx)(D.Z,{children:"Retry Policy Scope:"}),(0,s.jsxs)(V.Z,{className:"ml-2 w-48",defaultValue:"global",value:"global"===l?"global":l||a[0],onValueChange:e=>t(e),children:[(0,s.jsx)(q.Z,{value:"global",children:"Global Default"}),a.map((e,l)=>(0,s.jsx)(q.Z,{value:e,onClick:()=>t(e),children:e},l))]})]})}),"global"===l?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(W.Z,{children:"Global Retry Policy"}),(0,s.jsx)(D.Z,{className:"mb-6",children:"Default retry settings applied to all model groups unless overridden"})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(W.Z,{children:["Retry Policy for ",l]}),(0,s.jsx)(D.Z,{className:"mb-6",children:"Model-specific retry settings. Falls back to global defaults if not set."})]}),$&&(0,s.jsx)("table",{children:(0,s.jsx)("tbody",{children:Object.entries($).map((e,t)=>{var a,c,m,u;let h,[x,p]=e;if("global"===l)h=null!==(a=null==r?void 0:r[p])&&void 0!==a?a:n;else{let e=null==o?void 0:null===(c=o[l])||void 0===c?void 0:c[p];h=null!=e?e:null!==(m=null==r?void 0:r[p])&&void 0!==m?m:n}return(0,s.jsxs)("tr",{className:"flex justify-between items-center mt-2",children:[(0,s.jsxs)("td",{children:[(0,s.jsx)(D.Z,{children:x}),"global"!==l&&(0,s.jsxs)(D.Z,{className:"text-xs text-gray-500 ml-2",children:["(Global: ",null!==(u=null==r?void 0:r[p])&&void 0!==u?u:n,")"]})]}),(0,s.jsx)("td",{children:(0,s.jsx)(Y.Z,{className:"ml-5",value:h,min:0,step:1,onChange:e=>{"global"===l?i(l=>null==e?l:{...null!=l?l:{},[p]:e}):d(t=>{var s;let a=null!==(s=null==t?void 0:t[l])&&void 0!==s?s:{};return{...null!=t?t:{},[l]:{...a,[p]:e}}})}})})]},t)})})}),(0,s.jsx)(E.Z,{className:"mt-6 mr-8",onClick:c,children:"Save"})]})},Q=t(57840),ee=t(58760),el=t(867),et=t(5945),es=t(3810),ea=t(22116),er=t(89245),ei=t(5540),en=t(8881),eo=t(9114);let{Text:ed}=Q.default;var ec=e=>{let{accessToken:l,onReloadSuccess:t,buttonText:r="Reload Price Data",showIcon:i=!0,size:n="middle",type:o="primary",className:d=""}=e,[c,m]=(0,f.useState)(!1),[u,h]=(0,f.useState)(!1),[x,p]=(0,f.useState)(!1),[g,j]=(0,f.useState)(!1),[v,b]=(0,f.useState)(6),[y,N]=(0,f.useState)(null),[w,Z]=(0,f.useState)(!1);(0,f.useEffect)(()=>{C();let e=setInterval(()=>{C()},3e4);return()=>clearInterval(e)},[l]);let C=async()=>{if(l){Z(!0);try{console.log("Fetching reload status...");let e=await (0,a.getModelCostMapReloadStatus)(l);console.log("Received status:",e),N(e)}catch(e){console.error("Failed to fetch reload status:",e),N({scheduled:!1,interval_hours:null,last_run:null,next_run:null})}finally{Z(!1)}}},k=async()=>{if(!l){eo.Z.fromBackend("No access token available");return}m(!0);try{let e=await (0,a.reloadModelCostMap)(l);"success"===e.status?(eo.Z.success("Price data reloaded successfully! ".concat(e.models_count||0," models updated.")),null==t||t(),await C()):eo.Z.fromBackend("Failed to reload price data")}catch(e){console.error("Error reloading price data:",e),eo.Z.fromBackend("Failed to reload price data. Please try again.")}finally{m(!1)}},S=async()=>{if(!l){eo.Z.fromBackend("No access token available");return}if(v<=0){eo.Z.fromBackend("Hours must be greater than 0");return}h(!0);try{let e=await (0,a.scheduleModelCostMapReload)(l,v);"success"===e.status?(eo.Z.success("Periodic reload scheduled for every ".concat(v," hours")),j(!1),await C()):eo.Z.fromBackend("Failed to schedule periodic reload")}catch(e){console.error("Error scheduling reload:",e),eo.Z.fromBackend("Failed to schedule periodic reload. Please try again.")}finally{h(!1)}},A=async()=>{if(!l){eo.Z.fromBackend("No access token available");return}p(!0);try{let e=await (0,a.cancelModelCostMapReload)(l);"success"===e.status?(eo.Z.success("Periodic reload cancelled successfully"),await C()):eo.Z.fromBackend("Failed to cancel periodic reload")}catch(e){console.error("Error cancelling reload:",e),eo.Z.fromBackend("Failed to cancel periodic reload. Please try again.")}finally{p(!1)}},E=e=>{if(!e)return"Never";try{return new Date(e).toLocaleString()}catch(l){return e}};return(0,s.jsxs)("div",{className:d,children:[(0,s.jsxs)(ee.Z,{direction:"horizontal",size:"middle",style:{marginBottom:16},children:[(0,s.jsx)(el.Z,{title:"Hard Refresh Price Data",description:"This will immediately fetch the latest pricing information from the remote source. Continue?",onConfirm:k,okText:"Yes",cancelText:"No",okButtonProps:{style:{backgroundColor:"#6366f1",borderColor:"#6366f1",color:"white",fontWeight:"500",borderRadius:"0.375rem",padding:"0.375rem 0.75rem",height:"auto",fontSize:"0.875rem",lineHeight:"1.25rem",transition:"all 0.2s ease-in-out"},onMouseEnter:e=>{e.currentTarget.style.backgroundColor="#4f46e5"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="#6366f1"}},children:(0,s.jsx)(_.ZP,{type:o,size:n,loading:c,icon:i?(0,s.jsx)(er.Z,{}):void 0,style:{backgroundColor:"#6366f1",borderColor:"#6366f1",color:"white",fontWeight:"500",borderRadius:"0.375rem",padding:"0.375rem 0.75rem",height:"auto",fontSize:"0.875rem",lineHeight:"1.25rem",transition:"all 0.2s ease-in-out"},onMouseEnter:e=>{e.currentTarget.style.backgroundColor="#4f46e5"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="#6366f1"},children:r})}),(null==y?void 0:y.scheduled)?(0,s.jsx)(_.ZP,{type:"default",size:n,danger:!0,icon:(0,s.jsx)(en.Z,{}),loading:x,onClick:A,style:{borderColor:"#ff4d4f",color:"#ff4d4f",fontWeight:"500",borderRadius:"0.375rem",padding:"0.375rem 0.75rem",height:"auto",fontSize:"0.875rem",lineHeight:"1.25rem"},children:"Cancel Periodic Reload"}):(0,s.jsx)(_.ZP,{type:"default",size:n,icon:(0,s.jsx)(ei.Z,{}),onClick:()=>j(!0),style:{borderColor:"#d9d9d9",color:"#6366f1",fontWeight:"500",borderRadius:"0.375rem",padding:"0.375rem 0.75rem",height:"auto",fontSize:"0.875rem",lineHeight:"1.25rem"},children:"Set Up Periodic Reload"})]}),y&&(0,s.jsx)(et.Z,{size:"small",style:{backgroundColor:"#f8f9fa",border:"1px solid #e9ecef",borderRadius:8},children:(0,s.jsxs)(ee.Z,{direction:"vertical",size:"small",style:{width:"100%"},children:[y.scheduled?(0,s.jsx)("div",{children:(0,s.jsxs)(es.Z,{color:"green",icon:(0,s.jsx)(ei.Z,{}),children:["Scheduled every ",y.interval_hours," hours"]})}):(0,s.jsx)(ed,{type:"secondary",children:"No periodic reload scheduled"}),(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,s.jsx)(ed,{type:"secondary",style:{fontSize:"12px"},children:"Last run:"}),(0,s.jsx)(ed,{style:{fontSize:"12px"},children:E(y.last_run)})]}),y.scheduled&&(0,s.jsxs)(s.Fragment,{children:[y.next_run&&(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,s.jsx)(ed,{type:"secondary",style:{fontSize:"12px"},children:"Next run:"}),(0,s.jsx)(ed,{style:{fontSize:"12px"},children:E(y.next_run)})]}),(0,s.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,s.jsx)(ed,{type:"secondary",style:{fontSize:"12px"},children:"Status:"}),(0,s.jsx)(es.Z,{color:(null==y?void 0:y.scheduled)?y.last_run?"success":"processing":"default",children:(null==y?void 0:y.scheduled)?y.last_run?"Active":"Ready":"Not scheduled"})]})]})]})}),(0,s.jsxs)(ea.Z,{title:"Set Up Periodic Reload",open:g,onOk:S,onCancel:()=>j(!1),confirmLoading:u,okText:"Schedule",cancelText:"Cancel",okButtonProps:{style:{backgroundColor:"#6366f1",borderColor:"#6366f1",color:"white"}},children:[(0,s.jsx)("div",{style:{marginBottom:16},children:(0,s.jsx)(ed,{children:"Set up automatic reload of price data every:"})}),(0,s.jsx)("div",{style:{marginBottom:16},children:(0,s.jsx)(Y.Z,{min:1,max:168,value:v,onChange:e=>b(e||6),addonAfter:"hours",style:{width:"100%"}})}),(0,s.jsx)("div",{children:(0,s.jsxs)(ed,{type:"secondary",children:["This will automatically fetch the latest pricing data from the remote source every ",v," hours."]})})]})]})},em=()=>{let{accessToken:e}=(0,n.Z)(),{refetch:l}=m();return(0,s.jsx)(z.Z,{children:(0,s.jsxs)("div",{className:"p-6",children:[(0,s.jsxs)("div",{className:"mb-6",children:[(0,s.jsx)(W.Z,{children:"Price Data Management"}),(0,s.jsx)(D.Z,{className:"text-tremor-content",children:"Manage model pricing data and configure automatic reload schedules"})]}),(0,s.jsx)(ec,{accessToken:e,onReloadSuccess:()=>{l()},buttonText:"Reload Price Data",size:"middle",type:"primary",className:"w-full"})]})})};let eu=async(e,l,t)=>{try{var s,a;console.log("handling submit for formValues:",e);let l=e.model_mappings||[];if("model_mappings"in e&&delete e.model_mappings,e.model&&e.model.includes("all-wildcard")){let t=e.custom_llm_provider,a=(null!==(s=L.fK[t])&&void 0!==s?s:t.toLowerCase())+"/*";e.model_name=a,l.push({public_name:a,litellm_model:a}),e.model=a}let t=[];for(let s of l){let l={},r={},i=s.public_name;for(let[t,i]of(l.model=s.litellm_model,e.input_cost_per_token&&(e.input_cost_per_token=Number(e.input_cost_per_token)/1e6),e.output_cost_per_token&&(e.output_cost_per_token=Number(e.output_cost_per_token)/1e6),l.model=s.litellm_model,console.log("formValues add deployment:",e),Object.entries(e)))if(""!==i&&"custom_pricing"!==t&&"pricing_model"!==t&&"cache_control"!==t){if("model_name"==t)l.model=i;else if("custom_llm_provider"==t){console.log("custom_llm_provider:",i);let e=null!==(a=L.fK[i])&&void 0!==a?a:i.toLowerCase();l.custom_llm_provider=e,console.log("custom_llm_provider mappingResult:",e)}else if("model"==t)continue;else if("base_model"===t)r[t]=i;else if("team_id"===t)r.team_id=i;else if("model_access_group"===t)r.access_groups=i;else if("mode"==t)console.log("placing mode in modelInfo"),r.mode=i,delete l.mode;else if("custom_model_name"===t)l.model=i;else if("litellm_extra_params"==t){console.log("litellm_extra_params:",i);let e={};if(i&&void 0!=i){try{e=JSON.parse(i)}catch(e){throw eo.Z.fromBackend("Failed to parse LiteLLM Extra Params: "+e),Error("Failed to parse litellm_extra_params: "+e)}for(let[t,s]of Object.entries(e))l[t]=s}}else if("model_info_params"==t){console.log("model_info_params:",i);let e={};if(i&&void 0!=i){try{e=JSON.parse(i)}catch(e){throw eo.Z.fromBackend("Failed to parse LiteLLM Extra Params: "+e),Error("Failed to parse litellm_extra_params: "+e)}for(let[l,t]of Object.entries(e))r[l]=t}}else if("input_cost_per_token"===t||"output_cost_per_token"===t||"input_cost_per_second"===t){i&&(l[t]=Number(i));continue}else l[t]=i}t.push({litellmParamsObj:l,modelInfoObj:r,modelName:i})}return t}catch(e){eo.Z.fromBackend("Failed to create model: "+e)}},eh=async(e,l,t,s)=>{try{let r=await eu(e,l,t);if(!r||0===r.length)return;for(let e of r){let{litellmParamsObj:t,modelInfoObj:s,modelName:r}=e,i={model_name:r,litellm_params:t,model_info:s},n=await (0,a.modelCreateCall)(l,i);console.log("response for model create call: ".concat(n.data))}s&&s(),t.resetFields()}catch(e){eo.Z.fromBackend("Failed to add model: "+e)}};var ex=t(53410),ep=t(62490),eg=t(10032),ef=t(21609),ej=t(31283),ev=t(37592);let e_=(0,i.n)("providerFields"),eb=()=>(0,r.a)({queryKey:e_.list({}),queryFn:async()=>await (0,a.getProviderCreateMetadata)(),staleTime:864e5,gcTime:864e5});var ey=t(3632),eN=t(56522),ew=t(47451),eZ=t(69410),eC=t(65319),ek=t(4260);let{Link:eS}=Q.default,eA=e=>{var l,t,s,a,r;let i="password"===e.field_type?"password":"select"===e.field_type?"select":"upload"===e.field_type?"upload":"textarea"===e.field_type?"textarea":"text";return{key:e.key,label:e.label,placeholder:null!==(l=e.placeholder)&&void 0!==l?l:void 0,tooltip:null!==(t=e.tooltip)&&void 0!==t?t:void 0,required:null!==(s=e.required)&&void 0!==s&&s,type:i,options:null!==(a=e.options)&&void 0!==a?a:void 0,defaultValue:null!==(r=e.default_value)&&void 0!==r?r:void 0}},eE={};var eP=e=>{let{selectedProvider:l,uploadProps:t}=e,a=L.Cl[l],r=eg.Z.useFormInstance(),{data:i,isLoading:n,error:o}=eb(),d=f.useMemo(()=>{if(!i)return null;let e={};return i.forEach(l=>{let t=l.provider_display_name,s=l.credential_fields.map(eA);e[t]=s,l.provider&&(e[l.provider]=s),l.litellm_provider&&(e[l.litellm_provider]=s)}),e},[i]);f.useEffect(()=>{d&&Object.assign(eE,d)},[d]);let c=f.useMemo(()=>{var e;let t=null!==(e=eE[a])&&void 0!==e?e:eE[l];if(t)return t;if(!i)return[];let s=i.find(e=>e.provider_display_name===a||e.provider===l||e.litellm_provider===l);if(!s)return[];let r=s.credential_fields.map(eA);return eE[s.provider_display_name]=r,s.provider&&(eE[s.provider]=r),s.litellm_provider&&(eE[s.litellm_provider]=r),r},[a,l,i]),m={name:"file",accept:".json",beforeUpload:e=>{if("application/json"===e.type){let l=new FileReader;l.onload=e=>{if(e.target){let l=e.target.result;console.log("Setting field value from JSON, length: ".concat(l.length)),r.setFieldsValue({vertex_credentials:l}),console.log("Form values after setting:",r.getFieldsValue())}},l.readAsText(e)}return!1},onChange(e){console.log("Upload onChange triggered in ProviderSpecificFields"),console.log("Current form values:",r.getFieldsValue()),"uploading"!==e.file.status&&console.log(e.file,e.fileList)}};return(0,s.jsxs)(s.Fragment,{children:[n&&0===c.length&&(0,s.jsx)(ew.Z,{children:(0,s.jsx)(eZ.Z,{span:24,children:(0,s.jsx)(eN.x,{className:"mb-2",children:"Loading provider fields..."})})}),o&&0===c.length&&(0,s.jsx)(ew.Z,{children:(0,s.jsx)(eZ.Z,{span:24,children:(0,s.jsx)(eN.x,{className:"mb-2 text-red-500",children:o instanceof Error?o.message:"Failed to load provider credential fields"})})}),c.map(e=>{var l;return(0,s.jsxs)(f.Fragment,{children:[(0,s.jsx)(eg.Z.Item,{label:e.label,name:e.key,rules:e.required?[{required:!0,message:"Required"}]:void 0,tooltip:e.tooltip,className:"vertex_credentials"===e.key?"mb-0":void 0,children:"select"===e.type?(0,s.jsx)(ev.default,{placeholder:e.placeholder,defaultValue:e.defaultValue,children:null===(l=e.options)||void 0===l?void 0:l.map(e=>(0,s.jsx)(ev.default.Option,{value:e,children:e},e))}):"upload"===e.type?(0,s.jsx)(eC.default,{...m,onChange:l=>{(null==t?void 0:t.onChange)&&t.onChange(l),setTimeout(()=>{let l=r.getFieldValue(e.key);console.log("".concat(e.key," value after upload:"),JSON.stringify(l))},500)},children:(0,s.jsx)(_.ZP,{icon:(0,s.jsx)(ey.Z,{}),children:"Click to Upload"})}):"textarea"===e.type?(0,s.jsx)(ek.default.TextArea,{placeholder:e.placeholder,defaultValue:e.defaultValue,rows:6,style:{fontFamily:"monospace",fontSize:"12px"}}):(0,s.jsx)(eN.o,{placeholder:e.placeholder,type:"password"===e.type?"password":"text",defaultValue:e.defaultValue})}),"vertex_credentials"===e.key&&(0,s.jsx)(ew.Z,{children:(0,s.jsx)(eZ.Z,{children:(0,s.jsx)(eN.x,{className:"mb-3 mt-1",children:"Give a gcp service account(.json file)"})})}),"base_model"===e.key&&(0,s.jsxs)(ew.Z,{children:[(0,s.jsx)(eZ.Z,{span:10}),(0,s.jsx)(eZ.Z,{span:10,children:(0,s.jsxs)(eN.x,{className:"mb-2",children:["The actual model your azure deployment uses. Used for accurate cost tracking. Select name from"," ",(0,s.jsx)(eS,{href:"https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json",target:"_blank",children:"here"})]})})]})]},e.key)})]})};let{Link:eM}=Q.default;var eL=e=>{let{open:l,onCancel:t,onAddCredential:a,uploadProps:r}=e,[i]=eg.Z.useForm(),[n,o]=(0,f.useState)(L.Cl.OpenAI);return(0,s.jsx)(ea.Z,{title:"Add New Credential",open:l,onCancel:()=>{t(),i.resetFields()},footer:null,width:600,children:(0,s.jsxs)(eg.Z,{form:i,onFinish:e=>{a(Object.entries(e).reduce((e,l)=>{let[t,s]=l;return""!==s&&null!=s&&(e[t]=s),e},{})),i.resetFields()},layout:"vertical",children:[(0,s.jsx)(eg.Z.Item,{label:"Credential Name:",name:"credential_name",rules:[{required:!0,message:"Credential name is required"}],children:(0,s.jsx)(ej.o,{placeholder:"Enter a friendly name for these credentials"})}),(0,s.jsx)(eg.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Provider:",name:"custom_llm_provider",tooltip:"Helper to auto-populate provider specific fields",children:(0,s.jsx)(ev.default,{showSearch:!0,onChange:e=>{o(e),i.setFieldValue("custom_llm_provider",e)},children:Object.entries(L.Cl).map(e=>{let[l,t]=e;return(0,s.jsx)(ev.default.Option,{value:l,children:(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,s.jsx)("img",{src:L.cd[t],alt:"".concat(l," logo"),className:"w-5 h-5",onError:e=>{let l=e.target,s=l.parentElement;if(s){let e=document.createElement("div");e.className="w-5 h-5 rounded-full bg-gray-200 flex items-center justify-center text-xs",e.textContent=t.charAt(0),s.replaceChild(e,l)}}}),(0,s.jsx)("span",{children:t})]})},l)})})}),(0,s.jsx)(eP,{selectedProvider:n,uploadProps:r}),(0,s.jsxs)("div",{className:"flex justify-between items-center",children:[(0,s.jsx)(M.Z,{title:"Get help on our github",children:(0,s.jsx)(eM,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)(_.ZP,{onClick:()=>{t(),i.resetFields()},style:{marginRight:10},children:"Cancel"}),(0,s.jsx)(_.ZP,{htmlType:"submit",children:"Add Credential"})]})]})]})})};let{Link:eF}=Q.default;function eI(e){let{open:l,onCancel:t,onUpdateCredential:a,uploadProps:r,existingCredential:i}=e,[n]=eg.Z.useForm(),[o,d]=(0,f.useState)(L.Cl.Anthropic);return(0,f.useEffect)(()=>{if(i){let e=Object.entries(i.credential_values||{}).reduce((e,l)=>{let[t,s]=l;return e[t]=null!=s?s:null,e},{});n.setFieldsValue({credential_name:i.credential_name,custom_llm_provider:i.credential_info.custom_llm_provider,...e}),d(i.credential_info.custom_llm_provider)}},[i]),(0,s.jsx)(ea.Z,{title:"Edit Credential",open:l,onCancel:()=>{t(),n.resetFields()},footer:null,width:600,destroyOnHidden:!0,children:(0,s.jsxs)(eg.Z,{form:n,onFinish:e=>{a(Object.entries(e).reduce((e,l)=>{let[t,s]=l;return""!==s&&null!=s&&(e[t]=s),e},{})),n.resetFields()},layout:"vertical",children:[(0,s.jsx)(eg.Z.Item,{label:"Credential Name:",name:"credential_name",rules:[{required:!0,message:"Credential name is required"}],initialValue:null==i?void 0:i.credential_name,children:(0,s.jsx)(ej.o,{placeholder:"Enter a friendly name for these credentials",disabled:null!=i&&!!i.credential_name})}),(0,s.jsx)(eg.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Provider:",name:"custom_llm_provider",tooltip:"Helper to auto-populate provider specific fields",children:(0,s.jsx)(ev.default,{showSearch:!0,onChange:e=>{d(e),n.setFieldValue("custom_llm_provider",e)},children:Object.entries(L.Cl).map(e=>{let[l,t]=e;return(0,s.jsx)(ev.default.Option,{value:l,children:(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,s.jsx)("img",{src:L.cd[t],alt:"".concat(l," logo"),className:"w-5 h-5",onError:e=>{let l=e.target,s=l.parentElement;if(s){let e=document.createElement("div");e.className="w-5 h-5 rounded-full bg-gray-200 flex items-center justify-center text-xs",e.textContent=t.charAt(0),s.replaceChild(e,l)}}}),(0,s.jsx)("span",{children:t})]})},l)})})}),(0,s.jsx)(eP,{selectedProvider:o,uploadProps:r}),(0,s.jsxs)("div",{className:"flex justify-between items-center",children:[(0,s.jsx)(M.Z,{title:"Get help on our github",children:(0,s.jsx)(eF,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)(_.ZP,{onClick:()=>{t(),n.resetFields()},style:{marginRight:10},children:"Cancel"}),(0,s.jsx)(_.ZP,{htmlType:"submit",children:"Update Credential"})]})]})]})})}var eT=e=>{var l;let{uploadProps:t}=e,{accessToken:r}=(0,n.Z)(),{data:i,refetch:o}=d(),c=(null==i?void 0:i.credentials)||[],[m,u]=(0,f.useState)(!1),[h,x]=(0,f.useState)(!1),[p,g]=(0,f.useState)(null),[j,v]=(0,f.useState)(null),[_,b]=(0,f.useState)(!1),[y,N]=(0,f.useState)(!1),[w]=eg.Z.useForm(),Z=["credential_name","custom_llm_provider"],C=async e=>{if(!r)return;let l=Object.entries(e).filter(e=>{let[l]=e;return!Z.includes(l)}).reduce((e,l)=>{let[t,s]=l;return{...e,[t]:s}},{}),t={credential_name:e.credential_name,credential_values:l,credential_info:{custom_llm_provider:e.custom_llm_provider}};await (0,a.credentialUpdateCall)(r,e.credential_name,t),eo.Z.success("Credential updated successfully"),x(!1),await o()},k=async e=>{if(!r)return;let l=Object.entries(e).filter(e=>{let[l]=e;return!Z.includes(l)}).reduce((e,l)=>{let[t,s]=l;return{...e,[t]:s}},{}),t={credential_name:e.credential_name,credential_values:l,credential_info:{custom_llm_provider:e.custom_llm_provider}};await (0,a.credentialCreateCall)(r,t),eo.Z.success("Credential added successfully"),u(!1),await o()},A=e=>{let l={openai:"blue",azure:"indigo",anthropic:"purple",default:"gray"},t=l[e.toLowerCase()]||l.default;return(0,s.jsx)(ep.Ct,{color:t,size:"xs",children:e})},E=async()=>{if(r&&j){N(!0);try{await (0,a.credentialDeleteCall)(r,j.credential_name),eo.Z.success("Credential deleted successfully"),await o()}catch(e){eo.Z.error("Failed to delete credential")}finally{v(null),b(!1),N(!1)}}},P=e=>{v(e),b(!0)};return(0,s.jsxs)("div",{className:"w-full mx-auto flex-auto overflow-y-auto p-2",children:[(0,s.jsx)(ep.zx,{onClick:()=>u(!0),children:"Add Credential"}),(0,s.jsx)("div",{className:"flex justify-between items-center mt-4 mb-4",children:(0,s.jsx)(ep.xv,{children:"Configured credentials for different AI providers. Add and manage your API credentials."})}),(0,s.jsx)(ep.Zb,{children:(0,s.jsxs)(ep.iA,{children:[(0,s.jsx)(ep.ss,{children:(0,s.jsxs)(ep.SC,{children:[(0,s.jsx)(ep.xs,{children:"Credential Name"}),(0,s.jsx)(ep.xs,{children:"Provider"}),(0,s.jsx)(ep.xs,{children:"Actions"})]})}),(0,s.jsx)(ep.RM,{children:c&&0!==c.length?c.map((e,l)=>{var t;return(0,s.jsxs)(ep.SC,{children:[(0,s.jsx)(ep.pj,{children:e.credential_name}),(0,s.jsx)(ep.pj,{children:A((null===(t=e.credential_info)||void 0===t?void 0:t.custom_llm_provider)||"-")}),(0,s.jsxs)(ep.pj,{children:[(0,s.jsx)(ep.zx,{icon:ex.Z,variant:"light",size:"sm",onClick:()=>{g(e),x(!0)}}),(0,s.jsx)(ep.zx,{icon:S.Z,variant:"light",size:"sm",onClick:()=>P(e),className:"ml-2"})]})]},l)}):(0,s.jsx)(ep.SC,{children:(0,s.jsx)(ep.pj,{colSpan:4,className:"text-center py-4 text-gray-500",children:"No credentials configured"})})})]})}),m&&(0,s.jsx)(eL,{onAddCredential:k,open:m,onCancel:()=>u(!1),uploadProps:t}),h&&(0,s.jsx)(eI,{open:h,existingCredential:p,onUpdateCredential:C,uploadProps:t,onCancel:()=>x(!1)}),(0,s.jsx)(ef.Z,{isOpen:_,onCancel:()=>{v(null),b(!1)},onOk:E,title:"Delete Credential?",message:"Are you sure you want to delete this credential? This action cannot be undone and may break existing integrations.",resourceInformationTitle:"Credential Information",resourceInformation:[{label:"Credential Name",value:null==j?void 0:j.credential_name},{label:"Provider",value:(null==j?void 0:null===(l=j.credential_info)||void 0===l?void 0:l.custom_llm_provider)||"-"}],confirmLoading:y,requiredConfirmation:null==j?void 0:j.credential_name})]})},eR=t(20347),eO=t(23628),eV=t(29827),eq=t(49804),ez=t(12485),eD=t(18135),eB=t(35242),eG=t(77991),eU=t(34419),eH=t(58643),eK=t(29),eJ=t.n(eK),eW=t(23496),eY=t(35291),e$=t(23639);let{Text:eX}=Q.default;var eQ=e=>{let{formValues:l,accessToken:t,testMode:r,modelName:i="this model",onClose:n,onTestComplete:o}=e,[d,c]=f.useState(null),[m,u]=f.useState(null),[h,x]=f.useState(null),[p,g]=f.useState(!0),[j,v]=f.useState(!1),[b,y]=f.useState(!1),N=async()=>{g(!0),y(!1),c(null),u(null),x(null),v(!1),await new Promise(e=>setTimeout(e,100));try{console.log("Testing connection with form values:",l);let r=await eu(l,t,null);if(!r){console.log("No result from prepareModelAddRequest"),c("Failed to prepare model data. Please check your form inputs."),v(!1),g(!1);return}console.log("Result from prepareModelAddRequest:",r);let{litellmParamsObj:i,modelInfoObj:n,modelName:o}=r[0],d=await (0,a.testConnectionRequest)(t,i,n,null==n?void 0:n.mode);if("success"===d.status)eo.Z.success("Connection test successful!"),c(null),v(!0);else{var e,s;let l=(null===(e=d.result)||void 0===e?void 0:e.error)||d.message||"Unknown error";c(l),u(i),x(null===(s=d.result)||void 0===s?void 0:s.raw_request_typed_dict),v(!1)}}catch(e){console.error("Test connection error:",e),c(e instanceof Error?e.message:String(e)),v(!1)}finally{g(!1),o&&o()}};f.useEffect(()=>{let e=setTimeout(()=>{N()},200);return()=>clearTimeout(e)},[]);let w=e=>e?e.split("stack trace:")[0].trim().replace(/^litellm\.(.*?)Error: /,""):"Unknown error",Z="string"==typeof d?w(d):(null==d?void 0:d.message)?w(d.message):"Unknown error",C=h?((e,l,t)=>{let s=JSON.stringify(l,null,2).split("\n").map(e=>" ".concat(e)).join("\n"),a=Object.entries(t).map(e=>{let[l,t]=e;return"-H '".concat(l,": ").concat(t,"'")}).join(" \\\n ");return"curl -X POST \\\n ".concat(e," \\\n ").concat(a?"".concat(a," \\\n "):"","-H 'Content-Type: application/json' \\\n -d '{\n").concat(s,"\n }'")})(h.raw_request_api_base,h.raw_request_body,h.raw_request_headers||{}):"";return(0,s.jsxs)("div",{style:{padding:"24px",borderRadius:"8px",backgroundColor:"#fff"},children:[p?(0,s.jsxs)("div",{style:{textAlign:"center",padding:"32px 20px"},className:"jsx-dc9a0e2d897fe63b",children:[(0,s.jsx)("div",{style:{marginBottom:"16px"},className:"jsx-dc9a0e2d897fe63b loading-spinner",children:(0,s.jsx)("div",{style:{border:"3px solid #f3f3f3",borderTop:"3px solid #1890ff",borderRadius:"50%",width:"30px",height:"30px",animation:"spin 1s linear infinite",margin:"0 auto"},className:"jsx-dc9a0e2d897fe63b"})}),(0,s.jsxs)(eX,{style:{fontSize:"16px"},children:["Testing connection to ",i,"..."]}),(0,s.jsx)(eJ(),{id:"dc9a0e2d897fe63b",children:"@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}"})]}):j?(0,s.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",padding:"32px 20px"},children:[(0,s.jsx)("div",{style:{color:"#52c41a",fontSize:"24px",display:"flex",alignItems:"center"},children:(0,s.jsx)("svg",{viewBox:"64 64 896 896",focusable:"false","data-icon":"check-circle",width:"1em",height:"1em",fill:"currentColor","aria-hidden":"true",children:(0,s.jsx)("path",{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"})})}),(0,s.jsxs)(eX,{type:"success",style:{fontSize:"18px",fontWeight:500,marginLeft:"10px"},children:["Connection to ",i," successful!"]})]}):(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{style:{display:"flex",alignItems:"center",marginBottom:"20px"},children:[(0,s.jsx)(eY.Z,{style:{color:"#ff4d4f",fontSize:"24px",marginRight:"12px"}}),(0,s.jsxs)(eX,{type:"danger",style:{fontSize:"18px",fontWeight:500},children:["Connection to ",i," failed"]})]}),(0,s.jsxs)("div",{style:{backgroundColor:"#fff2f0",border:"1px solid #ffccc7",borderRadius:"8px",padding:"16px",marginBottom:"20px",boxShadow:"0 1px 2px rgba(0, 0, 0, 0.03)"},children:[(0,s.jsxs)(eX,{strong:!0,style:{display:"block",marginBottom:"8px"},children:["Error:"," "]}),(0,s.jsx)(eX,{type:"danger",style:{fontSize:"14px",lineHeight:"1.5"},children:Z}),d&&(0,s.jsx)("div",{style:{marginTop:"12px"},children:(0,s.jsx)(_.ZP,{type:"link",onClick:()=>y(!b),style:{paddingLeft:0,height:"auto"},children:b?"Hide Details":"Show Details"})})]}),b&&(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)(eX,{strong:!0,style:{display:"block",marginBottom:"8px",fontSize:"15px"},children:"Troubleshooting Details"}),(0,s.jsx)("pre",{style:{backgroundColor:"#f5f5f5",padding:"16px",borderRadius:"8px",fontSize:"13px",maxHeight:"200px",overflow:"auto",border:"1px solid #e8e8e8",lineHeight:"1.5"},children:"string"==typeof d?d:JSON.stringify(d,null,2)})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(eX,{strong:!0,style:{display:"block",marginBottom:"8px",fontSize:"15px"},children:"API Request"}),(0,s.jsx)("pre",{style:{backgroundColor:"#f5f5f5",padding:"16px",borderRadius:"8px",fontSize:"13px",maxHeight:"250px",overflow:"auto",border:"1px solid #e8e8e8",lineHeight:"1.5"},children:C||"No request data available"}),(0,s.jsx)(_.ZP,{style:{marginTop:"8px"},icon:(0,s.jsx)(e$.Z,{}),onClick:()=>{navigator.clipboard.writeText(C||""),eo.Z.success("Copied to clipboard")},children:"Copy to Clipboard"})]})]})}),(0,s.jsx)(eW.Z,{style:{margin:"24px 0 16px"}}),(0,s.jsx)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:(0,s.jsx)(_.ZP,{type:"link",href:"https://docs.litellm.ai/docs/providers",target:"_blank",icon:(0,s.jsx)(R.Z,{}),children:"View Documentation"})})]})};let e0=async(e,l,t,s)=>{try{console.log("=== AUTO ROUTER SUBMIT HANDLER CALLED ==="),console.log("handling auto router submit for formValues:",e),console.log("Access token:",l?"Present":"Missing"),console.log("Form:",t?"Present":"Missing"),console.log("Callback:",s?"Present":"Missing");let r={model_name:e.auto_router_name,litellm_params:{model:"auto_router/".concat(e.auto_router_name),auto_router_config:JSON.stringify(e.auto_router_config),auto_router_default_model:e.auto_router_default_model},model_info:{}};e.auto_router_embedding_model&&"custom"!==e.auto_router_embedding_model?r.litellm_params.auto_router_embedding_model=e.auto_router_embedding_model:e.custom_embedding_model&&(r.litellm_params.auto_router_embedding_model=e.custom_embedding_model),e.team_id&&(r.model_info.team_id=e.team_id),e.model_access_group&&e.model_access_group.length>0&&(r.model_info.access_groups=e.model_access_group),console.log("Auto router configuration to be created:",r),console.log("Auto router config (stringified):",r.litellm_params.auto_router_config),console.log("Calling modelCreateCall with:",{accessToken:l?"Present":"Missing",config:r});let i=await (0,a.modelCreateCall)(l,r);console.log("response for auto router create call:",i),t.resetFields()}catch(e){console.error("Failed to add auto router:",e),eo.Z.fromBackend("Failed to add auto router: "+e)}};var e1=t(10703),e2=t(44851),e4=t(96473),e5=t(70464),e6=t(26349),e3=t(92280);let{TextArea:e8}=ek.default,{Panel:e7}=e2.default;var e9=e=>{let{modelInfo:l,value:t,onChange:a}=e,[r,i]=(0,f.useState)([]),[n,o]=(0,f.useState)(!1),[d,c]=(0,f.useState)([]);(0,f.useEffect)(()=>{if(null==t?void 0:t.routes){let e=t.routes.map((e,l)=>({id:e.id||"route-".concat(l,"-").concat(Date.now()),model:e.name||e.model||"",utterances:e.utterances||[],description:e.description||"",score_threshold:e.score_threshold||.5}));i(e),c(e.map(e=>e.id))}else i([]),c([])},[t]);let m=e=>{let l=r.filter(l=>l.id!==e);i(l),h(l),c(l=>l.filter(l=>l!==e))},u=(e,l,t)=>{let s=r.map(s=>s.id===e?{...s,[l]:t}:s);i(s),h(s)},h=e=>{let l={routes:e.map(e=>({name:e.model,utterances:e.utterances,description:e.description,score_threshold:e.score_threshold}))};null==a||a(l)},x=l.map(e=>({value:e.model_group,label:e.model_group}));return(0,s.jsxs)("div",{className:"w-full max-w-none",children:[(0,s.jsxs)("div",{className:"flex justify-between items-center mb-6 w-full",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)(e3.x,{className:"text-lg font-semibold",children:"Routes Configuration"}),(0,s.jsx)(M.Z,{title:"Configure routing logic to automatically select the best model based on user input patterns",children:(0,s.jsx)(R.Z,{className:"text-gray-400"})})]}),(0,s.jsx)(_.ZP,{type:"primary",icon:(0,s.jsx)(e4.Z,{}),onClick:()=>{let e="route-".concat(Date.now()),l=[...r,{id:e,model:"",utterances:[],description:"",score_threshold:.5}];i(l),h(l),c(l=>[...l,e])},className:"bg-blue-600 hover:bg-blue-700",children:"Add Route"})]}),0===r.length?(0,s.jsx)("div",{className:"text-center py-12 text-gray-500 bg-gray-50 rounded-lg border-2 border-dashed border-gray-200 mb-6",children:(0,s.jsx)(e3.x,{children:"No routes configured. Click ā€œAdd Routeā€ to get started."})}):(0,s.jsx)("div",{className:"space-y-3 mb-6 w-full",children:r.map((e,l)=>(0,s.jsx)(et.Z,{className:"border border-gray-200 shadow-sm w-full",bodyStyle:{padding:0},children:(0,s.jsx)(e2.default,{ghost:!0,expandIcon:e=>{let{isActive:l}=e;return(0,s.jsx)(e5.Z,{rotate:l?180:0})},activeKey:d,onChange:e=>c(Array.isArray(e)?e:[e].filter(Boolean)),items:[{key:e.id,label:(0,s.jsxs)("div",{className:"flex justify-between items-center py-2",children:[(0,s.jsxs)(e3.x,{className:"font-medium text-base",children:["Route ",l+1,": ",e.model||"Unnamed"]}),(0,s.jsx)(_.ZP,{type:"text",danger:!0,icon:(0,s.jsx)(e6.Z,{}),onClick:l=>{l.stopPropagation(),m(e.id)},className:"mr-2"})]}),children:(0,s.jsxs)("div",{className:"px-6 pb-6 w-full",children:[(0,s.jsxs)("div",{className:"mb-4 w-full",children:[(0,s.jsx)(e3.x,{className:"text-sm font-medium mb-2 block",children:"Model"}),(0,s.jsx)(ev.default,{value:e.model,onChange:l=>u(e.id,"model",l),placeholder:"Select model",showSearch:!0,style:{width:"100%"},options:x})]}),(0,s.jsxs)("div",{className:"mb-4 w-full",children:[(0,s.jsx)(e3.x,{className:"text-sm font-medium mb-2 block",children:"Description"}),(0,s.jsx)(e8,{value:e.description,onChange:l=>u(e.id,"description",l.target.value),placeholder:"Describe when this route should be used...",rows:2,style:{width:"100%"}})]}),(0,s.jsxs)("div",{className:"mb-4 w-full",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 mb-2",children:[(0,s.jsx)(e3.x,{className:"text-sm font-medium",children:"Score Threshold"}),(0,s.jsx)(M.Z,{title:"Minimum similarity score to route to this model (0-1)",children:(0,s.jsx)(R.Z,{className:"text-gray-400"})})]}),(0,s.jsx)(Y.Z,{value:e.score_threshold,onChange:l=>u(e.id,"score_threshold",l||0),min:0,max:1,step:.1,style:{width:"100%"},placeholder:"0.5"})]}),(0,s.jsxs)("div",{className:"w-full",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 mb-2",children:[(0,s.jsx)(e3.x,{className:"text-sm font-medium",children:"Example Utterances"}),(0,s.jsx)(M.Z,{title:"Training examples for this route. Type an utterance and press Enter to add it.",children:(0,s.jsx)(R.Z,{className:"text-gray-400"})})]}),(0,s.jsx)(e3.x,{className:"text-xs text-gray-500 mb-2",children:"Type an utterance and press Enter to add it. You can also paste multiple lines."}),(0,s.jsx)(ev.default,{mode:"tags",value:e.utterances,onChange:l=>u(e.id,"utterances",l),placeholder:"Type an utterance and press Enter...",style:{width:"100%"},tokenSeparators:["\n"],maxTagCount:"responsive",allowClear:!0})]})]})}]})},e.id))}),(0,s.jsxs)("div",{className:"border-t pt-6 w-full",children:[(0,s.jsxs)("div",{className:"flex justify-between items-center mb-4 w-full",children:[(0,s.jsx)(e3.x,{className:"text-lg font-semibold",children:"JSON Preview"}),(0,s.jsx)(_.ZP,{type:"link",onClick:()=>o(!n),className:"text-blue-600 p-0",children:n?"Hide":"Show"})]}),n&&(0,s.jsx)(et.Z,{className:"bg-gray-50 w-full",children:(0,s.jsx)("pre",{className:"text-sm overflow-auto max-h-64 w-full",children:JSON.stringify({routes:r.map(e=>({name:e.model,utterances:e.utterances,description:e.description,score_threshold:e.score_threshold}))},null,2)})})]})]})};let{Title:le,Link:ll}=Q.default;var lt=e=>{let{form:l,handleOk:t,accessToken:r,userRole:i}=e,[n,o]=(0,f.useState)(!1),[d,c]=(0,f.useState)(!1),[m,u]=(0,f.useState)(""),[h,x]=(0,f.useState)([]),[p,g]=(0,f.useState)([]),[j,v]=(0,f.useState)(!1),[b,y]=(0,f.useState)(!1),[N,w]=(0,f.useState)(null);(0,f.useEffect)(()=>{(async()=>{x((await (0,a.modelAvailableCall)(r,"","",!1,null,!0,!0)).data.map(e=>e.id))})()},[r]),(0,f.useEffect)(()=>{(async()=>{try{let e=await (0,e1.p)(r);console.log("Fetched models for auto router:",e),g(e)}catch(e){console.error("Error fetching model info for auto router:",e)}})()},[r]);let Z=eR.ZL.includes(i),C=async()=>{c(!0),u("test-".concat(Date.now())),o(!0)},k=()=>{console.log("Auto router submit triggered!"),console.log("Router config:",N);let e=l.getFieldsValue();if(console.log("Form values:",e),!e.auto_router_name){eo.Z.fromBackend("Please enter an Auto Router Name");return}if(!e.auto_router_default_model){eo.Z.fromBackend("Please select a Default Model");return}if(l.setFieldsValue({custom_llm_provider:"auto_router",model:e.auto_router_name,api_key:"not_required_for_auto_router"}),!N||!N.routes||0===N.routes.length){eo.Z.fromBackend("Please configure at least one route for the auto router");return}if(N.routes.filter(e=>!e.name||!e.description||0===e.utterances.length).length>0){eo.Z.fromBackend("Please ensure all routes have a target model, description, and at least one utterance");return}l.validateFields().then(e=>{console.log("Form validation passed, submitting with values:",e);let s={...e,auto_router_config:N};console.log("Final submit values:",s),e0(s,r,l,t)}).catch(e=>{console.error("Validation failed:",e);let l=e.errorFields||[];if(l.length>0){let e=l.map(e=>{let l=e.name[0];return({auto_router_name:"Auto Router Name",auto_router_default_model:"Default Model",auto_router_embedding_model:"Embedding Model"})[l]||l});eo.Z.fromBackend("Please fill in the following required fields: ".concat(e.join(", ")))}else eo.Z.fromBackend("Please fill in all required fields")})};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(le,{level:2,children:"Add Auto Router"}),(0,s.jsx)(eN.x,{className:"text-gray-600 mb-6",children:"Create an auto router with intelligent routing logic that automatically selects the best model based on user input patterns and semantic matching."}),(0,s.jsx)(et.Z,{children:(0,s.jsxs)(eg.Z,{form:l,onFinish:k,labelCol:{span:10},wrapperCol:{span:16},labelAlign:"left",children:[(0,s.jsx)(eg.Z.Item,{rules:[{required:!0,message:"Auto router name is required"}],label:"Auto Router Name",name:"auto_router_name",tooltip:"Unique name for this auto router configuration",labelCol:{span:10},labelAlign:"left",children:(0,s.jsx)(eN.o,{placeholder:"e.g., auto_router_1, smart_routing"})}),(0,s.jsx)("div",{className:"w-full mb-4",children:(0,s.jsx)(e9,{modelInfo:p,value:N,onChange:e=>{w(e),l.setFieldValue("auto_router_config",e)}})}),(0,s.jsx)(eg.Z.Item,{rules:[{required:!0,message:"Default model is required"}],label:"Default Model",name:"auto_router_default_model",tooltip:"Fallback model to use when auto routing logic cannot determine the best model",labelCol:{span:10},labelAlign:"left",children:(0,s.jsx)(ev.default,{placeholder:"Select a default model",onChange:e=>{v("custom"===e)},options:[...Array.from(new Set(p.map(e=>e.model_group))).map(e=>({value:e,label:e})),{value:"custom",label:"Enter custom model name"}],style:{width:"100%"},showSearch:!0})}),(0,s.jsx)(eg.Z.Item,{label:"Embedding Model",name:"auto_router_embedding_model",tooltip:"Optional: Embedding model to use for semantic routing decisions",labelCol:{span:10},labelAlign:"left",children:(0,s.jsx)(ev.default,{value:l.getFieldValue("auto_router_embedding_model"),placeholder:"Select an embedding model (optional)",onChange:e=>{y("custom"===e),l.setFieldValue("auto_router_embedding_model",e)},options:[...Array.from(new Set(p.map(e=>e.model_group))).map(e=>({value:e,label:e})),{value:"custom",label:"Enter custom model name"}],style:{width:"100%"},showSearch:!0,allowClear:!0})}),(0,s.jsxs)("div",{className:"flex items-center my-4",children:[(0,s.jsx)("div",{className:"flex-grow border-t border-gray-200"}),(0,s.jsx)("span",{className:"px-4 text-gray-500 text-sm",children:"Additional Settings"}),(0,s.jsx)("div",{className:"flex-grow border-t border-gray-200"})]}),Z&&(0,s.jsx)(eg.Z.Item,{label:"Model Access Group",name:"model_access_group",className:"mb-4",tooltip:"Use model access groups to control who can access this auto router",children:(0,s.jsx)(ev.default,{mode:"tags",showSearch:!0,placeholder:"Select existing groups or type to create new ones",optionFilterProp:"children",tokenSeparators:[","],options:h.map(e=>({value:e,label:e})),maxTagCount:"responsive",allowClear:!0})}),(0,s.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,s.jsx)(M.Z,{title:"Get help on our github",children:(0,s.jsx)(Q.default.Link,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})}),(0,s.jsxs)("div",{className:"space-x-2",children:[(0,s.jsx)(_.ZP,{onClick:C,loading:d,children:"Test Connect"}),(0,s.jsx)(_.ZP,{onClick:()=>{console.log("Add Auto Router button clicked!"),console.log("Current router config:",N),console.log("Current form values:",l.getFieldsValue()),k()},children:"Add Auto Router"})]})]})]})}),(0,s.jsx)(ea.Z,{title:"Connection Test Results",open:n,onCancel:()=>{o(!1),c(!1)},footer:[(0,s.jsx)(_.ZP,{onClick:()=>{o(!1),c(!1)},children:"Close"},"close")],width:700,children:n&&(0,s.jsx)(eQ,{formValues:l.getFieldsValue(),accessToken:r,testMode:"chat",modelName:l.getFieldValue("auto_router_name"),onClose:()=>{o(!1),c(!1)},onTestComplete:()=>c(!1)},m)})]})};let ls=(0,i.n)("guardrails"),la=()=>{let{accessToken:e,userId:l,userRole:t}=(0,n.Z)();return(0,r.a)({queryKey:ls.list({}),queryFn:async()=>(await (0,a.getGuardrailsList)(e)).guardrails.map(e=>e.guardrail_name),enabled:!!(e&&l&&t)})},lr=(0,i.n)("tags"),li=()=>{let{accessToken:e,userId:l,userRole:t}=(0,n.Z)();return(0,r.a)({queryKey:lr.list({}),queryFn:async()=>await (0,a.tagListCall)(e),enabled:!!(e&&l&&t)})};var ln=t(59341),lo=t(51653),ld=t(84376),lc=t(63709),lm=t(26210),lu=t(34766),lh=t(45246),lx=t(24199);let{Text:lp}=Q.default;var lg=e=>{let{form:l,showCacheControl:t,onCacheControlChange:a}=e,r=e=>{let t=l.getFieldValue("litellm_extra_params");try{let s=t?JSON.parse(t):{};e.length>0?s.cache_control_injection_points=e:delete s.cache_control_injection_points,Object.keys(s).length>0?l.setFieldValue("litellm_extra_params",JSON.stringify(s,null,2)):l.setFieldValue("litellm_extra_params","")}catch(e){console.error("Error updating cache control points:",e)}};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(eg.Z.Item,{label:"Cache Control Injection Points",name:"cache_control",valuePropName:"checked",className:"mb-4",tooltip:"Tell litellm where to inject cache control checkpoints. You can specify either by role (to apply to all messages of that role) or by specific message index.",children:(0,s.jsx)(lc.Z,{onChange:a,className:"bg-gray-600"})}),t&&(0,s.jsxs)("div",{className:"ml-6 pl-4 border-l-2 border-gray-200",children:[(0,s.jsx)(lp,{className:"text-sm text-gray-500 block mb-4",children:"Providers like Anthropic, Bedrock API require users to specify where to inject cache control checkpoints, litellm can automatically add them for you as a cost saving feature."}),(0,s.jsx)(eg.Z.List,{name:"cache_control_injection_points",initialValue:[{location:"message"}],children:(e,t)=>{let{add:a,remove:i}=t;return(0,s.jsxs)(s.Fragment,{children:[e.map((t,a)=>(0,s.jsxs)("div",{className:"flex items-center mb-4 gap-4",children:[(0,s.jsx)(eg.Z.Item,{...t,label:"Type",name:[t.name,"location"],initialValue:"message",className:"mb-0",style:{width:"180px"},children:(0,s.jsx)(ev.default,{disabled:!0,options:[{value:"message",label:"Message"}]})}),(0,s.jsx)(eg.Z.Item,{...t,label:"Role",name:[t.name,"role"],className:"mb-0",style:{width:"180px"},tooltip:"LiteLLM will mark all messages of this role as cacheable",children:(0,s.jsx)(ev.default,{placeholder:"Select a role",allowClear:!0,options:[{value:"user",label:"User"},{value:"system",label:"System"},{value:"assistant",label:"Assistant"}],onChange:()=>{r(l.getFieldValue("cache_control_points"))}})}),(0,s.jsx)(eg.Z.Item,{...t,label:"Index",name:[t.name,"index"],className:"mb-0",style:{width:"180px"},tooltip:"(Optional) If set litellm will mark the message at this index as cacheable",children:(0,s.jsx)(lx.Z,{type:"number",placeholder:"Optional",step:1,onChange:()=>{r(l.getFieldValue("cache_control_points"))}})}),e.length>1&&(0,s.jsx)(lh.Z,{className:"text-red-500 cursor-pointer text-lg ml-12",onClick:()=>{i(t.name),setTimeout(()=>{r(l.getFieldValue("cache_control_points"))},0)}})]},t.key)),(0,s.jsx)(eg.Z.Item,{children:(0,s.jsxs)("button",{type:"button",className:"flex items-center justify-center w-full border border-dashed border-gray-300 py-2 px-4 text-gray-600 hover:text-blue-600 hover:border-blue-300 transition-all rounded",onClick:()=>a(),children:[(0,s.jsx)(e4.Z,{className:"mr-2"}),"Add Injection Point"]})})]})}})]})]})},lf=t(9309);let{Link:lj}=Q.default;var lv=e=>{let{showAdvancedSettings:l,setShowAdvancedSettings:t,teams:a,guardrailsList:r,tagsList:i}=e,[n]=eg.Z.useForm(),[o,d]=f.useState(!1),[c,m]=f.useState("per_token"),[u,h]=f.useState(!1),x=(e,l)=>l&&(isNaN(Number(l))||0>Number(l))?Promise.reject("Please enter a valid positive number"):Promise.resolve();return(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)(lm.UQ,{className:"mt-2 mb-4",children:[(0,s.jsx)(lm._m,{children:(0,s.jsx)("b",{children:"Advanced Settings"})}),(0,s.jsx)(lm.X1,{children:(0,s.jsxs)("div",{className:"bg-white rounded-lg",children:[(0,s.jsx)(eg.Z.Item,{label:"Custom Pricing",name:"custom_pricing",valuePropName:"checked",className:"mb-4",children:(0,s.jsx)(lc.Z,{onChange:e=>{d(e),e||n.setFieldsValue({input_cost_per_token:void 0,output_cost_per_token:void 0,input_cost_per_second:void 0})},className:"bg-gray-600"})}),(0,s.jsx)(eg.Z.Item,{label:(0,s.jsxs)("span",{children:["Guardrails"," ",(0,s.jsx)(M.Z,{title:"Apply safety guardrails to this key to filter content or enforce policies",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(R.Z,{style:{marginLeft:"4px"}})})})]}),name:"guardrails",className:"mt-4",help:"Select existing guardrails. Go to 'Guardrails' tab to create new guardrails.",children:(0,s.jsx)(ev.default,{mode:"tags",style:{width:"100%"},placeholder:"Select or enter guardrails",options:r.map(e=>({value:e,label:e}))})}),(0,s.jsx)(eg.Z.Item,{label:"Tags",name:"tags",className:"mb-4",children:(0,s.jsx)(ev.default,{mode:"tags",style:{width:"100%"},placeholder:"Select or enter tags",options:Object.values(i).map(e=>({value:e.name,label:e.name,title:e.description||e.name}))})}),o&&(0,s.jsxs)("div",{className:"ml-6 pl-4 border-l-2 border-gray-200",children:[(0,s.jsx)(eg.Z.Item,{label:"Pricing Model",name:"pricing_model",className:"mb-4",children:(0,s.jsx)(ev.default,{defaultValue:"per_token",onChange:e=>m(e),options:[{value:"per_token",label:"Per Million Tokens"},{value:"per_second",label:"Per Second"}]})}),"per_token"===c?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(eg.Z.Item,{label:"Input Cost (per 1M tokens)",name:"input_cost_per_token",rules:[{validator:x}],className:"mb-4",children:(0,s.jsx)(lm.oi,{})}),(0,s.jsx)(eg.Z.Item,{label:"Output Cost (per 1M tokens)",name:"output_cost_per_token",rules:[{validator:x}],className:"mb-4",children:(0,s.jsx)(lm.oi,{})})]}):(0,s.jsx)(eg.Z.Item,{label:"Cost Per Second",name:"input_cost_per_second",rules:[{validator:x}],className:"mb-4",children:(0,s.jsx)(lm.oi,{})})]}),(0,s.jsx)(eg.Z.Item,{label:"Use in pass through routes",name:"use_in_pass_through",valuePropName:"checked",className:"mb-4 mt-4",tooltip:(0,s.jsxs)("span",{children:["Allow using these credentials in pass through routes."," ",(0,s.jsx)(lj,{href:"https://docs.litellm.ai/docs/pass_through/vertex_ai",target:"_blank",children:"Learn more"})]}),children:(0,s.jsx)(lc.Z,{onChange:e=>{let l=n.getFieldValue("litellm_extra_params");try{let t=l?JSON.parse(l):{};e?t.use_in_pass_through=!0:delete t.use_in_pass_through,Object.keys(t).length>0?n.setFieldValue("litellm_extra_params",JSON.stringify(t,null,2)):n.setFieldValue("litellm_extra_params","")}catch(l){e?n.setFieldValue("litellm_extra_params",JSON.stringify({use_in_pass_through:!0},null,2)):n.setFieldValue("litellm_extra_params","")}},className:"bg-gray-600"})}),(0,s.jsx)(lg,{form:n,showCacheControl:u,onCacheControlChange:e=>{if(h(e),!e){let e=n.getFieldValue("litellm_extra_params");try{let l=e?JSON.parse(e):{};delete l.cache_control_injection_points,Object.keys(l).length>0?n.setFieldValue("litellm_extra_params",JSON.stringify(l,null,2)):n.setFieldValue("litellm_extra_params","")}catch(e){n.setFieldValue("litellm_extra_params","")}}}}),(0,s.jsx)(eg.Z.Item,{label:"LiteLLM Params",name:"litellm_extra_params",tooltip:"Optional litellm params used for making a litellm.completion() call.",className:"mb-4 mt-4",rules:[{validator:lf.Ac}],children:(0,s.jsx)(lu.Z,{rows:4,placeholder:'{ "rpm": 100, "timeout": 0, "stream_timeout": 0 }'})}),(0,s.jsxs)(ew.Z,{className:"mb-4",children:[(0,s.jsx)(eZ.Z,{span:10}),(0,s.jsx)(eZ.Z,{span:10,children:(0,s.jsxs)(lm.xv,{className:"text-gray-600 text-sm",children:["Pass JSON of litellm supported params"," ",(0,s.jsx)(lj,{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",children:"litellm.completion() call"})]})})]}),(0,s.jsx)(eg.Z.Item,{label:"Model Info",name:"model_info_params",tooltip:"Optional model info params. Returned when calling `/model/info` endpoint.",className:"mb-0",rules:[{validator:lf.Ac}],children:(0,s.jsx)(lu.Z,{rows:4,placeholder:'{ "mode": "chat" }'})})]})})]})})},l_=t(56609),lb=t(67187);let ly=e=>{let{content:l,children:t,width:a="auto",className:r=""}=e,[i,n]=(0,f.useState)(!1),[o,d]=(0,f.useState)("top"),c=(0,f.useRef)(null),m=()=>{if(c.current){let e=c.current.getBoundingClientRect(),l=e.top,t=window.innerHeight-e.bottom;l<300&&t>300?d("bottom"):d("top")}};return(0,s.jsxs)("div",{className:"relative inline-block",ref:c,children:[t||(0,s.jsx)(lb.Z,{className:"ml-1 text-gray-500 cursor-help",onMouseEnter:()=>{m(),n(!0)},onMouseLeave:()=>n(!1)}),i&&(0,s.jsxs)("div",{className:"absolute left-1/2 -translate-x-1/2 z-50 bg-black/90 text-white p-2 rounded-md text-sm font-normal shadow-lg ".concat(r),style:{["top"===o?"bottom":"top"]:"100%",width:a,marginBottom:"top"===o?"8px":"0",marginTop:"bottom"===o?"8px":"0"},children:[l,(0,s.jsx)("div",{className:"absolute left-1/2 -translate-x-1/2 w-0 h-0",style:{top:"top"===o?"100%":"auto",bottom:"bottom"===o?"100%":"auto",borderTop:"top"===o?"6px solid rgba(0, 0, 0, 0.9)":"6px solid transparent",borderBottom:"bottom"===o?"6px solid rgba(0, 0, 0, 0.9)":"6px solid transparent",borderLeft:"6px solid transparent",borderRight:"6px solid transparent"}})]})]})};var lN=()=>{let e=eg.Z.useFormInstance(),[l,t]=(0,f.useState)(0),a=eg.Z.useWatch("model",e)||[],r=Array.isArray(a)?a:[a],i=eg.Z.useWatch("custom_model_name",e),n=!r.includes("all-wildcard"),o=eg.Z.useWatch("custom_llm_provider",e);if((0,f.useEffect)(()=>{if(i&&r.includes("custom")){let l=(e.getFieldValue("model_mappings")||[]).map(e=>"custom"===e.public_name||"custom"===e.litellm_model?o===L.Cl.Azure?{public_name:i,litellm_model:"azure/".concat(i)}:{public_name:i,litellm_model:i}:e);e.setFieldValue("model_mappings",l),t(e=>e+1)}},[i,r,o,e]),(0,f.useEffect)(()=>{if(r.length>0&&!r.includes("all-wildcard")){let l=e.getFieldValue("model_mappings")||[];if(l.length!==r.length||!r.every(e=>l.some(l=>"custom"===e?"custom"===l.litellm_model||l.litellm_model===i:o===L.Cl.Azure?l.litellm_model==="azure/".concat(e):l.litellm_model===e))){let l=r.map(e=>"custom"===e&&i?o===L.Cl.Azure?{public_name:i,litellm_model:"azure/".concat(i)}:{public_name:i,litellm_model:i}:o===L.Cl.Azure?{public_name:e,litellm_model:"azure/".concat(e)}:{public_name:e,litellm_model:e});e.setFieldValue("model_mappings",l),t(e=>e+1)}}},[r,i,o,e]),!n)return null;let d=(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"mb-2 font-normal",children:"The name you specify in your API calls to LiteLLM Proxy"}),(0,s.jsxs)("div",{className:"mb-2 font-normal",children:[(0,s.jsx)("strong",{children:"Example:"})," If you name your public model"," ",(0,s.jsx)("code",{className:"bg-gray-700 px-1 py-0.5 rounded text-xs",children:"example-name"}),", and choose"," ",(0,s.jsx)("code",{className:"bg-gray-700 px-1 py-0.5 rounded text-xs",children:"openai/qwen-plus-latest"})," as the LiteLLM model"]}),(0,s.jsxs)("div",{className:"mb-2 font-normal",children:[(0,s.jsx)("strong",{children:"Usage:"})," You make an API call to the LiteLLM proxy with"," ",(0,s.jsx)("code",{className:"bg-gray-700 px-1 py-0.5 rounded text-xs",children:'model = "example-name"'})]}),(0,s.jsxs)("div",{className:"font-normal",children:[(0,s.jsx)("strong",{children:"Result:"})," LiteLLM sends"," ",(0,s.jsx)("code",{className:"bg-gray-700 px-1 py-0.5 rounded text-xs",children:"qwen-plus-latest"})," to the provider"]})]}),c=(0,s.jsx)("div",{children:"The model name LiteLLM will send to the LLM API"}),m=[{title:(0,s.jsxs)("span",{className:"flex items-center",children:["Public Model Name",(0,s.jsx)(ly,{content:d,width:"500px"})]}),dataIndex:"public_name",key:"public_name",render:(l,t,a)=>(0,s.jsx)(ej.o,{value:l,onChange:l=>{let t=l.target.value,s=[...e.getFieldValue("model_mappings")],r=o===L.Cl.Anthropic,i=t.endsWith("-1m"),n=e.getFieldValue("litellm_extra_params"),d=!n||""===n.trim(),c=t;if(r&&i&&d){let l=JSON.stringify({extra_headers:{"anthropic-beta":"context-1m-2025-08-07"}},null,2);e.setFieldValue("litellm_extra_params",l),c=t.slice(0,-3)}s[a].public_name=c,e.setFieldValue("model_mappings",s)}})},{title:(0,s.jsxs)("span",{className:"flex items-center",children:["LiteLLM Model Name",(0,s.jsx)(ly,{content:c,width:"360px"})]}),dataIndex:"litellm_model",key:"litellm_model"}];return(0,s.jsx)(s.Fragment,{children:(0,s.jsx)(eg.Z.Item,{label:"Model Mappings",name:"model_mappings",tooltip:"Map public model names to LiteLLM model names for load balancing",labelCol:{span:10},wrapperCol:{span:16},labelAlign:"left",rules:[{required:!0,validator:async(e,l)=>{if(!l||0===l.length)throw Error("At least one model mapping is required");if(l.filter(e=>!e.public_name||""===e.public_name.trim()).length>0)throw Error("All model mappings must have valid public names")}}],children:(0,s.jsx)(l_.Z,{dataSource:e.getFieldValue("model_mappings"),columns:m,pagination:!1,size:"small"},l)})})},lw=e=>{let{selectedProvider:l,providerModels:t,getPlaceholder:a}=e,r=eg.Z.useFormInstance(),i=e=>{let t=e.target.value,s=(r.getFieldValue("model_mappings")||[]).map(e=>"custom"===e.public_name||"custom"===e.litellm_model?l===L.Cl.Azure?{public_name:t,litellm_model:"azure/".concat(t)}:{public_name:t,litellm_model:t}:e);r.setFieldsValue({model_mappings:s})};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(eg.Z.Item,{label:"LiteLLM Model Name(s)",tooltip:"The model name LiteLLM will send to the LLM API",className:"mb-0",children:[(0,s.jsx)(eg.Z.Item,{name:"model",rules:[{required:!0,message:"Please enter ".concat(l===L.Cl.Azure?"a deployment name":"at least one model",".")}],noStyle:!0,children:l===L.Cl.Azure||l===L.Cl.OpenAI_Compatible||l===L.Cl.Ollama?(0,s.jsx)(s.Fragment,{children:(0,s.jsx)(eN.o,{placeholder:a(l),onChange:l===L.Cl.Azure?e=>{let l=e.target.value,t=l?[{public_name:l,litellm_model:"azure/".concat(l)}]:[];r.setFieldsValue({model:l,model_mappings:t})}:void 0})}):t.length>0?(0,s.jsx)(ev.default,{mode:"multiple",allowClear:!0,showSearch:!0,placeholder:"Select models",onChange:e=>{let t=Array.isArray(e)?e:[e];if(t.includes("all-wildcard"))r.setFieldsValue({model_name:void 0,model_mappings:[]});else if(JSON.stringify(r.getFieldValue("model"))!==JSON.stringify(t)){let e=t.map(e=>l===L.Cl.Azure?{public_name:e,litellm_model:"azure/".concat(e)}:{public_name:e,litellm_model:e});r.setFieldsValue({model:t,model_mappings:e})}},optionFilterProp:"children",filterOption:(e,l)=>{var t;return(null!==(t=null==l?void 0:l.label)&&void 0!==t?t:"").toLowerCase().includes(e.toLowerCase())},options:[{label:"Custom Model Name (Enter below)",value:"custom"},{label:"All ".concat(l," Models (Wildcard)"),value:"all-wildcard"},...t.map(e=>({label:e,value:e}))],style:{width:"100%"}}):(0,s.jsx)(eN.o,{placeholder:a(l)})}),(0,s.jsx)(eg.Z.Item,{noStyle:!0,shouldUpdate:(e,l)=>e.model!==l.model,children:e=>{let{getFieldValue:t}=e,a=t("model")||[];return(Array.isArray(a)?a:[a]).includes("custom")&&(0,s.jsx)(eg.Z.Item,{name:"custom_model_name",rules:[{required:!0,message:"Please enter a custom model name."}],className:"mt-2",children:(0,s.jsx)(eN.o,{placeholder:l===L.Cl.Azure?"Enter Azure deployment name":"Enter custom model name",onChange:i})})}})]}),(0,s.jsxs)(ew.Z,{children:[(0,s.jsx)(eZ.Z,{span:10}),(0,s.jsx)(eZ.Z,{span:14,children:(0,s.jsx)(eN.x,{className:"mb-3 mt-1",children:l===L.Cl.Azure?"Your deployment name will be saved as the public model name, and LiteLLM will use 'azure/deployment-name' internally":"The model name LiteLLM will send to the LLM API"})})]})]})};let lZ=[{value:"chat",label:"Chat - /chat/completions"},{value:"completion",label:"Completion - /completions"},{value:"embedding",label:"Embedding - /embeddings"},{value:"audio_speech",label:"Audio Speech - /audio/speech"},{value:"audio_transcription",label:"Audio Transcription - /audio/transcriptions"},{value:"image_generation",label:"Image Generation - /images/generations"},{value:"video_generation",label:"Video Generation - /videos"},{value:"rerank",label:"Rerank - /rerank"},{value:"realtime",label:"Realtime - /realtime"},{value:"batch",label:"Batch - /batch"},{value:"ocr",label:"OCR - /ocr"}],{Title:lC,Link:lk}=Q.default;var lS=e=>{let{form:l,handleOk:t,selectedProvider:r,setSelectedProvider:i,providerModels:o,setProviderModelsFn:d,getPlaceholder:c,uploadProps:m,showAdvancedSettings:u,setShowAdvancedSettings:h,teams:x,credentials:p}=e,[g,j]=(0,f.useState)("chat"),[v,b]=(0,f.useState)(!1),[y,N]=(0,f.useState)(!1),[w,Z]=(0,f.useState)(""),{accessToken:C,userRole:k,premiumUser:S,userId:A}=(0,n.Z)(),{data:E,isLoading:P,error:I}=eb(),{data:T,isLoading:R,error:O}=la(),{data:V,isLoading:q,error:z}=li(),B=async()=>{N(!0),Z("test-".concat(Date.now())),b(!0)},[G,U]=(0,f.useState)(!1),[H,K]=(0,f.useState)([]),[J,W]=(0,f.useState)(null);(0,f.useEffect)(()=>{(async()=>{K((await (0,a.modelAvailableCall)(C,"","",!1,null,!0,!0)).data.map(e=>e.id))})()},[C]);let Y=(0,f.useMemo)(()=>E?[...E].sort((e,l)=>e.provider_display_name.localeCompare(l.provider_display_name)):[],[E]),$=I?I instanceof Error?I.message:"Failed to load providers":null,X=eR.ZL.includes(k),ee=(0,eR.yV)(x,A);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(lC,{level:2,children:"Add Model"}),(0,s.jsx)(et.Z,{children:(0,s.jsx)(eg.Z,{form:l,onFinish:async e=>{console.log("\uD83D\uDD25 Form onFinish triggered with values:",e),await t().then(()=>{W(null)})},onFinishFailed:e=>{console.log("\uD83D\uDCA5 Form onFinishFailed triggered:",e)},labelCol:{span:10},wrapperCol:{span:16},labelAlign:"left",children:(0,s.jsxs)(s.Fragment,{children:[ee&&!X&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(eg.Z.Item,{label:"Select Team",name:"team_id",rules:[{required:!0,message:"Please select a team to continue"}],tooltip:"Select the team for which you want to add this model",children:(0,s.jsx)(ld.Z,{teams:x,onChange:e=>{W(e)}})}),!J&&(0,s.jsx)(lo.Z,{message:"Team Selection Required",description:"As a team admin, you need to select your team first before adding models.",type:"info",showIcon:!0,className:"mb-4"})]}),(X||ee&&J)&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(eg.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Provider:",name:"custom_llm_provider",tooltip:"E.g. OpenAI, Azure OpenAI, Anthropic, Bedrock, etc.",labelCol:{span:10},labelAlign:"left",children:(0,s.jsxs)(ev.default,{virtual:!1,showSearch:!0,loading:P,placeholder:P?"Loading providers...":"Select a provider",optionFilterProp:"data-label",onChange:e=>{i(e),d(e),l.setFieldsValue({custom_llm_provider:e}),l.setFieldsValue({model:[],model_name:void 0})},children:[$&&0===Y.length&&(0,s.jsx)(ev.default.Option,{value:"",children:$},"__error"),Y.map(e=>{let l=e.provider_display_name,t=e.provider;return L.cd[l],(0,s.jsx)(ev.default.Option,{value:t,"data-label":l,children:(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,s.jsx)(F,{provider:t,className:"w-5 h-5"}),(0,s.jsx)("span",{children:l})]})},t)})]})}),(0,s.jsx)(lw,{selectedProvider:r,providerModels:o,getPlaceholder:c}),(0,s.jsx)(lN,{}),(0,s.jsx)(eg.Z.Item,{label:"Mode",name:"mode",className:"mb-1",children:(0,s.jsx)(ev.default,{style:{width:"100%"},value:g,onChange:e=>j(e),options:lZ})}),(0,s.jsxs)(ew.Z,{children:[(0,s.jsx)(eZ.Z,{span:10}),(0,s.jsx)(eZ.Z,{span:10,children:(0,s.jsxs)(D.Z,{className:"mb-5 mt-1",children:[(0,s.jsx)("strong",{children:"Optional"})," - LiteLLM endpoint to use when health checking this model"," ",(0,s.jsx)(lk,{href:"https://docs.litellm.ai/docs/proxy/health#health",target:"_blank",children:"Learn more"})]})})]}),(0,s.jsx)("div",{className:"mb-4",children:(0,s.jsx)(Q.default.Text,{className:"text-sm text-gray-500 mb-2",children:"Either select existing credentials OR enter new provider credentials below"})}),(0,s.jsx)(eg.Z.Item,{label:"Existing Credentials",name:"litellm_credential_name",initialValue:null,children:(0,s.jsx)(ev.default,{showSearch:!0,placeholder:"Select or search for existing credentials",optionFilterProp:"children",filterOption:(e,l)=>{var t;return(null!==(t=null==l?void 0:l.label)&&void 0!==t?t:"").toLowerCase().includes(e.toLowerCase())},options:[{value:null,label:"None"},...p.map(e=>({value:e.credential_name,label:e.credential_name}))],allowClear:!0})}),(0,s.jsx)(eg.Z.Item,{noStyle:!0,shouldUpdate:(e,l)=>e.litellm_credential_name!==l.litellm_credential_name||e.provider!==l.provider,children:e=>{let{getFieldValue:l}=e,t=l("litellm_credential_name");return(console.log("\uD83D\uDD11 Credential Name Changed:",t),t)?null:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:"flex items-center my-4",children:[(0,s.jsx)("div",{className:"flex-grow border-t border-gray-200"}),(0,s.jsx)("span",{className:"px-4 text-gray-500 text-sm",children:"OR"}),(0,s.jsx)("div",{className:"flex-grow border-t border-gray-200"})]}),(0,s.jsx)(eP,{selectedProvider:r,uploadProps:m})]})}}),(0,s.jsxs)("div",{className:"flex items-center my-4",children:[(0,s.jsx)("div",{className:"flex-grow border-t border-gray-200"}),(0,s.jsx)("span",{className:"px-4 text-gray-500 text-sm",children:"Additional Model Info Settings"}),(0,s.jsx)("div",{className:"flex-grow border-t border-gray-200"})]}),(X||!ee)&&(0,s.jsx)(eg.Z.Item,{label:"Team-BYOK Model",tooltip:"Only use this model + credential combination for this team. Useful when teams want to onboard their own OpenAI keys.",className:"mb-4",children:(0,s.jsx)(M.Z,{title:S?"":"This is an enterprise-only feature. Upgrade to premium to restrict model+credential combinations to a specific team.",placement:"top",children:(0,s.jsx)(ln.Z,{checked:G,onChange:e=>{U(e),e||l.setFieldValue("team_id",void 0)},disabled:!S})})}),G&&(X||!ee)&&(0,s.jsx)(eg.Z.Item,{label:"Select Team",name:"team_id",className:"mb-4",tooltip:"Only keys for this team will be able to call this model.",rules:[{required:G&&!X,message:"Please select a team."}],children:(0,s.jsx)(ld.Z,{teams:x,disabled:!S})}),X&&(0,s.jsx)(s.Fragment,{children:(0,s.jsx)(eg.Z.Item,{label:"Model Access Group",name:"model_access_group",className:"mb-4",tooltip:"Use model access groups to give users access to select models, and add new ones to the group over time.",children:(0,s.jsx)(ev.default,{mode:"tags",showSearch:!0,placeholder:"Select existing groups or type to create new ones",optionFilterProp:"children",tokenSeparators:[","],options:H.map(e=>({value:e,label:e})),maxTagCount:"responsive",allowClear:!0})})}),(0,s.jsx)(lv,{showAdvancedSettings:u,setShowAdvancedSettings:h,teams:x,guardrailsList:T||[],tagsList:V||{}})]}),(0,s.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,s.jsx)(M.Z,{title:"Get help on our github",children:(0,s.jsx)(Q.default.Link,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})}),(0,s.jsxs)("div",{className:"space-x-2",children:[(0,s.jsx)(_.ZP,{onClick:B,loading:y,children:"Test Connect"}),(0,s.jsx)(_.ZP,{htmlType:"submit",children:"Add Model"})]})]})]})})}),(0,s.jsx)(ea.Z,{title:"Connection Test Results",open:v,onCancel:()=>{b(!1),N(!1)},footer:[(0,s.jsx)(_.ZP,{onClick:()=>{b(!1),N(!1)},children:"Close"},"close")],width:700,children:v&&(0,s.jsx)(eQ,{formValues:l.getFieldsValue(),accessToken:C,testMode:g,modelName:l.getFieldValue("model_name")||l.getFieldValue("model"),onClose:()=>{b(!1),N(!1)},onTestComplete:()=>N(!1)},w)})]})},lA=e=>{let{form:l,handleOk:t,selectedProvider:a,setSelectedProvider:r,providerModels:i,setProviderModelsFn:n,getPlaceholder:o,uploadProps:d,showAdvancedSettings:c,setShowAdvancedSettings:m,teams:u,credentials:h,accessToken:x,userRole:p}=e,[g]=eg.Z.useForm();return(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)(eH.v0,{className:"w-full",children:[(0,s.jsxs)(eH.td,{className:"mb-4",children:[(0,s.jsx)(eH.OK,{children:"Add Model"}),(0,s.jsx)(eH.OK,{children:"Add Auto Router"})]}),(0,s.jsxs)(eH.nP,{children:[(0,s.jsx)(eH.x4,{children:(0,s.jsx)(lS,{form:l,handleOk:t,selectedProvider:a,setSelectedProvider:r,providerModels:i,setProviderModelsFn:n,getPlaceholder:o,uploadProps:d,showAdvancedSettings:c,setShowAdvancedSettings:m,teams:u,credentials:h})}),(0,s.jsx)(eH.x4,{children:(0,s.jsx)(lt,{form:g,handleOk:()=>{g.validateFields().then(e=>{e0(e,x,g,t)}).catch(e=>{console.error("Validation failed:",e)})},accessToken:x,userRole:p})})]})]})})},lE=t(8048),lP=t(4156),lM=t(15731),lL=t(91126);let lF=(e,l,t,a,r,i,n,o,d,c,m)=>[{header:()=>(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)(lP.Z,{checked:t,indeterminate:l.length>0&&!t,onChange:e=>r(e.target.checked),onClick:e=>e.stopPropagation()}),(0,s.jsx)("span",{children:"Model ID"})]}),accessorKey:"model_info.id",enableSorting:!0,sortingFn:"alphanumeric",cell:e=>{let{row:t}=e,r=t.original,i=r.model_name,n=l.includes(i);return(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)(lP.Z,{checked:n,onChange:e=>a(i,e.target.checked),onClick:e=>e.stopPropagation()}),(0,s.jsx)(M.Z,{title:r.model_info.id,children:(0,s.jsx)("div",{className:"font-mono text-blue-500 bg-blue-50 hover:bg-blue-100 text-xs font-normal px-2 py-0.5 text-left w-full truncate whitespace-nowrap cursor-pointer max-w-[15ch]",onClick:()=>m&&m(r.model_info.id),children:r.model_info.id})})]})}},{header:"Model Name",accessorKey:"model_name",enableSorting:!0,sortingFn:"alphanumeric",cell:e=>{let{row:l}=e,t=l.original,a=o(t)||t.model_name;return(0,s.jsx)("div",{className:"font-medium text-sm",children:(0,s.jsx)(M.Z,{title:a,children:(0,s.jsx)("div",{className:"truncate max-w-[200px]",children:a})})})}},{header:"Health Status",accessorKey:"health_status",enableSorting:!0,sortingFn:(e,l,t)=>{var s,a;let r=e.getValue("health_status")||"unknown",i=l.getValue("health_status")||"unknown",n={healthy:0,checking:1,unknown:2,unhealthy:3};return(null!==(s=n[r])&&void 0!==s?s:4)-(null!==(a=n[i])&&void 0!==a?a:4)},cell:l=>{var t;let{row:a}=l,r=a.original,i={status:r.health_status,loading:r.health_loading,error:r.health_error};if(i.loading)return(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,s.jsxs)("div",{className:"flex space-x-1",children:[(0,s.jsx)("div",{className:"w-2 h-2 bg-indigo-500 rounded-full animate-pulse"}),(0,s.jsx)("div",{className:"w-2 h-2 bg-indigo-500 rounded-full animate-pulse",style:{animationDelay:"0.2s"}}),(0,s.jsx)("div",{className:"w-2 h-2 bg-indigo-500 rounded-full animate-pulse",style:{animationDelay:"0.4s"}})]}),(0,s.jsx)(e3.x,{className:"text-gray-600 text-sm",children:"Checking..."})]});let o=r.model_name,d="healthy"===i.status&&(null===(t=e[o])||void 0===t?void 0:t.successResponse);return(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[n(i.status),d&&c&&(0,s.jsx)(M.Z,{title:"View response details",placement:"top",children:(0,s.jsx)("button",{onClick:()=>{var l;return c(o,null===(l=e[o])||void 0===l?void 0:l.successResponse)},className:"p-1 text-green-600 hover:text-green-800 hover:bg-green-50 rounded cursor-pointer transition-colors",children:(0,s.jsx)(lM.Z,{className:"h-4 w-4"})})})]})}},{header:"Error Details",accessorKey:"health_error",enableSorting:!1,cell:l=>{let{row:t}=l,a=t.original.model_name,r=e[a];if(!(null==r?void 0:r.error))return(0,s.jsx)(e3.x,{className:"text-gray-400 text-sm",children:"No errors"});let i=r.error,n=r.fullError||r.error;return(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,s.jsx)("div",{className:"max-w-[200px]",children:(0,s.jsx)(M.Z,{title:i,placement:"top",children:(0,s.jsx)(e3.x,{className:"text-red-600 text-sm truncate",children:i})})}),d&&n!==i&&(0,s.jsx)(M.Z,{title:"View full error details",placement:"top",children:(0,s.jsx)("button",{onClick:()=>d(a,i,n),className:"p-1 text-red-600 hover:text-red-800 hover:bg-red-50 rounded cursor-pointer transition-colors",children:(0,s.jsx)(lM.Z,{className:"h-4 w-4"})})})]})}},{header:"Last Check",accessorKey:"last_check",enableSorting:!0,sortingFn:(e,l,t)=>{let s=e.getValue("last_check")||"Never checked",a=l.getValue("last_check")||"Never checked";if("Never checked"===s&&"Never checked"===a)return 0;if("Never checked"===s)return 1;if("Never checked"===a)return -1;if("Check in progress..."===s&&"Check in progress..."===a)return 0;if("Check in progress..."===s)return -1;if("Check in progress..."===a)return 1;let r=new Date(s),i=new Date(a);return isNaN(r.getTime())&&isNaN(i.getTime())?0:isNaN(r.getTime())?1:isNaN(i.getTime())?-1:i.getTime()-r.getTime()},cell:e=>{let{row:l}=e,t=l.original;return(0,s.jsx)(e3.x,{className:"text-gray-600 text-sm",children:t.health_loading?"Check in progress...":t.last_check})}},{header:"Last Success",accessorKey:"last_success",enableSorting:!0,sortingFn:(e,l,t)=>{let s=e.getValue("last_success")||"Never succeeded",a=l.getValue("last_success")||"Never succeeded";if("Never succeeded"===s&&"Never succeeded"===a)return 0;if("Never succeeded"===s)return 1;if("Never succeeded"===a)return -1;if("None"===s&&"None"===a)return 0;if("None"===s)return 1;if("None"===a)return -1;let r=new Date(s),i=new Date(a);return isNaN(r.getTime())&&isNaN(i.getTime())?0:isNaN(r.getTime())?1:isNaN(i.getTime())?-1:i.getTime()-r.getTime()},cell:l=>{let{row:t}=l,a=e[t.original.model_name],r=(null==a?void 0:a.lastSuccess)||"None";return(0,s.jsx)(e3.x,{className:"text-gray-600 text-sm",children:r})}},{header:"Actions",id:"actions",cell:e=>{let{row:l}=e,t=l.original,a=t.model_name,r=t.health_status&&"none"!==t.health_status,n=t.health_loading?"Checking...":r?"Re-run Health Check":"Run Health Check";return(0,s.jsx)(M.Z,{title:n,placement:"top",children:(0,s.jsx)("button",{className:"p-2 rounded-md transition-colors ".concat(t.health_loading?"text-gray-400 cursor-not-allowed bg-gray-100":"text-indigo-600 hover:text-indigo-700 hover:bg-indigo-50"),onClick:()=>{t.health_loading||i(a)},disabled:t.health_loading,children:t.health_loading?(0,s.jsxs)("div",{className:"flex space-x-1",children:[(0,s.jsx)("div",{className:"w-1 h-1 bg-gray-400 rounded-full animate-pulse"}),(0,s.jsx)("div",{className:"w-1 h-1 bg-gray-400 rounded-full animate-pulse",style:{animationDelay:"0.2s"}}),(0,s.jsx)("div",{className:"w-1 h-1 bg-gray-400 rounded-full animate-pulse",style:{animationDelay:"0.4s"}})]}):r?(0,s.jsx)(eO.Z,{className:"h-4 w-4"}):(0,s.jsx)(lL.Z,{className:"h-4 w-4"})})})},enableSorting:!1}],lI=[{pattern:/Missing .* API Key/i,replacement:"Missing API Key"},{pattern:/Connection timeout/i,replacement:"Connection timeout"},{pattern:/Network.*not.*ok/i,replacement:"Network connection failed"},{pattern:/403.*Forbidden/i,replacement:"Access forbidden - check API key permissions"},{pattern:/401.*Unauthorized/i,replacement:"Unauthorized - invalid API key"},{pattern:/429.*rate limit/i,replacement:"Rate limit exceeded"},{pattern:/500.*Internal Server Error/i,replacement:"Provider internal server error"},{pattern:/litellm\.AuthenticationError/i,replacement:"Authentication failed"},{pattern:/litellm\.RateLimitError/i,replacement:"Rate limit exceeded"},{pattern:/litellm\.APIError/i,replacement:"API error"}];var lT=e=>{let{accessToken:l,modelData:t,all_models_on_proxy:r,getDisplayModelName:i,setSelectedModelId:n}=e,[o,d]=(0,f.useState)({}),[c,m]=(0,f.useState)([]),[u,h]=(0,f.useState)(!1),[x,p]=(0,f.useState)(!1),[g,j]=(0,f.useState)(null),[v,b]=(0,f.useState)(!1),[y,N]=(0,f.useState)(null);(0,f.useRef)(null),(0,f.useEffect)(()=>{l&&(null==t?void 0:t.data)&&(async()=>{let e={};t.data.forEach(l=>{e[l.model_name]={status:"none",lastCheck:"None",lastSuccess:"None",loading:!1,error:void 0,fullError:void 0,successResponse:void 0}});try{let s=await (0,a.latestHealthChecksCall)(l);s&&s.latest_health_checks&&"object"==typeof s.latest_health_checks&&Object.entries(s.latest_health_checks).forEach(l=>{let[s,a]=l;if(!a)return;let r=null,i=t.data.find(e=>e.model_name===s);if(i)r=i.model_name;else{let e=t.data.find(e=>e.model_info&&e.model_info.id===s);if(e)r=e.model_name;else if(a.model_name){let e=t.data.find(e=>e.model_name===a.model_name);e&&(r=e.model_name)}}if(r){let l=a.error_message||void 0;e[r]={status:a.status||"unknown",lastCheck:a.checked_at?new Date(a.checked_at).toLocaleString():"None",lastSuccess:"healthy"===a.status&&a.checked_at?new Date(a.checked_at).toLocaleString():"None",loading:!1,error:l?w(l):void 0,fullError:l,successResponse:"healthy"===a.status?a:void 0}}})}catch(e){console.warn("Failed to load health check history (using default states):",e)}d(e)})()},[l,t]);let w=e=>{var l;if(!e)return"Health check failed";let t="string"==typeof e?e:JSON.stringify(e),s=t.match(/(\w+Error):\s*(\d{3})/i);if(s)return"".concat(s[1],": ").concat(s[2]);let a=t.match(/(AuthenticationError|RateLimitError|BadRequestError|InternalServerError|TimeoutError|NotFoundError|ForbiddenError|ServiceUnavailableError|BadGatewayError|ContentPolicyViolationError|\w+Error)/i),r=t.match(/\b(400|401|403|404|408|429|500|502|503|504)\b/);if(a&&r)return"".concat(a[1],": ").concat(r[1]);if(r){let e=r[1];return"".concat({400:"BadRequestError",401:"AuthenticationError",403:"ForbiddenError",404:"NotFoundError",408:"TimeoutError",429:"RateLimitError",500:"InternalServerError",502:"BadGatewayError",503:"ServiceUnavailableError",504:"GatewayTimeoutError"}[e],": ").concat(e)}if(a){let e=a[1],l={AuthenticationError:"401",RateLimitError:"429",BadRequestError:"400",InternalServerError:"500",TimeoutError:"408",NotFoundError:"404",ForbiddenError:"403",ServiceUnavailableError:"503",BadGatewayError:"502",GatewayTimeoutError:"504",ContentPolicyViolationError:"400"}[e];return l?"".concat(e,": ").concat(l):e}for(let{pattern:e,replacement:l}of lI)if(e.test(t))return l;if(/missing.*api.*key|invalid.*key|unauthorized/i.test(t))return"AuthenticationError: 401";if(/rate.*limit|too.*many.*requests/i.test(t))return"RateLimitError: 429";if(/timeout|timed.*out/i.test(t))return"TimeoutError: 408";if(/not.*found/i.test(t))return"NotFoundError: 404";if(/forbidden|access.*denied/i.test(t))return"ForbiddenError: 403";if(/internal.*server.*error/i.test(t))return"InternalServerError: 500";let i=t.replace(/[\n\r]+/g," ").replace(/\s+/g," ").trim(),n=null===(l=i.split(/[.!?]/)[0])||void 0===l?void 0:l.trim();return n&&n.length>0?n.length>100?n.substring(0,97)+"...":n:i.length>100?i.substring(0,97)+"...":i},Z=async e=>{if(l){d(l=>({...l,[e]:{...l[e],loading:!0,status:"checking"}}));try{var s,r;let i=await (0,a.individualModelHealthCheckCall)(l,e),n=new Date().toLocaleString();if(i.unhealthy_count>0&&i.unhealthy_endpoints&&i.unhealthy_endpoints.length>0){let l=(null===(s=i.unhealthy_endpoints[0])||void 0===s?void 0:s.error)||"Health check failed",t=w(l);d(s=>{var a;return{...s,[e]:{status:"unhealthy",lastCheck:n,lastSuccess:(null===(a=s[e])||void 0===a?void 0:a.lastSuccess)||"None",loading:!1,error:t,fullError:l}}})}else d(l=>({...l,[e]:{status:"healthy",lastCheck:n,lastSuccess:n,loading:!1,successResponse:i}}));try{let s=await (0,a.latestHealthChecksCall)(l),i=t.data.find(l=>l.model_name===e);if(i){let l=i.model_info.id,t=null===(r=s.latest_health_checks)||void 0===r?void 0:r[l];if(t){let l=t.error_message||void 0;d(s=>{var a,r,i,n,o,d,c;return{...s,[e]:{status:t.status||(null===(a=s[e])||void 0===a?void 0:a.status)||"unknown",lastCheck:t.checked_at?new Date(t.checked_at).toLocaleString():(null===(r=s[e])||void 0===r?void 0:r.lastCheck)||"None",lastSuccess:"healthy"===t.status?t.checked_at?new Date(t.checked_at).toLocaleString():(null===(i=s[e])||void 0===i?void 0:i.lastSuccess)||"None":(null===(n=s[e])||void 0===n?void 0:n.lastSuccess)||"None",loading:!1,error:l?w(l):null===(o=s[e])||void 0===o?void 0:o.error,fullError:l||(null===(d=s[e])||void 0===d?void 0:d.fullError),successResponse:"healthy"===t.status?t:null===(c=s[e])||void 0===c?void 0:c.successResponse}}})}}}catch(e){console.debug("Could not fetch updated status from database (non-critical):",e)}}catch(a){let l=new Date().toLocaleString(),t=a instanceof Error?a.message:String(a),s=w(t);d(a=>{var r;return{...a,[e]:{status:"unhealthy",lastCheck:l,lastSuccess:(null===(r=a[e])||void 0===r?void 0:r.lastSuccess)||"None",loading:!1,error:s,fullError:t}}})}}},C=async()=>{let e=c.length>0?c:r,s=e.reduce((e,l)=>(e[l]={...o[l],loading:!0,status:"checking"},e),{});d(e=>({...e,...s}));let i={},n=e.map(async e=>{if(l)try{let s=await (0,a.individualModelHealthCheckCall)(l,e);i[e]=s;let r=new Date().toLocaleString();if(s.unhealthy_count>0&&s.unhealthy_endpoints&&s.unhealthy_endpoints.length>0){var t;let l=(null===(t=s.unhealthy_endpoints[0])||void 0===t?void 0:t.error)||"Health check failed",a=w(l);d(t=>{var s;return{...t,[e]:{status:"unhealthy",lastCheck:r,lastSuccess:(null===(s=t[e])||void 0===s?void 0:s.lastSuccess)||"None",loading:!1,error:a,fullError:l}}})}else d(l=>({...l,[e]:{status:"healthy",lastCheck:r,lastSuccess:r,loading:!1,successResponse:s}}))}catch(a){console.error("Health check failed for ".concat(e,":"),a);let l=new Date().toLocaleString(),t=a instanceof Error?a.message:String(a),s=w(t);d(a=>{var r;return{...a,[e]:{status:"unhealthy",lastCheck:l,lastSuccess:(null===(r=a[e])||void 0===r?void 0:r.lastSuccess)||"None",loading:!1,error:s,fullError:t}}})}});await Promise.allSettled(n);try{if(!l)return;let s=await (0,a.latestHealthChecksCall)(l);s.latest_health_checks&&Object.entries(s.latest_health_checks).forEach(l=>{let[s,a]=l,r=t.data.find(e=>e.model_info.id===s);if(r&&e.includes(r.model_name)&&a){let e=r.model_name,l=a.error_message||void 0;d(t=>{let s=t[e];return{...t,[e]:{status:a.status||(null==s?void 0:s.status)||"unknown",lastCheck:a.checked_at?new Date(a.checked_at).toLocaleString():(null==s?void 0:s.lastCheck)||"None",lastSuccess:"healthy"===a.status&&a.checked_at?new Date(a.checked_at).toLocaleString():(null==s?void 0:s.lastSuccess)||"None",loading:!1,error:l?w(l):null==s?void 0:s.error,fullError:l||(null==s?void 0:s.fullError),successResponse:"healthy"===a.status?a:null==s?void 0:s.successResponse}}})}})}catch(e){console.warn("Failed to fetch updated health statuses from database (non-critical):",e)}},k=e=>{h(e),e?m(r):m([])},S=()=>{p(!1),j(null)},P=()=>{b(!1),N(null)};return(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"mb-6",children:(0,s.jsxs)("div",{className:"flex justify-between items-center",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(W.Z,{children:"Model Health Status"}),(0,s.jsx)(D.Z,{className:"text-gray-600 mt-1",children:"Run health checks on individual models to verify they are working correctly"})]}),(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[c.length>0&&(0,s.jsx)(E.Z,{size:"sm",variant:"light",onClick:()=>k(!1),className:"px-3 py-1 text-sm",children:"Clear Selection"}),(0,s.jsx)(E.Z,{size:"sm",variant:"secondary",onClick:C,disabled:Object.values(o).some(e=>e.loading),className:"px-3 py-1 text-sm",children:c.length>0&&c.length{l?m(l=>[...l,e]):(m(l=>l.filter(l=>l!==e)),h(!1))},k,Z,e=>{switch(e){case"healthy":return(0,s.jsx)(A.Z,{color:"emerald",children:"healthy"});case"unhealthy":return(0,s.jsx)(A.Z,{color:"red",children:"unhealthy"});case"checking":return(0,s.jsx)(A.Z,{color:"blue",children:"checking"});case"none":return(0,s.jsx)(A.Z,{color:"gray",children:"none"});default:return(0,s.jsx)(A.Z,{color:"gray",children:"unknown"})}},i,(e,l,t)=>{j({modelName:e,cleanedError:l,fullError:t}),p(!0)},(e,l)=>{N({modelName:e,response:l}),b(!0)},n),data:t.data.map(e=>{let l=o[e.model_name]||{status:"none",lastCheck:"None",loading:!1};return{model_name:e.model_name,model_info:e.model_info,provider:e.provider,litellm_model_name:e.litellm_model_name,health_status:l.status,last_check:l.lastCheck,last_success:l.lastSuccess||"None",health_loading:l.loading,health_error:l.error,health_full_error:l.fullError}}),isLoading:!1})}),(0,s.jsx)(ea.Z,{title:g?"Health Check Error - ".concat(g.modelName):"Error Details",open:x,onCancel:S,footer:[(0,s.jsx)(_.ZP,{onClick:S,children:"Close"},"close")],width:800,children:g&&(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Error:"}),(0,s.jsx)("div",{className:"mt-2 p-3 bg-red-50 border border-red-200 rounded-md",children:(0,s.jsx)(D.Z,{className:"text-red-800",children:g.cleanedError})})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Full Error Details:"}),(0,s.jsx)("div",{className:"mt-2 p-3 bg-gray-50 border border-gray-200 rounded-md max-h-96 overflow-y-auto",children:(0,s.jsx)("pre",{className:"text-sm text-gray-800 whitespace-pre-wrap",children:g.fullError})})]})]})}),(0,s.jsx)(ea.Z,{title:y?"Health Check Response - ".concat(y.modelName):"Response Details",open:v,onCancel:P,footer:[(0,s.jsx)(_.ZP,{onClick:P,children:"Close"},"close")],width:800,children:y&&(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Status:"}),(0,s.jsx)("div",{className:"mt-2 p-3 bg-green-50 border border-green-200 rounded-md",children:(0,s.jsx)(D.Z,{className:"text-green-800",children:"Health check passed successfully"})})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Response Details:"}),(0,s.jsx)("div",{className:"mt-2 p-3 bg-gray-50 border border-gray-200 rounded-md max-h-96 overflow-y-auto",children:(0,s.jsx)("pre",{className:"text-sm text-gray-800 whitespace-pre-wrap",children:JSON.stringify(y.response,null,2)})})]})]})})]})},lR=t(47686),lO=t(77355),lV=t(93416),lq=t(95704),lz=e=>{let{accessToken:l,initialModelGroupAlias:t={},onAliasUpdate:r}=e,[i,n]=(0,f.useState)([]),[o,d]=(0,f.useState)({aliasName:"",targetModelGroup:""}),[c,m]=(0,f.useState)(null),[u,h]=(0,f.useState)(!0);(0,f.useEffect)(()=>{n(Object.entries(t).map((e,l)=>{var t;let[s,a]=e;return{id:"".concat(l,"-").concat(s),aliasName:s,targetModelGroup:"string"==typeof a?a:null!==(t=null==a?void 0:a.model)&&void 0!==t?t:""}}))},[t]);let x=async e=>{if(!l)return console.error("Access token is missing"),!1;try{let t={};return e.forEach(e=>{t[e.aliasName]=e.targetModelGroup}),console.log("Saving model group alias:",t),await (0,a.setCallbacksCall)(l,{router_settings:{model_group_alias:t}}),r&&r(t),!0}catch(e){return console.error("Failed to save model group alias settings:",e),eo.Z.fromBackend("Failed to save model group alias settings"),!1}},p=async()=>{if(!o.aliasName||!o.targetModelGroup){eo.Z.fromBackend("Please provide both alias name and target model group");return}if(i.some(e=>e.aliasName===o.aliasName)){eo.Z.fromBackend("An alias with this name already exists");return}let e=[...i,{id:"".concat(Date.now(),"-").concat(o.aliasName),aliasName:o.aliasName,targetModelGroup:o.targetModelGroup}];await x(e)&&(n(e),d({aliasName:"",targetModelGroup:""}),eo.Z.success("Alias added successfully"))},g=e=>{m({...e})},j=async()=>{if(!c)return;if(!c.aliasName||!c.targetModelGroup){eo.Z.fromBackend("Please provide both alias name and target model group");return}if(i.some(e=>e.id!==c.id&&e.aliasName===c.aliasName)){eo.Z.fromBackend("An alias with this name already exists");return}let e=i.map(e=>e.id===c.id?c:e);await x(e)&&(n(e),m(null),eo.Z.success("Alias updated successfully"))},v=()=>{m(null)},_=async e=>{let l=i.filter(l=>l.id!==e);await x(l)&&(n(l),eo.Z.success("Alias deleted successfully"))},b=i.reduce((e,l)=>(e[l.aliasName]=l.targetModelGroup,e),{});return(0,s.jsxs)(lq.Zb,{className:"mb-6",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between cursor-pointer",onClick:()=>h(!u),children:[(0,s.jsxs)("div",{className:"flex flex-col",children:[(0,s.jsx)(lq.Dx,{className:"mb-0",children:"Model Group Alias Settings"}),(0,s.jsx)("p",{className:"text-sm text-gray-500",children:"Create aliases for your model groups to simplify API calls. For example, you can create an alias 'gpt-4o' that points to 'gpt-4o-mini-openai' model group."})]}),(0,s.jsx)("div",{className:"flex items-center",children:u?(0,s.jsx)(y.Z,{className:"w-5 h-5 text-gray-500"}):(0,s.jsx)(lR.Z,{className:"w-5 h-5 text-gray-500"})})]}),u&&(0,s.jsxs)("div",{className:"mt-4",children:[(0,s.jsxs)("div",{className:"mb-6",children:[(0,s.jsx)(lq.xv,{className:"text-sm font-medium text-gray-700 mb-2",children:"Add New Alias"}),(0,s.jsxs)("div",{className:"grid grid-cols-3 gap-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"block text-xs text-gray-500 mb-1",children:"Alias Name"}),(0,s.jsx)("input",{type:"text",value:o.aliasName,onChange:e=>d({...o,aliasName:e.target.value}),placeholder:"e.g., gpt-4o",className:"w-full px-3 py-2 border border-gray-300 rounded-md text-sm"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"block text-xs text-gray-500 mb-1",children:"Target Model Group"}),(0,s.jsx)("input",{type:"text",value:o.targetModelGroup,onChange:e=>d({...o,targetModelGroup:e.target.value}),placeholder:"e.g., gpt-4o-mini-openai",className:"w-full px-3 py-2 border border-gray-300 rounded-md text-sm"})]}),(0,s.jsx)("div",{className:"flex items-end",children:(0,s.jsxs)("button",{onClick:p,disabled:!o.aliasName||!o.targetModelGroup,className:"flex items-center px-4 py-2 rounded-md text-sm ".concat(o.aliasName&&o.targetModelGroup?"bg-green-600 text-white hover:bg-green-700":"bg-gray-300 text-gray-500 cursor-not-allowed"),children:[(0,s.jsx)(lO.Z,{className:"w-4 h-4 mr-1"}),"Add Alias"]})})]})]}),(0,s.jsx)(lq.xv,{className:"text-sm font-medium text-gray-700 mb-2",children:"Manage Existing Aliases"}),(0,s.jsx)("div",{className:"rounded-lg custom-border relative mb-6",children:(0,s.jsx)("div",{className:"overflow-x-auto",children:(0,s.jsxs)(lq.iA,{className:"[&_td]:py-0.5 [&_th]:py-1",children:[(0,s.jsx)(lq.ss,{children:(0,s.jsxs)(lq.SC,{children:[(0,s.jsx)(lq.xs,{className:"py-1 h-8",children:"Alias Name"}),(0,s.jsx)(lq.xs,{className:"py-1 h-8",children:"Target Model Group"}),(0,s.jsx)(lq.xs,{className:"py-1 h-8",children:"Actions"})]})}),(0,s.jsxs)(lq.RM,{children:[i.map(e=>(0,s.jsx)(lq.SC,{className:"h-8",children:c&&c.id===e.id?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(lq.pj,{className:"py-0.5",children:(0,s.jsx)("input",{type:"text",value:c.aliasName,onChange:e=>m({...c,aliasName:e.target.value}),className:"w-full px-2 py-1 border border-gray-300 rounded-md text-sm"})}),(0,s.jsx)(lq.pj,{className:"py-0.5",children:(0,s.jsx)("input",{type:"text",value:c.targetModelGroup,onChange:e=>m({...c,targetModelGroup:e.target.value}),className:"w-full px-2 py-1 border border-gray-300 rounded-md text-sm"})}),(0,s.jsx)(lq.pj,{className:"py-0.5 whitespace-nowrap",children:(0,s.jsxs)("div",{className:"flex space-x-2",children:[(0,s.jsx)("button",{onClick:j,className:"text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100",children:"Save"}),(0,s.jsx)("button",{onClick:v,className:"text-xs bg-gray-50 text-gray-600 px-2 py-1 rounded hover:bg-gray-100",children:"Cancel"})]})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(lq.pj,{className:"py-0.5 text-sm text-gray-900",children:e.aliasName}),(0,s.jsx)(lq.pj,{className:"py-0.5 text-sm text-gray-500",children:e.targetModelGroup}),(0,s.jsx)(lq.pj,{className:"py-0.5 whitespace-nowrap",children:(0,s.jsxs)("div",{className:"flex space-x-2",children:[(0,s.jsx)("button",{onClick:()=>g(e),className:"text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100",children:(0,s.jsx)(lV.Z,{className:"w-3 h-3"})}),(0,s.jsx)("button",{onClick:()=>_(e.id),className:"text-xs bg-red-50 text-red-600 px-2 py-1 rounded hover:bg-red-100",children:(0,s.jsx)(S.Z,{className:"w-3 h-3"})})]})})]})},e.id)),0===i.length&&(0,s.jsx)(lq.SC,{children:(0,s.jsx)(lq.pj,{colSpan:3,className:"py-0.5 text-sm text-gray-500 text-center",children:"No aliases added yet. Add a new alias above."})})]})]})})}),(0,s.jsxs)(lq.Zb,{children:[(0,s.jsx)(lq.Dx,{className:"mb-4",children:"Configuration Example"}),(0,s.jsx)(lq.xv,{className:"text-gray-600 mb-4",children:"Here's how your current aliases would look in the config.yaml:"}),(0,s.jsx)("div",{className:"bg-gray-100 rounded-lg p-4 font-mono text-sm",children:(0,s.jsxs)("div",{className:"text-gray-700",children:["router_settings:",(0,s.jsx)("br",{}),"\xa0\xa0model_group_alias:",0===Object.keys(b).length?(0,s.jsxs)("span",{className:"text-gray-500",children:[(0,s.jsx)("br",{}),"\xa0\xa0\xa0\xa0# No aliases configured yet"]}):Object.entries(b).map(e=>{let[l,t]=e;return(0,s.jsxs)("span",{children:[(0,s.jsx)("br",{}),'\xa0\xa0\xa0\xa0"',l,'": "',t,'"']},l)})]})})]})]})]})},lD=t(10900),lB=t(12514),lG=t(49566),lU=t(30401),lH=t(78867),lK=t(59872),lJ=e=>{let{isVisible:l,onCancel:t,onSuccess:r,modelData:i,accessToken:n,userRole:o}=e,[d]=eg.Z.useForm(),[c,m]=(0,f.useState)(!1),[u,h]=(0,f.useState)([]),[x,p]=(0,f.useState)([]),[g,j]=(0,f.useState)(!1),[v,b]=(0,f.useState)(!1),[y,N]=(0,f.useState)(null);(0,f.useEffect)(()=>{l&&i&&w()},[l,i]),(0,f.useEffect)(()=>{let e=async()=>{if(n)try{let e=await (0,a.modelAvailableCall)(n,"","",!1,null,!0,!0);h(e.data.map(e=>e.id))}catch(e){console.error("Error fetching model access groups:",e)}},t=async()=>{if(n)try{let e=await (0,e1.p)(n);p(e)}catch(e){console.error("Error fetching model info:",e)}};l&&(e(),t())},[l,n]);let w=()=>{try{var e,l,t,s,a,r;let n=null;(null===(e=i.litellm_params)||void 0===e?void 0:e.auto_router_config)&&(n="string"==typeof i.litellm_params.auto_router_config?JSON.parse(i.litellm_params.auto_router_config):i.litellm_params.auto_router_config),N(n),d.setFieldsValue({auto_router_name:i.model_name,auto_router_default_model:(null===(l=i.litellm_params)||void 0===l?void 0:l.auto_router_default_model)||"",auto_router_embedding_model:(null===(t=i.litellm_params)||void 0===t?void 0:t.auto_router_embedding_model)||"",model_access_group:(null===(s=i.model_info)||void 0===s?void 0:s.access_groups)||[]});let o=new Set(x.map(e=>e.model_group));j(!o.has(null===(a=i.litellm_params)||void 0===a?void 0:a.auto_router_default_model)),b(!o.has(null===(r=i.litellm_params)||void 0===r?void 0:r.auto_router_embedding_model))}catch(e){console.error("Error parsing auto router config:",e),eo.Z.fromBackend("Error loading auto router configuration")}},Z=async()=>{try{m(!0);let e=await d.validateFields(),l={...i.litellm_params,auto_router_config:JSON.stringify(y),auto_router_default_model:e.auto_router_default_model,auto_router_embedding_model:e.auto_router_embedding_model||void 0},s={...i.model_info,access_groups:e.model_access_group||[]},o={model_name:e.auto_router_name,litellm_params:l,model_info:s};await (0,a.modelPatchUpdateCall)(n,o,i.model_info.id);let c={...i,model_name:e.auto_router_name,litellm_params:l,model_info:s};eo.Z.success("Auto router configuration updated successfully"),r(c),t()}catch(e){console.error("Error updating auto router:",e),eo.Z.fromBackend("Failed to update auto router configuration")}finally{m(!1)}},C=x.map(e=>({value:e.model_group,label:e.model_group}));return(0,s.jsx)(ea.Z,{title:"Edit Auto Router Configuration",open:l,onCancel:t,footer:[(0,s.jsx)(_.ZP,{onClick:t,children:"Cancel"},"cancel"),(0,s.jsx)(_.ZP,{loading:c,onClick:Z,children:"Save Changes"},"submit")],width:1e3,destroyOnClose:!0,children:(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsx)(eN.x,{className:"text-gray-600",children:"Edit the auto router configuration including routing logic, default models, and access settings."}),(0,s.jsxs)(eg.Z,{form:d,layout:"vertical",className:"space-y-4",children:[(0,s.jsx)(eg.Z.Item,{label:"Auto Router Name",name:"auto_router_name",rules:[{required:!0,message:"Auto router name is required"}],children:(0,s.jsx)(eN.o,{placeholder:"e.g., auto_router_1, smart_routing"})}),(0,s.jsx)("div",{className:"w-full",children:(0,s.jsx)(e9,{modelInfo:x,value:y,onChange:e=>{N(e)}})}),(0,s.jsx)(eg.Z.Item,{label:"Default Model",name:"auto_router_default_model",rules:[{required:!0,message:"Default model is required"}],children:(0,s.jsx)(ev.default,{placeholder:"Select a default model",onChange:e=>{j("custom"===e)},options:[...C,{value:"custom",label:"Enter custom model name"}],showSearch:!0})}),(0,s.jsx)(eg.Z.Item,{label:"Embedding Model",name:"auto_router_embedding_model",children:(0,s.jsx)(ev.default,{placeholder:"Select an embedding model (optional)",onChange:e=>{b("custom"===e)},options:[...C,{value:"custom",label:"Enter custom model name"}],showSearch:!0,allowClear:!0})}),"Admin"===o&&(0,s.jsx)(eg.Z.Item,{label:"Model Access Groups",name:"model_access_group",tooltip:"Control who can access this auto router",children:(0,s.jsx)(ev.default,{mode:"tags",showSearch:!0,placeholder:"Select existing groups or type to create new ones",optionFilterProp:"children",tokenSeparators:[","],options:u.map(e=>({value:e,label:e})),maxTagCount:"responsive",allowClear:!0})})]})]})})};let{Title:lW,Link:lY}=Q.default;var l$=e=>{let{isVisible:l,onCancel:t,onAddCredential:a,existingCredential:r,setIsCredentialModalOpen:i}=e,[n]=eg.Z.useForm();return console.log("existingCredential in add credentials tab: ".concat(JSON.stringify(r))),(0,s.jsx)(ea.Z,{title:"Reuse Credentials",visible:l,onCancel:()=>{t(),n.resetFields()},footer:null,width:600,children:(0,s.jsxs)(eg.Z,{form:n,onFinish:e=>{a(e),n.resetFields(),i(!1)},layout:"vertical",children:[(0,s.jsx)(eg.Z.Item,{label:"Credential Name:",name:"credential_name",rules:[{required:!0,message:"Credential name is required"}],initialValue:null==r?void 0:r.credential_name,children:(0,s.jsx)(ej.o,{placeholder:"Enter a friendly name for these credentials"})}),Object.entries((null==r?void 0:r.credential_values)||{}).map(e=>{let[l,t]=e;return(0,s.jsx)(eg.Z.Item,{label:l,name:l,initialValue:t,children:(0,s.jsx)(ej.o,{placeholder:"Enter ".concat(l),disabled:!0})},l)}),(0,s.jsxs)("div",{className:"flex justify-between items-center",children:[(0,s.jsx)(M.Z,{title:"Get help on our github",children:(0,s.jsx)(lY,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)(_.ZP,{onClick:()=>{t(),n.resetFields()},style:{marginRight:10},children:"Cancel"}),(0,s.jsx)(_.ZP,{htmlType:"submit",children:"Reuse Credentials"})]})]})]})})};function lX(e){var l,t,r,i,n,o,d,c,h,x,p,g,j,v,b,y,N,w,Z,C,A,P,F,I,V,q,B,G,U,H,J,Y,$;let{modelId:X,onClose:Q,accessToken:ee,userID:el,userRole:et,onModelUpdate:es,modelAccessGroups:er}=e,[ei]=eg.Z.useForm(),[en,ed]=(0,f.useState)(null),[ec,em]=(0,f.useState)(!1),[eu,eh]=(0,f.useState)(!1),[ex,ep]=(0,f.useState)(!1),[ej,e_]=(0,f.useState)(!1),[eb,ey]=(0,f.useState)(!1),[eN,ew]=(0,f.useState)(!1),[eZ,eC]=(0,f.useState)(null),[eS,eA]=(0,f.useState)(!1),[eE,eP]=(0,f.useState)({}),[eM,eL]=(0,f.useState)(!1),[eF,eI]=(0,f.useState)([]),[eT,eR]=(0,f.useState)({}),{data:eV,isLoading:eq}=(0,u.XP)(1,50,void 0,X),{data:eU}=m(),{data:eH}=(0,u.VI)(),eK=e=>null!=eU&&"object"==typeof eU&&e in eU?eU[e].litellm_provider:"openai",eJ=(0,f.useMemo)(()=>(null==eV?void 0:eV.data)&&0!==eV.data.length&&K(eV,eK).data[0]||null,[eV,eU]),eW=("Admin"===et||(null==eJ?void 0:null===(l=eJ.model_info)||void 0===l?void 0:l.created_by)===el)&&(null==eJ?void 0:null===(t=eJ.model_info)||void 0===t?void 0:t.db_model),eY="Admin"===et,e$=(null==eJ?void 0:null===(r=eJ.litellm_params)||void 0===r?void 0:r.auto_router_config)!=null,eX=(null==eJ?void 0:null===(i=eJ.litellm_params)||void 0===i?void 0:i.litellm_credential_name)!=null&&(null==eJ?void 0:null===(n=eJ.litellm_params)||void 0===n?void 0:n.litellm_credential_name)!=void 0;(0,f.useEffect)(()=>{if(eJ&&!en){var e,l,t,s,a,r,i;let n=eJ;n.litellm_model_name||(n={...n,litellm_model_name:null!==(i=null!==(r=null!==(a=null==n?void 0:null===(l=n.litellm_params)||void 0===l?void 0:l.litellm_model_name)&&void 0!==a?a:null==n?void 0:null===(t=n.litellm_params)||void 0===t?void 0:t.model)&&void 0!==r?r:null==n?void 0:null===(s=n.model_info)||void 0===s?void 0:s.key)&&void 0!==i?i:null}),ed(n),(null==n?void 0:null===(e=n.litellm_params)||void 0===e?void 0:e.cache_control_injection_points)&&eA(!0)}},[eJ,en]),(0,f.useEffect)(()=>{let e=async()=>{var e,l,t,s,r,i,n;if(!ee||eJ)return;let o=await (0,a.modelInfoV1Call)(ee,X);console.log("modelInfoResponse, ",o);let d=o.data[0];d&&!d.litellm_model_name&&(d={...d,litellm_model_name:null!==(n=null!==(i=null!==(r=null==d?void 0:null===(l=d.litellm_params)||void 0===l?void 0:l.litellm_model_name)&&void 0!==r?r:null==d?void 0:null===(t=d.litellm_params)||void 0===t?void 0:t.model)&&void 0!==i?i:null==d?void 0:null===(s=d.model_info)||void 0===s?void 0:s.key)&&void 0!==n?n:null}),ed(d),(null==d?void 0:null===(e=d.litellm_params)||void 0===e?void 0:e.cache_control_injection_points)&&eA(!0)},l=async()=>{if(ee)try{let e=(await (0,a.getGuardrailsList)(ee)).guardrails.map(e=>e.guardrail_name);eI(e)}catch(e){console.error("Failed to fetch guardrails:",e)}},t=async()=>{if(ee)try{let e=await (0,a.tagListCall)(ee);eR(e)}catch(e){console.error("Failed to fetch tags:",e)}};(async()=>{if(console.log("accessToken, ",ee),!ee||eX)return;let e=await (0,a.credentialGetCall)(ee,null,X);console.log("existingCredentialResponse, ",e),eC({credential_name:e.credential_name,credential_values:e.credential_values,credential_info:e.credential_info})})(),e(),l(),t()},[ee,X]);let eQ=async e=>{var l;if(console.log("values, ",e),!ee)return;let t={credential_name:e.credential_name,model_id:X,credential_info:{custom_llm_provider:null===(l=en.litellm_params)||void 0===l?void 0:l.custom_llm_provider}};eo.Z.info("Storing credential.."),console.log("credentialResponse, ",await (0,a.credentialCreateCall)(ee,t)),eo.Z.success("Credential stored successfully")},e0=async e=>{try{var l;let t;if(!ee)return;ey(!0),console.log("values.model_name, ",e.model_name);let s={};try{s=e.litellm_extra_params?JSON.parse(e.litellm_extra_params):{}}catch(e){eo.Z.fromBackend("Invalid JSON in LiteLLM Params"),ey(!1);return}let r={...e.litellm_params,...s,model:e.litellm_model_name,api_base:e.api_base,custom_llm_provider:e.custom_llm_provider,organization:e.organization,tpm:e.tpm,rpm:e.rpm,max_retries:e.max_retries,timeout:e.timeout,stream_timeout:e.stream_timeout,input_cost_per_token:e.input_cost/1e6,output_cost_per_token:e.output_cost/1e6,tags:e.tags};e.guardrails&&(r.guardrails=e.guardrails),e.cache_control&&(null===(l=e.cache_control_injection_points)||void 0===l?void 0:l.length)>0?r.cache_control_injection_points=e.cache_control_injection_points:delete r.cache_control_injection_points;try{t=e.model_info?JSON.parse(e.model_info):eJ.model_info,e.model_access_group&&(t={...t,access_groups:e.model_access_group}),void 0!==e.health_check_model&&(t={...t,health_check_model:e.health_check_model})}catch(e){eo.Z.fromBackend("Invalid JSON in Model Info");return}let i={model_name:e.model_name,litellm_params:r,model_info:t};await (0,a.modelPatchUpdateCall)(ee,i,X);let n={...en,model_name:e.model_name,litellm_model_name:e.litellm_model_name,litellm_params:r,model_info:t};ed(n),es&&es(n),eo.Z.success("Model settings updated successfully"),e_(!1),ew(!1)}catch(e){console.error("Error updating model:",e),eo.Z.fromBackend("Failed to update model settings")}finally{ey(!1)}};if(eq)return(0,s.jsxs)("div",{className:"p-4",children:[(0,s.jsx)(E.Z,{icon:lD.Z,variant:"light",onClick:Q,className:"mb-4",children:"Back to Models"}),(0,s.jsx)(D.Z,{children:"Loading..."})]});if(!eJ)return(0,s.jsxs)("div",{className:"p-4",children:[(0,s.jsx)(E.Z,{icon:lD.Z,variant:"light",onClick:Q,className:"mb-4",children:"Back to Models"}),(0,s.jsx)(D.Z,{children:"Model not found"})]});let e1=async()=>{if(ee)try{var e,l,t;eo.Z.info("Testing connection...");let s=await (0,a.testConnectionRequest)(ee,{custom_llm_provider:en.litellm_params.custom_llm_provider,litellm_credential_name:en.litellm_params.litellm_credential_name,model:en.litellm_model_name},{mode:null===(e=en.model_info)||void 0===e?void 0:e.mode},null===(l=en.model_info)||void 0===l?void 0:l.mode);if("success"===s.status)eo.Z.success("Connection test successful!");else throw Error((null==s?void 0:null===(t=s.result)||void 0===t?void 0:t.error)||(null==s?void 0:s.message)||"Unknown error")}catch(e){e instanceof Error?eo.Z.error("Error testing connection: "+(0,lf.aS)(e.message,100)):eo.Z.error("Error testing connection: "+String(e))}},e2=async()=>{try{if(eh(!0),!ee)return;await (0,a.modelDeleteCall)(ee,X),eo.Z.success("Model deleted successfully"),es&&es({deleted:!0,model_info:{id:X}}),Q()}catch(e){console.error("Error deleting the model:",e),eo.Z.fromBackend("Failed to delete model")}finally{eh(!1),em(!1)}},e4=async(e,l)=>{await (0,lK.vQ)(e)&&(eP(e=>({...e,[l]:!0})),setTimeout(()=>{eP(e=>({...e,[l]:!1}))},2e3))},e5=eJ.litellm_model_name.includes("*");return console.log("isWildcardModel, ",e5),(0,s.jsxs)("div",{className:"p-4",children:[(0,s.jsxs)("div",{className:"flex justify-between items-center mb-6",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(E.Z,{icon:lD.Z,variant:"light",onClick:Q,className:"mb-4",children:"Back to Models"}),(0,s.jsxs)(W.Z,{children:["Public Model Name: ",T(eJ)]}),(0,s.jsxs)("div",{className:"flex items-center cursor-pointer",children:[(0,s.jsx)(D.Z,{className:"text-gray-500 font-mono",children:eJ.model_info.id}),(0,s.jsx)(_.ZP,{type:"text",size:"small",icon:eE["model-id"]?(0,s.jsx)(lU.Z,{size:12}):(0,s.jsx)(lH.Z,{size:12}),onClick:()=>e4(eJ.model_info.id,"model-id"),className:"left-2 z-10 transition-all duration-200 ".concat(eE["model-id"]?"text-green-600 bg-green-50 border-green-200":"text-gray-500 hover:text-gray-700 hover:bg-gray-100")})]})]}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(E.Z,{variant:"secondary",icon:eO.Z,onClick:e1,className:"flex items-center gap-2","data-testid":"test-connection-button",children:"Test Connection"}),(0,s.jsx)(E.Z,{icon:k.Z,variant:"secondary",onClick:()=>ep(!0),className:"flex items-center",disabled:!eY,"data-testid":"reuse-credentials-button",children:"Re-use Credentials"}),(0,s.jsx)(E.Z,{icon:S.Z,variant:"secondary",onClick:()=>em(!0),className:"flex items-center text-red-500 border-red-500 hover:text-red-700",disabled:!eW,"data-testid":"delete-model-button",children:"Delete Model"})]})]}),(0,s.jsxs)(eD.Z,{children:[(0,s.jsxs)(eB.Z,{className:"mb-6",children:[(0,s.jsx)(ez.Z,{children:"Overview"}),(0,s.jsx)(ez.Z,{children:"Raw JSON"})]}),(0,s.jsxs)(eG.Z,{children:[(0,s.jsxs)(z.Z,{children:[(0,s.jsxs)(O.Z,{numItems:1,numItemsSm:2,numItemsLg:3,className:"gap-6 mb-6",children:[(0,s.jsxs)(lB.Z,{children:[(0,s.jsx)(D.Z,{children:"Provider"}),(0,s.jsxs)("div",{className:"mt-2 flex items-center space-x-2",children:[eJ.provider&&(0,s.jsx)("img",{src:(0,L.dr)(eJ.provider).logo,alt:"".concat(eJ.provider," logo"),className:"w-4 h-4",onError:e=>{let l=e.currentTarget,t=l.parentElement;if(t&&t.contains(l))try{var s;let e=document.createElement("div");e.className="w-4 h-4 rounded-full bg-gray-200 flex items-center justify-center text-xs",e.textContent=(null===(s=eJ.provider)||void 0===s?void 0:s.charAt(0))||"-",t.replaceChild(e,l)}catch(e){console.error("Failed to replace provider logo fallback:",e)}}}),(0,s.jsx)(W.Z,{children:eJ.provider||"Not Set"})]})]}),(0,s.jsxs)(lB.Z,{children:[(0,s.jsx)(D.Z,{children:"LiteLLM Model"}),(0,s.jsx)("div",{className:"mt-2 overflow-hidden",children:(0,s.jsx)(M.Z,{title:eJ.litellm_model_name||"Not Set",children:(0,s.jsx)("div",{className:"break-all text-sm font-medium leading-relaxed cursor-pointer",children:eJ.litellm_model_name||"Not Set"})})})]}),(0,s.jsxs)(lB.Z,{children:[(0,s.jsx)(D.Z,{children:"Pricing"}),(0,s.jsxs)("div",{className:"mt-2",children:[(0,s.jsxs)(D.Z,{children:["Input: $",eJ.input_cost,"/1M tokens"]}),(0,s.jsxs)(D.Z,{children:["Output: $",eJ.output_cost,"/1M tokens"]})]})]})]}),(0,s.jsxs)("div",{className:"mb-6 text-sm text-gray-500 flex items-center gap-x-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-x-2",children:[(0,s.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})}),"Created At"," ",eJ.model_info.created_at?new Date(eJ.model_info.created_at).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}):"Not Set"]}),(0,s.jsxs)("div",{className:"flex items-center gap-x-2",children:[(0,s.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"})}),"Created By ",eJ.model_info.created_by||"Not Set"]})]}),(0,s.jsxs)(lB.Z,{children:[(0,s.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,s.jsx)(W.Z,{children:"Model Settings"}),(0,s.jsxs)("div",{className:"flex gap-2",children:[e$&&eW&&!eN&&(0,s.jsx)(E.Z,{onClick:()=>eL(!0),className:"flex items-center",children:"Edit Auto Router"}),eW?!eN&&(0,s.jsx)(E.Z,{onClick:()=>ew(!0),className:"flex items-center",children:"Edit Settings"}):(0,s.jsx)(M.Z,{title:"Only DB models can be edited. You must be an admin or the creator of the model to edit it.",children:(0,s.jsx)(R.Z,{})})]})]}),en?(0,s.jsx)(eg.Z,{form:ei,onFinish:e0,initialValues:{model_name:en.model_name,litellm_model_name:en.litellm_model_name,api_base:en.litellm_params.api_base,custom_llm_provider:en.litellm_params.custom_llm_provider,organization:en.litellm_params.organization,tpm:en.litellm_params.tpm,rpm:en.litellm_params.rpm,max_retries:en.litellm_params.max_retries,timeout:en.litellm_params.timeout,stream_timeout:en.litellm_params.stream_timeout,input_cost:en.litellm_params.input_cost_per_token?1e6*en.litellm_params.input_cost_per_token:(null===(o=en.model_info)||void 0===o?void 0:o.input_cost_per_token)*1e6||null,output_cost:(null===(d=en.litellm_params)||void 0===d?void 0:d.output_cost_per_token)?1e6*en.litellm_params.output_cost_per_token:(null===(c=en.model_info)||void 0===c?void 0:c.output_cost_per_token)*1e6||null,cache_control:null!==(h=en.litellm_params)&&void 0!==h&&!!h.cache_control_injection_points,cache_control_injection_points:(null===(x=en.litellm_params)||void 0===x?void 0:x.cache_control_injection_points)||[],model_access_group:Array.isArray(null===(p=en.model_info)||void 0===p?void 0:p.access_groups)?en.model_info.access_groups:[],guardrails:Array.isArray(null===(g=en.litellm_params)||void 0===g?void 0:g.guardrails)?en.litellm_params.guardrails:[],tags:Array.isArray(null===(j=en.litellm_params)||void 0===j?void 0:j.tags)?en.litellm_params.tags:[],health_check_model:e5?null===(v=en.model_info)||void 0===v?void 0:v.health_check_model:null,litellm_extra_params:JSON.stringify(en.litellm_params||{},null,2)},layout:"vertical",onValuesChange:()=>e_(!0),children:(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Model Name"}),eN?(0,s.jsx)(eg.Z.Item,{name:"model_name",className:"mb-0",children:(0,s.jsx)(lG.Z,{placeholder:"Enter model name"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:en.model_name})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"LiteLLM Model Name"}),eN?(0,s.jsx)(eg.Z.Item,{name:"litellm_model_name",className:"mb-0",children:(0,s.jsx)(lG.Z,{placeholder:"Enter LiteLLM model name"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:en.litellm_model_name})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Input Cost (per 1M tokens)"}),eN?(0,s.jsx)(eg.Z.Item,{name:"input_cost",className:"mb-0",children:(0,s.jsx)(lx.Z,{placeholder:"Enter input cost"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null==en?void 0:null===(b=en.litellm_params)||void 0===b?void 0:b.input_cost_per_token)?((null===(y=en.litellm_params)||void 0===y?void 0:y.input_cost_per_token)*1e6).toFixed(4):(null==en?void 0:null===(N=en.model_info)||void 0===N?void 0:N.input_cost_per_token)?(1e6*en.model_info.input_cost_per_token).toFixed(4):null})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Output Cost (per 1M tokens)"}),eN?(0,s.jsx)(eg.Z.Item,{name:"output_cost",className:"mb-0",children:(0,s.jsx)(lx.Z,{placeholder:"Enter output cost"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null==en?void 0:null===(w=en.litellm_params)||void 0===w?void 0:w.output_cost_per_token)?(1e6*en.litellm_params.output_cost_per_token).toFixed(4):(null==en?void 0:null===(Z=en.model_info)||void 0===Z?void 0:Z.output_cost_per_token)?(1e6*en.model_info.output_cost_per_token).toFixed(4):null})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"API Base"}),eN?(0,s.jsx)(eg.Z.Item,{name:"api_base",className:"mb-0",children:(0,s.jsx)(lG.Z,{placeholder:"Enter API base"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(C=en.litellm_params)||void 0===C?void 0:C.api_base)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Custom LLM Provider"}),eN?(0,s.jsx)(eg.Z.Item,{name:"custom_llm_provider",className:"mb-0",children:(0,s.jsx)(lG.Z,{placeholder:"Enter custom LLM provider"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(A=en.litellm_params)||void 0===A?void 0:A.custom_llm_provider)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Organization"}),eN?(0,s.jsx)(eg.Z.Item,{name:"organization",className:"mb-0",children:(0,s.jsx)(lG.Z,{placeholder:"Enter organization"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(P=en.litellm_params)||void 0===P?void 0:P.organization)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"TPM (Tokens per Minute)"}),eN?(0,s.jsx)(eg.Z.Item,{name:"tpm",className:"mb-0",children:(0,s.jsx)(lx.Z,{placeholder:"Enter TPM"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(F=en.litellm_params)||void 0===F?void 0:F.tpm)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"RPM (Requests per Minute)"}),eN?(0,s.jsx)(eg.Z.Item,{name:"rpm",className:"mb-0",children:(0,s.jsx)(lx.Z,{placeholder:"Enter RPM"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(I=en.litellm_params)||void 0===I?void 0:I.rpm)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Max Retries"}),eN?(0,s.jsx)(eg.Z.Item,{name:"max_retries",className:"mb-0",children:(0,s.jsx)(lx.Z,{placeholder:"Enter max retries"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(V=en.litellm_params)||void 0===V?void 0:V.max_retries)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Timeout (seconds)"}),eN?(0,s.jsx)(eg.Z.Item,{name:"timeout",className:"mb-0",children:(0,s.jsx)(lx.Z,{placeholder:"Enter timeout"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(q=en.litellm_params)||void 0===q?void 0:q.timeout)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Stream Timeout (seconds)"}),eN?(0,s.jsx)(eg.Z.Item,{name:"stream_timeout",className:"mb-0",children:(0,s.jsx)(lx.Z,{placeholder:"Enter stream timeout"})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(B=en.litellm_params)||void 0===B?void 0:B.stream_timeout)||"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Model Access Groups"}),eN?(0,s.jsx)(eg.Z.Item,{name:"model_access_group",className:"mb-0",children:(0,s.jsx)(ev.default,{mode:"tags",showSearch:!0,placeholder:"Select existing groups or type to create new ones",optionFilterProp:"children",tokenSeparators:[","],maxTagCount:"responsive",allowClear:!0,style:{width:"100%"},options:null==er?void 0:er.map(e=>({value:e,label:e}))})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(G=en.model_info)||void 0===G?void 0:G.access_groups)?Array.isArray(en.model_info.access_groups)?en.model_info.access_groups.length>0?(0,s.jsx)("div",{className:"flex flex-wrap gap-1",children:en.model_info.access_groups.map((e,l)=>(0,s.jsx)("span",{className:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800",children:e},l))}):"No groups assigned":en.model_info.access_groups:"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsxs)(D.Z,{className:"font-medium",children:["Guardrails",(0,s.jsx)(M.Z,{title:"Apply safety guardrails to this model to filter content or enforce policies",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(R.Z,{style:{marginLeft:"4px"}})})})]}),eN?(0,s.jsx)(eg.Z.Item,{name:"guardrails",className:"mb-0",children:(0,s.jsx)(ev.default,{mode:"tags",showSearch:!0,placeholder:"Select existing guardrails or type to create new ones",optionFilterProp:"children",tokenSeparators:[","],maxTagCount:"responsive",allowClear:!0,style:{width:"100%"},options:eF.map(e=>({value:e,label:e}))})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(U=en.litellm_params)||void 0===U?void 0:U.guardrails)?Array.isArray(en.litellm_params.guardrails)?en.litellm_params.guardrails.length>0?(0,s.jsx)("div",{className:"flex flex-wrap gap-1",children:en.litellm_params.guardrails.map((e,l)=>(0,s.jsx)("span",{className:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800",children:e},l))}):"No guardrails assigned":en.litellm_params.guardrails:"Not Set"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Tags"}),eN?(0,s.jsx)(eg.Z.Item,{name:"tags",className:"mb-0",children:(0,s.jsx)(ev.default,{mode:"tags",showSearch:!0,placeholder:"Select existing tags or type to create new ones",optionFilterProp:"children",tokenSeparators:[","],maxTagCount:"responsive",allowClear:!0,style:{width:"100%"},options:Object.values(eT).map(e=>({value:e.name,label:e.name,title:e.description||e.name}))})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(H=en.litellm_params)||void 0===H?void 0:H.tags)?Array.isArray(en.litellm_params.tags)?en.litellm_params.tags.length>0?(0,s.jsx)("div",{className:"flex flex-wrap gap-1",children:en.litellm_params.tags.map((e,l)=>(0,s.jsx)("span",{className:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-purple-100 text-purple-800",children:e},l))}):"No tags assigned":en.litellm_params.tags:"Not Set"})]}),e5&&(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Health Check Model"}),eN?(0,s.jsx)(eg.Z.Item,{name:"health_check_model",className:"mb-0",children:(0,s.jsx)(ev.default,{showSearch:!0,placeholder:"Select existing health check model",optionFilterProp:"children",allowClear:!0,options:(()=>{var e;let l=eJ.litellm_model_name.split("/")[0];return(null==eH?void 0:null===(e=eH.data)||void 0===e?void 0:e.filter(e=>{var t;return(null===(t=e.providers)||void 0===t?void 0:t.includes(l))&&e.model_group!==eJ.litellm_model_name}).map(e=>({value:e.model_group,label:e.model_group})))||[]})()})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(J=en.model_info)||void 0===J?void 0:J.health_check_model)||"Not Set"})]}),eN?(0,s.jsx)(lg,{form:ei,showCacheControl:eS,onCacheControlChange:e=>eA(e)}):(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Cache Control"}),(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(null===(Y=en.litellm_params)||void 0===Y?void 0:Y.cache_control_injection_points)?(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{children:"Enabled"}),(0,s.jsx)("div",{className:"mt-2",children:en.litellm_params.cache_control_injection_points.map((e,l)=>(0,s.jsxs)("div",{className:"text-sm text-gray-600 mb-1",children:["Location: ",e.location,",",e.role&&(0,s.jsxs)("span",{children:[" Role: ",e.role]}),void 0!==e.index&&(0,s.jsxs)("span",{children:[" Index: ",e.index]})]},l))})]}):"Disabled"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Model Info"}),eN?(0,s.jsx)(eg.Z.Item,{name:"model_info",className:"mb-0",children:(0,s.jsx)(ek.default.TextArea,{rows:4,placeholder:'{"gpt-4": 100, "claude-v1": 200}',defaultValue:JSON.stringify(eJ.model_info,null,2)})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(0,s.jsx)("pre",{className:"bg-gray-100 p-2 rounded text-xs overflow-auto mt-1",children:JSON.stringify(en.model_info,null,2)})})]}),(0,s.jsxs)("div",{children:[(0,s.jsxs)(D.Z,{className:"font-medium",children:["LiteLLM Params",(0,s.jsx)(M.Z,{title:"Optional litellm params used for making a litellm.completion() call. Some params are automatically added by LiteLLM.",children:(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,s.jsx)(R.Z,{style:{marginLeft:"4px"}})})})]}),eN?(0,s.jsx)(eg.Z.Item,{name:"litellm_extra_params",rules:[{validator:lf.Ac}],children:(0,s.jsx)(ek.default.TextArea,{rows:4,placeholder:'{ "rpm": 100, "timeout": 0, "stream_timeout": 0 }'})}):(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:(0,s.jsx)("pre",{className:"bg-gray-100 p-2 rounded text-xs overflow-auto mt-1",children:JSON.stringify(en.litellm_params,null,2)})})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(D.Z,{className:"font-medium",children:"Team ID"}),(0,s.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:eJ.model_info.team_id||"Not Set"})]})]}),eN&&(0,s.jsxs)("div",{className:"mt-6 flex justify-end gap-2",children:[(0,s.jsx)(E.Z,{variant:"secondary",onClick:()=>{ei.resetFields(),e_(!1),ew(!1)},disabled:eb,children:"Cancel"}),(0,s.jsx)(E.Z,{variant:"primary",onClick:()=>ei.submit(),loading:eb,children:"Save Changes"})]})]})}):(0,s.jsx)(D.Z,{children:"Loading..."})]})]}),(0,s.jsx)(z.Z,{children:(0,s.jsx)(lB.Z,{children:(0,s.jsx)("pre",{className:"bg-gray-100 p-4 rounded text-xs overflow-auto",children:JSON.stringify(eJ,null,2)})})})]})]}),(0,s.jsx)(ef.Z,{isOpen:ec,title:"Delete Model",alertMessage:"This action cannot be undone.",message:"Are you sure you want to delete this model?",resourceInformationTitle:"Model Information",resourceInformation:[{label:"Model Name",value:(null==eJ?void 0:eJ.model_name)||"Not Set"},{label:"LiteLLM Model Name",value:(null==eJ?void 0:eJ.litellm_model_name)||"Not Set"},{label:"Provider",value:(null==eJ?void 0:eJ.provider)||"Not Set"},{label:"Created By",value:(null==eJ?void 0:null===($=eJ.model_info)||void 0===$?void 0:$.created_by)||"Not Set"}],onCancel:()=>em(!1),onOk:e2,confirmLoading:eu}),ex&&!eX?(0,s.jsx)(l$,{isVisible:ex,onCancel:()=>ep(!1),onAddCredential:eQ,existingCredential:eZ,setIsCredentialModalOpen:ep}):(0,s.jsx)(ea.Z,{open:ex,onCancel:()=>ep(!1),title:"Using Existing Credential",children:(0,s.jsx)(D.Z,{children:eJ.litellm_params.litellm_credential_name})}),(0,s.jsx)(lJ,{isVisible:eM,onCancel:()=>eL(!1),onSuccess:e=>{ed(e),es&&es(e)},modelData:en||eJ,accessToken:ee||"",userRole:et||""})]})}var lQ=t(27593),l0=t(56147),l1=e=>{var l;let{premiumUser:t,teams:r}=e,{accessToken:i,token:o,userRole:c,userId:x}=(0,n.Z)(),[p]=eg.Z.useForm(),[g,j]=(0,f.useState)(""),[v,_]=(0,f.useState)([]),[b,y]=(0,f.useState)(L.Cl.Anthropic),[N,w]=(0,f.useState)(null),[Z,C]=(0,f.useState)(null),[k,S]=(0,f.useState)(null),[A,E]=(0,f.useState)(0),[M,F]=(0,f.useState)({}),[I,R]=(0,f.useState)(!1),[V,q]=(0,f.useState)(null),[B,G]=(0,f.useState)(null),[U,H]=(0,f.useState)(0),W=(0,eV.NL)(),{data:Y,isLoading:$,refetch:ee}=(0,u.XP)(),{data:el,isLoading:et}=m(),{data:es,isLoading:ea}=d(),er=(null==es?void 0:es.credentials)||[],{data:ei,isLoading:en}=(0,h.L)(),ed=(0,f.useMemo)(()=>{if(!(null==Y?void 0:Y.data))return[];let e=new Set;for(let l of Y.data)e.add(l.model_name);return Array.from(e).sort()},[null==Y?void 0:Y.data]),ec=(0,f.useMemo)(()=>{if(!(null==Y?void 0:Y.data))return[];let e=new Set;for(let l of Y.data){let t=l.model_info;if(null==t?void 0:t.access_groups)for(let l of t.access_groups)e.add(l)}return Array.from(e)},[null==Y?void 0:Y.data]),eu=(0,f.useMemo)(()=>(null==Y?void 0:Y.data)?Y.data.map(e=>e.model_name):[],[null==Y?void 0:Y.data]),ex=e=>null!=el&&"object"==typeof el&&e in el?el[e].litellm_provider:"openai",ep=(0,f.useMemo)(()=>(null==Y?void 0:Y.data)?K(Y,ex):{data:[]},[null==Y?void 0:Y.data,ex]),ef=c&&(0,eR.P4)(c),ej=c&&eR.lo.includes(c),ev=x&&(0,eR.yV)(r,x),e_=ej&&(null==ei?void 0:null===(l=ei.values)||void 0===l?void 0:l.disable_model_add_for_internal_users)===!0,eb=!ef&&(e_||!ev),ey={name:"file",accept:".json",pastable:!1,beforeUpload:e=>{if("application/json"===e.type){let l=new FileReader;l.onload=e=>{if(e.target){let l=e.target.result;p.setFieldsValue({vertex_credentials:l})}},l.readAsText(e)}return!1},onChange(e){"done"===e.file.status?eo.Z.success("".concat(e.file.name," file uploaded successfully")):"error"===e.file.status&&eo.Z.fromBackend("".concat(e.file.name," file upload failed."))}},eN=()=>{j(new Date().toLocaleString()),W.invalidateQueries({queryKey:["models","list"]}),ee()},ew=async()=>{if(i)try{let e={router_settings:{}};"global"===N?(k&&(e.router_settings.retry_policy=k),eo.Z.success("Global retry settings saved successfully")):(Z&&(e.router_settings.model_group_retry_policy=Z),eo.Z.success("Retry settings saved successfully for ".concat(N))),await (0,a.setCallbacksCall)(i,e)}catch(e){eo.Z.fromBackend("Failed to save retry settings")}};if((0,f.useEffect)(()=>{if(!i||!o||!c||!x||!Y)return;let e=async()=>{try{let e=(await (0,a.getCallbacksCall)(i,x,c)).router_settings,l=e.model_group_retry_policy,t=e.num_retries;C(l),S(e.retry_policy),E(t);let s=e.model_group_alias||{};F(s)}catch(e){console.error("Error fetching model data:",e)}};i&&o&&c&&x&&Y&&e()},[i,o,c,x,Y]),c&&"Admin Viewer"==c){let{Title:e,Paragraph:l}=Q.default;return(0,s.jsxs)("div",{children:[(0,s.jsx)(e,{level:1,children:"Access Denied"}),(0,s.jsx)(l,{children:"Ask your proxy admin for access to view all models"})]})}let eZ=async()=>{try{let e=await p.validateFields();await eh(e,i,p,eN)}catch(t){var e;let l=(null===(e=t.errorFields)||void 0===e?void 0:e.map(e=>"".concat(e.name.join("."),": ").concat(e.errors.join(", "))).join(" | "))||"Unknown validation error";eo.Z.fromBackend("Please fill in the following required fields: ".concat(l))}};return(Object.keys(L.Cl).find(e=>L.Cl[e]===b),B)?(0,s.jsx)("div",{className:"w-full h-full",children:(0,s.jsx)(l0.Z,{teamId:B,onClose:()=>G(null),accessToken:i,is_team_admin:"Admin"===c,is_proxy_admin:"Proxy Admin"===c,userModels:eu,editTeam:!1,onUpdate:eN,premiumUser:t})}):(0,s.jsx)("div",{className:"w-full mx-4 h-[75vh]",children:(0,s.jsx)(O.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:(0,s.jsxs)(eq.Z,{numColSpan:1,className:"flex flex-col gap-2",children:[(0,s.jsx)("div",{className:"flex justify-between items-center mb-4",children:(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold",children:"Model Management"}),eR.ZL.includes(c)?(0,s.jsx)("p",{className:"text-sm text-gray-600",children:"Add and manage models for the proxy"}):(0,s.jsx)("p",{className:"text-sm text-gray-600",children:"Add models for teams you are an admin for."})]})}),(0,s.jsxs)("div",{className:"mb-4 px-4 py-3 bg-blue-50 rounded-lg border border-blue-100 flex items-center gap-4",children:[(0,s.jsx)("div",{className:"flex-shrink-0 w-10 h-10 bg-white rounded-full flex items-center justify-center border border-blue-200",children:(0,s.jsx)(eU.Z,{style:{fontSize:"18px",color:"#6366f1"}})}),(0,s.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,s.jsx)("h4",{className:"text-gray-900 font-semibold text-sm m-0",children:"Missing a provider?"}),(0,s.jsx)("p",{className:"text-gray-500 text-xs m-0 mt-0.5",children:"The LiteLLM engineering team is constantly adding support for new LLM models, providers, endpoints. If you don't see the one you need, let us know and we'll prioritize it."})]}),(0,s.jsxs)("a",{href:"https://models.litellm.ai/?request=true",target:"_blank",rel:"noopener noreferrer",className:"flex-shrink-0 inline-flex items-center gap-2 px-4 py-2 bg-[#6366f1] hover:bg-[#5558e3] text-white text-sm font-medium rounded-lg transition-colors",children:["Request Provider",(0,s.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:(0,s.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"})})]})]}),V&&!($||et||ea||en)?(0,s.jsx)(lX,{modelId:V,onClose:()=>{q(null)},accessToken:i,userID:x,userRole:c,onModelUpdate:e=>{W.invalidateQueries({queryKey:["models","list"]}),eN()},modelAccessGroups:ec}):(0,s.jsxs)(eD.Z,{index:U,onIndexChange:H,className:"gap-2 h-[75vh] w-full ",children:[(0,s.jsxs)(eB.Z,{className:"flex justify-between mt-2 w-full items-center",children:[(0,s.jsxs)("div",{className:"flex",children:[eR.ZL.includes(c)?(0,s.jsx)(ez.Z,{children:"All Models"}):(0,s.jsx)(ez.Z,{children:"Your Models"}),!eb&&(0,s.jsx)(ez.Z,{children:"Add Model"}),eR.ZL.includes(c)&&(0,s.jsx)(ez.Z,{children:"LLM Credentials"}),eR.ZL.includes(c)&&(0,s.jsx)(ez.Z,{children:"Pass-Through Endpoints"}),eR.ZL.includes(c)&&(0,s.jsx)(ez.Z,{children:"Health Status"}),eR.ZL.includes(c)&&(0,s.jsx)(ez.Z,{children:"Model Retry Settings"}),eR.ZL.includes(c)&&(0,s.jsx)(ez.Z,{children:"Model Group Alias"}),eR.ZL.includes(c)&&(0,s.jsx)(ez.Z,{children:"Price Data Reload"})]}),(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[g&&(0,s.jsxs)(D.Z,{children:["Last Refreshed: ",g]}),(0,s.jsx)(P.Z,{icon:eO.Z,variant:"shadow",size:"xs",className:"self-center",onClick:eN})]})]}),(0,s.jsxs)(eG.Z,{children:[(0,s.jsx)(J,{selectedModelGroup:N,setSelectedModelGroup:w,availableModelGroups:ed,availableModelAccessGroups:ec,setSelectedModelId:q,setSelectedTeamId:G}),!eb&&(0,s.jsx)(z.Z,{className:"h-full",children:(0,s.jsx)(lA,{form:p,handleOk:eZ,selectedProvider:b,setSelectedProvider:y,providerModels:v,setProviderModelsFn:e=>{_((0,L.bK)(e,el))},getPlaceholder:L.ph,uploadProps:ey,showAdvancedSettings:I,setShowAdvancedSettings:R,teams:r,credentials:er,accessToken:i,userRole:c})}),(0,s.jsx)(z.Z,{children:(0,s.jsx)(eT,{uploadProps:ey})}),(0,s.jsx)(z.Z,{children:(0,s.jsx)(lQ.Z,{accessToken:i,userRole:c,userID:x,modelData:ep,premiumUser:t})}),(0,s.jsx)(z.Z,{children:(0,s.jsx)(lT,{accessToken:i,modelData:ep,all_models_on_proxy:eu,getDisplayModelName:T,setSelectedModelId:q})}),(0,s.jsx)(X,{selectedModelGroup:N,setSelectedModelGroup:w,availableModelGroups:ed,globalRetryPolicy:k,setGlobalRetryPolicy:S,defaultRetry:A,modelGroupRetryPolicy:Z,setModelGroupRetryPolicy:C,handleSaveRetrySettings:ew}),(0,s.jsx)(z.Z,{children:(0,s.jsx)(lz,{accessToken:i,initialModelGroupAlias:M,onAliasUpdate:F})}),(0,s.jsx)(em,{})]})]})]})})})}},27593:function(e,l,t){t.d(l,{Z:function(){return Y}});var s=t(57437),a=t(2265),r=t(78489),i=t(47323),n=t(84264),o=t(96761),d=t(19250),c=t(99981),m=t(33866),u=t(15731),h=t(53410),x=t(74998),p=t(59341),g=t(49566),f=t(12514),j=t(97765),v=t(37592),_=t(10032),b=t(22116),y=t(51653),N=t(24199),w=t(12660),Z=t(15424),C=t(58760),k=t(5545),S=t(45246),A=t(96473),E=t(31283),P=e=>{let{value:l={},onChange:t}=e,[r,i]=(0,a.useState)(Object.entries(l)),n=e=>{let l=r.filter((l,t)=>t!==e);i(l),null==t||t(Object.fromEntries(l))},o=(e,l,s)=>{let a=[...r];a[e]=[l,s],i(a),null==t||t(Object.fromEntries(a))};return(0,s.jsxs)("div",{children:[r.map((e,l)=>{let[t,a]=e;return(0,s.jsxs)(C.Z,{style:{display:"flex",marginBottom:8},align:"center",children:[(0,s.jsx)(E.o,{placeholder:"Header Name",value:t,onChange:e=>o(l,e.target.value,a)}),(0,s.jsx)(E.o,{placeholder:"Header Value",value:a,onChange:e=>o(l,t,e.target.value)}),(0,s.jsx)("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%"},children:(0,s.jsx)(S.Z,{onClick:()=>n(l),style:{cursor:"pointer"}})})]},l)}),(0,s.jsx)(k.ZP,{type:"dashed",onClick:()=>{i([...r,["",""]])},icon:(0,s.jsx)(A.Z,{}),children:"Add Header"})]})},M=t(77565),L=e=>{let{pathValue:l,targetValue:t,includeSubpath:a}=e,r=(0,d.getProxyBaseUrl)();return l&&t?(0,s.jsxs)(f.Z,{className:"p-5",children:[(0,s.jsx)(o.Z,{className:"text-lg font-semibold text-gray-900 mb-2",children:"Route Preview"}),(0,s.jsx)(j.Z,{className:"text-gray-600 mb-5",children:"How your requests will be routed"}),(0,s.jsxs)("div",{className:"space-y-5",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-base font-semibold text-gray-900 mb-3",children:"Basic routing:"}),(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[(0,s.jsxs)("div",{className:"flex-1 bg-gray-50 border border-gray-200 rounded-lg p-3",children:[(0,s.jsx)("div",{className:"text-sm text-gray-600 mb-2",children:"Your endpoint"}),(0,s.jsx)("code",{className:"font-mono text-sm text-gray-900",children:l?"".concat(r).concat(l):""})]}),(0,s.jsx)("div",{className:"text-gray-400",children:(0,s.jsx)(M.Z,{className:"text-lg"})}),(0,s.jsxs)("div",{className:"flex-1 bg-gray-50 border border-gray-200 rounded-lg p-3",children:[(0,s.jsx)("div",{className:"text-sm text-gray-600 mb-2",children:"Forwards to"}),(0,s.jsx)("code",{className:"font-mono text-sm text-gray-900",children:t})]})]})]}),a&&(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-base font-semibold text-gray-900 mb-3",children:"With subpaths:"}),(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[(0,s.jsxs)("div",{className:"flex-1 bg-gray-50 border border-gray-200 rounded-lg p-3",children:[(0,s.jsx)("div",{className:"text-sm text-gray-600 mb-2",children:"Your endpoint + subpath"}),(0,s.jsxs)("code",{className:"font-mono text-sm text-gray-900",children:[l&&"".concat(r).concat(l),(0,s.jsx)("span",{className:"text-blue-600",children:"/v1/text-to-image/base/model"})]})]}),(0,s.jsx)("div",{className:"text-gray-400",children:(0,s.jsx)(M.Z,{className:"text-lg"})}),(0,s.jsxs)("div",{className:"flex-1 bg-gray-50 border border-gray-200 rounded-lg p-3",children:[(0,s.jsx)("div",{className:"text-sm text-gray-600 mb-2",children:"Forwards to"}),(0,s.jsxs)("code",{className:"font-mono text-sm text-gray-900",children:[t,(0,s.jsx)("span",{className:"text-blue-600",children:"/v1/text-to-image/base/model"})]})]})]}),(0,s.jsxs)("div",{className:"mt-3 text-sm text-gray-600",children:["Any path after ",l," will be appended to the target URL"]})]})}),!a&&(0,s.jsx)("div",{className:"mt-4 p-3 bg-blue-50 rounded-md border border-blue-200",children:(0,s.jsxs)("div",{className:"flex items-start",children:[(0,s.jsx)(Z.Z,{className:"text-blue-500 mt-0.5 mr-2 flex-shrink-0"}),(0,s.jsxs)("div",{className:"text-sm text-blue-700",children:[(0,s.jsx)("span",{className:"font-medium",children:"Not seeing the routing you wanted?"})," Try enabling - Include Subpaths - above - this allows subroutes like"," ",(0,s.jsx)("code",{className:"bg-blue-100 px-1 py-0.5 rounded font-mono text-xs",children:"/api/v1/models"})," to be forwarded automatically."]})]})})]})]}):null},F=t(9114),I=t(63709),T=e=>{let{premiumUser:l,authEnabled:t,onAuthChange:a}=e;return(0,s.jsxs)(f.Z,{className:"p-6",children:[(0,s.jsx)(o.Z,{className:"text-lg font-semibold text-gray-900 mb-2",children:"Security"}),(0,s.jsx)(j.Z,{className:"text-gray-600 mb-4",children:"When enabled, requests to this endpoint will require a valid LiteLLM Virtual Key"}),l?(0,s.jsx)(_.Z.Item,{name:"auth",valuePropName:"checked",className:"mb-0",children:(0,s.jsx)(I.Z,{checked:t,onChange:e=>{a(e)}})}):(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex items-center mb-3",children:[(0,s.jsx)(I.Z,{disabled:!0,checked:!1,style:{outline:"2px solid #d1d5db",outlineOffset:"2px"}}),(0,s.jsx)("span",{className:"ml-2 text-sm text-gray-400",children:"Authentication (Premium)"})]}),(0,s.jsx)("div",{className:"p-3 bg-yellow-50 border border-yellow-200 rounded-lg",children:(0,s.jsxs)(n.Z,{className:"text-sm text-yellow-800",children:["Setting authentication for pass-through endpoints is a LiteLLM Enterprise feature. Get a trial key"," ",(0,s.jsx)("a",{href:"https://www.litellm.ai/#pricing",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"here"}),"."]})})]})]})},R=t(67479),O=e=>{let{accessToken:l,value:t={},onChange:r,disabled:i=!1}=e,[n,d]=(0,a.useState)(Object.keys(t)),[m,u]=(0,a.useState)(t);(0,a.useEffect)(()=>{u(t),d(Object.keys(t))},[t]);let h=(e,l,t)=>{var s,a;let i=m[e]||{},n={...m,[e]:{...i,[l]:t.length>0?t:void 0}};(null===(s=n[e])||void 0===s?void 0:s.request_fields)||(null===(a=n[e])||void 0===a?void 0:a.response_fields)||(n[e]=null),u(n),r&&r(n)};return(0,s.jsxs)(f.Z,{className:"p-6",children:[(0,s.jsx)(o.Z,{className:"text-lg font-semibold text-gray-900 mb-2",children:"Guardrails"}),(0,s.jsx)(j.Z,{className:"text-gray-600 mb-6",children:"Configure guardrails to enforce policies on requests and responses. Guardrails are opt-in for passthrough endpoints."}),(0,s.jsx)(y.Z,{message:(0,s.jsxs)("span",{children:["Field-Level Targeting"," ",(0,s.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/pass_through_guardrails#field-level-targeting",target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:text-blue-800 underline",children:"(Learn More)"})]}),description:(0,s.jsxs)("div",{className:"space-y-2",children:[(0,s.jsx)("div",{children:"Optionally specify which fields to check. If left empty, the entire request/response is sent to the guardrail."}),(0,s.jsxs)("div",{className:"text-xs space-y-1 mt-2",children:[(0,s.jsx)("div",{className:"font-medium",children:"Common Examples:"}),(0,s.jsxs)("div",{children:["• ",(0,s.jsx)("code",{className:"bg-gray-100 px-1 rounded",children:"query"})," - Single field"]}),(0,s.jsxs)("div",{children:["• ",(0,s.jsx)("code",{className:"bg-gray-100 px-1 rounded",children:"documents[*].text"})," - All text in documents array"]}),(0,s.jsxs)("div",{children:["• ",(0,s.jsx)("code",{className:"bg-gray-100 px-1 rounded",children:"messages[*].content"})," - All message contents"]})]})]}),type:"info",showIcon:!0,className:"mb-4"}),(0,s.jsx)(_.Z.Item,{label:(0,s.jsxs)("span",{className:"text-sm font-medium text-gray-700 flex items-center",children:["Select Guardrails",(0,s.jsx)(c.Z,{title:"Choose which guardrails should run on this endpoint. Org/team/key level guardrails will also be included.",children:(0,s.jsx)(Z.Z,{className:"ml-2 text-blue-400 hover:text-blue-600 cursor-help"})})]}),children:(0,s.jsx)(R.Z,{accessToken:l,value:n,onChange:e=>{d(e);let l={};e.forEach(e=>{l[e]=m[e]||null}),u(l),r&&r(l)},disabled:i})}),n.length>0&&(0,s.jsxs)("div",{className:"mt-6 space-y-4",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,s.jsx)("div",{className:"text-sm font-medium text-gray-700",children:"Field Targeting (Optional)"}),(0,s.jsx)("div",{className:"text-xs text-gray-500",children:"\uD83D\uDCA1 Tip: Leave empty to check entire payload"})]}),n.map(e=>{var l,t;return(0,s.jsxs)(f.Z,{className:"p-4 bg-gray-50",children:[(0,s.jsx)("div",{className:"text-sm font-medium text-gray-900 mb-3",children:e}),(0,s.jsxs)("div",{className:"space-y-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex items-center justify-between mb-1",children:[(0,s.jsxs)("label",{className:"text-xs text-gray-600 flex items-center",children:["Request Fields (pre_call)",(0,s.jsx)(c.Z,{title:(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"font-medium mb-1",children:"Specify which request fields to check"}),(0,s.jsxs)("div",{className:"text-xs space-y-1",children:[(0,s.jsx)("div",{children:"Examples:"}),(0,s.jsx)("div",{children:"• query"}),(0,s.jsx)("div",{children:"• documents[*].text"}),(0,s.jsx)("div",{children:"• messages[*].content"})]})]}),children:(0,s.jsx)(Z.Z,{className:"ml-1 text-gray-400"})})]}),(0,s.jsxs)("div",{className:"flex gap-1",children:[(0,s.jsx)("button",{type:"button",onClick:()=>{var l;let t=(null===(l=m[e])||void 0===l?void 0:l.request_fields)||[];h(e,"request_fields",[...t,"query"])},className:"text-xs px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50",disabled:i,children:"+ query"}),(0,s.jsx)("button",{type:"button",onClick:()=>{var l;let t=(null===(l=m[e])||void 0===l?void 0:l.request_fields)||[];h(e,"request_fields",[...t,"documents[*]"])},className:"text-xs px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50",disabled:i,children:"+ documents[*]"})]})]}),(0,s.jsx)(v.default,{mode:"tags",style:{width:"100%"},placeholder:"Type field name or use + buttons above (e.g., query, documents[*].text)",value:(null===(l=m[e])||void 0===l?void 0:l.request_fields)||[],onChange:l=>h(e,"request_fields",l),disabled:i,tokenSeparators:[","]})]}),(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex items-center justify-between mb-1",children:[(0,s.jsxs)("label",{className:"text-xs text-gray-600 flex items-center",children:["Response Fields (post_call)",(0,s.jsx)(c.Z,{title:(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"font-medium mb-1",children:"Specify which response fields to check"}),(0,s.jsxs)("div",{className:"text-xs space-y-1",children:[(0,s.jsx)("div",{children:"Examples:"}),(0,s.jsx)("div",{children:"• results[*].text"}),(0,s.jsx)("div",{children:"• choices[*].message.content"})]})]}),children:(0,s.jsx)(Z.Z,{className:"ml-1 text-gray-400"})})]}),(0,s.jsx)("div",{className:"flex gap-1",children:(0,s.jsx)("button",{type:"button",onClick:()=>{var l;let t=(null===(l=m[e])||void 0===l?void 0:l.response_fields)||[];h(e,"response_fields",[...t,"results[*]"])},className:"text-xs px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50",disabled:i,children:"+ results[*]"})})]}),(0,s.jsx)(v.default,{mode:"tags",style:{width:"100%"},placeholder:"Type field name or use + buttons above (e.g., results[*].text)",value:(null===(t=m[e])||void 0===t?void 0:t.response_fields)||[],onChange:l=>h(e,"response_fields",l),disabled:i,tokenSeparators:[","]})]})]})]},e)})]})]})};let{Option:V}=v.default;var q=e=>{let{accessToken:l,setPassThroughItems:t,passThroughItems:i,premiumUser:n=!1}=e,[m]=_.Z.useForm(),[u,h]=(0,a.useState)(!1),[x,v]=(0,a.useState)(!1),[C,k]=(0,a.useState)(""),[S,A]=(0,a.useState)(""),[E,M]=(0,a.useState)(""),[I,R]=(0,a.useState)(!0),[V,q]=(0,a.useState)(!1),[z,D]=(0,a.useState)({}),B=()=>{m.resetFields(),A(""),M(""),R(!0),D({}),h(!1)},G=e=>{let l=e;e&&!e.startsWith("/")&&(l="/"+e),A(l),m.setFieldsValue({path:l})},U=async e=>{console.log("addPassThrough called with:",e),v(!0);try{!n&&"auth"in e&&delete e.auth,z&&Object.keys(z).length>0&&(e.guardrails=z),console.log("formValues: ".concat(JSON.stringify(e)));let s=(await (0,d.createPassThroughEndpoint)(l,e)).endpoints[0],a=[...i,s];t(a),F.Z.success("Pass-through endpoint created successfully"),m.resetFields(),A(""),M(""),R(!0),D({}),h(!1)}catch(e){F.Z.fromBackend("Error creating pass-through endpoint: "+e)}finally{v(!1)}};return(0,s.jsxs)("div",{children:[(0,s.jsx)(r.Z,{className:"mx-auto mb-4 mt-4",onClick:()=>h(!0),children:"+ Add Pass-Through Endpoint"}),(0,s.jsx)(b.Z,{title:(0,s.jsxs)("div",{className:"flex items-center space-x-3 pb-4 border-b border-gray-100",children:[(0,s.jsx)(w.Z,{className:"text-xl text-blue-500"}),(0,s.jsx)("h2",{className:"text-xl font-semibold text-gray-900",children:"Add Pass-Through Endpoint"})]}),open:u,width:1e3,onCancel:B,footer:null,className:"top-8",styles:{body:{padding:"24px"},header:{padding:"24px 24px 0 24px",border:"none"}},children:(0,s.jsxs)("div",{className:"mt-6",children:[(0,s.jsx)(y.Z,{message:"What is a Pass-Through Endpoint?",description:"Route requests from your LiteLLM proxy to any external API. Perfect for custom models, image generation APIs, or any service you want to proxy through LiteLLM.",type:"info",showIcon:!0,className:"mb-6"}),(0,s.jsxs)(_.Z,{form:m,onFinish:U,layout:"vertical",className:"space-y-6",initialValues:{include_subpath:!0,path:S,target:E},children:[(0,s.jsxs)(f.Z,{className:"p-5",children:[(0,s.jsx)(o.Z,{className:"text-lg font-semibold text-gray-900 mb-2",children:"Route Configuration"}),(0,s.jsx)(j.Z,{className:"text-gray-600 mb-5",children:"Configure how requests to your domain will be forwarded to the target API"}),(0,s.jsxs)("div",{className:"space-y-5",children:[(0,s.jsx)(_.Z.Item,{label:(0,s.jsx)("span",{className:"text-sm font-medium text-gray-700",children:"Path Prefix"}),name:"path",rules:[{required:!0,message:"Path is required",pattern:/^\//}],extra:(0,s.jsx)("div",{className:"text-xs text-gray-500 mt-1",children:"Example: /bria, /adobe-photoshop, /elasticsearch"}),className:"mb-4",children:(0,s.jsx)("div",{className:"flex items-center",children:(0,s.jsx)(g.Z,{placeholder:"bria",value:S,onChange:e=>G(e.target.value),className:"flex-1"})})}),(0,s.jsx)(_.Z.Item,{label:(0,s.jsx)("span",{className:"text-sm font-medium text-gray-700",children:"Target URL"}),name:"target",rules:[{required:!0,message:"Target URL is required"},{type:"url",message:"Please enter a valid URL"}],extra:(0,s.jsx)("div",{className:"text-xs text-gray-500 mt-1",children:"Example:https://engine.prod.bria-api.com"}),className:"mb-4",children:(0,s.jsx)(g.Z,{placeholder:"https://engine.prod.bria-api.com",value:E,onChange:e=>{M(e.target.value),m.setFieldsValue({target:e.target.value})}})}),(0,s.jsxs)("div",{className:"flex items-center justify-between py-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-sm font-medium text-gray-700",children:"Include Subpaths"}),(0,s.jsx)("div",{className:"text-xs text-gray-500 mt-0.5",children:"Forward all subpaths to the target API (recommended for REST APIs)"})]}),(0,s.jsx)(_.Z.Item,{name:"include_subpath",valuePropName:"checked",className:"mb-0",children:(0,s.jsx)(p.Z,{checked:I,onChange:R})})]})]})]}),(0,s.jsx)(L,{pathValue:S,targetValue:E,includeSubpath:I}),(0,s.jsxs)(f.Z,{className:"p-6",children:[(0,s.jsx)(o.Z,{className:"text-lg font-semibold text-gray-900 mb-2",children:"Headers"}),(0,s.jsx)(j.Z,{className:"text-gray-600 mb-6",children:"Add headers that will be sent with every request to the target API"}),(0,s.jsx)(_.Z.Item,{label:(0,s.jsxs)("span",{className:"text-sm font-medium text-gray-700 flex items-center",children:["Authentication Headers",(0,s.jsx)(c.Z,{title:"Authentication and other headers to forward with requests",children:(0,s.jsx)(Z.Z,{className:"ml-2 text-blue-400 hover:text-blue-600 cursor-help"})})]}),name:"headers",rules:[{required:!0,message:"Please configure the headers"}],extra:(0,s.jsxs)("div",{className:"text-xs text-gray-500 mt-2",children:[(0,s.jsx)("div",{className:"font-medium mb-1",children:"Add authentication tokens and other required headers"}),(0,s.jsx)("div",{children:"Common examples: auth_token, Authorization, x-api-key"})]}),children:(0,s.jsx)(P,{})})]}),(0,s.jsx)(T,{premiumUser:n,authEnabled:V,onAuthChange:e=>{q(e),m.setFieldsValue({auth:e})}}),(0,s.jsx)(O,{accessToken:l,value:z,onChange:D}),(0,s.jsxs)(f.Z,{className:"p-6",children:[(0,s.jsx)(o.Z,{className:"text-lg font-semibold text-gray-900 mb-2",children:"Billing"}),(0,s.jsx)(j.Z,{className:"text-gray-600 mb-6",children:"Optional cost tracking for this endpoint"}),(0,s.jsx)(_.Z.Item,{label:(0,s.jsxs)("span",{className:"text-sm font-medium text-gray-700 flex items-center",children:["Cost Per Request (USD)",(0,s.jsx)(c.Z,{title:"Optional: Track costs for requests to this endpoint",children:(0,s.jsx)(Z.Z,{className:"ml-2 text-gray-400 hover:text-gray-600"})})]}),name:"cost_per_request",extra:(0,s.jsx)("div",{className:"text-xs text-gray-500 mt-2",children:"The cost charged for each request through this endpoint"}),children:(0,s.jsx)(N.Z,{min:0,step:.001,precision:4,placeholder:"2.0000",size:"large"})})]}),(0,s.jsxs)("div",{className:"flex items-center justify-end space-x-3 pt-6 border-t border-gray-100",children:[(0,s.jsx)(r.Z,{variant:"secondary",onClick:B,children:"Cancel"}),(0,s.jsx)(r.Z,{variant:"primary",loading:x,onClick:()=>{console.log("Submit button clicked"),m.submit()},children:x?"Creating...":"Add Pass-Through Endpoint"})]})]})]})})]})},z=t(30078),D=t(4260),B=t(12221),G=t(87769),U=t(42208);let H=e=>{let{value:l}=e,[t,r]=(0,a.useState)(!1),i=JSON.stringify(l,null,2);return(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,s.jsx)("pre",{className:"font-mono text-xs bg-gray-50 p-2 rounded max-w-md overflow-auto",children:t?i:"••••••••"}),(0,s.jsx)("button",{onClick:()=>r(!t),className:"p-1 hover:bg-gray-100 rounded",type:"button",children:t?(0,s.jsx)(G.Z,{className:"w-4 h-4 text-gray-500"}):(0,s.jsx)(U.Z,{className:"w-4 h-4 text-gray-500"})})]})};var K=e=>{let{endpointData:l,onClose:t,accessToken:r,isAdmin:i,premiumUser:n=!1,onEndpointUpdated:o}=e,[c,m]=(0,a.useState)(l),[u,h]=(0,a.useState)(!1),[x,p]=(0,a.useState)(!1),[g,f]=(0,a.useState)((null==l?void 0:l.auth)||!1),[j,v]=(0,a.useState)((null==l?void 0:l.guardrails)||{}),[b]=_.Z.useForm(),y=async e=>{try{if(!r||!(null==c?void 0:c.id))return;let l={};if(e.headers)try{l="string"==typeof e.headers?JSON.parse(e.headers):e.headers}catch(e){F.Z.fromBackend("Invalid JSON format for headers");return}let t={path:c.path,target:e.target,headers:l,include_subpath:e.include_subpath,cost_per_request:e.cost_per_request,auth:n?e.auth:void 0,guardrails:j&&Object.keys(j).length>0?j:void 0};await (0,d.updatePassThroughEndpoint)(r,c.id,t),m({...c,...t}),p(!1),o&&o()}catch(e){console.error("Error updating endpoint:",e),F.Z.fromBackend("Failed to update pass through endpoint")}},N=async()=>{try{if(!r||!(null==c?void 0:c.id))return;await (0,d.deletePassThroughEndpointsCall)(r,c.id),F.Z.success("Pass through endpoint deleted successfully"),t(),o&&o()}catch(e){console.error("Error deleting endpoint:",e),F.Z.fromBackend("Failed to delete pass through endpoint")}};return u?(0,s.jsx)("div",{className:"p-4",children:"Loading..."}):c?(0,s.jsxs)("div",{className:"p-4",children:[(0,s.jsx)("div",{className:"flex justify-between items-center mb-6",children:(0,s.jsxs)("div",{children:[(0,s.jsx)(k.ZP,{onClick:t,className:"mb-4",children:"← Back"}),(0,s.jsxs)(z.Dx,{children:["Pass Through Endpoint: ",c.path]}),(0,s.jsx)(z.xv,{className:"text-gray-500 font-mono",children:c.id})]})}),(0,s.jsxs)(z.v0,{children:[(0,s.jsxs)(z.td,{className:"mb-4",children:[(0,s.jsx)(z.OK,{children:"Overview"},"overview"),i?(0,s.jsx)(z.OK,{children:"Settings"},"settings"):(0,s.jsx)(s.Fragment,{})]}),(0,s.jsxs)(z.nP,{children:[(0,s.jsxs)(z.x4,{children:[(0,s.jsxs)(z.rj,{numItems:1,numItemsSm:2,numItemsLg:3,className:"gap-6",children:[(0,s.jsxs)(z.Zb,{children:[(0,s.jsx)(z.xv,{children:"Path"}),(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)(z.Dx,{className:"font-mono",children:c.path})})]}),(0,s.jsxs)(z.Zb,{children:[(0,s.jsx)(z.xv,{children:"Target"}),(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)(z.Dx,{children:c.target})})]}),(0,s.jsxs)(z.Zb,{children:[(0,s.jsx)(z.xv,{children:"Configuration"}),(0,s.jsxs)("div",{className:"mt-2 space-y-2",children:[(0,s.jsx)("div",{children:(0,s.jsx)(z.Ct,{color:c.include_subpath?"green":"gray",children:c.include_subpath?"Include Subpath":"Exact Path"})}),(0,s.jsx)("div",{children:(0,s.jsx)(z.Ct,{color:c.auth?"blue":"gray",children:c.auth?"Auth Required":"No Auth"})}),void 0!==c.cost_per_request&&(0,s.jsx)("div",{children:(0,s.jsxs)(z.xv,{children:["Cost per request: $",c.cost_per_request]})})]})]})]}),(0,s.jsx)("div",{className:"mt-6",children:(0,s.jsx)(L,{pathValue:c.path,targetValue:c.target,includeSubpath:c.include_subpath||!1})}),c.headers&&Object.keys(c.headers).length>0&&(0,s.jsxs)(z.Zb,{className:"mt-6",children:[(0,s.jsxs)("div",{className:"flex justify-between items-center",children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Headers"}),(0,s.jsxs)(z.Ct,{color:"blue",children:[Object.keys(c.headers).length," headers configured"]})]}),(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(H,{value:c.headers})})]}),c.guardrails&&Object.keys(c.guardrails).length>0&&(0,s.jsxs)(z.Zb,{className:"mt-6",children:[(0,s.jsxs)("div",{className:"flex justify-between items-center",children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Guardrails"}),(0,s.jsxs)(z.Ct,{color:"purple",children:[Object.keys(c.guardrails).length," guardrails configured"]})]}),(0,s.jsx)("div",{className:"mt-4 space-y-2",children:Object.entries(c.guardrails).map(e=>{let[l,t]=e;return(0,s.jsxs)("div",{className:"p-3 bg-gray-50 rounded",children:[(0,s.jsx)("div",{className:"font-medium text-sm",children:l}),t&&(t.request_fields||t.response_fields)&&(0,s.jsxs)("div",{className:"mt-2 text-xs text-gray-600 space-y-1",children:[t.request_fields&&(0,s.jsxs)("div",{children:["Request fields: ",t.request_fields.join(", ")]}),t.response_fields&&(0,s.jsxs)("div",{children:["Response fields: ",t.response_fields.join(", ")]})]}),!t&&(0,s.jsx)("div",{className:"text-xs text-gray-600 mt-1",children:"Uses entire payload"})]},l)})})]})]}),i&&(0,s.jsx)(z.x4,{children:(0,s.jsxs)(z.Zb,{children:[(0,s.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,s.jsx)(z.Dx,{children:"Pass Through Endpoint Settings"}),(0,s.jsx)("div",{className:"space-x-2",children:!x&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(z.zx,{onClick:()=>p(!0),children:"Edit Settings"}),(0,s.jsx)(z.zx,{onClick:N,variant:"secondary",color:"red",children:"Delete Endpoint"})]})})]}),x?(0,s.jsxs)(_.Z,{form:b,onFinish:y,initialValues:{target:c.target,headers:c.headers?JSON.stringify(c.headers,null,2):"",include_subpath:c.include_subpath||!1,cost_per_request:c.cost_per_request,auth:c.auth||!1},layout:"vertical",children:[(0,s.jsx)(_.Z.Item,{label:"Target URL",name:"target",rules:[{required:!0,message:"Please input a target URL"}],children:(0,s.jsx)(z.oi,{placeholder:"https://api.example.com"})}),(0,s.jsx)(_.Z.Item,{label:"Headers (JSON)",name:"headers",children:(0,s.jsx)(D.default.TextArea,{rows:5,placeholder:'{"Authorization": "Bearer your-token", "Content-Type": "application/json"}'})}),(0,s.jsx)(_.Z.Item,{label:"Include Subpath",name:"include_subpath",valuePropName:"checked",children:(0,s.jsx)(I.Z,{})}),(0,s.jsx)(_.Z.Item,{label:"Cost per Request",name:"cost_per_request",children:(0,s.jsx)(B.Z,{min:0,step:.01,precision:2,placeholder:"0.00",addonBefore:"$"})}),(0,s.jsx)(T,{premiumUser:n,authEnabled:g,onAuthChange:e=>{f(e),b.setFieldsValue({auth:e})}}),(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(O,{accessToken:r||"",value:j,onChange:v})}),(0,s.jsxs)("div",{className:"flex justify-end gap-2 mt-6",children:[(0,s.jsx)(k.ZP,{onClick:()=>p(!1),children:"Cancel"}),(0,s.jsx)(z.zx,{children:"Save Changes"})]})]}):(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Path"}),(0,s.jsx)("div",{className:"font-mono",children:c.path})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Target URL"}),(0,s.jsx)("div",{children:c.target})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Include Subpath"}),(0,s.jsx)(z.Ct,{color:c.include_subpath?"green":"gray",children:c.include_subpath?"Yes":"No"})]}),void 0!==c.cost_per_request&&(0,s.jsxs)("div",{children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Cost per Request"}),(0,s.jsxs)("div",{children:["$",c.cost_per_request]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Authentication Required"}),(0,s.jsx)(z.Ct,{color:c.auth?"green":"gray",children:c.auth?"Yes":"No"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(z.xv,{className:"font-medium",children:"Headers"}),c.headers&&Object.keys(c.headers).length>0?(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)(H,{value:c.headers})}):(0,s.jsx)("div",{className:"text-gray-500",children:"No headers configured"})]})]})]})})]})]})]}):(0,s.jsx)("div",{className:"p-4",children:"Pass through endpoint not found"})},J=t(12322);let W=e=>{let{value:l}=e,[t,r]=(0,a.useState)(!1),i=JSON.stringify(l);return(0,s.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,s.jsx)("span",{className:"font-mono text-xs",children:t?i:"••••••••"}),(0,s.jsx)("button",{onClick:()=>r(!t),className:"p-1 hover:bg-gray-100 rounded",type:"button",children:t?(0,s.jsx)(G.Z,{className:"w-4 h-4 text-gray-500"}):(0,s.jsx)(U.Z,{className:"w-4 h-4 text-gray-500"})})]})};var Y=e=>{let{accessToken:l,userRole:t,userID:p,modelData:g,premiumUser:f}=e,[j,v]=(0,a.useState)([]),[_,b]=(0,a.useState)(null),[y,N]=(0,a.useState)(!1),[w,Z]=(0,a.useState)(null);(0,a.useEffect)(()=>{l&&t&&p&&(0,d.getPassThroughEndpointsCall)(l).then(e=>{v(e.endpoints)})},[l,t,p]);let C=async e=>{Z(e),N(!0)},k=async()=>{if(null!=w&&l){try{await (0,d.deletePassThroughEndpointsCall)(l,w);let e=j.filter(e=>e.id!==w);v(e),F.Z.success("Endpoint deleted successfully.")}catch(e){console.error("Error deleting the endpoint:",e),F.Z.fromBackend("Error deleting the endpoint: "+e)}N(!1),Z(null)}},S=(e,l)=>{C(e)},A=[{header:"ID",accessorKey:"id",cell:e=>(0,s.jsx)(c.Z,{title:e.row.original.id,children:(0,s.jsx)("div",{className:"font-mono text-blue-500 bg-blue-50 hover:bg-blue-100 text-xs font-normal px-2 py-0.5 text-left w-full truncate whitespace-nowrap cursor-pointer max-w-[15ch]",onClick:()=>e.row.original.id&&b(e.row.original.id),children:e.row.original.id})})},{header:"Path",accessorKey:"path"},{header:"Target",accessorKey:"target",cell:e=>(0,s.jsx)(n.Z,{children:e.getValue()})},{header:()=>(0,s.jsxs)("div",{className:"flex items-center gap-1",children:[(0,s.jsx)("span",{children:"Authentication"}),(0,s.jsx)(c.Z,{title:"LiteLLM Virtual Key required to call endpoint",children:(0,s.jsx)(u.Z,{className:"w-4 h-4 text-gray-400 cursor-help"})})]}),accessorKey:"auth",cell:e=>(0,s.jsx)(m.Z,{color:e.getValue()?"green":"gray",children:e.getValue()?"Yes":"No"})},{header:"Headers",accessorKey:"headers",cell:e=>(0,s.jsx)(W,{value:e.getValue()||{}})},{header:"Actions",id:"actions",cell:e=>{let{row:l}=e;return(0,s.jsxs)("div",{className:"flex space-x-1",children:[(0,s.jsx)(i.Z,{icon:h.Z,size:"sm",onClick:()=>l.original.id&&b(l.original.id),title:"Edit"}),(0,s.jsx)(i.Z,{icon:x.Z,size:"sm",onClick:()=>S(l.original.id,l.index),title:"Delete"})]})}}];if(!l)return null;if(_){console.log("selectedEndpointId",_),console.log("generalSettings",j);let e=j.find(e=>e.id===_);return e?(0,s.jsx)(K,{endpointData:e,onClose:()=>b(null),accessToken:l,isAdmin:"Admin"===t||"admin"===t,premiumUser:f,onEndpointUpdated:()=>{l&&(0,d.getPassThroughEndpointsCall)(l).then(e=>{v(e.endpoints)})}}):(0,s.jsx)("div",{children:"Endpoint not found"})}return(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{children:"Pass Through Endpoints"}),(0,s.jsx)(n.Z,{className:"text-tremor-content",children:"Configure and manage your pass-through endpoints"})]}),(0,s.jsx)(q,{accessToken:l,setPassThroughItems:v,passThroughItems:j,premiumUser:f}),(0,s.jsx)(J.w,{data:j,columns:A,renderSubComponent:()=>(0,s.jsx)("div",{}),getRowCanExpand:()=>!1,isLoading:!1,noDataMessage:"No pass-through endpoints configured"}),y&&(0,s.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,s.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,s.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,s.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,s.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,s.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,s.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,s.jsx)("div",{className:"sm:flex sm:items-start",children:(0,s.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,s.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Pass-Through Endpoint"}),(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this pass-through endpoint? This action cannot be undone."})})]})})}),(0,s.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,s.jsx)(r.Z,{onClick:k,color:"red",className:"ml-2",children:"Delete"}),(0,s.jsx)(r.Z,{onClick:()=>{N(!1),Z(null)},children:"Cancel"})]})]})]})})]})}},12322:function(e,l,t){t.d(l,{w:function(){return o}});var s=t(57437),a=t(2265),r=t(71594),i=t(24525),n=t(19130);function o(e){let{data:l=[],columns:t,onRowClick:o,renderSubComponent:d,getRowCanExpand:c,isLoading:m=!1,loadingMessage:u="\uD83D\uDE85 Loading logs...",noDataMessage:h="No logs found"}=e,x=!!d&&!!c,p=(0,r.b7)({data:l,columns:t,...x&&{getRowCanExpand:c},getRowId:(e,l)=>{var t;return null!==(t=null==e?void 0:e.request_id)&&void 0!==t?t:String(l)},getCoreRowModel:(0,i.sC)(),...x&&{getExpandedRowModel:(0,i.rV)()}});return(0,s.jsx)("div",{className:"rounded-lg custom-border overflow-x-auto w-full max-w-full box-border",children:(0,s.jsxs)(n.iA,{className:"[&_td]:py-0.5 [&_th]:py-1 table-fixed w-full box-border",style:{minWidth:"400px"},children:[(0,s.jsx)(n.ss,{children:p.getHeaderGroups().map(e=>(0,s.jsx)(n.SC,{children:e.headers.map(e=>(0,s.jsx)(n.xs,{className:"py-1 h-8",children:e.isPlaceholder?null:(0,r.ie)(e.column.columnDef.header,e.getContext())},e.id))},e.id))}),(0,s.jsx)(n.RM,{children:m?(0,s.jsx)(n.SC,{children:(0,s.jsx)(n.pj,{colSpan:t.length,className:"h-8 text-center",children:(0,s.jsx)("div",{className:"text-center text-gray-500",children:(0,s.jsx)("p",{children:u})})})}):p.getRowModel().rows.length>0?p.getRowModel().rows.map(e=>(0,s.jsxs)(a.Fragment,{children:[(0,s.jsx)(n.SC,{className:"h-8 ".concat(x?"":"cursor-pointer hover:bg-gray-50"),onClick:()=>!x&&(null==o?void 0:o(e.original)),children:e.getVisibleCells().map(e=>(0,s.jsx)(n.pj,{className:"py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap",children:(0,r.ie)(e.column.columnDef.cell,e.getContext())},e.id))}),x&&e.getIsExpanded()&&d&&(0,s.jsx)(n.SC,{children:(0,s.jsx)(n.pj,{colSpan:e.getVisibleCells().length,className:"p-0",children:(0,s.jsx)("div",{className:"w-full max-w-full overflow-hidden box-border",children:d({row:e})})})})]},e.id)):(0,s.jsx)(n.SC,{children:(0,s.jsx)(n.pj,{colSpan:t.length,className:"h-8 text-center",children:(0,s.jsx)("div",{className:"text-center text-gray-500",children:(0,s.jsx)("p",{children:h})})})})})]})})}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1789-c534ff8966aa231a.js b/litellm/proxy/_experimental/out/_next/static/chunks/1789-c534ff8966aa231a.js new file mode 100644 index 00000000000..a555310c8a2 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/1789-c534ff8966aa231a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1789],{25512:function(e,s,l){l.d(s,{P:function(){return t.Z},Q:function(){return i.Z}});var t=l(27281),i=l(57365)},51789:function(e,s,l){l.d(s,{Z:function(){return e1}});var t=l(57437),i=l(2265),r=l(57840),n=l(51653),a=l(99376),o=l(10032),c=l(4260),d=l(5545),u=l(22116);l(25512);var m=l(78489),g=l(94789),p=l(12514),x=l(12485),h=l(18135),_=l(35242),f=l(29706),j=l(77991),y=l(21626),v=l(97214),b=l(28241),S=l(58834),Z=l(69552),w=l(71876),N=l(37592),I=l(4156),C=l(56522),k=l(19250),O=l(9114),E=l(85968);let T={google:"https://artificialanalysis.ai/img/logos/google_small.svg",microsoft:"https://upload.wikimedia.org/wikipedia/commons/a/a8/Microsoft_Azure_Logo.svg",okta:"https://www.okta.com/sites/default/files/Okta_Logo_BrightBlue_Medium.png",generic:""},L={google:{envVarMap:{google_client_id:"GOOGLE_CLIENT_ID",google_client_secret:"GOOGLE_CLIENT_SECRET"},fields:[{label:"Google Client ID",name:"google_client_id"},{label:"Google Client Secret",name:"google_client_secret"}]},microsoft:{envVarMap:{microsoft_client_id:"MICROSOFT_CLIENT_ID",microsoft_client_secret:"MICROSOFT_CLIENT_SECRET",microsoft_tenant:"MICROSOFT_TENANT"},fields:[{label:"Microsoft Client ID",name:"microsoft_client_id"},{label:"Microsoft Client Secret",name:"microsoft_client_secret"},{label:"Microsoft Tenant",name:"microsoft_tenant"}]},okta:{envVarMap:{generic_client_id:"GENERIC_CLIENT_ID",generic_client_secret:"GENERIC_CLIENT_SECRET",generic_authorization_endpoint:"GENERIC_AUTHORIZATION_ENDPOINT",generic_token_endpoint:"GENERIC_TOKEN_ENDPOINT",generic_userinfo_endpoint:"GENERIC_USERINFO_ENDPOINT"},fields:[{label:"Generic Client ID",name:"generic_client_id"},{label:"Generic Client Secret",name:"generic_client_secret"},{label:"Authorization Endpoint",name:"generic_authorization_endpoint",placeholder:"https://your-domain/authorize"},{label:"Token Endpoint",name:"generic_token_endpoint",placeholder:"https://your-domain/token"},{label:"Userinfo Endpoint",name:"generic_userinfo_endpoint",placeholder:"https://your-domain/userinfo"}]},generic:{envVarMap:{generic_client_id:"GENERIC_CLIENT_ID",generic_client_secret:"GENERIC_CLIENT_SECRET",generic_authorization_endpoint:"GENERIC_AUTHORIZATION_ENDPOINT",generic_token_endpoint:"GENERIC_TOKEN_ENDPOINT",generic_userinfo_endpoint:"GENERIC_USERINFO_ENDPOINT"},fields:[{label:"Generic Client ID",name:"generic_client_id"},{label:"Generic Client Secret",name:"generic_client_secret"},{label:"Authorization Endpoint",name:"generic_authorization_endpoint"},{label:"Token Endpoint",name:"generic_token_endpoint"},{label:"Userinfo Endpoint",name:"generic_userinfo_endpoint"}]}};var P=e=>{let{isAddSSOModalVisible:s,isInstructionsModalVisible:l,handleAddSSOOk:r,handleAddSSOCancel:n,handleShowInstructions:a,handleInstructionsOk:m,handleInstructionsCancel:g,form:p,accessToken:x,ssoConfigured:h=!1}=e,[_,f]=(0,i.useState)(!1);(0,i.useEffect)(()=>{(async()=>{if(s&&x)try{let s=await (0,k.getSSOSettings)(x);if(console.log("Raw SSO data received:",s),s&&s.values){var e,l,t,i,r,n;console.log("SSO values:",s.values),console.log("user_email from API:",s.values.user_email);let a=null;s.values.google_client_id?a="google":s.values.microsoft_client_id?a="microsoft":s.values.generic_client_id&&(a=(null===(e=s.values.generic_authorization_endpoint)||void 0===e?void 0:e.includes("okta"))||(null===(l=s.values.generic_authorization_endpoint)||void 0===l?void 0:l.includes("auth0"))?"okta":"generic");let o={};if(s.values.role_mappings){let e=s.values.role_mappings,l=e=>e&&0!==e.length?e.join(", "):"";o={use_role_mappings:!0,group_claim:e.group_claim,default_role:e.default_role||"internal_user",proxy_admin_teams:l(null===(t=e.roles)||void 0===t?void 0:t.proxy_admin),admin_viewer_teams:l(null===(i=e.roles)||void 0===i?void 0:i.proxy_admin_viewer),internal_user_teams:l(null===(r=e.roles)||void 0===r?void 0:r.internal_user),internal_viewer_teams:l(null===(n=e.roles)||void 0===n?void 0:n.internal_user_viewer)}}let c={sso_provider:a,proxy_base_url:s.values.proxy_base_url,user_email:s.values.user_email,...s.values,...o};console.log("Setting form values:",c),p.resetFields(),setTimeout(()=>{p.setFieldsValue(c),console.log("Form values set, current form values:",p.getFieldsValue())},100)}}catch(e){console.error("Failed to load SSO settings:",e)}})()},[s,x,p]);let j=async e=>{if(!x){O.Z.fromBackend("No access token available");return}try{let{proxy_admin_teams:s,admin_viewer_teams:l,internal_user_teams:t,internal_viewer_teams:i,default_role:r,group_claim:n,use_role_mappings:o,...c}=e,d={...c};if(o){let e=e=>e&&""!==e.trim()?e.split(",").map(e=>e.trim()).filter(e=>e.length>0):[];d.role_mappings={provider:"generic",group_claim:n,default_role:({internal_user_viewer:"internal_user_viewer",internal_user:"internal_user",proxy_admin_viewer:"proxy_admin_viewer",proxy_admin:"proxy_admin"})[r]||"internal_user",roles:{proxy_admin:e(s),proxy_admin_viewer:e(l),internal_user:e(t),internal_user_viewer:e(i)}}}await (0,k.updateSSOSettings)(x,d),a(e)}catch(e){O.Z.fromBackend("Failed to save SSO settings: "+(0,E.O)(e))}},y=async()=>{if(!x){O.Z.fromBackend("No access token available");return}try{await (0,k.updateSSOSettings)(x,{google_client_id:null,google_client_secret:null,microsoft_client_id:null,microsoft_client_secret:null,microsoft_tenant:null,generic_client_id:null,generic_client_secret:null,generic_authorization_endpoint:null,generic_token_endpoint:null,generic_userinfo_endpoint:null,proxy_base_url:null,user_email:null,sso_provider:null,role_mappings:null}),p.resetFields(),f(!1),r(),O.Z.success("SSO settings cleared successfully")}catch(e){console.error("Failed to clear SSO settings:",e),O.Z.fromBackend("Failed to clear SSO settings")}},v=e=>{let s=L[e];return s?s.fields.map(e=>(0,t.jsx)(o.Z.Item,{label:e.label,name:e.name,rules:[{required:!0,message:"Please enter the ".concat(e.label.toLowerCase())}],children:e.name.includes("client")?(0,t.jsx)(c.default.Password,{}):(0,t.jsx)(C.o,{placeholder:e.placeholder})},e.name)):null};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(u.Z,{title:h?"Edit SSO Settings":"Add SSO",visible:s,width:800,footer:null,onOk:r,onCancel:n,children:(0,t.jsxs)(o.Z,{form:p,onFinish:j,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.Z.Item,{label:"SSO Provider",name:"sso_provider",rules:[{required:!0,message:"Please select an SSO provider"}],children:(0,t.jsx)(N.default,{children:Object.entries(T).map(e=>{let[s,l]=e;return(0,t.jsx)(N.default.Option,{value:s,children:(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",padding:"4px 0"},children:[l&&(0,t.jsx)("img",{src:l,alt:s,style:{height:24,width:24,marginRight:12,objectFit:"contain"}}),(0,t.jsxs)("span",{children:["okta"===s.toLowerCase()?"Okta / Auth0":s.charAt(0).toUpperCase()+s.slice(1)," ","SSO"]})]})},s)})})}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.sso_provider!==s.sso_provider,children:e=>{let{getFieldValue:s}=e,l=s("sso_provider");return l?v(l):null}}),(0,t.jsx)(o.Z.Item,{label:"Proxy Admin Email",name:"user_email",rules:[{required:!0,message:"Please enter the email of the proxy admin"}],children:(0,t.jsx)(C.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Proxy Base URL",name:"proxy_base_url",normalize:e=>null==e?void 0:e.trim(),rules:[{required:!0,message:"Please enter the proxy base url"},{pattern:/^https?:\/\/.+/,message:"URL must start with http:// or https://"},{validator:(e,s)=>s&&/^https?:\/\/.+/.test(s)&&s.endsWith("/")?Promise.reject("URL must not end with a trailing slash"):Promise.resolve()}],children:(0,t.jsx)(C.o,{placeholder:"https://example.com"})}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.sso_provider!==s.sso_provider,children:e=>{let{getFieldValue:s}=e,l=s("sso_provider");return"okta"===l||"generic"===l?(0,t.jsx)(o.Z.Item,{label:"Use Role Mappings",name:"use_role_mappings",valuePropName:"checked",children:(0,t.jsx)(I.Z,{})}):null}}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.use_role_mappings!==s.use_role_mappings,children:e=>{let{getFieldValue:s}=e;return s("use_role_mappings")?(0,t.jsx)(o.Z.Item,{label:"Group Claim",name:"group_claim",rules:[{required:!0,message:"Please enter the group claim"}],children:(0,t.jsx)(C.o,{})}):null}}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.use_role_mappings!==s.use_role_mappings,children:e=>{let{getFieldValue:s}=e;return s("use_role_mappings")?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.Z.Item,{label:"Default Role",name:"default_role",initialValue:"Internal User",children:(0,t.jsxs)(N.default,{children:[(0,t.jsx)(N.default.Option,{value:"internal_user_viewer",children:"Internal Viewer"}),(0,t.jsx)(N.default.Option,{value:"internal_user",children:"Internal User"}),(0,t.jsx)(N.default.Option,{value:"proxy_admin_viewer",children:"Admin Viewer"}),(0,t.jsx)(N.default.Option,{value:"proxy_admin",children:"Proxy Admin"})]})}),(0,t.jsx)(o.Z.Item,{label:"Proxy Admin Teams",name:"proxy_admin_teams",children:(0,t.jsx)(C.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Admin Viewer Teams",name:"admin_viewer_teams",children:(0,t.jsx)(C.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Internal User Teams",name:"internal_user_teams",children:(0,t.jsx)(C.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Internal Viewer Teams",name:"internal_viewer_teams",children:(0,t.jsx)(C.o,{})})]}):null}})]}),(0,t.jsxs)("div",{style:{textAlign:"right",marginTop:"10px",display:"flex",justifyContent:"flex-end",alignItems:"center",gap:"8px"},children:[h&&(0,t.jsx)(d.ZP,{onClick:()=>f(!0),style:{backgroundColor:"#6366f1",borderColor:"#6366f1",color:"white"},onMouseEnter:e=>{e.currentTarget.style.backgroundColor="#5558eb",e.currentTarget.style.borderColor="#5558eb"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="#6366f1",e.currentTarget.style.borderColor="#6366f1"},children:"Clear"}),(0,t.jsx)(d.ZP,{htmlType:"submit",children:"Save"})]})]})}),(0,t.jsxs)(u.Z,{title:"Confirm Clear SSO Settings",visible:_,onOk:y,onCancel:()=>f(!1),okText:"Yes, Clear",cancelText:"Cancel",okButtonProps:{danger:!0,style:{backgroundColor:"#dc2626",borderColor:"#dc2626"}},children:[(0,t.jsx)("p",{children:"Are you sure you want to clear all SSO settings? This action cannot be undone."}),(0,t.jsx)("p",{children:"Users will no longer be able to login using SSO after this change."})]}),(0,t.jsxs)(u.Z,{title:"SSO Setup Instructions",visible:l,width:800,footer:null,onOk:m,onCancel:g,children:[(0,t.jsx)("p",{children:"Follow these steps to complete the SSO setup:"}),(0,t.jsx)(C.x,{className:"mt-2",children:"1. DO NOT Exit this TAB"}),(0,t.jsx)(C.x,{className:"mt-2",children:"2. Open a new tab, visit your proxy base url"}),(0,t.jsx)(C.x,{className:"mt-2",children:"3. Confirm your SSO is configured correctly and you can login on the new Tab"}),(0,t.jsx)(C.x,{className:"mt-2",children:"4. If Step 3 is successful, you can close this tab"}),(0,t.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,t.jsx)(d.ZP,{onClick:m,children:"Done"})})]})]})},A=l(67982),U=l(67101),R=l(84264),M=l(49566),z=l(96761),F=l(29233),G=l(62272),D=l(23639),B=l(92403),V=l(29271),q=l(34419),Y=e=>{let{accessToken:s,userID:l,proxySettings:r}=e,[n]=o.Z.useForm(),[a,c]=(0,i.useState)(!1),[d,u]=(0,i.useState)(null),[x,h]=(0,i.useState)("");(0,i.useEffect)(()=>{let e="";h(r&&r.PROXY_BASE_URL&&void 0!==r.PROXY_BASE_URL?r.PROXY_BASE_URL:window.location.origin)},[r]);let _="".concat(x,"/scim/v2"),f=async e=>{if(!s||!l){O.Z.fromBackend("You need to be logged in to create a SCIM token");return}try{c(!0);let t={key_alias:e.key_alias||"SCIM Access Token",team_id:null,models:[],allowed_routes:["/scim/*"]},i=await (0,k.keyCreateCall)(s,l,t);u(i),O.Z.success("SCIM token created successfully")}catch(e){console.error("Error creating SCIM token:",e),O.Z.fromBackend("Failed to create SCIM token: "+(0,E.O)(e))}finally{c(!1)}};return(0,t.jsx)(U.Z,{numItems:1,children:(0,t.jsxs)(p.Z,{children:[(0,t.jsx)("div",{className:"flex items-center mb-4",children:(0,t.jsx)(z.Z,{children:"SCIM Configuration"})}),(0,t.jsx)(R.Z,{className:"text-gray-600",children:"System for Cross-domain Identity Management (SCIM) allows you to automatically provision and manage users and groups in LiteLLM."}),(0,t.jsx)(A.Z,{}),(0,t.jsxs)("div",{className:"space-y-8",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center mb-2",children:[(0,t.jsx)("div",{className:"flex items-center justify-center w-6 h-6 rounded-full bg-blue-100 text-blue-700 mr-2",children:"1"}),(0,t.jsxs)(z.Z,{className:"text-lg flex items-center",children:[(0,t.jsx)(G.Z,{className:"h-5 w-5 mr-2"}),"SCIM Tenant URL"]})]}),(0,t.jsx)(R.Z,{className:"text-gray-600 mb-3",children:"Use this URL in your identity provider SCIM integration settings."}),(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)(M.Z,{value:_,disabled:!0,className:"flex-grow"}),(0,t.jsx)(F.CopyToClipboard,{text:_,onCopy:()=>O.Z.success("URL copied to clipboard"),children:(0,t.jsxs)(m.Z,{variant:"primary",className:"ml-2 flex items-center",children:[(0,t.jsx)(D.Z,{className:"h-4 w-4 mr-1"}),"Copy"]})})]})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center mb-2",children:[(0,t.jsx)("div",{className:"flex items-center justify-center w-6 h-6 rounded-full bg-blue-100 text-blue-700 mr-2",children:"2"}),(0,t.jsxs)(z.Z,{className:"text-lg flex items-center",children:[(0,t.jsx)(B.Z,{className:"h-5 w-5 mr-2"}),"Authentication Token"]})]}),(0,t.jsx)(g.Z,{title:"Using SCIM",color:"blue",className:"mb-4",children:"You need a SCIM token to authenticate with the SCIM API. Create one below and use it in your SCIM provider configuration."}),d?(0,t.jsxs)(p.Z,{className:"border border-yellow-300 bg-yellow-50",children:[(0,t.jsxs)("div",{className:"flex items-center mb-2 text-yellow-800",children:[(0,t.jsx)(V.Z,{className:"h-5 w-5 mr-2"}),(0,t.jsx)(z.Z,{className:"text-lg text-yellow-800",children:"Your SCIM Token"})]}),(0,t.jsx)(R.Z,{className:"text-yellow-800 mb-4 font-medium",children:"Make sure to copy this token now. You will not be able to see it again."}),(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)(M.Z,{value:d.key,className:"flex-grow mr-2 bg-white",type:"password",disabled:!0}),(0,t.jsx)(F.CopyToClipboard,{text:d.key,onCopy:()=>O.Z.success("Token copied to clipboard"),children:(0,t.jsxs)(m.Z,{variant:"primary",className:"flex items-center",children:[(0,t.jsx)(D.Z,{className:"h-4 w-4 mr-1"}),"Copy"]})})]}),(0,t.jsxs)(m.Z,{className:"mt-4 flex items-center",variant:"secondary",onClick:()=>u(null),children:[(0,t.jsx)(q.Z,{className:"h-4 w-4 mr-1"}),"Create Another Token"]})]}):(0,t.jsx)("div",{className:"bg-gray-50 p-4 rounded-lg",children:(0,t.jsxs)(o.Z,{form:n,onFinish:f,layout:"vertical",children:[(0,t.jsx)(o.Z.Item,{name:"key_alias",label:"Token Name",rules:[{required:!0,message:"Please enter a name for your token"}],children:(0,t.jsx)(M.Z,{placeholder:"SCIM Access Token"})}),(0,t.jsx)(o.Z.Item,{children:(0,t.jsxs)(m.Z,{variant:"primary",type:"submit",loading:a,className:"flex items-center",children:[(0,t.jsx)(B.Z,{className:"h-4 w-4 mr-1"}),"Create SCIM Token"]})})]})})]})]})]})})},K=e=>{let{accessToken:s,onSuccess:l}=e,[r]=o.Z.useForm(),[n,a]=(0,i.useState)(!1);(0,i.useEffect)(()=>{(async()=>{if(s)try{let e=await (0,k.getSSOSettings)(s);if(e&&e.values){let s=e.values.ui_access_mode,l={};s&&"object"==typeof s?l={ui_access_mode_type:s.type,restricted_sso_group:s.restricted_sso_group,sso_group_jwt_field:s.sso_group_jwt_field}:"string"==typeof s&&(l={ui_access_mode_type:s,restricted_sso_group:e.values.restricted_sso_group,sso_group_jwt_field:e.values.team_ids_jwt_field||e.values.sso_group_jwt_field}),r.setFieldsValue(l)}}catch(e){console.error("Failed to load UI access settings:",e)}})()},[s,r]);let c=async e=>{if(!s){O.Z.fromBackend("No access token available");return}a(!0);try{let t;t="all_authenticated_users"===e.ui_access_mode_type?{ui_access_mode:"none"}:{ui_access_mode:{type:e.ui_access_mode_type,restricted_sso_group:e.restricted_sso_group,sso_group_jwt_field:e.sso_group_jwt_field}},await (0,k.updateSSOSettings)(s,t),l()}catch(e){console.error("Failed to save UI access settings:",e),O.Z.fromBackend("Failed to save UI access settings")}finally{a(!1)}};return(0,t.jsxs)("div",{style:{padding:"16px"},children:[(0,t.jsx)("div",{style:{marginBottom:"16px"},children:(0,t.jsx)(C.x,{style:{fontSize:"14px",color:"#6b7280"},children:"Configure who can access the UI interface and how group information is extracted from JWT tokens."})}),(0,t.jsxs)(o.Z,{form:r,onFinish:c,layout:"vertical",children:[(0,t.jsx)(o.Z.Item,{label:"UI Access Mode",name:"ui_access_mode_type",tooltip:"Controls who can access the UI interface",children:(0,t.jsxs)(N.default,{placeholder:"Select access mode",children:[(0,t.jsx)(N.default.Option,{value:"all_authenticated_users",children:"All Authenticated Users"}),(0,t.jsx)(N.default.Option,{value:"restricted_sso_group",children:"Restricted SSO Group"})]})}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.ui_access_mode_type!==s.ui_access_mode_type,children:e=>{let{getFieldValue:s}=e;return"restricted_sso_group"===s("ui_access_mode_type")?(0,t.jsx)(o.Z.Item,{label:"Restricted SSO Group",name:"restricted_sso_group",rules:[{required:!0,message:"Please enter the restricted SSO group"}],children:(0,t.jsx)(C.o,{placeholder:"ui-access-group"})}):null}}),(0,t.jsx)(o.Z.Item,{label:"SSO Group JWT Field",name:"sso_group_jwt_field",tooltip:"JWT field name that contains team/group information. Use dot notation to access nested fields.",children:(0,t.jsx)(C.o,{placeholder:"groups"})}),(0,t.jsx)("div",{style:{textAlign:"right",marginTop:"16px"},children:(0,t.jsx)(d.ZP,{type:"primary",htmlType:"submit",loading:n,style:{backgroundColor:"#6366f1",borderColor:"#6366f1"},children:"Update UI Access Control"})})]})]})},H=l(12363),W=l(55584),Q=l(29827),J=l(21770),X=l(90246);let $=(0,X.n)("uiSettings"),ee=e=>{let s=(0,Q.NL)();return(0,J.D)({mutationFn:async s=>{if(!e)throw Error("Access token is required");return(0,k.updateUiSettings)(e,s)},onSuccess:()=>{s.invalidateQueries({queryKey:$.all})}})};var es=l(39760),el=l(1633);let et={"api-keys":"Manage virtual keys for API access and authentication","llm-playground":"Interactive playground for testing LLM requests",models:"Configure and manage LLM models and endpoints",agents:"Create and manage AI agents","mcp-servers":"Configure Model Context Protocol servers",guardrails:"Set up content moderation and safety guardrails",policies:"Define access control and usage policies","search-tools":"Configure RAG search and retrieval tools","vector-stores":"Manage vector databases for embeddings",new_usage:"View usage analytics and metrics",logs:"Access request and response logs",users:"Manage internal user accounts and permissions",teams:"Create and manage teams for access control",organizations:"Manage organizations and their members",budgets:"Set and monitor spending budgets",api_ref:"Browse API documentation and endpoints","model-hub-table":"Explore available AI models and providers","learning-resources":"Access tutorials and documentation",caching:"Configure response caching settings","transform-request":"Set up request transformation rules","cost-tracking":"Track and analyze API costs","ui-theme":"Customize dashboard appearance","tag-management":"Organize resources with tags",prompts:"Manage and version prompt templates","claude-code-plugins":"Configure Claude Code plugins",usage:"View legacy usage dashboard","router-settings":"Configure routing and load balancing settings","logging-and-alerts":"Set up logging and alert configurations","admin-panel":"Access admin panel and settings"};var ei=l(20347);let er=e=>!e||0===e.length||e.some(e=>ei.lo.includes(e)),en=()=>{let e=[];return el.j.forEach(s=>{s.items.forEach(l=>{if(l.page&&"tools"!==l.page&&"experimental"!==l.page&&"settings"!==l.page&&er(l.roles)){let t="string"==typeof l.label?l.label:l.key;e.push({page:l.page,label:t,group:s.groupLabel,description:et[l.page]||"No description available"})}if(l.children){let t="string"==typeof l.label?l.label:l.key;l.children.forEach(l=>{if(er(l.roles)){let i="string"==typeof l.label?l.label:l.key;e.push({page:l.page,label:i,group:"".concat(s.groupLabel," > ").concat(t),description:et[l.page]||"No description available"})}})}})}),e};var ea=l(58760),eo=l(3810),ec=l(44851);function ed(e){let{enabledPagesInternalUsers:s,enabledPagesPropertyDescription:l,isUpdating:n,onUpdate:a}=e,o=null!=s,c=(0,i.useMemo)(()=>en(),[]),u=(0,i.useMemo)(()=>{let e={};return c.forEach(s=>{e[s.group]||(e[s.group]=[]),e[s.group].push(s)}),e},[c]),[m,g]=(0,i.useState)(s||[]);return(0,i.useMemo)(()=>{s?g(s):g([])},[s]),(0,t.jsxs)(ea.Z,{direction:"vertical",size:"middle",style:{width:"100%"},children:[(0,t.jsxs)(ea.Z,{direction:"vertical",size:4,children:[(0,t.jsxs)(ea.Z,{align:"center",children:[(0,t.jsx)(r.default.Text,{strong:!0,children:"Internal User Page Visibility"}),!o&&(0,t.jsx)(eo.Z,{color:"default",style:{marginLeft:"8px"},children:"Not set (all pages visible)"}),o&&(0,t.jsxs)(eo.Z,{color:"blue",style:{marginLeft:"8px"},children:[m.length," page",1!==m.length?"s":""," selected"]})]}),l&&(0,t.jsx)(r.default.Text,{type:"secondary",children:l}),(0,t.jsx)(r.default.Text,{type:"secondary",style:{fontSize:"12px",fontStyle:"italic"},children:"By default, all pages are visible to internal users. Select specific pages to restrict visibility."}),(0,t.jsx)(r.default.Text,{type:"secondary",style:{fontSize:"12px",color:"#8b5cf6"},children:"Note: Only pages accessible to internal user roles are shown here. Admin-only pages are excluded as they cannot be made visible to internal users regardless of this setting."})]}),(0,t.jsx)(ec.default,{items:[{key:"page-visibility",label:"Configure Page Visibility",children:(0,t.jsxs)(ea.Z,{direction:"vertical",size:"middle",style:{width:"100%"},children:[(0,t.jsx)(I.Z.Group,{value:m,onChange:g,style:{width:"100%"},children:(0,t.jsx)(ea.Z,{direction:"vertical",size:"middle",style:{width:"100%"},children:Object.entries(u).map(e=>{let[s,l]=e;return(0,t.jsxs)("div",{children:[(0,t.jsx)(r.default.Text,{strong:!0,style:{fontSize:"11px",color:"#6b7280",letterSpacing:"0.05em",display:"block",marginBottom:"8px"},children:s}),(0,t.jsx)(ea.Z,{direction:"vertical",size:"small",style:{marginLeft:"16px",width:"100%"},children:l.map(e=>(0,t.jsx)("div",{style:{marginBottom:"4px"},children:(0,t.jsx)(I.Z,{value:e.page,children:(0,t.jsxs)(ea.Z,{direction:"vertical",size:0,children:[(0,t.jsx)(r.default.Text,{children:e.label}),(0,t.jsx)(r.default.Text,{type:"secondary",style:{fontSize:"12px"},children:e.description})]})})},e.page))})]},s)})})}),(0,t.jsxs)(ea.Z,{children:[(0,t.jsx)(d.ZP,{type:"primary",onClick:()=>{a({enabled_ui_pages_internal_users:m.length>0?m:null})},loading:n,disabled:n,children:"Save Page Visibility Settings"}),o&&(0,t.jsx)(d.ZP,{onClick:()=>{g([]),a({enabled_ui_pages_internal_users:null})},loading:n,disabled:n,children:"Reset to Default (All Pages)"})]})]})}]})]})}var eu=l(5945),em=l(50337),eg=l(63709),ep=l(23496);function ex(){var e,s,l,i,a,o;let{accessToken:c}=(0,es.Z)(),{data:d,isLoading:u,isError:m,error:g}=(0,W.L)(),{mutate:p,isPending:x,error:h}=ee(c),_=null==d?void 0:d.field_schema,f=null==_?void 0:null===(e=_.properties)||void 0===e?void 0:e.disable_model_add_for_internal_users,j=null==_?void 0:null===(s=_.properties)||void 0===s?void 0:s.disable_team_admin_delete_team_user,y=null==_?void 0:null===(l=_.properties)||void 0===l?void 0:l.enabled_ui_pages_internal_users,v=null!==(i=null==d?void 0:d.values)&&void 0!==i?i:{},b=!!v.disable_model_add_for_internal_users,S=!!v.disable_team_admin_delete_team_user;return(0,t.jsx)(eu.Z,{title:"UI Settings",children:u?(0,t.jsx)(em.Z,{active:!0}):m?(0,t.jsx)(n.Z,{type:"error",message:"Could not load UI settings",description:g instanceof Error?g.message:void 0}):(0,t.jsxs)(ea.Z,{direction:"vertical",size:"large",style:{width:"100%"},children:[(null==_?void 0:_.description)&&(0,t.jsx)(r.default.Paragraph,{style:{marginBottom:0},children:_.description}),h&&(0,t.jsx)(n.Z,{type:"error",message:"Could not update UI settings",description:h instanceof Error?h.message:void 0}),(0,t.jsxs)(ea.Z,{align:"start",size:"middle",children:[(0,t.jsx)(eg.Z,{checked:b,disabled:x,loading:x,onChange:e=>{p({disable_model_add_for_internal_users:e},{onSuccess:()=>{O.Z.success("UI settings updated successfully")},onError:e=>{O.Z.fromBackend(e)}})},"aria-label":null!==(a=null==f?void 0:f.description)&&void 0!==a?a:"Disable model add for internal users"}),(0,t.jsxs)(ea.Z,{direction:"vertical",size:4,children:[(0,t.jsx)(r.default.Text,{strong:!0,children:"Disable model add for internal users"}),(null==f?void 0:f.description)&&(0,t.jsx)(r.default.Text,{type:"secondary",children:f.description})]})]}),(0,t.jsxs)(ea.Z,{align:"start",size:"middle",children:[(0,t.jsx)(eg.Z,{checked:S,disabled:x,loading:x,onChange:e=>{p({disable_team_admin_delete_team_user:e},{onSuccess:()=>{O.Z.success("UI settings updated successfully")},onError:e=>{O.Z.fromBackend(e)}})},"aria-label":null!==(o=null==j?void 0:j.description)&&void 0!==o?o:"Disable team admin delete team user"}),(0,t.jsxs)(ea.Z,{direction:"vertical",size:4,children:[(0,t.jsx)(r.default.Text,{strong:!0,children:"Disable team admin delete team user"}),(null==j?void 0:j.description)&&(0,t.jsx)(r.default.Text,{type:"secondary",children:j.description})]})]}),(0,t.jsx)(ep.Z,{}),(0,t.jsx)(ed,{enabledPagesInternalUsers:v.enabled_ui_pages_internal_users,enabledPagesPropertyDescription:null==y?void 0:y.description,isUpdating:x,onUpdate:e=>{p(e,{onSuccess:()=>{O.Z.success("Page visibility settings updated successfully")},onError:e=>{O.Z.fromBackend(e)}})}})]})})}var eh=l(11713);let e_=(0,X.n)("sso"),ef=()=>{let{accessToken:e,userId:s,userRole:l}=(0,es.Z)();return(0,eh.a)({queryKey:e_.detail("settings"),queryFn:async()=>await (0,k.getSSOSettings)(e),enabled:!!(e&&s&&l)})};var ej=l(76188),ey=l(88906),ev=l(15868),eb=l(18930);let eS={google:"https://artificialanalysis.ai/img/logos/google_small.svg",microsoft:"https://upload.wikimedia.org/wikipedia/commons/a/a8/Microsoft_Azure_Logo.svg",okta:"https://www.okta.com/sites/default/files/Okta_Logo_BrightBlue_Medium.png",generic:""},eZ={google:"Google SSO",microsoft:"Microsoft SSO",okta:"Okta / Auth0 SSO",generic:"Generic SSO"},ew={internal_user_viewer:"Internal Viewer",internal_user:"Internal User",proxy_admin_viewer:"Proxy Admin Viewer",proxy_admin:"Proxy Admin"};var eN=l(31283);let eI={google:{envVarMap:{google_client_id:"GOOGLE_CLIENT_ID",google_client_secret:"GOOGLE_CLIENT_SECRET"},fields:[{label:"Google Client ID",name:"google_client_id"},{label:"Google Client Secret",name:"google_client_secret"}]},microsoft:{envVarMap:{microsoft_client_id:"MICROSOFT_CLIENT_ID",microsoft_client_secret:"MICROSOFT_CLIENT_SECRET",microsoft_tenant:"MICROSOFT_TENANT"},fields:[{label:"Microsoft Client ID",name:"microsoft_client_id"},{label:"Microsoft Client Secret",name:"microsoft_client_secret"},{label:"Microsoft Tenant",name:"microsoft_tenant"}]},okta:{envVarMap:{generic_client_id:"GENERIC_CLIENT_ID",generic_client_secret:"GENERIC_CLIENT_SECRET",generic_authorization_endpoint:"GENERIC_AUTHORIZATION_ENDPOINT",generic_token_endpoint:"GENERIC_TOKEN_ENDPOINT",generic_userinfo_endpoint:"GENERIC_USERINFO_ENDPOINT"},fields:[{label:"Generic Client ID",name:"generic_client_id"},{label:"Generic Client Secret",name:"generic_client_secret"},{label:"Authorization Endpoint",name:"generic_authorization_endpoint",placeholder:"https://your-domain/authorize"},{label:"Token Endpoint",name:"generic_token_endpoint",placeholder:"https://your-domain/token"},{label:"Userinfo Endpoint",name:"generic_userinfo_endpoint",placeholder:"https://your-domain/userinfo"}]},generic:{envVarMap:{generic_client_id:"GENERIC_CLIENT_ID",generic_client_secret:"GENERIC_CLIENT_SECRET",generic_authorization_endpoint:"GENERIC_AUTHORIZATION_ENDPOINT",generic_token_endpoint:"GENERIC_TOKEN_ENDPOINT",generic_userinfo_endpoint:"GENERIC_USERINFO_ENDPOINT"},fields:[{label:"Generic Client ID",name:"generic_client_id"},{label:"Generic Client Secret",name:"generic_client_secret"},{label:"Authorization Endpoint",name:"generic_authorization_endpoint"},{label:"Token Endpoint",name:"generic_token_endpoint"},{label:"Userinfo Endpoint",name:"generic_userinfo_endpoint"}]}},eC=e=>{let s=eI[e];return s?s.fields.map(e=>(0,t.jsx)(o.Z.Item,{label:e.label,name:e.name,rules:[{required:!0,message:"Please enter the ".concat(e.label.toLowerCase())}],children:e.name.includes("client")?(0,t.jsx)(c.default.Password,{}):(0,t.jsx)(eN.o,{placeholder:e.placeholder})},e.name)):null};var ek=e=>{let{form:s,onFormSubmit:l}=e;return(0,t.jsx)("div",{children:(0,t.jsxs)(o.Z,{form:s,onFinish:l,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,t.jsx)(o.Z.Item,{label:"SSO Provider",name:"sso_provider",rules:[{required:!0,message:"Please select an SSO provider"}],children:(0,t.jsx)(N.default,{children:Object.entries(eS).map(e=>{let[s,l]=e;return(0,t.jsx)(N.default.Option,{value:s,children:(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",padding:"4px 0"},children:[l&&(0,t.jsx)("img",{src:l,alt:s,style:{height:24,width:24,marginRight:12,objectFit:"contain"}}),(0,t.jsx)("span",{children:eZ[s]||s.charAt(0).toUpperCase()+s.slice(1)+" SSO"})]})},s)})})}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.sso_provider!==s.sso_provider,children:e=>{let{getFieldValue:s}=e,l=s("sso_provider");return l?eC(l):null}}),(0,t.jsx)(o.Z.Item,{label:"Proxy Admin Email",name:"user_email",rules:[{required:!0,message:"Please enter the email of the proxy admin"}],children:(0,t.jsx)(eN.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Proxy Base URL",name:"proxy_base_url",normalize:e=>null==e?void 0:e.trim(),rules:[{required:!0,message:"Please enter the proxy base url"},{pattern:/^https?:\/\/.+/,message:"URL must start with http:// or https://"},{validator:(e,s)=>s&&/^https?:\/\/.+/.test(s)&&s.endsWith("/")?Promise.reject("URL must not end with a trailing slash"):Promise.resolve()}],children:(0,t.jsx)(eN.o,{placeholder:"https://example.com"})}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.sso_provider!==s.sso_provider,children:e=>{let{getFieldValue:s}=e,l=s("sso_provider");return"okta"===l||"generic"===l?(0,t.jsx)(o.Z.Item,{label:"Use Role Mappings",name:"use_role_mappings",valuePropName:"checked",children:(0,t.jsx)(I.Z,{})}):null}}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.use_role_mappings!==s.use_role_mappings||e.sso_provider!==s.sso_provider,children:e=>{let{getFieldValue:s}=e,l=s("use_role_mappings"),i=s("sso_provider");return l&&("okta"===i||"generic"===i)?(0,t.jsx)(o.Z.Item,{label:"Group Claim",name:"group_claim",rules:[{required:!0,message:"Please enter the group claim"}],children:(0,t.jsx)(eN.o,{})}):null}}),(0,t.jsx)(o.Z.Item,{noStyle:!0,shouldUpdate:(e,s)=>e.use_role_mappings!==s.use_role_mappings||e.sso_provider!==s.sso_provider,children:e=>{let{getFieldValue:s}=e,l=s("use_role_mappings"),i=s("sso_provider");return l&&("okta"===i||"generic"===i)?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.Z.Item,{label:"Default Role",name:"default_role",initialValue:"Internal User",children:(0,t.jsxs)(N.default,{children:[(0,t.jsx)(N.default.Option,{value:"internal_user_viewer",children:"Internal Viewer"}),(0,t.jsx)(N.default.Option,{value:"internal_user",children:"Internal User"}),(0,t.jsx)(N.default.Option,{value:"proxy_admin_viewer",children:"Admin Viewer"}),(0,t.jsx)(N.default.Option,{value:"proxy_admin",children:"Proxy Admin"})]})}),(0,t.jsx)(o.Z.Item,{label:"Proxy Admin Teams",name:"proxy_admin_teams",children:(0,t.jsx)(eN.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Admin Viewer Teams",name:"admin_viewer_teams",children:(0,t.jsx)(eN.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Internal User Teams",name:"internal_user_teams",children:(0,t.jsx)(eN.o,{})}),(0,t.jsx)(o.Z.Item,{label:"Internal Viewer Teams",name:"internal_viewer_teams",children:(0,t.jsx)(eN.o,{})})]}):null}})]})})};let eO=()=>{let{accessToken:e}=(0,es.Z)();return(0,J.D)({mutationFn:async s=>{if(!e)throw Error("Access token is required");return await (0,k.updateSSOSettings)(e,s)}})},eE=e=>{let{proxy_admin_teams:s,admin_viewer_teams:l,internal_user_teams:t,internal_viewer_teams:i,default_role:r,group_claim:n,use_role_mappings:a,...o}=e,c={...o};if(a){let e=e=>e&&""!==e.trim()?e.split(",").map(e=>e.trim()).filter(e=>e.length>0):[];c.role_mappings={provider:"generic",group_claim:n,default_role:({internal_user_viewer:"internal_user_viewer",internal_user:"internal_user",proxy_admin_viewer:"proxy_admin_viewer",proxy_admin:"proxy_admin"})[r]||"internal_user",roles:{proxy_admin:e(s),proxy_admin_viewer:e(l),internal_user:e(t),internal_user_viewer:e(i)}}}return c},eT=e=>{if(e.google_client_id)return"google";if(e.microsoft_client_id)return"microsoft";if(e.generic_client_id){var s,l;return(null===(s=e.generic_authorization_endpoint)||void 0===s?void 0:s.includes("okta"))||(null===(l=e.generic_authorization_endpoint)||void 0===l?void 0:l.includes("auth0"))?"okta":"generic"}return null};var eL=e=>{let{isVisible:s,onCancel:l,onSuccess:i}=e,[r]=o.Z.useForm(),{mutateAsync:n,isPending:a}=eO(),c=async e=>{let s=eE(e);await n(s,{onSuccess:()=>{O.Z.success("SSO settings added successfully"),i()},onError:e=>{O.Z.fromBackend("Failed to save SSO settings: "+(0,E.O)(e))}})},m=()=>{r.resetFields(),l()};return(0,t.jsx)(u.Z,{title:"Add SSO",open:s,width:800,footer:(0,t.jsxs)(ea.Z,{children:[(0,t.jsx)(d.ZP,{onClick:m,disabled:a,children:"Cancel"}),(0,t.jsx)(d.ZP,{loading:a,onClick:()=>r.submit(),children:a?"Adding...":"Add SSO"})]}),onCancel:m,children:(0,t.jsx)(ek,{form:r,onFormSubmit:c})})},eP=l(21609),eA=e=>{let{isVisible:s,onCancel:l,onSuccess:i}=e,{data:r}=ef(),{mutateAsync:n,isPending:a}=eO(),o=async()=>{await n({google_client_id:null,google_client_secret:null,microsoft_client_id:null,microsoft_client_secret:null,microsoft_tenant:null,generic_client_id:null,generic_client_secret:null,generic_authorization_endpoint:null,generic_token_endpoint:null,generic_userinfo_endpoint:null,proxy_base_url:null,user_email:null,sso_provider:null,role_mappings:null},{onSuccess:()=>{O.Z.success("SSO settings cleared successfully"),l(),i()},onError:e=>{O.Z.fromBackend("Failed to clear SSO settings: "+(0,E.O)(e))}})};return(0,t.jsx)(eP.Z,{isOpen:s,title:"Confirm Clear SSO Settings",alertMessage:"This action cannot be undone.",message:"Are you sure you want to clear all SSO settings? Users will no longer be able to login using SSO after this change.",resourceInformationTitle:"SSO Settings",resourceInformation:[{label:"Provider",value:(null==r?void 0:r.values)&&eT(null==r?void 0:r.values)||"Generic"}],onCancel:l,onOk:o,confirmLoading:a})},eU=e=>{let{isVisible:s,onCancel:l,onSuccess:r}=e,[n]=o.Z.useForm(),a=ef(),{mutateAsync:c,isPending:m}=eO();(0,i.useEffect)(()=>{if(s&&a.data&&a.data.values){var e,l,t,i,r,o;let s=a.data;console.log("Raw SSO data received:",s),console.log("SSO values:",s.values),console.log("user_email from API:",s.values.user_email);let c=null;s.values.google_client_id?c="google":s.values.microsoft_client_id?c="microsoft":s.values.generic_client_id&&(c=(null===(e=s.values.generic_authorization_endpoint)||void 0===e?void 0:e.includes("okta"))||(null===(l=s.values.generic_authorization_endpoint)||void 0===l?void 0:l.includes("auth0"))?"okta":"generic");let d={};if(s.values.role_mappings){let e=s.values.role_mappings,l=e=>e&&0!==e.length?e.join(", "):"";d={use_role_mappings:!0,group_claim:e.group_claim,default_role:e.default_role||"internal_user",proxy_admin_teams:l(null===(t=e.roles)||void 0===t?void 0:t.proxy_admin),admin_viewer_teams:l(null===(i=e.roles)||void 0===i?void 0:i.proxy_admin_viewer),internal_user_teams:l(null===(r=e.roles)||void 0===r?void 0:r.internal_user),internal_viewer_teams:l(null===(o=e.roles)||void 0===o?void 0:o.internal_user_viewer)}}let u={sso_provider:c,...s.values,...d};console.log("Setting form values:",u),n.resetFields(),setTimeout(()=>{n.setFieldsValue(u),console.log("Form values set, current form values:",n.getFieldsValue())},100)}},[s,a.data,n]);let g=async e=>{try{let s=eE(e);await c(s,{onSuccess:()=>{O.Z.success("SSO settings updated successfully"),r()},onError:e=>{O.Z.fromBackend("Failed to save SSO settings: "+(0,E.O)(e))}})}catch(e){O.Z.fromBackend("Failed to process SSO settings: "+(0,E.O)(e))}},p=()=>{n.resetFields(),l()};return(0,t.jsx)(u.Z,{title:"Edit SSO Settings",open:s,width:800,footer:(0,t.jsxs)(ea.Z,{children:[(0,t.jsx)(d.ZP,{onClick:p,disabled:m,children:"Cancel"}),(0,t.jsx)(d.ZP,{loading:m,onClick:()=>n.submit(),children:m?"Saving...":"Save"})]}),onCancel:p,children:(0,t.jsx)(ek,{form:n,onFormSubmit:g})})},eR=l(42208),eM=l(87769);function ez(e){let{defaultHidden:s=!0,value:l}=e,[r,n]=(0,i.useState)(s);return(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:"font-mono text-gray-600 flex-1",children:l?r?"•".repeat(l.length):l:(0,t.jsx)("span",{className:"text-gray-400 italic",children:"Not configured"})}),l&&(0,t.jsx)(d.ZP,{type:"text",size:"small",icon:r?(0,t.jsx)(eR.Z,{className:"w-4 h-4"}):(0,t.jsx)(eM.Z,{className:"w-4 h-4"}),onClick:()=>n(!r),className:"text-gray-400 hover:text-gray-600"})]})}var eF=l(56609),eG=l(95805);let{Title:eD,Text:eB}=r.default;function eV(e){let{roleMappings:s}=e;if(!s)return null;let l=[{title:"Role",dataIndex:"role",key:"role",render:e=>(0,t.jsx)(eB,{strong:!0,children:ew[e]})},{title:"Mapped Groups",dataIndex:"groups",key:"groups",render:e=>(0,t.jsx)(t.Fragment,{children:e.length>0?e.map((e,s)=>(0,t.jsx)(eo.Z,{color:"blue",children:e},s)):(0,t.jsx)(eB,{className:"text-gray-400 italic",children:"No groups mapped"})})}];return(0,t.jsxs)(eu.Z,{children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)(eG.Z,{className:"w-6 h-6 text-gray-400 mb-2"}),(0,t.jsx)(eD,{level:3,children:"Role Mappings"})]}),(0,t.jsxs)("div",{className:"space-y-8",children:[(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)(eD,{level:5,children:"Group Claim"}),(0,t.jsx)("div",{children:(0,t.jsx)(eB,{code:!0,children:s.group_claim})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eD,{level:5,children:"Default Role"}),(0,t.jsx)("div",{children:(0,t.jsx)(eB,{strong:!0,children:ew[s.default_role]})})]})]}),(0,t.jsx)(ep.Z,{}),(0,t.jsx)(eF.Z,{columns:l,dataSource:Object.entries(s.roles).map(e=>{let[s,l]=e;return{role:s,groups:l}}),pagination:!1,bordered:!0,size:"small",className:"w-full"})]})]})}var eq=l(85180);let{Title:eY,Paragraph:eK}=r.default;function eH(e){let{onAdd:s}=e;return(0,t.jsx)("div",{className:"bg-white p-12 rounded-lg border border-dashed border-gray-300 text-center w-full",children:(0,t.jsx)(eq.Z,{image:eq.Z.PRESENTED_IMAGE_SIMPLE,description:(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(eY,{level:4,children:"No SSO Configuration Found"}),(0,t.jsx)(eK,{type:"secondary",className:"max-w-md mx-auto",children:"Configure Single Sign-On (SSO) to enable seamless authentication for your team members using your identity provider."})]}),children:(0,t.jsx)(d.ZP,{type:"primary",size:"large",onClick:s,className:"flex items-center gap-2 mx-auto mt-4",children:"Configure SSO"})})})}let{Title:eW,Text:eQ}=r.default;function eJ(){return(0,t.jsx)(eu.Z,{children:(0,t.jsxs)(ea.Z,{direction:"vertical",size:"large",className:"w-full",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)(ey.Z,{className:"w-6 h-6 text-gray-400"}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eW,{level:3,children:"SSO Configuration"}),(0,t.jsx)(eQ,{type:"secondary",children:"Manage Single Sign-On authentication settings"})]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)(em.Z.Button,{active:!0,size:"default",style:{width:170,height:32}}),(0,t.jsx)(em.Z.Button,{active:!0,size:"default",style:{width:190,height:32}})]})]}),(0,t.jsxs)(ej.Z,{bordered:!0,column:{xxl:1,xl:1,lg:1,md:1,sm:1,xs:1},children:[(0,t.jsx)(ej.Z.Item,{label:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:80,height:16}}),children:(0,t.jsx)("div",{style:{display:"flex",alignItems:"center",gap:"8px"},children:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:100,height:16}})})}),(0,t.jsx)(ej.Z.Item,{label:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:80,height:16}}),children:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:200,height:16}})}),(0,t.jsx)(ej.Z.Item,{label:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:80,height:16}}),children:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:250,height:16}})}),(0,t.jsx)(ej.Z.Item,{label:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:80,height:16}}),children:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:180,height:16}})}),(0,t.jsx)(ej.Z.Item,{label:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:80,height:16}}),children:(0,t.jsx)(em.Z.Node,{active:!0,style:{width:220,height:16}})})]})]})})}let{Title:eX,Text:e$}=r.default;function e0(){let{data:e,refetch:s,isLoading:l}=ef(),[r,n]=(0,i.useState)(!1),[a,o]=(0,i.useState)(!1),[c,u]=(0,i.useState)(!1),m=!!(null==e?void 0:e.values.google_client_id)||!!(null==e?void 0:e.values.microsoft_client_id)||!!(null==e?void 0:e.values.generic_client_id),g=(null==e?void 0:e.values)?eT(e.values):null,p=!!(null==e?void 0:e.values.role_mappings),x=e=>(0,t.jsx)(e$,{className:"font-mono text-gray-600 text-sm",copyable:!!e,children:e||"-"}),h=e=>e||(0,t.jsx)("span",{className:"text-gray-400 italic",children:"Not configured"}),_={column:{xxl:1,xl:1,lg:1,md:1,sm:1,xs:1}},f={google:{providerText:eZ.google,fields:[{label:"Client ID",render:e=>(0,t.jsx)(ez,{value:e.google_client_id})},{label:"Client Secret",render:e=>(0,t.jsx)(ez,{value:e.google_client_secret})},{label:"Proxy Base URL",render:e=>h(e.proxy_base_url)}]},microsoft:{providerText:eZ.microsoft,fields:[{label:"Client ID",render:e=>(0,t.jsx)(ez,{value:e.microsoft_client_id})},{label:"Client Secret",render:e=>(0,t.jsx)(ez,{value:e.microsoft_client_secret})},{label:"Tenant",render:e=>h(e.microsoft_tenant)},{label:"Proxy Base URL",render:e=>h(e.proxy_base_url)}]},okta:{providerText:eZ.okta,fields:[{label:"Client ID",render:e=>(0,t.jsx)(ez,{value:e.generic_client_id})},{label:"Client Secret",render:e=>(0,t.jsx)(ez,{value:e.generic_client_secret})},{label:"Authorization Endpoint",render:e=>x(e.generic_authorization_endpoint)},{label:"Token Endpoint",render:e=>x(e.generic_token_endpoint)},{label:"User Info Endpoint",render:e=>x(e.generic_userinfo_endpoint)},{label:"Proxy Base URL",render:e=>h(e.proxy_base_url)}]},generic:{providerText:eZ.generic,fields:[{label:"Client ID",render:e=>(0,t.jsx)(ez,{value:e.generic_client_id})},{label:"Client Secret",render:e=>(0,t.jsx)(ez,{value:e.generic_client_secret})},{label:"Authorization Endpoint",render:e=>x(e.generic_authorization_endpoint)},{label:"Token Endpoint",render:e=>x(e.generic_token_endpoint)},{label:"User Info Endpoint",render:e=>x(e.generic_userinfo_endpoint)},{label:"Proxy Base URL",render:e=>h(e.proxy_base_url)}]}};return(0,t.jsxs)(t.Fragment,{children:[l?(0,t.jsx)(eJ,{}):(0,t.jsxs)(ea.Z,{direction:"vertical",size:"large",className:"w-full",children:[(0,t.jsx)(eu.Z,{children:(0,t.jsxs)(ea.Z,{direction:"vertical",size:"large",className:"w-full",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(0,t.jsx)(ey.Z,{className:"w-6 h-6 text-gray-400"}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eX,{level:3,children:"SSO Configuration"}),(0,t.jsx)(e$,{type:"secondary",children:"Manage Single Sign-On authentication settings"})]})]}),(0,t.jsx)("div",{className:"flex items-center gap-3",children:m&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(d.ZP,{icon:(0,t.jsx)(ev.Z,{className:"w-4 h-4"}),onClick:()=>u(!0),children:"Edit SSO Settings"}),(0,t.jsx)(d.ZP,{danger:!0,icon:(0,t.jsx)(eb.Z,{className:"w-4 h-4"}),onClick:()=>n(!0),children:"Delete SSO Settings"})]})})]}),m?(()=>{if(!(null==e?void 0:e.values)||!g)return null;let{values:s}=e,l=f[g];return l?(0,t.jsxs)(ej.Z,{bordered:!0,..._,children:[(0,t.jsx)(ej.Z.Item,{label:"Provider",children:(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"8px"},children:[eS[g]&&(0,t.jsx)("img",{src:eS[g],alt:g,style:{height:24,width:24,objectFit:"contain"}}),(0,t.jsx)("span",{children:l.providerText})]})}),l.fields.map((e,l)=>(0,t.jsx)(ej.Z.Item,{label:e.label,children:e.render(s)},l))]}):null})():(0,t.jsx)(eH,{onAdd:()=>o(!0)})]})}),p&&(0,t.jsx)(eV,{roleMappings:null==e?void 0:e.values.role_mappings})]}),(0,t.jsx)(eA,{isVisible:r,onCancel:()=>n(!1),onSuccess:()=>s()}),(0,t.jsx)(eL,{isVisible:a,onCancel:()=>o(!1),onSuccess:()=>{o(!1),s()}}),(0,t.jsx)(eU,{isVisible:c,onCancel:()=>u(!1),onSuccess:()=>{u(!1),s()}})]})}var e1=e=>{let{searchParams:s,accessToken:l,userID:N,showSSOBanner:I,premiumUser:C,proxySettings:E,userRole:T}=e,[L]=o.Z.useForm(),[A]=o.Z.useForm(),{Title:U,Paragraph:R}=r.default,[M,z]=(0,i.useState)(""),[F,G]=(0,i.useState)(null),[D,B]=(0,i.useState)(null),[V,q]=(0,i.useState)(!1),[W,Q]=(0,i.useState)(!1),[J,X]=(0,i.useState)(!1),[$,ee]=(0,i.useState)(!1),[es,el]=(0,i.useState)(!1),[et,ei]=(0,i.useState)(!1),[er,en]=(0,i.useState)(!1),[ea,eo]=(0,i.useState)(!1),[ec,ed]=(0,i.useState)(!1),[eu,em]=(0,i.useState)(!1),[eg,ep]=(0,i.useState)([]),[eh,e_]=(0,i.useState)(null),[ef,ej]=(0,i.useState)(!1);(0,a.useRouter)();let[ey,ev]=(0,i.useState)(null);console.log=function(){};let eb=(0,H.n)(),eS="All IP Addresses Allowed",eZ=eb;eZ+="/fallback/login";let ew=async()=>{if(l)try{let e=await (0,k.getSSOSettings)(l);if(console.log("SSO data:",e),e&&e.values){let s=e.values.google_client_id&&e.values.google_client_secret,l=e.values.microsoft_client_id&&e.values.microsoft_client_secret,t=e.values.generic_client_id&&e.values.generic_client_secret;ej(s||l||t)}else ej(!1)}catch(e){console.error("Error checking SSO configuration:",e),ej(!1)}},eN=async()=>{try{if(!0!==C){O.Z.fromBackend("This feature is only available for premium users. Please upgrade your account.");return}if(l){let e=await (0,k.getAllowedIPs)(l);ep(e&&e.length>0?e:[eS])}else ep([eS])}catch(e){console.error("Error fetching allowed IPs:",e),O.Z.fromBackend("Failed to fetch allowed IPs ".concat(e)),ep([eS])}finally{!0===C&&en(!0)}},eI=async e=>{try{if(l){await (0,k.addAllowedIP)(l,e.ip);let s=await (0,k.getAllowedIPs)(l);ep(s),O.Z.success("IP address added successfully")}}catch(e){console.error("Error adding IP:",e),O.Z.fromBackend("Failed to add IP address ".concat(e))}finally{eo(!1)}},eC=async e=>{e_(e),ed(!0)},ek=async()=>{if(eh&&l)try{await (0,k.deleteAllowedIP)(l,eh);let e=await (0,k.getAllowedIPs)(l);ep(e.length>0?e:[eS]),O.Z.success("IP address deleted successfully")}catch(e){console.error("Error deleting IP:",e),O.Z.fromBackend("Failed to delete IP address ".concat(e))}finally{ed(!1),e_(null)}};(0,i.useEffect)(()=>{(async()=>{if(null!=l){let e=[],s=await (0,k.userGetAllUsersCall)(l,"proxy_admin_viewer");console.log("proxy admin viewer response: ",s);let t=s.users;console.log("proxy viewers response: ".concat(t)),t.forEach(s=>{e.push({user_role:s.user_role,user_id:s.user_id,user_email:s.user_email})}),console.log("proxy viewers: ".concat(t));let i=(await (0,k.userGetAllUsersCall)(l,"proxy_admin")).users;i.forEach(s=>{e.push({user_role:s.user_role,user_id:s.user_id,user_email:s.user_email})}),console.log("proxy admins: ".concat(i)),console.log("combinedList: ".concat(e)),G(e),ev(await (0,k.getPossibleUserRoles)(l))}})()},[l]),(0,i.useEffect)(()=>{ew()},[l,C]);let eO=()=>{em(!1)};return console.log("admins: ".concat(null==F?void 0:F.length)),(0,t.jsxs)("div",{className:"w-full m-2 mt-2 p-8",children:[(0,t.jsx)(U,{level:4,children:"Admin Access "}),(0,t.jsx)(R,{children:"Go to 'Internal Users' page to add other admins."}),(0,t.jsxs)(h.Z,{children:[(0,t.jsxs)(_.Z,{children:[(0,t.jsx)(x.Z,{children:"SSO Settings"}),(0,t.jsx)(x.Z,{children:"Security Settings"}),(0,t.jsx)(x.Z,{children:"SCIM"}),(0,t.jsx)(x.Z,{children:"UI Settings"})]}),(0,t.jsxs)(j.Z,{children:[(0,t.jsx)(f.Z,{children:(0,t.jsx)(e0,{})}),(0,t.jsxs)(f.Z,{children:[(0,t.jsxs)(p.Z,{children:[(0,t.jsx)(U,{level:4,children:" ✨ Security Settings"}),(0,t.jsx)(n.Z,{message:"SSO Configuration Deprecated",description:"Editing SSO Settings on this page is deprecated and will be removed in a future version. Please use the SSO Settings tab for SSO configuration.",type:"warning",showIcon:!0}),(0,t.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:"1rem",marginTop:"1rem",marginLeft:"0.5rem"},children:[(0,t.jsx)("div",{children:(0,t.jsx)(m.Z,{style:{width:"150px"},onClick:()=>el(!0),children:ef?"Edit SSO Settings":"Add SSO"})}),(0,t.jsx)("div",{children:(0,t.jsx)(m.Z,{style:{width:"150px"},onClick:eN,children:"Allowed IPs"})}),(0,t.jsx)("div",{children:(0,t.jsx)(m.Z,{style:{width:"150px"},onClick:()=>!0===C?em(!0):O.Z.fromBackend("Only premium users can configure UI access control"),children:"UI Access Control"})})]})]}),(0,t.jsxs)("div",{className:"flex justify-start mb-4",children:[(0,t.jsx)(P,{isAddSSOModalVisible:es,isInstructionsModalVisible:et,handleAddSSOOk:()=>{el(!1),L.resetFields(),l&&C&&ew()},handleAddSSOCancel:()=>{el(!1),L.resetFields()},handleShowInstructions:e=>{el(!1),ei(!0)},handleInstructionsOk:()=>{ei(!1),l&&C&&ew()},handleInstructionsCancel:()=>{ei(!1),l&&C&&ew()},form:L,accessToken:l,ssoConfigured:ef}),(0,t.jsx)(u.Z,{title:"Manage Allowed IP Addresses",width:800,visible:er,onCancel:()=>en(!1),footer:[(0,t.jsx)(m.Z,{className:"mx-1",onClick:()=>eo(!0),children:"Add IP Address"},"add"),(0,t.jsx)(m.Z,{onClick:()=>en(!1),children:"Close"},"close")],children:(0,t.jsxs)(y.Z,{children:[(0,t.jsx)(S.Z,{children:(0,t.jsxs)(w.Z,{children:[(0,t.jsx)(Z.Z,{children:"IP Address"}),(0,t.jsx)(Z.Z,{className:"text-right",children:"Action"})]})}),(0,t.jsx)(v.Z,{children:eg.map((e,s)=>(0,t.jsxs)(w.Z,{children:[(0,t.jsx)(b.Z,{children:e}),(0,t.jsx)(b.Z,{className:"text-right",children:e!==eS&&(0,t.jsx)(m.Z,{onClick:()=>eC(e),color:"red",size:"xs",children:"Delete"})})]},s))})]})}),(0,t.jsx)(u.Z,{title:"Add Allowed IP Address",visible:ea,onCancel:()=>eo(!1),footer:null,children:(0,t.jsxs)(o.Z,{onFinish:eI,children:[(0,t.jsx)(o.Z.Item,{name:"ip",rules:[{required:!0,message:"Please enter an IP address"}],children:(0,t.jsx)(c.default,{placeholder:"Enter IP address"})}),(0,t.jsx)(o.Z.Item,{children:(0,t.jsx)(d.ZP,{htmlType:"submit",children:"Add IP Address"})})]})}),(0,t.jsx)(u.Z,{title:"Confirm Delete",visible:ec,onCancel:()=>ed(!1),onOk:ek,footer:[(0,t.jsx)(m.Z,{className:"mx-1",onClick:()=>ek(),children:"Yes"},"delete"),(0,t.jsx)(m.Z,{onClick:()=>ed(!1),children:"Close"},"close")],children:(0,t.jsxs)("p",{children:["Are you sure you want to delete the IP address: ",eh,"?"]})}),(0,t.jsx)(u.Z,{title:"UI Access Control Settings",visible:eu,width:600,footer:null,onOk:eO,onCancel:()=>{em(!1)},children:(0,t.jsx)(K,{accessToken:l,onSuccess:()=>{eO(),O.Z.success("UI Access Control settings updated successfully")}})})]}),(0,t.jsxs)(g.Z,{title:"Login without SSO",color:"teal",children:["If you need to login without sso, you can access"," ",(0,t.jsxs)("a",{href:eZ,target:"_blank",children:[(0,t.jsx)("b",{children:eZ})," "]})]})]}),(0,t.jsx)(f.Z,{children:(0,t.jsx)(Y,{accessToken:l,userID:N,proxySettings:E})}),(0,t.jsx)(f.Z,{children:(0,t.jsx)(ex,{})})]})]})]})}},1633:function(e,s,l){l.d(s,{j:function(){return R}});var t=l(57437),i=l(39823),r=l(39760),n=l(92403),a=l(28595),o=l(68208),c=l(69993),d=l(58630),u=l(57400),m=l(93750),g=l(29436),p=l(44625),x=l(9775),h=l(48231),_=l(15883),f=l(41361),j=l(37527),y=l(99458),v=l(12660),b=l(88009),S=l(71916),Z=l(41169),w=l(38434),N=l(71891),I=l(55322),C=l(11429),k=l(13817),O=l(18310),E=l(60985),T=l(2265),L=l(20347),P=l(79262),A=l(91027);let{Sider:U}=k.default,R=[{groupLabel:"AI GATEWAY",items:[{key:"api-keys",page:"api-keys",label:"Virtual Keys",icon:(0,t.jsx)(n.Z,{})},{key:"llm-playground",page:"llm-playground",label:"Playground",icon:(0,t.jsx)(a.Z,{}),roles:L.LQ},{key:"models",page:"models",label:"Models + Endpoints",icon:(0,t.jsx)(o.Z,{}),roles:L.LQ},{key:"agents",page:"agents",label:"Agents",icon:(0,t.jsx)(c.Z,{}),roles:L.LQ},{key:"mcp-servers",page:"mcp-servers",label:"MCP Servers",icon:(0,t.jsx)(d.Z,{})},{key:"guardrails",page:"guardrails",label:"Guardrails",icon:(0,t.jsx)(u.Z,{}),roles:L.ZL},{key:"policies",page:"policies",label:(0,t.jsx)("span",{className:"flex items-center gap-4",children:"Policies"}),icon:(0,t.jsx)(m.Z,{}),roles:L.ZL},{key:"tools",page:"tools",label:"Tools",icon:(0,t.jsx)(d.Z,{}),children:[{key:"search-tools",page:"search-tools",label:"Search Tools",icon:(0,t.jsx)(g.Z,{})},{key:"vector-stores",page:"vector-stores",label:"Vector Stores",icon:(0,t.jsx)(p.Z,{})}]}]},{groupLabel:"OBSERVABILITY",items:[{key:"new_usage",page:"new_usage",icon:(0,t.jsx)(x.Z,{}),roles:[...L.ZL,...L.lo],label:"Usage"},{key:"logs",page:"logs",label:(0,t.jsxs)("span",{className:"flex items-center gap-4",children:["Logs ",(0,t.jsx)(A.Z,{})]}),icon:(0,t.jsx)(h.Z,{})}]},{groupLabel:"ACCESS CONTROL",items:[{key:"users",page:"users",label:"Internal Users",icon:(0,t.jsx)(_.Z,{}),roles:L.ZL},{key:"teams",page:"teams",label:"Teams",icon:(0,t.jsx)(f.Z,{})},{key:"organizations",page:"organizations",label:"Organizations",icon:(0,t.jsx)(j.Z,{}),roles:L.ZL},{key:"budgets",page:"budgets",label:"Budgets",icon:(0,t.jsx)(y.Z,{}),roles:L.ZL}]},{groupLabel:"DEVELOPER TOOLS",items:[{key:"api_ref",page:"api_ref",label:"API Reference",icon:(0,t.jsx)(v.Z,{})},{key:"model-hub-table",page:"model-hub-table",label:"AI Hub",icon:(0,t.jsx)(b.Z,{})},{key:"learning-resources",page:"learning-resources",label:"Learning Resources",icon:(0,t.jsx)(S.Z,{}),external_url:"https://models.litellm.ai/cookbook"},{key:"experimental",page:"experimental",label:"Experimental",icon:(0,t.jsx)(Z.Z,{}),children:[{key:"caching",page:"caching",label:"Caching",icon:(0,t.jsx)(p.Z,{}),roles:L.ZL},{key:"prompts",page:"prompts",label:"Prompts",icon:(0,t.jsx)(w.Z,{}),roles:L.ZL},{key:"transform-request",page:"transform-request",label:"API Playground",icon:(0,t.jsx)(v.Z,{}),roles:[...L.ZL,...L.lo]},{key:"tag-management",page:"tag-management",label:"Tag Management",icon:(0,t.jsx)(N.Z,{}),roles:L.ZL},{key:"claude-code-plugins",page:"claude-code-plugins",label:"Claude Code Plugins",icon:(0,t.jsx)(d.Z,{}),roles:L.ZL},{key:"4",page:"usage",label:"Old Usage",icon:(0,t.jsx)(x.Z,{})}]}]},{groupLabel:"SETTINGS",roles:L.ZL,items:[{key:"settings",page:"settings",label:(0,t.jsx)("span",{className:"flex items-center gap-4",children:"Settings"}),icon:(0,t.jsx)(I.Z,{}),roles:L.ZL,children:[{key:"router-settings",page:"router-settings",label:"Router Settings",icon:(0,t.jsx)(I.Z,{}),roles:L.ZL},{key:"logging-and-alerts",page:"logging-and-alerts",label:"Logging & Alerts",icon:(0,t.jsx)(I.Z,{}),roles:L.ZL},{key:"admin-panel",page:"admin-panel",label:"Admin Settings",icon:(0,t.jsx)(I.Z,{}),roles:L.ZL},{key:"cost-tracking",page:"cost-tracking",label:"Cost Tracking",icon:(0,t.jsx)(x.Z,{}),roles:L.ZL},{key:"ui-theme",page:"ui-theme",label:"UI Theme",icon:(0,t.jsx)(C.Z,{}),roles:L.ZL}]}]}];s.Z=e=>{let{setPage:s,defaultSelectedKey:l,collapsed:n=!1,enabledPagesInternalUsers:a}=e,{userId:o,accessToken:c,userRole:d}=(0,r.Z)(),{data:u}=(0,i.q)(),m=(0,T.useMemo)(()=>!!o&&!!u&&u.some(e=>{var s;return null===(s=e.members)||void 0===s?void 0:s.some(e=>e.user_id===o&&"org_admin"===e.user_role)}),[o,u]),g=e=>{let l=new URLSearchParams(window.location.search);l.set("page",e),window.history.pushState(null,"","?".concat(l.toString())),s(e)},p=e=>{let s=(0,L.tY)(d);return null!=a&&console.log("[LeftNav] Filtering with enabled pages:",{userRole:d,isAdmin:s,enabledPagesInternalUsers:a}),e.map(e=>({...e,children:e.children?p(e.children):void 0})).filter(e=>{if("organizations"===e.key){if(!(!e.roles||e.roles.includes(d)||m))return!1;if(!s&&null!=a){let s=a.includes(e.page);return console.log('[LeftNav] Page "'.concat(e.page,'" (').concat(e.key,"): ").concat(s?"VISIBLE":"HIDDEN")),s}return!0}if(e.roles&&!e.roles.includes(d))return!1;if(!s&&null!=a){if(e.children&&e.children.length>0&&e.children.some(e=>a.includes(e.page)))return console.log('[LeftNav] Parent "'.concat(e.page,'" (').concat(e.key,"): VISIBLE (has visible children)")),!0;let s=a.includes(e.page);return console.log('[LeftNav] Page "'.concat(e.page,'" (').concat(e.key,"): ").concat(s?"VISIBLE":"HIDDEN")),s}return!0})},x=(e=>{for(let s of R)for(let l of s.items){if(l.page===e)return l.key;if(l.children){let s=l.children.find(s=>s.page===e);if(s)return s.key}}return"api-keys"})(l);return(0,t.jsx)(k.default,{children:(0,t.jsxs)(U,{theme:"light",width:220,collapsed:n,collapsedWidth:80,collapsible:!0,trigger:null,style:{transition:"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",position:"relative"},children:[(0,t.jsx)(O.ZP,{theme:{components:{Menu:{iconSize:15,fontSize:13,itemMarginInline:4,itemPaddingInline:8,itemHeight:30,itemBorderRadius:6,subMenuItemBorderRadius:6,groupTitleFontSize:10,groupTitleLineHeight:1.5}}},children:(0,t.jsx)(E.Z,{mode:"inline",selectedKeys:[x],defaultOpenKeys:[],inlineCollapsed:n,className:"custom-sidebar-menu",style:{borderRight:0,backgroundColor:"transparent",fontSize:"13px",paddingTop:"4px"},items:(()=>{let e=[];return R.forEach(s=>{if(s.roles&&!s.roles.includes(d))return;let l=p(s.items);0!==l.length&&e.push({type:"group",label:n?null:(0,t.jsx)("span",{style:{fontSize:"10px",fontWeight:600,color:"#6b7280",letterSpacing:"0.05em",padding:"12px 0 4px 12px",display:"block",marginBottom:"2px"},children:s.groupLabel}),children:l.map(e=>{var s;return{key:e.key,icon:e.icon,label:e.label,children:null===(s=e.children)||void 0===s?void 0:s.map(e=>({key:e.key,icon:e.icon,label:e.label,onClick:()=>{e.external_url?window.open(e.external_url,"_blank"):g(e.page)}})),onClick:e.children?void 0:()=>{e.external_url?window.open(e.external_url,"_blank"):g(e.page)}}})})}),e})()})}),(0,L.tY)(d)&&!n&&(0,t.jsx)(P.Z,{accessToken:c,width:220})]})})}},79262:function(e,s,l){l.d(s,{Z:function(){return g}});var t=l(57437);l(1309);var i=l(76865),r=l(70525),n=l(95805),a=l(51817),o=l(21047);l(22135),l(40875);var c=l(49663),d=l(2265),u=l(19250);let m=function(){for(var e=arguments.length,s=Array(e),l=0;l{(async()=>{if(s){y(!0),b(null);try{let e=await (0,u.getRemainingUsers)(s);f(e)}catch(e){console.error("Failed to fetch usage data:",e),b("Failed to load usage data")}finally{y(!1)}}})()},[s]);let{isOverLimit:S,isNearLimit:Z,usagePercentage:w,userMetrics:N,teamMetrics:I}=(e=>{if(!e)return{isOverLimit:!1,isNearLimit:!1,usagePercentage:0,userMetrics:{isOverLimit:!1,isNearLimit:!1,usagePercentage:0},teamMetrics:{isOverLimit:!1,isNearLimit:!1,usagePercentage:0}};let s=e.total_users?e.total_users_used/e.total_users*100:0,l=s>100,t=s>=80&&s<=100,i=e.total_teams?e.total_teams_used/e.total_teams*100:0,r=i>100,n=i>=80&&i<=100,a=l||r;return{isOverLimit:a,isNearLimit:(t||n)&&!a,usagePercentage:Math.max(s,i),userMetrics:{isOverLimit:l,isNearLimit:t,usagePercentage:s},teamMetrics:{isOverLimit:r,isNearLimit:n,usagePercentage:i}}})(_),C=()=>S?(0,t.jsx)(i.Z,{className:"h-3 w-3"}):Z?(0,t.jsx)(r.Z,{className:"h-3 w-3"}):null;return s&&((null==_?void 0:_.total_users)!==null||(null==_?void 0:_.total_teams)!==null)?(0,t.jsx)("div",{className:"fixed bottom-4 left-4 z-50",style:{width:"".concat(Math.min(l,220),"px")},children:(0,t.jsx)(()=>x?(0,t.jsx)("button",{onClick:()=>h(!1),className:m("bg-white border border-gray-200 rounded-lg shadow-sm p-3 hover:shadow-md transition-all w-full"),title:"Show usage details",children:(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(n.Z,{className:"h-4 w-4 flex-shrink-0"}),(S||Z)&&(0,t.jsx)("span",{className:"flex-shrink-0",children:C()}),(0,t.jsxs)("div",{className:"flex items-center gap-2 text-sm font-medium truncate",children:[_&&null!==_.total_users&&(0,t.jsxs)("span",{className:m("flex-shrink-0 px-1.5 py-0.5 rounded text-xs border",N.isOverLimit&&"bg-red-50 text-red-700 border-red-200",N.isNearLimit&&"bg-yellow-50 text-yellow-700 border-yellow-200",!N.isOverLimit&&!N.isNearLimit&&"bg-gray-50 text-gray-700 border-gray-200"),children:["U: ",_.total_users_used,"/",_.total_users]}),_&&null!==_.total_teams&&(0,t.jsxs)("span",{className:m("flex-shrink-0 px-1.5 py-0.5 rounded text-xs border",I.isOverLimit&&"bg-red-50 text-red-700 border-red-200",I.isNearLimit&&"bg-yellow-50 text-yellow-700 border-yellow-200",!I.isOverLimit&&!I.isNearLimit&&"bg-gray-50 text-gray-700 border-gray-200"),children:["T: ",_.total_teams_used,"/",_.total_teams]}),!_||null===_.total_users&&null===_.total_teams&&(0,t.jsx)("span",{className:"truncate",children:"Usage"})]})]})}):j?(0,t.jsx)("div",{className:"bg-white border border-gray-200 rounded-lg shadow-sm p-4 w-full",children:(0,t.jsxs)("div",{className:"flex items-center justify-center gap-2 py-2",children:[(0,t.jsx)(a.Z,{className:"h-4 w-4 animate-spin"}),(0,t.jsx)("span",{className:"text-sm text-gray-500 truncate",children:"Loading..."})]})}):v||!_?(0,t.jsx)("div",{className:"bg-white border border-gray-200 rounded-lg shadow-sm p-4 group w-full",children:(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,t.jsx)("div",{className:"flex-1 min-w-0",children:(0,t.jsx)("span",{className:"text-sm text-gray-500 truncate block",children:v||"No data"})}),(0,t.jsx)("button",{onClick:()=>h(!0),className:"opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-100 rounded transition-all flex-shrink-0",title:"Minimize",children:(0,t.jsx)(o.Z,{className:"h-3 w-3 text-gray-400"})})]})}):(0,t.jsxs)("div",{className:m("bg-white border rounded-lg shadow-sm p-3 transition-all duration-200 group w-full"),children:[(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2 mb-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 min-w-0 flex-1",children:[(0,t.jsx)(n.Z,{className:"h-4 w-4 flex-shrink-0"}),(0,t.jsx)("span",{className:"font-medium text-sm truncate",children:"Usage"})]}),(0,t.jsx)("button",{onClick:()=>h(!0),className:"opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-100 rounded transition-all flex-shrink-0",title:"Minimize",children:(0,t.jsx)(o.Z,{className:"h-3 w-3 text-gray-400"})})]}),(0,t.jsxs)("div",{className:"space-y-3 text-sm",children:[null!==_.total_users&&(0,t.jsxs)("div",{className:m("space-y-1 border rounded-md p-2",N.isOverLimit&&"border-red-200 bg-red-50",N.isNearLimit&&"border-yellow-200 bg-yellow-50"),children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 text-xs text-gray-600 mb-1",children:[(0,t.jsx)(n.Z,{className:"h-3 w-3"}),(0,t.jsx)("span",{className:"font-medium",children:"Users"}),(0,t.jsx)("span",{className:m("ml-1 px-1.5 py-0.5 rounded border",N.isOverLimit&&"bg-red-50 text-red-700 border-red-200",N.isNearLimit&&"bg-yellow-50 text-yellow-700 border-yellow-200",!N.isOverLimit&&!N.isNearLimit&&"bg-gray-50 text-gray-600 border-gray-200"),children:N.isOverLimit?"Over limit":N.isNearLimit?"Near limit":"OK"})]}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{className:"text-gray-600 text-xs",children:"Used:"}),(0,t.jsxs)("span",{className:"font-medium text-right",children:[_.total_users_used,"/",_.total_users]})]}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{className:"text-gray-600 text-xs",children:"Remaining:"}),(0,t.jsx)("span",{className:m("font-medium text-right",N.isOverLimit&&"text-red-600",N.isNearLimit&&"text-yellow-600"),children:_.total_users_remaining})]}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{className:"text-gray-600 text-xs",children:"Usage:"}),(0,t.jsxs)("span",{className:"font-medium text-right",children:[Math.round(N.usagePercentage),"%"]})]}),(0,t.jsx)("div",{className:"w-full bg-gray-200 rounded-full h-2",children:(0,t.jsx)("div",{className:m("h-2 rounded-full transition-all duration-300",N.isOverLimit&&"bg-red-500",N.isNearLimit&&"bg-yellow-500",!N.isOverLimit&&!N.isNearLimit&&"bg-green-500"),style:{width:"".concat(Math.min(N.usagePercentage,100),"%")}})})]}),null!==_.total_teams&&(0,t.jsxs)("div",{className:m("space-y-1 border rounded-md p-2",I.isOverLimit&&"border-red-200 bg-red-50",I.isNearLimit&&"border-yellow-200 bg-yellow-50"),children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 text-xs text-gray-600 mb-1",children:[(0,t.jsx)(c.Z,{className:"h-3 w-3"}),(0,t.jsx)("span",{className:"font-medium",children:"Teams"}),(0,t.jsx)("span",{className:m("ml-1 px-1.5 py-0.5 rounded border",I.isOverLimit&&"bg-red-50 text-red-700 border-red-200",I.isNearLimit&&"bg-yellow-50 text-yellow-700 border-yellow-200",!I.isOverLimit&&!I.isNearLimit&&"bg-gray-50 text-gray-600 border-gray-200"),children:I.isOverLimit?"Over limit":I.isNearLimit?"Near limit":"OK"})]}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{className:"text-gray-600 text-xs",children:"Used:"}),(0,t.jsxs)("span",{className:"font-medium text-right",children:[_.total_teams_used,"/",_.total_teams]})]}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{className:"text-gray-600 text-xs",children:"Remaining:"}),(0,t.jsx)("span",{className:m("font-medium text-right",I.isOverLimit&&"text-red-600",I.isNearLimit&&"text-yellow-600"),children:_.total_teams_remaining})]}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{className:"text-gray-600 text-xs",children:"Usage:"}),(0,t.jsxs)("span",{className:"font-medium text-right",children:[Math.round(I.usagePercentage),"%"]})]}),(0,t.jsx)("div",{className:"w-full bg-gray-200 rounded-full h-2",children:(0,t.jsx)("div",{className:m("h-2 rounded-full transition-all duration-300",I.isOverLimit&&"bg-red-500",I.isNearLimit&&"bg-yellow-500",!I.isOverLimit&&!I.isNearLimit&&"bg-green-500"),style:{width:"".concat(Math.min(I.usagePercentage,100),"%")}})})]})]})]}),{})}):null}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/1901-9d6d72bdecc0e0c8.js b/litellm/proxy/_experimental/out/_next/static/chunks/1901-9d6d72bdecc0e0c8.js deleted file mode 100644 index 9f3b7ca550d..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/1901-9d6d72bdecc0e0c8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1901],{91027:function(e,s,a){a.d(s,{Z:function(){return o}});var t=a(57437),l=a(33866),r=a(2265),n=a(9245);function i(e){let s=s=>{"disableShowNewBadge"===s.key&&e()},a=s=>{let{key:a}=s.detail;"disableShowNewBadge"===a&&e()};return window.addEventListener("storage",s),window.addEventListener(n.Qg,a),()=>{window.removeEventListener("storage",s),window.removeEventListener(n.Qg,a)}}function d(){return"true"===(0,n.le)("disableShowNewBadge")}function o(e){let{children:s}=e;return(0,r.useSyncExternalStore)(i,d)?s?(0,t.jsx)(t.Fragment,{children:s}):null:s?(0,t.jsx)(l.Z,{color:"blue",count:"New",children:s}):(0,t.jsx)(l.Z,{color:"blue",count:"New"})}},12363:function(e,s,a){a.d(s,{d:function(){return r},n:function(){return l}});var t=a(2265);let l=()=>{let[e,s]=(0,t.useState)("http://localhost:4000");return(0,t.useEffect)(()=>{{let{protocol:e,host:a}=window.location;s("".concat(e,"//").concat(a))}},[]),e},r=25},30841:function(e,s,a){a.d(s,{IE:function(){return r},LO:function(){return l},cT:function(){return n}});var t=a(19250);let l=async e=>{if(!e)return[];try{let{aliases:s}=await (0,t.keyAliasesCall)(e);return Array.from(new Set((s||[]).filter(Boolean)))}catch(e){return console.error("Error fetching all key aliases:",e),[]}},r=async(e,s)=>{if(!e)return[];try{let a=[],l=1,r=!0;for(;r;){let n=await (0,t.teamListCall)(e,s||null,null);a=[...a,...n],l{if(!e)return[];try{let s=[],a=1,l=!0;for(;l;){let r=await (0,t.organizationListCall)(e);s=[...s,...r],a{let{options:s,onApplyFilters:a,onResetFilters:o,initialValues:m={},buttonLabel:x="Filters"}=e,[u,h]=(0,l.useState)(!1),[g,p]=(0,l.useState)(m),[j,f]=(0,l.useState)({}),[v,y]=(0,l.useState)({}),[b,N]=(0,l.useState)({}),[w,_]=(0,l.useState)({}),k=(0,l.useCallback)(c()(async(e,s)=>{if(s.isSearchable&&s.searchFn){y(e=>({...e,[s.name]:!0}));try{let a=await s.searchFn(e);f(e=>({...e,[s.name]:a}))}catch(e){console.error("Error searching:",e),f(e=>({...e,[s.name]:[]}))}finally{y(e=>({...e,[s.name]:!1}))}}},300),[]),S=(0,l.useCallback)(async e=>{if(e.isSearchable&&e.searchFn&&!w[e.name]){y(s=>({...s,[e.name]:!0})),_(s=>({...s,[e.name]:!0}));try{let s=await e.searchFn("");f(a=>({...a,[e.name]:s}))}catch(s){console.error("Error loading initial options:",s),f(s=>({...s,[e.name]:[]}))}finally{y(s=>({...s,[e.name]:!1}))}}},[w]);(0,l.useEffect)(()=>{u&&s.forEach(e=>{e.isSearchable&&!w[e.name]&&S(e)})},[u,s,S,w]);let C=(e,s)=>{let t={...g,[e]:s};p(t),a(t)},L=(e,s)=>{e&&s.isSearchable&&!w[s.name]&&S(s)};return(0,t.jsxs)("div",{className:"w-full",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 mb-6",children:[(0,t.jsx)(r.ZP,{icon:(0,t.jsx)(d.Z,{className:"h-4 w-4"}),onClick:()=>h(!u),className:"flex items-center gap-2",children:x}),(0,t.jsx)(r.ZP,{onClick:()=>{let e={};s.forEach(s=>{e[s.name]=""}),p(e),o()},children:"Reset Filters"})]}),u&&(0,t.jsx)("div",{className:"grid grid-cols-3 gap-x-6 gap-y-4 mb-6",children:["Team ID","Status","Organization ID","Key Alias","User ID","End User","Error Code","Key Hash","Model"].map(e=>{let a=s.find(s=>s.label===e||s.name===e);return a?(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsx)("label",{className:"text-sm text-gray-600",children:a.label||a.name}),a.isSearchable?(0,t.jsx)(n.default,{showSearch:!0,className:"w-full",placeholder:"Search ".concat(a.label||a.name,"..."),value:g[a.name]||void 0,onChange:e=>C(a.name,e),onDropdownVisibleChange:e=>L(e,a),onSearch:e=>{N(s=>({...s,[a.name]:e})),a.searchFn&&k(e,a)},filterOption:!1,loading:v[a.name],options:j[a.name]||[],allowClear:!0,notFoundContent:v[a.name]?"Loading...":"No results found"}):a.options?(0,t.jsx)(n.default,{className:"w-full",placeholder:"Select ".concat(a.label||a.name,"..."),value:g[a.name]||void 0,onChange:e=>C(a.name,e),allowClear:!0,children:a.options.map(e=>(0,t.jsx)(n.default.Option,{value:e.value,children:e.label},e.value))}):(0,t.jsx)(i.default,{className:"w-full",placeholder:"Enter ".concat(a.label||a.name,"..."),value:g[a.name]||"",onChange:e=>C(a.name,e.target.value),allowClear:!0})]},a.name):null})})]})}},31901:function(e,s,a){a.d(s,{I:function(){return eU},Z:function(){return eV}});var t=a(57437),l=a(77398),r=a.n(l),n=a(11713),i=a(2265),d=a(29827),o=a(19250),c=a(60493),m=a(59872),x=a(41649),u=a(78489),h=a(99981),g=a(42673);let p=e=>{try{return new Date(e).toLocaleString("en-US",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!0}).replace(",","")}catch(e){return"Error converting time"}},j=e=>{let{utcTime:s}=e;return(0,t.jsx)("span",{style:{fontFamily:"monospace",width:"180px",display:"inline-block"},children:p(s)})},f=(e,s)=>{var a,t;return(null===(t=e.metadata)||void 0===t?void 0:null===(a=t.mcp_tool_call_metadata)||void 0===a?void 0:a.mcp_server_logo_url)?e.metadata.mcp_tool_call_metadata.mcp_server_logo_url:s?(0,g.dr)(s).logo:""},v=[{id:"expander",header:()=>null,cell:e=>{let{row:s}=e;return(0,t.jsx)(()=>{let[e,a]=i.useState(s.getIsExpanded()),l=i.useCallback(()=>{a(e=>!e),s.getToggleExpandedHandler()()},[s]);return s.getCanExpand()?(0,t.jsx)("button",{onClick:l,style:{cursor:"pointer"},"aria-label":e?"Collapse row":"Expand row",className:"w-6 h-6 flex items-center justify-center focus:outline-none",children:(0,t.jsx)("svg",{className:"w-4 h-4 transform transition-transform duration-75 ".concat(e?"rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})})}):(0,t.jsx)("span",{className:"w-6 h-6 flex items-center justify-center",children:"ā—"})},{})}},{header:"Time",accessorKey:"startTime",cell:e=>(0,t.jsx)(j,{utcTime:e.getValue()})},{header:"Status",accessorKey:"metadata.status",cell:e=>{let s="failure"!==(e.getValue()||"Success").toLowerCase();return(0,t.jsx)("span",{className:"px-2 py-1 rounded-md text-xs font-medium inline-block text-center w-16 ".concat(s?"bg-green-100 text-green-800":"bg-red-100 text-red-800"),children:s?"Success":"Failure"})}},{header:"Session ID",accessorKey:"session_id",cell:e=>{let s=String(e.getValue()||""),a=e.row.original.onSessionClick;return(0,t.jsx)(h.Z,{title:String(e.getValue()||""),children:(0,t.jsx)(u.Z,{size:"xs",variant:"light",className:"font-mono text-blue-500 bg-blue-50 hover:bg-blue-100 text-xs font-normal text-xs max-w-[15ch] truncate block",onClick:()=>null==a?void 0:a(s),children:String(e.getValue()||"")})})}},{header:"Request ID",accessorKey:"request_id",cell:e=>(0,t.jsx)(h.Z,{title:String(e.getValue()||""),children:(0,t.jsx)("span",{className:"font-mono text-xs max-w-[15ch] truncate block",children:String(e.getValue()||"")})})},{header:"Cost",accessorKey:"spend",cell:e=>(0,t.jsx)(h.Z,{title:"$".concat(String(e.getValue()||0)," "),children:(0,t.jsx)("span",{children:(0,m.GS)(e.getValue()||0)})})},{header:"Duration (s)",accessorKey:"duration",cell:e=>(0,t.jsx)(h.Z,{title:String(e.getValue()||"-"),children:(0,t.jsx)("span",{className:"max-w-[15ch] truncate block",children:String(e.getValue()||"-")})})},{header:"Team Name",accessorKey:"metadata.user_api_key_team_alias",cell:e=>(0,t.jsx)(h.Z,{title:String(e.getValue()||"-"),children:(0,t.jsx)("span",{className:"max-w-[15ch] truncate block",children:String(e.getValue()||"-")})})},{header:"Key Hash",accessorKey:"metadata.user_api_key",cell:e=>{let s=String(e.getValue()||"-"),a=e.row.original.onKeyHashClick;return(0,t.jsx)(h.Z,{title:s,children:(0,t.jsx)("span",{className:"font-mono max-w-[15ch] truncate block cursor-pointer hover:text-blue-600",onClick:()=>null==a?void 0:a(s),children:s})})}},{header:"Key Name",accessorKey:"metadata.user_api_key_alias",cell:e=>(0,t.jsx)(h.Z,{title:String(e.getValue()||"-"),children:(0,t.jsx)("span",{className:"max-w-[15ch] truncate block",children:String(e.getValue()||"-")})})},{header:"Model",accessorKey:"model",cell:e=>{let s=e.row.original,a=s.custom_llm_provider,l=String(e.getValue()||"");return(0,t.jsxs)("div",{className:"flex items-center space-x-2",children:[a&&(0,t.jsx)("img",{src:f(s,a),alt:"",className:"w-4 h-4",onError:e=>{e.target.style.display="none"}}),(0,t.jsx)(h.Z,{title:l,children:(0,t.jsx)("span",{className:"max-w-[15ch] truncate block",children:l})})]})}},{header:"Tokens",accessorKey:"total_tokens",cell:e=>{let s=e.row.original;return(0,t.jsxs)("span",{className:"text-sm",children:[String(s.total_tokens||"0"),(0,t.jsxs)("span",{className:"text-gray-400 text-xs ml-1",children:["(",String(s.prompt_tokens||"0"),"+",String(s.completion_tokens||"0"),")"]})]})}},{header:"Internal User",accessorKey:"user",cell:e=>(0,t.jsx)(h.Z,{title:String(e.getValue()||"-"),children:(0,t.jsx)("span",{className:"max-w-[15ch] truncate block",children:String(e.getValue()||"-")})})},{header:"End User",accessorKey:"end_user",cell:e=>(0,t.jsx)(h.Z,{title:String(e.getValue()||"-"),children:(0,t.jsx)("span",{className:"max-w-[15ch] truncate block",children:String(e.getValue()||"-")})})},{header:"Tags",accessorKey:"request_tags",cell:e=>{let s=e.getValue();if(!s||0===Object.keys(s).length)return"-";let a=Object.entries(s),l=a[0],r=a.slice(1);return(0,t.jsx)("div",{className:"flex flex-wrap gap-1",children:(0,t.jsx)(h.Z,{title:(0,t.jsx)("div",{className:"flex flex-col gap-1",children:a.map(e=>{let[s,a]=e;return(0,t.jsxs)("span",{children:[s,": ",String(a)]},s)})}),children:(0,t.jsxs)("span",{className:"px-2 py-1 bg-gray-100 rounded-full text-xs",children:[l[0],": ",String(l[1]),r.length>0&&" +".concat(r.length)]})})})}}],y=e=>(0,t.jsx)(x.Z,{color:"gray",className:"flex items-center gap-1",children:(0,t.jsx)("span",{className:"whitespace-nowrap text-xs",children:e})}),b=[{id:"expander",header:()=>null,cell:e=>{let{row:s}=e;return(0,t.jsx)(()=>{let[e,a]=i.useState(s.getIsExpanded()),l=i.useCallback(()=>{a(e=>!e),s.getToggleExpandedHandler()()},[s]);return s.getCanExpand()?(0,t.jsx)("button",{onClick:l,style:{cursor:"pointer"},"aria-label":e?"Collapse row":"Expand row",className:"w-6 h-6 flex items-center justify-center focus:outline-none",children:(0,t.jsx)("svg",{className:"w-4 h-4 transform transition-transform ".concat(e?"rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})})}):(0,t.jsx)("span",{className:"w-6 h-6 flex items-center justify-center",children:"ā—"})},{})}},{header:"Timestamp",accessorKey:"updated_at",cell:e=>(0,t.jsx)(j,{utcTime:e.getValue()})},{header:"Table Name",accessorKey:"table_name",cell:e=>{let s=e.getValue(),a=s;switch(s){case"LiteLLM_VerificationToken":a="Keys";break;case"LiteLLM_TeamTable":a="Teams";break;case"LiteLLM_OrganizationTable":a="Organizations";break;case"LiteLLM_UserTable":a="Users";break;case"LiteLLM_ProxyModelTable":a="Models";break;default:a=s}return(0,t.jsx)("span",{children:a})}},{header:"Action",accessorKey:"action",cell:e=>(0,t.jsx)("span",{children:y(e.getValue())})},{header:"Changed By",accessorKey:"changed_by",cell:e=>{let s=e.row.original.changed_by,a=e.row.original.changed_by_api_key;return(0,t.jsxs)("div",{className:"space-y-1",children:[(0,t.jsx)("div",{className:"font-medium",children:s}),a&&(0,t.jsx)(h.Z,{title:a,children:(0,t.jsxs)("div",{className:"text-xs text-muted-foreground max-w-[15ch] truncate",children:[" ",a]})})]})}},{header:"Affected Item ID",accessorKey:"object_id",cell:e=>(0,t.jsx)(()=>{let s=e.getValue(),[a,l]=(0,i.useState)(!1);if(!s)return(0,t.jsx)(t.Fragment,{children:"-"});let r=async()=>{try{await navigator.clipboard.writeText(String(s)),l(!0),setTimeout(()=>l(!1),1500)}catch(e){console.error("Failed to copy object ID: ",e)}};return(0,t.jsx)(h.Z,{title:a?"Copied!":String(s),children:(0,t.jsx)("span",{className:"max-w-[20ch] truncate block cursor-pointer hover:text-blue-600",onClick:r,children:String(s)})})},{})}],N=async(e,s,a,t)=>{console.log("prefetchLogDetails called with",e.length,"logs");let l=e.map(e=>{if(e.request_id)return console.log("Prefetching details for request_id:",e.request_id),t.prefetchQuery({queryKey:["logDetails",e.request_id,s],queryFn:async()=>{console.log("Fetching details for",e.request_id);let t=await (0,o.uiSpendLogDetailsCall)(a,e.request_id,s);return console.log("Received details for",e.request_id,":",t?"success":"failed"),t},staleTime:6e5,gcTime:6e5})});try{let e=await Promise.all(l);return console.log("All prefetch promises completed:",e.length),e}catch(e){throw console.error("Error in prefetchLogDetails:",e),e}};var w=a(9114),_=a(86669);function k(e){let{row:s,hasMessages:a,hasResponse:l,hasError:r,errorInfo:n,getRawRequest:i,formattedResponse:d}=e,o=async e=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0;{let s=document.createElement("textarea");s.value=e,s.style.position="fixed",s.style.opacity="0",document.body.appendChild(s),s.focus(),s.select();let a=document.execCommand("copy");if(document.body.removeChild(s),!a)throw Error("execCommand failed");return!0}}catch(e){return console.error("Copy failed:",e),!1}},c=async()=>{await o(JSON.stringify(i(),null,2))?w.Z.success("Request copied to clipboard"):w.Z.fromBackend("Failed to copy request")},m=async()=>{await o(JSON.stringify(d(),null,2))?w.Z.success("Response copied to clipboard"):w.Z.fromBackend("Failed to copy response")};return(0,t.jsxs)("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4 w-full max-w-full overflow-hidden box-border",children:[(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow w-full max-w-full overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center p-4 border-b",children:[(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Request"}),(0,t.jsx)("button",{onClick:c,className:"p-1 hover:bg-gray-200 rounded",title:"Copy request",children:(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),(0,t.jsx)("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})]}),(0,t.jsx)("div",{className:"p-4 overflow-auto max-h-96 w-full max-w-full box-border",children:(0,t.jsx)("div",{className:"[&_[role='tree']]:bg-white [&_[role='tree']]:text-slate-900",children:(0,t.jsx)(_.gc,{data:i(),style:_.jF,clickToExpandNode:!0})})})]}),(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow w-full max-w-full overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center p-4 border-b",children:[(0,t.jsxs)("h3",{className:"text-lg font-medium",children:["Response",r&&(0,t.jsxs)("span",{className:"ml-2 text-sm text-red-600",children:["• HTTP code ",(null==n?void 0:n.error_code)||400]})]}),(0,t.jsx)("button",{onClick:m,className:"p-1 hover:bg-gray-200 rounded",title:"Copy response",disabled:!l,children:(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),(0,t.jsx)("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})]}),(0,t.jsx)("div",{className:"p-4 overflow-auto max-h-96 w-full max-w-full box-border",children:l?(0,t.jsx)("div",{className:"[&_[role='tree']]:bg-white [&_[role='tree']]:text-slate-900",children:(0,t.jsx)(_.gc,{data:d(),style:_.jF,clickToExpandNode:!0})}):(0,t.jsx)("div",{className:"text-gray-500 text-sm italic text-center py-4",children:"Response data not available"})})]})]})}a(52621);let S=e=>{var s;let{errorInfo:a}=e,[l,r]=i.useState({}),[n,d]=i.useState(!1),o=e=>{r(s=>({...s,[e]:!s[e]}))},c=a.traceback&&(s=a.traceback)?Array.from(s.matchAll(/File "([^"]+)", line (\d+)/g)).map(e=>{let a=e[1],t=e[2],l=a.split("/").pop()||a,r=e.index||0,n=s.indexOf('File "',r+1),i=n>-1?s.substring(r,n).trim():s.substring(r).trim(),d=i.split("\n"),o="";return d.length>1&&(o=d[d.length-1].trim()),{filePath:a,fileName:l,lineNumber:t,code:o,inFunction:i.includes(" in ")?i.split(" in ")[1].split("\n")[0]:""}}):[];return(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow",children:[(0,t.jsx)("div",{className:"p-4 border-b",children:(0,t.jsxs)("h3",{className:"text-lg font-medium flex items-center text-red-600",children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}),"Error Details"]})}),(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)("div",{className:"bg-red-50 rounded-md p-4 mb-4",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"text-red-800 font-medium w-20",children:"Type:"}),(0,t.jsx)("span",{className:"text-red-700",children:a.error_class||"Unknown Error"})]}),(0,t.jsxs)("div",{className:"flex mt-2",children:[(0,t.jsx)("span",{className:"text-red-800 font-medium w-20 flex-shrink-0",children:"Message:"}),(0,t.jsx)("span",{className:"text-red-700 break-words whitespace-pre-wrap",children:a.error_message||"Unknown error occurred"})]})]}),a.traceback&&(0,t.jsxs)("div",{className:"mt-4",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-2",children:[(0,t.jsx)("h4",{className:"font-medium",children:"Traceback"}),(0,t.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,t.jsx)("button",{onClick:()=>{let e=!n;if(d(e),c.length>0){let s={};c.forEach((a,t)=>{s[t]=e}),r(s)}},className:"text-gray-500 hover:text-gray-700 flex items-center text-sm",children:n?"Collapse All":"Expand All"}),(0,t.jsxs)("button",{onClick:()=>navigator.clipboard.writeText(a.traceback||""),className:"text-gray-500 hover:text-gray-700 flex items-center",title:"Copy traceback",children:[(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),(0,t.jsx)("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]}),(0,t.jsx)("span",{className:"ml-1",children:"Copy"})]})]})]}),(0,t.jsx)("div",{className:"bg-white rounded-md border border-gray-200 overflow-hidden shadow-sm",children:c.map((e,s)=>(0,t.jsxs)("div",{className:"border-b border-gray-200 last:border-b-0",children:[(0,t.jsxs)("div",{className:"px-4 py-2 flex items-center justify-between cursor-pointer hover:bg-gray-50",onClick:()=>o(s),children:[(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("span",{className:"text-gray-400 mr-2 w-12 text-right",children:e.lineNumber}),(0,t.jsx)("span",{className:"text-gray-600 font-medium",children:e.fileName}),(0,t.jsx)("span",{className:"text-gray-500 mx-1",children:"in"}),(0,t.jsx)("span",{className:"text-indigo-600 font-medium",children:e.inFunction||e.fileName})]}),(0,t.jsx)("svg",{className:"w-5 h-5 text-gray-500 transition-transform ".concat(l[s]?"transform rotate-180":""),fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]}),(l[s]||!1)&&e.code&&(0,t.jsx)("div",{className:"px-12 py-2 font-mono text-sm text-gray-800 bg-gray-50 overflow-x-auto border-t border-gray-100",children:e.code})]},s))})]})]})]})};var C=a(20347);let L=e=>{let{show:s}=e;return s?(0,t.jsxs)("div",{className:"bg-blue-50 border border-blue-200 rounded-lg p-4 flex items-start",children:[(0,t.jsx)("div",{className:"text-blue-500 mr-3 flex-shrink-0 mt-0.5",children:(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("circle",{cx:"12",cy:"12",r:"10"}),(0,t.jsx)("line",{x1:"12",y1:"16",x2:"12",y2:"12"}),(0,t.jsx)("line",{x1:"12",y1:"8",x2:"12.01",y2:"8"})]})}),(0,t.jsxs)("div",{children:[(0,t.jsx)("h4",{className:"text-sm font-medium text-blue-800",children:"Request/Response Data Not Available"}),(0,t.jsxs)("p",{className:"text-sm text-blue-700 mt-1",children:["To view request and response details, enable prompt storage in your LiteLLM configuration by adding the following to your ",(0,t.jsx)("code",{className:"bg-blue-100 px-1 py-0.5 rounded",children:"proxy_config.yaml"})," file:"]}),(0,t.jsx)("pre",{className:"mt-2 bg-white p-3 rounded border border-blue-200 text-xs font-mono overflow-auto",children:"general_settings:\n store_model_in_db: true\n store_prompts_in_spend_logs: true"}),(0,t.jsx)("p",{className:"text-xs text-blue-700 mt-2",children:"Note: This will only affect new requests after the configuration change."})]})]}):null};var D=a(50665),M=a(12514),E=a(35829),T=a(84264),A=a(96761),R=a(10900),z=a(5545),O=a(30401),Z=a(78867);let I=e=>{let{sessionId:s,logs:a,onBack:l}=e,[r,n]=(0,i.useState)(null),[d,o]=(0,i.useState)({}),x=a.reduce((e,s)=>e+(s.spend||0),0),g=a.reduce((e,s)=>e+(s.total_tokens||0),0),p=a.reduce((e,s)=>{var a,t;return e+((null===(t=s.metadata)||void 0===t?void 0:null===(a=t.additional_usage_values)||void 0===a?void 0:a.cache_read_input_tokens)||0)},0),j=a.reduce((e,s)=>{var a,t;return e+((null===(t=s.metadata)||void 0===t?void 0:null===(a=t.additional_usage_values)||void 0===a?void 0:a.cache_creation_input_tokens)||0)},0),f=g+p+j,y=a.length>0?new Date(a[0].startTime):new Date;(((a.length>0?new Date(a[a.length-1].endTime):new Date).getTime()-y.getTime())/1e3).toFixed(2),a.map(e=>({time:new Date(e.startTime).toISOString(),tokens:e.total_tokens||0,cost:e.spend||0}));let b=async(e,s)=>{await (0,m.vQ)(e)&&(o(e=>({...e,[s]:!0})),setTimeout(()=>{o(e=>({...e,[s]:!1}))},2e3))};return(0,t.jsxs)("div",{className:"space-y-6",children:[(0,t.jsxs)("div",{className:"mb-8",children:[(0,t.jsx)(u.Z,{icon:R.Z,variant:"light",onClick:l,className:"mb-4",children:"Back to All Logs"}),(0,t.jsxs)("div",{className:"mt-4",children:[(0,t.jsx)("h1",{className:"text-2xl font-semibold text-gray-900",children:"Session Details"}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center cursor-pointer",children:[(0,t.jsx)("p",{className:"text-sm text-gray-500 font-mono",children:s}),(0,t.jsx)(z.ZP,{type:"text",size:"small",icon:d["session-id"]?(0,t.jsx)(O.Z,{size:12}):(0,t.jsx)(Z.Z,{size:12}),onClick:()=>b(s,"session-id"),className:"left-2 z-10 transition-all duration-200 ".concat(d["session-id"]?"text-green-600 bg-green-50 border-green-200":"text-gray-500 hover:text-gray-700 hover:bg-gray-100")})]}),(0,t.jsxs)("a",{href:"https://docs.litellm.ai/docs/proxy/ui_logs_sessions",target:"_blank",rel:"noopener noreferrer",className:"text-sm text-blue-600 hover:text-blue-800 flex items-center gap-1",children:["Get started with session management here",(0,t.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"})})]})]})]})]}),(0,t.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-4 gap-4",children:[(0,t.jsxs)(M.Z,{children:[(0,t.jsx)(T.Z,{children:"Total Requests"}),(0,t.jsx)(E.Z,{children:a.length})]}),(0,t.jsxs)(M.Z,{children:[(0,t.jsx)(T.Z,{children:"Total Cost"}),(0,t.jsxs)(E.Z,{children:["$",(0,m.pw)(x,6)]})]}),(0,t.jsx)(h.Z,{title:(0,t.jsxs)("div",{className:"text-white min-w-[200px]",children:[(0,t.jsx)("div",{className:"text-lg font-medium mb-3",children:"Usage breakdown"}),(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"text-base font-medium mb-2",children:"Input usage:"}),(0,t.jsxs)("div",{className:"space-y-2 text-sm text-gray-300",children:[(0,t.jsxs)("div",{className:"flex justify-between",children:[(0,t.jsx)("span",{children:"input:"}),(0,t.jsx)("span",{className:"ml-8",children:(0,m.pw)(a.reduce((e,s)=>e+(s.prompt_tokens||0),0))})]}),p>0&&(0,t.jsxs)("div",{className:"flex justify-between",children:[(0,t.jsx)("span",{children:"input_cached_tokens:"}),(0,t.jsx)("span",{className:"ml-8",children:(0,m.pw)(p)})]}),j>0&&(0,t.jsxs)("div",{className:"flex justify-between",children:[(0,t.jsx)("span",{children:"input_cache_creation_tokens:"}),(0,t.jsx)("span",{className:"ml-8",children:(0,m.pw)(j)})]})]})]}),(0,t.jsxs)("div",{className:"border-t border-gray-600 pt-3",children:[(0,t.jsx)("div",{className:"text-base font-medium mb-2",children:"Output usage:"}),(0,t.jsx)("div",{className:"space-y-2 text-sm text-gray-300",children:(0,t.jsxs)("div",{className:"flex justify-between",children:[(0,t.jsx)("span",{children:"output:"}),(0,t.jsx)("span",{className:"ml-8",children:(0,m.pw)(a.reduce((e,s)=>e+(s.completion_tokens||0),0))})]})})]}),(0,t.jsx)("div",{className:"border-t border-gray-600 pt-3",children:(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{className:"text-base font-medium",children:"Total usage:"}),(0,t.jsx)("span",{className:"text-sm text-gray-300",children:(0,m.pw)(f)})]})})]})]}),placement:"top",overlayStyle:{minWidth:"300px"},children:(0,t.jsxs)(M.Z,{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsx)(T.Z,{children:"Total Tokens"}),(0,t.jsx)("span",{className:"text-gray-400 text-sm",children:"ā“˜"})]}),(0,t.jsx)(E.Z,{children:(0,m.pw)(f)})]})})]}),(0,t.jsx)(A.Z,{children:"Session Logs"}),(0,t.jsx)("div",{className:"mt-4",children:(0,t.jsx)(c.w,{columns:v,data:a,renderSubComponent:eU,getRowCanExpand:()=>!0,loadingMessage:"Loading logs...",noDataMessage:"No logs found"})})]})};function K(e){let{data:s}=e,[a,l]=(0,i.useState)(!0),[r,n]=(0,i.useState)({});if(!s||0===s.length)return null;let d=e=>new Date(1e3*e).toLocaleString(),o=(e,s)=>"".concat(((s-e)*1e3).toFixed(2),"ms"),c=(e,s)=>{let a="".concat(e,"-").concat(s);n(e=>({...e,[a]:!e[a]}))};return(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow mb-6",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center p-4 border-b cursor-pointer hover:bg-gray-50",onClick:()=>l(!a),children:[(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2 text-gray-600 transition-transform ".concat(a?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Vector Store Requests"})]}),(0,t.jsx)("span",{className:"text-sm text-gray-500",children:a?"Click to collapse":"Click to expand"})]}),a&&(0,t.jsx)("div",{className:"p-4",children:s.map((e,s)=>(0,t.jsxs)("div",{className:"mb-6 last:mb-0",children:[(0,t.jsx)("div",{className:"bg-white rounded-lg border p-4 mb-4",children:(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Query:"}),(0,t.jsx)("span",{className:"font-mono",children:e.query})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Vector Store ID:"}),(0,t.jsx)("span",{className:"font-mono",children:e.vector_store_id})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Provider:"}),(0,t.jsx)("span",{className:"flex items-center",children:(()=>{let{logo:s,displayName:a}=(0,g.dr)(e.custom_llm_provider);return(0,t.jsxs)(t.Fragment,{children:[s&&(0,t.jsx)("img",{src:s,alt:"".concat(a," logo"),className:"h-5 w-5 mr-2"}),a]})})()})]})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Start Time:"}),(0,t.jsx)("span",{children:d(e.start_time)})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"End Time:"}),(0,t.jsx)("span",{children:d(e.end_time)})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Duration:"}),(0,t.jsx)("span",{children:o(e.start_time,e.end_time)})]})]})]})}),(0,t.jsx)("h4",{className:"font-medium mb-2",children:"Search Results"}),(0,t.jsx)("div",{className:"space-y-2",children:e.vector_store_search_response.data.map((e,a)=>{let l=r["".concat(s,"-").concat(a)]||!1;return(0,t.jsxs)("div",{className:"border rounded-lg overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex items-center p-3 bg-gray-50 cursor-pointer",onClick:()=>c(s,a),children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2 transition-transform ".concat(l?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsxs)("span",{className:"font-medium mr-2",children:["Result ",a+1]}),(0,t.jsxs)("span",{className:"text-gray-500 text-sm",children:["Score: ",(0,t.jsx)("span",{className:"font-mono",children:e.score.toFixed(4)})]})]})]}),l&&(0,t.jsx)("div",{className:"p-3 border-t bg-white",children:e.content.map((e,s)=>(0,t.jsxs)("div",{className:"mb-2 last:mb-0",children:[(0,t.jsx)("div",{className:"text-xs text-gray-500 mb-1",children:e.type}),(0,t.jsx)("pre",{className:"text-xs font-mono whitespace-pre-wrap break-all bg-gray-50 p-2 rounded",children:e.text})]},s))})]},a)})})]},s))})]})}let H=e=>e>=.8?"text-green-600":"text-yellow-600";var P=e=>{let{entities:s}=e,[a,l]=(0,i.useState)(!0),[r,n]=(0,i.useState)({}),d=e=>{n(s=>({...s,[e]:!s[e]}))};return s&&0!==s.length?(0,t.jsxs)("div",{className:"mt-4",children:[(0,t.jsxs)("div",{className:"flex items-center mb-2 cursor-pointer",onClick:()=>l(!a),children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2 transition-transform ".concat(a?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsxs)("h4",{className:"font-medium",children:["Detected Entities (",s.length,")"]})]}),a&&(0,t.jsx)("div",{className:"space-y-2",children:s.map((e,s)=>{let a=r[s]||!1;return(0,t.jsxs)("div",{className:"border rounded-lg overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between p-3 bg-gray-50 cursor-pointer hover:bg-gray-100",onClick:()=>d(s),children:[(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2 transition-transform ".concat(a?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsx)("span",{className:"font-medium mr-2",children:e.entity_type}),(0,t.jsxs)("span",{className:"font-mono ".concat(H(e.score)),children:["Score: ",e.score.toFixed(2)]})]}),(0,t.jsxs)("span",{className:"text-xs text-gray-500",children:["Position: ",e.start,"-",e.end]})]}),a&&(0,t.jsx)("div",{className:"p-3 border-t bg-white",children:(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4 mb-2",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Entity Type:"}),(0,t.jsx)("span",{children:e.entity_type})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Position:"}),(0,t.jsxs)("span",{children:["Characters ",e.start,"-",e.end]})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Confidence:"}),(0,t.jsx)("span",{className:H(e.score),children:e.score.toFixed(2)})]})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[e.recognition_metadata&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Recognizer:"}),(0,t.jsx)("span",{children:e.recognition_metadata.recognizer_name})]}),(0,t.jsxs)("div",{className:"flex overflow-hidden",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Identifier:"}),(0,t.jsx)("span",{className:"truncate text-xs font-mono",children:e.recognition_metadata.recognizer_identifier})]})]}),e.analysis_explanation&&(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Explanation:"}),(0,t.jsx)("span",{children:e.analysis_explanation})]})]})]})})]},s)})})]}):null};let F=function(e){let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"slate";return(0,t.jsx)("span",{className:"px-2 py-1 rounded-md text-xs font-medium inline-block ".concat({green:"bg-green-100 text-green-800",red:"bg-red-100 text-red-800",blue:"bg-blue-50 text-blue-700",slate:"bg-slate-100 text-slate-800",amber:"bg-amber-100 text-amber-800"}[s]),children:e})},q=e=>e?F("detected","red"):F("not detected","slate"),Y=e=>{let{title:s,count:a,defaultOpen:l=!0,right:r,children:n}=e,[d,o]=(0,i.useState)(l);return(0,t.jsxs)("div",{className:"border rounded-lg overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between p-3 bg-gray-50 cursor-pointer hover:bg-gray-100",onClick:()=>o(e=>!e),children:[(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2 transition-transform ".concat(d?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsxs)("h5",{className:"font-medium",children:[s," ","number"==typeof a&&(0,t.jsxs)("span",{className:"text-gray-500 font-normal",children:["(",a,")"]})]})]}),(0,t.jsx)("div",{children:r})]}),d&&(0,t.jsx)("div",{className:"p-3 border-t bg-white",children:n})]})},B=e=>{let{label:s,children:a,mono:l}=e;return(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:s}),(0,t.jsx)("span",{className:l?"font-mono text-sm break-all":"",children:a})]})},V=()=>(0,t.jsx)("div",{className:"my-3 border-t"});var U=e=>{var s,a,l,r,n,i,d,o,c,m;let{response:x}=e;if(!x)return null;let u=null!==(n=null!==(r=x.outputs)&&void 0!==r?r:x.output)&&void 0!==n?n:[],h="GUARDRAIL_INTERVENED"===x.action?"red":"green",g=(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(null===(s=x.guardrailCoverage)||void 0===s?void 0:s.textCharacters)&&F("text guarded ".concat(null!==(i=x.guardrailCoverage.textCharacters.guarded)&&void 0!==i?i:0,"/").concat(null!==(d=x.guardrailCoverage.textCharacters.total)&&void 0!==d?d:0),"blue"),(null===(a=x.guardrailCoverage)||void 0===a?void 0:a.images)&&F("images guarded ".concat(null!==(o=x.guardrailCoverage.images.guarded)&&void 0!==o?o:0,"/").concat(null!==(c=x.guardrailCoverage.images.total)&&void 0!==c?c:0),"blue")]}),p=x.usage&&(0,t.jsx)("div",{className:"flex flex-wrap gap-2",children:Object.entries(x.usage).map(e=>{let[s,a]=e;return"number"==typeof a?(0,t.jsxs)("span",{className:"px-2 py-1 bg-slate-100 text-slate-800 rounded-md text-xs font-medium",children:[s,": ",a]},s):null})});return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"border rounded-lg p-4",children:[(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(B,{label:"Action:",children:F(null!==(m=x.action)&&void 0!==m?m:"N/A",h)}),x.actionReason&&(0,t.jsx)(B,{label:"Action Reason:",children:x.actionReason}),x.blockedResponse&&(0,t.jsx)(B,{label:"Blocked Response:",children:(0,t.jsx)("span",{className:"italic",children:x.blockedResponse})})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(B,{label:"Coverage:",children:g}),(0,t.jsx)(B,{label:"Usage:",children:p})]})]}),u.length>0&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(V,{}),(0,t.jsx)("h4",{className:"font-medium mb-2",children:"Outputs"}),(0,t.jsx)("div",{className:"space-y-2",children:u.map((e,s)=>{var a;return(0,t.jsx)("div",{className:"p-3 bg-gray-50 rounded-md",children:(0,t.jsx)("div",{className:"text-sm whitespace-pre-wrap",children:null!==(a=e.text)&&void 0!==a?a:(0,t.jsx)("em",{children:"(non-text output)"})})},s)})})]})]}),(null===(l=x.assessments)||void 0===l?void 0:l.length)?(0,t.jsx)("div",{className:"space-y-3",children:x.assessments.map((e,s)=>{var a,l,r,n,i,d,o,c,m,x,u,h,g,p,j,f,v,y,b,N,w,_,k,S;let C=(0,t.jsxs)("div",{className:"flex flex-wrap gap-1",children:[e.wordPolicy&&F("word","slate"),e.contentPolicy&&F("content","slate"),e.topicPolicy&&F("topic","slate"),e.sensitiveInformationPolicy&&F("sensitive-info","slate"),e.contextualGroundingPolicy&&F("contextual-grounding","slate"),e.automatedReasoningPolicy&&F("automated-reasoning","slate")]});return(0,t.jsxs)(Y,{title:"Assessment #".concat(s+1),defaultOpen:!0,right:(0,t.jsxs)("div",{className:"flex items-center gap-3",children:[(null===(a=e.invocationMetrics)||void 0===a?void 0:a.guardrailProcessingLatency)!=null&&F("".concat(e.invocationMetrics.guardrailProcessingLatency," ms"),"amber"),C]}),children:[e.wordPolicy&&(0,t.jsxs)("div",{className:"mb-3",children:[(0,t.jsx)("h6",{className:"font-medium mb-2",children:"Word Policy"}),(null!==(f=null===(l=e.wordPolicy.customWords)||void 0===l?void 0:l.length)&&void 0!==f?f:0)>0&&(0,t.jsx)(Y,{title:"Custom Words",defaultOpen:!0,children:(0,t.jsx)("div",{className:"space-y-2",children:e.wordPolicy.customWords.map((e,s)=>{var a;return(0,t.jsxs)("div",{className:"flex justify-between items-center p-2 bg-gray-50 rounded",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[F(null!==(a=e.action)&&void 0!==a?a:"N/A",e.detected?"red":"slate"),(0,t.jsx)("span",{className:"font-mono text-sm break-all",children:e.match})]}),q(e.detected)]},s)})})}),(null!==(v=null===(r=e.wordPolicy.managedWordLists)||void 0===r?void 0:r.length)&&void 0!==v?v:0)>0&&(0,t.jsx)(Y,{title:"Managed Word Lists",defaultOpen:!1,children:(0,t.jsx)("div",{className:"space-y-2",children:e.wordPolicy.managedWordLists.map((e,s)=>{var a;return(0,t.jsxs)("div",{className:"flex justify-between items-center p-2 bg-gray-50 rounded",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[F(null!==(a=e.action)&&void 0!==a?a:"N/A",e.detected?"red":"slate"),(0,t.jsx)("span",{className:"font-mono text-sm break-all",children:e.match}),e.type&&F(e.type,"slate")]}),q(e.detected)]},s)})})})]}),(null===(i=e.contentPolicy)||void 0===i?void 0:null===(n=i.filters)||void 0===n?void 0:n.length)?(0,t.jsxs)("div",{className:"mb-3",children:[(0,t.jsx)("h6",{className:"font-medium mb-2",children:"Content Policy"}),(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsxs)("table",{className:"min-w-full text-sm",children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{className:"text-left text-gray-600",children:[(0,t.jsx)("th",{className:"py-1 pr-4",children:"Type"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Action"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Detected"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Strength"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Confidence"})]})}),(0,t.jsx)("tbody",{children:e.contentPolicy.filters.map((e,s)=>{var a,l,r,n;return(0,t.jsxs)("tr",{className:"border-t",children:[(0,t.jsx)("td",{className:"py-1 pr-4",children:null!==(a=e.type)&&void 0!==a?a:"—"}),(0,t.jsx)("td",{className:"py-1 pr-4",children:F(null!==(l=e.action)&&void 0!==l?l:"—",e.detected?"red":"slate")}),(0,t.jsx)("td",{className:"py-1 pr-4",children:q(e.detected)}),(0,t.jsx)("td",{className:"py-1 pr-4",children:null!==(r=e.filterStrength)&&void 0!==r?r:"—"}),(0,t.jsx)("td",{className:"py-1 pr-4",children:null!==(n=e.confidence)&&void 0!==n?n:"—"})]},s)})})]})})]}):null,(null===(o=e.contextualGroundingPolicy)||void 0===o?void 0:null===(d=o.filters)||void 0===d?void 0:d.length)?(0,t.jsxs)("div",{className:"mb-3",children:[(0,t.jsx)("h6",{className:"font-medium mb-2",children:"Contextual Grounding"}),(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsxs)("table",{className:"min-w-full text-sm",children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{className:"text-left text-gray-600",children:[(0,t.jsx)("th",{className:"py-1 pr-4",children:"Type"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Action"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Detected"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Score"}),(0,t.jsx)("th",{className:"py-1 pr-4",children:"Threshold"})]})}),(0,t.jsx)("tbody",{children:e.contextualGroundingPolicy.filters.map((e,s)=>{var a,l,r,n;return(0,t.jsxs)("tr",{className:"border-t",children:[(0,t.jsx)("td",{className:"py-1 pr-4",children:null!==(a=e.type)&&void 0!==a?a:"—"}),(0,t.jsx)("td",{className:"py-1 pr-4",children:F(null!==(l=e.action)&&void 0!==l?l:"—",e.detected?"red":"slate")}),(0,t.jsx)("td",{className:"py-1 pr-4",children:q(e.detected)}),(0,t.jsx)("td",{className:"py-1 pr-4",children:null!==(r=e.score)&&void 0!==r?r:"—"}),(0,t.jsx)("td",{className:"py-1 pr-4",children:null!==(n=e.threshold)&&void 0!==n?n:"—"})]},s)})})]})})]}):null,e.sensitiveInformationPolicy&&(0,t.jsxs)("div",{className:"mb-3",children:[(0,t.jsx)("h6",{className:"font-medium mb-2",children:"Sensitive Information"}),(null!==(y=null===(c=e.sensitiveInformationPolicy.piiEntities)||void 0===c?void 0:c.length)&&void 0!==y?y:0)>0&&(0,t.jsx)(Y,{title:"PII Entities",defaultOpen:!0,children:(0,t.jsx)("div",{className:"space-y-2",children:e.sensitiveInformationPolicy.piiEntities.map((e,s)=>{var a;return(0,t.jsxs)("div",{className:"flex justify-between items-center p-2 bg-gray-50 rounded",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[F(null!==(a=e.action)&&void 0!==a?a:"N/A",e.detected?"red":"slate"),e.type&&F(e.type,"slate"),(0,t.jsx)("span",{className:"font-mono text-xs break-all",children:e.match})]}),q(e.detected)]},s)})})}),(null!==(b=null===(m=e.sensitiveInformationPolicy.regexes)||void 0===m?void 0:m.length)&&void 0!==b?b:0)>0&&(0,t.jsx)(Y,{title:"Custom Regexes",defaultOpen:!1,children:(0,t.jsx)("div",{className:"space-y-2",children:e.sensitiveInformationPolicy.regexes.map((e,s)=>{var a,l;return(0,t.jsxs)("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between p-2 bg-gray-50 rounded gap-1",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[F(null!==(a=e.action)&&void 0!==a?a:"N/A",e.detected?"red":"slate"),(0,t.jsx)("span",{className:"font-medium",children:null!==(l=e.name)&&void 0!==l?l:"regex"}),(0,t.jsx)("span",{className:"font-mono text-xs break-all",children:e.regex})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[q(e.detected),e.match&&(0,t.jsx)("span",{className:"font-mono text-xs break-all",children:e.match})]})]},s)})})})]}),(null===(u=e.topicPolicy)||void 0===u?void 0:null===(x=u.topics)||void 0===x?void 0:x.length)?(0,t.jsxs)("div",{className:"mb-3",children:[(0,t.jsx)("h6",{className:"font-medium mb-2",children:"Topic Policy"}),(0,t.jsx)("div",{className:"flex flex-wrap gap-2",children:e.topicPolicy.topics.map((e,s)=>{var a,l;return(0,t.jsx)("div",{className:"px-3 py-1.5 bg-gray-50 rounded-md text-xs",children:(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[F(null!==(a=e.action)&&void 0!==a?a:"N/A",e.detected?"red":"slate"),(0,t.jsx)("span",{className:"font-medium",children:null!==(l=e.name)&&void 0!==l?l:"topic"}),e.type&&F(e.type,"slate"),q(e.detected)]})},s)})})]}):null,e.invocationMetrics&&(0,t.jsx)(Y,{title:"Invocation Metrics",defaultOpen:!1,children:(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(B,{label:"Latency (ms)",children:null!==(N=e.invocationMetrics.guardrailProcessingLatency)&&void 0!==N?N:"—"}),(0,t.jsx)(B,{label:"Coverage:",children:(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(null===(h=e.invocationMetrics.guardrailCoverage)||void 0===h?void 0:h.textCharacters)&&F("text ".concat(null!==(w=e.invocationMetrics.guardrailCoverage.textCharacters.guarded)&&void 0!==w?w:0,"/").concat(null!==(_=e.invocationMetrics.guardrailCoverage.textCharacters.total)&&void 0!==_?_:0),"blue"),(null===(g=e.invocationMetrics.guardrailCoverage)||void 0===g?void 0:g.images)&&F("images ".concat(null!==(k=e.invocationMetrics.guardrailCoverage.images.guarded)&&void 0!==k?k:0,"/").concat(null!==(S=e.invocationMetrics.guardrailCoverage.images.total)&&void 0!==S?S:0),"blue")]})})]}),(0,t.jsx)("div",{className:"space-y-2",children:(0,t.jsx)(B,{label:"Usage:",children:(0,t.jsx)("div",{className:"flex flex-wrap gap-2",children:e.invocationMetrics.usage&&Object.entries(e.invocationMetrics.usage).map(e=>{let[s,a]=e;return"number"==typeof a?(0,t.jsxs)("span",{className:"px-2 py-1 bg-slate-100 text-slate-800 rounded-md text-xs font-medium",children:[s,": ",a]},s):null})})})})]})}),(null===(j=e.automatedReasoningPolicy)||void 0===j?void 0:null===(p=j.findings)||void 0===p?void 0:p.length)?(0,t.jsx)(Y,{title:"Automated Reasoning Findings",defaultOpen:!1,children:(0,t.jsx)("div",{className:"space-y-2",children:e.automatedReasoningPolicy.findings.map((e,s)=>(0,t.jsx)("pre",{className:"bg-gray-50 rounded p-2 text-xs overflow-x-auto",children:JSON.stringify(e,null,2)},s))})}):null]},s)})}):null,(0,t.jsx)(Y,{title:"Raw Bedrock Guardrail Response",defaultOpen:!1,children:(0,t.jsx)("pre",{className:"bg-gray-50 rounded p-3 text-xs overflow-x-auto",children:JSON.stringify(x,null,2)})})]})};let W=function(e){let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"slate";return(0,t.jsx)("span",{className:"px-2 py-1 rounded-md text-xs font-medium inline-block ".concat({green:"bg-green-100 text-green-800",red:"bg-red-100 text-red-800",blue:"bg-blue-50 text-blue-700",slate:"bg-slate-100 text-slate-800",amber:"bg-amber-100 text-amber-800"}[s]),children:e})},J=e=>{let{title:s,count:a,defaultOpen:l=!0,children:r}=e,[n,d]=(0,i.useState)(l);return(0,t.jsxs)("div",{className:"border rounded-lg overflow-hidden",children:[(0,t.jsx)("div",{className:"flex items-center justify-between p-3 bg-gray-50 cursor-pointer hover:bg-gray-100",onClick:()=>d(e=>!e),children:(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2 transition-transform ".concat(n?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsxs)("h5",{className:"font-medium",children:[s," ","number"==typeof a&&(0,t.jsxs)("span",{className:"text-gray-500 font-normal",children:["(",a,")"]})]})]})}),n&&(0,t.jsx)("div",{className:"p-3 border-t bg-white",children:r})]})},G=e=>{let{label:s,children:a,mono:l}=e;return(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:s}),(0,t.jsx)("span",{className:l?"font-mono text-sm break-all":"",children:a})]})};var Q=e=>{let{response:s}=e;if(!s||"string"==typeof s)return"string"==typeof s&&s?(0,t.jsx)("div",{className:"bg-white rounded-lg border border-red-200 p-4",children:(0,t.jsxs)("div",{className:"text-red-800",children:[(0,t.jsx)("h5",{className:"font-medium mb-2",children:"Error"}),(0,t.jsx)("p",{className:"text-sm",children:s})]})}):null;let a=Array.isArray(s)?s:[];if(0===a.length)return(0,t.jsx)("div",{className:"bg-white rounded-lg border border-gray-200 p-4",children:(0,t.jsx)("div",{className:"text-gray-600 text-sm",children:"No detections found"})});let l=a.filter(e=>"pattern"===e.type),r=a.filter(e=>"blocked_word"===e.type),n=a.filter(e=>"category_keyword"===e.type),i=a.filter(e=>"BLOCK"===e.action).length,d=a.filter(e=>"MASK"===e.action).length,o=a.length;return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)("div",{className:"bg-white rounded-lg border border-gray-200 p-4",children:(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(G,{label:"Total Detections:",children:(0,t.jsx)("span",{className:"font-semibold",children:o})}),(0,t.jsx)(G,{label:"Actions:",children:(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[i>0&&W("".concat(i," blocked"),"red"),d>0&&W("".concat(d," masked"),"blue"),0===i&&0===d&&W("passed","green")]})})]}),(0,t.jsx)("div",{className:"space-y-2",children:(0,t.jsx)(G,{label:"By Type:",children:(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[l.length>0&&W("".concat(l.length," patterns"),"slate"),r.length>0&&W("".concat(r.length," keywords"),"slate"),n.length>0&&W("".concat(n.length," categories"),"slate")]})})})]})}),l.length>0&&(0,t.jsx)(J,{title:"Patterns Matched",count:l.length,defaultOpen:!0,children:(0,t.jsx)("div",{className:"space-y-2",children:l.map((e,s)=>(0,t.jsx)("div",{className:"p-3 bg-gray-50 rounded-md",children:(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsx)("div",{className:"space-y-1",children:(0,t.jsx)(G,{label:"Pattern:",children:e.pattern_name||"unknown"})}),(0,t.jsx)("div",{className:"space-y-1",children:(0,t.jsx)(G,{label:"Action:",children:W(e.action,"BLOCK"===e.action?"red":"blue")})})]})},s))})}),r.length>0&&(0,t.jsx)(J,{title:"Blocked Words Detected",count:r.length,defaultOpen:!0,children:(0,t.jsx)("div",{className:"space-y-2",children:r.map((e,s)=>(0,t.jsx)("div",{className:"p-3 bg-gray-50 rounded-md",children:(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{className:"space-y-1",children:[(0,t.jsx)(G,{label:"Keyword:",mono:!0,children:e.keyword||"unknown"}),e.description&&(0,t.jsx)(G,{label:"Description:",children:e.description})]}),(0,t.jsx)("div",{className:"space-y-1",children:(0,t.jsx)(G,{label:"Action:",children:W(e.action,"BLOCK"===e.action?"red":"blue")})})]})},s))})}),n.length>0&&(0,t.jsx)(J,{title:"Category Keywords Detected",count:n.length,defaultOpen:!0,children:(0,t.jsx)("div",{className:"space-y-2",children:n.map((e,s)=>(0,t.jsx)("div",{className:"p-3 bg-gray-50 rounded-md",children:(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{className:"space-y-1",children:[(0,t.jsx)(G,{label:"Category:",children:e.category||"unknown"}),(0,t.jsx)(G,{label:"Keyword:",mono:!0,children:e.keyword||"unknown"}),e.severity&&(0,t.jsx)(G,{label:"Severity:",children:W(e.severity,"high"===e.severity?"red":"medium"===e.severity?"amber":"slate")})]}),(0,t.jsx)("div",{className:"space-y-1",children:(0,t.jsx)(G,{label:"Action:",children:W(e.action,"BLOCK"===e.action?"red":"blue")})})]})},s))})}),(0,t.jsx)(J,{title:"Raw Detection Data",defaultOpen:!1,children:(0,t.jsx)("pre",{className:"bg-gray-50 rounded p-3 text-xs overflow-x-auto",children:JSON.stringify(a,null,2)})})]})};let $=e=>new Date(1e3*e).toLocaleString(),X=new Set(["presidio","bedrock","litellm_content_filter"]),ee=e=>{let{response:s}=e,[a,l]=(0,i.useState)(!1);return(0,t.jsx)("div",{className:"mt-4",children:(0,t.jsxs)("div",{className:"border rounded-lg overflow-hidden",children:[(0,t.jsx)("div",{className:"flex items-center justify-between p-3 bg-gray-50 cursor-pointer hover:bg-gray-100",onClick:()=>l(!a),children:(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("svg",{className:"w-5 h-5 mr-2 transition-transform ".concat(a?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsx)("h5",{className:"font-medium",children:"Raw Guardrail Response"})]})}),a&&(0,t.jsx)("div",{className:"p-3 border-t bg-white",children:(0,t.jsx)("pre",{className:"bg-gray-50 rounded p-3 text-xs overflow-x-auto",children:JSON.stringify(s,null,2)})})]})})},es=e=>{var s,a;let{entry:l,index:r,total:n}=e,i=null!==(s=l.guardrail_provider)&&void 0!==s?s:"presidio",d=null!==(a=l.guardrail_status)&&void 0!==a?a:"unknown",o="success"===d.toLowerCase(),c=l.masked_entity_count||{},m=Object.values(c).reduce((e,s)=>e+("number"==typeof s?s:0),0),x=l.guardrail_response,u=Array.isArray(x)?x:[],g="bedrock"!==i||null===x||"object"!=typeof x||Array.isArray(x)?void 0:x;return(0,t.jsxs)("div",{className:"bg-white rounded-lg border border-gray-200 p-4",children:[n>1&&(0,t.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,t.jsxs)("h4",{className:"text-base font-semibold",children:["Guardrail #",r+1,(0,t.jsx)("span",{className:"ml-2 font-mono text-sm text-gray-600",children:l.guardrail_name})]}),(0,t.jsx)("span",{className:"px-2 py-0.5 bg-gray-100 text-gray-600 rounded-md text-xs capitalize",children:i})]}),(0,t.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Guardrail Name:"}),(0,t.jsx)("span",{className:"font-mono break-words",children:l.guardrail_name})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Mode:"}),(0,t.jsx)("span",{className:"font-mono break-words",children:l.guardrail_mode})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Status:"}),(0,t.jsx)(h.Z,{title:o?null:"Guardrail failed to run.",placement:"top",arrow:!0,destroyTooltipOnHide:!0,children:(0,t.jsx)("span",{className:"px-2 py-1 rounded-md text-xs font-medium inline-block ".concat(o?"bg-green-100 text-green-800":"bg-red-100 text-red-800 cursor-help"),children:d})})]})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Start Time:"}),(0,t.jsx)("span",{children:$(l.start_time)})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"End Time:"}),(0,t.jsx)("span",{children:$(l.end_time)})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Duration:"}),(0,t.jsxs)("span",{children:[l.duration.toFixed(4),"s"]})]})]})]}),m>0&&(0,t.jsxs)("div",{className:"mt-4 pt-4 border-t",children:[(0,t.jsx)("h5",{className:"font-medium mb-2",children:"Masked Entity Summary"}),(0,t.jsx)("div",{className:"flex flex-wrap gap-2",children:Object.entries(c).map(e=>{let[s,a]=e;return(0,t.jsxs)("span",{className:"px-3 py-1.5 bg-blue-50 text-blue-700 rounded-md text-xs font-medium",children:[s,": ",a]},s)})})]}),"presidio"===i&&u.length>0&&(0,t.jsx)("div",{className:"mt-4",children:(0,t.jsx)(P,{entities:u})}),"bedrock"===i&&g&&(0,t.jsx)("div",{className:"mt-4",children:(0,t.jsx)(U,{response:g})}),"litellm_content_filter"===i&&x&&(0,t.jsx)("div",{className:"mt-4",children:(0,t.jsx)(Q,{response:x})}),i&&!X.has(i)&&x&&(0,t.jsx)(ee,{response:x})]})};var ea=e=>{let{data:s}=e,a=Array.isArray(s)?s.filter(e=>!!e):s?[s]:[],[l,r]=(0,i.useState)(!0),n=1===a.length?a[0].guardrail_name:"".concat(a.length," guardrails"),d=Array.from(new Set(a.map(e=>e.guardrail_status))).every(e=>"success"===(null!=e?e:"").toLowerCase()),o=a.reduce((e,s)=>e+Object.values(s.masked_entity_count||{}).reduce((e,s)=>e+("number"==typeof s?s:0),0),0);return 0===a.length?null:(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow mb-6",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center p-4 border-b cursor-pointer hover:bg-gray-50",onClick:()=>r(!l),children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("svg",{className:"w-5 h-5 text-gray-600 transition-transform ".concat(l?"transform rotate-90":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 5l7 7-7 7"})}),(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Guardrail Information"}),(0,t.jsx)(h.Z,{title:d?null:"Guardrail failed to run.",placement:"top",arrow:!0,destroyTooltipOnHide:!0,children:(0,t.jsx)("span",{className:"ml-2 px-2 py-1 rounded-md text-xs font-medium inline-block ".concat(d?"bg-green-100 text-green-800":"bg-red-100 text-red-800 cursor-help"),children:d?"success":"failure"})}),(0,t.jsx)("span",{className:"ml-2 font-mono text-sm text-gray-600",children:n}),o>0&&(0,t.jsxs)("span",{className:"ml-2 px-2 py-1 bg-blue-50 text-blue-700 rounded-md text-xs font-medium",children:[o," masked ",1===o?"entity":"entities"]})]}),(0,t.jsx)("span",{className:"text-sm text-gray-500",children:l?"Click to collapse":"Click to expand"})]}),l&&(0,t.jsx)("div",{className:"p-4 space-y-6",children:a.map((e,s)=>{var l;return(0,t.jsx)(es,{entry:e,index:s,total:a.length},"".concat(null!==(l=e.guardrail_name)&&void 0!==l?l:"guardrail","-").concat(s))})})]})},et=a(87452),el=a(88829),er=a(72208);let en=e=>null==e?"-":"$".concat((0,m.pw)(e,8)),ei=e=>null==e?"-":"".concat((100*e).toFixed(2),"%"),ed=e=>{var s;let{costBreakdown:a,totalSpend:l}=e;if(!a)return null;let r=void 0!==a.discount_percent&&0!==a.discount_percent||void 0!==a.discount_amount&&0!==a.discount_amount,n=void 0!==a.margin_percent&&0!==a.margin_percent||void 0!==a.margin_fixed_amount&&0!==a.margin_fixed_amount||void 0!==a.margin_total_amount&&0!==a.margin_total_amount;return void 0!==a.input_cost||void 0!==a.output_cost||r||n?(0,t.jsx)("div",{className:"bg-white rounded-lg shadow w-full max-w-full overflow-hidden",children:(0,t.jsxs)(et.Z,{children:[(0,t.jsx)(er.Z,{className:"p-4 border-b hover:bg-gray-50 transition-colors text-left",children:(0,t.jsxs)("div",{className:"flex items-center justify-between w-full",children:[(0,t.jsx)("h3",{className:"text-lg font-medium text-gray-900",children:"Cost Breakdown"}),(0,t.jsxs)("div",{className:"flex items-center space-x-2 mr-4",children:[(0,t.jsx)("span",{className:"text-sm text-gray-500",children:"Total:"}),(0,t.jsx)("span",{className:"text-sm font-semibold text-gray-900",children:en(l)})]})]})}),(0,t.jsx)(el.Z,{className:"px-0",children:(0,t.jsxs)("div",{className:"p-6 space-y-4",children:[(0,t.jsxs)("div",{className:"space-y-2 max-w-2xl",children:[(0,t.jsxs)("div",{className:"flex text-sm",children:[(0,t.jsx)("span",{className:"text-gray-600 font-medium w-1/3",children:"Input Cost:"}),(0,t.jsx)("span",{className:"text-gray-900",children:en(a.input_cost)})]}),(0,t.jsxs)("div",{className:"flex text-sm",children:[(0,t.jsx)("span",{className:"text-gray-600 font-medium w-1/3",children:"Output Cost:"}),(0,t.jsx)("span",{className:"text-gray-900",children:en(a.output_cost)})]}),void 0!==a.tool_usage_cost&&a.tool_usage_cost>0&&(0,t.jsxs)("div",{className:"flex text-sm",children:[(0,t.jsx)("span",{className:"text-gray-600 font-medium w-1/3",children:"Tool Usage Cost:"}),(0,t.jsx)("span",{className:"text-gray-900",children:en(a.tool_usage_cost)})]})]}),(0,t.jsx)("div",{className:"pt-2 border-t border-gray-100 max-w-2xl",children:(0,t.jsxs)("div",{className:"flex text-sm font-semibold",children:[(0,t.jsx)("span",{className:"text-gray-900 w-1/3",children:"Original LLM Cost:"}),(0,t.jsx)("span",{className:"text-gray-900",children:en(a.original_cost)})]})}),(r||n)&&(0,t.jsxs)("div",{className:"pt-2 space-y-2 max-w-2xl",children:[r&&(0,t.jsxs)("div",{className:"space-y-2",children:[void 0!==a.discount_percent&&0!==a.discount_percent&&(0,t.jsxs)("div",{className:"flex text-sm text-gray-600",children:[(0,t.jsxs)("span",{className:"font-medium w-1/3",children:["Discount (",ei(a.discount_percent),"):"]}),(0,t.jsxs)("span",{className:"text-gray-900",children:["-",en(a.discount_amount)]})]}),void 0!==a.discount_amount&&void 0===a.discount_percent&&(0,t.jsxs)("div",{className:"flex text-sm text-gray-600",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Discount Amount:"}),(0,t.jsxs)("span",{className:"text-gray-900",children:["-",en(a.discount_amount)]})]})]}),n&&(0,t.jsxs)("div",{className:"space-y-2",children:[void 0!==a.margin_percent&&0!==a.margin_percent&&(0,t.jsxs)("div",{className:"flex text-sm text-gray-600",children:[(0,t.jsxs)("span",{className:"font-medium w-1/3",children:["Margin (",ei(a.margin_percent),"):"]}),(0,t.jsxs)("span",{className:"text-gray-900",children:["+",en((a.margin_total_amount||0)-(a.margin_fixed_amount||0))]})]}),void 0!==a.margin_fixed_amount&&0!==a.margin_fixed_amount&&(0,t.jsxs)("div",{className:"flex text-sm text-gray-600",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Margin:"}),(0,t.jsxs)("span",{className:"text-gray-900",children:["+",en(a.margin_fixed_amount)]})]})]})]}),(0,t.jsx)("div",{className:"mt-4 pt-4 border-t border-gray-200 max-w-2xl",children:(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("span",{className:"font-bold text-sm text-gray-900 w-1/3",children:"Final Calculated Cost:"}),(0,t.jsx)("span",{className:"text-sm font-bold text-gray-900",children:en(null!==(s=a.total_cost)&&void 0!==s?s:l)})]})})]})})]})}):null};var eo=a(23048),ec=a(30841),em=a(7310),ex=a.n(em),eu=a(12363);let eh={TEAM_ID:"Team ID",KEY_HASH:"Key Hash",REQUEST_ID:"Request ID",MODEL:"Model",USER_ID:"User ID",END_USER:"End User",STATUS:"Status",KEY_ALIAS:"Key Alias",ERROR_CODE:"Error Code"};var eg=a(59341),ep=a(12485),ej=a(18135),ef=a(35242),ev=a(29706),ey=a(77991),eb=a(92280);let eN="".concat("../ui/assets/","audit-logs-preview.png");function ew(e){let{userID:s,userRole:a,token:l,accessToken:d,isActive:x,premiumUser:u,allTeams:h}=e,[g,p]=(0,i.useState)(r()().subtract(24,"hours").format("YYYY-MM-DDTHH:mm")),j=(0,i.useRef)(null),f=(0,i.useRef)(null),[v,y]=(0,i.useState)(1),[N]=(0,i.useState)(50),[w,_]=(0,i.useState)({}),[k,S]=(0,i.useState)(""),[C,L]=(0,i.useState)(""),[D,M]=(0,i.useState)(""),[E,T]=(0,i.useState)("all"),[A,R]=(0,i.useState)("all"),[z,O]=(0,i.useState)(!1),[Z,I]=(0,i.useState)(!1),K=(0,n.a)({queryKey:["all_audit_logs",d,l,a,s,g],queryFn:async()=>{if(!d||!l||!a||!s)return[];let e=r()(g).utc().format("YYYY-MM-DD HH:mm:ss"),t=r()().utc().format("YYYY-MM-DD HH:mm:ss"),n=[],i=1,c=1;do{let s=await (0,o.uiAuditLogsCall)(d,e,t,i,50);n=n.concat(s.audit_logs),c=s.total_pages,i++}while(i<=c);return n},enabled:!!d&&!!l&&!!a&&!!s&&x,refetchInterval:5e3,refetchIntervalInBackground:!0}),H=(0,i.useCallback)(async e=>{if(d)try{let s=(await (0,o.keyListCall)(d,null,null,e,null,null,1,10)).keys.find(s=>s.key_alias===e);s?L(s.token):L("")}catch(e){console.error("Error fetching key hash for alias:",e),L("")}},[d]);(0,i.useEffect)(()=>{if(!d)return;let e=!1,s=!1;w["Team ID"]?k!==w["Team ID"]&&(S(w["Team ID"]),e=!0):""!==k&&(S(""),e=!0),w["Key Hash"]?C!==w["Key Hash"]&&(L(w["Key Hash"]),s=!0):w["Key Alias"]?H(w["Key Alias"]):""!==C&&(L(""),s=!0),(e||s)&&y(1)},[w,d,H,k,C]),(0,i.useEffect)(()=>{y(1)},[k,C,g,D,E,A]),(0,i.useEffect)(()=>{function e(e){j.current&&!j.current.contains(e.target)&&O(!1),f.current&&!f.current.contains(e.target)&&I(!1)}return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[]);let P=(0,i.useMemo)(()=>K.data?K.data.filter(e=>{var s,a,t,l,r,n,i;let d=!0,o=!0,c=!0,m=!0,x=!0;if(k){let r="string"==typeof e.before_value?null===(s=JSON.parse(e.before_value))||void 0===s?void 0:s.team_id:null===(a=e.before_value)||void 0===a?void 0:a.team_id,n="string"==typeof e.updated_values?null===(t=JSON.parse(e.updated_values))||void 0===t?void 0:t.team_id:null===(l=e.updated_values)||void 0===l?void 0:l.team_id;d=r===k||n===k}if(C)try{let s="string"==typeof e.before_value?JSON.parse(e.before_value):e.before_value,a="string"==typeof e.updated_values?JSON.parse(e.updated_values):e.updated_values,t=null==s?void 0:s.token,l=null==a?void 0:a.token;o="string"==typeof t&&t.includes(C)||"string"==typeof l&&l.includes(C)}catch(e){o=!1}if(D&&(c=null===(r=e.object_id)||void 0===r?void 0:r.toLowerCase().includes(D.toLowerCase())),"all"!==E&&(m=(null===(n=e.action)||void 0===n?void 0:n.toLowerCase())===E.toLowerCase()),"all"!==A){let s="";switch(A){case"keys":s="litellm_verificationtoken";break;case"teams":s="litellm_teamtable";break;case"users":s="litellm_usertable";break;default:s=A}x=(null===(i=e.table_name)||void 0===i?void 0:i.toLowerCase())===s}return d&&o&&c&&m&&x}):[],[K.data,k,C,D,E,A]),F=P.length,q=Math.ceil(F/N)||1,Y=(0,i.useMemo)(()=>{let e=(v-1)*N,s=e+N;return P.slice(e,s)},[P,v,N]),B=!K.data||0===K.data.length,V=(0,i.useCallback)(e=>{let{row:s}=e;return(0,t.jsx)(e=>{let{rowData:s}=e,{before_value:a,updated_values:l,table_name:r,action:n}=s,i=(e,s)=>{if(!e||0===Object.keys(e).length)return(0,t.jsx)(eb.x,{children:"N/A"});if(s){let s=Object.keys(e),a=["token","spend","max_budget"];if(s.every(e=>a.includes(e))&&s.length>0)return(0,t.jsxs)("div",{children:[s.includes("token")&&(0,t.jsxs)("p",{children:[(0,t.jsx)("strong",{children:"Token:"})," ",e.token||"N/A"]}),s.includes("spend")&&(0,t.jsxs)("p",{children:[(0,t.jsx)("strong",{children:"Spend:"})," ",void 0!==e.spend?"$".concat((0,m.pw)(e.spend,6)):"N/A"]}),s.includes("max_budget")&&(0,t.jsxs)("p",{children:[(0,t.jsx)("strong",{children:"Max Budget:"})," ",void 0!==e.max_budget?"$".concat((0,m.pw)(e.max_budget,6)):"N/A"]})]});if(e["No differing fields detected in 'before' state"]||e["No differing fields detected in 'updated' state"]||e["No fields changed"])return(0,t.jsx)(eb.x,{children:e[Object.keys(e)[0]]})}return(0,t.jsx)("pre",{className:"p-2 bg-gray-50 border rounded text-xs overflow-auto max-h-60",children:JSON.stringify(e,null,2)})},d=a,o=l;if(("updated"===n||"rotated"===n)&&a&&l&&("LiteLLM_TeamTable"===r||"LiteLLM_UserTable"===r||"LiteLLM_VerificationToken"===r)){let e={},s={};new Set([...Object.keys(a),...Object.keys(l)]).forEach(t=>{JSON.stringify(a[t])!==JSON.stringify(l[t])&&(a.hasOwnProperty(t)&&(e[t]=a[t]),l.hasOwnProperty(t)&&(s[t]=l[t]))}),Object.keys(a).forEach(t=>{l.hasOwnProperty(t)||e.hasOwnProperty(t)||(e[t]=a[t],s[t]=void 0)}),Object.keys(l).forEach(t=>{a.hasOwnProperty(t)||s.hasOwnProperty(t)||(s[t]=l[t],e[t]=void 0)}),d=Object.keys(e).length>0?e:{"No differing fields detected in 'before' state":"N/A"},o=Object.keys(s).length>0?s:{"No differing fields detected in 'updated' state":"N/A"},0===Object.keys(e).length&&0===Object.keys(s).length&&(d={"No fields changed":"N/A"},o={"No fields changed":"N/A"})}return(0,t.jsxs)("div",{className:"-mx-4 p-4 bg-slate-100 border-y border-slate-300 grid grid-cols-1 md:grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h4",{className:"font-semibold mb-2 text-sm text-slate-700",children:"Before Value:"}),i(d,"LiteLLM_VerificationToken"===r)]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("h4",{className:"font-semibold mb-2 text-sm text-slate-700",children:"Updated Value:"}),i(o,"LiteLLM_VerificationToken"===r)]})]})},{rowData:s.original})},[]);if(!u)return(0,t.jsxs)("div",{style:{textAlign:"center",marginTop:"20px"},children:[(0,t.jsx)("h1",{style:{display:"block",marginBottom:"10px"},children:"✨ Enterprise Feature."}),(0,t.jsx)(eb.x,{style:{display:"block",marginBottom:"10px"},children:"This is a LiteLLM Enterprise feature, and requires a valid key to use."}),(0,t.jsx)(eb.x,{style:{display:"block",marginBottom:"20px",fontStyle:"italic"},children:"Here's a preview of what Audit Logs offer:"}),(0,t.jsx)("img",{src:eN,alt:"Audit Logs Preview",style:{maxWidth:"100%",maxHeight:"700px",borderRadius:"8px",boxShadow:"0 4px 8px rgba(0,0,0,0.1)",margin:"0 auto"},onError:e=>{console.error("Failed to load audit logs preview image"),e.target.style.display="none"}})]});let U=F>0?(v-1)*N+1:0,W=Math.min(v*N,F);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"flex items-center justify-between mb-4"}),(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow",children:[(0,t.jsxs)("div",{className:"border-b px-6 py-4",children:[(0,t.jsx)("h1",{className:"text-xl font-semibold py-4",children:"Audit Logs"}),(0,t.jsx)(e=>{let{show:s}=e;return s?(0,t.jsxs)("div",{className:"bg-blue-50 border border-blue-200 rounded-lg p-4 flex items-start mb-6",children:[(0,t.jsx)("div",{className:"text-blue-500 mr-3 flex-shrink-0 mt-0.5",children:(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("circle",{cx:"12",cy:"12",r:"10"}),(0,t.jsx)("line",{x1:"12",y1:"16",x2:"12",y2:"12"}),(0,t.jsx)("line",{x1:"12",y1:"8",x2:"12.01",y2:"8"})]})}),(0,t.jsxs)("div",{children:[(0,t.jsx)("h4",{className:"text-sm font-medium text-blue-800",children:"Audit Logs Not Available"}),(0,t.jsx)("p",{className:"text-sm text-blue-700 mt-1",children:"To enable audit logging, add the following configuration to your LiteLLM proxy configuration file:"}),(0,t.jsx)("pre",{className:"mt-2 bg-white p-3 rounded border border-blue-200 text-xs font-mono overflow-auto",children:"litellm_settings:\n store_audit_logs: true"}),(0,t.jsx)("p",{className:"text-xs text-blue-700 mt-2",children:"Note: This will only affect new requests after the configuration change and proxy restart."})]})]}):null},{show:B}),(0,t.jsxs)("div",{className:"flex flex-col md:flex-row items-start md:items-center justify-between space-y-4 md:space-y-0",children:[(0,t.jsx)("div",{className:"flex flex-wrap items-center gap-3",children:(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("div",{className:"flex items-center",children:(0,t.jsx)("input",{type:"text",placeholder:"Search by Object ID...",value:D,onChange:e=>M(e.target.value),className:"px-3 py-2 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})}),(0,t.jsxs)("button",{onClick:()=>{K.refetch()},className:"px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2",title:"Refresh data",children:[(0,t.jsx)("svg",{className:"w-4 h-4 ".concat(K.isFetching?"animate-spin":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),(0,t.jsx)("span",{children:"Refresh"})]})]})}),(0,t.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,t.jsxs)("div",{className:"relative",ref:j,children:[(0,t.jsx)("label",{htmlFor:"actionFilterDisplay",className:"mr-2 text-sm font-medium text-gray-700 sr-only",children:"Action:"}),(0,t.jsxs)("button",{id:"actionFilterDisplay",onClick:()=>O(!z),className:"px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2 bg-white w-40 text-left justify-between",children:[(0,t.jsxs)("span",{children:["all"===E&&"All Actions","created"===E&&"Created","updated"===E&&"Updated","deleted"===E&&"Deleted","rotated"===E&&"Rotated"]}),(0,t.jsx)("svg",{className:"w-4 h-4 text-gray-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M19 9l-7 7-7-7"})})]}),z&&(0,t.jsx)("div",{className:"absolute left-0 mt-2 w-40 bg-white rounded-lg shadow-lg border p-1 z-50",children:(0,t.jsx)("div",{className:"space-y-1",children:[{label:"All Actions",value:"all"},{label:"Created",value:"created"},{label:"Updated",value:"updated"},{label:"Deleted",value:"deleted"},{label:"Rotated",value:"rotated"}].map(e=>(0,t.jsx)("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 rounded-md ".concat(E===e.value?"bg-blue-50 text-blue-600 font-medium":"font-normal"),onClick:()=>{T(e.value),O(!1)},children:e.label},e.value))})})]}),(0,t.jsxs)("div",{className:"relative",ref:f,children:[(0,t.jsx)("label",{htmlFor:"tableFilterDisplay",className:"mr-2 text-sm font-medium text-gray-700 sr-only",children:"Table:"}),(0,t.jsxs)("button",{id:"tableFilterDisplay",onClick:()=>I(!Z),className:"px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2 bg-white w-40 text-left justify-between",children:[(0,t.jsxs)("span",{children:["all"===A&&"All Tables","keys"===A&&"Keys","teams"===A&&"Teams","users"===A&&"Users"]}),(0,t.jsx)("svg",{className:"w-4 h-4 text-gray-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M19 9l-7 7-7-7"})})]}),Z&&(0,t.jsx)("div",{className:"absolute left-0 mt-2 w-40 bg-white rounded-lg shadow-lg border p-1 z-50",children:(0,t.jsx)("div",{className:"space-y-1",children:[{label:"All Tables",value:"all"},{label:"Keys",value:"keys"},{label:"Teams",value:"teams"},{label:"Users",value:"users"}].map(e=>(0,t.jsx)("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 rounded-md ".concat(A===e.value?"bg-blue-50 text-blue-600 font-medium":"font-normal"),onClick:()=>{R(e.value),I(!1)},children:e.label},e.value))})})]}),(0,t.jsxs)("span",{className:"text-sm text-gray-700",children:["Showing ",K.isLoading?"...":U," -"," ",K.isLoading?"...":W," of"," ",K.isLoading?"...":F," results"]}),(0,t.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,t.jsxs)("span",{className:"text-sm text-gray-700",children:["Page ",K.isLoading?"...":v," of"," ",K.isLoading?"...":q]}),(0,t.jsx)("button",{onClick:()=>y(e=>Math.max(1,e-1)),disabled:K.isLoading||1===v,className:"px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",children:"Previous"}),(0,t.jsx)("button",{onClick:()=>y(e=>Math.min(q,e+1)),disabled:K.isLoading||v===q,className:"px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",children:"Next"})]})]})]})]}),(0,t.jsx)(c.w,{columns:b,data:Y,renderSubComponent:V,getRowCanExpand:()=>!0})]})]})}let e_=(e,s,a)=>{if(e)return"".concat(r()(s).format("MMM D, h:mm A")," - ").concat(r()(a).format("MMM D, h:mm A"));let t=r()(),l=r()(s),n=t.diff(l,"minutes");if(n>=0&&n<2)return"Last 1 Minute";if(n>=2&&n<16)return"Last 15 Minutes";if(n>=16&&n<61)return"Last Hour";let i=t.diff(l,"hours");return i>=1&&i<5?"Last 4 Hours":i>=5&&i<25?"Last 24 Hours":i>=25&&i<169?"Last 7 Days":"".concat(l.format("MMM D")," - ").concat(t.format("MMM D"))};var ek=a(9309),eS=a(30280),eC=a(44633),eL=a(86462),eD=a(49084),eM=a(71594),eE=a(24525),eT=a(19130);function eA(e){let{keys:s,totalCount:a,isLoading:l,isFetching:r,pageIndex:n,pageSize:d,onPageChange:o}=e,[c,x]=(0,i.useState)([{id:"deleted_at",desc:!0}]),[u,g]=(0,i.useState)({pageIndex:n,pageSize:d});i.useEffect(()=>{g({pageIndex:n,pageSize:d})},[n,d]);let p=[{id:"token",accessorKey:"token",header:"Key ID",size:150,maxSize:250,cell:e=>{let s=e.getValue();return(0,t.jsx)(h.Z,{title:s,children:(0,t.jsx)("span",{className:"font-mono text-blue-500 text-xs truncate block max-w-[250px]",children:s||"-"})})}},{id:"key_alias",accessorKey:"key_alias",header:"Key Alias",size:150,maxSize:200,cell:e=>{let s=e.getValue();return(0,t.jsx)(h.Z,{title:s,children:(0,t.jsx)("span",{className:"font-mono text-xs truncate block max-w-[200px]",children:null!=s?s:"-"})})}},{id:"team_alias",accessorKey:"team_alias",header:"Team Alias",size:120,maxSize:180,cell:e=>{let s=e.getValue();return(0,t.jsx)("span",{className:"truncate block max-w-[180px]",children:s||"-"})}},{id:"spend",accessorKey:"spend",header:"Spend (USD)",size:100,maxSize:140,cell:e=>(0,t.jsx)("span",{className:"block max-w-[140px]",children:(0,m.pw)(e.getValue(),4)})},{id:"max_budget",accessorKey:"max_budget",header:"Budget (USD)",size:110,maxSize:150,cell:e=>{let s=e.getValue();return(0,t.jsx)("span",{className:"block max-w-[150px]",children:null===s?"Unlimited":"$".concat((0,m.pw)(s))})}},{id:"user_email",accessorKey:"user_email",header:"User Email",size:160,maxSize:250,cell:e=>{let s=e.getValue();return(0,t.jsx)(h.Z,{title:s,children:(0,t.jsx)("span",{className:"font-mono text-xs truncate block max-w-[250px]",children:null!=s?s:"-"})})}},{id:"user_id",accessorKey:"user_id",header:"User ID",size:120,maxSize:200,cell:e=>{let s=e.getValue();return(0,t.jsx)(h.Z,{title:s||void 0,children:(0,t.jsx)("span",{className:"truncate block max-w-[200px]",children:s||"-"})})}},{id:"created_at",accessorKey:"created_at",header:"Created At",size:120,maxSize:140,cell:e=>{let s=e.getValue();return(0,t.jsx)("span",{className:"block max-w-[140px]",children:s?new Date(s).toLocaleDateString():"-"})}},{id:"created_by",accessorKey:"created_by",header:"Created By",size:120,maxSize:180,cell:e=>{let s=e.row.original.created_by;return(0,t.jsx)(h.Z,{title:s||void 0,children:(0,t.jsx)("span",{className:"truncate block max-w-[180px]",children:s||"-"})})}},{id:"deleted_at",accessorKey:"deleted_at",header:"Deleted At",size:120,maxSize:140,cell:e=>{let s=e.row.original.deleted_at;return(0,t.jsx)("span",{className:"block max-w-[140px]",children:s?new Date(s).toLocaleDateString():"-"})}},{id:"deleted_by",accessorKey:"deleted_by",header:"Deleted By",size:120,maxSize:180,cell:e=>{let s=e.row.original.deleted_by;return(0,t.jsx)(h.Z,{title:s||void 0,children:(0,t.jsx)("span",{className:"truncate block max-w-[180px]",children:s||"-"})})}}],j=(0,eM.b7)({data:s,columns:p,columnResizeMode:"onChange",columnResizeDirection:"ltr",state:{sorting:c,pagination:u},onSortingChange:x,onPaginationChange:e=>{let s="function"==typeof e?e(u):e;g(s),o(s.pageIndex)},getCoreRowModel:(0,eE.sC)(),getSortedRowModel:(0,eE.tj)(),getPaginationRowModel:(0,eE.G_)(),enableSorting:!0,manualSorting:!1,manualPagination:!0,pageCount:Math.ceil(a/d)}),{pageIndex:f}=j.getState().pagination,v=f*d+1,y="".concat(v," - ").concat(Math.min((f+1)*d,a));return(0,t.jsx)("div",{className:"w-full h-full overflow-hidden",children:(0,t.jsxs)("div",{className:"border-b py-4 flex-1 overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between w-full mb-4",children:[l||r?(0,t.jsx)("span",{className:"inline-flex text-sm text-gray-700",children:"Loading..."}):(0,t.jsxs)("span",{className:"inline-flex text-sm text-gray-700",children:["Showing ",y," of ",a," results"]}),(0,t.jsxs)("div",{className:"inline-flex items-center gap-2",children:[l||r?(0,t.jsx)("span",{className:"text-sm text-gray-700",children:"Loading..."}):(0,t.jsxs)("span",{className:"text-sm text-gray-700",children:["Page ",f+1," of ",j.getPageCount()]}),(0,t.jsx)("button",{onClick:()=>j.previousPage(),disabled:l||r||!j.getCanPreviousPage(),className:"px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",children:"Previous"}),(0,t.jsx)("button",{onClick:()=>j.nextPage(),disabled:l||r||!j.getCanNextPage(),className:"px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",children:"Next"})]})]}),(0,t.jsx)("div",{className:"h-[75vh] overflow-auto",children:(0,t.jsx)("div",{className:"rounded-lg custom-border relative",children:(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsxs)(eT.iA,{className:"[&_td]:py-0.5 [&_th]:py-1",style:{width:j.getCenterTotalSize()},children:[(0,t.jsx)(eT.ss,{children:j.getHeaderGroups().map(e=>(0,t.jsx)(eT.SC,{children:e.headers.map(e=>(0,t.jsx)(eT.xs,{"data-header-id":e.id,className:"py-1 h-8 relative hover:bg-gray-50",style:{width:e.getSize(),maxWidth:e.column.columnDef.maxSize,position:"relative"},onMouseEnter:()=>{let s=document.querySelector('[data-header-id="'.concat(e.id,'"] .resizer'));s&&(s.style.opacity="0.5")},onMouseLeave:()=>{let s=document.querySelector('[data-header-id="'.concat(e.id,'"] .resizer'));s&&!e.column.getIsResizing()&&(s.style.opacity="0")},onClick:e.column.getToggleSortingHandler(),children:(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,t.jsx)("div",{className:"flex items-center",children:e.isPlaceholder?null:(0,eM.ie)(e.column.columnDef.header,e.getContext())}),(0,t.jsx)("div",{className:"w-4",children:e.column.getIsSorted()?({asc:(0,t.jsx)(eC.Z,{className:"h-4 w-4 text-blue-500"}),desc:(0,t.jsx)(eL.Z,{className:"h-4 w-4 text-blue-500"})})[e.column.getIsSorted()]:(0,t.jsx)(eD.Z,{className:"h-4 w-4 text-gray-400"})}),(0,t.jsx)("div",{onDoubleClick:()=>e.column.resetSize(),onMouseDown:e.getResizeHandler(),onTouchStart:e.getResizeHandler(),className:"resizer ".concat(j.options.columnResizeDirection," ").concat(e.column.getIsResizing()?"isResizing":""),style:{position:"absolute",right:0,top:0,height:"100%",width:"5px",background:e.column.getIsResizing()?"#3b82f6":"transparent",cursor:"col-resize",userSelect:"none",touchAction:"none",opacity:e.column.getIsResizing()?1:0}})]})},e.id))},e.id))}),(0,t.jsx)(eT.RM,{children:l||r?(0,t.jsx)(eT.SC,{children:(0,t.jsx)(eT.pj,{colSpan:p.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"\uD83D\uDE85 Loading keys..."})})})}):s.length>0?j.getRowModel().rows.map(e=>(0,t.jsx)(eT.SC,{className:"h-8",children:e.getVisibleCells().map(e=>(0,t.jsx)(eT.pj,{style:{width:e.column.getSize(),maxWidth:e.column.columnDef.maxSize,whiteSpace:"pre-wrap",overflow:"hidden"},className:"py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap",children:(0,eM.ie)(e.column.columnDef.cell,e.getContext())},e.id))},e.id)):(0,t.jsx)(eT.SC,{children:(0,t.jsx)(eT.pj,{colSpan:p.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"No deleted keys found"})})})})})]})})})})]})})}function eR(){let[e,s]=(0,i.useState)(0),[a]=(0,i.useState)(50),{data:l,isPending:r,isFetching:n}=(0,eS.Tv)(e+1,a);return(0,t.jsx)(eA,{keys:(null==l?void 0:l.keys)||[],totalCount:(null==l?void 0:l.total_count)||0,isLoading:r,isFetching:n,pageIndex:e,pageSize:a,onPageChange:s})}var ez=a(47359),eO=a(21626),eZ=a(97214),eI=a(28241),eK=a(58834),eH=a(69552),eP=a(71876),eF=a(46468);function eq(e){let{teams:s,isLoading:a,isFetching:l}=e,[r,n]=(0,i.useState)([{id:"deleted_at",desc:!0}]),d=[{id:"team_alias",accessorKey:"team_alias",header:"Team Name",size:150,maxSize:200,cell:e=>{let s=e.getValue();return(0,t.jsx)(h.Z,{title:s||void 0,children:(0,t.jsx)("span",{className:"truncate block max-w-[200px]",children:s||"-"})})}},{id:"team_id",accessorKey:"team_id",header:"Team ID",size:150,maxSize:250,cell:e=>{let s=e.getValue();return(0,t.jsx)(h.Z,{title:s,children:(0,t.jsx)("span",{className:"font-mono text-blue-500 text-xs truncate block max-w-[250px]",children:s||"-"})})}},{id:"created_at",accessorKey:"created_at",header:"Created",size:120,maxSize:140,cell:e=>{let s=e.getValue();return(0,t.jsx)("span",{className:"block max-w-[140px]",children:s?new Date(s).toLocaleDateString():"-"})}},{id:"spend",accessorKey:"spend",header:"Spend (USD)",size:100,maxSize:140,cell:e=>{let s=e.row.original.spend;return(0,t.jsx)("span",{className:"block max-w-[140px]",children:void 0!==s?(0,m.pw)(s,4):"-"})}},{id:"max_budget",accessorKey:"max_budget",header:"Budget (USD)",size:110,maxSize:150,cell:e=>{let s=e.getValue();return(0,t.jsx)("span",{className:"block max-w-[150px]",children:null==s?"No limit":"$".concat((0,m.pw)(s))})}},{id:"models",accessorKey:"models",header:"Models",size:200,maxSize:300,cell:e=>{let s=e.getValue();return Array.isArray(s)&&0!==s.length?(0,t.jsxs)("div",{className:"flex flex-wrap gap-1 max-w-[300px]",children:[s.slice(0,3).map((e,s)=>"all-proxy-models"===e?(0,t.jsx)(x.Z,{size:"xs",color:"red",children:(0,t.jsx)(T.Z,{children:"All Proxy Models"})},s):(0,t.jsx)(x.Z,{size:"xs",color:"blue",children:(0,t.jsx)(T.Z,{children:e.length>30?"".concat((0,eF.W0)(e).slice(0,30),"..."):(0,eF.W0)(e)})},s)),s.length>3&&(0,t.jsx)(x.Z,{size:"xs",color:"gray",children:(0,t.jsxs)(T.Z,{children:["+",s.length-3," ",s.length-3==1?"more model":"more models"]})})]}):(0,t.jsx)(x.Z,{size:"xs",color:"red",children:(0,t.jsx)(T.Z,{children:"All Proxy Models"})})}},{id:"organization_id",accessorKey:"organization_id",header:"Organization",size:150,maxSize:200,cell:e=>{let s=e.getValue();return(0,t.jsx)(h.Z,{title:s||void 0,children:(0,t.jsx)("span",{className:"truncate block max-w-[200px]",children:s||"-"})})}},{id:"deleted_at",accessorKey:"deleted_at",header:"Deleted At",size:120,maxSize:140,cell:e=>{let s=e.row.original.deleted_at;return(0,t.jsx)("span",{className:"block max-w-[140px]",children:s?new Date(s).toLocaleDateString():"-"})}},{id:"deleted_by",accessorKey:"deleted_by",header:"Deleted By",size:120,maxSize:180,cell:e=>{let s=e.row.original.deleted_by;return(0,t.jsx)(h.Z,{title:s||void 0,children:(0,t.jsx)("span",{className:"truncate block max-w-[180px]",children:s||"-"})})}}],o=(0,eM.b7)({data:s,columns:d,columnResizeMode:"onChange",columnResizeDirection:"ltr",state:{sorting:r},onSortingChange:n,getCoreRowModel:(0,eE.sC)(),getSortedRowModel:(0,eE.tj)(),enableSorting:!0,manualSorting:!1});return(0,t.jsx)("div",{className:"w-full h-full overflow-hidden",children:(0,t.jsxs)("div",{className:"border-b py-4 flex-1 overflow-hidden",children:[(0,t.jsx)("div",{className:"flex items-center justify-between w-full mb-4",children:a||l?(0,t.jsx)("span",{className:"inline-flex text-sm text-gray-700",children:"Loading..."}):(0,t.jsxs)("span",{className:"inline-flex text-sm text-gray-700",children:["Showing ",s.length," ",1===s.length?"team":"teams"]})}),(0,t.jsx)("div",{className:"h-[75vh] overflow-auto",children:(0,t.jsx)("div",{className:"rounded-lg custom-border relative",children:(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsxs)(eO.Z,{className:"[&_td]:py-0.5 [&_th]:py-1",style:{width:o.getCenterTotalSize()},children:[(0,t.jsx)(eK.Z,{children:o.getHeaderGroups().map(e=>(0,t.jsx)(eP.Z,{children:e.headers.map(e=>(0,t.jsx)(eH.Z,{"data-header-id":e.id,className:"py-1 h-8 relative hover:bg-gray-50",style:{width:e.getSize(),maxWidth:e.column.columnDef.maxSize,position:"relative"},onMouseEnter:()=>{let s=document.querySelector('[data-header-id="'.concat(e.id,'"] .resizer'));s&&(s.style.opacity="0.5")},onMouseLeave:()=>{let s=document.querySelector('[data-header-id="'.concat(e.id,'"] .resizer'));s&&!e.column.getIsResizing()&&(s.style.opacity="0")},onClick:e.column.getToggleSortingHandler(),children:(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,t.jsx)("div",{className:"flex items-center",children:e.isPlaceholder?null:(0,eM.ie)(e.column.columnDef.header,e.getContext())}),(0,t.jsx)("div",{className:"w-4",children:e.column.getIsSorted()?({asc:(0,t.jsx)(eC.Z,{className:"h-4 w-4 text-blue-500"}),desc:(0,t.jsx)(eL.Z,{className:"h-4 w-4 text-blue-500"})})[e.column.getIsSorted()]:(0,t.jsx)(eD.Z,{className:"h-4 w-4 text-gray-400"})}),(0,t.jsx)("div",{onDoubleClick:()=>e.column.resetSize(),onMouseDown:e.getResizeHandler(),onTouchStart:e.getResizeHandler(),className:"resizer ".concat(o.options.columnResizeDirection," ").concat(e.column.getIsResizing()?"isResizing":""),style:{position:"absolute",right:0,top:0,height:"100%",width:"5px",background:e.column.getIsResizing()?"#3b82f6":"transparent",cursor:"col-resize",userSelect:"none",touchAction:"none",opacity:e.column.getIsResizing()?1:0}})]})},e.id))},e.id))}),(0,t.jsx)(eZ.Z,{children:a||l?(0,t.jsx)(eP.Z,{children:(0,t.jsx)(eI.Z,{colSpan:d.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"\uD83D\uDE85 Loading teams..."})})})}):s.length>0?o.getRowModel().rows.map(e=>(0,t.jsx)(eP.Z,{className:"h-8",children:e.getVisibleCells().map(e=>(0,t.jsx)(eI.Z,{style:{width:e.column.getSize(),maxWidth:e.column.columnDef.maxSize,whiteSpace:"pre-wrap",overflow:"hidden"},className:"py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap",children:(0,eM.ie)(e.column.columnDef.cell,e.getContext())},e.id))},e.id)):(0,t.jsx)(eP.Z,{children:(0,t.jsx)(eI.Z,{colSpan:d.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"No deleted teams found"})})})})})]})})})})]})})}function eY(){let{data:e,isPending:s,isFetching:a}=(0,ez.iN)(1,100);return(0,t.jsx)(eq,{teams:e||[],isLoading:s,isFetching:a})}var eB=a(91027);function eV(e){var s,a,l;let{accessToken:m,token:x,userRole:u,userID:h,allTeams:g,premiumUser:p}=e,[j,f]=(0,i.useState)(""),[y,b]=(0,i.useState)(!1),[w,_]=(0,i.useState)(!1),[k,S]=(0,i.useState)(1),[L]=(0,i.useState)(50),M=(0,i.useRef)(null),E=(0,i.useRef)(null),T=(0,i.useRef)(null),[A,R]=(0,i.useState)(r()().subtract(24,"hours").format("YYYY-MM-DDTHH:mm")),[z,O]=(0,i.useState)(r()().format("YYYY-MM-DDTHH:mm")),[Z,K]=(0,i.useState)(!1),[H,P]=(0,i.useState)(!1),[F,q]=(0,i.useState)(""),[Y,B]=(0,i.useState)(""),[V,U]=(0,i.useState)(""),[W,J]=(0,i.useState)(""),[G,Q]=(0,i.useState)(""),[$,X]=(0,i.useState)(null),[ee,es]=(0,i.useState)(null),[ea,et]=(0,i.useState)(""),[el,er]=(0,i.useState)(""),[en,ei]=(0,i.useState)(u&&C.lo.includes(u)),[ed,em]=(0,i.useState)("request logs"),[eb,eN]=(0,i.useState)(null),[ek,eS]=(0,i.useState)(null),eC=(0,d.NL)(),[eL,eD]=(0,i.useState)(()=>{let e=sessionStorage.getItem("isLiveTail");return null===e||JSON.parse(e)});(0,i.useEffect)(()=>{sessionStorage.setItem("isLiveTail",JSON.stringify(eL))},[eL]);let[eM,eE]=(0,i.useState)({value:24,unit:"hours"});(0,i.useEffect)(()=>{(async()=>{ee&&m&&X({...(await (0,o.keyInfoV1Call)(m,ee)).info,token:ee,api_key:ee})})()},[ee,m]),(0,i.useEffect)(()=>{function e(e){M.current&&!M.current.contains(e.target)&&_(!1),E.current&&!E.current.contains(e.target)&&b(!1),T.current&&!T.current.contains(e.target)&&P(!1)}return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[]),(0,i.useEffect)(()=>{u&&C.lo.includes(u)&&ei(!0)},[u]);let eT=(0,n.a)({queryKey:["logs","table",k,L,A,z,V,W,en?h:null,ea,G],queryFn:async()=>{if(!m||!x||!u||!h)return{data:[],total:0,page:1,page_size:L,total_pages:0};let e=r()(A).utc().format("YYYY-MM-DD HH:mm:ss"),s=Z?r()(z).utc().format("YYYY-MM-DD HH:mm:ss"):r()().utc().format("YYYY-MM-DD HH:mm:ss"),a=await (0,o.uiSpendLogsCall)(m,W||void 0,V||void 0,void 0,e,s,k,L,en?h:void 0,el,ea,G);return await N(a.data,e,m,eC),a.data=a.data.map(s=>{let a=eC.getQueryData(["logDetails",s.request_id,e]);return(null==a?void 0:a.messages)&&(null==a?void 0:a.response)&&(s.messages=a.messages,s.response=a.response),s}),a},enabled:!!m&&!!x&&!!u&&!!h&&"request logs"===ed,refetchInterval:!!eL&&1===k&&15e3,refetchIntervalInBackground:!0}),eA=eT.data||{data:[],total:0,page:1,page_size:L||10,total_pages:1},{filters:ez,filteredLogs:eO,allTeams:eZ,allKeyAliases:eI,handleFilterChange:eK,handleFilterReset:eH}=function(e){let{logs:s,accessToken:a,startTime:t,endTime:l,pageSize:d=eu.d,isCustomDate:c,setCurrentPage:m,userID:x,userRole:u}=e,h=(0,i.useMemo)(()=>({[eh.TEAM_ID]:"",[eh.KEY_HASH]:"",[eh.REQUEST_ID]:"",[eh.MODEL]:"",[eh.USER_ID]:"",[eh.END_USER]:"",[eh.STATUS]:"",[eh.KEY_ALIAS]:"",[eh.ERROR_CODE]:""}),[]),[g,p]=(0,i.useState)(h),[j,f]=(0,i.useState)({data:[],total:0,page:1,page_size:50,total_pages:0}),v=(0,i.useRef)(0),y=(0,i.useCallback)(async function(e){let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;if(!a)return;console.log("Filters being sent to API:",e);let n=Date.now();v.current=n;let i=r()(t).utc().format("YYYY-MM-DD HH:mm:ss"),m=c?r()(l).utc().format("YYYY-MM-DD HH:mm:ss"):r()().utc().format("YYYY-MM-DD HH:mm:ss");try{let t=await (0,o.uiSpendLogsCall)(a,e[eh.KEY_HASH]||void 0,e[eh.TEAM_ID]||void 0,e[eh.REQUEST_ID]||void 0,i,m,s,d,e[eh.USER_ID]||void 0,e[eh.END_USER]||void 0,e[eh.STATUS]||void 0,e[eh.MODEL]||void 0,e[eh.KEY_ALIAS]||void 0,e[eh.ERROR_CODE]||void 0);n===v.current&&t.data&&f(t)}catch(e){console.error("Error searching users:",e)}},[a,t,l,c,d]),b=(0,i.useMemo)(()=>ex()((e,s)=>y(e,s),300),[y]);(0,i.useEffect)(()=>()=>b.cancel(),[b]);let N=(0,n.a)({queryKey:["allKeys"],queryFn:async()=>{if(!a)throw Error("Access token required");return await (0,ec.LO)(a)},enabled:!!a}).data||[],w=(0,i.useMemo)(()=>!!(g[eh.KEY_ALIAS]||g[eh.KEY_HASH]||g[eh.REQUEST_ID]||g[eh.USER_ID]||g[eh.END_USER]||g[eh.ERROR_CODE]),[g]),_=(0,i.useMemo)(()=>{if(!s||!s.data)return{data:[],total:0,page:1,page_size:50,total_pages:0};if(w)return s;let e=[...s.data];return g[eh.TEAM_ID]&&(e=e.filter(e=>e.team_id===g[eh.TEAM_ID])),g[eh.STATUS]&&(e=e.filter(e=>"success"===g[eh.STATUS]?!e.status||"success"===e.status:e.status===g[eh.STATUS])),g[eh.MODEL]&&(e=e.filter(e=>e.model===g[eh.MODEL])),g[eh.KEY_HASH]&&(e=e.filter(e=>e.api_key===g[eh.KEY_HASH])),g[eh.END_USER]&&(e=e.filter(e=>e.end_user===g[eh.END_USER])),g[eh.ERROR_CODE]&&(e=e.filter(e=>{let s=(e.metadata||{}).error_information;return s&&s.error_code===g[eh.ERROR_CODE]})),{data:e,total:s.total,page:s.page,page_size:s.page_size,total_pages:s.total_pages}},[s,g,w]),k=(0,i.useMemo)(()=>w?j&&j.data&&j.data.length>0?j:s||{data:[],total:0,page:1,page_size:50,total_pages:0}:_,[w,j,_,s]),{data:S}=(0,n.a)({queryKey:["allTeamsForLogFilters",a],queryFn:async()=>a&&await (0,ec.IE)(a)||[],enabled:!!a});return{filters:g,filteredLogs:k,allKeyAliases:N,allTeams:S,handleFilterChange:e=>{p(s=>{let a={...s,...e};for(let e of Object.keys(h))e in a||(a[e]=h[e]);return JSON.stringify(a)!==JSON.stringify(s)&&(m(1),b(a,1)),a})},handleFilterReset:()=>{p(h),f({data:[],total:0,page:1,page_size:50,total_pages:0}),b(h,1)}}}({logs:eA,accessToken:m,startTime:A,endTime:z,pageSize:L,isCustomDate:Z,setCurrentPage:S,userID:h,userRole:u}),eP=(0,i.useCallback)(async e=>{if(m)try{let s=(await (0,o.keyListCall)(m,null,null,e,null,null,k,L)).keys.find(s=>s.key_alias===e);s&&J(s.token)}catch(e){console.error("Error fetching key hash for alias:",e)}},[m,k,L]);(0,i.useEffect)(()=>{m&&(ez["Team ID"]?U(ez["Team ID"]):U(""),et(ez.Status||""),Q(ez.Model||""),er(ez["End User"]||""),ez["Key Hash"]?J(ez["Key Hash"]):ez["Key Alias"]?eP(ez["Key Alias"]):J(""))},[ez,m,eP]);let eF=(0,n.a)({queryKey:["sessionLogs",ek],queryFn:async()=>{if(!m||!ek)return{data:[],total:0,page:1,page_size:50,total_pages:1};let e=await (0,o.sessionSpendLogsCall)(m,ek);return{data:e.data||e||[],total:(e.data||e||[]).length,page:1,page_size:1e3,total_pages:1}},enabled:!!m&&!!ek});if((0,i.useEffect)(()=>{var e;(null===(e=eT.data)||void 0===e?void 0:e.data)&&eb&&!eT.data.data.some(e=>e.request_id===eb)&&eN(null)},[null===(s=eT.data)||void 0===s?void 0:s.data,eb]),!m||!x||!u||!h)return null;let eq=eO.data.filter(e=>!j||e.request_id.includes(j)||e.model.includes(j)||e.user&&e.user.includes(j)).map(e=>({...e,duration:(Date.parse(e.endTime)-Date.parse(e.startTime))/1e3,onKeyHashClick:e=>es(e),onSessionClick:e=>{e&&eS(e)}}))||[],eV=(null===(l=eF.data)||void 0===l?void 0:null===(a=l.data)||void 0===a?void 0:a.map(e=>({...e,onKeyHashClick:e=>es(e),onSessionClick:e=>{}})))||[],eW=function(e){let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",a=new Set;return e.forEach(e=>{let t=e.metadata||{};if("failure"===t.status&&t.error_information){let e=t.error_information.error_code;e&&(!s||e.toLowerCase().includes(s.toLowerCase()))&&a.add(e)}}),Array.from(a).map(e=>({label:e,value:e}))},eJ=[{name:"Team ID",label:"Team ID",isSearchable:!0,searchFn:async e=>g&&0!==g.length?g.filter(s=>s.team_id.toLowerCase().includes(e.toLowerCase())||s.team_alias&&s.team_alias.toLowerCase().includes(e.toLowerCase())).map(e=>({label:"".concat(e.team_alias||e.team_id," (").concat(e.team_id,")"),value:e.team_id})):[]},{name:"Status",label:"Status",isSearchable:!1,options:[{label:"Success",value:"success"},{label:"Failure",value:"failure"}]},{name:"Model",label:"Model",isSearchable:!1},{name:"Key Alias",label:"Key Alias",isSearchable:!0,searchFn:async e=>m?(await (0,ec.LO)(m)).filter(s=>s.toLowerCase().includes(e.toLowerCase())).map(e=>({label:e,value:e})):[]},{name:"End User",label:"End User",isSearchable:!0,searchFn:async e=>{if(!m)return[];let s=await (0,o.allEndUsersCall)(m);return((null==s?void 0:s.map(e=>e.user_id))||[]).filter(s=>s.toLowerCase().includes(e.toLowerCase())).map(e=>({label:e,value:e}))}},{name:"Error Code",label:"Error Code",isSearchable:!0,searchFn:async e=>eW(eA.data,e)},{name:"Key Hash",label:"Key Hash",isSearchable:!1}];if(ek&&eF.data)return(0,t.jsx)("div",{className:"w-full p-6",children:(0,t.jsx)(I,{sessionId:ek,logs:eF.data.data,onBack:()=>eS(null)})});let eG=[{label:"Last 15 Minutes",value:15,unit:"minutes"},{label:"Last Hour",value:1,unit:"hours"},{label:"Last 4 Hours",value:4,unit:"hours"},{label:"Last 24 Hours",value:24,unit:"hours"},{label:"Last 7 Days",value:7,unit:"days"}],eQ=eG.find(e=>e.value===eM.value&&e.unit===eM.unit),e$=Z?e_(Z,A,z):null==eQ?void 0:eQ.label;return(0,t.jsx)("div",{className:"w-full max-w-screen p-6 overflow-x-hidden box-border",children:(0,t.jsxs)(ej.Z,{defaultIndex:0,onIndexChange:e=>em(0===e?"request logs":"audit logs"),children:[(0,t.jsxs)(ef.Z,{children:[(0,t.jsx)(ep.Z,{children:"Request Logs"}),(0,t.jsx)(ep.Z,{children:"Audit Logs"}),(0,t.jsx)(ep.Z,{children:(0,t.jsxs)(t.Fragment,{children:["Deleted Keys ",(0,t.jsx)(eB.Z,{})]})}),(0,t.jsx)(ep.Z,{children:(0,t.jsxs)(t.Fragment,{children:["Deleted Teams ",(0,t.jsx)(eB.Z,{})]})})]}),(0,t.jsxs)(ey.Z,{children:[(0,t.jsxs)(ev.Z,{children:[(0,t.jsx)("div",{className:"flex items-center justify-between mb-4",children:(0,t.jsx)("h1",{className:"text-xl font-semibold",children:ek?(0,t.jsxs)(t.Fragment,{children:["Session: ",(0,t.jsx)("span",{className:"font-mono",children:ek}),(0,t.jsx)("button",{className:"ml-4 px-3 py-1 text-sm border rounded hover:bg-gray-50",onClick:()=>eS(null),children:"← Back to All Logs"})]}):"Request Logs"})}),$&&ee&&$.api_key===ee?(0,t.jsx)(D.Z,{keyId:ee,keyData:$,teams:g,onClose:()=>es(null),backButtonText:"Back to Logs"}):ek?(0,t.jsx)("div",{className:"bg-white rounded-lg shadow",children:(0,t.jsx)(c.w,{columns:v,data:eV,renderSubComponent:eU,getRowCanExpand:()=>!0})}):(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(eo.Z,{options:eJ,onApplyFilters:eK,onResetFilters:eH}),(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow w-full max-w-full box-border",children:[(0,t.jsx)("div",{className:"border-b px-6 py-4 w-full max-w-full box-border",children:(0,t.jsxs)("div",{className:"flex flex-col md:flex-row items-start md:items-center justify-between space-y-4 md:space-y-0 w-full max-w-full box-border",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-3 w-full max-w-full box-border",children:[(0,t.jsxs)("div",{className:"relative w-64 min-w-0 flex-shrink-0",children:[(0,t.jsx)("input",{type:"text",placeholder:"Search by Request ID",className:"w-full px-3 py-2 pl-8 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",value:j,onChange:e=>f(e.target.value)}),(0,t.jsx)("svg",{className:"absolute left-2.5 top-2.5 h-4 w-4 text-gray-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2 min-w-0 flex-shrink",children:[(0,t.jsxs)("div",{className:"relative z-50",ref:T,children:[(0,t.jsxs)("button",{onClick:()=>P(!H),className:"px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2",children:[(0,t.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"})}),e$]}),H&&(0,t.jsx)("div",{className:"absolute right-0 mt-2 w-64 bg-white rounded-lg shadow-lg border p-2 z-50",children:(0,t.jsxs)("div",{className:"space-y-1",children:[eG.map(e=>(0,t.jsx)("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 rounded-md ".concat(e$===e.label?"bg-blue-50 text-blue-600":""),onClick:()=>{O(r()().format("YYYY-MM-DDTHH:mm")),R(r()().subtract(e.value,e.unit).format("YYYY-MM-DDTHH:mm")),eE({value:e.value,unit:e.unit}),K(!1),P(!1)},children:e.label},e.label)),(0,t.jsx)("div",{className:"border-t my-2"}),(0,t.jsx)("button",{className:"w-full px-3 py-2 text-left text-sm hover:bg-gray-50 rounded-md ".concat(Z?"bg-blue-50 text-blue-600":""),onClick:()=>K(!Z),children:"Custom Range"})]})})]}),(0,t.jsx)(()=>(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:"text-sm font-medium text-gray-900",children:"Live Tail"}),(0,t.jsx)(eg.Z,{color:"green",checked:eL,defaultChecked:!0,onChange:eD})]}),{}),(0,t.jsxs)("button",{onClick:()=>{eT.refetch()},className:"px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2",title:"Refresh data",children:[(0,t.jsx)("svg",{className:"w-4 h-4 ".concat(eT.isFetching?"animate-spin":""),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),(0,t.jsx)("span",{children:"Refresh"})]})]}),Z&&(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("div",{children:(0,t.jsx)("input",{type:"datetime-local",value:A,onChange:e=>{R(e.target.value),S(1)},className:"px-3 py-2 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})}),(0,t.jsx)("span",{className:"text-gray-500",children:"to"}),(0,t.jsx)("div",{children:(0,t.jsx)("input",{type:"datetime-local",value:z,onChange:e=>{O(e.target.value),S(1)},className:"px-3 py-2 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"})})]})]}),(0,t.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,t.jsxs)("span",{className:"text-sm text-gray-700 whitespace-nowrap",children:["Showing ",eT.isLoading?"...":eO?(k-1)*L+1:0," -"," ",eT.isLoading?"...":eO?Math.min(k*L,eO.total):0," ","of ",eT.isLoading?"...":eO?eO.total:0," results"]}),(0,t.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,t.jsxs)("span",{className:"text-sm text-gray-700 min-w-[90px]",children:["Page ",eT.isLoading?"...":k," of"," ",eT.isLoading?"...":eO?eO.total_pages:1]}),(0,t.jsx)("button",{onClick:()=>S(e=>Math.max(1,e-1)),disabled:eT.isLoading||1===k,className:"px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",children:"Previous"}),(0,t.jsx)("button",{onClick:()=>S(e=>Math.min(eO.total_pages||1,e+1)),disabled:eT.isLoading||k===(eO.total_pages||1),className:"px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",children:"Next"})]})]})]})}),eL&&1===k&&(0,t.jsxs)("div",{className:"mb-4 px-4 py-2 bg-green-50 border border-greem-200 rounded-md flex items-center justify-between",children:[(0,t.jsx)("div",{className:"flex items-center gap-2",children:(0,t.jsx)("span",{className:"text-sm text-green-700",children:"Auto-refreshing every 15 seconds"})}),(0,t.jsx)("button",{onClick:()=>eD(!1),className:"text-sm text-green-600 hover:text-green-800",children:"Stop"})]}),(0,t.jsx)(c.w,{columns:v,data:eq,renderSubComponent:eU,getRowCanExpand:()=>!0})]})]})]}),(0,t.jsx)(ev.Z,{children:(0,t.jsx)(ew,{userID:h,userRole:u,token:x,accessToken:m,isActive:"audit logs"===ed,premiumUser:p,allTeams:g})}),(0,t.jsx)(ev.Z,{children:(0,t.jsx)(eR,{})}),(0,t.jsx)(ev.Z,{children:(0,t.jsx)(eY,{})})]})]})})}function eU(e){var s,a,l,r,n,i,d,o,c,x,u,g;let{row:p}=e,j=e=>{if("string"==typeof e)try{return JSON.parse(e)}catch(e){}return e},f=p.original.metadata||{},v="failure"===f.status,y=v?f.error_information:null,b=p.original.messages&&(Array.isArray(p.original.messages)?p.original.messages.length>0:Object.keys(p.original.messages).length>0),N=p.original.response&&Object.keys(j(p.original.response)).length>0,w=f.vector_store_request_metadata&&Array.isArray(f.vector_store_request_metadata)&&f.vector_store_request_metadata.length>0,_=null===(s=p.original.metadata)||void 0===s?void 0:s.guardrail_information,C=Array.isArray(_)?_:_?[_]:[],D=C.length>0,M=C.reduce((e,s)=>{let a=null==s?void 0:s.masked_entity_count;return a?e+Object.values(a).reduce((e,s)=>"number"==typeof s?e+s:e,0):e},0),E=1===C.length?null!==(g=null===(a=C[0])||void 0===a?void 0:a.guardrail_name)&&void 0!==g?g:"-":C.length>1?"".concat(C.length," guardrails"):"-",T=(0,ek.aS)(p.original.request_id,64);return(0,t.jsxs)("div",{className:"p-6 bg-gray-50 space-y-6 w-full max-w-full overflow-hidden box-border",children:[(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow w-full max-w-full overflow-hidden",children:[(0,t.jsx)("div",{className:"p-4 border-b",children:(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Request Details"})}),(0,t.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4 p-4 w-full max-w-full overflow-hidden",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Request ID:"}),p.original.request_id.length>64?(0,t.jsx)(h.Z,{title:p.original.request_id,children:(0,t.jsx)("span",{className:"font-mono text-sm",children:T})}):(0,t.jsx)("span",{className:"font-mono text-sm",children:p.original.request_id})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Model:"}),(0,t.jsx)("span",{children:p.original.model})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Model ID:"}),(0,t.jsx)("span",{children:p.original.model_id})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Call Type:"}),(0,t.jsx)("span",{children:p.original.call_type})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Provider:"}),(0,t.jsx)("span",{children:p.original.custom_llm_provider||"-"})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"API Base:"}),(0,t.jsx)(h.Z,{title:p.original.api_base||"-",children:(0,t.jsx)("span",{className:"max-w-[15ch] truncate block",children:p.original.api_base||"-"})})]}),(null==p?void 0:null===(l=p.original)||void 0===l?void 0:l.requester_ip_address)&&(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"IP Address:"}),(0,t.jsx)("span",{children:null==p?void 0:null===(r=p.original)||void 0===r?void 0:r.requester_ip_address})]}),D&&(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Guardrail:"}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"font-mono",children:E}),M>0&&(0,t.jsxs)("span",{className:"ml-2 px-2 py-0.5 bg-blue-50 text-blue-700 rounded-md text-xs font-medium",children:[M," masked"]})]})]})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Tokens:"}),(0,t.jsxs)("span",{children:[p.original.total_tokens," (",p.original.prompt_tokens," prompt tokens +"," ",p.original.completion_tokens," completion tokens)"]})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Cache Read Tokens:"}),(0,t.jsx)("span",{children:(0,m.pw)((null===(i=p.original.metadata)||void 0===i?void 0:null===(n=i.additional_usage_values)||void 0===n?void 0:n.cache_read_input_tokens)||0)})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Cache Creation Tokens:"}),(0,t.jsx)("span",{children:(0,m.pw)(null===(d=p.original.metadata)||void 0===d?void 0:d.additional_usage_values.cache_creation_input_tokens)})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Cost:"}),(0,t.jsxs)("span",{children:["$",(0,m.pw)(p.original.spend||0,6)]})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Cache Hit:"}),(0,t.jsx)("span",{children:p.original.cache_hit})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Status:"}),(0,t.jsx)("span",{className:"px-2 py-1 rounded-md text-xs font-medium inline-block text-center w-16 ".concat("failure"!==((null===(o=p.original.metadata)||void 0===o?void 0:o.status)||"Success").toLowerCase()?"bg-green-100 text-green-800":"bg-red-100 text-red-800"),children:"failure"!==((null===(c=p.original.metadata)||void 0===c?void 0:c.status)||"Success").toLowerCase()?"Success":"Failure"})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Start Time:"}),(0,t.jsx)("span",{children:p.original.startTime})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"End Time:"}),(0,t.jsx)("span",{children:p.original.endTime})]}),(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"Duration:"}),(0,t.jsxs)("span",{children:[p.original.duration," s."]})]}),(null===(x=p.original.metadata)||void 0===x?void 0:x.litellm_overhead_time_ms)!==void 0&&(0,t.jsxs)("div",{className:"flex",children:[(0,t.jsx)("span",{className:"font-medium w-1/3",children:"LiteLLM Overhead:"}),(0,t.jsxs)("span",{children:[p.original.metadata.litellm_overhead_time_ms," ms"]})]})]})]})]}),(0,t.jsx)(ed,{costBreakdown:null===(u=p.original.metadata)||void 0===u?void 0:u.cost_breakdown,totalSpend:p.original.spend||0}),(0,t.jsx)(L,{show:!b&&!N}),(0,t.jsx)("div",{className:"w-full max-w-full overflow-hidden",children:(0,t.jsx)(k,{row:p,hasMessages:b,hasResponse:N,hasError:v,errorInfo:y,getRawRequest:()=>{var e;return(null===(e=p.original)||void 0===e?void 0:e.proxy_server_request)?j(p.original.proxy_server_request):j(p.original.messages)},formattedResponse:()=>v&&y?{error:{message:y.error_message||"An error occurred",type:y.error_class||"error",code:y.error_code||"unknown",param:null}}:j(p.original.response)})}),D&&(0,t.jsx)(ea,{data:_}),w&&(0,t.jsx)(K,{data:f.vector_store_request_metadata}),v&&y&&(0,t.jsx)(S,{errorInfo:y}),p.original.request_tags&&Object.keys(p.original.request_tags).length>0&&(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow",children:[(0,t.jsx)("div",{className:"flex justify-between items-center p-4 border-b",children:(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Request Tags"})}),(0,t.jsx)("div",{className:"p-4",children:(0,t.jsx)("div",{className:"flex flex-wrap gap-2",children:Object.entries(p.original.request_tags).map(e=>{let[s,a]=e;return(0,t.jsxs)("span",{className:"px-2 py-1 bg-gray-100 rounded-full text-xs",children:[s,": ",String(a)]},s)})})})]}),p.original.metadata&&Object.keys(p.original.metadata).length>0&&(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center p-4 border-b",children:[(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Metadata"}),(0,t.jsx)("button",{onClick:()=>{navigator.clipboard.writeText(JSON.stringify(p.original.metadata,null,2))},className:"p-1 hover:bg-gray-200 rounded",title:"Copy metadata",children:(0,t.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),(0,t.jsx)("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})]}),(0,t.jsx)("div",{className:"p-4 overflow-auto max-h-64",children:(0,t.jsx)("pre",{className:"text-xs font-mono whitespace-pre-wrap break-all",children:JSON.stringify(p.original.metadata,null,2)})})]})]})}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/2318-8bec43289448e95d.js b/litellm/proxy/_experimental/out/_next/static/chunks/2318-8bec43289448e95d.js new file mode 100644 index 00000000000..5d5774da27e --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/2318-8bec43289448e95d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2318],{88913:function(e,s,l){l.d(s,{Dx:function(){return d.Z},Zb:function(){return a.Z},iz:function(){return i.Z},oi:function(){return n.Z},xv:function(){return r.Z},zx:function(){return t.Z}});var t=l(78489),a=l(12514),i=l(67982),r=l(84264),n=l(49566),d=l(96761)},42318:function(e,s,l){l.d(s,{Z:function(){return eI}});var t=l(57437),a=l(58643),i=l(2265),r=l(16312),n=l(57840),d=l(42264),o=l(22116),c=l(4156),u=l(56609),m=l(23496),x=l(5945),h=l(58760),g=l(37592),v=l(12221),j=l(19250),p=l(10032),f=l(99981),y=l(24199),_=l(57365),b=l(49566),N=l(16853),S=l(46468),Z=l(20347),w=l(15424),k=l(65925);function C(e){let{userData:s,onCancel:l,onSubmit:a,teams:n,accessToken:d,userID:o,userRole:c,userModels:u,possibleUIRoles:m,isBulkEdit:x=!1}=e,[h]=p.Z.useForm();return i.useEffect(()=>{var e,l,t,a,i,r,n;h.setFieldsValue({user_id:s.user_id,user_email:null===(e=s.user_info)||void 0===e?void 0:e.user_email,user_alias:null===(l=s.user_info)||void 0===l?void 0:l.user_alias,user_role:null===(t=s.user_info)||void 0===t?void 0:t.user_role,models:(null===(a=s.user_info)||void 0===a?void 0:a.models)||[],max_budget:null===(i=s.user_info)||void 0===i?void 0:i.max_budget,budget_duration:null===(r=s.user_info)||void 0===r?void 0:r.budget_duration,metadata:(null===(n=s.user_info)||void 0===n?void 0:n.metadata)?JSON.stringify(s.user_info.metadata,null,2):void 0})},[s,h]),(0,t.jsxs)(p.Z,{form:h,onFinish:e=>{if(e.metadata&&"string"==typeof e.metadata)try{e.metadata=JSON.parse(e.metadata)}catch(e){console.error("Error parsing metadata JSON:",e);return}a(e)},layout:"vertical",children:[!x&&(0,t.jsx)(p.Z.Item,{label:"User ID",name:"user_id",children:(0,t.jsx)(b.Z,{disabled:!0})}),!x&&(0,t.jsx)(p.Z.Item,{label:"Email",name:"user_email",children:(0,t.jsx)(b.Z,{})}),(0,t.jsx)(p.Z.Item,{label:"User Alias",name:"user_alias",children:(0,t.jsx)(b.Z,{})}),(0,t.jsx)(p.Z.Item,{label:(0,t.jsxs)("span",{children:["Global Proxy Role"," ",(0,t.jsx)(f.Z,{title:"This is the role that the user will globally on the proxy. This role is independent of any team/org specific roles.",children:(0,t.jsx)(w.Z,{})})]}),name:"user_role",children:(0,t.jsx)(g.default,{children:m&&Object.entries(m).map(e=>{let[s,{ui_label:l,description:a}]=e;return(0,t.jsx)(_.Z,{value:s,title:l,children:(0,t.jsxs)("div",{className:"flex",children:[l," ",(0,t.jsx)("p",{className:"ml-2",style:{color:"gray",fontSize:"12px"},children:a})]})},s)})})}),(0,t.jsx)(p.Z.Item,{label:(0,t.jsxs)("span",{children:["Personal Models"," ",(0,t.jsx)(f.Z,{title:"Select which models this user can access outside of team-scope. Choose 'All Proxy Models' to grant access to all models available on the proxy.",children:(0,t.jsx)(w.Z,{style:{marginLeft:"4px"}})})]}),name:"models",children:(0,t.jsxs)(g.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},disabled:!Z.ZL.includes(c||""),children:[(0,t.jsx)(g.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),(0,t.jsx)(g.default.Option,{value:"no-default-models",children:"No Default Models"},"no-default-models"),u.map(e=>(0,t.jsx)(g.default.Option,{value:e,children:(0,S.W0)(e)},e))]})}),(0,t.jsx)(p.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,t.jsx)(y.Z,{step:.01,precision:2,style:{width:"100%"}})}),(0,t.jsx)(p.Z.Item,{label:"Reset Budget",name:"budget_duration",children:(0,t.jsx)(k.Z,{})}),(0,t.jsx)(p.Z.Item,{label:"Metadata",name:"metadata",children:(0,t.jsx)(N.Z,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,t.jsxs)("div",{className:"flex justify-end space-x-2",children:[(0,t.jsx)(r.z,{variant:"secondary",type:"button",onClick:l,children:"Cancel"}),(0,t.jsx)(r.z,{type:"submit",children:"Save Changes"})]})]})}var U=l(9114);let{Text:I,Title:D}=n.default;var z=e=>{let{open:s,onCancel:l,selectedUsers:a,possibleUIRoles:r,accessToken:n,onSuccess:p,teams:f,userRole:y,userModels:_,allowAllUsers:b=!1}=e,[N,S]=(0,i.useState)(!1),[Z,w]=(0,i.useState)([]),[k,z]=(0,i.useState)(null),[A,B]=(0,i.useState)(!1),[E,T]=(0,i.useState)(!1),O=()=>{w([]),z(null),B(!1),T(!1),l()},L=i.useMemo(()=>({user_id:"bulk_edit",user_info:{user_email:"",user_role:"",teams:[],models:[],max_budget:null,spend:0,metadata:{},created_at:null,updated_at:null},keys:[],teams:f||[]}),[f,s]),F=async e=>{if(console.log("formValues",e),!n){U.Z.fromBackend("Access token not found");return}S(!0);try{let s=a.map(e=>e.user_id),t={};e.user_role&&""!==e.user_role&&(t.user_role=e.user_role),null!==e.max_budget&&void 0!==e.max_budget&&(t.max_budget=e.max_budget),e.models&&e.models.length>0&&(t.models=e.models),e.budget_duration&&""!==e.budget_duration&&(t.budget_duration=e.budget_duration),e.metadata&&Object.keys(e.metadata).length>0&&(t.metadata=e.metadata);let i=Object.keys(t).length>0,r=A&&Z.length>0;if(!i&&!r){U.Z.fromBackend("Please modify at least one field or select teams to add users to");return}let o=[];if(i){if(E){let e=await (0,j.userBulkUpdateUserCall)(n,t,void 0,!0);o.push("Updated all users (".concat(e.total_requested," total)"))}else await (0,j.userBulkUpdateUserCall)(n,t,s),o.push("Updated ".concat(s.length," user(s)"))}if(r){let e=[];for(let s of Z)try{let l=null;l=E?null:a.map(e=>({user_id:e.user_id,role:"user",user_email:e.user_email||null}));let t=await (0,j.teamBulkMemberAddCall)(n,s,l||null,k||void 0,E);console.log("result",t),e.push({teamId:s,success:!0,successfulAdditions:t.successful_additions,failedAdditions:t.failed_additions})}catch(l){console.error("Failed to add users to team ".concat(s,":"),l),e.push({teamId:s,success:!1,error:l})}let s=e.filter(e=>e.success),l=e.filter(e=>!e.success);if(s.length>0){let e=s.reduce((e,s)=>e+s.successfulAdditions,0);o.push("Added users to ".concat(s.length," team(s) (").concat(e," total additions)"))}l.length>0&&d.ZP.warning("Failed to add users to ".concat(l.length," team(s)"))}o.length>0&&U.Z.success(o.join(". ")),w([]),z(null),B(!1),T(!1),p(),l()}catch(e){console.error("Bulk operation failed:",e),U.Z.fromBackend("Failed to perform bulk operations")}finally{S(!1)}};return(0,t.jsxs)(o.Z,{open:s,onCancel:O,footer:null,title:E?"Bulk Edit All Users":"Bulk Edit ".concat(a.length," User(s)"),width:800,children:[b&&(0,t.jsxs)("div",{className:"mb-4",children:[(0,t.jsx)(c.Z,{checked:E,onChange:e=>T(e.target.checked),children:(0,t.jsx)(I,{strong:!0,children:"Update ALL users in the system"})}),E&&(0,t.jsx)("div",{style:{marginTop:8},children:(0,t.jsx)(I,{type:"warning",style:{fontSize:"12px"},children:"āš ļø This will apply changes to ALL users in the system, not just the selected ones."})})]}),!E&&(0,t.jsxs)("div",{className:"mb-4",children:[(0,t.jsxs)(D,{level:5,children:["Selected Users (",a.length,"):"]}),(0,t.jsx)(u.Z,{size:"small",bordered:!0,dataSource:a,pagination:!1,scroll:{y:200},rowKey:"user_id",columns:[{title:"User ID",dataIndex:"user_id",key:"user_id",width:"30%",render:e=>(0,t.jsx)(I,{strong:!0,style:{fontSize:"12px"},children:e.length>20?"".concat(e.slice(0,20),"..."):e})},{title:"Email",dataIndex:"user_email",key:"user_email",width:"25%",render:e=>(0,t.jsx)(I,{type:"secondary",style:{fontSize:"12px"},children:e||"No email"})},{title:"Current Role",dataIndex:"user_role",key:"user_role",width:"25%",render:e=>{var s;return(0,t.jsx)(I,{style:{fontSize:"12px"},children:(null==r?void 0:null===(s=r[e])||void 0===s?void 0:s.ui_label)||e})}},{title:"Budget",dataIndex:"max_budget",key:"max_budget",width:"20%",render:e=>(0,t.jsx)(I,{style:{fontSize:"12px"},children:null!==e?"$".concat(e):"Unlimited"})}]})]}),(0,t.jsx)(m.Z,{}),(0,t.jsx)("div",{className:"mb-4",children:(0,t.jsxs)(I,{children:[(0,t.jsx)("strong",{children:"Instructions:"})," Fill in the fields below with the values you want to apply to all selected users. You can bulk edit: role, budget, models, and metadata. You can also add users to teams."]})}),(0,t.jsx)(x.Z,{title:"Team Management",size:"small",className:"mb-4",style:{backgroundColor:"#fafafa"},children:(0,t.jsxs)(h.Z,{direction:"vertical",style:{width:"100%"},children:[(0,t.jsx)(c.Z,{checked:A,onChange:e=>B(e.target.checked),children:"Add selected users to teams"}),A&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{children:[(0,t.jsx)(I,{strong:!0,children:"Select Teams:"}),(0,t.jsx)(g.default,{mode:"multiple",placeholder:"Select teams to add users to",value:Z,onChange:w,style:{width:"100%",marginTop:8},options:(null==f?void 0:f.map(e=>({label:e.team_alias||e.team_id,value:e.team_id})))||[]})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(I,{strong:!0,children:"Team Budget (Optional):"}),(0,t.jsx)(v.Z,{placeholder:"Max budget per user in team",value:k,onChange:e=>z(e),style:{width:"100%",marginTop:8},min:0,step:.01,precision:2}),(0,t.jsx)(I,{type:"secondary",style:{fontSize:"12px"},children:"Leave empty for unlimited budget within team limits"})]}),(0,t.jsx)(I,{type:"secondary",style:{fontSize:"12px"},children:'Users will be added with "user" role by default. All users will be added to each selected team.'})]})]})}),(0,t.jsx)(C,{userData:L,onCancel:O,onSubmit:F,teams:f,accessToken:n,userID:"bulk_edit",userRole:y,userModels:_,possibleUIRoles:r,isBulkEdit:!0}),N&&(0,t.jsx)("div",{style:{textAlign:"center",marginTop:"10px"},children:(0,t.jsxs)(I,{children:["Updating ",E?"all users":a.length," user(s)..."]})})]})},A=l(7765),B=l(5545),E=e=>{let{visible:s,possibleUIRoles:l,onCancel:a,user:r,onSubmit:n}=e,[d,c]=(0,i.useState)(r),[u]=p.Z.useForm();(0,i.useEffect)(()=>{u.resetFields()},[r]);let m=async()=>{u.resetFields(),a()},x=async e=>{n(e),u.resetFields(),a()};return r?(0,t.jsx)(o.Z,{visible:s,onCancel:m,footer:null,title:"Edit User "+r.user_id,width:1e3,children:(0,t.jsx)(p.Z,{form:u,onFinish:x,initialValues:r,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(p.Z.Item,{className:"mt-8",label:"User Email",tooltip:"Email of the User",name:"user_email",children:(0,t.jsx)(b.Z,{})}),(0,t.jsx)(p.Z.Item,{label:"user_id",name:"user_id",hidden:!0,children:(0,t.jsx)(b.Z,{})}),(0,t.jsx)(p.Z.Item,{label:"User Role",name:"user_role",children:(0,t.jsx)(g.default,{children:l&&Object.entries(l).map(e=>{let[s,{ui_label:l,description:a}]=e;return(0,t.jsx)(_.Z,{value:s,title:l,children:(0,t.jsxs)("div",{className:"flex",children:[l," ",(0,t.jsx)("p",{className:"ml-2",style:{color:"gray",fontSize:"12px"},children:a})]})},s)})})}),(0,t.jsx)(p.Z.Item,{label:"Spend (USD)",name:"spend",tooltip:"(float) - Spend of all LLM calls completed by this user",help:"Across all keys (including keys with team_id).",children:(0,t.jsx)(v.Z,{min:0,step:.01})}),(0,t.jsx)(p.Z.Item,{label:"User Budget (USD)",name:"max_budget",tooltip:"(float) - Maximum budget of this user",help:"Maximum budget of this user.",children:(0,t.jsx)(y.Z,{min:0,step:.01})}),(0,t.jsx)(p.Z.Item,{label:"Reset Budget",name:"budget_duration",children:(0,t.jsx)(k.Z,{})}),(0,t.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,t.jsx)(B.ZP,{htmlType:"submit",children:"Save"})}),(0,t.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,t.jsx)(B.ZP,{htmlType:"submit",children:"Save"})})]})})}):null},T=l(98187),O=l(59872),L=l(19616),F=l(29827),R=l(11713),P=l(21609),M=l(88913),K=l(63709),V=l(10353),q=l(26349),G=l(96473),J=e=>{var s;let{accessToken:l,possibleUIRoles:a,userID:r,userRole:d}=e,[o,c]=(0,i.useState)(!0),[u,m]=(0,i.useState)(null),[x,h]=(0,i.useState)(!1),[p,f]=(0,i.useState)({}),[y,_]=(0,i.useState)(!1),[b,N]=(0,i.useState)([]),{Paragraph:Z}=n.default,{Option:w}=g.default;(0,i.useEffect)(()=>{(async()=>{if(!l){c(!1);return}try{let e=await (0,j.getInternalUserSettings)(l);if(m(e),f(e.values||{}),l)try{let e=await (0,j.modelAvailableCall)(l,r,d);if(e&&e.data){let s=e.data.map(e=>e.id);N(s)}}catch(e){console.error("Error fetching available models:",e)}}catch(e){console.error("Error fetching SSO settings:",e),U.Z.fromBackend("Failed to fetch SSO settings")}finally{c(!1)}})()},[l]);let C=async()=>{if(l){_(!0);try{let e=Object.entries(p).reduce((e,s)=>{let[l,t]=s;return e[l]=""===t?null:t,e},{}),s=await (0,j.updateInternalUserSettings)(l,e);m({...u,values:s.settings}),h(!1)}catch(e){console.error("Error updating SSO settings:",e),U.Z.fromBackend("Failed to update settings: "+e)}finally{_(!1)}}},I=(e,s)=>{f(l=>({...l,[e]:s}))},D=e=>e&&Array.isArray(e)?e.map(e=>"string"==typeof e?{team_id:e,user_role:"user"}:"object"==typeof e&&e.team_id?{team_id:e.team_id,max_budget_in_team:e.max_budget_in_team,user_role:e.user_role||"user"}:{team_id:"",user_role:"user"}):[],z=e=>{let s=D(e),l=(e,l,t)=>{let a=[...s];a[e]={...a[e],[l]:t},I("teams",a)},a=e=>{I("teams",s.filter((s,l)=>l!==e))};return(0,t.jsxs)("div",{className:"space-y-3",children:[s.map((e,s)=>(0,t.jsxs)("div",{className:"border rounded-lg p-4 bg-gray-50",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,t.jsxs)(M.xv,{className:"font-medium",children:["Team ",s+1]}),(0,t.jsx)(M.zx,{size:"sm",variant:"secondary",icon:q.Z,onClick:()=>a(s),className:"text-red-500 hover:text-red-700",children:"Remove"})]}),(0,t.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-3",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)(M.xv,{className:"text-sm font-medium mb-1",children:"Team ID"}),(0,t.jsx)(M.oi,{value:e.team_id,onChange:e=>l(s,"team_id",e.target.value),placeholder:"Enter team ID"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(M.xv,{className:"text-sm font-medium mb-1",children:"Max Budget in Team"}),(0,t.jsx)(v.Z,{style:{width:"100%"},value:e.max_budget_in_team,onChange:e=>l(s,"max_budget_in_team",e),placeholder:"Optional",min:0,step:.01,precision:2})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(M.xv,{className:"text-sm font-medium mb-1",children:"User Role"}),(0,t.jsxs)(g.default,{style:{width:"100%"},value:e.user_role,onChange:e=>l(s,"user_role",e),children:[(0,t.jsx)(w,{value:"user",children:"User"}),(0,t.jsx)(w,{value:"admin",children:"Admin"})]})]})]})]},s)),(0,t.jsx)(M.zx,{variant:"secondary",icon:G.Z,onClick:()=>{I("teams",[...s,{team_id:"",user_role:"user"}])},className:"w-full",children:"Add Team"})]})},A=(e,s,l)=>{var i;let r=s.type;if("teams"===e)return(0,t.jsx)("div",{className:"mt-2",children:z(p[e]||[])});if("user_role"===e&&a)return(0,t.jsx)(g.default,{style:{width:"100%"},value:p[e]||"",onChange:s=>I(e,s),className:"mt-2",children:Object.entries(a).filter(e=>{let[s]=e;return s.includes("internal_user")}).map(e=>{let[s,{ui_label:l,description:a}]=e;return(0,t.jsx)(w,{value:s,children:(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)("span",{children:l}),(0,t.jsx)("span",{className:"ml-2 text-xs text-gray-500",children:a})]})},s)})});if("budget_duration"===e)return(0,t.jsx)(k.Z,{value:p[e]||null,onChange:s=>I(e,s),className:"mt-2"});if("boolean"===r)return(0,t.jsx)("div",{className:"mt-2",children:(0,t.jsx)(K.Z,{checked:!!p[e],onChange:s=>I(e,s)})});if("array"===r&&(null===(i=s.items)||void 0===i?void 0:i.enum))return(0,t.jsx)(g.default,{mode:"multiple",style:{width:"100%"},value:p[e]||[],onChange:s=>I(e,s),className:"mt-2",children:s.items.enum.map(e=>(0,t.jsx)(w,{value:e,children:e},e))});if("models"===e)return(0,t.jsxs)(g.default,{mode:"multiple",style:{width:"100%"},value:p[e]||[],onChange:s=>I(e,s),className:"mt-2",children:[(0,t.jsx)(w,{value:"no-default-models",children:"No Default Models"},"no-default-models"),(0,t.jsx)(w,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),b.map(e=>(0,t.jsx)(w,{value:e,children:(0,S.W0)(e)},e))]});if("string"===r&&s.enum)return(0,t.jsx)(g.default,{style:{width:"100%"},value:p[e]||"",onChange:s=>I(e,s),className:"mt-2",children:s.enum.map(e=>(0,t.jsx)(w,{value:e,children:e},e))});else return(0,t.jsx)(M.oi,{value:void 0!==p[e]?String(p[e]):"",onChange:s=>I(e,s.target.value),placeholder:s.description||"",className:"mt-2"})},B=(e,s)=>{if(null==s)return(0,t.jsx)("span",{className:"text-gray-400",children:"Not set"});if("teams"===e&&Array.isArray(s)){if(0===s.length)return(0,t.jsx)("span",{className:"text-gray-400",children:"No teams assigned"});let e=D(s);return(0,t.jsx)("div",{className:"space-y-2 mt-1",children:e.map((e,s)=>(0,t.jsx)("div",{className:"border rounded-lg p-3 bg-white",children:(0,t.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2 text-sm",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"font-medium text-gray-600",children:"Team ID:"}),(0,t.jsx)("p",{className:"text-gray-900",children:e.team_id||"Not specified"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"font-medium text-gray-600",children:"Max Budget:"}),(0,t.jsx)("p",{className:"text-gray-900",children:void 0!==e.max_budget_in_team?"$".concat((0,O.pw)(e.max_budget_in_team,4)):"No limit"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"font-medium text-gray-600",children:"Role:"}),(0,t.jsx)("p",{className:"text-gray-900 capitalize",children:e.user_role})]})]})},s))})}if("user_role"===e&&a&&a[s]){let{ui_label:e,description:l}=a[s];return(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"font-medium",children:e}),l&&(0,t.jsx)("p",{className:"text-xs text-gray-500 mt-1",children:l})]})}return"budget_duration"===e?(0,t.jsx)("span",{children:(0,k.m)(s)}):"boolean"==typeof s?(0,t.jsx)("span",{children:s?"Enabled":"Disabled"}):"models"===e&&Array.isArray(s)?0===s.length?(0,t.jsx)("span",{className:"text-gray-400",children:"None"}):(0,t.jsx)("div",{className:"flex flex-wrap gap-2 mt-1",children:s.map((e,s)=>(0,t.jsx)("span",{className:"px-2 py-1 bg-blue-100 rounded text-xs",children:(0,S.W0)(e)},s))}):"object"==typeof s?Array.isArray(s)?0===s.length?(0,t.jsx)("span",{className:"text-gray-400",children:"None"}):(0,t.jsx)("div",{className:"flex flex-wrap gap-2 mt-1",children:s.map((e,s)=>(0,t.jsx)("span",{className:"px-2 py-1 bg-blue-100 rounded text-xs",children:"object"==typeof e?JSON.stringify(e):String(e)},s))}):(0,t.jsx)("pre",{className:"bg-gray-100 p-2 rounded text-xs overflow-auto mt-1",children:JSON.stringify(s,null,2)}):(0,t.jsx)("span",{children:String(s)})};return o?(0,t.jsx)("div",{className:"flex justify-center items-center h-64",children:(0,t.jsx)(V.Z,{size:"large"})}):u?(0,t.jsxs)(M.Zb,{children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,t.jsx)(M.Dx,{children:"Default User Settings"}),!o&&u&&(x?(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(M.zx,{variant:"secondary",onClick:()=>{h(!1),f(u.values||{})},disabled:y,children:"Cancel"}),(0,t.jsx)(M.zx,{onClick:C,loading:y,children:"Save Changes"})]}):(0,t.jsx)(M.zx,{onClick:()=>h(!0),children:"Edit Settings"}))]}),(null==u?void 0:null===(s=u.field_schema)||void 0===s?void 0:s.description)&&(0,t.jsx)(Z,{className:"mb-4",children:u.field_schema.description}),(0,t.jsx)(M.iz,{}),(0,t.jsx)("div",{className:"mt-4 space-y-4",children:(()=>{let{values:e,field_schema:s}=u;return s&&s.properties?Object.entries(s.properties).map(s=>{let[l,a]=s,i=e[l],r=l.replace(/_/g," ").replace(/\b\w/g,e=>e.toUpperCase());return(0,t.jsxs)("div",{className:"mb-6 pb-6 border-b border-gray-200 last:border-0",children:[(0,t.jsx)(M.xv,{className:"font-medium text-lg",children:r}),(0,t.jsx)(Z,{className:"text-sm text-gray-500 mt-1",children:a.description||"No description available"}),x?(0,t.jsx)("div",{className:"mt-2",children:A(l,a,i)}):(0,t.jsx)("div",{className:"mt-1 p-2 bg-gray-50 rounded",children:B(l,i)})]},l)}):(0,t.jsx)(M.xv,{children:"No schema information available"})})()})]}):(0,t.jsx)(M.Zb,{children:(0,t.jsx)(M.xv,{children:"No settings available or you do not have permission to view them."})})},Q=l(41649),H=l(67101),$=l(47323),W=l(15731),Y=l(53410),X=l(74998),ee=l(23628);let es=(e,s,l,a,i,r)=>{let n=[{header:"User ID",accessorKey:"user_id",enableSorting:!0,cell:e=>{let{row:s}=e;return(0,t.jsx)(f.Z,{title:s.original.user_id,children:(0,t.jsx)("span",{className:"text-xs",children:s.original.user_id?"".concat(s.original.user_id.slice(0,7),"..."):"-"})})}},{header:"Email",accessorKey:"user_email",enableSorting:!0,cell:e=>{let{row:s}=e;return(0,t.jsx)("span",{className:"text-xs",children:s.original.user_email||"-"})}},{header:"Global Proxy Role",accessorKey:"user_role",enableSorting:!0,cell:s=>{var l;let{row:a}=s;return(0,t.jsx)("span",{className:"text-xs",children:(null==e?void 0:null===(l=e[a.original.user_role])||void 0===l?void 0:l.ui_label)||"-"})}},{header:"User Alias",accessorKey:"user_alias",enableSorting:!1,cell:e=>{let{row:s}=e;return(0,t.jsx)("span",{className:"text-xs",children:s.original.user_alias||"-"})}},{header:"Spend (USD)",accessorKey:"spend",enableSorting:!0,cell:e=>{let{row:s}=e;return(0,t.jsx)("span",{className:"text-xs",children:s.original.spend?(0,O.pw)(s.original.spend,4):"-"})}},{header:"Budget (USD)",accessorKey:"max_budget",enableSorting:!1,cell:e=>{let{row:s}=e;return(0,t.jsx)("span",{className:"text-xs",children:null!==s.original.max_budget?s.original.max_budget:"Unlimited"})}},{header:()=>(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{children:"SSO ID"}),(0,t.jsx)(f.Z,{title:"SSO ID is the ID of the user in the SSO provider. If the user is not using SSO, this will be null.",children:(0,t.jsx)(W.Z,{className:"w-4 h-4"})})]}),accessorKey:"sso_user_id",enableSorting:!1,cell:e=>{let{row:s}=e;return(0,t.jsx)("span",{className:"text-xs",children:null!==s.original.sso_user_id?s.original.sso_user_id:"-"})}},{header:"Virtual Keys",accessorKey:"key_count",enableSorting:!1,cell:e=>{let{row:s}=e;return(0,t.jsx)(H.Z,{numItems:2,children:s.original.key_count>0?(0,t.jsxs)(Q.Z,{size:"xs",color:"indigo",children:[s.original.key_count," ",1===s.original.key_count?"Key":"Keys"]}):(0,t.jsx)(Q.Z,{size:"xs",color:"gray",children:"No Keys"})})}},{header:"Created At",accessorKey:"created_at",enableSorting:!0,cell:e=>{let{row:s}=e;return(0,t.jsx)("span",{className:"text-xs",children:s.original.created_at?new Date(s.original.created_at).toLocaleDateString():"-"})}},{header:"Updated At",accessorKey:"updated_at",enableSorting:!1,cell:e=>{let{row:s}=e;return(0,t.jsx)("span",{className:"text-xs",children:s.original.updated_at?new Date(s.original.updated_at).toLocaleDateString():"-"})}},{id:"actions",header:"Actions",enableSorting:!1,cell:e=>{let{row:s}=e;return(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(f.Z,{title:"Edit user details",children:(0,t.jsx)($.Z,{icon:Y.Z,size:"sm",onClick:()=>i(s.original.user_id,!0),className:"cursor-pointer hover:text-blue-600"})}),(0,t.jsx)(f.Z,{title:"Delete user",children:(0,t.jsx)($.Z,{icon:X.Z,size:"sm",onClick:()=>l(s.original),className:"cursor-pointer hover:text-red-600"})}),(0,t.jsx)(f.Z,{title:"Reset Password",children:(0,t.jsx)($.Z,{icon:ee.Z,size:"sm",onClick:()=>a(s.original.user_id),className:"cursor-pointer hover:text-green-600"})})]})}}];if(r){let{onSelectUser:e,onSelectAll:s,isUserSelected:l,isAllSelected:a,isIndeterminate:i}=r;return[{id:"select",enableSorting:!1,header:()=>(0,t.jsx)(c.Z,{indeterminate:i,checked:a,onChange:e=>s(e.target.checked),onClick:e=>e.stopPropagation()}),cell:s=>{let{row:a}=s;return(0,t.jsx)(c.Z,{checked:l(a.original),onChange:s=>e(a.original,s.target.checked),onClick:e=>e.stopPropagation()})}},...n]}return n};var el=l(71594),et=l(24525),ea=l(27281),ei=l(21626),er=l(97214),en=l(28241),ed=l(58834),eo=l(69552),ec=l(71876),eu=l(44633),em=l(86462),ex=l(49084),eh=l(50337),eg=l(84717),ev=l(10900),ej=l(30401),ep=l(78867);function ef(e){var s,l,a,r,n,d,o,c,u,m,x,h,g,v,p,f,y,_,b,N,S,w,I,D,z,A,E,L,F,R,M,K,V,q,G,J,Q,H,$,W,Y,es,el,et,ea;let{userId:ei,onClose:er,accessToken:en,userRole:ed,onDelete:eo,possibleUIRoles:ec,initialTab:eu=0,startInEditMode:em=!1}=e,[ex,eh]=(0,i.useState)(null),[ef,ey]=(0,i.useState)(!1),[e_,eb]=(0,i.useState)(!1),[eN,eS]=(0,i.useState)(!0),[eZ,ew]=(0,i.useState)(em),[ek,eC]=(0,i.useState)([]),[eU,eI]=(0,i.useState)(!1),[eD,ez]=(0,i.useState)(null),[eA,eB]=(0,i.useState)(null),[eE,eT]=(0,i.useState)(eu),[eO,eL]=(0,i.useState)({}),[eF,eR]=(0,i.useState)(!1);i.useEffect(()=>{eB((0,j.getProxyBaseUrl)())},[]),i.useEffect(()=>{console.log("userId: ".concat(ei,", userRole: ").concat(ed,", accessToken: ").concat(en)),(async()=>{try{if(!en)return;let e=await (0,j.userInfoCall)(en,ei,ed||"",!1,null,null,!0);eh(e);let s=(await (0,j.modelAvailableCall)(en,ei,ed||"")).data.map(e=>e.id);eC(s)}catch(e){console.error("Error fetching user data:",e),U.Z.fromBackend("Failed to fetch user data")}finally{eS(!1)}})()},[en,ei,ed]);let eP=async()=>{if(!en){U.Z.fromBackend("Access token not found");return}try{U.Z.success("Generating password reset link...");let e=await (0,j.invitationCreateCall)(en,ei);ez(e),eI(!0)}catch(e){U.Z.fromBackend("Failed to generate password reset link")}},eM=async()=>{try{if(!en)return;eb(!0),await (0,j.userDeleteCall)(en,[ei]),U.Z.success("User deleted successfully"),eo&&eo(),er()}catch(e){console.error("Error deleting user:",e),U.Z.fromBackend("Failed to delete user")}finally{ey(!1),eb(!1)}},eK=async e=>{try{if(!en||!ex)return;await (0,j.userUpdateUserCall)(en,e,null),eh({...ex,user_info:{...ex.user_info,user_email:e.user_email,user_alias:e.user_alias,models:e.models,max_budget:e.max_budget,budget_duration:e.budget_duration,metadata:e.metadata}}),U.Z.success("User updated successfully"),ew(!1)}catch(e){console.error("Error updating user:",e),U.Z.fromBackend("Failed to update user")}};if(eN)return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsx)(eg.zx,{icon:ev.Z,variant:"light",onClick:er,className:"mb-4",children:"Back to Users"}),(0,t.jsx)(eg.xv,{children:"Loading user data..."})]});if(!ex)return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsx)(eg.zx,{icon:ev.Z,variant:"light",onClick:er,className:"mb-4",children:"Back to Users"}),(0,t.jsx)(eg.xv,{children:"User not found"})]});let eV=async(e,s)=>{await (0,O.vQ)(e)&&(eL(e=>({...e,[s]:!0})),setTimeout(()=>{eL(e=>({...e,[s]:!1}))},2e3))};return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-6",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.zx,{icon:ev.Z,variant:"light",onClick:er,className:"mb-4",children:"Back to Users"}),(0,t.jsx)(eg.Dx,{children:(null===(s=ex.user_info)||void 0===s?void 0:s.user_email)||"User"}),(0,t.jsxs)("div",{className:"flex items-center cursor-pointer",children:[(0,t.jsx)(eg.xv,{className:"text-gray-500 font-mono",children:ex.user_id}),(0,t.jsx)(B.ZP,{type:"text",size:"small",icon:eO["user-id"]?(0,t.jsx)(ej.Z,{size:12}):(0,t.jsx)(ep.Z,{size:12}),onClick:()=>eV(ex.user_id,"user-id"),className:"left-2 z-10 transition-all duration-200 ".concat(eO["user-id"]?"text-green-600 bg-green-50 border-green-200":"text-gray-500 hover:text-gray-700 hover:bg-gray-100")})]})]}),ed&&Z.LQ.includes(ed)&&(0,t.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,t.jsx)(eg.zx,{icon:ee.Z,variant:"secondary",onClick:eP,className:"flex items-center",children:"Reset Password"}),(0,t.jsx)(eg.zx,{icon:X.Z,variant:"secondary",onClick:()=>ey(!0),className:"flex items-center text-red-500 border-red-500 hover:text-red-600 hover:border-red-600",children:"Delete User"})]})]}),(0,t.jsx)(P.Z,{isOpen:ef,title:"Delete User?",message:"Are you sure you want to delete this user? This action cannot be undone.",resourceInformationTitle:"User Information",resourceInformation:[{label:"Email",value:null===(l=ex.user_info)||void 0===l?void 0:l.user_email},{label:"User ID",value:ex.user_id,code:!0},{label:"Global Proxy Role",value:(null===(a=ex.user_info)||void 0===a?void 0:a.user_role)&&(null==ec?void 0:null===(r=ec[ex.user_info.user_role])||void 0===r?void 0:r.ui_label)||(null===(n=ex.user_info)||void 0===n?void 0:n.user_role)||"-"},{label:"Total Spend (USD)",value:(null===(d=ex.user_info)||void 0===d?void 0:d.spend)!==null&&(null===(o=ex.user_info)||void 0===o?void 0:o.spend)!==void 0?ex.user_info.spend.toFixed(2):void 0}],onCancel:()=>{ey(!1)},onOk:eM,confirmLoading:e_}),(0,t.jsxs)(eg.v0,{defaultIndex:eE,onIndexChange:eT,children:[(0,t.jsxs)(eg.td,{className:"mb-4",children:[(0,t.jsx)(eg.OK,{children:"Overview"}),(0,t.jsx)(eg.OK,{children:"Details"})]}),(0,t.jsxs)(eg.nP,{children:[(0,t.jsx)(eg.x4,{children:(0,t.jsxs)(eg.rj,{numItems:1,numItemsSm:2,numItemsLg:3,className:"gap-6",children:[(0,t.jsxs)(eg.Zb,{children:[(0,t.jsx)(eg.xv,{children:"Spend"}),(0,t.jsxs)("div",{className:"mt-2",children:[(0,t.jsxs)(eg.Dx,{children:["$",(0,O.pw)((null===(c=ex.user_info)||void 0===c?void 0:c.spend)||0,4)]}),(0,t.jsxs)(eg.xv,{children:["of"," ",(null===(u=ex.user_info)||void 0===u?void 0:u.max_budget)!==null?"$".concat((0,O.pw)(ex.user_info.max_budget,4)):"Unlimited"]})]})]}),(0,t.jsxs)(eg.Zb,{children:[(0,t.jsx)(eg.xv,{children:"Teams"}),(0,t.jsx)("div",{className:"mt-2",children:(null===(m=ex.teams)||void 0===m?void 0:m.length)&&(null===(x=ex.teams)||void 0===x?void 0:x.length)>0?(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[null===(h=ex.teams)||void 0===h?void 0:h.slice(0,eF?ex.teams.length:20).map((e,s)=>(0,t.jsx)(eg.Ct,{color:"blue",title:e.team_alias,children:e.team_alias},s)),!eF&&(null===(g=ex.teams)||void 0===g?void 0:g.length)>20&&(0,t.jsxs)(eg.Ct,{color:"gray",className:"cursor-pointer hover:bg-gray-200 transition-colors",onClick:()=>eR(!0),children:["+",ex.teams.length-20," more"]}),eF&&(null===(v=ex.teams)||void 0===v?void 0:v.length)>20&&(0,t.jsx)(eg.Ct,{color:"gray",className:"cursor-pointer hover:bg-gray-200 transition-colors",onClick:()=>eR(!1),children:"Show Less"})]}):(0,t.jsx)(eg.xv,{children:"No teams"})})]}),(0,t.jsxs)(eg.Zb,{children:[(0,t.jsx)(eg.xv,{children:"Virtual Keys"}),(0,t.jsx)("div",{className:"mt-2",children:(0,t.jsxs)(eg.xv,{children:[(null===(p=ex.keys)||void 0===p?void 0:p.length)||0," ",(null===(f=ex.keys)||void 0===f?void 0:f.length)===1?"Key":"Keys"]})})]}),(0,t.jsxs)(eg.Zb,{children:[(0,t.jsx)(eg.xv,{children:"Personal Models"}),(0,t.jsx)("div",{className:"mt-2",children:(null===(_=ex.user_info)||void 0===_?void 0:null===(y=_.models)||void 0===y?void 0:y.length)&&(null===(N=ex.user_info)||void 0===N?void 0:null===(b=N.models)||void 0===b?void 0:b.length)>0?null===(w=ex.user_info)||void 0===w?void 0:null===(S=w.models)||void 0===S?void 0:S.map((e,s)=>(0,t.jsx)(eg.xv,{children:e},s)):(0,t.jsx)(eg.xv,{children:"All proxy models"})})]})]})}),(0,t.jsx)(eg.x4,{children:(0,t.jsxs)(eg.Zb,{children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,t.jsx)(eg.Dx,{children:"User Settings"}),!eZ&&ed&&Z.LQ.includes(ed)&&(0,t.jsx)(eg.zx,{onClick:()=>ew(!0),children:"Edit Settings"})]}),eZ&&ex?(0,t.jsx)(C,{userData:ex,onCancel:()=>ew(!1),onSubmit:eK,teams:ex.teams,accessToken:en,userID:ei,userRole:ed,userModels:ek,possibleUIRoles:ec}):(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"User ID"}),(0,t.jsxs)("div",{className:"flex items-center cursor-pointer",children:[(0,t.jsx)(eg.xv,{className:"font-mono",children:ex.user_id}),(0,t.jsx)(B.ZP,{type:"text",size:"small",icon:eO["user-id"]?(0,t.jsx)(ej.Z,{size:12}):(0,t.jsx)(ep.Z,{size:12}),onClick:()=>eV(ex.user_id,"user-id"),className:"left-2 z-10 transition-all duration-200 ".concat(eO["user-id"]?"text-green-600 bg-green-50 border-green-200":"text-gray-500 hover:text-gray-700 hover:bg-gray-100")})]})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Email"}),(0,t.jsx)(eg.xv,{children:(null===(I=ex.user_info)||void 0===I?void 0:I.user_email)||"Not Set"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"User Alias"}),(0,t.jsx)(eg.xv,{children:(null===(D=ex.user_info)||void 0===D?void 0:D.user_alias)||"Not Set"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Global Proxy Role"}),(0,t.jsx)(eg.xv,{children:(null===(z=ex.user_info)||void 0===z?void 0:z.user_role)||"Not Set"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Created"}),(0,t.jsx)(eg.xv,{children:(null===(A=ex.user_info)||void 0===A?void 0:A.created_at)?new Date(ex.user_info.created_at).toLocaleString():"Unknown"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Last Updated"}),(0,t.jsx)(eg.xv,{children:(null===(E=ex.user_info)||void 0===E?void 0:E.updated_at)?new Date(ex.user_info.updated_at).toLocaleString():"Unknown"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Teams"}),(0,t.jsx)("div",{className:"flex flex-wrap gap-2 mt-1",children:(null===(L=ex.teams)||void 0===L?void 0:L.length)&&(null===(F=ex.teams)||void 0===F?void 0:F.length)>0?(0,t.jsxs)(t.Fragment,{children:[null===(R=ex.teams)||void 0===R?void 0:R.slice(0,eF?ex.teams.length:20).map((e,s)=>(0,t.jsx)("span",{className:"px-2 py-1 bg-blue-100 rounded text-xs",title:e.team_alias||e.team_id,children:e.team_alias||e.team_id},s)),!eF&&(null===(M=ex.teams)||void 0===M?void 0:M.length)>20&&(0,t.jsxs)("span",{className:"px-2 py-1 bg-gray-100 rounded text-xs cursor-pointer hover:bg-gray-200 transition-colors",onClick:()=>eR(!0),children:["+",ex.teams.length-20," more"]}),eF&&(null===(K=ex.teams)||void 0===K?void 0:K.length)>20&&(0,t.jsx)("span",{className:"px-2 py-1 bg-gray-100 rounded text-xs cursor-pointer hover:bg-gray-200 transition-colors",onClick:()=>eR(!1),children:"Show Less"})]}):(0,t.jsx)(eg.xv,{children:"No teams"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Personal Models"}),(0,t.jsx)("div",{className:"flex flex-wrap gap-2 mt-1",children:(null===(q=ex.user_info)||void 0===q?void 0:null===(V=q.models)||void 0===V?void 0:V.length)&&(null===(J=ex.user_info)||void 0===J?void 0:null===(G=J.models)||void 0===G?void 0:G.length)>0?null===(H=ex.user_info)||void 0===H?void 0:null===(Q=H.models)||void 0===Q?void 0:Q.map((e,s)=>(0,t.jsx)("span",{className:"px-2 py-1 bg-blue-100 rounded text-xs",children:e},s)):(0,t.jsx)(eg.xv,{children:"All proxy models"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Virtual Keys"}),(0,t.jsx)("div",{className:"flex flex-wrap gap-2 mt-1",children:(null===($=ex.keys)||void 0===$?void 0:$.length)&&(null===(W=ex.keys)||void 0===W?void 0:W.length)>0?ex.keys.map((e,s)=>(0,t.jsx)("span",{className:"px-2 py-1 bg-green-100 rounded text-xs",children:e.key_alias||e.token},s)):(0,t.jsx)(eg.xv,{children:"No Virtual Keys"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Max Budget"}),(0,t.jsx)(eg.xv,{children:(null===(Y=ex.user_info)||void 0===Y?void 0:Y.max_budget)!==null&&(null===(es=ex.user_info)||void 0===es?void 0:es.max_budget)!==void 0?"$".concat((0,O.pw)(ex.user_info.max_budget,4)):"Unlimited"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Budget Reset"}),(0,t.jsx)(eg.xv,{children:(0,k.m)(null!==(ea=null===(el=ex.user_info)||void 0===el?void 0:el.budget_duration)&&void 0!==ea?ea:null)})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(eg.xv,{className:"font-medium",children:"Metadata"}),(0,t.jsx)("pre",{className:"bg-gray-100 p-2 rounded text-xs overflow-auto mt-1",children:JSON.stringify((null===(et=ex.user_info)||void 0===et?void 0:et.metadata)||{},null,2)})]})]})]})})]})]}),(0,t.jsx)(T.Z,{isInvitationLinkModalVisible:eU,setIsInvitationLinkModalVisible:eI,baseUrl:eA||"",invitationLinkData:eD,modalType:"resetPassword"})]})}var ey=l(56083),e_=l(51205),eb=l(57716),eN=l(73247),eS=l(92369),eZ=l(66344);function ew(e){let{data:s=[],columns:l,isLoading:a=!1,onSortChange:r,currentSort:n,accessToken:d,userRole:o,possibleUIRoles:c,handleEdit:u,handleDelete:m,handleResetPassword:x,selectedUsers:h=[],onSelectionChange:g,enableSelection:v=!1,filters:j,updateFilters:p,initialFilters:f,teams:y,userListResponse:b,currentPage:N,handlePageChange:S}=e,[Z,w]=i.useState([{id:(null==n?void 0:n.sortBy)||"created_at",desc:(null==n?void 0:n.sortOrder)==="desc"}]),[k,C]=i.useState(null),[U,I]=i.useState(!1),[D,z]=i.useState(!1),A=function(e){let s=arguments.length>1&&void 0!==arguments[1]&&arguments[1];C(e),I(s)},B=(e,s)=>{g&&(s?g([...h,e]):g(h.filter(s=>s.user_id!==e.user_id)))},E=e=>{g&&(e?g(s):g([]))},T=e=>h.some(s=>s.user_id===e.user_id),O=s.length>0&&h.length===s.length,L=h.length>0&&h.lengthc?es(c,u,m,x,A,v?{selectedUsers:h,onSelectUser:B,onSelectAll:E,isUserSelected:T,isAllSelected:O,isIndeterminate:L}:void 0):l,[c,u,m,x,A,l,v,h,O,L]),R=(0,el.b7)({data:s,columns:F,state:{sorting:Z},onSortingChange:e=>{let s="function"==typeof e?e(Z):e;if(w(s),s&&Array.isArray(s)&&s.length>0&&s[0]){let e=s[0];if(e.id){let s=e.id,l=e.desc?"desc":"asc";null==r||r(s,l)}}else null==r||r("created_at","desc")},getCoreRowModel:(0,et.sC)(),manualSorting:!0,enableSorting:!0});return(i.useEffect(()=>{n&&w([{id:n.sortBy,desc:"desc"===n.sortOrder}])},[n]),k)?(0,t.jsx)(ef,{userId:k,onClose:()=>{C(null),I(!1)},accessToken:d,userRole:o,possibleUIRoles:c,initialTab:U?1:0,startInEditMode:U}):(0,t.jsxs)("div",{className:"bg-white rounded-lg shadow",children:[(0,t.jsx)("div",{className:"border-b px-6 py-4",children:(0,t.jsxs)("div",{className:"flex flex-col space-y-4",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,t.jsx)(ey.H,{placeholder:"Search by email...",value:j.email,onChange:e=>p({email:e}),icon:eN.Z}),(0,t.jsx)(e_.c,{onClick:()=>z(!D),active:D,hasActiveFilters:!!(j.user_id||j.user_role||j.team)}),(0,t.jsx)(eb.z,{onClick:()=>{p(f)}})]}),D&&(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-3 mt-3",children:[(0,t.jsx)(ey.H,{placeholder:"Filter by User ID",value:j.user_id,onChange:e=>p({user_id:e}),icon:eS.Z}),(0,t.jsx)(ey.H,{placeholder:"Filter by SSO ID",value:j.sso_user_id,onChange:e=>p({sso_user_id:e}),icon:eZ.Z}),(0,t.jsx)("div",{className:"w-64",children:(0,t.jsx)(ea.Z,{value:j.user_role,onValueChange:e=>p({user_role:e}),placeholder:"Select Role",children:c&&Object.entries(c).map(e=>{let[s,l]=e;return(0,t.jsx)(_.Z,{value:s,children:l.ui_label},s)})})}),(0,t.jsx)("div",{className:"w-64",children:(0,t.jsx)(ea.Z,{value:j.team,onValueChange:e=>p({team:e}),placeholder:"Select Team",children:null==y?void 0:y.map(e=>(0,t.jsx)(_.Z,{value:e.team_id,children:e.team_alias||e.team_id},e.team_id))})})]}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[a?(0,t.jsx)(eh.Z.Input,{active:!0,style:{width:192,height:20}}):(0,t.jsxs)("span",{className:"text-sm text-gray-700",children:["Showing"," ",b&&b.users&&b.users.length>0?(b.page-1)*b.page_size+1:0," ","-"," ",b&&b.users?Math.min(b.page*b.page_size,b.total):0," ","of ",b?b.total:0," results"]}),(0,t.jsx)("div",{className:"flex space-x-2",children:a?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(eh.Z.Button,{active:!0,size:"small",style:{width:80,height:30}}),(0,t.jsx)(eh.Z.Button,{active:!0,size:"small",style:{width:60,height:30}})]}):(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("button",{onClick:()=>S(N-1),disabled:1===N,className:"px-3 py-1 text-sm border rounded-md ".concat(1===N?"bg-gray-100 text-gray-400 cursor-not-allowed":"hover:bg-gray-50"),children:"Previous"}),(0,t.jsx)("button",{onClick:()=>S(N+1),disabled:!b||N>=b.total_pages,className:"px-3 py-1 text-sm border rounded-md ".concat(!b||N>=b.total_pages?"bg-gray-100 text-gray-400 cursor-not-allowed":"hover:bg-gray-50"),children:"Next"})]})})]})]})}),(0,t.jsx)("div",{className:"overflow-auto",children:(0,t.jsx)("div",{className:"rounded-lg custom-border relative",children:(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsxs)(ei.Z,{className:"[&_td]:py-0.5 [&_th]:py-1",children:[(0,t.jsx)(ed.Z,{children:R.getHeaderGroups().map(e=>(0,t.jsx)(ec.Z,{children:e.headers.map(e=>(0,t.jsx)(eo.Z,{className:"py-1 h-8 ".concat("actions"===e.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)]":""," ").concat(e.column.getCanSort()?"cursor-pointer hover:bg-gray-50":""),onClick:e.column.getToggleSortingHandler(),children:(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,t.jsx)("div",{className:"flex items-center",children:e.isPlaceholder?null:(0,el.ie)(e.column.columnDef.header,e.getContext())}),"actions"!==e.id&&e.column.getCanSort()&&(0,t.jsx)("div",{className:"w-4",children:e.column.getIsSorted()?({asc:(0,t.jsx)(eu.Z,{className:"h-4 w-4 text-blue-500"}),desc:(0,t.jsx)(em.Z,{className:"h-4 w-4 text-blue-500"})})[e.column.getIsSorted()]:(0,t.jsx)(ex.Z,{className:"h-4 w-4 text-gray-400"})})]})},e.id))},e.id))}),(0,t.jsx)(er.Z,{children:a?(0,t.jsx)(ec.Z,{children:(0,t.jsx)(en.Z,{colSpan:F.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"\uD83D\uDE85 Loading users..."})})})}):s.length>0?R.getRowModel().rows.map(e=>(0,t.jsx)(ec.Z,{className:"h-8",children:e.getVisibleCells().map(e=>(0,t.jsx)(en.Z,{className:"py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap ".concat("actions"===e.column.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)]":""),onClick:()=>{"user_id"===e.column.id&&A(e.getValue(),!1)},style:{cursor:"user_id"===e.column.id?"pointer":"default",color:"user_id"===e.column.id?"#3b82f6":"inherit"},children:(0,el.ie)(e.column.columnDef.cell,e.getContext())},e.id))},e.id)):(0,t.jsx)(ec.Z,{children:(0,t.jsx)(en.Z,{colSpan:F.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"No users found"})})})})})]})})})})]})}let{Text:ek,Title:eC}=n.default,eU={email:"",user_id:"",user_role:"",sso_user_id:"",team:"",model:"",min_spend:null,max_spend:null,sort_by:"created_at",sort_order:"desc"};var eI=e=>{var s,l,n;let{accessToken:d,token:o,userRole:c,userID:u,teams:m}=e,x=(0,F.NL)(),[h,g]=(0,i.useState)(1),[v,p]=(0,i.useState)(!1),[f,y]=(0,i.useState)(null),[_,b]=(0,i.useState)(!1),[N,S]=(0,i.useState)(!1),[w,k]=(0,i.useState)(null),[C,I]=(0,i.useState)("users"),[D,B]=(0,i.useState)(eU),[M,K,V]=(0,L.G)(D,{wait:300}),[q,G]=(0,i.useState)(!1),[Q,H]=(0,i.useState)(null),[$,W]=(0,i.useState)(null),[Y,X]=(0,i.useState)([]),[ee,el]=(0,i.useState)(!1),[et,ea]=(0,i.useState)(!1),[ei,er]=(0,i.useState)([]),en=e=>{k(e),b(!0)};(0,i.useEffect)(()=>()=>{V.cancel()},[V]),(0,i.useEffect)(()=>{W((0,j.getProxyBaseUrl)())},[]),(0,i.useEffect)(()=>{(async()=>{try{if(!u||!c||!d)return;let e=(await (0,j.modelAvailableCall)(d,u,c)).data.map(e=>e.id);console.log("available_model_names:",e),er(e)}catch(e){console.error("Error fetching user models:",e)}})()},[d,u,c]);let ed=e=>{B(s=>{let l={...s,...e};return K(l),l})},eo=async e=>{if(!d){U.Z.fromBackend("Access token not found");return}try{U.Z.success("Generating password reset link...");let s=await (0,j.invitationCreateCall)(d,e);H(s),G(!0)}catch(e){U.Z.fromBackend("Failed to generate password reset link")}},ec=async()=>{if(w&&d)try{S(!0),await (0,j.userDeleteCall)(d,[w.user_id]),x.setQueriesData({queryKey:["userList"]},e=>{if(void 0===e)return e;let s=e.users.filter(e=>e.user_id!==w.user_id);return{...e,users:s}}),U.Z.success("User deleted successfully")}catch(e){console.error("Error deleting user:",e),U.Z.fromBackend("Failed to delete user")}finally{b(!1),k(null),S(!1)}},eu=async()=>{y(null),p(!1)},em=async e=>{if(console.log("inside handleEditSubmit:",e),d&&o&&c&&u){try{let s=await (0,j.userUpdateUserCall)(d,e,null);x.setQueriesData({queryKey:["userList"]},e=>{if(void 0===e)return e;let l=e.users.map(e=>e.user_id===s.data.user_id?(0,O.nl)(e,s.data):e);return{...e,users:l}}),U.Z.success("User ".concat(e.user_id," updated successfully"))}catch(e){console.error("There was an error updating the user",e)}y(null),p(!1)}},ex=async e=>{g(e)},eg=(0,R.a)({queryKey:["userList",{debouncedFilter:M,currentPage:h}],queryFn:async()=>{if(!d)throw Error("Access token required");return await (0,j.userListCall)(d,M.user_id?[M.user_id]:null,h,25,M.email||null,M.user_role||null,M.team||null,M.sso_user_id||null,M.sort_by,M.sort_order)},enabled:!!(d&&o&&c&&u),placeholderData:e=>e}),ev=eg.data,ej=(0,R.a)({queryKey:["userRoles"],initialData:()=>({}),queryFn:async()=>{if(!d)throw Error("Access token required");return await (0,j.getPossibleUserRoles)(d)},enabled:!!(d&&o&&c&&u)}).data,ep=es(ej,e=>{y(e),p(!0)},en,eo,()=>{});return(0,t.jsxs)("div",{className:"w-full p-8 overflow-hidden",children:[(0,t.jsx)("div",{className:"flex items-center justify-between mb-4",children:(0,t.jsx)("div",{className:"flex space-x-3",children:eg.isLoading?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(eh.Z.Button,{active:!0,size:"default",shape:"default",style:{width:110,height:36}}),(0,t.jsx)(eh.Z.Button,{active:!0,size:"default",shape:"default",style:{width:145,height:36}}),(0,t.jsx)(eh.Z.Button,{active:!0,size:"default",shape:"default",style:{width:110,height:36}})]}):u&&d?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(A.Z,{userID:u,accessToken:d,teams:m,possibleUIRoles:ej}),(0,t.jsx)(r.z,{onClick:()=>{ea(!et),X([])},variant:et?"primary":"secondary",className:"flex items-center",children:et?"Cancel Selection":"Select Users"}),et&&(0,t.jsxs)(r.z,{onClick:()=>{if(0===Y.length){U.Z.fromBackend("Please select users to edit");return}el(!0)},disabled:0===Y.length,className:"flex items-center",children:["Bulk Edit (",Y.length," selected)"]})]}):null})}),(0,t.jsxs)(a.v0,{defaultIndex:0,onIndexChange:e=>I(0===e?"users":"settings"),children:[(0,t.jsxs)(a.td,{className:"mb-4",children:[(0,t.jsx)(a.OK,{children:"Users"}),(0,t.jsx)(a.OK,{children:"Default User Settings"})]}),(0,t.jsxs)(a.nP,{children:[(0,t.jsx)(a.x4,{children:(0,t.jsx)(ew,{data:(null===(s=eg.data)||void 0===s?void 0:s.users)||[],columns:ep,isLoading:eg.isLoading,accessToken:d,userRole:c,onSortChange:(e,s)=>{ed({sort_by:e,sort_order:s})},currentSort:{sortBy:D.sort_by,sortOrder:D.sort_order},possibleUIRoles:ej,handleEdit:e=>{y(e),p(!0)},handleDelete:en,handleResetPassword:eo,enableSelection:et,selectedUsers:Y,onSelectionChange:e=>{X(e)},filters:D,updateFilters:ed,initialFilters:eU,teams:m,userListResponse:ev,currentPage:h,handlePageChange:ex})}),(0,t.jsx)(a.x4,{children:u&&c&&d?(0,t.jsx)(J,{accessToken:d,possibleUIRoles:ej,userID:u,userRole:c}):(0,t.jsx)("div",{className:"flex justify-center items-center h-64",children:(0,t.jsx)(eh.Z,{active:!0,paragraph:{rows:4}})})})]})]}),(0,t.jsx)(E,{visible:v,possibleUIRoles:ej,onCancel:eu,user:f,onSubmit:em}),(0,t.jsx)(P.Z,{isOpen:_,title:"Delete User?",message:"Are you sure you want to delete this user? This action cannot be undone.",resourceInformationTitle:"User Information",resourceInformation:[{label:"Email",value:null==w?void 0:w.user_email},{label:"User ID",value:null==w?void 0:w.user_id,code:!0},{label:"Global Proxy Role",value:w&&(null==ej?void 0:null===(l=ej[w.user_role])||void 0===l?void 0:l.ui_label)||(null==w?void 0:w.user_role)||"-"},{label:"Total Spend (USD)",value:null==w?void 0:null===(n=w.spend)||void 0===n?void 0:n.toFixed(2)}],onCancel:()=>{b(!1),k(null)},onOk:ec,confirmLoading:N}),(0,t.jsx)(T.Z,{isInvitationLinkModalVisible:q,setIsInvitationLinkModalVisible:G,baseUrl:$||"",invitationLinkData:Q,modalType:"resetPassword"}),(0,t.jsx)(z,{open:ee,onCancel:()=>el(!1),selectedUsers:Y,possibleUIRoles:ej,accessToken:d,onSuccess:()=>{x.invalidateQueries({queryKey:["userList"]}),X([]),ea(!1)},teams:m,userRole:c,userModels:ei,allowAllUsers:!!c&&(0,Z.tY)(c)})]})}}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/2344-03dd7ba935a2a2f3.js b/litellm/proxy/_experimental/out/_next/static/chunks/2344-03dd7ba935a2a2f3.js deleted file mode 100644 index ac70c71a273..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/2344-03dd7ba935a2a2f3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2344],{38434:function(t,e,n){n.d(e,{Z:function(){return i}});var r=n(1119),a=n(2265),o={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494zM504 618H320c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zM312 490v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H320c-4.4 0-8 3.6-8 8z"}}]},name:"file-text",theme:"outlined"},c=n(55015),i=a.forwardRef(function(t,e){return a.createElement(c.Z,(0,r.Z)({},t,{ref:e,icon:o}))})},96473:function(t,e,n){n.d(e,{Z:function(){return i}});var r=n(1119),a=n(2265),o={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"}},{tag:"path",attrs:{d:"M192 474h672q8 0 8 8v60q0 8-8 8H160q-8 0-8-8v-60q0-8 8-8z"}}]},name:"plus",theme:"outlined"},c=n(55015),i=a.forwardRef(function(t,e){return a.createElement(c.Z,(0,r.Z)({},t,{ref:e,icon:o}))})},77565:function(t,e,n){n.d(e,{Z:function(){return i}});var r=n(1119),a=n(2265),o={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"}}]},name:"right",theme:"outlined"},c=n(55015),i=a.forwardRef(function(t,e){return a.createElement(c.Z,(0,r.Z)({},t,{ref:e,icon:o}))})},57400:function(t,e,n){n.d(e,{Z:function(){return i}});var r=n(1119),a=n(2265),o={icon:{tag:"svg",attrs:{viewBox:"0 0 1024 1024",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 64L128 192v384c0 212.1 171.9 384 384 384s384-171.9 384-384V192L512 64zm312 512c0 172.3-139.7 312-312 312S200 748.3 200 576V246l312-110 312 110v330z"}},{tag:"path",attrs:{d:"M378.4 475.1a35.91 35.91 0 00-50.9 0 35.91 35.91 0 000 50.9l129.4 129.4 2.1 2.1a33.98 33.98 0 0048.1 0L730.6 434a33.98 33.98 0 000-48.1l-2.8-2.8a33.98 33.98 0 00-48.1 0L483 579.7 378.4 475.1z"}}]},name:"safety",theme:"outlined"},c=n(55015),i=a.forwardRef(function(t,e){return a.createElement(c.Z,(0,r.Z)({},t,{ref:e,icon:o}))})},15883:function(t,e,n){n.d(e,{Z:function(){return i}});var r=n(1119),a=n(2265),o={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M858.5 763.6a374 374 0 00-80.6-119.5 375.63 375.63 0 00-119.5-80.6c-.4-.2-.8-.3-1.2-.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-.4.2-.8.3-1.2.5-44.8 18.9-85 46-119.5 80.6a375.63 375.63 0 00-80.6 119.5A371.7 371.7 0 00136 901.8a8 8 0 008 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c.1 4.4 3.6 7.8 8 7.8h60a8 8 0 008-8.2c-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z"}}]},name:"user",theme:"outlined"},c=n(55015),i=a.forwardRef(function(t,e){return a.createElement(c.Z,(0,r.Z)({},t,{ref:e,icon:o}))})},23496:function(t,e,n){n.d(e,{Z:function(){return p}});var r=n(2265),a=n(36760),o=n.n(a),c=n(71744),i=n(33759),l=n(93463),d=n(12918),s=n(99320),f=n(71140);let h=t=>{let{componentCls:e}=t;return{[e]:{"&-horizontal":{["&".concat(e)]:{"&-sm":{marginBlock:t.marginXS},"&-md":{marginBlock:t.margin}}}}}},u=t=>{let{componentCls:e,sizePaddingEdgeHorizontal:n,colorSplit:r,lineWidth:a,textPaddingInline:o,orientationMargin:c,verticalMarginInline:i}=t;return{[e]:Object.assign(Object.assign({},(0,d.Wf)(t)),{borderBlockStart:"".concat((0,l.bf)(a)," solid ").concat(r),"&-vertical":{position:"relative",top:"-0.06em",display:"inline-block",height:"0.9em",marginInline:i,marginBlock:0,verticalAlign:"middle",borderTop:0,borderInlineStart:"".concat((0,l.bf)(a)," solid ").concat(r)},"&-horizontal":{display:"flex",clear:"both",width:"100%",minWidth:"100%",margin:"".concat((0,l.bf)(t.marginLG)," 0")},["&-horizontal".concat(e,"-with-text")]:{display:"flex",alignItems:"center",margin:"".concat((0,l.bf)(t.dividerHorizontalWithTextGutterMargin)," 0"),color:t.colorTextHeading,fontWeight:500,fontSize:t.fontSizeLG,whiteSpace:"nowrap",textAlign:"center",borderBlockStart:"0 ".concat(r),"&::before, &::after":{position:"relative",width:"50%",borderBlockStart:"".concat((0,l.bf)(a)," solid transparent"),borderBlockStartColor:"inherit",borderBlockEnd:0,transform:"translateY(50%)",content:"''"}},["&-horizontal".concat(e,"-with-text-start")]:{"&::before":{width:"calc(".concat(c," * 100%)")},"&::after":{width:"calc(100% - ".concat(c," * 100%)")}},["&-horizontal".concat(e,"-with-text-end")]:{"&::before":{width:"calc(100% - ".concat(c," * 100%)")},"&::after":{width:"calc(".concat(c," * 100%)")}},["".concat(e,"-inner-text")]:{display:"inline-block",paddingBlock:0,paddingInline:o},"&-dashed":{background:"none",borderColor:r,borderStyle:"dashed",borderWidth:"".concat((0,l.bf)(a)," 0 0")},["&-horizontal".concat(e,"-with-text").concat(e,"-dashed")]:{"&::before, &::after":{borderStyle:"dashed none none"}},["&-vertical".concat(e,"-dashed")]:{borderInlineStartWidth:a,borderInlineEnd:0,borderBlockStart:0,borderBlockEnd:0},"&-dotted":{background:"none",borderColor:r,borderStyle:"dotted",borderWidth:"".concat((0,l.bf)(a)," 0 0")},["&-horizontal".concat(e,"-with-text").concat(e,"-dotted")]:{"&::before, &::after":{borderStyle:"dotted none none"}},["&-vertical".concat(e,"-dotted")]:{borderInlineStartWidth:a,borderInlineEnd:0,borderBlockStart:0,borderBlockEnd:0},["&-plain".concat(e,"-with-text")]:{color:t.colorText,fontWeight:"normal",fontSize:t.fontSize},["&-horizontal".concat(e,"-with-text-start").concat(e,"-no-default-orientation-margin-start")]:{"&::before":{width:0},"&::after":{width:"100%"},["".concat(e,"-inner-text")]:{paddingInlineStart:n}},["&-horizontal".concat(e,"-with-text-end").concat(e,"-no-default-orientation-margin-end")]:{"&::before":{width:"100%"},"&::after":{width:0},["".concat(e,"-inner-text")]:{paddingInlineEnd:n}}})}};var g=(0,s.I$)("Divider",t=>{let e=(0,f.IX)(t,{dividerHorizontalWithTextGutterMargin:t.margin,sizePaddingEdgeHorizontal:0});return[u(e),h(e)]},t=>({textPaddingInline:"1em",orientationMargin:.05,verticalMarginInline:t.marginXS}),{unitless:{orientationMargin:!0}}),m=function(t,e){var n={};for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&0>e.indexOf(r)&&(n[r]=t[r]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var a=0,r=Object.getOwnPropertySymbols(t);ae.indexOf(r[a])&&Object.prototype.propertyIsEnumerable.call(t,r[a])&&(n[r[a]]=t[r[a]]);return n};let b={small:"sm",middle:"md"};var p=t=>{let{getPrefixCls:e,direction:n,className:a,style:l}=(0,c.dj)("divider"),{prefixCls:d,type:s="horizontal",orientation:f="center",orientationMargin:h,className:u,rootClassName:p,children:v,dashed:w,variant:y="solid",plain:x,style:k,size:z}=t,S=m(t,["prefixCls","type","orientation","orientationMargin","className","rootClassName","children","dashed","variant","plain","style","size"]),Z=e("divider",d),[M,E,B]=g(Z),C=b[(0,i.Z)(z)],I=!!v,O=r.useMemo(()=>"left"===f?"rtl"===n?"end":"start":"right"===f?"rtl"===n?"start":"end":f,[n,f]),j="start"===O&&null!=h,L="end"===O&&null!=h,N=o()(Z,a,E,B,"".concat(Z,"-").concat(s),{["".concat(Z,"-with-text")]:I,["".concat(Z,"-with-text-").concat(O)]:I,["".concat(Z,"-dashed")]:!!w,["".concat(Z,"-").concat(y)]:"solid"!==y,["".concat(Z,"-plain")]:!!x,["".concat(Z,"-rtl")]:"rtl"===n,["".concat(Z,"-no-default-orientation-margin-start")]:j,["".concat(Z,"-no-default-orientation-margin-end")]:L,["".concat(Z,"-").concat(C)]:!!C},u,p),W=r.useMemo(()=>"number"==typeof h?h:/^\d+$/.test(h)?Number(h):h,[h]);return M(r.createElement("div",Object.assign({className:N,style:Object.assign(Object.assign({},l),k)},S,{role:"separator"}),v&&"vertical"!==s&&r.createElement("span",{className:"".concat(Z,"-inner-text"),style:{marginInlineStart:j?W:void 0,marginInlineEnd:L?W:void 0}},v)))}},79205:function(t,e,n){n.d(e,{Z:function(){return f}});var r=n(2265);let a=t=>t.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),o=t=>t.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,e,n)=>n?n.toUpperCase():e.toLowerCase()),c=t=>{let e=o(t);return e.charAt(0).toUpperCase()+e.slice(1)},i=function(){for(var t=arguments.length,e=Array(t),n=0;n!!t&&""!==t.trim()&&n.indexOf(t)===e).join(" ").trim()},l=t=>{for(let e in t)if(e.startsWith("aria-")||"role"===e||"title"===e)return!0};var d={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let s=(0,r.forwardRef)((t,e)=>{let{color:n="currentColor",size:a=24,strokeWidth:o=2,absoluteStrokeWidth:c,className:s="",children:f,iconNode:h,...u}=t;return(0,r.createElement)("svg",{ref:e,...d,width:a,height:a,stroke:n,strokeWidth:c?24*Number(o)/Number(a):o,className:i("lucide",s),...!f&&!l(u)&&{"aria-hidden":"true"},...u},[...h.map(t=>{let[e,n]=t;return(0,r.createElement)(e,n)}),...Array.isArray(f)?f:[f]])}),f=(t,e)=>{let n=(0,r.forwardRef)((n,o)=>{let{className:l,...d}=n;return(0,r.createElement)(s,{ref:o,iconNode:e,className:i("lucide-".concat(a(c(t))),"lucide-".concat(t),l),...d})});return n.displayName=c(t),n}},82222:function(t,e,n){n.d(e,{Z:function(){return r}});let r=(0,n(79205).Z)("bot",[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]])},51817:function(t,e,n){n.d(e,{Z:function(){return r}});let r=(0,n(79205).Z)("loader-circle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]])},98728:function(t,e,n){n.d(e,{Z:function(){return r}});let r=(0,n(79205).Z)("settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]])},79862:function(t,e,n){n.d(e,{Z:function(){return r}});let r=(0,n(79205).Z)("user-round",[["circle",{cx:"12",cy:"8",r:"5",key:"1hypcn"}],["path",{d:"M20 21a8 8 0 0 0-16 0",key:"rfgkzh"}]])},32489:function(t,e,n){n.d(e,{Z:function(){return r}});let r=(0,n(79205).Z)("x",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]])},25523:function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"RouterContext",{enumerable:!0,get:function(){return r}});let r=n(47043)._(n(2265)).default.createContext(null)}}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/2353-c94748c0aac514ff.js b/litellm/proxy/_experimental/out/_next/static/chunks/2353-c94748c0aac514ff.js new file mode 100644 index 00000000000..3426c548b25 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/2353-c94748c0aac514ff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2353],{57365:function(e,t,n){n.d(t,{Z:function(){return a}});var r=n(5853),o=n(2265),l=n(51975),i=n(13241);let u=(0,n(1153).fn)("SelectItem"),a=o.forwardRef((e,t)=>{let{value:n,icon:a,className:s,children:c}=e,d=(0,r._T)(e,["value","icon","className","children"]);return o.createElement(l.wt,Object.assign({className:(0,i.q)(u("root"),"flex justify-start items-center cursor-default text-tremor-default px-2.5 py-2.5","data-[focus]:bg-tremor-background-muted data-[focus]:text-tremor-content-strong data-[selected]:text-tremor-content-strong data-[selected]:bg-tremor-background-muted text-tremor-content-emphasis","dark:data-[focus]:bg-dark-tremor-background-muted dark:data-[focus]:text-dark-tremor-content-strong dark:data-[selected]:text-dark-tremor-content-strong dark:data-[selected]:bg-dark-tremor-background-muted dark:text-dark-tremor-content-emphasis",s),ref:t,key:n,value:n},d),a&&o.createElement(a,{className:(0,i.q)(u("icon"),"flex-none w-5 h-5 mr-1.5","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")}),o.createElement("span",{className:"whitespace-nowrap truncate"},null!=c?c:n))});a.displayName="SelectItem"},44140:function(e,t,n){n.d(t,{Z:function(){return o}});var r=n(2265);let o=(e,t)=>{let n=void 0!==t,[o,l]=(0,r.useState)(e);return[n?t:o,e=>{n||l(e)}]}},64803:function(e,t,n){n.d(t,{RR:function(){return v},YF:function(){return d},cv:function(){return f},dp:function(){return m},uY:function(){return p}});var r=n(51050),o=n(2265),l=n(54887),i="undefined"!=typeof document?o.useLayoutEffect:function(){};function u(e,t){let n,r,o;if(e===t)return!0;if(typeof e!=typeof t)return!1;if("function"==typeof e&&e.toString()===t.toString())return!0;if(e&&t&&"object"==typeof e){if(Array.isArray(e)){if((n=e.length)!==t.length)return!1;for(r=n;0!=r--;)if(!u(e[r],t[r]))return!1;return!0}if((n=(o=Object.keys(e)).length)!==Object.keys(t).length)return!1;for(r=n;0!=r--;)if(!({}).hasOwnProperty.call(t,o[r]))return!1;for(r=n;0!=r--;){let n=o[r];if(("_owner"!==n||!e.$$typeof)&&!u(e[n],t[n]))return!1}return!0}return e!=e&&t!=t}function a(e){return"undefined"==typeof window?1:(e.ownerDocument.defaultView||window).devicePixelRatio||1}function s(e,t){let n=a(e);return Math.round(t*n)/n}function c(e){let t=o.useRef(e);return i(()=>{t.current=e}),t}function d(e){void 0===e&&(e={});let{placement:t="bottom",strategy:n="absolute",middleware:d=[],platform:f,elements:{reference:p,floating:v}={},transform:m=!0,whileElementsMounted:g,open:h}=e,[b,x]=o.useState({x:0,y:0,strategy:n,placement:t,middlewareData:{},isPositioned:!1}),[E,y]=o.useState(d);u(E,d)||y(d);let[S,O]=o.useState(null),[R,w]=o.useState(null),C=o.useCallback(e=>{e!==k.current&&(k.current=e,O(e))},[]),P=o.useCallback(e=>{e!==M.current&&(M.current=e,w(e))},[]),L=p||S,T=v||R,k=o.useRef(null),M=o.useRef(null),I=o.useRef(b),F=null!=g,A=c(g),D=c(f),N=c(h),z=o.useCallback(()=>{if(!k.current||!M.current)return;let e={placement:t,strategy:n,middleware:E};D.current&&(e.platform=D.current),(0,r.oo)(k.current,M.current,e).then(e=>{let t={...e,isPositioned:!1!==N.current};H.current&&!u(I.current,t)&&(I.current=t,l.flushSync(()=>{x(t)}))})},[E,t,n,D,N]);i(()=>{!1===h&&I.current.isPositioned&&(I.current.isPositioned=!1,x(e=>({...e,isPositioned:!1})))},[h]);let H=o.useRef(!1);i(()=>(H.current=!0,()=>{H.current=!1}),[]),i(()=>{if(L&&(k.current=L),T&&(M.current=T),L&&T){if(A.current)return A.current(L,T,z);z()}},[L,T,z,A,F]);let _=o.useMemo(()=>({reference:k,floating:M,setReference:C,setFloating:P}),[C,P]),B=o.useMemo(()=>({reference:L,floating:T}),[L,T]),V=o.useMemo(()=>{let e={position:n,left:0,top:0};if(!B.floating)return e;let t=s(B.floating,b.x),r=s(B.floating,b.y);return m?{...e,transform:"translate("+t+"px, "+r+"px)",...a(B.floating)>=1.5&&{willChange:"transform"}}:{position:n,left:t,top:r}},[n,m,B.floating,b.x,b.y]);return o.useMemo(()=>({...b,update:z,refs:_,elements:B,floatingStyles:V}),[b,z,_,B,V])}let f=(e,t)=>({...(0,r.cv)(e),options:[e,t]}),p=(e,t)=>({...(0,r.uY)(e),options:[e,t]}),v=(e,t)=>({...(0,r.RR)(e),options:[e,t]}),m=(e,t)=>({...(0,r.dp)(e),options:[e,t]})},52307:function(e,t,n){n.d(t,{dk:function(){return f},fw:function(){return d},zH:function(){return c}});var r=n(2265),o=n(93980),l=n(73389),i=n(67561),u=n(87550),a=n(38929);let s=(0,r.createContext)(null);function c(){var e,t;return null!=(t=null==(e=(0,r.useContext)(s))?void 0:e.value)?t:void 0}function d(){let[e,t]=(0,r.useState)([]);return[e.length>0?e.join(" "):void 0,(0,r.useMemo)(()=>function(e){let n=(0,o.z)(e=>(t(t=>[...t,e]),()=>t(t=>{let n=t.slice(),r=n.indexOf(e);return -1!==r&&n.splice(r,1),n}))),l=(0,r.useMemo)(()=>({register:n,slot:e.slot,name:e.name,props:e.props,value:e.value}),[n,e.slot,e.name,e.props,e.value]);return r.createElement(s.Provider,{value:l},e.children)},[t])]}s.displayName="DescriptionContext";let f=Object.assign((0,a.yV)(function(e,t){let n=(0,r.useId)(),o=(0,u.B)(),{id:c="headlessui-description-".concat(n),...d}=e,f=function e(){let t=(0,r.useContext)(s);if(null===t){let t=Error("You used a component, but it is not inside a relevant parent.");throw Error.captureStackTrace&&Error.captureStackTrace(t,e),t}return t}(),p=(0,i.T)(t);(0,l.e)(()=>f.register(c),[c,f.register]);let v=o||!1,m=(0,r.useMemo)(()=>({...f.slot,disabled:v}),[f.slot,v]),g={ref:p,...f.props,id:c};return(0,a.L6)()({ourProps:g,theirProps:d,slot:m,defaultTag:"p",name:f.name||"Description"})}),{})},7935:function(e,t,n){n.d(t,{__:function(){return p},bE:function(){return f},wp:function(){return d}});var r=n(2265),o=n(93980),l=n(73389),i=n(67561),u=n(87550),a=n(80281),s=n(38929);let c=(0,r.createContext)(null);function d(e){var t,n,o;let l=null!=(n=null==(t=(0,r.useContext)(c))?void 0:t.value)?n:void 0;return(null!=(o=null==e?void 0:e.length)?o:0)>0?[l,...e].filter(Boolean).join(" "):l}function f(){let{inherit:e=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=d(),[n,l]=(0,r.useState)([]),i=e?[t,...n].filter(Boolean):n;return[i.length>0?i.join(" "):void 0,(0,r.useMemo)(()=>function(e){let t=(0,o.z)(e=>(l(t=>[...t,e]),()=>l(t=>{let n=t.slice(),r=n.indexOf(e);return -1!==r&&n.splice(r,1),n}))),n=(0,r.useMemo)(()=>({register:t,slot:e.slot,name:e.name,props:e.props,value:e.value}),[t,e.slot,e.name,e.props,e.value]);return r.createElement(c.Provider,{value:n},e.children)},[l])]}c.displayName="LabelContext";let p=Object.assign((0,s.yV)(function(e,t){var n;let d=(0,r.useId)(),f=function e(){let t=(0,r.useContext)(c);if(null===t){let t=Error("You used a