diff --git a/.circleci/config.yml b/.circleci/config.yml index a8a33335ad7..abcdbf45187 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -133,6 +133,26 @@ commands: done echo "record/replay proxy did not become ready" >&2 exit 1 + start_fake_openai_endpoint: + description: "Start the canned OpenAI mock (tests/_fake_openai_endpoint_server.py) on host port 8190 and wait until healthy. Models whose api_base points here (via FAKE_OPENAI_API_BASE) get well-formed chat/text/embedding responses with realistic usage, so the E2E run neither pays for nor depends on the live provider. A request whose model is '429' returns HTTP 429 for rate-limit/cooldown tests. Run after uv deps are synced." + steps: + - run: + name: Start fake OpenAI endpoint + background: true + command: | + uv run --no-sync python tests/_fake_openai_endpoint_server.py --host 0.0.0.0 --port 8190 + - run: + name: Wait for fake OpenAI endpoint + command: | + for i in $(seq 1 30); do + if curl -sf http://localhost:8190/health >/dev/null 2>&1; then + echo "fake OpenAI endpoint is up" + exit 0 + fi + sleep 1 + done + echo "fake OpenAI endpoint did not become ready" >&2 + exit 1 setup_litellm_enterprise_pip: steps: - run: @@ -168,6 +188,8 @@ jobs: name: win/default shell: powershell.exe working_directory: ~/project + environment: + UV_PYTHON: "3.11" steps: - checkout - run: @@ -200,7 +222,7 @@ jobs: if (-not (Select-String -Path $PROFILE -SimpleMatch $uvBin -Quiet)) { Add-Content -Path $PROFILE -Value "`$env:Path = `"$uvBin;`$env:Path`"" } - uv sync --frozen --group dev --python (Get-Command python).Source + uv sync --frozen --group dev --python 3.11 - run: name: Run Windows-specific test command: | @@ -594,6 +616,8 @@ jobs: working_directory: ~/project resource_class: large parallelism: 4 + environment: + FAKE_OPENAI_API_BASE: http://127.0.0.1:8190 steps: - checkout - setup_google_dns @@ -609,6 +633,7 @@ jobs: paths: - ~/.cache/uv key: v1-uv-cache-{{ checksum "uv.lock" }} + - start_fake_openai_endpoint # Run pytest and generate JUnit XML report - setup_litellm_enterprise_pip - run: @@ -1549,6 +1574,7 @@ jobs: name: Install Dependencies command: | uv sync --frozen --all-groups --all-extras --python 3.12 + - start_fake_openai_endpoint - start_postgres: db_name: litellm_test - attach_workspace: @@ -1586,6 +1612,7 @@ jobs: -e DATABASE_URL="postgresql://postgres:postgres@host.docker.internal:5432/litellm_test" \ -e DEFAULT_NUM_WORKERS_LITELLM_PROXY=1 \ -e DISABLE_SCHEMA_UPDATE="True" \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ --name my-app \ --add-host=host.docker.internal:host-gateway \ -v $(pwd)/litellm/proxy/example_config_yaml/bad_schema.prisma:/app/schema.prisma \ @@ -1648,6 +1675,7 @@ jobs: zstd -d litellm-docker-database.tar.zst --stdout | docker load docker tag litellm-docker-database:ci my-app:latest - start_openai_record_replay_proxy + - start_fake_openai_endpoint - run: name: Run Docker container command: | @@ -1655,6 +1683,7 @@ jobs: -p 4000:4000 \ -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e USE_PRISMA_MIGRATE=True \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e AZURE_API_KEY=$AZURE_API_KEY \ -e REDIS_HOST=$REDIS_HOST \ -e REDIS_PASSWORD=$REDIS_PASSWORD \ @@ -1817,6 +1846,7 @@ jobs: zstd -d litellm-docker-database.tar.zst --stdout | docker load docker images | grep litellm-docker-database - start_openai_record_replay_proxy + - start_fake_openai_endpoint - run: name: Run Docker container # intentionally give bad redis credentials here @@ -1830,6 +1860,7 @@ jobs: -e REDIS_PORT=$REDIS_PORT \ -e LITELLM_MASTER_KEY="sk-1234" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ -e OTEL_EXPORTER="in_memory" \ -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ @@ -1889,6 +1920,7 @@ jobs: -e REDIS_PORT=$REDIS_PORT \ -e LITELLM_MASTER_KEY="sk-1234" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE="bad-license" \ --add-host host.docker.internal:host-gateway \ --name my-app-3 \ @@ -1938,6 +1970,7 @@ jobs: uv sync --frozen --all-groups --all-extras --python 3.12 - start_postgres - start_redis + - start_fake_openai_endpoint - attach_workspace: at: ~/project - run: @@ -1961,6 +1994,7 @@ jobs: -e REDIS_PORT=6379 \ -e LITELLM_MASTER_KEY="sk-1234" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ @@ -2020,6 +2054,7 @@ jobs: command: | uv sync --frozen --all-groups --all-extras --python 3.12 - start_postgres + - start_fake_openai_endpoint - attach_workspace: at: ~/project - run: @@ -2039,6 +2074,7 @@ jobs: -e REDIS_PASSWORD=$REDIS_PASSWORD \ -e REDIS_PORT=$REDIS_PORT \ -e LITELLM_MASTER_KEY="sk-1234" \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ -e USE_DDTRACE=True \ -e DD_API_KEY=$DD_API_KEY \ @@ -2060,6 +2096,7 @@ jobs: -e REDIS_PASSWORD=$REDIS_PASSWORD \ -e REDIS_PORT=$REDIS_PORT \ -e LITELLM_MASTER_KEY="sk-1234" \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ -e USE_DDTRACE=True \ -e DD_API_KEY=$DD_API_KEY \ @@ -2112,6 +2149,7 @@ jobs: command: | uv sync --frozen --all-groups --all-extras --python 3.12 - start_postgres + - start_fake_openai_endpoint - attach_workspace: at: ~/project - run: @@ -2129,6 +2167,7 @@ jobs: -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \ -e STORE_MODEL_IN_DB="True" \ -e LITELLM_MASTER_KEY="sk-1234" \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ --add-host host.docker.internal:host-gateway \ --name my-app \ @@ -2187,6 +2226,7 @@ jobs: command: | docker build -t my-app:latest -f docker/build_from_pip/Dockerfile.build_from_pip . - start_postgres + - start_fake_openai_endpoint - run: name: Run Docker container # intentionally give bad redis credentials here @@ -2200,6 +2240,7 @@ jobs: -e REDIS_PORT=$REDIS_PORT \ -e LITELLM_MASTER_KEY="sk-1234" \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ + -e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \ -e LITELLM_LICENSE=$LITELLM_LICENSE \ -e OTEL_EXPORTER="in_memory" \ -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ @@ -2690,6 +2731,122 @@ jobs: path: ui/litellm-dashboard/playwright-report destination: e2e-playwright-report + e2e_ui_testing_server_root_path: + docker: + - image: cimg/python:3.12-browsers@sha256:b432899af01c9a311bf74f4f22e9ada2e5306d4b1b4383f8d29e1228a5844ef2 + auth: + username: ${DOCKERHUB_USERNAME} + password: ${DOCKERHUB_PASSWORD} + - image: cimg/postgres:16.0@sha256:b125148bc76e8e8eee5eb3ad6020a3a14110a14e8192f1c645128afebe2e2f84 + environment: + POSTGRES_USER: e2euser + POSTGRES_PASSWORD: e2epassword + POSTGRES_DB: litellm_e2e + resource_class: large + working_directory: ~/project + environment: + DATABASE_URL: "postgresql://e2euser:e2epassword@localhost:5432/litellm_e2e" + CI: "true" + # The whole job exercises the proxy mounted under a prefix. SERVER_ROOT_PATH + # is read both by the proxy at boot (to rewrite the built UI bundle in place) + # and by migration.serverRootPath.config.ts, which refuses to run without it. + SERVER_ROOT_PATH: "/litellm" + steps: + - checkout + - setup_google_dns + - install_uv + - restore_cache: + keys: + - v1-uv-cache-{{ checksum "uv.lock" }} + - run: + name: Install Python dependencies + command: | + uv sync --frozen --all-groups --all-extras --python 3.12 + uv run --no-sync python -m prisma generate --schema litellm/proxy/schema.prisma + - save_cache: + key: v1-uv-cache-{{ checksum "uv.lock" }} + paths: + - ~/.cache/uv + - restore_cache: + keys: + - ui-e2e-node-deps-v2-{{ checksum "ui/litellm-dashboard/package-lock.json" }} + - run: + name: Install Node dependencies and Playwright + command: | + cd ui/litellm-dashboard + npm ci + npx playwright install chromium + - save_cache: + key: ui-e2e-node-deps-v2-{{ checksum "ui/litellm-dashboard/package-lock.json" }} + paths: + - ui/litellm-dashboard/node_modules + - ~/.cache/ms-playwright + - run: + name: Build UI from source + command: | + cd ui/litellm-dashboard + npm run build + rm -rf ../../litellm/proxy/_experimental/out + mv out ../../litellm/proxy/_experimental/out + find ../../litellm/proxy/_experimental/out -name '*.html' ! -name 'index.html' | while read -r f; do + d="${f%.html}"; mkdir -p "$d"; mv "$f" "$d/index.html" + done + - wait_for_service: + url: tcp://localhost:5432 + timeout: "30" + - run: + name: Push Prisma schema + command: uv run --no-sync python -m prisma db push --schema litellm/proxy/schema.prisma --accept-data-loss + - run: + name: Seed database + command: | + PGPASSWORD=e2epassword psql -h localhost -p 5432 -U e2euser -d litellm_e2e \ + -f ui/litellm-dashboard/e2e_tests/fixtures/seed.sql + - run: + name: Start mock LLM server + command: uv run --no-sync python ui/litellm-dashboard/e2e_tests/fixtures/mock_llm_server/server.py + background: true + - run: + name: Start LiteLLM proxy under a server root path + environment: + LITELLM_MASTER_KEY: "sk-1234" + MOCK_LLM_URL: "http://127.0.0.1:8090/v1" + DISABLE_SCHEMA_UPDATE: "true" + # Output flows to this step's own log, so a boot crash is visible here + # rather than swallowed by a downstream readiness probe. + command: | + LITELLM_LICENSE="$LITELLM_LICENSE" \ + uv run --no-sync python -m litellm.proxy.proxy_cli \ + --config ui/litellm-dashboard/e2e_tests/fixtures/config.yml \ + --port 4000 + background: true + - run: + name: Wait for prefixed proxy to be ready + command: | + for i in $(seq 1 60); do + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 -H "Authorization: Bearer sk-1234" http://127.0.0.1:4000/litellm/health 2>/dev/null || true) + if [ "$HTTP_CODE" = "200" ]; then + echo "Prefixed proxy is ready" + exit 0 + fi + sleep 2 + done + echo "Prefixed proxy failed to start; see the 'Start LiteLLM proxy under a server root path' step for the boot log" + exit 1 + - run: + name: Run migration smoke under SERVER_ROOT_PATH + command: | + cd ui/litellm-dashboard + LITELLM_LICENSE="$LITELLM_LICENSE" \ + npx playwright test --config e2e_tests/migration.serverRootPath.config.ts + no_output_timeout: 10m + - store_artifacts: + path: ui/litellm-dashboard/test-results + destination: e2e-server-root-path-test-results + - store_artifacts: + path: ui/litellm-dashboard/playwright-report + destination: e2e-server-root-path-playwright-report + build_docker_database_image: machine: image: ubuntu-2204:2024.04.1 @@ -2795,6 +2952,8 @@ workflows: filters: *main_branches - e2e_ui_testing: filters: *main_branches + - e2e_ui_testing_server_root_path: + filters: *main_branches - build_and_test: requires: - build_docker_database_image diff --git a/.githooks/commit-msg b/.githooks/commit-msg new file mode 100755 index 00000000000..b64e38a2286 --- /dev/null +++ b/.githooks/commit-msg @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# +# commit-msg — enforce Conventional Commits 1.0.0 +# https://www.conventionalcommits.org/en/v1.0.0/ +# +# Subject format: ()!: +# - must be one of the angular types (feat, fix, ...) +# - () is optional +# - ! is optional and marks a breaking change +# - is mandatory and must be non-empty +# +# Bypass: commit with --no-verify. +# Merge, revert, fixup!, squash!, and amend! messages are passed through. + +set -eu + +COMMIT_MSG_FILE="${1:-}" +if [ -z "$COMMIT_MSG_FILE" ] || [ ! -f "$COMMIT_MSG_FILE" ]; then + echo "commit-msg: missing commit message file" >&2 + exit 1 +fi + +# First non-comment, non-empty line is the subject. +subject="" +while IFS= read -r line || [ -n "$line" ]; do + case "$line" in + ''|'#'*) continue ;; + esac + subject="$line" + break +done < "$COMMIT_MSG_FILE" + +if [ -z "$subject" ]; then + echo "commit-msg: empty commit message" >&2 + exit 1 +fi + +# Pass-through commits generated by git itself. +case "$subject" in + "Merge "*|"Revert \""*|"fixup! "*|"squash! "*|"amend! "*) + exit 0 + ;; +esac + +ALLOWED_TYPES="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert" +# Description must not start with an uppercase letter — kept in sync with the +# subjectPattern in .github/workflows/conventional-commits.yml so the local +# hook is the strictly tighter of the two gates. (Without this guard, a commit +# like "feat: Add thing" passes locally but fails the PR-title CI check.) +PATTERN="^(${ALLOWED_TYPES})(\([^)]+\))?!?: [^A-Z].*" + +if printf '%s' "$subject" | grep -Eq "$PATTERN"; then + exit 0 +fi + +cat >&2 <()!: + (description must start with a lowercase letter) + + Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert + Examples: + feat(router): add weighted round-robin strategy + fix(bedrock): decouple STS region from aws_region_name + chore(deps): bump black to 26.3.1 + refactor!: drop Python 3.8 support + +See https://www.conventionalcommits.org/en/v1.0.0/ + +To bypass (use sparingly): git commit --no-verify +EOF +exit 1 diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 00000000000..c2267c8501c --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# +# pre-push — enforce Conventional Branches +# https://conventional-branch.github.io/ +# +# Branch format: / +# must be one of: feature, bugfix, hotfix, release, chore +# +# Protected branches (always allowed): +# - main +# - litellm_internal_staging +# - dependabot/* +# - gh-readonly-queue/* +# +# Tag pushes and branch deletions are skipped. +# Bypass: git push --no-verify. + +set -eu + +ZERO_OID="0000000000000000000000000000000000000000" +ZERO_OID_SHA256="0000000000000000000000000000000000000000000000000000000000000000" +ALLOWED_TYPES="feature|bugfix|hotfix|release|chore" +BRANCH_PATTERN="^(${ALLOWED_TYPES})/.+" + +PROTECTED_NAMES="main litellm_internal_staging" +PROTECTED_PREFIXES="dependabot/ gh-readonly-queue/" + +is_protected() { + branch="$1" + for name in $PROTECTED_NAMES; do + if [ "$branch" = "$name" ]; then + return 0 + fi + done + for prefix in $PROTECTED_PREFIXES; do + case "$branch" in "$prefix"*) return 0 ;; esac + done + return 1 +} + +invalid="" + +while read -r local_ref local_oid remote_ref remote_oid; do + # Branch deletion (no local commit being pushed). + if [ "$local_oid" = "$ZERO_OID" ] || [ "$local_oid" = "$ZERO_OID_SHA256" ]; then + continue + fi + + # Only validate branch pushes; ignore tags and other ref namespaces. + case "$remote_ref" in + refs/heads/*) ;; + *) continue ;; + esac + + branch="${remote_ref#refs/heads/}" + + if is_protected "$branch"; then + continue + fi + + if ! printf '%s' "$branch" | grep -Eq "$BRANCH_PATTERN"; then + invalid="$invalid $branch" + fi +done + +if [ -n "$invalid" ]; then + cat >&2 </ + + Allowed types: feature, bugfix, hotfix, release, chore + Examples: + feature/weighted-round-robin + bugfix/streaming-empty-chunks + chore/bump-deps + hotfix/auth-bypass + + Protected (always allowed): main, litellm_internal_staging, + dependabot/*, gh-readonly-queue/*. + +See https://conventional-branch.github.io/ + +Rename with: git branch -m +To bypass (use sparingly): git push --no-verify +EOF + exit 1 +fi + +exit 0 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 99f79c0b272..9658baeb89a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,7 +4,7 @@ ## Linear ticket - + ## Pre-Submission checklist diff --git a/.github/scripts/_agent_shin_actions.py b/.github/scripts/_agent_shin_actions.py new file mode 100644 index 00000000000..b3d1ff055b3 --- /dev/null +++ b/.github/scripts/_agent_shin_actions.py @@ -0,0 +1,50 @@ +"""Dry-run wrapper(s) around Agent Shin GitHub mutations. + +The rollout scripts currently need only one mutation wrapped, so this module +exposes a single ``maybe_post_comment`` helper. It takes a ``dry_run: bool`` +keyword argument and the body is intentionally trivial: + + if dry_run: + print(...) # log what we would do, return + return + real_mutation(...) # otherwise, actually do it + +That shape means a dry-run preview differs from the real run in exactly one +line per side effect: the call site. So when you `python3 script.py` locally +without ``--close``, you can be confident the actions printed are the ones the +GitHub Action would have performed (modulo ordering on retry/error paths, +which are deliberately simple). Any further mutation a rollout script needs +should get the same ``maybe_*`` treatment instead of calling the raw +``triage_with_llm`` mutation directly. + +Importing from this module pulls in the real mutation from ``triage_with_llm`` +— call sites in the rollout scripts should NEVER import ``post_comment`` +directly; that would skip the dry-run gate and is the bug class this module +exists to prevent. +""" + +from __future__ import annotations + +import sys +import textwrap + +# Import the module itself rather than the bare names so monkeypatching +# `triage_with_llm.post_comment` (or any of the other mutations) in tests is +# reflected here — `from triage_with_llm import post_comment` would bind the +# original function to a local name and bypass the patch, defeating the whole +# point of these wrappers. +import triage_with_llm + + +def _log(line: str) -> None: + """Print a single dry-run line to stdout (one log statement per side effect).""" + print(line, file=sys.stdout, flush=True) + + +def maybe_post_comment(repo: str, number: int, body: str, *, dry_run: bool) -> None: + """Post a comment on ``repo#number`` — or, in dry-run, log what we would post.""" + if dry_run: + _log(f"[DRY RUN] comment {repo}#{number}:") + _log(textwrap.indent(body, " ")) + return + triage_with_llm.post_comment(repo, number, body) diff --git a/.github/scripts/agent_shin_shared.py b/.github/scripts/agent_shin_shared.py new file mode 100644 index 00000000000..8f3dc3c2322 --- /dev/null +++ b/.github/scripts/agent_shin_shared.py @@ -0,0 +1,211 @@ +"""Constants and helpers shared by Agent Shin's triage scripts. + +Both `triage_with_llm.py` (the LLM-judge entrypoint) and +`close_low_quality_prs.py` (the daily Greptile-score sweep) need to +agree on the same notions of: + + * What counts as a Greptile-authored review comment + (``GREPTILE_BOT_LOGINS``) and how to extract a confidence score from + its body (``SCORE_PATTERN`` / :func:`extract_greptile_score`). + * How long the 2-hour grace window is (``GRACE_PERIOD_SECONDS``) and + the HTML marker stamped into a grace-warning comment so the *other* + script can see "Agent Shin already warned" and behave accordingly + (``GRACE_COMMENT_MARKER``). + * Who Agent Shin is on GitHub (``AGENT_SHIN_DEFAULT_BOT_LOGIN``). + * How GitHub-style ISO-8601 timestamps round-trip into timezone-aware + :class:`datetime.datetime` (:func:`parse_iso8601`). + +Keeping these in one module means a future change (new Greptile output +format, a longer grace window, a new allowlisted account) is a single edit +instead of two — the original split version had to call out in comments +that the two copies "must stay in sync" precisely because nothing +enforced it. +""" + +from __future__ import annotations + +import datetime as dt +import json +import os +import re +import subprocess +from typing import Iterable + +GREPTILE_BOT_LOGINS = frozenset({"greptile-apps", "greptile-apps[bot]"}) + +SCORE_PATTERN = re.compile( + r"confidence\s*score\s*[:\-]?\s*(\d+)\s*/\s*5", + re.IGNORECASE, +) + +GRACE_COMMENT_MARKER = "" + +# Hidden HTML marker stamped on every Agent Shin auto-close comment (the LLM +# judge's grace/review-gate close and the daily Greptile sweep's close). +# `was_closed_by_agent_shin` requires this marker — not just the closing actor — +# before `@agent-shin reconsider` may reopen, because the `github-actions[bot]` +# identity is shared with every other workflow in the repo and is not unique to +# Agent Shin. Both close paths must stamp it or the reconsider path silently +# rejects the contributor. +AGENT_SHIN_CLOSE_MARKER = "" + +# 2 hours between the grace warning and the auto-close. Short enough to +# dogfood the "fix it before it closes" loop in one sitting; bump back up +# (e.g. 86400 for a day) for the public rollout. +GRACE_PERIOD_SECONDS = 7200 + +AGENT_SHIN_DEFAULT_BOT_LOGIN = "github-actions[bot]" + + +def _logins(*names: str) -> frozenset[str]: + """Build a login set normalized for case-insensitive membership checks. + + Callers compare via ``login.lower() in ``, so the stored values + must be lowercase. Normalizing here lets the literals keep each + account's canonical GitHub casing (e.g. ``SwiftWinds``) for + readability without breaking the lookup. + """ + return frozenset(name.lower() for name in names) + + +# Dogfood rollout gate. While this set is non-empty, Agent Shin acts ONLY on +# PRs/issues authored by these logins and skips everyone else. For an +# allowlisted author the usual internal/external classification is bypassed, so +# an internal account (e.g. a maintainer's own work login) still gets triaged +# while the bot is being tested on a small set of accounts. Empty the set to +# lift the restriction and restore full triage for the public rollout. Logins +# are compared case-insensitively. +ALLOWLIST_LOGINS = _logins("mateo-berri", "SwiftWinds") + +# `gh {pr,issue} list` has no "fetch everything" flag — `--limit` is the only +# control and it defaults to 30. Pass a ceiling far above any realistic open +# backlog (low thousands today) so gh paginates the API until the queue is +# exhausted rather than silently truncating. The bulk sweeps MUST see the whole +# backlog: gh lists newest-first, so a low cap drops the *oldest* PRs/issues — +# exactly the stale ones a low-quality sweep is meant to catch. +GH_LIST_ALL_LIMIT = 100_000 + + +def extract_greptile_score(comments: Iterable[dict]) -> tuple[int, dict] | None: + """Return (score, comment) for the most recent Greptile-authored comment + that contains a "Confidence Score: X/5". Returns None if no such comment. + + "Most recent" is determined by the comment's `updated_at` (falling back to + `created_at`), so re-reviews override earlier passes. + """ + candidates: list[tuple[str, int, dict]] = [] + for comment in comments: + user = (comment.get("user") or {}).get("login", "") + if user not in GREPTILE_BOT_LOGINS: + continue + body = comment.get("body") or "" + match = SCORE_PATTERN.search(body) + if not match: + continue + score = int(match.group(1)) + timestamp = comment.get("updated_at") or comment.get("created_at") or "" + candidates.append((timestamp, score, comment)) + + if not candidates: + return None + + candidates.sort(key=lambda triple: triple[0]) + _, score, comment = candidates[-1] + return score, comment + + +def parse_iso8601(value: str) -> dt.datetime: + """Parse a GitHub ISO-8601 timestamp into a timezone-aware datetime.""" + return dt.datetime.fromisoformat(value.replace("Z", "+00:00")) + + +def gh(*args: str) -> str: + """Run a `gh` CLI command and return stdout. Raises on non-zero exit. + + Shared by both Agent Shin entrypoints so a future change here + (timeout handling, logging, retry on transient failures) only needs + to be made once. + """ + result = subprocess.run( + ["gh", *args], + capture_output=True, + text=True, + check=True, + ) + return result.stdout + + +def list_open_items(kind: str, *, repo: str | None, fields: str) -> list[dict]: + """Return EVERY open PR (``kind="pr"``) or issue (``kind="issue"``) in ``repo``. + + Wraps ``gh {pr,issue} list`` with ``--limit GH_LIST_ALL_LIMIT`` so the full + backlog is fetched instead of the default 30 (or any other arbitrary cap). + Both bulk sweeps — the daily Greptile closer and the one-shot rollout + heads-up — rely on this seeing the whole queue, including the oldest items. + + ``fields`` is the comma-separated ``--json`` field list the caller needs + (e.g. ``"number"`` for the rollout, the full set for the closer). + """ + if kind not in ("pr", "issue"): + raise ValueError(f"kind must be 'pr' or 'issue', got {kind!r}") + repo_args = ["--repo", repo] if repo else [] + raw = gh( + kind, + "list", + "--state", + "open", + "--limit", + str(GH_LIST_ALL_LIMIT), + "--json", + fields, + *repo_args, + ) + return json.loads(raw) + + +def seconds_since_latest_marker_comment( + comments: Iterable[dict], + *, + marker: str, + bot_login: str | None = None, + now: dt.datetime | None = None, +) -> float | None: + """Return seconds since the bot's most recent comment containing ``marker``. + + Filters comments by author so a contributor who quotes the HTML + marker (e.g. via GitHub's "Quote reply" feature, which preserves + HTML comments in the raw markdown of the quoted text) is not + mistaken for a bot warning — that would silently reset cooldown + timers and suppress legitimate notifications. + + ``bot_login`` defaults to the `AGENT_SHIN_BOT_LOGIN` env override or + ``AGENT_SHIN_DEFAULT_BOT_LOGIN`` so callers normally don't need to + pass it. ``now`` is injectable for tests / callers (like the daily + sweep) that want every age calculation pinned to one snapshot. + """ + expected_login = ( + bot_login + or os.environ.get("AGENT_SHIN_BOT_LOGIN") + or AGENT_SHIN_DEFAULT_BOT_LOGIN + ).lower() + latest: dt.datetime | None = None + for comment in comments: + author = ((comment.get("user") or {}).get("login") or "").lower() + if author != expected_login: + continue + body = comment.get("body") or "" + if marker not in body: + continue + created = comment.get("created_at") + if not created: + continue + try: + ts = parse_iso8601(created) + except ValueError: + continue + if latest is None or ts > latest: + latest = ts + if latest is None: + return None + reference = now if now is not None else dt.datetime.now(dt.timezone.utc) + return (reference - latest).total_seconds() diff --git a/.github/scripts/close_low_quality_prs.py b/.github/scripts/close_low_quality_prs.py new file mode 100644 index 00000000000..7b9bbb579e3 --- /dev/null +++ b/.github/scripts/close_low_quality_prs.py @@ -0,0 +1,573 @@ +#!/usr/bin/env python3 +""" +Auto-close low-quality pull requests. + +Closes open PRs (including drafts, regardless of age) that satisfy ALL of: + 1. Have a Greptile (`greptile-apps`) review comment whose latest + "Confidence Score: X/5" is below the configured threshold (default: 4). + 2. Are authored by an external OSS contributor (internal BerriAI + contributors are exempt). + 3. Do not carry an opt-out label (default: "do not close"). + +`--min-age-days` is retained as an opt-in safety net for one-off backfill +runs (default: 0). The team's intent is that the count of open PRs equals +the count of PRs internal collaborators need to action on, so neither age +nor draft status acts as a free pass. + +For each match, the script posts an explanatory comment and closes the PR. +Because OSS contributors *cannot* reopen a PR closed by the bot/maintainer +(GitHub limitation), the close-comment instructs them to push their fixes +and **open a fresh PR**, or to comment `@agent-shin reconsider` on the +closed PR to have the LLM judge re-evaluate (and reopen on pass). + +Requires the `gh` CLI to be authenticated. + +Usage examples: + # Dry run (default) - prints what would be closed + python3 close_low_quality_prs.py + + # Actually close matching PRs + python3 close_low_quality_prs.py --close + + # Restrict to PRs at least N days old (one-off backfill safety net) + python3 close_low_quality_prs.py --min-age-days 7 --min-score 4 --close +""" + +from __future__ import annotations + +import argparse +import datetime as dt +import json +import os +import subprocess +import sys +from typing import Iterable + +# Add this script's directory to `sys.path` so the sibling +# `agent_shin_shared` module is importable when the script is invoked +# directly (e.g. `python3 .github/scripts/close_low_quality_prs.py ...`). +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from agent_shin_shared import ( # noqa: E402 -- sys.path adjusted above + AGENT_SHIN_CLOSE_MARKER, + ALLOWLIST_LOGINS, + GRACE_COMMENT_MARKER, + GRACE_PERIOD_SECONDS, + GREPTILE_BOT_LOGINS, + SCORE_PATTERN, + extract_greptile_score, + gh, + list_open_items, + parse_iso8601, + seconds_since_latest_marker_comment, +) + +# `GREPTILE_BOT_LOGINS` and `SCORE_PATTERN` (Greptile's GitHub App login +# variants and the "Confidence Score: X/5" regex) are imported from +# `agent_shin_shared` so the LLM judge in `triage_with_llm.py` and this +# daily Greptile sweep read the score through the same set of logins +# and the same regex. + +# `author_association` values for internal BerriAI contributors who should be +# exempt from auto-triage. +INTERNAL_AUTHOR_ASSOCIATIONS = frozenset({"OWNER", "MEMBER", "COLLABORATOR"}) + +# Default labels that exempt a PR from auto-close. Defined at module scope (not +# as a mutable argparse default) so that `--optout-label foo` REPLACES the +# defaults instead of appending to them — the argparse `action="append"` + +# `default=[...]` combination silently mutates the shared default list. +DEFAULT_OPTOUT_LABELS = ("do not close", "keep open", "wip") + +# `GRACE_COMMENT_MARKER` (HTML marker appended to grace-period warning +# comments — used by either script to recognize that a warning was +# already posted) and `GRACE_PERIOD_SECONDS` (length of the grace +# period between the warning and the actual auto-close, 2 hours) are +# imported from `agent_shin_shared` so the Agent Shin LLM judge and +# this daily Greptile sweep agree on the same marker and duration. + + +def fetch_open_prs(repo: str | None) -> list[dict]: + """Fetch all open PRs (number, createdAt, isDraft, labels, author). + + Includes drafts: `gh pr list --state open` returns both ready-for-review + and draft PRs by default. This is the desired behavior — drafts are not + a free pass; the internal-collaborator open-PR queue should reflect every + PR that needs human attention regardless of draft status. + """ + fields = "number,title,createdAt,isDraft,labels,author,url" + return list_open_items("pr", repo=repo, fields=fields) + + +def fetch_pr_author_association(pr_number: int, repo: str | None) -> str: + """Return the GitHub `author_association` for a PR, uppercase. + + Values: OWNER, MEMBER, COLLABORATOR, CONTRIBUTOR, FIRST_TIME_CONTRIBUTOR, + FIRST_TIMER, MANNEQUIN, NONE. Returns "" on lookup failure. + """ + endpoint = ( + f"repos/{repo}/pulls/{pr_number}" + if repo + else f"repos/{{owner}}/{{repo}}/pulls/{pr_number}" + ) + try: + data = json.loads(gh("api", endpoint)) + except subprocess.CalledProcessError: + return "" + return (data.get("author_association") or "").upper() + + +def is_external_pr_author(pr: dict, repo: str | None) -> bool: + """Return True if the PR author is an external OSS contributor. + + Internal = `OWNER` / `MEMBER` / `COLLABORATOR` association, or a bot login. + """ + login = ((pr.get("author") or {}).get("login") or "").lower() + if login.endswith("[bot]") or login in {"dependabot", "github-actions"}: + return False + association = fetch_pr_author_association(pr["number"], repo) + # Fail-safe: if the API lookup failed (empty string), treat the author as + # internal so we don't auto-close their PR. Auto-close is destructive, so + # an unknown association should never make a PR eligible for closing. + if not association or association in INTERNAL_AUTHOR_ASSOCIATIONS: + return False + return True + + +def fetch_pr_comments(pr_number: int, repo: str | None) -> list[dict]: + """Fetch issue-level comments on a PR (where Greptile posts its summary).""" + endpoint = ( + f"repos/{repo}/issues/{pr_number}/comments?per_page=100" + if repo + else f"repos/{{owner}}/{{repo}}/issues/{pr_number}/comments?per_page=100" + ) + raw = gh("api", "--paginate", endpoint) + comments: list[dict] = [] + for line in raw.strip().splitlines(): + line = line.strip() + if not line: + continue + try: + parsed = json.loads(line) + except json.JSONDecodeError: + # A malformed line should not blow up the whole sweep. Skip and + # carry on so the remaining PRs in this run still get evaluated. + continue + if isinstance(parsed, list): + comments.extend(parsed) + else: + comments.append(parsed) + return comments + + +def has_optout_label(pr: dict, optout_labels: set[str]) -> bool: + labels = {label.get("name", "").lower() for label in pr.get("labels", [])} + return bool(labels & {lbl.lower() for lbl in optout_labels}) + + +def seconds_since_last_grace_warning( + comments: Iterable[dict], + *, + bot_login: str | None = None, + now: dt.datetime | None = None, +) -> float | None: + """Return seconds since the bot's most recent grace-period warning, or + None if no such warning has ever been posted on this PR. + + Thin wrapper over + `agent_shin_shared.seconds_since_latest_marker_comment` — the + centralized helper handles the bot-author filter, marker match, + timestamp parsing, and `now` injection. Keeping this wrapper + preserves the closer's "already-fetched comments + injectable now" + interface so callers (and tests) don't need to change. + """ + return seconds_since_latest_marker_comment( + comments, + marker=GRACE_COMMENT_MARKER, + bot_login=bot_login, + now=now, + ) + + +def format_grace_warning_comment(score: int, threshold: int) -> str: + """Comment posted on the FIRST low-Greptile-score detection — gives + the contributor a 2-hour grace window before the auto-close fires on + the next daily cron run. + + Mirrors `format_grace_warning_pr_comment` in + `triage_with_llm.py` in spirit (2-hour grace + escape hatches), but + framed around Greptile's confidence score instead of the LLM judge's + rubric since the close trigger here is the Greptile signal. + """ + return ( + "🚅 Hi, thanks for the PR! I'm **Agent Shin**, the automated triage bot for this " + "repository.\n" + "\n" + "Heads up: Greptile's most recent review scored this PR " + f"**{score}/5**, below our merge bar of **{threshold}/5**.\n" + "\n" + "If the score isn't lifted in the next **2 hours**, I'll auto-close this PR. That's " + "**not** us saying the change isn't worthwhile. We want the open-PR list to mirror " + "what a maintainer can act on *right now*, so contributors like you don't get lost in " + "a backlog. Take your time; everything below still works after the close.\n" + "\n" + "**During the grace period:** push fixes that address Greptile's feedback, then comment " + "`@greptileai` to request a fresh review. If " + f"the new score is **{threshold}/5 or higher**, the PR stays open and no further " + "action is needed on your side.\n" + "\n" + "**If the PR does get auto-closed in 2 hours, you still have an easy recovery path:**\n" + "\n" + "- Comment `@greptileai` to request a fresh review. **This still works even after " + f"the PR is closed**, and a score of {threshold}/5 or higher is one of the signals " + "that lifts the PR back into the review queue. A low Greptile score isn't a blocker.\n" + "- Comment `@agent-shin reconsider` after pushing fixes; I'll re-run the rubric and " + "reopen the PR if both gates (description rubric + Greptile score) now pass.\n" + "\n" + f"{GRACE_COMMENT_MARKER}" + ) + + +def post_grace_warning( + pr: dict, + score: int, + threshold: int, + repo: str | None, + dry_run: bool, +) -> None: + """Post the 2-hour grace-period warning comment on `pr`. + + The warning carries `GRACE_COMMENT_MARKER` so subsequent runs can + detect that the contributor has already been told about the + pending close. Does NOT close the PR — the close happens on the + next eligible run after `GRACE_PERIOD_SECONDS` elapses (handled + by `close_pr`). + """ + pr_number = pr["number"] + repo_args = ["--repo", repo] if repo else [] + + if dry_run: + print( + f" [DRY RUN] Would post grace warning to PR #{pr_number} " + f"(greptile={score}/5): {pr['title']}" + ) + return + + comment_body = format_grace_warning_comment(score, threshold) + gh("pr", "comment", str(pr_number), "--body", comment_body, *repo_args) + print(f" Posted grace warning on PR #{pr_number} (greptile={score}/5)") + + +def format_close_comment(score: int, threshold: int) -> str: + """Comment posted when a low-Greptile-score PR is auto-closed. + + Carries `AGENT_SHIN_CLOSE_MARKER` so the `@agent-shin reconsider` path + (guarded by `was_closed_by_agent_shin`) recognizes this as an Agent Shin + close and is allowed to reopen the PR once it passes again; without the + marker that recovery path the comment advertises silently rejects the + contributor. + """ + score_sentence = ( + f"Greptile's most recent review scored this PR **{score}/5**, below " + f"our merge bar of **{threshold}/5**, and the 2-hour grace period since " + "the warning has elapsed.\n\n" + ) + return ( + f"Closing as part of automated PR triage.\n\n" + f"{score_sentence}" + "We close low-confidence PRs aggressively to keep the review queue " + "manageable for maintainers and contributors alike. **This is not a " + "rejection of the idea.** To bring this back:\n\n" + "1. Push the fixes that address Greptile's feedback (continue using " + "your existing branch is fine).\n" + "2. **Open a new PR** with the updated branch. Greptile will review " + "it again, and if it scores " + f"**{threshold}/5 or higher** a maintainer will take another look.\n\n" + "_Why open a new PR instead of reopening this one?_ GitHub does not " + "let external contributors reopen a PR that was closed by a bot or " + "maintainer, so a fresh PR is the most reliable path forward. If you " + "would prefer this exact PR re-evaluated, comment " + "`@agent-shin reconsider` once you've pushed the fixes; Agent Shin " + "will re-run triage and reopen this PR if it now meets the bar. " + "You can also comment `@greptileai` to request a fresh Greptile " + "review; that works **even after the PR is closed**.\n\n" + "Thanks for contributing to LiteLLM. We know auto-closures can sting; " + "the goal is to keep the project healthy, not to dismiss your work." + f"\n\n{AGENT_SHIN_CLOSE_MARKER}" + ) + + +def close_pr( + pr: dict, + score: int, + threshold: int, + age_days: int, + repo: str | None, + dry_run: bool, + label: str | None, +) -> None: + """Post the explanatory comment and close the PR.""" + pr_number = pr["number"] + repo_args = ["--repo", repo] if repo else [] + + if dry_run: + print( + f" [DRY RUN] Would close PR #{pr_number} " + f"(age={age_days}d, greptile={score}/5): {pr['title']}" + ) + return + + comment_body = format_close_comment(score, threshold) + gh("pr", "comment", str(pr_number), "--body", comment_body, *repo_args) + + if label: + try: + gh("pr", "edit", str(pr_number), "--add-label", label, *repo_args) + except subprocess.CalledProcessError as exc: + stderr = (exc.stderr or "").strip() + print(f" warn: failed to add label '{label}' to #{pr_number}: {stderr}") + + gh("pr", "close", str(pr_number), *repo_args) + print(f" Closed PR #{pr_number} (greptile={score}/5, age={age_days}d)") + + +def evaluate_pr( + pr: dict, + now: dt.datetime, + min_age_days: int, + min_score: int, + repo: str | None, + optout_labels: set[str], + allowlist: frozenset[str] = ALLOWLIST_LOGINS, +) -> tuple[str, int | None, int | None]: + """Decide what to do with `pr` on this triage run. + + Returns (action, score_or_none, age_days_or_none) where action is one of: + "skip-too-young", "skip-optout-label", "skip-not-allowlisted", + "skip-internal", "skip-no-greptile-score", "skip-score-ok", + "warn-grace", "skip-in-grace-period", or "close". + + Drafts are NOT skipped — the goal is "open PR count == PRs internal + collaborators need to action on", and a draft that Greptile scored <4/5 + is still in that queue. Authors can opt out via the `wip` label (see + `DEFAULT_OPTOUT_LABELS`) if they need to keep a long-lived draft open. + + Grace-period semantics: the first time a PR fails the rubric, the + action is `warn-grace` — the caller should post a warning comment but + NOT close the PR. On a subsequent run, if the warning is still less + than `GRACE_PERIOD_SECONDS` old AND the PR still fails, the action is + `skip-in-grace-period`. Once the warning ages out and the rubric is + still failing, the action is `close`. + """ + if has_optout_label(pr, optout_labels): + return ("skip-optout-label", None, None) + + created = parse_iso8601(pr["createdAt"]) + age_days = (now - created).days + # `min_age_days` defaults to 0 (close as soon as Greptile scores low). + # Set a positive value via --min-age-days for one-off backfill runs that + # want to skip very-young PRs. + if min_age_days > 0 and age_days < min_age_days: + return ("skip-too-young", None, age_days) + + # While the allowlist is active it is the sole author gate: only those + # logins are acted on and the external-only restriction is bypassed for + # them. Otherwise auto-close only external OSS contributors — internal + # contributors (BerriAI org members) handle their own backlog. + login = ((pr.get("author") or {}).get("login") or "").lower() + if allowlist: + if login not in allowlist: + return ("skip-not-allowlisted", None, age_days) + elif not is_external_pr_author(pr, repo): + return ("skip-internal", None, age_days) + + comments = fetch_pr_comments(pr["number"], repo) + extraction = extract_greptile_score(comments) + if extraction is None: + return ("skip-no-greptile-score", None, age_days) + + score, _ = extraction + if score >= min_score: + return ("skip-score-ok", score, age_days) + + grace_age = seconds_since_last_grace_warning(comments, now=now) + if grace_age is None: + return ("warn-grace", score, age_days) + if grace_age < GRACE_PERIOD_SECONDS: + return ("skip-in-grace-period", score, age_days) + + return ("close", score, age_days) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--repo", + type=str, + default=None, + help="Repository (owner/repo). Auto-detected if omitted.", + ) + parser.add_argument( + "--min-age-days", + type=int, + default=0, + help=( + "Minimum age (in days) before a PR is eligible. Default 0 = " + "close as soon as Greptile flags it. Set a positive value for " + "one-off backfill runs that want to spare very-young PRs." + ), + ) + parser.add_argument( + "--min-score", + type=int, + default=4, + choices=range(1, 6), + help="Greptile score below which a PR is closed (default: 4 -> closes <4/5).", + ) + parser.add_argument( + "--optout-label", + action="append", + default=None, + help=( + "Label(s) that exempt a PR from auto-close. Repeat to add more. " + "Case-insensitive. When omitted, defaults to " + f"{list(DEFAULT_OPTOUT_LABELS)!r}; passing this flag REPLACES the " + "defaults (argparse `append` with a mutable default would append " + "instead, which we explicitly avoid)." + ), + ) + parser.add_argument( + "--close-label", + type=str, + default=None, + help=( + "Optional label to add to PRs that get auto-closed " + "(e.g. 'auto-closed-low-quality'). Must already exist on the repo." + ), + ) + parser.add_argument( + "--close", + action="store_true", + help="Actually close matching PRs (default is dry-run).", + ) + parser.add_argument( + "--limit", + type=int, + default=None, + help="Maximum number of PRs to close in one run (safety net).", + ) + args = parser.parse_args() + + dry_run = not args.close + if dry_run: + print("=== DRY RUN MODE (pass --close to actually close PRs) ===\n") + + print("Fetching open PRs...") + prs = fetch_open_prs(args.repo) + print(f"Found {len(prs)} open PRs.\n") + + now = dt.datetime.now(dt.timezone.utc) + optout_labels = set(args.optout_label or DEFAULT_OPTOUT_LABELS) + + closed = 0 + summary = { + "close": 0, + "warn-grace": 0, + "skip-in-grace-period": 0, + "skip-too-young": 0, + "skip-optout-label": 0, + "skip-not-allowlisted": 0, + "skip-internal": 0, + "skip-no-greptile-score": 0, + "skip-score-ok": 0, + } + + # `warned` tracks grace-warning comments posted in this run so the + # `--limit` safety net bounds *all* destructive write actions, not + # just closures. Without this cap, a backlog of PRs failing the + # threshold simultaneously could flood contributors with comments. + warned = 0 + for pr in sorted(prs, key=lambda p: p["createdAt"]): + try: + action, score, age_days = evaluate_pr( + pr, + now, + args.min_age_days, + args.min_score, + args.repo, + optout_labels, + ) + summary[action] = summary.get(action, 0) + 1 + + if action == "warn-grace": + assert score is not None + print( + f"#{pr['number']}: \"{pr['title']}\" " + f"(age={age_days}d, greptile={score}/5) -> warn-grace" + ) + post_grace_warning( + pr, + score=score, + threshold=args.min_score, + repo=args.repo, + dry_run=dry_run, + ) + if not dry_run: + warned += 1 + if args.limit is not None and (warned + closed) >= args.limit: + print( + f"\nReached --limit={args.limit} " + f"(closed={closed}, warned={warned}); stopping." + ) + break + continue + + if action != "close": + continue + + assert score is not None and age_days is not None + print( + f"#{pr['number']}: \"{pr['title']}\" " + f"(age={age_days}d, greptile={score}/5) -> close" + ) + close_pr( + pr, + score=score, + threshold=args.min_score, + age_days=age_days, + repo=args.repo, + dry_run=dry_run, + label=args.close_label, + ) + + if not dry_run: + closed += 1 + if args.limit is not None and (warned + closed) >= args.limit: + print( + f"\nReached --limit={args.limit} " + f"(closed={closed}, warned={warned}); stopping." + ) + break + except Exception as exc: # noqa: BLE001 - per-PR errors don't abort the sweep + summary["error"] = summary.get("error", 0) + 1 + print( + f"!! PR #{pr.get('number')}: {exc}", + file=sys.stderr, + ) + continue + + print("\n=== Summary ===") + for key, value in summary.items(): + print(f" {key:28s} {value}") + if dry_run: + print(f"\nTotal would close: {summary['close']}") + else: + print(f"\nTotal closed: {closed}") + print( + f"Total {'would warn (grace)' if dry_run else 'warned (grace)'}: " + f"{summary['warn-grace']}" + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.github/scripts/triage-requirements.txt b/.github/scripts/triage-requirements.txt new file mode 100644 index 00000000000..a18f05fbb95 --- /dev/null +++ b/.github/scripts/triage-requirements.txt @@ -0,0 +1,282 @@ +# Hash-pinned dependency set for the Agent Shin triage scripts. +# Installed in privileged triage workflows, so every package is pinned to an +# exact version with SHA-256 hashes and installed with pip --require-hashes. +# +# Regenerate after bumping openai: +# echo 'openai==' \ +# | uv pip compile - --generate-hashes --python-version 3.12 \ +# --no-annotate --no-header -o .github/scripts/triage-requirements.txt + +annotated-types==0.7.0 \ + --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ + --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 +anyio==4.14.0 \ + --hash=sha256:b47c1f9ccf73e67021df785332508f99379c68fa7d0684e8e3492cb1d4b23f89 \ + --hash=sha256:dd9b7a2a9799ed6552fde617b2c5df02b7fdd7d88392fc48101e51bae46164d9 +certifi==2026.6.17 \ + --hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \ + --hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db +distro==1.9.0 \ + --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ + --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 +h11==0.16.0 \ + --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \ + --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 +httpcore==1.0.9 \ + --hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \ + --hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8 +httpx==0.28.1 \ + --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ + --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad +idna==3.18 \ + --hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \ + --hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848 +jiter==0.15.0 \ + --hash=sha256:01a8222cf05ab1128e239421156c207949808acaaea2bdfd33130ae666786e86 \ + --hash=sha256:032396229564bca02440396bd327710719f724f5e7b7e9f7a8eb3faa4a2c2281 \ + --hash=sha256:04b400bbf8c9efb03d9bdd976475c919c1d85593b04b9fff7ae234065daf87ae \ + --hash=sha256:05906b93d72f03339e6bb7cf8dc10ebda64a0266126eed6beba79e20abcf5fd4 \ + --hash=sha256:066f8f33f18b2419cd8213b2436fa7fbc9c499f315971cfa3ce1f9820c001b1b \ + --hash=sha256:0ab068bce62a45aa3e7367eceaffb5dde60b7eb853be8dece45132e3d0ff4879 \ + --hash=sha256:0be6f5ad41a809f303f416d17cec92a7a725902fb9b4f3de3d19362ac0ef8554 \ + --hash=sha256:0e90a1c315a0226ec822d973817967f9223b7701546c8c2a7913e7ab0926294d \ + --hash=sha256:0f862193b8696249d22ec433e85fd2ab0ad9596bc3e45e6c0bc55e8aeba97be2 \ + --hash=sha256:1303d4d68a9b051ea90502402063ecf3807da00ad2affa19ca1ae3b90b3c5f67 \ + --hash=sha256:144f8e72cb53dab146347b91cceac01f5481237f2b93b4a339a1ee8f8878b67c \ + --hash=sha256:182226cbc930c9fab81bc2e41a4da672f89539906dadb05e75670ac07b94f71f \ + --hash=sha256:1c11465f97e2abf45a014b83b730222f8f1c5335e802c7055a67d50de6f1f4e3 \ + --hash=sha256:1c15024a3d892223b18f597c86d59387249dc396590844ce6b9f6131d1093bae \ + --hash=sha256:1d54fb5b31dea401a41af3f8a7d2512e9b6a6a005491e6166c7e4ffab9639a9c \ + --hash=sha256:25ffbe229aa8cd98c28879d8aa1a6e34ae77992ab984a65fba800859dab16269 \ + --hash=sha256:2a77aadd57cac1682e4401a72724d2796d89a4ba129b1a5812aa94ee480826eb \ + --hash=sha256:2ae901f3a55bfafdde31d289590fa25e3245735a2b1e8c7cc15871710a002871 \ + --hash=sha256:2b0074e2f56eb2dacca1689760fd2852a068f85a0547a157b82cb4cafeb6768b \ + --hash=sha256:2c8aea7781d2a372227871de4e1a1332aa96f5a89fd76c5e835dafdbad102887 \ + --hash=sha256:2c9cb907439d20bd0c7d7565ca01ee52234203208433749bae5b516907526928 \ + --hash=sha256:2fb6a5d26af81fc0f00f9360a891e05cf755e149bba391c4d563adc54812973d \ + --hash=sha256:2fd73e3da91a0a722d67165e849ce2cdc10de0e0d48738c142be8c6c5f310f4c \ + --hash=sha256:30ce1a5d16b5641dc935d50ef775af6a0871e3d14ab05d6fc54dff371b78e558 \ + --hash=sha256:30ce785d2adb8e32c3f7741442370a74834ec4c01f3c48f0750227a0b4ef27d6 \ + --hash=sha256:30f2218e6a9e5c18bc10fe6d41ac189c442c88eacf11bad9f28ef95a9bef00e6 \ + --hash=sha256:351a341c2105aa430b7047e30f1bf7975f6313b00165d3fc07be2edaf741f279 \ + --hash=sha256:37a10c377ce3a4a85f4a67f28b7afe093154cde77eaf248a72e856aa08b4d865 \ + --hash=sha256:392b8ab019e5502d08aff85c6272209c24bc2cbe706ea82a56368f524236614a \ + --hash=sha256:3e4540b8e74e4268811ac05db226a6a128ff572e7e0ce3f1163b693cadb184cd \ + --hash=sha256:40b2c7e92c44a84d748d21706c68dc6ff8161d80b59c99d774721a0d2317d7c7 \ + --hash=sha256:411fa4dfa5a7ae3d11491027ffb9beadec3996010a986862db70d91abba1c750 \ + --hash=sha256:4251acc80e2b7c9b7b8823456ea0fceeb0734dac2df7636d3c711b38476b5a76 \ + --hash=sha256:42bfb257930800cf43e7c62c832402c704ab60797c992faf88d20e903eac8f32 \ + --hash=sha256:4363818355dbc70ae1a8e9eaba9de350d93ede4ff6992b8f8eb8cbb6e5122d42 \ + --hash=sha256:4ab395feec8d249ec4044e228e98a7033f043426a265df439dc3698823f0a4e4 \ + --hash=sha256:50164d7610c00e7cd913a873fce30b6beeebf4b37e53983e33f22de4c900f6b8 \ + --hash=sha256:50e51156192722a9c58db112837d3f8ef96fb3c5ecc14e95f409134b08b158ec \ + --hash=sha256:510c8b3c17a0ed9ac69850c0438dada3c9b82d9c4d589fcb62002a5a9cf3a866 \ + --hash=sha256:5157de9f76eb4bc5ea74a1219366a25f945ad305641d74e04f59c54087091aa9 \ + --hash=sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a \ + --hash=sha256:553fcac2ef2cb990877f9fc0833b8b629a3e6a5670b6b5fd58219b41a653ddc4 \ + --hash=sha256:5607e6013ed7e6b0ec9661e467b7ffde0aa7ab36833a04850f26fcf88ed4845b \ + --hash=sha256:5d6a60072b44c3c2b797a7ddcbcbbf2b34ea3cfd4721580fbfd2a09d9d9b84ba \ + --hash=sha256:5f30bae8bc1c2d613e28e5af3e8cceb09b742f1c8a8a5f839fb67afaffc03b61 \ + --hash=sha256:62ebd14e47e9aed9df4472afcb2663668ce4d74891cd54f86bf6e44029d6dc89 \ + --hash=sha256:631f13a3d04e97d4e083993b10f4b99530e3a10d953e2eb5e196b7dc7f812ce0 \ + --hash=sha256:6550fa135c7deb8ead6af49ed7ff648532ea8334a1447fe34a36315ef79c5c29 \ + --hash=sha256:66b1880df2d01e206e8339769d1c7c1753bcb653efd6289e203f6f24ebada0c0 \ + --hash=sha256:6eac374c5c975709b69c10f09afd199df74150172156ad10c8d4fd785b7da995 \ + --hash=sha256:71683c38c825452999b5717fcae07ea708e8c93003e808be4319c1b02e3d176e \ + --hash=sha256:7553333dd0930c104a5a0db8df72bf7219fe663d731383b576bb6ed6351c984d \ + --hash=sha256:75e8a04e91432dde9f1838373cf93d23726c79d3e908d319acf0e796f85592e7 \ + --hash=sha256:773b6eb282ce11ee19f05f6b2d4404fa308e5bbd353b0b80a0262caad6db2cd7 \ + --hash=sha256:774f93f65031856bf14ad9f59bdcab8b8cad501e5ceabd51ba3525f76937a25b \ + --hash=sha256:7c468136b8bd6bb18c8786e4236a1fa27362f24cb23450ba0cb204ab379b8e6f \ + --hash=sha256:7ce8902f939970048b233087082e7bb829db29375811c7ad50687b8624c6fd08 \ + --hash=sha256:7d3d6683288c11cbab50e865f2e2f13950179aa45410e30b2cfbd3fb7b0177bf \ + --hash=sha256:7f6163c0f10b055245f814dcc59f4818da60dfe72f3e72ab89fc24b6bd5e9c52 \ + --hash=sha256:8020c99ec13a7db2b6f96cbe82ef4721c88b426a4892f27478044af0284615ef \ + --hash=sha256:813dfbb17d65328bf86e5f0905dd277ba2265d3ca20556e86c0c7035b7182e5a \ + --hash=sha256:860a74063284a2ae9bfedd694f299cc2c68e2696c5f3d440cc9d18bb81b9dd04 \ + --hash=sha256:8c9004af7c8d67cce7f1aae1026fb55607f4aa600710d08ede3a3ce4aeefe7e0 \ + --hash=sha256:8d2c0c44d569ce0f2850f5c926f8caeb5f245fbc84475aeb36efccc2103e6dbd \ + --hash=sha256:8f7e9bc0f1135039b22ee6eab588d42df1ce55842b30740a352885eb267bd941 \ + --hash=sha256:90c5db5527c221249a876160663ab891ace358c17f7b9c93ec1478b7f0550e5c \ + --hash=sha256:9100ddbec09741cc66feb0fc6773f8bdbd0e3c345689368f260082ff85dcc0cd \ + --hash=sha256:913d02d29c9606643418d9ccfc3b72492ab25a6bf7889934e09a3490f8d3438b \ + --hash=sha256:980c256edb05b78a111b99c4de3b1d32e31634b867fd1fc2cf726e7b7bba9854 \ + --hash=sha256:9f924585cdacf631cd382b657966847bb537bf9ed0a6f9b991da5f05a631480f \ + --hash=sha256:a254e10b593624d230c365b6d616b22ca0ad65e63a16e6631c2b3466022e6ba8 \ + --hash=sha256:a2a438005b6f22d0273413484d6094d7c2c5d10ec1b3a3bf128e0d1d3ba53258 \ + --hash=sha256:a97261f1fccb8e50ecd2890a96e46efdc3f57c80a197324c6777827231eca712 \ + --hash=sha256:ab596fa3837e91e7e6a31b5f639988bfc6a35d1f915ac3932d946062219d588f \ + --hash=sha256:abbf258599526ad0326fe51e252e24f2bd6f24f1852681b4b78feda3808f1d18 \ + --hash=sha256:ac0d9ddea4350974be7a221fc25895f251a8fee748c889bdced2141c0fec1a49 \ + --hash=sha256:acf4ee4d1fc55917239fe72972fb292dd773055d05eb040d36f4326e02cc2c0e \ + --hash=sha256:ae1b0d82ac2d987f9ea512b1c9adfcc71a28de3dea3a6039b54d76cffda9901e \ + --hash=sha256:b15741f501469009ae0ae90b7147958a664a7dede40aa7ff174a8a4645f546d0 \ + --hash=sha256:b15d3ec9b0449c40e85319bdb4caa8b77ab526e74f5532ed94bec15e2f66822c \ + --hash=sha256:b3b3b775e33d3bfaec9899edc526ae97b0da0bf9d071a46124ba419149a414f8 \ + --hash=sha256:b6c0ffae686c39bf3737be60793783267628783ea42545632c10b291105aee45 \ + --hash=sha256:c210f8b35dc6f30aafd4b4365ca89b9d1189f21ab49b8e68fa6322a847aef138 \ + --hash=sha256:c2f6bb8b5216ab9e7873bc08b5d7bef2b8abbb578a3069bf1cd14a45d71d771d \ + --hash=sha256:c60e71b6d10cfc284c9bf36bd885e8d44c46f688ce50aa91b5edd90181dea687 \ + --hash=sha256:c6694a173ecabc12eb60efbc0b474464ead1951ff65cd8b1e72100715c64512b \ + --hash=sha256:c77496cb10bd7549690fbbab3e5ec05857b83e49276f4a9423a766ddd2afcd4c \ + --hash=sha256:c84c1b7be454b0c16f8499b4ebfbfd82ea5cca6527cceefcbbc06a7557b5ed2e \ + --hash=sha256:cc0bc345cf2df9d1c00ac443f50d543c1ccfa8b0422cb85b1ab70d681c0b255b \ + --hash=sha256:ceb8fc27d38793f9c97149be8302720c5b22e5c195a37bf2c45dc36c4600a512 \ + --hash=sha256:cf4bd113a69c0a740e27cb962ce10630c36d2b8f59d759a651b955ee9d18a823 \ + --hash=sha256:d1aa62e277fc1cbd80e6deacae6f4d983b41b3d7728e0645c5d741a6149bba45 \ + --hash=sha256:d1e7b1776f0797956c509e123d0952d10d293a9492dea9f288ab9570ec01d1a5 \ + --hash=sha256:d636d5095155afd364247f65070fab7beda13498d7ff4de331046e704ab9657f \ + --hash=sha256:d726e3ceeb337191324b49de298142f27c3ad10886341555d1d5315b5f252c6a \ + --hash=sha256:d72d8af5c1013656a8870c866660627d1a75bc185814ee022c8533caa1de88ae \ + --hash=sha256:d8d2955167274e15d79a7a020afdd9b39c990eb80b2d89fca695d92dcfdd38ec \ + --hash=sha256:d92a5cd21fdb083931d546c207aa29633787c5dc5b02daab2d32b843f88a2c53 \ + --hash=sha256:e58585a58209d72691ce2d62a9147445f5a87beb0bde97fde284c96ae392a3d1 \ + --hash=sha256:e7196e56f1cd69af1dbb07dff02dcfb260a50b45a82d409d92a06fedb32473b5 \ + --hash=sha256:eda3071db3346334beae1360b46da4606da57bf3528c167b3c38533afaf9f2c5 \ + --hash=sha256:edebcf7d1f601199084bb6e844d7dc67e03e04f6ac786b0332d616635c4ff7a4 \ + --hash=sha256:ef1fd24d9413f6209e00d3d5a453e67acfe004a25cc6c8e8484faed4311ab9e8 \ + --hash=sha256:f0b271b462769543716f92d3a4f90527df6ef5ed05ee95ec4137f513e21e1b77 \ + --hash=sha256:f18f85e4218d1b40f000f42a92239a7a61a902cd42c65e6c360dbd17dcb20894 \ + --hash=sha256:f1e1754960f38ec40613a07e5e372df67acb3b890fb383b6fb3de3e49ddbf3c7 \ + --hash=sha256:f2143ab06181d2b029eedcb6af3cebe95f11bbac62441781860f98ee9330a6a6 \ + --hash=sha256:f3d37768fce7f88dd2a8c6091f2325dea27d30d30d5c6e7a1c0f0af77723b708 \ + --hash=sha256:fa248c9eb220197d363f688818dac2fd4b2f0cd7d843ca7105d652034823427d +openai==2.33.0 \ + --hash=sha256:03ac37d70e8c9e3a8124214e3afa785e2cbc12e627fbd98177a086ef2fd87ad5 \ + --hash=sha256:f850c435e2a4685bba3295bd54912dd26315d9c1b7733068186134d6e0599f9a +pydantic==2.13.4 \ + --hash=sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba \ + --hash=sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6 +pydantic-core==2.46.4 \ + --hash=sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0 \ + --hash=sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262 \ + --hash=sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda \ + --hash=sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0 \ + --hash=sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e \ + --hash=sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b \ + --hash=sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594 \ + --hash=sha256:10e17cbb10a330363733efc4d7c4d0dd827ac0909b8f6a6542298fed1ea62f29 \ + --hash=sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2 \ + --hash=sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c \ + --hash=sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d \ + --hash=sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398 \ + --hash=sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d \ + --hash=sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3 \ + --hash=sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f \ + --hash=sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb \ + --hash=sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7 \ + --hash=sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5 \ + --hash=sha256:228ee9bae8bef5b1e97ec58302f80357c37199e0d0a99174e138d28e6957b9d9 \ + --hash=sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462 \ + --hash=sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4 \ + --hash=sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b \ + --hash=sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d \ + --hash=sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df \ + --hash=sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2 \ + --hash=sha256:3447661d99f75a3683a4cf5c87da72f2161964611864dbbeac7fbb118bb4bfc0 \ + --hash=sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519 \ + --hash=sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd \ + --hash=sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7 \ + --hash=sha256:3be77f45df024d789a672ae34f8b06fb346c4f9f46ea714956660ea4862e89ac \ + --hash=sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6 \ + --hash=sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565 \ + --hash=sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898 \ + --hash=sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb \ + --hash=sha256:432c179df7874eeb73307aad2df0755e1ae0efa61ff0ea89b93e194411ae3928 \ + --hash=sha256:4a05d69cba51d852c5c3e92758653245a50c0b646ced0cf05bd793ed592839d6 \ + --hash=sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3 \ + --hash=sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a \ + --hash=sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596 \ + --hash=sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987 \ + --hash=sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e \ + --hash=sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d \ + --hash=sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712 \ + --hash=sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008 \ + --hash=sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd \ + --hash=sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1 \ + --hash=sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be \ + --hash=sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea \ + --hash=sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292 \ + --hash=sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33 \ + --hash=sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3 \ + --hash=sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4 \ + --hash=sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b \ + --hash=sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826 \ + --hash=sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac \ + --hash=sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7 \ + --hash=sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d \ + --hash=sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf \ + --hash=sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4 \ + --hash=sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc \ + --hash=sha256:8b9bab013d1c7a79d3501ff86d0bc9c31bf587db4551677b96bec07df78c6b15 \ + --hash=sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3 \ + --hash=sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b \ + --hash=sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914 \ + --hash=sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04 \ + --hash=sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c \ + --hash=sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b \ + --hash=sha256:91a06d2e259ecfbd8c901d70c3c507900458498142b3026a296b7de4d1322cc9 \ + --hash=sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce \ + --hash=sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4 \ + --hash=sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a \ + --hash=sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f \ + --hash=sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424 \ + --hash=sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894 \ + --hash=sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9 \ + --hash=sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76 \ + --hash=sha256:9f444c499b3eefd3a92e348059471ea0c3a6e303d9c1cec09fa748fd9f895201 \ + --hash=sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb \ + --hash=sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109 \ + --hash=sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4 \ + --hash=sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848 \ + --hash=sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526 \ + --hash=sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0 \ + --hash=sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01 \ + --hash=sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458 \ + --hash=sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e \ + --hash=sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba \ + --hash=sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a \ + --hash=sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39 \ + --hash=sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c \ + --hash=sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000 \ + --hash=sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b \ + --hash=sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf \ + --hash=sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4 \ + --hash=sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd \ + --hash=sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28 \ + --hash=sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9 \ + --hash=sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30 \ + --hash=sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983 \ + --hash=sha256:d80ee3d731373b24cebbc10d689ca4ee1875caf0d5703a245db18efd4dd37fc1 \ + --hash=sha256:d995260fdf4e1db774581b4900e0f832abe3c7c84996726bbc161b19c8f29e76 \ + --hash=sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5 \ + --hash=sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4 \ + --hash=sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7 \ + --hash=sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c \ + --hash=sha256:e68b7a074f65a2fd746c52a7ce6142ab7006074ac269ace0c25cd8ba171f8066 \ + --hash=sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3 \ + --hash=sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02 \ + --hash=sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89 \ + --hash=sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50 \ + --hash=sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76 \ + --hash=sha256:f13a646d65d09fbf1bc6b3a9635d30095c8e7e5cc419ff35ecc563c5fd04cd49 \ + --hash=sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b \ + --hash=sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d \ + --hash=sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7 \ + --hash=sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4 \ + --hash=sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c \ + --hash=sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e \ + --hash=sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff \ + --hash=sha256:fd8b3d9fd264be37976686c7f65cd52a83f5e84f4bfd2adf9c1d469676bbb6ae +sniffio==1.3.1 \ + --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ + --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc +tqdm==4.68.3 \ + --hash=sha256:00dfa48452b6b6cfae3dd9885636c23d3422d1ec97c66d96818cbd5e0821d482 \ + --hash=sha256:39832cc2def2789a6f29df83f172db7416cea70052c0907a57801c5f2fdccb03 +typing-extensions==4.15.0 \ + --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ + --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 +typing-inspection==0.4.2 \ + --hash=sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 \ + --hash=sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464 diff --git a/.github/scripts/triage_rollout_heads_up.py b/.github/scripts/triage_rollout_heads_up.py new file mode 100644 index 00000000000..a5dedb1c9e7 --- /dev/null +++ b/.github/scripts/triage_rollout_heads_up.py @@ -0,0 +1,557 @@ +#!/usr/bin/env python3 +"""One-shot 7-day heads-up sweep for the Agent Shin rollout. + +Posts a friendly "the OSS triage bot kicks in next Monday" comment on every +open external PR/issue that currently *would* fail the new rubric — i.e., +every PR/issue Agent Shin would close once the rollout completes. The point +is to give contributors a full week to fix their description before the bot +ever takes a destructive action, so nobody is surprised by an auto-close. + +The script is designed to run **exactly once** at rollout, fired by a manual +``workflow_dispatch`` (``dry_run=false``) on the heads-up workflow. Re-runs +are safe: every comment is stamped with the hidden ``HEADS_UP_MARKER`` and +PRs/issues that already carry the marker are skipped. + +Dry-run vs. real run +-------------------- +Defaults to dry-run. Passing ``--close`` flips into real mode. Every GitHub +mutation goes through ``_agent_shin_actions``, which has a one-line +``if dry_run: log else: do_it`` per call, so the only difference between a +dry-run preview and the real run is the call site that actually hits the +GitHub API. + +Local preview:: + + python3 .github/scripts/triage_rollout_heads_up.py --repo BerriAI/litellm + +Real run (the manual rollout dispatch uses this):: + + python3 .github/scripts/triage_rollout_heads_up.py --repo BerriAI/litellm --close +""" + +from __future__ import annotations + +import argparse +import datetime as dt +import json +import os +import sys +from pathlib import Path +from typing import Any + +# Make the sibling triage_with_llm + _agent_shin_actions importable when this +# script is invoked directly (the GitHub workflow does `python3 .github/scripts/...`). +_SCRIPTS_DIR = Path(__file__).resolve().parent +if str(_SCRIPTS_DIR) not in sys.path: + sys.path.insert(0, str(_SCRIPTS_DIR)) + +from _agent_shin_actions import maybe_post_comment # noqa: E402 +from agent_shin_shared import ( # noqa: E402 + AGENT_SHIN_DEFAULT_BOT_LOGIN, + ALLOWLIST_LOGINS, + list_open_items, +) +from triage_with_llm import ( # noqa: E402 + DEFAULT_MODEL, + call_llm_judge, + fetch_issue, + fetch_pr, + gh, + is_internal_contributor, + review_gate, + triage, +) + +# Hidden marker so re-runs skip PRs/issues we've already notified. Distinct from +# the within-grace / ready / regressed markers so it can't be confused with the +# steady-state lifecycle comments. +HEADS_UP_MARKER = "" + +# Placeholder until the litellm-docs PR ships. The rollout blog post explains +# the new rubric, the 7-day grace, and how to recover after an auto-close. +# TODO(docs): replace with the canonical URL once the litellm-docs PR merges. +ROLLOUT_BLOG_URL = "https://docs.litellm.ai/docs/agent_shin_triage_rollout" + +# Default cutoff is one week from "now". Computed at runtime so the wording +# stays correct even if the rollout is merged later than planned. The user can +# override with --close-on YYYY-MM-DD when running the script manually. +DEFAULT_GRACE_DAYS = 7 + +# The daily auto-close sweeps (close_low_quality_prs.yml at 09:00 UTC and +# review_gate.yml at 09:30 UTC) are what actually close a still-failing item, +# so the deadline we promise contributors has to name that wall-clock moment. +ACTIVATION_TIME_UTC = "09:00 UTC" + + +def _format_cutoff(cutoff: dt.date) -> str: + """Human-readable, timezone-explicit cutoff, e.g. ``Monday, June 1, 2026 + (09:00 UTC)`` — the moment a still-failing PR/issue gets closed.""" + return ( + f"{cutoff.strftime('%A, %B')} {cutoff.day}, {cutoff.year} " + f"({ACTIVATION_TIME_UTC})" + ) + + +def _rubric_section_pr() -> str: + return ( + "**Going forward, every external PR needs ONE of:**\n" + "\n" + "- A linked GitHub issue using a closing keyword: " + "`Fixes #1234`, `Closes #1234`, or `Resolves #1234`, OR\n" + "- All three of: a clear **problem description**, **expected vs. " + "actual behavior**, and **end-to-end QA proof** (at least one of a " + "short screen recording / video, before/after screenshots, or the " + "exact commands you ran with their real output; mocked or stubbed " + "runs don't count).\n" + "\n" + "PRs also need a **Greptile confidence score of 4/5 or higher** before " + "the bot will tag them `ready for review`. You can `@greptileai` to " + "request a fresh review at any time, including after the PR is closed." + ) + + +def _rubric_section_issue() -> str: + return ( + "**Going forward, every external issue needs:**\n" + "\n" + "- For **bug reports**: end-to-end evidence of the bug (at least one " + "of a screen recording / video, a screenshot, or the exact commands " + "you ran with their real output / traceback) plus expected vs. actual " + "behavior. Written steps with no run output don't count, and mocked " + "or stubbed runs don't count.\n" + "- For **feature requests**: a clear description of the proposed " + "feature plus a use case + concrete example (config, API call, UI " + "flow, or scenario showing what's blocked today)." + ) + + +def _description_only_note(kind: str) -> str: + noun = "PR" if kind == "pr" else "issue" + return ( + f"⚠️ **The requirements must live in the {noun} *description*, not in " + "comments.** Some PRs/issues collect 100+ comments from humans and " + "bots; reading the entire thread on every triage run would balloon " + "GitHub API usage (we'd start getting 429'd) and blow out the LLM " + "judge's context. The bot only reads the description, so anything " + "you add as a comment will be invisible to it." + ) + + +def _missing_section(verdict: dict, greptile_score: int | None) -> str: + """Bullet list of what's currently missing on this PR/issue. + + Combines the LLM judge's `missing` list (rubric items) with a Greptile + shortfall (for PRs) so the contributor sees one list of things to fix. + """ + missing = list(verdict.get("missing") or []) + if greptile_score is not None and greptile_score < 4: + missing.insert( + 0, + f"Greptile's most recent review scored this PR {greptile_score}/5 " + "(below the 4/5 bar Agent Shin will require).", + ) + if not missing: + return ( + "_The bot couldn't articulate a specific missing piece; see the " + "rubric link above and double-check the description includes all " + "of it before the rollout._" + ) + bullets = "\n".join(f"- {m}" for m in missing) + return f"**What this one is currently missing:**\n\n{bullets}" + + +def _recovery_section(kind: str) -> str: + if kind == "pr": + return ( + "**If the bot closes this PR after the rollout:** update the " + "description with the missing pieces, then either open a fresh " + "PR or comment `@agent-shin reconsider` on the closed PR. If " + "Greptile re-scores you at 4/5 or higher I'll reopen and tag " + "the PR `ready for review`. (`@greptileai` works on closed PRs " + "too; a fresh review is one of the signals that lifts you back " + "into the queue.) This is **not** us losing interest in your " + "change; far from it. We just need open PRs to be a list of " + "things a maintainer can act on, so we can get to yours faster." + ) + return ( + "**If the bot closes this issue after the rollout:** edit the issue " + "description to add the missing pieces, then comment `@agent-shin " + "reconsider` on the closed issue. I'll re-evaluate and, if the rubric " + "is met, reopen it. (GitHub doesn't let external authors reopen an " + "issue a maintainer or bot closed, so the comment is the reliable " + "path.) This is **not** us saying the bug isn't real or the request " + "isn't useful; it's so the remaining open issues are a list of things " + "a maintainer can act on." + ) + + +def format_heads_up_comment( + *, kind: str, verdict: dict, greptile_score: int | None, cutoff: dt.date +) -> str: + """Compose the friendly 7-day heads-up comment posted on a failing PR/issue.""" + noun = "PR" if kind == "pr" else "issue" + rubric = _rubric_section_pr() if kind == "pr" else _rubric_section_issue() + cutoff_str = _format_cutoff(cutoff) + explanation = (verdict.get("explanation") or "").strip() + explanation_block = ( + f"> _(The judge's note for this one: {explanation})_\n\n" if explanation else "" + ) + + return ( + "🚅 **Heads-up: we're turning on the OSS triage bot in " + f"{DEFAULT_GRACE_DAYS} days, on {cutoff_str}.**\n" + "\n" + "We're rolling out **Agent Shin**, an LLM-as-judge triage bot for " + f"external {noun}s. Once it's live, the bot reads each open " + f"{noun}'s description, scores it against a small rubric, and " + f"auto-closes any {noun} that's missing the basics, with a single " + f"comment explaining what's missing and how to recover. Full " + f"context: [Agent Shin rollout blog post]({ROLLOUT_BLOG_URL}).\n" + "\n" + f"{rubric}\n" + "\n" + f"{_description_only_note(kind)}\n" + "\n" + f"{_missing_section(verdict, greptile_score)}\n" + "\n" + f"{explanation_block}" + "**Timeline (you have a week):**\n" + "\n" + f"- We turn the bot on in {DEFAULT_GRACE_DAYS} days, on " + f"**{cutoff_str}**. You have until then to update this {noun}'s " + "description with the missing pieces above.\n" + f"- If this {noun} still fails the rubric at **{cutoff_str}**, " + "we'll close it.\n" + f"- From then on the bot runs daily, and every {noun} that fails " + "the rubric gets a **2-hour lifetime**: one warning comment, then " + "auto-close 2 hours later.\n" + "\n" + f"{_recovery_section(kind)}\n" + "\n" + f"{HEADS_UP_MARKER}" + ) + + +def _list_open_numbers(repo: str, kind: str) -> list[int]: + """Return every open PR or issue number in ``repo``. + + Delegates to ``list_open_items`` so the full backlog is fetched (no cap) + and the `gh {pr,issue} list` invocation stays in one shared place. ``gh + issue list`` would include PRs, but ``list_open_items`` uses the dedicated + command per kind, so the two never mix. + """ + return [ + item["number"] for item in list_open_items(kind, repo=repo, fields="number") + ] + + +def _has_heads_up_marker(item: dict) -> bool: + """Cheap fast-path: check the PR/issue body itself for the marker. + + The marker is appended to the *comment* we post, not the body, so this + will only fire if the body literally contains the marker text. We still + do the comment-marker check separately below; this body check just lets + us short-circuit for PRs/issues that quote the marker for any reason. + """ + body = item.get("body") or "" + return HEADS_UP_MARKER in body + + +def _comments_have_marker(repo: str, number: int) -> bool: + """True if the bot already posted a comment carrying the marker. + + Used for idempotency: a re-run skips items the previous run notified. + Filters by author (matching the sibling marker-checks in + ``triage_with_llm._has_marker`` and + ``agent_shin_shared.seconds_since_latest_marker_comment``) so a + contributor who quotes the heads-up via GitHub's "Quote reply" — which + preserves HTML comments in the raw markdown — can't trick the + idempotency check into silently skipping a real heads-up. + + Comments live on the unified issues endpoint regardless of whether the + item is a PR or an issue, so no ``kind`` argument is required here. + """ + expected_login = ( + os.environ.get("AGENT_SHIN_BOT_LOGIN") or AGENT_SHIN_DEFAULT_BOT_LOGIN + ).lower() + raw = gh( + "api", + "--paginate", + f"repos/{repo}/issues/{number}/comments?per_page=100", + ) + for line in raw.splitlines(): + line = line.strip() + if not line: + continue + try: + payload = json.loads(line) + except json.JSONDecodeError: + continue + comments = payload if isinstance(payload, list) else [payload] + for comment in comments: + author = ((comment.get("user") or {}).get("login") or "").lower() + if author != expected_login: + continue + if HEADS_UP_MARKER in (comment.get("body") or ""): + return True + return False + + +def _evaluate_pr(*, repo: str, number: int, model: str, judge: Any = None) -> dict: + """Run the future PR rubric (review_gate) in dry-run and return the result.""" + return review_gate( + repo=repo, + number=number, + close=False, # we only want the verdict, never act here + model=model, + judge=judge, + ) + + +def _evaluate_issue(*, repo: str, number: int, model: str, judge: Any = None) -> dict: + """Run the future issue rubric (triage kind='issue') in dry-run.""" + return triage( + repo=repo, + kind="issue", + number=number, + close=False, + model=model, + judge=judge, + ) + + +def _would_be_closed(kind: str, result: dict) -> bool: + """True if the future triage would auto-close this PR/issue based on the + rubric (regardless of grace-period gating). + + For PRs we trust ``review_gate``'s ``passing`` field — it combines the LLM + verdict and the Greptile score. For issues we read the LLM verdict + directly. Both fields are ``None``/missing on skip paths + (skip-internal-author, skip-llm-error, etc.) where the future bot would + NOT close the item — those return False. + """ + if kind == "pr": + passing = result.get("passing") + if passing is None: + return False # skipped — nothing for the heads-up to warn about + return passing is False + verdict = result.get("verdict") or {} + return (verdict.get("verdict") or "").lower() == "fail" + + +def _process_one( + *, + repo: str, + kind: str, + number: int, + model: str, + cutoff: dt.date, + dry_run: bool, + judge: Any = None, + skip_marker_check: bool = False, + allowlist: frozenset[str] = ALLOWLIST_LOGINS, +) -> dict: + """Evaluate one PR/issue and post a heads-up if it would be auto-closed. + + Returns a per-item dict for the summary table. + """ + base = {"kind": kind, "number": number} + fetcher = fetch_pr if kind == "pr" else fetch_issue + item = fetcher(repo, number) + + if (item.get("state") or "") != "open": + return {**base, "action": "skip-not-open"} + if allowlist: + login = (item.get("user") or {}).get("login") or "" + if login.lower() not in allowlist: + return {**base, "action": "skip-not-allowlisted"} + elif is_internal_contributor(item): + return {**base, "action": "skip-internal-author"} + if not skip_marker_check and _has_heads_up_marker(item): + return {**base, "action": "skip-already-marked-in-body"} + if not skip_marker_check and _comments_have_marker(repo, number): + return {**base, "action": "skip-already-notified"} + + if kind == "pr": + result = _evaluate_pr(repo=repo, number=number, model=model, judge=judge) + else: + result = _evaluate_issue(repo=repo, number=number, model=model, judge=judge) + + if not _would_be_closed(kind, result): + return {**base, "action": "skip-passing", "evaluator": result.get("action")} + + verdict = result.get("verdict") or {} + greptile_score = result.get("greptile_score") if kind == "pr" else None + comment = format_heads_up_comment( + kind=kind, verdict=verdict, greptile_score=greptile_score, cutoff=cutoff + ) + maybe_post_comment(repo, number, comment, dry_run=dry_run) + return { + **base, + "action": "heads-up-posted" if not dry_run else "would-post-heads-up", + "verdict": (verdict.get("verdict") or "").lower(), + "greptile_score": greptile_score, + } + + +def _print_summary(results: list[dict]) -> None: + """Tally per-action counts so a dry-run preview tells you at a glance how + many comments the real run would post.""" + counts: dict[str, int] = {} + for r in results: + counts[r["action"]] = counts.get(r["action"], 0) + 1 + print("\n=== rollout heads-up summary ===") + for action in sorted(counts): + print(f" {action:35s} {counts[action]}") + print(f" total {len(results)}") + + +def run( + *, + repo: str, + close: bool, + cutoff: dt.date, + model: str, + kinds: tuple[str, ...] = ("pr", "issue"), + judge: Any = None, + only_numbers: dict[str, list[int]] | None = None, + skip_marker_check: bool = False, +) -> list[dict]: + """Sweep ``repo`` and post heads-up comments. Returns the per-item results.""" + dry_run = not close + if dry_run: + print( + f"[DRY RUN] sweeping {repo}; --close not passed, no comments will be posted." + ) + else: + print(f"[REAL RUN] sweeping {repo}; comments WILL be posted.") + print(f"Cutoff date in comment body: {cutoff.isoformat()}") + + results: list[dict] = [] + for kind in kinds: + if only_numbers and kind in only_numbers: + numbers = list(only_numbers[kind]) + else: + numbers = _list_open_numbers(repo, kind) + print(f"\n--- {kind}s: {len(numbers)} open ---") + for n in numbers: + try: + result = _process_one( + repo=repo, + kind=kind, + number=n, + model=model, + cutoff=cutoff, + dry_run=dry_run, + judge=judge, + skip_marker_check=skip_marker_check, + ) + except ( + Exception + ) as exc: # noqa: BLE001 - per-item errors don't abort the sweep + result = { + "kind": kind, + "number": n, + "action": "error", + "error": str(exc), + } + print(f"!! {kind}#{n}: {exc}", file=sys.stderr) + print(f" {kind}#{n}: {result['action']}") + results.append(result) + _print_summary(results) + return results + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--repo", required=True, help="owner/repo") + parser.add_argument( + "--close", + action="store_true", + help=( + "Actually post comments. Without this flag the script is in " + "dry-run mode and only logs what it would do." + ), + ) + parser.add_argument( + "--close-on", + type=dt.date.fromisoformat, + default=None, + help=( + "Cutoff date shown in the heads-up comment as the rollout date " + f"(default: today + {DEFAULT_GRACE_DAYS} days)." + ), + ) + parser.add_argument( + "--model", + default=os.environ.get("TRIAGE_MODEL") or DEFAULT_MODEL, + help=f"Model for the rubric LLM judge (default: {DEFAULT_MODEL}).", + ) + parser.add_argument( + "--kind", + choices=("pr", "issue", "both"), + default="both", + help="Restrict the sweep to PRs or issues only (default: both).", + ) + parser.add_argument( + "--only-pr", + type=int, + action="append", + default=[], + help="Limit the PR sweep to these PR numbers (repeat for several).", + ) + parser.add_argument( + "--only-issue", + type=int, + action="append", + default=[], + help="Limit the issue sweep to these issue numbers (repeat for several).", + ) + parser.add_argument( + "--ignore-existing-marker", + action="store_true", + help=( + "Re-post on PRs/issues that already carry the heads-up marker. " + "Useful for testing the comment wording on a known PR." + ), + ) + args = parser.parse_args() + + cutoff = args.close_on or ( + dt.datetime.now(dt.timezone.utc).date() + dt.timedelta(days=DEFAULT_GRACE_DAYS) + ) + + kinds: tuple[str, ...] + if args.kind == "pr": + kinds = ("pr",) + elif args.kind == "issue": + kinds = ("issue",) + else: + kinds = ("pr", "issue") + + only: dict[str, list[int]] = {} + if args.only_pr: + only["pr"] = args.only_pr + if args.only_issue: + only["issue"] = args.only_issue + + # The script must NOT hit the LLM in dry-run if no key is set — we still + # want a useful preview that says "skip-no-llm-key" for items that would + # have been judged. Production runs require OPENAI_API_KEY. + if args.close and not os.environ.get("OPENAI_API_KEY"): + parser.error("OPENAI_API_KEY must be set for --close (real-run) mode.") + + run( + repo=args.repo, + close=args.close, + cutoff=cutoff, + model=args.model, + kinds=kinds, + only_numbers=only or None, + skip_marker_check=args.ignore_existing_marker, + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.github/scripts/triage_with_llm.py b/.github/scripts/triage_with_llm.py new file mode 100644 index 00000000000..d2536058e01 --- /dev/null +++ b/.github/scripts/triage_with_llm.py @@ -0,0 +1,1778 @@ +#!/usr/bin/env python3 +""" +Agent Shin — LLM-as-judge triage for external OSS pull requests and issues. + +Evaluates a single PR or issue against the contribution rubric and, when the +LLM judge marks it as failing, posts an explanatory comment + closes the +PR/issue. Re-triggers on `reopened` so contributors can iterate back in by +filling in the missing pieces and reopening. + +Internal BerriAI contributors (`author_association` in {OWNER, MEMBER, +COLLABORATOR}) and bot accounts are skipped entirely. + +Usage: + triage_with_llm.py --repo owner/repo --pr 1234 + triage_with_llm.py --repo owner/repo --issue 5678 + triage_with_llm.py --repo owner/repo --pr 1234 --close # actually close + triage_with_llm.py --repo owner/repo --pr 1234 --print-prompt # show prompt + +Defaults are SAFE: without `--close` the script writes a verdict to stdout (and, +when running in GitHub Actions, to $GITHUB_STEP_SUMMARY) but takes no GitHub +write actions. + +Environment: + GH_TOKEN / GITHUB_TOKEN - for `gh` CLI auth (auto-set in Actions) + OPENAI_API_KEY - required when --close is passed + OPENAI_BASE_URL - optional (route to any OpenAI-compatible API) + TRIAGE_MODEL - optional model override (default: gpt-5.4-mini) +""" + +from __future__ import annotations + +import argparse +import datetime as dt +import json +import os +import re +import subprocess +import sys +import textwrap +import urllib.parse +from typing import Any, Iterable + +# Add this script's directory to `sys.path` so the sibling +# `agent_shin_shared` module is importable when the script is invoked +# directly (e.g. `python3 .github/scripts/triage_with_llm.py ...`) and +# also when the tests load this script via +# `importlib.util.spec_from_file_location`. +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from agent_shin_shared import ( # noqa: E402 -- sys.path adjusted above + AGENT_SHIN_CLOSE_MARKER, + AGENT_SHIN_DEFAULT_BOT_LOGIN, + ALLOWLIST_LOGINS, + GRACE_COMMENT_MARKER, + GRACE_PERIOD_SECONDS, + GREPTILE_BOT_LOGINS, + SCORE_PATTERN, + extract_greptile_score, + gh, + parse_iso8601, + seconds_since_latest_marker_comment, +) + +DEFAULT_MODEL = "gpt-5.4-mini" + +INTERNAL_ASSOCIATIONS = frozenset({"OWNER", "MEMBER", "COLLABORATOR"}) + +# `AGENT_SHIN_DEFAULT_BOT_LOGIN` is imported from `agent_shin_shared`. +# When the workflow uses the default `secrets.GITHUB_TOKEN`, the +# closure / reopen event's `actor.login` is `github-actions[bot]`. The +# env override `AGENT_SHIN_BOT_LOGIN` exists for local debugging and for +# repos that wire Agent Shin to a PAT. + +# HTML marker appended to every reconsider verdict comment. We grep for this +# on subsequent reconsider triggers to enforce a short cooldown so that +# repeated `@agent-shin reconsider` comments don't burn CI/LLM budget. +# Using a unique HTML comment keeps the marker invisible to humans while +# being trivially greppable from a comments-list API response. +RECONSIDER_COMMENT_MARKER = "" + +# Minimum gap between two reconsider verdicts on the same PR/issue. Set to +# 10 minutes — long enough that a contributor can't trivially spam the +# trigger, short enough that a genuine "I just pushed a fix and reupdated +# the body" iteration loop isn't punished. +RECONSIDER_RATE_LIMIT_SECONDS = 600 + +# `GRACE_COMMENT_MARKER` (HTML marker on the grace-period warning comment +# posted on the first low-quality detection — used on subsequent triage +# runs to detect that a warning was already posted and measure how long +# ago it was posted) and `GRACE_PERIOD_SECONDS` (length of the grace +# period between the warning and the actual auto-close, 2 hours) are +# imported from `agent_shin_shared` so the daily Greptile sweep and the +# LLM judge agree on the same marker and duration. + +# --- Review-gate ("ready for review" label lifecycle) configuration ---------- +# The review gate keeps a single label in sync with whether a PR currently +# clears BOTH quality bars: the LLM rubric (clear problem + expected/actual + +# QA proof, or a linked issue) AND Greptile's most recent confidence score. +READY_FOR_REVIEW_LABEL = "ready for review" +DEFAULT_GRACE_DAYS = 1 # 24h before an un-passing, un-tagged PR is auto-closed +DEFAULT_MIN_GREPTILE_SCORE = 4 # Greptile < 4/5 counts as "not passing" + +# Hidden HTML-comment markers stamped into review-gate comments. They never +# render in the GitHub UI but let the gate detect its own prior actions so it +# (a) posts the within-grace "what's missing" notice at most once and (b) can +# tell a first-time pass ("ready for review") from a recovery after a +# regression ("all clear again"). +READY_MARKER = "" +REGRESSED_MARKER = "" +WITHIN_GRACE_MARKER = "" + +# `GREPTILE_BOT_LOGINS` (Greptile's GitHub App login variants — +# `greptile-apps[bot]` in REST API comments, `greptile-apps` in +# `gh pr view --json` output) and `SCORE_PATTERN` (regex matching lines +# like `Confidence Score: 3/5`) are imported from `agent_shin_shared` +# so the daily sweep and the review gate read the score through the +# same set of logins / patterns. + +# `AGENT_SHIN_CLOSE_MARKER` is imported from `agent_shin_shared` so this LLM +# judge and the daily Greptile sweep stamp the same marker on their close +# comments — `was_closed_by_agent_shin` keys the reconsider reopen path off it. + +# Model families that require `reasoning_effort` to be set, and that reject +# `temperature != 1` unless `reasoning_effort` is "none". For these models we +# pass `reasoning_effort="none"` so a `temperature=0` deterministic judgment +# is still accepted. See litellm/llms/openai/chat/gpt_5_transformation.py for +# the full set of constraints LiteLLM applies to these models. +GPT5_FAMILY_PREFIX = "gpt-5" + +# Regexes for picking off "obvious passes" without burning LLM tokens. +# +# Keep this list to GitHub's documented PR-closing keywords only +# (https://docs.github.com/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue). +# Casual mentions like "see #1234" or "ref #1234" are intentionally NOT +# auto-passed — they should fall through to the LLM judge, which has the +# stricter rubric "a bare issue number without a closing keyword counts only +# if it's clearly the related issue (not a passing mention)". +LINKED_ISSUE_PATTERN = re.compile( + r"\b(?:fixes|fix|fixed|closes|close|closed|resolves|resolve|resolved)\s+" + r"(?:#\d+|https?://github\.com/[\w.-]+/[\w.-]+/issues/\d+)", + re.IGNORECASE, +) +HTML_COMMENT_PATTERN = re.compile(r"", re.DOTALL) + + +# --------------------------------------------------------------------------- +# gh helpers +# +# `gh` is imported from `agent_shin_shared` so a future change (timeout, +# logging, retry) only needs to be made once. + + +def fetch_pr(repo: str, number: int) -> dict: + """Return the full GitHub REST representation of a PR.""" + return json.loads(gh("api", f"repos/{repo}/pulls/{number}")) + + +def fetch_issue(repo: str, number: int) -> dict: + """Return the full GitHub REST representation of an issue.""" + return json.loads(gh("api", f"repos/{repo}/issues/{number}")) + + +def post_comment(repo: str, number: int, body: str) -> None: + """Post an issue-style comment (works for both issues and PRs).""" + gh( + "api", + f"repos/{repo}/issues/{number}/comments", + "-X", + "POST", + "-f", + f"body={body}", + ) + + +def close_pr(repo: str, number: int) -> None: + """Close a pull request (state=closed).""" + gh( + "api", + f"repos/{repo}/pulls/{number}", + "-X", + "PATCH", + "-f", + "state=closed", + ) + + +def reopen_pr(repo: str, number: int) -> None: + """Reopen a previously-closed pull request (state=open). + + Used by the `@agent-shin reconsider` comment-trigger flow: the bot has + write access via GH_TOKEN, so it can reopen on the contributor's behalf + even though GitHub doesn't let the OSS author do it themselves. + """ + gh( + "api", + f"repos/{repo}/pulls/{number}", + "-X", + "PATCH", + "-f", + "state=open", + ) + + +def close_issue(repo: str, number: int, *, not_planned: bool = True) -> None: + """Close an issue, marking state_reason=not_planned by default.""" + args = [ + "api", + f"repos/{repo}/issues/{number}", + "-X", + "PATCH", + "-f", + "state=closed", + ] + if not_planned: + args.extend(["-f", "state_reason=not_planned"]) + gh(*args) + + +def reopen_issue(repo: str, number: int) -> None: + """Reopen a previously-closed issue (state=open, state_reason=reopened).""" + gh( + "api", + f"repos/{repo}/issues/{number}", + "-X", + "PATCH", + "-f", + "state=open", + "-f", + "state_reason=reopened", + ) + + +def add_label(repo: str, number: int, label: str) -> None: + """Add a label to a PR/issue (GitHub creates the label if it's missing).""" + gh( + "api", + f"repos/{repo}/issues/{number}/labels", + "-X", + "POST", + "-f", + f"labels[]={label}", + ) + + +def remove_label(repo: str, number: int, label: str) -> None: + """Remove a label from a PR/issue. A missing label (404) is not an error.""" + encoded = urllib.parse.quote(label, safe="") + try: + gh( + "api", + f"repos/{repo}/issues/{number}/labels/{encoded}", + "-X", + "DELETE", + ) + except subprocess.CalledProcessError as exc: + stderr = (exc.stderr or "").lower() + if "404" in stderr or "not found" in stderr: + return + raise + + +def _iter_paginated_json(*api_args: str) -> Any: + """Yield JSON objects from `gh api --paginate ... -q '.[]'`. + + `gh api --paginate` on a JSON-array endpoint concatenates pages into + one stream; `-q '.[]'` flattens that stream into newline-delimited + objects (jq-style). This keeps memory bounded for chatty endpoints + like issue events/comments on long-lived PRs. + """ + raw = gh("api", "--paginate", *api_args, "-q", ".[]") + for line in raw.splitlines(): + line = line.strip() + if not line: + continue + try: + yield json.loads(line) + except json.JSONDecodeError: + # A malformed line should not blow up the whole guard. Skip and + # carry on — at worst the guard fail-closes (returns False / + # None) and the caller treats it as "unknown". + continue + + +def fetch_last_close_event( + repo: str, number: int +) -> tuple[str | None, dt.datetime | None]: + """Return the actor login and timestamp of the most recent `closed` event. + + Either field may be None: actor when the events API returns nothing + (unusual for a closed item, but possible on transient errors), and + timestamp when the event lacks `created_at` or the value can't be + parsed. `was_closed_by_agent_shin` fail-closes on either. + """ + actor: str | None = None + closed_at: dt.datetime | None = None + for event in _iter_paginated_json(f"repos/{repo}/issues/{number}/events"): + if event.get("event") != "closed": + continue + actor = (event.get("actor") or {}).get("login") + created = event.get("created_at") + if not created: + closed_at = None + continue + try: + closed_at = parse_iso8601(created) + except ValueError: + closed_at = None + return actor, closed_at + + +# How much older than the latest `closed` event the Agent Shin marker +# comment is allowed to be while still counting as "this close was Agent +# Shin's". Agent Shin posts the close comment immediately before closing, +# so the marker timestamp is normally at most a few seconds before the +# close event; the buffer just absorbs clock skew between the comments +# API and the events API. +AGENT_SHIN_CLOSE_MARKER_SKEW_SECONDS = 300 + + +def was_closed_by_agent_shin( + repo: str, number: int, *, bot_login: str | None = None +) -> bool: + """Return True iff Agent Shin itself most-recently closed this PR/issue. + + This is the guard that stops `@agent-shin reconsider` from reopening an + item Agent Shin did not close — a maintainer closing for non-rubric + reasons (security, duplicate, design rejection), or a different workflow + (stale/duplicate sweeps) closing under the shared `github-actions[bot]` + identity. Three independent signals must all hold, because that identity + is not unique to Agent Shin and a marker comment from a prior + closed/reopened cycle would otherwise vouch for an unrelated close: + + 1. The most recent `closed` event's actor is the bot identity. + 2. Agent Shin left one of its auto-close comments, detected via + `AGENT_SHIN_CLOSE_MARKER`. The actor check alone can't tell an + Agent Shin close from any other `github-actions[bot]` close. + 3. That marker comment was posted at (or just before) the latest + close event, not on a previous close in an + Agent-Shin-close -> reconsider-reopen -> other-bot-reclose cycle. + + The check is intentionally fail-closed: any uncertainty about who closed + the item is treated as "not Agent Shin" so the destructive reopen path + stays gated. + """ + expected = ( + bot_login + or os.environ.get("AGENT_SHIN_BOT_LOGIN") + or AGENT_SHIN_DEFAULT_BOT_LOGIN + ).lower() + actor, closed_at = fetch_last_close_event(repo, number) + if not actor or actor.lower() != expected or closed_at is None: + return False + marker_seconds = seconds_since_last_agent_shin_close( + repo, number, bot_login=bot_login + ) + if marker_seconds is None: + return False + close_age_seconds = (dt.datetime.now(dt.timezone.utc) - closed_at).total_seconds() + return marker_seconds <= close_age_seconds + AGENT_SHIN_CLOSE_MARKER_SKEW_SECONDS + + +def _seconds_since_latest_marker_comment( + repo: str, + number: int, + *, + marker: str, + bot_login: str | None = None, +) -> float | None: + """Return seconds since the bot's most recent comment with ``marker``. + + Fetches comments via `_iter_paginated_json` and delegates the + iteration / author-filter / timestamp logic to + `agent_shin_shared.seconds_since_latest_marker_comment` so the daily + Greptile sweep and the LLM judge use one source of truth for the + "bot already posted X" detection. The wall-clock `now` is resolved + against this module's `dt` so tests that freeze time via + `monkeypatch.setattr(triage_module, "dt", ...)` still apply. + """ + return seconds_since_latest_marker_comment( + _iter_paginated_json(f"repos/{repo}/issues/{number}/comments"), + marker=marker, + bot_login=bot_login, + now=dt.datetime.now(dt.timezone.utc), + ) + + +def seconds_since_last_reconsider_verdict( + repo: str, number: int, *, bot_login: str | None = None +) -> float | None: + """Return seconds since the bot's most recent reconsider verdict comment. + + Detects comments by matching the HTML marker `RECONSIDER_COMMENT_MARKER` + appended by `format_reopen_comment` and + `format_reconsider_still_failing_comment`. Returns None when the bot + has never posted a reconsider verdict on this PR/issue (or when the + only matching comments are missing a `created_at` timestamp, which + shouldn't happen on a real GitHub response). + """ + return _seconds_since_latest_marker_comment( + repo, number, marker=RECONSIDER_COMMENT_MARKER, bot_login=bot_login + ) + + +def seconds_since_last_grace_warning( + repo: str, number: int, *, bot_login: str | None = None +) -> float | None: + """Return seconds since the bot's most recent grace-period warning. + + Detects warning comments by matching the HTML marker + `GRACE_COMMENT_MARKER` appended by `format_grace_warning_pr_comment` + and `format_grace_warning_issue_comment`. Returns None when no + grace warning has ever been posted on this PR/issue — that's the + "first low-quality detection" signal that drives the warning path. + """ + return _seconds_since_latest_marker_comment( + repo, number, marker=GRACE_COMMENT_MARKER, bot_login=bot_login + ) + + +def seconds_since_last_agent_shin_close( + repo: str, number: int, *, bot_login: str | None = None +) -> float | None: + """Return seconds since Agent Shin's most recent auto-close comment. + + Detects close comments by matching `AGENT_SHIN_CLOSE_MARKER` (stamped by + `format_pr_close_comment` / `format_issue_close_comment`). Returns None + when Agent Shin has never closed this PR/issue — the signal + `was_closed_by_agent_shin` uses to keep the reconsider reopen path gated + against closures performed by other workflows sharing the bot identity. + """ + return _seconds_since_latest_marker_comment( + repo, number, marker=AGENT_SHIN_CLOSE_MARKER, bot_login=bot_login + ) + + +# --------------------------------------------------------------------------- +# Author classification + + +def is_internal_contributor(item: dict) -> bool: + """Return True if the PR/issue author should be exempted from triage. + + Fail-safe: if `author_association` is missing or empty (which should never + happen on a successful GitHub REST response but is possible on schema + changes or partial responses), treat the author as INTERNAL so the + destructive close path never fires on an unknown contributor. This matches + the sibling `is_external_pr_author` in `close_low_quality_prs.py`. + """ + login = ((item.get("user") or {}).get("login") or "").lower() + if login.endswith("[bot]") or login in {"dependabot", "github-actions"}: + return True + association = (item.get("author_association") or "").upper() + if not association or association in INTERNAL_ASSOCIATIONS: + return True + return False + + +# --------------------------------------------------------------------------- +# Greptile score + age helpers (`extract_greptile_score`, `parse_iso8601`) +# live in `agent_shin_shared` — they're imported at the top of this module +# so both `triage_with_llm.py` and `close_low_quality_prs.py` share a +# single source of truth for the Confidence-Score regex and ISO-8601 +# parsing. + + +# --------------------------------------------------------------------------- +# Prompt construction + + +def strip_html_comments(text: str) -> str: + """Remove HTML comments — template placeholder text shouldn't fool the judge.""" + return HTML_COMMENT_PATTERN.sub("", text or "") + + +def has_linked_issue(text: str) -> bool: + """Heuristic: does this body link to an open issue (Fixes #123 etc.)?""" + return bool(LINKED_ISSUE_PATTERN.search(strip_html_comments(text or ""))) + + +def build_pr_prompt(*, title: str, body: str) -> str: + cleaned_body = strip_html_comments(body or "").strip() or "(empty)" + # Dedent the static template *before* interpolating dynamic fields so that + # multi-line bodies (whose 2nd+ lines start at column 0) don't defeat the + # common-indent computation in textwrap.dedent. + template = textwrap.dedent(""" + You are "Agent Shin", the OSS triage bot for the LiteLLM open-source + repository (BerriAI/litellm). Decide whether this external pull request + meets the project's contribution standards. + + A PR PASSES triage only if BOTH (1) AND (2) are satisfied. A linked + issue alone is NOT enough — it covers context, not proof. + + (1) CONTEXT — the PR provides AT LEAST ONE of: + (a) A link to a related GitHub issue. Acceptable forms: + "Fixes #1234", "Closes #1234", "Resolves #1234", + "Refs https://github.com/BerriAI/litellm/issues/1234". A + bare "#1234" without a closing keyword counts only if it + is clearly the related issue (not a passing mention). + (b) A clear problem description in the body (what bug or + missing feature this addresses, beyond the title) AND + expected vs. actual behavior (or, for features, "what's + possible now vs. with this PR"). + + (2) END-TO-END QA PROOF: the PR body contains AT LEAST ONE of: + (a) A screen recording / video showing the behavior before + and after the change (the bug reproducing, then the fix + working). For a brand-new feature with no meaningful + "before", a recording of it working end-to-end is fine. + (b) A screenshot (or before/after screenshots) showing the + fix or feature working. + (c) Specific commands that were actually run (curl, python, + a CLI invocation, etc.) PAIRED WITH their real + output, demonstrating the change works end-to-end against + the real system. Commands whose external dependencies + (LLM provider, DB, network) are mocked or stubbed do NOT + satisfy (2c); they are not end-to-end. + + `has_qa_proof` must be set to `true` only when (2a), (2b), + or a non-mocked (2c) is actually present in the body. If the + only "proof" is mocked tests, `has_qa_proof` is `false` and + the verdict is "fail". + + The following do NOT count as QA proof: + - Generic claims like "I tested it", "works locally", "all + tests pass", or a checked "I added tests" checkbox with no + output shown. + - A description of what tests exist or were added, without + their actual output in the PR body. + - `pytest` (or any test runner) executed against the + repository's own unit tests. Those mock the LLM provider, + DB, and network, so they are NOT end-to-end and never + satisfy (2), no matter how much passing output is pasted. + - A linked issue. The linked issue is context (1a), never + proof (2). + + FAIL the PR if EITHER (1) or (2) is missing. Do not bias toward PASS: + if QA proof is absent, the verdict is "fail" even when the rest of + the PR is well-written. + + Respond with a single JSON object, no prose: + + {{ + "verdict": "pass" | "fail", + "linked_issue": boolean, + "has_problem_description": boolean, + "has_expected_vs_actual": boolean, + "has_qa_proof": boolean, + "qa_proof_type": "video" | "screenshot" | "commands_with_output" | "none", + "missing": ["plain-english strings naming what is missing"], + "explanation": "1-2 sentence reasoning for the team to skim" + }} + + --- + PR title: {title} + + PR body: + --- + {cleaned_body} + --- + """).strip() + return template.format(title=title, cleaned_body=cleaned_body) + + +def build_issue_prompt(*, title: str, body: str) -> str: + cleaned_body = strip_html_comments(body or "").strip() or "(empty)" + # Dedent the static template *before* interpolating dynamic fields so that + # multi-line bodies (whose 2nd+ lines start at column 0) don't defeat the + # common-indent computation in textwrap.dedent. + template = textwrap.dedent(""" + You are "Agent Shin", the OSS triage bot for the LiteLLM open-source + repository (BerriAI/litellm). Decide whether this GitHub issue meets + the project's reporting standards. + + For a BUG REPORT the issue PASSES triage only when it contains BOTH: + (1) END-TO-END EVIDENCE OF THE BUG (the "before"; set + `has_repro=true` only when this is present): AT LEAST ONE of: + (a) A screen recording / video of the bug happening. + (b) A screenshot of the bug. + (c) The exact command(s) actually run (curl, python, a CLI + invocation, etc.) PAIRED WITH their real output, traceback, + or logs showing the failure against the real system. + Commands whose external dependencies (LLM provider, DB, + network) are mocked or stubbed do NOT count. + Prose-only "steps to reproduce" with no run output, video, or + screenshot do NOT satisfy (1). + (2) Expected vs. actual behavior (`has_expected_vs_actual`). + + FAIL the bug report if either (1) or (2) is missing. Do not bias + toward PASS: if the bug isn't demonstrated end-to-end, the verdict is + "fail" even when the report is well-written. + + For a FEATURE REQUEST the issue PASSES triage only when it contains + ALL of: + - A clear description of the proposed feature (what should LiteLLM do + that it does not today). + - Motivation / use case with a concrete example (config, API call, + UI flow, or scenario showing what's blocked today). + + For an issue that is neither a bug report nor a feature request (a + question, support request, or discussion), PASS as long as it has a + clear, specific ask and is not empty or template placeholder text. + + Respond with a single JSON object, no prose: + + {{ + "verdict": "pass" | "fail", + "kind": "bug" | "feature" | "other", + "has_repro": boolean, + "has_expected_vs_actual": boolean, + "has_motivation_example": boolean, + "missing": ["plain-english strings naming what is missing"], + "explanation": "1-2 sentence reasoning for the team to skim" + }} + + --- + Issue title: {title} + + Issue body: + --- + {cleaned_body} + --- + """).strip() + return template.format(title=title, cleaned_body=cleaned_body) + + +# --------------------------------------------------------------------------- +# LLM call + verdict parsing + + +def call_llm_judge( + prompt: str, *, model: str, api_key: str, base_url: str | None +) -> str: + """Call an OpenAI-compatible chat completions endpoint. Returns raw text.""" + # Import inside the function so unit tests that monkey-patch this never + # need the openai package installed. + from openai import OpenAI + + client = ( + OpenAI(api_key=api_key, base_url=base_url) + if base_url + else OpenAI(api_key=api_key) + ) + kwargs: dict[str, Any] = { + "model": model, + "messages": [{"role": "user", "content": prompt}], + "temperature": 0, + "response_format": {"type": "json_object"}, + } + # gpt-5.x reasoning models reject `temperature != 1` unless + # `reasoning_effort` is explicitly "none". Set it via `extra_body` so this + # works across openai SDK versions regardless of whether the SDK natively + # types `reasoning_effort` as a top-level chat-completions param yet. + if model.lower().startswith(GPT5_FAMILY_PREFIX): + kwargs["extra_body"] = {"reasoning_effort": "none"} + response = client.chat.completions.create(**kwargs) + return response.choices[0].message.content or "" + + +def parse_verdict(raw: str) -> dict: + """Parse the LLM's JSON response. Tolerates ```json fences and stray text.""" + if not raw: + raise ValueError("empty LLM response") + text = raw.strip() + if text.startswith("```"): + text = re.sub(r"^```(?:json)?\s*", "", text) + text = re.sub(r"\s*```$", "", text) + try: + return json.loads(text) + except json.JSONDecodeError: + match = re.search(r"\{.*\}", text, re.DOTALL) + if not match: + raise ValueError(f"could not extract JSON from LLM response: {raw[:200]}") + return json.loads(match.group(0)) + + +# --------------------------------------------------------------------------- +# Comment composition + + +def _format_missing(missing: list[str]) -> str: + if not missing: + return "- (see explanation below)" + return "\n".join(f"- {m}" for m in missing) + + +# Rubric items the judge can mark present. The first element of each tuple is +# the verdict-JSON boolean field, the second is the human-readable label we +# render in the "what you got right" section of close / grace-warning comments. +_PR_PRESENT_LABELS: tuple[tuple[str, str], ...] = ( + ("linked_issue", "Linked a related GitHub issue"), + ("has_problem_description", "Clear problem description"), + ("has_expected_vs_actual", "Expected vs. actual behavior"), + ("has_qa_proof", "End-to-end QA proof"), +) + +# Issue rubric labels grouped by `kind`. The judge sets `kind` to one of +# {"bug", "feature", "other"}; when "other" we render both groups so we don't +# silently drop a present-flag the judge actually set to True. +_ISSUE_BUG_LABELS: tuple[tuple[str, str], ...] = ( + ( + "has_repro", + "End-to-end evidence of the bug (video, screenshot, or command + real output)", + ), + ("has_expected_vs_actual", "Expected vs. actual behavior"), +) +_ISSUE_FEATURE_LABELS: tuple[tuple[str, str], ...] = ( + ("has_motivation_example", "Motivation and concrete example"), +) + + +def _format_present_for_pr(verdict: dict) -> list[str]: + """Human-readable rubric items the judge confirmed are present on a PR. + + Drives the "what you got right" section in close / grace-warning comments. + The user gave explicit feedback: contributors should see what they nailed + *before* the list of gaps, so the comment doesn't read as pure rejection. + """ + return [label for field, label in _PR_PRESENT_LABELS if verdict.get(field)] + + +def _format_present_for_issue(verdict: dict) -> list[str]: + """Human-readable rubric items the judge confirmed are present on an issue. + + Branches on the judge's `kind` field. For `"other"` (or missing kind) we + render the union so a present-flag isn't dropped just because the judge + couldn't classify the issue cleanly. + """ + kind = (verdict.get("kind") or "").lower() + groups: list[tuple[tuple[str, str], ...]] = [] + if kind in ("bug", "other", ""): + groups.append(_ISSUE_BUG_LABELS) + if kind in ("feature", "other", ""): + groups.append(_ISSUE_FEATURE_LABELS) + out: list[str] = [] + for group in groups: + for field, label in group: + if verdict.get(field) and label not in out: + out.append(label) + return out + + +def _format_present_block(items: list[str]) -> str: + """Render the optional "what you got right" block. Empty string when the + judge didn't confirm anything as present — better to omit the section + entirely than to show "What you got right: (nothing)". + """ + if not items: + return "" + bullets = "\n".join(f"- ✅ {item}" for item in items) + return f"**What you got right:**\n\n{bullets}\n\n" + + +def format_pr_close_comment(verdict: dict) -> str: + missing_lines = _format_missing(verdict.get("missing") or []) + present_block = _format_present_block(_format_present_for_pr(verdict)) + explanation = verdict.get("explanation") or "" + return ( + "🚅 Hi, thanks for the PR! I'm **Agent Shin**, the automated triage bot for this " + "repository. " + "[What's this and why am I getting it?](https://docs.litellm.ai/blog/agent-shin-triage)\n" + "\n" + "I read the description against our " + "[contribution rubric](https://github.com/BerriAI/litellm/blob/main/.github/pull_request_template.md). " + "Here's how it lined up:\n" + "\n" + f"{present_block}" + "**What's still missing:**\n" + "\n" + f"{missing_lines}\n" + "\n" + f"> {explanation}\n" + "\n" + "**Closing this PR isn't a rejection of the change.** We want the open-PR list to " + "mirror what a maintainer can act on *right now*, so contributors don't get lost in a " + 'backlog. A closed PR is a soft "park this for later"; your work is still here, ' + "the diff is still here, and getting it reopened is one comment away. Take your time.\n" + "\n" + "**To bring this PR back:**\n" + "\n" + "- Update the description with the missing pieces, then comment `@agent-shin reconsider` " + "on this PR. I'll re-evaluate and reopen if it now passes.\n" + "- Or **Open a new PR** with the same fix and the updated description. GitHub doesn't " + "always let external contributors reopen a bot-closed PR, so a fresh PR is the most " + "reliable path back into the review queue.\n" + "- If Greptile's most recent score on this PR was below 4/5, comment `@greptileai` to " + "request a fresh review; that **still works even after the PR is closed**, and a " + "stronger score is one of the signals that lifts the PR back into the queue. A low " + "Greptile score isn't a blocker.\n" + "\n" + '**What "end-to-end QA proof" means**, since it\'s the most common gap: at least one ' + "of a short before/after screen recording / video (the bug reproducing, then the fix " + "working; for a brand-new feature, a recording of it working end-to-end), a screenshot " + "(or before/after screenshots) of it working, or the exact commands you ran paired " + "with their **real output** against the real system. Running `pytest` on the repo's " + "unit tests doesn't count; those mock the LLM provider, DB, and network, so they " + "aren't end-to-end. Output from a real, no-mocks integration run is what we look " + "for. A linked issue alone isn't enough either: it covers context, not proof. See " + "[the full rubric](https://docs.litellm.ai/blog/agent-shin-triage#the-rubric-for-pull-requests).\n" + "\n" + "Internal BerriAI contributors: this rubric doesn't apply to you; ping a maintainer.\n" + "\n" + "_(I'm an LLM, so I'm not infallible. If you think I got this wrong, comment " + "`@agent-shin reconsider` or ping a maintainer; they'll override me.)_" + f"\n\n{AGENT_SHIN_CLOSE_MARKER}" + ) + + +def format_issue_close_comment(verdict: dict) -> str: + missing_lines = _format_missing(verdict.get("missing") or []) + present_block = _format_present_block(_format_present_for_issue(verdict)) + explanation = verdict.get("explanation") or "" + return ( + "🚅 Hi, thanks for filing this! I'm **Agent Shin**, the automated triage bot for this " + "repository. " + "[What's this and why am I getting it?](https://docs.litellm.ai/blog/agent-shin-triage)\n" + "\n" + "I read the issue against our reporting checklist. Here's how it lined up:\n" + "\n" + f"{present_block}" + "**What's still missing:**\n" + "\n" + f"{missing_lines}\n" + "\n" + f"> {explanation}\n" + "\n" + "**Closing this isn't us saying the bug isn't real or the request isn't useful.** We " + "want the open-issue list to mirror what a maintainer can act on *right now*, so " + "reports like yours don't get buried in a backlog. A closed issue is a soft \"park " + 'this for later"; your report is still here, and getting it reopened is one comment ' + "away. Take your time.\n" + "\n" + "**To bring this issue back:**\n" + "\n" + "1. Edit the issue description to add the missing pieces:\n" + " - For **bug reports**: end-to-end evidence of the bug (a screen recording / " + "video, a screenshot, or the exact commands you ran with their real output / " + "traceback) plus expected vs. actual behavior. Written steps with no run output, " + "video, or screenshot don't count, and mocked or stubbed runs don't count.\n" + " - For **feature requests**: a concrete description of what should change, plus a " + "use case and example (config / API call / UI flow).\n" + "2. Comment `@agent-shin reconsider`. I'll re-run triage and reopen the issue if it " + "now meets the bar. (GitHub doesn't let external authors reopen an issue a maintainer " + "or bot closed, so the comment-based reconsider is the reliable path.)\n" + "\n" + "Internal BerriAI contributors: this rubric doesn't apply to you; ping a maintainer.\n" + "\n" + "_(I'm an LLM, so I'm not infallible. If you think I got this wrong, comment " + "`@agent-shin reconsider` or ping a maintainer; they'll override me.)_" + f"\n\n{AGENT_SHIN_CLOSE_MARKER}" + ) + + +def format_grace_warning_pr_comment(verdict: dict) -> str: + """Comment posted on the FIRST low-quality detection — gives the + contributor a 2-hour grace window to fix the PR before the next + triage run actually closes it. + + This is the "before-close" warning. On the second triage run, if the + grace marker is older than `GRACE_PERIOD_SECONDS` AND the PR still + fails the rubric, the close path runs (which posts + `format_pr_close_comment` and closes the PR). + """ + missing_lines = _format_missing(verdict.get("missing") or []) + present_block = _format_present_block(_format_present_for_pr(verdict)) + explanation = verdict.get("explanation") or "" + return ( + "🚅 Hi, thanks for the PR! I'm **Agent Shin**, the automated triage bot for this " + "repository. " + "[What's this and why am I getting it?](https://docs.litellm.ai/blog/agent-shin-triage)\n" + "\n" + "I read the description against our " + "[contribution rubric](https://github.com/BerriAI/litellm/blob/main/.github/pull_request_template.md). " + "Here's how it lined up:\n" + "\n" + f"{present_block}" + "**What's still missing:**\n" + "\n" + f"{missing_lines}\n" + "\n" + f"> {explanation}\n" + "\n" + "If the description isn't updated in the next **2 hours**, I'll auto-close this PR. " + "That's **not** us saying we don't care about the change; we want the open-PR list to " + "mirror what a maintainer can act on *right now*, so contributors don't get lost in a " + 'backlog. A closed PR is a soft "park this for later," not a rejection. Take your ' + "time; everything below still works after the close.\n" + "\n" + "**During the grace period:** just update the PR description with the missing pieces. " + "No need to ping me; I'll re-check on the next sweep and skip the auto-close if it " + "now passes. See " + "[what counts as QA proof](https://docs.litellm.ai/blog/agent-shin-triage#the-rubric-for-pull-requests) " + "for the full rubric (a linked issue alone isn't enough; it covers context, not proof).\n" + "\n" + "**If the PR does get auto-closed in 2 hours, you still have easy recovery paths:**\n" + "\n" + "- Comment `@agent-shin reconsider` after updating the description. I'll re-evaluate " + "and reopen the PR if it now passes.\n" + "- Comment `@greptileai` to request a fresh Greptile review; that **still works even " + "after the PR is closed**, and a stronger score is one of the signals that lifts the " + "PR back into the queue. So a low Greptile score isn't a blocker either.\n" + "\n" + "Internal BerriAI contributors: this rubric doesn't apply to you; ping a maintainer.\n" + "\n" + "_(I'm an LLM, so I'm not infallible. If you think I got this wrong, ping a " + "maintainer; they'll override me.)_\n" + "\n" + f"{GRACE_COMMENT_MARKER}" + ) + + +def format_grace_warning_issue_comment(verdict: dict) -> str: + """Issue analogue of `format_grace_warning_pr_comment`.""" + missing_lines = _format_missing(verdict.get("missing") or []) + present_block = _format_present_block(_format_present_for_issue(verdict)) + explanation = verdict.get("explanation") or "" + return ( + "🚅 Hi, thanks for filing this! I'm **Agent Shin**, the automated triage bot for this " + "repository. " + "[What's this and why am I getting it?](https://docs.litellm.ai/blog/agent-shin-triage)\n" + "\n" + "I read the issue against our reporting checklist. Here's how it lined up:\n" + "\n" + f"{present_block}" + "**What's still missing:**\n" + "\n" + f"{missing_lines}\n" + "\n" + f"> {explanation}\n" + "\n" + "If the issue isn't updated in the next **2 hours**, I'll auto-close it. That's **not** us " + "saying the bug isn't real or the request isn't useful; we want the open-issue list " + "to mirror what a maintainer can act on *right now*, so reports like yours don't get " + 'buried in a backlog. A closed issue is a soft "park this for later," not a ' + "rejection. Take your time; reopening is one comment away.\n" + "\n" + "**During the grace period:** just edit the issue description with the missing " + "pieces. No need to ping me; I'll re-check on the next sweep and skip the auto-close " + "if it now passes.\n" + "\n" + "Missing pieces, depending on what this is:\n" + "\n" + "- For **bug reports**: end-to-end evidence of the bug (a screen recording / video, a " + "screenshot, or the exact commands you ran with their real output / traceback) plus " + "expected vs. actual behavior. Written steps with no run output don't count, and " + "mocked or stubbed runs don't count.\n" + "- For **feature requests**: a concrete description of what should change, plus a use " + "case and example (config / API call / UI flow).\n" + "\n" + "**If the issue does get auto-closed in 2 hours**, comment `@agent-shin reconsider` " + "and I'll re-evaluate. If it now meets the bar, I'll reopen the issue.\n" + "\n" + "Internal BerriAI contributors: this rubric doesn't apply to you; ping a maintainer.\n" + "\n" + "_(I'm an LLM, so I'm not infallible. If you think I got this wrong, ping a " + "maintainer; they'll override me.)_\n" + "\n" + f"{GRACE_COMMENT_MARKER}" + ) + + +# --------------------------------------------------------------------------- +# Step-summary helpers + + +def write_step_summary(content: str) -> None: + """When running inside GitHub Actions, append to the step summary file.""" + path = os.environ.get("GITHUB_STEP_SUMMARY") + if not path: + return + try: + with open(path, "a", encoding="utf-8") as handle: + handle.write(content) + if not content.endswith("\n"): + handle.write("\n") + except OSError as exc: + print(f"warn: failed to write step summary: {exc}", file=sys.stderr) + + +# --------------------------------------------------------------------------- +# Core orchestration + + +def format_reopen_comment(kind: str) -> str: + """Comment posted when Agent Shin reopens after a successful reconsider.""" + noun = "PR" if kind == "pr" else "issue" + # The trailing HTML marker is used by `seconds_since_last_reconsider_verdict` + # to enforce a cooldown between repeated `@agent-shin reconsider` triggers. + # Keep the marker on its own line so it doesn't disturb the rendered text. + return ( + f"♻️ **Re-evaluated and reopened.** Thanks for updating the {noun}!\n" + "\n" + "Agent Shin re-ran triage on the latest description and it now meets " + "the bar. A maintainer will take another look soon; please don't " + f"close this {noun} again unless asked to.\n" + "\n" + "_(If a maintainer ends up closing this for non-rubric reasons, that " + "decision stands; comment `@agent-shin reconsider` again only if you " + "have substantively new information.)_\n" + "\n" + f"{RECONSIDER_COMMENT_MARKER}" + ) + + +def format_reconsider_still_failing_comment(kind: str, verdict: dict) -> str: + """Comment posted when reconsider re-runs triage but the verdict is still fail.""" + missing_lines = _format_missing(verdict.get("missing") or []) + explanation = verdict.get("explanation") or "" + noun = "PR" if kind == "pr" else "issue" + # The trailing HTML marker is used by `seconds_since_last_reconsider_verdict` + # to enforce a cooldown between repeated `@agent-shin reconsider` triggers. + return ( + f"⏸️ **Re-evaluated; this {noun} still doesn't meet the rubric.**\n" + "\n" + "Agent Shin re-ran triage on the current description but is still " + "missing:\n" + "\n" + f"{missing_lines}\n" + "\n" + f"> {explanation}\n" + "\n" + "Update the description with the missing pieces and comment " + "`@agent-shin reconsider` again, or ping a maintainer if you think " + "I got this wrong.\n" + "\n" + "_(I'm an LLM and I'm not infallible.)_\n" + "\n" + f"{RECONSIDER_COMMENT_MARKER}" + ) + + +# --------------------------------------------------------------------------- +# Review gate — "ready for review" label lifecycle + +_UNSET = object() + + +def _combine_missing( + verdict: dict, greptile_score: int | None, min_score: int +) -> list[str]: + """Merge the LLM rubric's `missing` list with a Greptile-score shortfall.""" + missing = list(verdict.get("missing") or []) + if greptile_score is not None and greptile_score < min_score: + missing.insert( + 0, + f"Greptile's most recent review scored this PR {greptile_score}/5 " + f"(below the {min_score}/5 bar)", + ) + return missing or ["(see explanation below)"] + + +def _has_marker( + comments: Iterable[dict], marker: str, *, bot_login: str | None = None +) -> bool: + """Return True iff the bot itself posted a comment containing ``marker``. + + Filters by author so a contributor who quotes the marker (e.g. via + GitHub's "Quote reply" feature, which preserves HTML comments in + raw markdown) is not mistaken for a bot action — that would + silently suppress notifications or change which "recovered" wording + is selected. Matches the author-filter pattern used by the sibling + `_seconds_since_latest_marker_comment` helper. + """ + expected_login = ( + bot_login + or os.environ.get("AGENT_SHIN_BOT_LOGIN") + or AGENT_SHIN_DEFAULT_BOT_LOGIN + ).lower() + for comment in comments: + author = ((comment.get("user") or {}).get("login") or "").lower() + if author != expected_login: + continue + if marker in (comment.get("body") or ""): + return True + return False + + +def format_ready_for_review_comment( + verdict: dict, + greptile_score: int | None, + min_greptile_score: int = DEFAULT_MIN_GREPTILE_SCORE, +) -> str: + """Posted the first time a PR clears the bar (label added).""" + score_line = ( + f" Greptile scored it **{greptile_score}/5**." + if greptile_score is not None + else "" + ) + explanation = verdict.get("explanation") or "" + return ( + "✅ **Triage passed, tagging `ready for review`.**\n" + "\n" + "Agent Shin checked this PR against the " + "[contribution rubric](https://github.com/BerriAI/litellm/blob/main/.github/pull_request_template.md) " + "and it clears the bar (a linked issue, or a clear problem description " + f"+ expected vs. actual + QA proof).{score_line}\n" + "\n" + f"> {explanation}\n" + "\n" + "A maintainer will take it from here. If a later re-check finds the PR " + f"has regressed (Greptile drops below {min_greptile_score}/5, " + "the QA proof is removed, etc.) I'll pull the tag and comment with " + "what's missing; fix it and the tag comes back automatically.\n" + f"{READY_MARKER}" + ) + + +def format_all_clear_comment(verdict: dict, greptile_score: int | None) -> str: + """Posted when a PR recovers after a regression (label re-added).""" + score_line = ( + f" Greptile is back to **{greptile_score}/5**." + if greptile_score is not None + else "" + ) + explanation = verdict.get("explanation") or "" + return ( + "✅ **All clear again, re-adding `ready for review`.**\n" + "\n" + "Thanks for addressing the earlier feedback. On re-check this PR meets " + f"the contribution bar once more.{score_line}\n" + "\n" + f"> {explanation}\n" + "\n" + "A maintainer will take another look.\n" + f"{READY_MARKER}" + ) + + +def format_regression_comment( + missing: list[str], explanation: str, grace_days: int +) -> str: + """Posted when a previously-tagged PR regresses (label removed, PR stays open). + + Discloses the same ``grace_days`` deadline the state machine enforces: + once that window elapses with the PR still failing, the close path fires. + Hiding the deadline behind a bare "stays open" would surprise contributors + with an auto-close they were never warned about. + """ + window = "24 hours" if grace_days == 1 else f"{grace_days} days" + return ( + "⚠️ **Removing the `ready for review` tag.**\n" + "\n" + "On a re-check this PR no longer meets the contribution bar. What's " + "missing now:\n" + "\n" + f"{_format_missing(missing)}\n" + "\n" + f"> {explanation}\n" + "\n" + f"The PR stays open for ~{window}; address the points above and Agent " + 'Shin will post an "all clear" comment and re-add the tag ' + "automatically. If the points still aren't addressed after that " + "window, the PR is auto-closed; that's not a rejection, and you can " + "comment `@agent-shin reconsider` to have it re-evaluated and reopened " + "once it passes.\n" + f"{REGRESSED_MARKER}" + ) + + +def format_within_grace_comment( + missing: list[str], explanation: str, grace_days: int +) -> str: + """Posted once while a failing PR is still inside its grace window.""" + window = "24 hours" if grace_days == 1 else f"{grace_days} days" + return ( + "🚅 Hi, thanks for the PR! This is **Agent Shin**, the automated triage " + "bot. This PR doesn't quite meet the contribution bar yet:\n" + "\n" + f"{_format_missing(missing)}\n" + "\n" + f"> {explanation}\n" + "\n" + f"You have ~{window} from when this PR was opened to add the missing " + "pieces; just update the description and I'll re-check on the next " + "sweep. Once it passes I'll tag it `ready for review`. If it does get " + "auto-closed, that's not a rejection; comment `@agent-shin reconsider` " + "and I'll re-evaluate and reopen if it now passes.\n" + f"{WITHIN_GRACE_MARKER}" + ) + + +def review_gate( + *, + repo: str, + number: int, + close: bool, + model: str, + judge: Any = None, + greptile_score: Any = _UNSET, + comments: Any = _UNSET, + now: dt.datetime | None = None, + grace_days: int = DEFAULT_GRACE_DAYS, + min_greptile_score: int = DEFAULT_MIN_GREPTILE_SCORE, + label: str = READY_FOR_REVIEW_LABEL, + allowlist: frozenset[str] = ALLOWLIST_LOGINS, +) -> dict: + """Reconcile the `ready for review` label with a PR's current quality. + + A PR is *passing* when it clears BOTH gates: the LLM rubric (linked issue, + or problem description + expected/actual + QA proof) AND Greptile's most + recent confidence score (>= ``min_greptile_score``; absence of a score is + not held against the PR). The gate then drives a small state machine, using + the label itself as the persisted state so comments fire only on + transitions (never on every scheduled run): + + passing, untagged -> add label + "ready for review" / "all clear" + passing, tagged -> noop-passing + not passing, tagged -> remove label + regression comment (stays open) + not passing, untagged, old -> close + comment (past the grace window) + not passing, untagged, new -> one-time "what's missing" notice (within grace) + + ``close`` gates every destructive side effect: with ``close=False`` the + function returns a ``would-*`` preview and touches nothing, mirroring the + dry-run contract of :func:`triage`. ``judge``/``greptile_score``/ + ``comments``/``now`` are injectable for tests; in production they are + resolved from the OpenAI judge, the PR's Greptile comment, the live comment + list, and the wall clock respectively. + """ + item = fetch_pr(repo, number) + + title = item.get("title") or "" + body = item.get("body") or "" + login = (item.get("user") or {}).get("login") or "" + association = item.get("author_association") or "" + state = item.get("state") or "" + # GitHub label names are case-insensitive; compare lowercased so a repo + # that already has e.g. "Ready for Review" is recognized as the same + # label as our READY_FOR_REVIEW_LABEL constant ("ready for review"). + labels_now = {(lbl.get("name") or "").lower() for lbl in (item.get("labels") or [])} + label_key = label.lower() + created_raw = item.get("created_at") or "" + + base_result = { + "kind": "pr", + "number": number, + "title": title, + "author": login, + "author_association": association, + "state": state, + "labeled": label_key in labels_now, + "review_gate": True, + } + + if state != "open": + return {**base_result, "action": "skip-not-open"} + + if allowlist: + if login.lower() not in allowlist: + return {**base_result, "action": "skip-not-allowlisted"} + elif is_internal_contributor(item): + return {**base_result, "action": "skip-internal-author"} + + # Resolve the comment list once — used for both the Greptile score and the + # marker-based dedup below. + if comments is _UNSET: + comments = list(_iter_paginated_json(f"repos/{repo}/issues/{number}/comments")) + + # --- rubric verdict: linked-issue short-circuit, else the LLM judge ------- + if has_linked_issue(body): + verdict = { + "verdict": "pass", + "linked_issue": True, + "missing": [], + "explanation": "Linked-issue regex matched; LLM was not called.", + } + rubric_pass = True + else: + prompt = build_pr_prompt(title=title, body=body) + if judge is None: + api_key = os.environ.get("OPENAI_API_KEY") + if not api_key: + return {**base_result, "action": "skip-no-llm-key"} + base_url = os.environ.get("OPENAI_BASE_URL") or None + + def judge(p: str) -> str: + return call_llm_judge( + p, model=model, api_key=api_key, base_url=base_url + ) + + try: + verdict = parse_verdict(judge(prompt)) + except Exception as exc: # noqa: BLE001 - judge errors must never act + return {**base_result, "action": "skip-llm-error", "error": str(exc)} + rubric_pass = (verdict.get("verdict") or "").lower() == "pass" + + # --- Greptile score ------------------------------------------------------- + if greptile_score is _UNSET: + extraction = extract_greptile_score(comments) + greptile_score = extraction[0] if extraction else None + greptile_ok = greptile_score is None or greptile_score >= min_greptile_score + passing = rubric_pass and greptile_ok + + # --- age ------------------------------------------------------------------ + age_days = None + if created_raw: + reference = now or dt.datetime.now(dt.timezone.utc) + age_days = (reference - parse_iso8601(created_raw)).days + + label_present = label_key in labels_now + explanation = verdict.get("explanation") or "" + # When the rubric short-circuited to pass (linked-issue regex) but + # Greptile dragged the PR below the bar, the synthetic verdict's + # explanation ("LLM was not called") would mislead a contributor reading + # the regression / close comment. Surface the real reason instead. + if rubric_pass and not greptile_ok: + explanation = ( + f"Greptile's most recent review scored this PR " + f"{greptile_score}/5 (below the {min_greptile_score}/5 bar)." + ) + verdict = {**verdict, "explanation": explanation} + base_result = { + **base_result, + "verdict": verdict, + "greptile_score": greptile_score, + "passing": passing, + "age_days": age_days, + } + + if passing: + if label_present: + return {**base_result, "action": "noop-passing"} + recovered = _has_marker(comments, REGRESSED_MARKER) + comment = ( + format_all_clear_comment(verdict, greptile_score) + if recovered + else format_ready_for_review_comment( + verdict, greptile_score, min_greptile_score + ) + ) + if not close: + return {**base_result, "action": "would-label-ready", "comment": comment} + post_comment(repo, number, comment) + add_label(repo, number, label) + return {**base_result, "action": "labeled-ready", "comment": comment} + + missing = _combine_missing(verdict, greptile_score, min_greptile_score) + + if label_present: + comment = format_regression_comment(missing, explanation, grace_days) + if not close: + return {**base_result, "action": "would-remove-label", "comment": comment} + remove_label(repo, number, label) + post_comment(repo, number, comment) + return {**base_result, "action": "label-removed-regressed", "comment": comment} + + # Not passing and not tagged. If the PR was previously tagged and then + # regressed (we removed the label and posted REGRESSED_MARKER), honor the + # "PR stays open — fix it and the tag comes back" promise from + # `format_regression_comment` and skip the close path. Without this guard, + # any PR older than `grace_days` would be closed on the next evaluation, + # giving the contributor no realistic window to address the regression. + # + # The promise has a deliberate expiration: once `grace_days` have elapsed + # since the regression notice, fall through to the close path so a PR that + # was abandoned post-regression doesn't sit open forever. + if _has_marker(comments, REGRESSED_MARKER): + reference = now or dt.datetime.now(dt.timezone.utc) + seconds_since_regression = seconds_since_latest_marker_comment( + comments, marker=REGRESSED_MARKER, now=reference + ) + grace_seconds = grace_days * 86400 + if seconds_since_regression is None or seconds_since_regression < grace_seconds: + return {**base_result, "action": "regressed-already-notified"} + + # Not passing and not tagged: close if past the grace window, else notify once. + if age_days is not None and age_days >= grace_days: + comment = format_pr_close_comment({**verdict, "missing": missing}) + if not close: + return {**base_result, "action": "would-close", "comment": comment} + post_comment(repo, number, comment) + close_pr(repo, number) + return {**base_result, "action": "closed", "comment": comment} + + if _has_marker(comments, WITHIN_GRACE_MARKER): + return {**base_result, "action": "within-grace-already-notified"} + comment = format_within_grace_comment(missing, explanation, grace_days) + if not close: + return { + **base_result, + "action": "would-notify-within-grace", + "comment": comment, + } + post_comment(repo, number, comment) + return {**base_result, "action": "within-grace-notified", "comment": comment} + + +def triage( + *, + repo: str, + kind: str, + number: int, + close: bool, + model: str, + judge: Any = None, + print_prompt: bool = False, + reconsider: bool = False, + allowlist: frozenset[str] = ALLOWLIST_LOGINS, +) -> dict: + """Triage a single PR or issue. Returns a result dict for logging/tests. + + `judge` is an optional callable `(prompt) -> str` for tests / dry-run with + a stub. In production, leave it None and the script uses `call_llm_judge`. + + When `reconsider=True`, the closed-state guard is skipped and a + fail-but-no-comment is replaced with a "still failing" comment + leave + closed; a pass triggers `reopen_pr`/`reopen_issue` plus a reopen comment. + Reconsider mode is intended for the `@agent-shin reconsider` comment + trigger. Like regular triage, `close=False` keeps reconsider in dry-run + (returns `would-reopen` / `would-reconsider-still-failing` so a local + operator can preview without write side effects); the workflow only + passes `--close` when `AGENT_SHIN_ENABLED=true`. + + Reconsider mode adds two extra safety guards on top of the regular + triage skip-internal-author check: + + 1. **Bot-closed guard.** Only reopens if the most recent close was + performed by the bot identity (default `github-actions[bot]`). + This stops a contributor from using `@agent-shin reconsider` to + override a maintainer's close for non-rubric reasons. + 2. **Rate-limit guard.** If the bot has already posted a reconsider + verdict on this PR/issue within `RECONSIDER_RATE_LIMIT_SECONDS`, + skip — repeated triggers from the same contributor shouldn't burn + CI minutes or LLM budget. + """ + fetcher = {"pr": fetch_pr, "issue": fetch_issue}[kind] + item = fetcher(repo, number) + + title = item.get("title") or "" + body = item.get("body") or "" + login = (item.get("user") or {}).get("login") or "" + association = item.get("author_association") or "" + state = item.get("state") or "" + + base_result = { + "kind": kind, + "number": number, + "title": title, + "author": login, + "author_association": association, + "state": state, + "reconsider": reconsider, + } + + # Reconsider only makes sense on a closed PR/issue. A "reconsider on an + # open PR" is a no-op (the regular triage flow already evaluates open + # PRs); return a clear skip so the workflow can short-circuit. + if reconsider: + if state != "closed": + return {**base_result, "action": "skip-not-closed"} + else: + if state != "open": + return {**base_result, "action": "skip-not-open"} + + if allowlist: + if login.lower() not in allowlist: + return {**base_result, "action": "skip-not-allowlisted"} + elif is_internal_contributor(item): + return {**base_result, "action": "skip-internal-author"} + + # Reconsider-only guards — these run BEFORE the LLM call so a + # maintainer-closed PR / rate-limited trigger never spends LLM budget. + if reconsider: + if not was_closed_by_agent_shin(repo, number): + return {**base_result, "action": "skip-not-bot-closed"} + age = seconds_since_last_reconsider_verdict(repo, number) + if age is not None and age < RECONSIDER_RATE_LIMIT_SECONDS: + return { + **base_result, + "action": "skip-rate-limited", + "rate_limit_age_seconds": age, + "rate_limit_window_seconds": RECONSIDER_RATE_LIMIT_SECONDS, + } + + if kind == "pr": + # Short-circuit: if body very clearly links a related issue, just pass. + if has_linked_issue(body): + base = { + **base_result, + "action": "pass-linked-issue", + "verdict": { + "verdict": "pass", + "linked_issue": True, + "explanation": "Linked-issue regex matched; LLM was not called.", + }, + } + if reconsider: + # Pass-on-reconsider -> reopen the PR with a friendly comment. + reopen_body = format_reopen_comment(kind) + if not close: + return { + **base, + "action": "would-reopen", + "comment": reopen_body, + } + post_comment(repo, number, reopen_body) + reopen_pr(repo, number) + return { + **base, + "action": "reopened", + "comment": reopen_body, + } + return base + prompt = build_pr_prompt(title=title, body=body) + else: + prompt = build_issue_prompt(title=title, body=body) + + if print_prompt: + return {**base_result, "action": "print-prompt", "prompt": prompt} + + if judge is None: + api_key = os.environ.get("OPENAI_API_KEY") + if not api_key: + # No key configured — never take a destructive action. Report skip. + return { + **base_result, + "action": "skip-no-llm-key", + "prompt_preview": prompt[:200], + } + base_url = os.environ.get("OPENAI_BASE_URL") or None + + def judge(p: str) -> str: + return call_llm_judge(p, model=model, api_key=api_key, base_url=base_url) + + try: + raw = judge(prompt) + verdict = parse_verdict(raw) + except Exception as exc: # noqa: BLE001 - judge errors must never close PRs + return {**base_result, "action": "skip-llm-error", "error": str(exc)} + + decision = (verdict.get("verdict") or "").lower() + + if reconsider: + # Reconsider: an explicit `pass` -> reopen + post reopen comment; + # anything else (fail, missing/malformed verdict, typo) -> leave + # closed + post a "still failing" comment so the contributor can + # iterate again. Reopen is destructive, so a flaky/empty verdict + # must not satisfy the gate. + # In dry-run (`close=False`) we return `would-*` actions instead + # of touching GitHub state, mirroring the regular triage flow's + # `would-close`. This lets a local operator preview the outcome + # of `python triage_with_llm.py --reconsider --pr N` without + # risking accidental comments or reopens. + if decision == "pass": + reopen_body = format_reopen_comment(kind) + if not close: + return { + **base_result, + "action": "would-reopen", + "verdict": verdict, + "comment": reopen_body, + } + post_comment(repo, number, reopen_body) + if kind == "pr": + reopen_pr(repo, number) + else: + reopen_issue(repo, number) + return { + **base_result, + "action": "reopened", + "verdict": verdict, + "comment": reopen_body, + } + still_failing = format_reconsider_still_failing_comment(kind, verdict) + if not close: + return { + **base_result, + "action": "would-reconsider-still-failing", + "verdict": verdict, + "comment": still_failing, + } + post_comment(repo, number, still_failing) + return { + **base_result, + "action": "reconsider-still-failing", + "verdict": verdict, + "comment": still_failing, + } + + if decision != "fail": + return {**base_result, "action": "pass-llm", "verdict": verdict} + + # Grace-period flow: on the first low-quality detection, post a warning + # comment instead of closing immediately. On a subsequent triage run + # (manual re-trigger, or the daily `close_low_quality_prs.py` cron + # finding the same PR in its own pass), if `GRACE_PERIOD_SECONDS` has + # elapsed since the warning AND the PR still fails the rubric, close. + grace_age = seconds_since_last_grace_warning(repo, number) + if grace_age is None: + warning_body = ( + format_grace_warning_pr_comment(verdict) + if kind == "pr" + else format_grace_warning_issue_comment(verdict) + ) + if not close: + return { + **base_result, + "action": "would-warn-grace", + "verdict": verdict, + "comment": warning_body, + } + post_comment(repo, number, warning_body) + return { + **base_result, + "action": "warned-grace", + "verdict": verdict, + "comment": warning_body, + } + if grace_age < GRACE_PERIOD_SECONDS: + return { + **base_result, + "action": "skip-in-grace-period", + "verdict": verdict, + "grace_age_seconds": grace_age, + "grace_period_seconds": GRACE_PERIOD_SECONDS, + } + + # The grace window has elapsed. `--close` still gates the destructive + # write so a dry-run preview never posts or closes — the workflow only + # passes `--close` when `AGENT_SHIN_ENABLED=true`, which keeps the bot + # inert by default. + if not close: + return {**base_result, "action": "would-close", "verdict": verdict} + + comment_body = ( + format_pr_close_comment(verdict) + if kind == "pr" + else format_issue_close_comment(verdict) + ) + post_comment(repo, number, comment_body) + if kind == "pr": + close_pr(repo, number) + else: + close_issue(repo, number) + + return { + **base_result, + "action": "closed", + "verdict": verdict, + "comment": comment_body, + } + + +# --------------------------------------------------------------------------- +# CLI + + +def render_summary(result: dict) -> str: + """Render a human-readable summary block (used for stdout + step summary).""" + lines = ["## Agent Shin verdict", ""] + lines.append( + f"- **{result['kind'].upper()} #{result['number']}**: {result.get('title', '')}" + ) + lines.append( + f"- **Author**: `{result.get('author', '')}` ({result.get('author_association', '')})" + ) + lines.append(f"- **State**: {result.get('state', '')}") + lines.append(f"- **Action**: `{result['action']}`") + verdict = result.get("verdict") + if verdict: + lines.append("") + lines.append("```json") + lines.append(json.dumps(verdict, indent=2)) + lines.append("```") + error = result.get("error") + if error: + lines.append("") + lines.append(f"_LLM error: {error}_") + comment = result.get("comment") + if comment: + lines.append("") + lines.append("### Posted comment:") + lines.append("") + lines.append("> " + comment.replace("\n", "\n> ")) + return "\n".join(lines) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--repo", required=True, help="Repository (owner/repo).") + target = parser.add_mutually_exclusive_group(required=True) + target.add_argument("--pr", type=int, help="Pull request number to triage.") + target.add_argument("--issue", type=int, help="Issue number to triage.") + parser.add_argument( + "--close", + action="store_true", + help="Actually post comment + close on fail (default: dry run).", + ) + parser.add_argument( + "--model", + # `os.environ.get("TRIAGE_MODEL", DEFAULT_MODEL)` would return "" when + # GitHub Actions exposes an unset repo variable as an empty-string env + # var, silently bypassing DEFAULT_MODEL and causing every call to fail + # as `skip-llm-error`. The `or` guard collapses empty -> default. + default=os.environ.get("TRIAGE_MODEL") or DEFAULT_MODEL, + help=f"OpenAI-compatible model name (default: {DEFAULT_MODEL}).", + ) + parser.add_argument( + "--print-prompt", + action="store_true", + help="Print the prompt that would be sent to the judge and exit.", + ) + parser.add_argument( + "--reconsider", + action="store_true", + help=( + "Re-run triage on a CLOSED PR/issue and reopen it on pass. " + "Used by the `@agent-shin reconsider` comment-trigger workflow. " + "Only invoke this from a workflow that has already gated on " + "AGENT_SHIN_ENABLED=true and verified the commenter is the " + "PR/issue author or an internal collaborator." + ), + ) + parser.add_argument( + "--review-gate", + action="store_true", + help=( + "Reconcile the `ready for review` label for an OPEN PR: tag on " + "pass, remove the tag + comment on regression, close after the " + "grace window if it never passed. PR-only." + ), + ) + parser.add_argument( + "--grace-days", + type=int, + default=DEFAULT_GRACE_DAYS, + help=( + "Review-gate only: hours/24 a failing, un-tagged PR may stay open " + f"before auto-close (default: {DEFAULT_GRACE_DAYS} = 24h)." + ), + ) + parser.add_argument( + "--min-greptile-score", + type=int, + default=DEFAULT_MIN_GREPTILE_SCORE, + choices=range(1, 6), + help=( + "Review-gate only: Greptile score below which a PR counts as not " + f"passing (default: {DEFAULT_MIN_GREPTILE_SCORE} -> <4/5 regresses)." + ), + ) + args = parser.parse_args() + + kind = "pr" if args.pr is not None else "issue" + number = args.pr if args.pr is not None else args.issue + + if args.review_gate: + if kind != "pr": + parser.error("--review-gate applies to pull requests only (use --pr).") + result = review_gate( + repo=args.repo, + number=number, + close=args.close, + model=args.model, + grace_days=args.grace_days, + min_greptile_score=args.min_greptile_score, + ) + else: + result = triage( + repo=args.repo, + kind=kind, + number=number, + close=args.close, + model=args.model, + print_prompt=args.print_prompt, + reconsider=args.reconsider, + ) + + if result.get("action") == "print-prompt": + print(result["prompt"]) + return 0 + + summary = render_summary(result) + print(summary) + write_step_summary(summary + "\n") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.github/workflows/check-ui-api-types.yml b/.github/workflows/check-ui-api-types.yml index eeb5545b15e..d8053c15683 100644 --- a/.github/workflows/check-ui-api-types.yml +++ b/.github/workflows/check-ui-api-types.yml @@ -54,7 +54,7 @@ jobs: run: uv run --no-sync prisma generate --schema litellm/proxy/schema.prisma - name: Set up Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: "20" cache: "npm" diff --git a/.github/workflows/close_low_quality_prs.yml b/.github/workflows/close_low_quality_prs.yml new file mode 100644 index 00000000000..2401be84000 --- /dev/null +++ b/.github/workflows/close_low_quality_prs.yml @@ -0,0 +1,92 @@ +name: Close Low-Quality PRs + +# Auto-close any open PR (including drafts, regardless of age) authored by an +# external OSS contributor that Greptile reviewed with a confidence score +# below 4/5. Closures are explained in a comment that tells the contributor +# to push fixes and open a fresh PR (since OSS authors cannot reopen a PR +# closed by a bot/maintainer) or comment `@agent-shin reconsider` to have +# Agent Shin re-evaluate. +# +# Manual one-off run: +# gh workflow run "Close Low-Quality PRs" -f close=true +# +# Dry-run preview (no PRs are touched): +# gh workflow run "Close Low-Quality PRs" -f close=false + +on: + schedule: + # Daily at 09:00 UTC. Pairs well with the stale-issue workflow at midnight. + - cron: "0 9 * * *" + workflow_dispatch: + inputs: + close: + description: "Actually close matching PRs (false = dry run)." + required: false + default: "false" + type: choice + options: + - "true" + - "false" + min_age_days: + description: "Minimum PR age in days (default 0 = no age filter)." + required: false + default: "0" + min_score: + description: "Greptile score below which a PR is closed (1-5)." + required: false + default: "4" + limit: + description: "Maximum number of PRs to close in a single run." + required: false + default: "25" + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + close-low-quality-prs: + if: github.repository == 'BerriAI/litellm' + runs-on: ubuntu-latest + steps: + - name: Checkout triage script + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + sparse-checkout: .github/scripts + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.12" + + - name: Run low-quality PR closer + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Scheduled runs are ALWAYS dry-run, even when AGENT_SHIN_ENABLED is + # "true", so the team can QA the closer's verdicts in step summaries + # before any contributor sees a PR closed. Real closures only happen + # on manual workflow_dispatch with close=true (and the variable set). + CLOSE_FLAG: ${{ github.event.inputs.close || 'false' }} + AGENT_SHIN_ENABLED: ${{ vars.AGENT_SHIN_ENABLED }} + MIN_AGE_DAYS: ${{ github.event.inputs.min_age_days || '0' }} + MIN_SCORE: ${{ github.event.inputs.min_score || '4' }} + LIMIT: ${{ github.event.inputs.limit || '25' }} + run: | + set -euo pipefail + ARGS=( + --repo "${{ github.repository }}" + --min-age-days "${MIN_AGE_DAYS}" + --min-score "${MIN_SCORE}" + --limit "${LIMIT}" + ) + if [ "${AGENT_SHIN_ENABLED:-false}" != "true" ]; then + echo "::notice::AGENT_SHIN_ENABLED is not 'true' -> forcing dry-run regardless of close input." + elif [ "${GITHUB_EVENT_NAME:-}" = "workflow_dispatch" ] && [ "${CLOSE_FLAG}" = "true" ]; then + ARGS+=(--close) + echo "::notice::Running in close-on-fail mode." + else + echo "::notice::AGENT_SHIN_ENABLED is true but this trigger is dry-run (scheduled event or close=false)." + fi + python3 .github/scripts/close_low_quality_prs.py "${ARGS[@]}" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index babe3b62933..d3a165a11da 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -43,14 +43,14 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@ebcb5b36ded6beda4ceefea6a8bc4cc885255bb3 # v3 + uses: github/codeql-action/init@ebcb5b36ded6beda4ceefea6a8bc4cc885255bb3 # v3.34.1 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} config-file: ./.github/codeql/codeql-config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ebcb5b36ded6beda4ceefea6a8bc4cc885255bb3 # v3 + uses: github/codeql-action/analyze@ebcb5b36ded6beda4ceefea6a8bc4cc885255bb3 # v3.34.1 with: category: "/language:${{ matrix.language }}" output: sarif-results @@ -77,7 +77,7 @@ jobs: output: sarif-results/python.sarif - name: Upload SARIF - uses: github/codeql-action/upload-sarif@ebcb5b36ded6beda4ceefea6a8bc4cc885255bb3 # v3 + uses: github/codeql-action/upload-sarif@ebcb5b36ded6beda4ceefea6a8bc4cc885255bb3 # v3.34.1 with: sarif_file: sarif-results category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml new file mode 100644 index 00000000000..69ade24d028 --- /dev/null +++ b/.github/workflows/conventional-commits.yml @@ -0,0 +1,46 @@ +name: Conventional PR Title + +# Squash-merge replaces the merge commit subject with the PR title, so +# enforcing Conventional Commits at the PR-title level is what actually gates +# the commits that land on the default branch. The local commit-msg hook +# (.githooks/commit-msg) is a best-effort assist; this workflow is the gate. +# +# See https://www.conventionalcommits.org/en/v1.0.0/ + +on: + pull_request: + types: [opened, edited, reopened, synchronize, labeled, unlabeled] + +permissions: + pull-requests: read + +jobs: + lint-pr-title: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - name: Check title against Conventional Commits + uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # Must mirror the type list in .githooks/commit-msg. + types: | + feat + fix + docs + style + refactor + perf + test + build + ci + chore + revert + requireScope: false + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + The subject "{subject}" must start with a lowercase character. + # Allow merges/reverts that GitHub generates automatically. + ignoreLabels: | + ignore-semantic-pull-request diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index a726a921a2b..4834775e329 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -52,6 +52,22 @@ jobs: // are stable maintenance releases, not pre-releases. const isPrerelease = /(?:rc|nightly|alpha|beta|[-.]dev)/i.test(tag); + // A stable release should only claim the repo "latest" badge when its + // version is >= the current latest. Otherwise a backport (e.g. 1.84.6) + // would steal "latest" from a newer line (e.g. 1.88.1). + const versionKey = (rawTag) => { + const m = String(rawTag).match(/^v?(\d+)\.(\d+)\.(\d+)/); + if (!m) return null; + const maintenance = String(rawTag).match(/(?:\.post|\.patch\.)(\d+)/i); + return [Number(m[1]), Number(m[2]), Number(m[3]), maintenance ? Number(maintenance[1]) : 0]; + }; + const isAtLeast = (a, b) => { + for (let i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return a[i] > b[i]; + } + return true; + }; + const cosignSection = [ `## Verify Docker Image Signature`, ``, @@ -90,6 +106,22 @@ jobs: ].join('\n'); try { + let makeLatest = "false"; + const newVersion = versionKey(tag); + if (!isPrerelease && newVersion) { + let latestVersion = null; + try { + const latest = await github.rest.repos.getLatestRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + }); + latestVersion = versionKey(latest.data.tag_name); + } catch (error) { + if (error.status !== 404) throw error; + } + makeLatest = (!latestVersion || isAtLeast(newVersion, latestVersion)) ? "true" : "false"; + } + const response = await github.rest.repos.createRelease({ draft: true, generate_release_notes: true, @@ -108,6 +140,7 @@ jobs: release_id: response.data.id, body: updatedBody, draft: false, + make_latest: makeLatest, }); } catch (error) { diff --git a/.github/workflows/osv-scan.yml b/.github/workflows/osv-scan.yml new file mode 100644 index 00000000000..9dd321f88db --- /dev/null +++ b/.github/workflows/osv-scan.yml @@ -0,0 +1,49 @@ +name: OSV Scan + +on: + pull_request: + branches: + - main + - litellm_internal_staging + - litellm_oss_branch + - "litellm_**" + paths: + - uv.lock + - ui/litellm-dashboard/package-lock.json + - osv-scanner.toml + - .github/workflows/osv-scan.yml + schedule: + - cron: "23 6 * * *" + workflow_dispatch: + +permissions: {} + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + osv-scan: + name: osv-scan + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + persist-credentials: false + + - name: Download osv-scanner v2.3.8 + run: | + curl -fsSL --retry 3 -o "$RUNNER_TEMP/osv-scanner" \ + https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_linux_amd64 + echo "bc98e15319ed0d515e3f9235287ba53cdc5535d576d24fd573978ecfe9ab92dc $RUNNER_TEMP/osv-scanner" | sha256sum -c - + chmod +x "$RUNNER_TEMP/osv-scanner" + + - name: Scan lockfiles + run: | + "$RUNNER_TEMP/osv-scanner" scan source \ + --config osv-scanner.toml \ + -L uv.lock \ + -L ui/litellm-dashboard/package-lock.json diff --git a/.github/workflows/test-linting.yml b/.github/workflows/test-linting.yml index b5e45a38cf9..de7e1b68346 100644 --- a/.github/workflows/test-linting.yml +++ b/.github/workflows/test-linting.yml @@ -14,11 +14,15 @@ permissions: jobs: lint: runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 steps: - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + # Check out the PR head, not the default refs/pull/N/merge: the merge ref + # folds in newer base commits, which the diff-based gates (ruff delta, + # Any-discipline) would otherwise blame on this branch. with: + ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 clean: true persist-credentials: false @@ -67,15 +71,25 @@ jobs: uv run --no-sync ruff check . cd .. + - name: Check strict-rule budget (delta vs base) + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + uv run --no-sync python scripts/ruff_strict_gate.py --base "$BASE_SHA" + + - name: Check type-discipline budget (mutable collections / casts / type guards / kwargs / unexplained suppressions, delta vs base) + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + uv run --no-sync python scripts/type_discipline_gate.py --base "$BASE_SHA" + - name: Print OpenAI version run: | uv run --no-sync python -c "import openai; print(f'OpenAI version: {openai.__version__}')" - - name: Run MyPy type checking + - name: Run basedpyright type checking run: | - cd litellm - uv run --no-sync mypy . - cd .. + (uv run --no-sync basedpyright --outputjson || true) | uv run --no-sync python scripts/type_check_gate.py - name: Check for circular imports run: | @@ -87,6 +101,33 @@ jobs: run: | uv run --no-sync python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1) + # Intentionally NON-GATING. This job turns red when a *-budget.json ceiling is + # raised (or a rule/budget is dropped) so a loosening is obvious in review, but it + # must be kept OUT of the branch-protection required-checks list so a justified + # bump can still be merged by a human who has seen and accepted the red. + budget-ratchet: + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.12" + + - name: Ratchet check (budgets may only decrease; non-gating) + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + python scripts/budget_ratchet_check.py --base "$BASE_SHA" + secret-scan: runs-on: ubuntu-latest timeout-minutes: 5 diff --git a/.github/workflows/test-litellm-ui-build.yml b/.github/workflows/test-litellm-ui-build.yml index 68497b10dbb..b83119712a7 100644 --- a/.github/workflows/test-litellm-ui-build.yml +++ b/.github/workflows/test-litellm-ui-build.yml @@ -25,7 +25,7 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: "20" cache: "npm" @@ -77,7 +77,7 @@ jobs: - name: Setup Node.js if: steps.changed.outputs.has_files == 'true' - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: "20" cache: "npm" diff --git a/.github/workflows/test-unit-misc.yml b/.github/workflows/test-unit-misc.yml index 9add77ff424..a7363ac3b43 100644 --- a/.github/workflows/test-unit-misc.yml +++ b/.github/workflows/test-unit-misc.yml @@ -28,6 +28,8 @@ jobs: tests/test_litellm/completion_extras tests/test_litellm/containers tests/test_litellm/experimental_mcp_client + tests/test_litellm/models + tests/test_litellm/repositories tests/test_litellm/images tests/test_litellm/interactions tests/test_litellm/passthrough diff --git a/.github/workflows/test-unit-proxy-endpoints.yml b/.github/workflows/test-unit-proxy-endpoints.yml index 0a9513ec024..d9b6a348b60 100644 --- a/.github/workflows/test-unit-proxy-endpoints.yml +++ b/.github/workflows/test-unit-proxy-endpoints.yml @@ -11,8 +11,6 @@ on: permissions: contents: read - id-token: write - pull-requests: write concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -20,6 +18,10 @@ concurrency: jobs: proxy-endpoints: + permissions: + contents: read + id-token: write + pull-requests: write uses: ./.github/workflows/_test-unit-base.yml with: test-path: >- @@ -52,6 +54,10 @@ jobs: # is independent and its coverage artifact is uploaded separately. # See: https://www.notion.so/36c43b8acdab81ee845fd5365128a2fc proxy-server: + permissions: + contents: read + id-token: write + pull-requests: write uses: ./.github/workflows/_test-unit-base.yml with: test-path: tests/test_litellm/proxy/proxy_server diff --git a/.github/workflows/test_server_root_path.yml b/.github/workflows/test_server_root_path.yml index 57ff746c9c8..985653796c2 100644 --- a/.github/workflows/test_server_root_path.yml +++ b/.github/workflows/test_server_root_path.yml @@ -32,17 +32,16 @@ jobs: df -h / - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Build Docker image - uses: docker/build-push-action@0adf9959216b96bec444f325f1e493d4aa344497 #v6.14 + uses: docker/build-push-action@0adf9959216b96bec444f325f1e493d4aa344497 # v6.14.0 with: context: . file: ./docker/Dockerfile.non_root tags: litellm-test:${{ github.sha }} load: true - cache-from: type=gha - cache-to: type=gha,mode=max + push: false - name: Start LiteLLM container with SERVER_ROOT_PATH run: | diff --git a/.github/workflows/triage_issue_with_llm.yml b/.github/workflows/triage_issue_with_llm.yml new file mode 100644 index 00000000000..765453cf2c6 --- /dev/null +++ b/.github/workflows/triage_issue_with_llm.yml @@ -0,0 +1,96 @@ +name: Agent Shin — Issue triage + +# LLM-as-judge triage for external GitHub issues. +# +# DRY-RUN BY DEFAULT. See .github/workflows/triage_pr_with_llm.yml for the +# enablement procedure — same repo variable (`AGENT_SHIN_ENABLED=true`) +# unlocks the PR and issue triage flows together. + +on: + issues: + types: [opened, reopened] + workflow_dispatch: + inputs: + issue_number: + description: "Issue number to triage manually." + required: true + close: + description: "If true and AGENT_SHIN_ENABLED=true, actually close on fail." + required: false + default: "false" + type: choice + options: + - "true" + - "false" + +permissions: + contents: read + issues: write + +jobs: + triage: + if: github.repository == 'BerriAI/litellm' + runs-on: ubuntu-latest + steps: + - name: Checkout triage script + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + sparse-checkout: .github/scripts + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.12" + + - name: Install LLM client + run: pip install --no-cache-dir --require-hashes -r .github/scripts/triage-requirements.txt + + - name: Run Agent Shin + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Only expose the LLM key when the bot is enabled or a collaborator + # triggers it manually, so an external user can't force paid LLM + # calls by churning issues while the bot is still in dry-run. + # The Python script calls the LLM whenever this var is set + # (regardless of `--close`); stripping `--close` doesn't suppress + # the API call, only the destructive side effects. + OPENAI_API_KEY: ${{ (vars.AGENT_SHIN_ENABLED == 'true' || github.event_name == 'workflow_dispatch') && secrets.OPENAI_API_KEY || '' }} + OPENAI_BASE_URL: ${{ vars.OPENAI_BASE_URL }} + TRIAGE_MODEL: ${{ vars.TRIAGE_MODEL }} + AGENT_SHIN_ENABLED: ${{ vars.AGENT_SHIN_ENABLED }} + DISPATCH_CLOSE: ${{ github.event.inputs.close }} + ISSUE_NUMBER: ${{ github.event.issue.number || github.event.inputs.issue_number }} + run: | + set -euo pipefail + ARGS=(--repo "${{ github.repository }}" --issue "${ISSUE_NUMBER}") + # Fail-safe gating: only the EXACT string "true" enables the + # destructive --close path. The workflow_dispatch input is a + # `choice` dropdown of "true"/"false" so the UI is constrained, + # but the API (`gh workflow run -f close=...`) accepts any + # string, and a `!= "false"` check would treat "True", "yes", + # "1", "TRUE", typos, and accidental whitespace as enabling + # closure. Mirror the Greptile closer's `= "true"` pattern. + if [ "${AGENT_SHIN_ENABLED:-false}" = "true" ] && [ "${DISPATCH_CLOSE:-false}" = "true" ]; then + ARGS+=(--close) + echo "::notice::Agent Shin is ENABLED and running in close-on-fail mode." + elif [ "${AGENT_SHIN_ENABLED:-false}" = "true" ]; then + echo "::notice::Agent Shin is ENABLED but this trigger is dry-run (workflow_dispatch close != 'true')." + else + echo "::notice::Agent Shin is in DRY-RUN mode (AGENT_SHIN_ENABLED is not 'true'). No comments will be posted; no issues will be closed." + fi + # Automatic `issues` events stay dry-run regardless until the team + # explicitly invokes workflow_dispatch with close=true. + if [ "${GITHUB_EVENT_NAME:-}" = "issues" ]; then + # filter out --close rather than substituting to "" (which would + # leave an empty positional arg that argparse rejects) + FILTERED=() + for arg in "${ARGS[@]}"; do + if [ "${arg}" != "--close" ]; then + FILTERED+=("${arg}") + fi + done + ARGS=("${FILTERED[@]}") + echo "::notice::issues trigger -> forcing dry-run." + fi + python3 .github/scripts/triage_with_llm.py "${ARGS[@]}" diff --git a/.github/workflows/triage_reconsider.yml b/.github/workflows/triage_reconsider.yml new file mode 100644 index 00000000000..f35f681d09a --- /dev/null +++ b/.github/workflows/triage_reconsider.yml @@ -0,0 +1,172 @@ +name: Agent Shin — reconsider + +# Comment-trigger workflow: when the PR/issue author (or an internal +# collaborator) comments `@agent-shin reconsider` on a CLOSED PR/issue, +# Agent Shin re-runs LLM-judge triage on the current title+body and: +# +# - on PASS: posts a "re-evaluated and reopened" comment + reopens. +# - on FAIL: posts a "still missing X" comment and leaves it closed, +# so the contributor can iterate again. +# +# This exists because GitHub does NOT let an external (non-write-access) +# OSS contributor reopen a PR/issue closed by a bot or maintainer. Without +# this comment trigger, a contributor whose PR Agent Shin auto-closed +# would have no path back into the review queue except opening a fresh PR +# (which loses the original PR's history). The bot, on the other hand, +# has write access via GH_TOKEN and can reopen on their behalf. +# +# DRY-RUN BY DEFAULT — gated on `vars.AGENT_SHIN_ENABLED == 'true'` just +# like the other Agent Shin workflows. The workflow also gates on the +# commenter being either the PR/issue author or an internal collaborator +# (OWNER/MEMBER/COLLABORATOR) so random commenters cannot DOS the LLM +# judge or force a reopen. + +on: + issue_comment: + types: [created] + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + reconsider: + if: | + github.repository == 'BerriAI/litellm' + && contains(github.event.comment.body, '@agent-shin reconsider') + runs-on: ubuntu-latest + steps: + - name: Authorize commenter + # Only the PR/issue author OR an internal collaborator may trigger + # a reconsider. Outside random commenters could otherwise spam the + # phrase to burn LLM budget or, if a fail-open bug were ever + # introduced, force a reopen on someone else's behalf. + # + # We expose the authorization decision as a step output and gate + # every subsequent (potentially destructive) step on it. A `run:` + # step with `exit 0` would NOT stop the job — only `if:` gating + # on a known-true output is safe here. + id: auth + env: + COMMENTER: ${{ github.event.comment.user.login }} + AUTHOR: ${{ github.event.issue.user.login }} + ASSOCIATION: ${{ github.event.comment.author_association }} + run: | + set -euo pipefail + if [ "${COMMENTER}" = "${AUTHOR}" ]; then + echo "::notice::Authorized: commenter is the PR/issue author." + echo "authorized=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + case "${ASSOCIATION}" in + OWNER|MEMBER|COLLABORATOR) + echo "::notice::Authorized: commenter is an internal collaborator (${ASSOCIATION})." + echo "authorized=true" >> "$GITHUB_OUTPUT" + ;; + *) + echo "::notice::Commenter '${COMMENTER}' (${ASSOCIATION}) is not authorized to trigger reconsider; skipping subsequent steps." + echo "authorized=false" >> "$GITHUB_OUTPUT" + ;; + esac + + - name: React 👀 to acknowledge the reconsider + # Add an eyes reaction to the triggering comment the moment we accept + # it, so the contributor gets instant feedback that the bot saw their + # `@agent-shin reconsider` before the slower triage steps run. Gated on + # AGENT_SHIN_ENABLED so dry-run leaves no visible trace. Best-effort: + # a reactions API hiccup must never fail the actual reconsider. + if: steps.auth.outputs.authorized == 'true' && vars.AGENT_SHIN_ENABLED == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMMENT_ID: ${{ github.event.comment.id }} + run: | + set -euo pipefail + gh api --method POST \ + -H "Accept: application/vnd.github+json" \ + "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}/reactions" \ + -f content=eyes \ + || echo "::warning::failed to add 👀 reaction (non-fatal)" + + - name: Checkout triage script + if: steps.auth.outputs.authorized == 'true' + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + sparse-checkout: .github/scripts + persist-credentials: false + + - name: Set up Python + if: steps.auth.outputs.authorized == 'true' + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.12" + + - name: Install LLM client + if: steps.auth.outputs.authorized == 'true' + run: pip install --no-cache-dir --require-hashes -r .github/scripts/triage-requirements.txt + + - name: Run Agent Shin reconsider + if: steps.auth.outputs.authorized == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Only expose the LLM key when the bot is enabled, so a PR/issue + # author can't force paid LLM calls by spamming `@agent-shin + # reconsider` while the bot is still in dry-run. The Python script + # calls the LLM whenever this var is set (regardless of `--close`); + # stripping `--close` doesn't suppress the API call, only the + # destructive side effects. Mirror the gating used by every other + # Agent Shin workflow (triage_pr_with_llm.yml, review_gate.yml, ...). + OPENAI_API_KEY: ${{ vars.AGENT_SHIN_ENABLED == 'true' && secrets.OPENAI_API_KEY || '' }} + OPENAI_BASE_URL: ${{ vars.OPENAI_BASE_URL }} + TRIAGE_MODEL: ${{ vars.TRIAGE_MODEL }} + AGENT_SHIN_ENABLED: ${{ vars.AGENT_SHIN_ENABLED }} + # `issue_comment` events fire for both issues and PR comments. + # `issue.pull_request` is set iff this is a PR comment, so we use + # its presence to decide whether to invoke `--pr N` or `--issue N`. + IS_PR: ${{ github.event.issue.pull_request != null }} + NUMBER: ${{ github.event.issue.number }} + run: | + set -euo pipefail + if [ "${IS_PR}" = "true" ]; then + ARGS=(--repo "${{ github.repository }}" --pr "${NUMBER}" --reconsider) + else + ARGS=(--repo "${{ github.repository }}" --issue "${NUMBER}" --reconsider) + fi + # Reconsider's destructive actions (post comment + reopen) are + # gated on `--close`, mirroring the regular triage workflows. + # When AGENT_SHIN_ENABLED is not the EXACT string "true", we + # still run the script so its verdict + would-X action lands in + # the step summary for QA — but without `--close`, the script + # returns `would-reopen` / `would-reconsider-still-failing` + # instead of touching GitHub state. + # + # Use the positive `= "true"` gate (not `!= "true" -> exit`) so + # the workflow guardrails in + # tests/test_litellm/test_github_triage_workflows.py see the + # canonical fail-safe enable pattern. Unknown values like + # "True", "yes", "1", or typos fall through to the dry-run + # branch, which is the safe default. + if [ "${AGENT_SHIN_ENABLED:-false}" = "true" ]; then + ARGS+=(--close) + echo "::notice::Agent Shin reconsider ENABLED — running real triage (close=true)." + else + echo "::notice::AGENT_SHIN_ENABLED is not 'true' -> reconsider stays in dry-run (no comment, no reopen)." + fi + python3 .github/scripts/triage_with_llm.py "${ARGS[@]}" + + - name: React 👍 when the reconsider finishes + # Once the reconsider run has completed successfully, add a thumbs-up so + # the contributor sees the bot is done (the 👀 stays, signalling + # seen -> handled). `success()` keeps this from firing if the run + # errored, and the AGENT_SHIN_ENABLED gate keeps dry-run inert. + if: success() && steps.auth.outputs.authorized == 'true' && vars.AGENT_SHIN_ENABLED == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMMENT_ID: ${{ github.event.comment.id }} + run: | + set -euo pipefail + gh api --method POST \ + -H "Accept: application/vnd.github+json" \ + "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}/reactions" \ + -f content=+1 \ + || echo "::warning::failed to add 👍 reaction (non-fatal)" diff --git a/.github/workflows/triage_rollout_heads_up.yml b/.github/workflows/triage_rollout_heads_up.yml new file mode 100644 index 00000000000..903960151e2 --- /dev/null +++ b/.github/workflows/triage_rollout_heads_up.yml @@ -0,0 +1,92 @@ +name: Agent Shin — rollout heads-up (one-shot) + +# Fires the 7-day heads-up comment on every open external PR/issue that the +# new triage bot would auto-close. The real sweep is a deliberate one-shot: +# trigger it at rollout via a manual `workflow_dispatch` with `dry_run=false`. +# The script is idempotent (skips items that already carry the +# `` marker), so a re-run is harmless. +# +# The automatic push trigger runs DRY-RUN only, so merging the script to +# `litellm_internal_staging` never posts a comment; it just confirms the +# workflow is wired up. Posting real comments requires the manual dispatch, +# which is also the only trigger that exposes `OPENAI_API_KEY`. The heads-up +# is intentionally NOT gated on `AGENT_SHIN_ENABLED`: it has to warn +# contributors while that flag is still off, ahead of the flip that turns on +# auto-closing. +# +# The workflow is a thin shell over `.github/scripts/triage_rollout_heads_up.py`. +# Dry-run vs. real run differ in EXACTLY one CLI flag (`--close`), added only +# on a manual dispatch with `dry_run=false`. + +on: + push: + branches: + - litellm_internal_staging + paths: + # The presence of this script on staging IS the rollout merge marker. + # Editing the file later would re-fire the workflow; that's safe because + # the script skips PRs/issues that already have the heads-up marker. + - ".github/scripts/triage_rollout_heads_up.py" + workflow_dispatch: + inputs: + dry_run: + description: "Dry run (true = preview only, false = actually post comments)." + required: false + default: "true" + type: choice + options: + - "true" + - "false" + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + heads-up: + if: github.repository == 'BerriAI/litellm' + runs-on: ubuntu-latest + steps: + - name: Checkout triage scripts + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + sparse-checkout: .github/scripts + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.12" + + - name: Install LLM client + run: pip install --no-cache-dir --require-hashes -r .github/scripts/triage-requirements.txt + + - name: Run heads-up sweep + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Only the manual dispatch (the real-run trigger) needs the LLM key. + # The automatic push trigger runs dry-run and never posts, so it gets + # no key. Mirrors the sibling triage workflows, which expose the key + # only on an enabled/dispatched run rather than unconditionally. + OPENAI_API_KEY: ${{ github.event_name == 'workflow_dispatch' && secrets.OPENAI_API_KEY || '' }} + OPENAI_BASE_URL: ${{ vars.OPENAI_BASE_URL }} + TRIAGE_MODEL: ${{ vars.TRIAGE_MODEL }} + # The real run is a deliberate manual dispatch with dry_run=false. + # Use the EXACT "false" comparison so any unexpected input value + # fail-closes to dry-run (mirrors the AGENT_SHIN_ENABLED pattern in + # the sibling workflows). The automatic push trigger always stays + # dry-run, so merging the script never posts. + DRY_RUN_INPUT: ${{ github.event.inputs.dry_run }} + run: | + set -euo pipefail + ARGS=(--repo "${{ github.repository }}") + if [ "${GITHUB_EVENT_NAME:-}" = "workflow_dispatch" ] && [ "${DRY_RUN_INPUT:-true}" = "false" ]; then + ARGS+=(--close) + echo "::notice::Manual rollout dispatch with dry_run=false -> heads-up comments WILL be posted." + elif [ "${GITHUB_EVENT_NAME:-}" = "workflow_dispatch" ]; then + echo "::notice::Manual dispatch in dry-run mode -> previewing only, no comments will be posted." + else + echo "::notice::Automatic push trigger -> dry-run preview only. Fire the real rollout sweep with a manual workflow_dispatch (dry_run=false)." + fi + python3 .github/scripts/triage_rollout_heads_up.py "${ARGS[@]}" diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 9a1e899fed5..db79fe43038 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -2,9 +2,9 @@ name: GitHub Actions Security Analysis on: push: - branches: [main] + branches: [main, litellm_internal_staging] pull_request: - branches: [main] + branches: [main, litellm_internal_staging] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -18,9 +18,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 permissions: - security-events: write contents: read - actions: read steps: - name: Checkout repository uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 @@ -28,4 +26,9 @@ jobs: persist-credentials: false - name: Run zizmor - uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2 + uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 + with: + version: "1.24.1" + min-severity: medium + advanced-security: false + annotations: true diff --git a/.gitignore b/.gitignore index 572830d35f6..fda3311fe02 100644 --- a/.gitignore +++ b/.gitignore @@ -74,7 +74,6 @@ tests/local_testing/log.txt .codegpt litellm/proxy/_new_new_secret_config.yaml litellm/proxy/custom_guardrail.py -**/.mypy_cache/ litellm/proxy/application.log tests/llm_translation/vertex_test_account.json tests/llm_translation/test_vertex_key.json diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index c114a838d6d..3d2fa3e51c8 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -240,6 +240,24 @@ graph LR 7. `DBSpendUpdateWriter.update_database()` queues spend increments to Redis 8. Background job `update_spend` flushes queued spend to PostgreSQL every 60s +### Data Access Layer (Models & Repositories) + +Database entities and the operations on them live in two packages at the root of `litellm/` so both the gateway (`proxy/`) and the SDK can use them without importing proxy internals: + +- `litellm/models/` holds the canonical Pydantic definitions for every persisted entity (`LiteLLM_VerificationToken`, `LiteLLM_TeamTable`, `LiteLLM_UserTable`, etc.). `proxy/_types.py` re-exports these for backwards compatibility, so existing imports keep working. +- `litellm/repositories/` holds the data-access layer. `BaseRepository[T]` provides the generic CRUD (`find_by_id`, `find_many`, `create`, `update`, `delete`, `count`, `exists`); entity repositories such as `VerificationTokenRepository`, `TeamRepository`, and `UserRepository` add domain-specific queries and writes on top of it. + +Conventions to follow when touching this layer: + +| Concern | How it's handled | +|---------|------------------| +| JSON columns | Prisma `Json` columns are stored as JSON strings. Repositories `json.dumps()` on write and `json.loads()` on read (see `_to_model` and the `_build_*_data` helpers). | +| Archive-then-delete | `delete_team` / `delete_token` copy the row into the `LiteLLM_Deleted*` table and delete the original inside a single `prisma_client.db.tx()` transaction. Archive payloads are built explicitly so only columns that exist on the archive table are written. | +| Column vs. field names | Where a model field differs from its DB column (for example `org_id` maps to the `organization_id` column), the repository translates in both directions rather than relying on Pydantic to guess. | +| Array mutations | Adds use Prisma's atomic `push` (`add_member`, `add_admin`, `add_models`) to avoid read-modify-write races. Removals fall back to read-modify-write because Prisma has no atomic array remove. | + +To add a new entity, define the model under `litellm/models/`, re-export it from `proxy/_types.py` if existing code imports it from there, and add a repository under `litellm/repositories/` (subclass `BaseRepository` for plain CRUD, or add bespoke methods when the entity needs encryption, archiving, or atomic array updates). Mirror the tests in `tests/test_litellm/repositories/`. + --- ## 2. SDK Request Flow diff --git a/CLAUDE.md b/CLAUDE.md index 02a9630b486..2070b6fcdd6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -36,6 +36,12 @@ Don't hesitate to use values in .env to get needed API keys and other secrets, a Run tests, format your code, and lint your code before each commit +When you fix violations gated by `ruff-strict-budget.json` or `basedpyright-code-budget.json`, run `make lint-budget-update` and commit the lowered baselines so the ceilings ratchet down instead of leaving stale headroom + +If you're trying to create a new function that relies on untyped stuff, instead of adding more Any's and pushing `reportAny` / `reportExplicitAny` closer to their basedpyright ceilings, just validate it in the caller with Pydantic (a model or `TypeAdapter` that returns the typed thing or raises will do) and then pass the now typed variable in + +If you get an LIT001 or LIT002 fail, refactor the code to follow functional programming best practices rather than introducing mutable data structures. For example, build values in one shot with comprehensions or generators wrapped in `tuple()` / `frozenset()` instead of seeding an empty `list`/`dict`/`set` and mutating it over time. Ideally `# mutable-ok` is never used; reach for it only as a genuine last resort when an immutable rewrite is truly impossible, and always pair it with a real reason + Ask to commit and push your work when you're done (or if you're confident that your code is good and works, just do it) When you must use real LLM models to, for example, write e2e tests, write a QA runbook, etc., make sure to use the latest models (doesn't have to be smartest, can also be a modern small, fast one. No strong preference for smart vs fast here, just use something modern) as of the year and month of the current date. Do a web search as necessary to figure that out @@ -52,6 +58,21 @@ Do not put names of customers or customer company names in code, PRs, and issues CI supply-chain safety: Never pipe a remote script into a shell (`curl ... | bash`, `wget ... | sh`); download the artifact to a file, verify its SHA-256 checksum, then install. Pin every external tool to a specific version with a full URL (not `latest` or `stable`). Verify checksums for all downloaded binaries, using the provider's official `.sha256` / `.sha256sum` sidecar when available. These rules apply to every download in CI +Follow these coding conventions for new/updated code (a three-line fix in a legacy file shouldn't trigger huge drive-by refactors): + +- Composition over inheritance +- Never-nester: early returns over deep nesting +- Don't throw; model failures as values (One function (e.g., raise_public) maps error union to existing public exception contracts via exhaustive match + assert_never) +- No mutation; don't reassign variables, global or local. Instead of mutable lists and dicts, prefer tuples, frozen dataclasses (with slots=True), etc. +- Use dependency injection +- Fully typed; no `Any` or coarse types like `dict[str, Any]` or just `dict`. Every function parameter must be strongly typed +- Use tagged unions + match +- No monster files or god objects +- No file sprawl: deliberate file and folder structure +- Standard over hand-rolled: use the official SDK or a library where one exists; where none does, follow industry standards instead of inventing local conventions + +Follow conventional commits for commit names and PR titles + ## Think Before Coding **Don't assume. Don't hide confusion. Surface tradeoffs** diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ac83341f64..1080579d0fa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,18 +38,25 @@ Before contributing code to LiteLLM, you must sign our [Contributor License Agre git clone https://github.com/YOUR_USERNAME/litellm.git cd litellm -# Create a new branch for your feature -git checkout -b your-feature-branch +# Create a new branch for your feature (see "Commit and Branch Conventions" below) +git checkout -b feature/your-feature # Install development dependencies make install-dev +# Install git hooks that enforce commit + branch conventions (one-time, opt-in) +make install-hooks + # Verify your setup works make help ``` That's it! Your local development environment is ready. +## Commit and Branch Conventions + +Commits follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and branches follow [Conventional Branches](https://conventional-branch.github.io/). Run `make install-hooks` once per clone to enable the local git hooks that enforce these — see the [contributor docs](https://docs.litellm.ai/docs/extras/contributing_code#commit-and-branch-conventions) for the full type list, examples, the protected-branch bypass list, and how to opt out. + ### 2. Development Workflow Here's the recommended workflow for making changes: @@ -67,12 +74,12 @@ make lint # Run unit tests to ensure nothing is broken make test-unit -# Commit your changes +# Commit your changes (must follow Conventional Commits — see above) git add . -git commit -m "Your descriptive commit message" +git commit -m "feat(scope): your descriptive commit message" -# Push and create a PR -git push origin your-feature-branch +# Push and create a PR (branch must follow Conventional Branches — see above) +git push origin feature/your-feature ``` ## Adding Testing @@ -147,7 +154,7 @@ Individual linting commands: ```bash make format-check # Check Black formatting make lint-ruff # Run Ruff linting -make lint-mypy # Run MyPy type checking +make lint-basedpyright # Run basedpyright type checking make check-circular-imports # Check for circular imports make check-import-safety # Check import safety ``` @@ -209,7 +216,7 @@ LiteLLM follows the [Google Python Style Guide](https://google.github.io/stylegu Our automated quality checks include: - **Black** for consistent code formatting - **Ruff** for linting and code quality -- **MyPy** for static type checking +- **basedpyright** for static type checking - **Circular import detection** - **Import safety validation** @@ -223,7 +230,7 @@ If `make lint` fails: 1. **Formatting issues**: Run `make format` to auto-fix 2. **Ruff issues**: Check the output and fix manually -3. **MyPy issues**: Add proper type hints +3. **basedpyright issues**: Add proper type hints 4. **Circular imports**: Refactor import dependencies 5. **Import safety**: Fix any unprotected imports @@ -238,7 +245,7 @@ If `make test-unit` fails: ### 3. Common Development Tips -- **Use type hints**: MyPy requires proper type annotations +- **Use type hints**: basedpyright requires proper type annotations - **Write descriptive commit messages**: Help reviewers understand your changes - **Keep PRs focused**: One feature/fix per PR - **Test edge cases**: Don't just test the happy path diff --git a/Dockerfile b/Dockerfile index 9ad9ab31b65..4d55148ff89 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,22 +68,24 @@ FROM $LITELLM_RUNTIME_IMAGE AS runtime USER root -RUN apk add --no-cache bash openssl tzdata nodejs npm python3 libsndfile && \ - npm install -g npm@11.14.0 tar@7.5.11 glob@13.0.6 @isaacs/brace-expansion@5.0.1 brace-expansion@5.0.5 minimatch@10.2.4 diff@8.0.3 picomatch@4.0.4 && \ - GLOBAL="$(npm root -g)" && \ - for pkg in tar glob @isaacs/brace-expansion brace-expansion minimatch diff picomatch; do \ - name="${pkg##*/}"; \ - find "$GLOBAL/npm" -type d -name "$name" -path "*/node_modules/$pkg" | while read d; do \ - rm -rf "$d" && cp -rL "$GLOBAL/$pkg" "$d"; \ - done; \ - done && \ - npm cache clean --force && \ - { apk del --no-cache npm 2>/dev/null || true; } +# node (without npm) is required by the prisma CLI at runtime +RUN apk add --no-cache bash openssl tzdata nodejs python3 libsndfile WORKDIR /app ENV PATH="/app/.venv/bin:${PATH}" -COPY --from=builder /app /app +# Copy only what runtime needs. The application is installed inside the venv; +# the rest of the builder's /app is source and build metadata that must not +# ship (manifest-scanning tools attribute everything in it to this image). +# entrypoint.sh invokes litellm/proxy/prisma_migration.py by source path. +COPY --from=builder /app/.venv /app/.venv +COPY --from=builder /app/docker /app/docker +COPY --from=builder /app/schema.prisma /app/schema.prisma +COPY --from=builder /app/litellm/proxy/prisma_migration.py /app/litellm/proxy/prisma_migration.py +# enterprise/ is imported by source path at runtime (proxy_cli puts the +# working directory on sys.path; litellm/proxy/hooks resolves +# enterprise.enterprise_hooks from it) +COPY --from=builder /app/enterprise /app/enterprise # Prisma binaries live in $HOME/.cache (default prisma-python location), # which is /root/.cache here. Copy only the Prisma subdirs — copying the # whole /root/.cache drags in the uv build cache (~660 MB, includes a diff --git a/Makefile b/Makefile index a00a90da601..27150aec938 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,9 @@ test-unit-integrations test-unit-core-utils test-unit-other test-unit-root \ test-proxy-unit-a test-proxy-unit-b test-integration test-unit-helm \ info lint lint-dev format \ - install-dev install-proxy-dev install-test-deps \ + lint-basedpyright lint-basedpyright-budget-update \ + lint-ruff-budget lint-ruff-budget-update lint-budget-update lint-gate \ + install-dev install-proxy-dev install-test-deps install-hooks \ install-helm-unittest check-circular-imports check-import-safety # Default target @@ -17,12 +19,18 @@ help: @echo " make install-proxy-dev-ci - Install proxy dev dependencies (CI-compatible)" @echo " make install-test-deps - Install the full local test environment" @echo " make install-helm-unittest - Install helm unittest plugin" + @echo " make install-hooks - Install git hooks (Conventional Commits + Branches)" @echo " make format - Apply Black code formatting" @echo " make format-check - Check Black code formatting (matches CI)" - @echo " make lint - Run all linting (Ruff, MyPy, Black check, circular imports, import safety)" + @echo " make lint - Run all linting (Ruff, basedpyright, Black check, circular imports, import safety)" @echo " make lint-ruff - Run Ruff linting only" - @echo " make lint-mypy - Run MyPy type checking only" + @echo " make lint-basedpyright - Run basedpyright strict, gated by per-rule error counts" + @echo " make lint-basedpyright-budget-update - Re-capture the basedpyright per-rule budget (ratchet)" @echo " make lint-black - Check Black formatting (matches CI)" + @echo " make lint-ruff-budget - Gate the codebase total of each strict ruff rule against its ceiling" + @echo " make lint-gate - Strict ruff gate in CI-parity mode (fetches staging, simulates the merge)" + @echo " make lint-ruff-budget-update - Re-capture per-rule baselines in ruff-strict-budget.json (ratchet)" + @echo " make lint-budget-update - Re-capture all ratchet budgets (ruff + basedpyright)" @echo " make check-circular-imports - Check for circular imports" @echo " make check-import-safety - Check import safety" @echo " make test - Run all tests" @@ -68,6 +76,11 @@ install-test-deps: install-proxy-dev install-helm-unittest: helm plugin install https://github.com/helm-unittest/helm-unittest --version v0.4.4 || echo "ignore error if plugin exists" +# Install git hooks that enforce Conventional Commits and Conventional Branches. +# Opt-in: not chained into install-dev. +install-hooks: + ./scripts/install_git_hooks.sh + # Formatting format: install-dev cd litellm && $(UV_RUN) black . && cd .. @@ -111,11 +124,29 @@ lint-ruff-FULL-dev: install-dev if [ -n "$$files" ]; then echo "$$files" | xargs $(UV_RUN) ruff check; \ else echo "No changed .py files to check."; fi -lint-mypy: install-dev - cd litellm && $(UV_RUN) mypy . --ignore-missing-imports && cd .. +lint-basedpyright: install-dev + ($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py + +lint-basedpyright-budget-update: install-dev + ($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py --update lint-black: format-check +lint-ruff-budget: install-dev + $(UV_RUN) python scripts/ruff_strict_gate.py + +# Strict gate, invoked the same way CI does in test-linting.yml so a local pass +# means the CI check will pass too. +lint-gate: install-dev + git fetch origin litellm_internal_staging + $(UV_RUN) python scripts/ruff_strict_gate.py --base origin/litellm_internal_staging + +lint-ruff-budget-update: install-dev + $(UV_RUN) python scripts/ruff_strict_gate.py --update + +# Ratchet all budgets in one shot (ruff strict + basedpyright) +lint-budget-update: lint-ruff-budget-update lint-basedpyright-budget-update + check-circular-imports: install-dev cd litellm && $(UV_RUN) python ../tests/documentation_tests/test_circular_imports.py && cd .. @@ -123,10 +154,10 @@ check-import-safety: install-dev @$(UV_RUN) python -c "from litellm import *; print('[from litellm import *] OK! no issues!');" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1) # Combined linting (matches test-linting.yml workflow) -lint: format-check lint-ruff lint-mypy check-circular-imports check-import-safety +lint: format-check lint-ruff lint-basedpyright check-circular-imports check-import-safety lint-ruff-budget # Faster linting for local development (only checks changed code) -lint-dev: lint-format-changed lint-mypy check-circular-imports check-import-safety +lint-dev: lint-format-changed check-circular-imports check-import-safety # Testing targets test: install-test-deps diff --git a/README.md b/README.md index 719f74e5924..3d0f7282d7c 100644 --- a/README.md +++ b/README.md @@ -327,6 +327,7 @@ curl -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ | [Maritalk (`maritalk`)](https://docs.litellm.ai/docs/providers/maritalk) | ✅ | ✅ | ✅ | | | | | | | | | [Meta - Llama API (`meta_llama`)](https://docs.litellm.ai/docs/providers/meta_llama) | ✅ | ✅ | ✅ | | | | | | | | | [Mistral AI API (`mistral`)](https://docs.litellm.ai/docs/providers/mistral) | ✅ | ✅ | ✅ | ✅ | | | | | | | +| [ModelScope (`modelscope`)](https://docs.litellm.ai/docs/providers/modelscope) | ✅ | ✅ | ✅ | | ✅ | | | | | | | [Moonshot (`moonshot`)](https://docs.litellm.ai/docs/providers/moonshot) | ✅ | ✅ | ✅ | | | | | | | | | [Morph (`morph`)](https://docs.litellm.ai/docs/providers/morph) | ✅ | ✅ | ✅ | | | | | | | | | [Nebius AI Studio (`nebius`)](https://docs.litellm.ai/docs/providers/nebius) | ✅ | ✅ | ✅ | ✅ | | | | | | | @@ -344,6 +345,7 @@ curl -X POST 'http://0.0.0.0:4000/v1/chat/completions' \ | [OVHCloud AI Endpoints (`ovhcloud`)](https://docs.litellm.ai/docs/providers/ovhcloud) | ✅ | ✅ | ✅ | | | | | | | | | [Perplexity AI (`perplexity`)](https://docs.litellm.ai/docs/providers/perplexity) | ✅ | ✅ | ✅ | | | | | | | | | [Petals (`petals`)](https://docs.litellm.ai/docs/providers/petals) | ✅ | ✅ | ✅ | | | | | | | | +| [Pinstripes (`pinstripes`)](https://docs.litellm.ai/docs/providers/pinstripes) | ✅ | ✅ | ✅ | | | | | | | | | [Predibase (`predibase`)](https://docs.litellm.ai/docs/providers/predibase) | ✅ | ✅ | ✅ | | | | | | | | | [Recraft (`recraft`)](https://docs.litellm.ai/docs/providers/recraft) | | | | | ✅ | | | | | | | [Replicate (`replicate`)](https://docs.litellm.ai/docs/providers/replicate) | ✅ | ✅ | ✅ | | | | | | | | diff --git a/backend/main.py b/backend/main.py index 4092cd63f69..292ece48e7d 100644 --- a/backend/main.py +++ b/backend/main.py @@ -20,7 +20,11 @@ DatabaseURLSettings.from_env().apply_to_env() from litellm.proxy.proxy_server import app -from backend.routes.allowlist import BACKEND_EXACT_PATHS, BACKEND_PATH_PREFIXES +from backend.routes.allowlist import ( + BACKEND_EXACT_PATHS, + BACKEND_MOUNT_PATHS, + BACKEND_PATH_PREFIXES, +) def _is_backend_route(route) -> bool: @@ -29,8 +33,9 @@ def _is_backend_route(route) -> bool: if path is None: return False if isinstance(route, Mount): - # Static UI mounts are served by the dedicated UI container, not here. - return False + # The dashboard UI static mounts are served by the dedicated UI container. + # Only Mounts in the backend allowlist (e.g. swagger docs) remain on backend. + return path in BACKEND_MOUNT_PATHS if path in BACKEND_EXACT_PATHS: return True return any(path.startswith(prefix) for prefix in BACKEND_PATH_PREFIXES) diff --git a/backend/routes/allowlist.py b/backend/routes/allowlist.py index 610ba3dbd69..d1a576aeb33 100644 --- a/backend/routes/allowlist.py +++ b/backend/routes/allowlist.py @@ -133,3 +133,9 @@ BACKEND_EXACT_PATHS: frozenset[str] = frozenset( "/fallback/login", } ) + +BACKEND_MOUNT_PATHS: frozenset[str] = frozenset( + { + "/swagger", # API documentation static assets belong to the backend + } +) diff --git a/basedpyright-code-budget.json b/basedpyright-code-budget.json new file mode 100644 index 00000000000..7ba7656e407 --- /dev/null +++ b/basedpyright-code-budget.json @@ -0,0 +1,194 @@ +{ + "reportAny": { + "baseline": 24989, + "slack": 2500 + }, + "reportArgumentType": { + "baseline": 1934, + "slack": 180 + }, + "reportAssignmentType": { + "baseline": 220, + "slack": 22 + }, + "reportAttributeAccessIssue": { + "baseline": 346, + "slack": 35 + }, + "reportCallIssue": { + "baseline": 87, + "slack": 10 + }, + "reportConstantRedefinition": { + "baseline": 39, + "slack": 4 + }, + "reportDeprecated": { + "baseline": 217, + "slack": 22 + }, + "reportDuplicateImport": { + "baseline": 28, + "slack": 3 + }, + "reportExplicitAny": { + "baseline": 6931, + "slack": 700 + }, + "reportFunctionMemberAccess": { + "baseline": 7, + "slack": 3 + }, + "reportGeneralTypeIssues": { + "baseline": 151, + "slack": 15 + }, + "reportIncompatibleMethodOverride": { + "baseline": 52, + "slack": 5 + }, + "reportIncompatibleVariableOverride": { + "baseline": 8, + "slack": 3 + }, + "reportInconsistentOverload": { + "baseline": 12, + "slack": 3 + }, + "reportIndexIssue": { + "baseline": 26, + "slack": 3 + }, + "reportInvalidTypeForm": { + "baseline": 23, + "slack": 3 + }, + "reportInvalidTypeVarUse": { + "baseline": 2, + "slack": 3 + }, + "reportMatchNotExhaustive": { + "baseline": 1, + "slack": 3 + }, + "reportMissingParameterType": { + "baseline": 3933, + "slack": 390 + }, + "reportMissingTypeArgument": { + "baseline": 10612, + "slack": 1000 + }, + "reportMissingTypeStubs": { + "baseline": 27, + "slack": 10 + }, + "reportOperatorIssue": { + "baseline": 6, + "slack": 3 + }, + "reportOptionalCall": { + "baseline": 4, + "slack": 3 + }, + "reportOptionalIterable": { + "baseline": 3, + "slack": 3 + }, + "reportOptionalMemberAccess": { + "baseline": 724, + "slack": 72 + }, + "reportOptionalOperand": { + "baseline": 3, + "slack": 3 + }, + "reportOptionalSubscript": { + "baseline": 11, + "slack": 3 + }, + "reportPossiblyUnboundVariable": { + "baseline": 52, + "slack": 10 + }, + "reportPrivateUsage": { + "baseline": 1625, + "slack": 160 + }, + "reportRedeclaration": { + "baseline": 8, + "slack": 3 + }, + "reportReturnType": { + "baseline": 126, + "slack": 13 + }, + "reportTypedDictNotRequiredAccess": { + "baseline": 20, + "slack": 3 + }, + "reportUndefinedVariable": { + "baseline": 2, + "slack": 3 + }, + "reportUnknownArgumentType": { + "baseline": 30603, + "slack": 3000 + }, + "reportUnknownLambdaType": { + "baseline": 75, + "slack": 10 + }, + "reportUnknownMemberType": { + "baseline": 27037, + "slack": 2500 + }, + "reportUnknownParameterType": { + "baseline": 13612, + "slack": 1000 + }, + "reportUnknownVariableType": { + "baseline": 21445, + "slack": 2000 + }, + "reportUnnecessaryCast": { + "baseline": 118, + "slack": 10 + }, + "reportUnnecessaryComparison": { + "baseline": 683, + "slack": 10 + }, + "reportUnnecessaryContains": { + "baseline": 4, + "slack": 3 + }, + "reportUnnecessaryIsInstance": { + "baseline": 808, + "slack": 80 + }, + "reportUntypedBaseClass": { + "baseline": 110, + "slack": 11 + }, + "reportUntypedFunctionDecorator": { + "baseline": 22, + "slack": 3 + }, + "reportUnusedClass": { + "baseline": 22, + "slack": 3 + }, + "reportUnusedFunction": { + "baseline": 137, + "slack": 10 + }, + "reportUnusedImport": { + "baseline": 670, + "slack": 50 + }, + "reportUnusedVariable": { + "baseline": 865, + "slack": 50 + } +} diff --git a/codecov.yaml b/codecov.yaml index 58681b884d0..3baea13e2d3 100644 --- a/codecov.yaml +++ b/codecov.yaml @@ -35,6 +35,22 @@ component_management: - component_id: "Enterprise" paths: - "enterprise/**" + - component_id: "Batches" + paths: + - "*/proxy/batches_endpoints/**" + - "litellm/batches/**" + - "*/llms/*/batches/**" + - component_id: "Videos" + paths: + - "litellm/videos/**" + - "*/proxy/video_endpoints/**" + - "*/llms/*/videos/**" + - component_id: "Realtime" + paths: + - "litellm/realtime_api/**" + - "*/proxy/realtime_endpoints/**" + - "*/llms/*/realtime/**" + - "litellm/litellm_core_utils/realtime_streaming.py" comment: layout: "header, diff, flags, components" # show component info in the PR comment diff --git a/db_scripts/create_views.py b/db_scripts/create_views.py index 3027b38958d..2b34664452d 100644 --- a/db_scripts/create_views.py +++ b/db_scripts/create_views.py @@ -15,7 +15,7 @@ db = Prisma( ) -async def check_view_exists(): # noqa: PLR0915 +async def check_view_exists(): """ Checks if the LiteLLM_VerificationTokenView and MonthlyGlobalSpend exists in the user's db. @@ -34,8 +34,7 @@ async def check_view_exists(): # noqa: PLR0915 print("LiteLLM_VerificationTokenView Exists!") # noqa except Exception: # If an error occurs, the view does not exist, so create it - await db.execute_raw( - """ + await db.execute_raw(""" CREATE VIEW "LiteLLM_VerificationTokenView" AS SELECT v.*, @@ -45,8 +44,7 @@ async def check_view_exists(): # noqa: PLR0915 t.rpm_limit AS team_rpm_limit FROM "LiteLLM_VerificationToken" v LEFT JOIN "LiteLLM_TeamTable" t ON v.team_id = t.team_id; - """ - ) + """) print("LiteLLM_VerificationTokenView Created!") # noqa diff --git a/db_scripts/partition_spend_logs.sql b/db_scripts/partition_spend_logs.sql new file mode 100644 index 00000000000..08fcbddb6f8 --- /dev/null +++ b/db_scripts/partition_spend_logs.sql @@ -0,0 +1,99 @@ +-- Converts an existing LiteLLM_SpendLogs table into a native Postgres +-- range-partitioned table keyed on "startTime". +-- +-- Why: at high request volume, retention via DELETE leaves dead tuples that +-- autovacuum cannot reclaim quickly enough, so the table keeps growing on disk +-- (seen at 450GB+ after ~1 month). With partitioning, retention drops whole +-- partitions, which is instant and returns disk to the OS immediately. +-- +-- This is an opt-in, manual operation. The default LiteLLM schema is NOT +-- partitioned, so existing installs are unaffected until you run this. +-- +-- IMPORTANT +-- * Test on a staging copy first and take a backup. +-- * Postgres cannot convert a populated table to partitioned in place, so this +-- renames the old table aside and creates a fresh partitioned table. +-- * The partition key ("startTime") must be part of the primary key, so the +-- PK becomes composite ("request_id", "startTime"). LiteLLM's write path uses +-- INSERT ... ON CONFLICT DO NOTHING, which is compatible with this. +-- * Choose a partition granularity ("day" is the recommended default for +-- high-volume tables) and keep it consistent with SPEND_LOG_PARTITION_INTERVAL. +-- +-- After running this, enable the feature and set a retention period in +-- proxy_config.yaml: +-- general_settings: +-- use_spend_logs_partitioning: true +-- maximum_spend_logs_retention_period: "30d" +-- The spend-log cleanup job then verifies the table is partitioned and reclaims +-- disk by dropping expired partitions instead of deleting rows. It also +-- pre-creates upcoming partitions on each run. To roll back, see +-- db_scripts/unpartition_spend_logs.sql. + +BEGIN; + +ALTER TABLE "LiteLLM_SpendLogs" RENAME TO "LiteLLM_SpendLogs_legacy"; + +-- Renaming a table does NOT rename its indexes, and index names are unique per +-- schema. Move the legacy table's indexes aside so the CREATE INDEX statements +-- below actually create indexes on the new partitioned table instead of being +-- silently skipped by IF NOT EXISTS, and so the new PK keeps the canonical +-- name instead of getting a "_pkey1" suffix. +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_pkey" + RENAME TO "LiteLLM_SpendLogs_legacy_pkey"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_startTime_idx" + RENAME TO "LiteLLM_SpendLogs_legacy_startTime_idx"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_startTime_request_id_idx" + RENAME TO "LiteLLM_SpendLogs_legacy_startTime_request_id_idx"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_end_user_idx" + RENAME TO "LiteLLM_SpendLogs_legacy_end_user_idx"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_session_id_idx" + RENAME TO "LiteLLM_SpendLogs_legacy_session_id_idx"; + +CREATE TABLE "LiteLLM_SpendLogs" ( + LIKE "LiteLLM_SpendLogs_legacy" INCLUDING DEFAULTS INCLUDING GENERATED +) PARTITION BY RANGE ("startTime"); + +ALTER TABLE "LiteLLM_SpendLogs" + ADD PRIMARY KEY ("request_id", "startTime"); + +-- Recreate every index Prisma defines on the table. LIKE ... INCLUDING DEFAULTS +-- INCLUDING GENERATED copies columns and defaults but NOT indexes, so without +-- these the admin-UI cost-reporting queries that filter by end_user/session_id +-- fall back to sequential scans. On a partitioned parent these propagate to +-- every current and future partition automatically. +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_startTime_idx" + ON "LiteLLM_SpendLogs" ("startTime"); + +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_startTime_request_id_idx" + ON "LiteLLM_SpendLogs" ("startTime", "request_id"); + +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_end_user_idx" + ON "LiteLLM_SpendLogs" ("end_user"); + +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_session_id_idx" + ON "LiteLLM_SpendLogs" ("session_id"); + +-- Safety net: any row whose startTime has no explicit partition lands here so +-- writes never fail. The cleanup job never drops the DEFAULT partition. +CREATE TABLE IF NOT EXISTS "LiteLLM_SpendLogs_pdefault" + PARTITION OF "LiteLLM_SpendLogs" DEFAULT; + +COMMIT; + +-- Backfill (optional). Rows route to the correct partition automatically. +-- For large legacy tables, copy in time-bounded batches during a low-traffic +-- window instead of one statement, or simply keep "LiteLLM_SpendLogs_legacy" +-- read-only until its data ages past your retention, then DROP it. +-- +-- Backfilled rows land in the DEFAULT partition until explicit partitions +-- cover their dates. Postgres refuses to create a partition whose range +-- overlaps rows already in DEFAULT, so the cleanup job may log a warning when +-- pre-creating today's partition right after a backfill; it recovers on its +-- own once those dates age out, and future partitions are unaffected because +-- they are always created ahead of writes. +-- +-- INSERT INTO "LiteLLM_SpendLogs" +-- SELECT * FROM "LiteLLM_SpendLogs_legacy" +-- WHERE "startTime" >= now() - interval '30 days'; +-- +-- DROP TABLE "LiteLLM_SpendLogs_legacy"; diff --git a/db_scripts/unpartition_spend_logs.sql b/db_scripts/unpartition_spend_logs.sql new file mode 100644 index 00000000000..0bd82513e4a --- /dev/null +++ b/db_scripts/unpartition_spend_logs.sql @@ -0,0 +1,69 @@ +-- Rolls back db_scripts/partition_spend_logs.sql: converts the native +-- range-partitioned "LiteLLM_SpendLogs" table back into a plain, +-- non-partitioned table matching the default LiteLLM schema. +-- +-- When/why: run this if you want to stop using partition-based retention and +-- return to DELETE-based cleanup, or to restore the original single-column +-- primary key ("request_id") that the partitioned layout had to widen to a +-- composite ("request_id", "startTime"). +-- +-- IMPORTANT +-- * Test on a staging copy first and take a backup. +-- * Postgres cannot convert a partitioned table back in place, so this +-- renames the partitioned table aside and creates a fresh plain table. +-- * The composite PK could in principle hold the same "request_id" in more +-- than one partition, so rows are copied with ON CONFLICT DO NOTHING to +-- restore the single-column PK without failing on such duplicates. +-- * For large tables the INSERT ... SELECT copies every surviving row and may +-- run long; do it during a low-traffic window. +-- * Also remove use_spend_logs_partitioning from proxy_config.yaml (or set it +-- to false) so the cleanup job returns to DELETE-based retention. + +BEGIN; + +ALTER TABLE "LiteLLM_SpendLogs" RENAME TO "LiteLLM_SpendLogs_partitioned"; + +-- Renaming a table does NOT rename its indexes, and index names are unique per +-- schema. Move the partitioned table's indexes aside so the CREATE INDEX +-- statements below actually create indexes on the new plain table instead of +-- being silently skipped by IF NOT EXISTS, and so the new PK keeps the +-- canonical name. +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_pkey" + RENAME TO "LiteLLM_SpendLogs_partitioned_pkey"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_pkey1" + RENAME TO "LiteLLM_SpendLogs_partitioned_pkey1"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_startTime_idx" + RENAME TO "LiteLLM_SpendLogs_partitioned_startTime_idx"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_startTime_request_id_idx" + RENAME TO "LiteLLM_SpendLogs_partitioned_startTime_request_id_idx"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_end_user_idx" + RENAME TO "LiteLLM_SpendLogs_partitioned_end_user_idx"; +ALTER INDEX IF EXISTS "LiteLLM_SpendLogs_session_id_idx" + RENAME TO "LiteLLM_SpendLogs_partitioned_session_id_idx"; + +CREATE TABLE "LiteLLM_SpendLogs" ( + LIKE "LiteLLM_SpendLogs_partitioned" INCLUDING DEFAULTS INCLUDING GENERATED +); + +ALTER TABLE "LiteLLM_SpendLogs" + ADD PRIMARY KEY ("request_id"); + +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_startTime_idx" + ON "LiteLLM_SpendLogs" ("startTime"); + +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_startTime_request_id_idx" + ON "LiteLLM_SpendLogs" ("startTime", "request_id"); + +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_end_user_idx" + ON "LiteLLM_SpendLogs" ("end_user"); + +CREATE INDEX IF NOT EXISTS "LiteLLM_SpendLogs_session_id_idx" + ON "LiteLLM_SpendLogs" ("session_id"); + +INSERT INTO "LiteLLM_SpendLogs" +SELECT * FROM "LiteLLM_SpendLogs_partitioned" +ON CONFLICT ("request_id") DO NOTHING; + +DROP TABLE "LiteLLM_SpendLogs_partitioned"; + +COMMIT; diff --git a/docker/Dockerfile.database b/docker/Dockerfile.database index c84003a065f..e591a4a2adb 100644 --- a/docker/Dockerfile.database +++ b/docker/Dockerfile.database @@ -66,36 +66,31 @@ FROM $LITELLM_RUNTIME_IMAGE AS runtime USER root -RUN apk add --no-cache bash openssl tzdata nodejs npm python3 libsndfile && \ - npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \ - GLOBAL="$(npm root -g)" && \ - find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \ - rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \ - done && \ - find "$GLOBAL/npm" -type d -name "glob" -path "*/node_modules/glob" | while read d; do \ - rm -rf "$d" && cp -rL "$GLOBAL/glob" "$d"; \ - done && \ - find "$GLOBAL/npm" -type d -name "brace-expansion" -path "*/node_modules/@isaacs/brace-expansion" | while read d; do \ - rm -rf "$d" && cp -rL "$GLOBAL/@isaacs/brace-expansion" "$d"; \ - done && \ - find "$GLOBAL/npm" -type d -name "minimatch" -path "*/node_modules/minimatch" | while read d; do \ - rm -rf "$d" && cp -rL "$GLOBAL/minimatch" "$d"; \ - done && \ - find "$GLOBAL/npm" -type d -name "diff" -path "*/node_modules/diff" | while read d; do \ - rm -rf "$d" && cp -rL "$GLOBAL/diff" "$d"; \ - done && \ - npm cache clean --force && \ - { apk del --no-cache npm 2>/dev/null || true; } +# node (without npm) is required by the prisma CLI at runtime +RUN apk add --no-cache bash openssl tzdata nodejs python3 libsndfile WORKDIR /app ENV PATH="/app/.venv/bin:${PATH}" -COPY --from=builder /app /app +# Copy only what runtime needs. The application is installed inside the venv; +# the rest of the builder's /app is source and build metadata that must not +# ship (manifest-scanning tools attribute everything in it to this image). +# entrypoint.sh invokes litellm/proxy/prisma_migration.py by source path. +COPY --from=builder /app/.venv /app/.venv +COPY --from=builder /app/docker /app/docker +COPY --from=builder /app/schema.prisma /app/schema.prisma +COPY --from=builder /app/litellm/proxy/prisma_migration.py /app/litellm/proxy/prisma_migration.py +# enterprise/ is imported by source path at runtime (proxy_cli puts the +# working directory on sys.path; litellm/proxy/hooks resolves +# enterprise.enterprise_hooks from it) +COPY --from=builder /app/enterprise /app/enterprise # Prisma binaries live in $HOME/.cache (default prisma-python location), # which is /root/.cache here. Copy them from the builder so they survive # deployments that volume-mount /app/.cache (e.g. readOnlyRootFilesystem # + emptyDir) — otherwise the mount would shadow the baked-in query engine. -COPY --from=builder /root/.cache /root/.cache +# Only the Prisma subdirs: the whole /root/.cache drags in the uv build cache. +COPY --from=builder /root/.cache/prisma /root/.cache/prisma +COPY --from=builder /root/.cache/prisma-python /root/.cache/prisma-python RUN find /app/.venv -type f -path "*/tornado/test/*" -delete && \ find /app/.venv -type d -path "*/tornado/test" -delete diff --git a/docker/Dockerfile.non_root b/docker/Dockerfile.non_root index 8717e5b3fcd..eafbd23fd90 100644 --- a/docker/Dockerfile.non_root +++ b/docker/Dockerfile.non_root @@ -95,7 +95,21 @@ RUN for i in 1 2 3; do \ apk add --no-cache python3 bash openssl tzdata libsndfile nodejs && break || sleep 5; \ done -COPY --from=builder /app /app +# Copy only what runtime needs. The application is installed inside the venv; +# the rest of the builder's /app is source and build metadata that must not +# ship (manifest-scanning tools attribute everything in it to this image). +# entrypoint.sh invokes litellm/proxy/prisma_migration.py by source path. +# Prisma caches live under /app/.cache here (XDG_CACHE_HOME / +# PRISMA_BINARY_CACHE_DIR) so the runtime prisma generate finds them. +COPY --from=builder /app/.venv /app/.venv +COPY --from=builder /app/docker /app/docker +COPY --from=builder /app/schema.prisma /app/schema.prisma +COPY --from=builder /app/litellm/proxy/prisma_migration.py /app/litellm/proxy/prisma_migration.py +# enterprise/ is imported by source path at runtime (proxy_cli puts the +# working directory on sys.path; litellm/proxy/hooks resolves +# enterprise.enterprise_hooks from it) +COPY --from=builder /app/enterprise /app/enterprise +COPY --from=builder /app/.cache /app/.cache COPY --from=builder /var/lib/litellm/ui /var/lib/litellm/ui COPY --from=builder /var/lib/litellm/assets /var/lib/litellm/assets diff --git a/docker/build_from_pip/litellm_config.yaml b/docker/build_from_pip/litellm_config.yaml index 51223026170..f54647853ef 100644 --- a/docker/build_from_pip/litellm_config.yaml +++ b/docker/build_from_pip/litellm_config.yaml @@ -3,7 +3,7 @@ model_list: litellm_params: model: openai/fake api_key: fake-key - api_base: https://exampleopenaiendpoint-production.up.railway.app/ + api_base: os.environ/FAKE_OPENAI_API_BASE general_settings: alerting: ["slack"] \ No newline at end of file diff --git a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py index ae5905f9cdf..8486e37384e 100644 --- a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py +++ b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py @@ -1,9 +1,9 @@ # What is this? ## This hook is used to check for LiteLLM managed files in the request body, and replace them with model-specific file id -import asyncio import base64 import json +from types import MappingProxyType from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Union, cast from fastapi import HTTPException @@ -412,7 +412,7 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): 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 + async def async_pre_call_hook( self, user_api_key_dict: UserAPIKeyAuth, cache: DualCache, @@ -504,7 +504,7 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): if retrieve_file_id else False ) - if potential_file_id: + if potential_file_id and "llm_output_file_id," in potential_file_id: model_id = self.get_model_id_from_unified_file_id(potential_file_id) if model_id: data["model"] = model_id @@ -1058,7 +1058,12 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): return file_id.split("llm_output_file_model_id,")[1].split(";")[0] def get_output_file_id_from_unified_file_id(self, file_id: str) -> str: - return file_id.split("llm_output_file_id,")[1].split(";")[0] + marker = "llm_output_file_id," + if marker not in file_id: + raise ValueError( + f"Unified id does not contain {marker!r}: {file_id[:80]!r}" + ) + return file_id.split(marker, 1)[1].split(";")[0] async def async_post_call_success_hook( self, data: Dict, user_api_key_dict: UserAPIKeyAuth, response: LLMResponseTypes @@ -1099,13 +1104,33 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): for file_attr in ["output_file_id", "error_file_id"]: file_id_value = getattr(response, file_attr, None) if file_id_value and model_id: - original_file_id = file_id_value - unified_file_id = self.get_unified_output_file_id( - output_file_id=original_file_id, - model_id=model_id, - model_name=resolved_model_name, + decoded_output_file_id = _is_base64_encoded_unified_file_id( + file_id_value ) - setattr(response, file_attr, unified_file_id) + if ( + decoded_output_file_id + and "llm_output_file_id," in decoded_output_file_id + ): + provider_file_id = ( + self.get_output_file_id_from_unified_file_id( + decoded_output_file_id + ) + ) + unified_file_id = file_id_value + elif decoded_output_file_id: + verbose_logger.warning( + f"Skipping {file_attr}={file_id_value!r}: " + "unified id is not a managed file output id" + ) + continue + else: + provider_file_id = file_id_value + unified_file_id = self.get_unified_output_file_id( + output_file_id=provider_file_id, + model_id=model_id, + model_name=resolved_model_name, + ) + setattr(response, file_attr, unified_file_id) # Use llm_router credentials when available. Without credentials, # Azure and other auth-required providers return 500/401. @@ -1125,27 +1150,27 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): or {} ) file_object = await litellm.afile_retrieve( - file_id=original_file_id, + file_id=provider_file_id, **_creds, ) else: file_object = await litellm.afile_retrieve( custom_llm_provider=model_name.split("/")[0] if model_name and "/" in model_name else "openai", # type: ignore[arg-type] - file_id=original_file_id, + file_id=provider_file_id, ) verbose_logger.debug( - f"Successfully retrieved file object for {file_attr}={original_file_id}" + f"Successfully retrieved file object for {file_attr}={provider_file_id}" ) except Exception as e: verbose_logger.warning( - f"Failed to retrieve file object for {file_attr}={original_file_id}: {str(e)}. Storing with None and will fetch on-demand." + f"Failed to retrieve file object for {file_attr}={provider_file_id}: {str(e)}. Storing with None and will fetch on-demand." ) await self.store_unified_file_id( file_id=unified_file_id, file_object=file_object, litellm_parent_otel_span=user_api_key_dict.parent_otel_span, - model_mappings={model_id: original_file_id}, + model_mappings={model_id: provider_file_id}, user_api_key_dict=user_api_key_dict, ) await self.store_unified_object_id( @@ -1447,8 +1472,8 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): error_message += f" (showing {MAX_BATCHES_IN_ERROR} most recent): {', '.join(batch_statuses)}. " error_message += ( - f"To delete this file before complete cost tracking, please delete or cancel the referencing batch(es) first. " - f"Alternatively, wait for all batches to complete and for cost to be computed (batch_processed=true)." + "To delete this file before complete cost tracking, please delete or cancel the referencing batch(es) first. " + "Alternatively, wait for all batches to complete and for cost to be computed (batch_processed=true)." ) # Record blocked deletion metric @@ -1525,9 +1550,22 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): if specific_model_file_id_mapping: exception_dict = {} - for model_id, file_id in specific_model_file_id_mapping.items(): + for model_id, provider_file_id in specific_model_file_id_mapping.items(): try: - return await llm_router.afile_content(model=model_id, file_id=file_id, **data) # type: ignore + # Cloud-storage providers (e.g. Bedrock S3) validate file ids + # against the deployment's configured bucket, which they only + # trust from this immutable server-side snapshot, never from + # request params. + credentials = llm_router.get_deployment_credentials_with_provider( + model_id=model_id + ) + if credentials is not None: + data["_litellm_internal_model_credentials"] = cast( + Dict, MappingProxyType(dict(credentials)) + ) + else: + data.pop("_litellm_internal_model_credentials", None) + return await llm_router.afile_content(model=model_id, file_id=provider_file_id, **data) # type: ignore except Exception as e: exception_dict[model_id] = str(e) raise Exception( diff --git a/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py b/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py index 75229bacc8f..a057df65500 100644 --- a/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py +++ b/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py @@ -483,7 +483,7 @@ async def new_project( response_model=LiteLLM_ProjectTable, ) @management_endpoint_wrapper -async def update_project( # noqa: PLR0915 +async def update_project( data: UpdateProjectRequest, http_request: Request, user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), diff --git a/enterprise/pyproject.toml b/enterprise/pyproject.toml index d0432448433..b032942427c 100644 --- a/enterprise/pyproject.toml +++ b/enterprise/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "litellm-enterprise" -version = "0.1.42" +version = "0.1.43" description = "Package for LiteLLM Enterprise features" readme = "README.md" requires-python = ">=3.9" @@ -26,7 +26,7 @@ required-version = ">=0.10.9" module-root = "" [tool.commitizen] -version = "0.1.42" +version = "0.1.43" version_files = [ "pyproject.toml:^version", "../pyproject.toml:litellm-enterprise==", diff --git a/litellm/__init__.py b/litellm/__init__.py index f22971dfa13..d21234d2a81 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -43,6 +43,7 @@ from typing import ( Type, ) from litellm.types.integrations.datadog import DatadogInitParams +from litellm.types.integrations.newrelic import NewRelicInitParams from litellm._logging import ( set_verbose, _turn_on_debug, @@ -72,6 +73,7 @@ from litellm.constants import ( replicate_models, clarifai_models, huggingface_models, + modelscope_models, empower_models, together_ai_models, baseten_models, @@ -154,10 +156,12 @@ _custom_logger_compatible_callbacks_literal = Literal[ "gitlab", "cloudzero", "focus", + "mavvrik", "vantage", "posthog", "levo", "compression_interception", + "newrelic", ] cold_storage_custom_logger: Optional[_custom_logger_compatible_callbacks_literal] = None logged_real_time_event_types: Optional[Union[List[str], Literal["*"]]] = None @@ -209,6 +213,15 @@ standard_logging_payload_excluded_fields: Optional[List[str]] = ( log_raw_request_response: bool = False redact_messages_in_exceptions: Optional[bool] = False redact_user_api_key_info: Optional[bool] = False +# When True (default — preserves historical behavior), the Router appends +# internal config names (model_group, fallback model groups, deployment +# timeouts, fallback failure details) onto exception messages and surfaces +# them to clients via ProxyException.message. Set to False if you do NOT +# want the proxy's internal model_name / fallback wiring visible to clients. +# Deprecation: planned to flip to False (redact by default) in a future +# major release; opt in early with `litellm.expose_router_debug_in_errors +# = False`. +expose_router_debug_in_errors: bool = True filter_invalid_headers: Optional[bool] = False add_user_information_to_llm_headers: Optional[bool] = ( None # adds user_id, team_id, token hash (params from StandardLoggingMetadata) to request headers @@ -231,6 +244,17 @@ modify_params = bool(os.getenv("LITELLM_MODIFY_PARAMS", False)) use_chat_completions_url_for_anthropic_messages: bool = bool( os.getenv("LITELLM_USE_CHAT_COMPLETIONS_URL_FOR_ANTHROPIC_MESSAGES", False) ) # When True, routes OpenAI /v1/messages requests to chat/completions instead of the Responses API +# When True, strip the OpenAI-flavored `usage.total_tokens` field that +# LiteLLM injects into non-streaming /v1/messages responses, bringing the +# wire response into line with the Anthropic spec (matches the streaming +# SSE path, which already omits total_tokens). Default False to preserve +# backward compatibility for clients that read the LiteLLM-shaped +# `usage.total_tokens` today. Planned to flip to True in a future major +# release; opt in early via Python: +# `litellm.strip_anthropic_total_tokens = True` +# Or via `litellm_settings.strip_anthropic_total_tokens: true` in +# config.yaml. +strip_anthropic_total_tokens: bool = False route_all_chat_openai_to_responses: bool = ( os.getenv("LITELLM_ROUTE_ALL_CHAT_OPENAI_TO_RESPONSES", "false").lower() == "true" ) # When True, routes all OpenAI /chat/completions requests through the Responses API bridge @@ -359,6 +383,9 @@ enable_gemini_default_thinking_level_low: bool = ( #################### logging: bool = True enable_loadbalancing_on_batch_endpoints: Optional[bool] = None +require_managed_files: bool = ( + False # proxy only - require target_model_names on POST /v1/files +) enable_caching_on_provider_specific_optional_params: bool = ( False # feature-flag for caching on optional params - e.g. 'top_k' ) @@ -406,12 +433,13 @@ anthropic_beta_headers_url: str = os.getenv( "LITELLM_ANTHROPIC_BETA_HEADERS_URL", "https://raw.githubusercontent.com/BerriAI/litellm/main/litellm/anthropic_beta_headers_config.json", ) -suppress_debug_info = False +suppress_debug_info: bool = False dynamodb_table_name: Optional[str] = None s3_callback_params: Optional[Dict] = None s3_audit_callback_params: Optional[Dict] = None datadog_llm_observability_params: Optional[Union[DatadogLLMObsInitParams, Dict]] = None datadog_params: Optional[Union[DatadogInitParams, Dict]] = None +newrelic_params: Optional[Union[NewRelicInitParams, Dict]] = None aws_sqs_callback_params: Optional[Dict] = None generic_logger_headers: Optional[Dict] = None default_key_generate_params: Optional[Dict] = None @@ -442,6 +470,13 @@ custom_prometheus_metadata_labels: List[str] = [] custom_prometheus_tags: List[str] = [] prometheus_metrics_config: Optional[List] = None prometheus_emit_stream_label: bool = False +# Opt-in: emit `rate_limit_category` and `rate_limit_type` labels on +# `litellm_proxy_failed_requests_metric`. Off by default to preserve the +# pre-unification label set so existing dashboards / recording rules keyed on +# that metric keep matching after upgrade. Enable when downstream consumers +# are ready to split 429s by source (vendor vs. litellm) and dimension +# (RPM/TPM/concurrent/budget). +prometheus_emit_rate_limit_labels: bool = False prometheus_user_budget_label_include_email_alias: bool = False prometheus_end_user_metrics_max_series_per_metric: Optional[int] = 10000 prometheus_end_user_metrics_ttl_seconds: Optional[float] = 3600.0 @@ -886,6 +921,8 @@ def add_known_models(model_cost_map: Optional[Dict] = None): heroku_models.add(key) elif value.get("litellm_provider") == "dashscope": dashscope_models.add(key) + elif value.get("litellm_provider") == "modelscope": + modelscope_models.add(key) elif value.get("litellm_provider") == "moonshot": moonshot_models.add(key) elif value.get("litellm_provider") == "publicai": @@ -1005,6 +1042,7 @@ model_list = list( | zai_models | fal_ai_models | deepseek_models + | modelscope_models | azure_ai_models | voyage_models | infinity_models @@ -1138,6 +1176,7 @@ models_by_provider: dict = { "elevenlabs": elevenlabs_models, "heroku": heroku_models, "dashscope": dashscope_models, + "modelscope": modelscope_models, "moonshot": moonshot_models, "publicai": publicai_models, "v0": v0_models, @@ -1303,6 +1342,8 @@ from .exceptions import ( NotFoundError, PermissionDeniedError, RateLimitError, + RateLimitErrorCategory, + RateLimitType, ServiceUnavailableError, BadGatewayError, OpenAIError, @@ -1360,10 +1401,12 @@ from .skills.main import ( from .containers.main import * from .ocr.main import * from .rag.main import * +from .sandbox.main import * from .search.main import * from .realtime_api.main import ( _arealtime, acreate_realtime_client_secret, + acreate_realtime_transcription_session, arealtime_calls, ) from .responses.main import _aresponses_websocket @@ -1714,6 +1757,9 @@ if TYPE_CHECKING: from .llms.voyage.embedding.transformation_contextual import ( VoyageContextualEmbeddingConfig as VoyageContextualEmbeddingConfig, ) + from .llms.voyage.embedding.transformation_multimodal import ( + VoyageMultimodalEmbeddingConfig as VoyageMultimodalEmbeddingConfig, + ) from .llms.infinity.embedding.transformation import ( InfinityEmbeddingConfig as InfinityEmbeddingConfig, ) @@ -1955,6 +2001,9 @@ if TYPE_CHECKING: from .llms.dashscope.rerank.transformation import ( DashScopeRerankConfig as DashScopeRerankConfig, ) + from .llms.modelscope.chat.transformation import ( + ModelScopeChatConfig as ModelScopeChatConfig, + ) from .llms.moonshot.chat.transformation import ( MoonshotChatConfig as MoonshotChatConfig, ) diff --git a/litellm/_lazy_imports_registry.py b/litellm/_lazy_imports_registry.py index bace54ffad1..e653b40fd04 100644 --- a/litellm/_lazy_imports_registry.py +++ b/litellm/_lazy_imports_registry.py @@ -223,6 +223,7 @@ LLM_CONFIG_NAMES = ( "GenAIHubOrchestrationConfig", "VoyageEmbeddingConfig", "VoyageContextualEmbeddingConfig", + "VoyageMultimodalEmbeddingConfig", "InfinityEmbeddingConfig", "PerplexityEmbeddingConfig", "AzureAIStudioConfig", @@ -305,6 +306,7 @@ LLM_CONFIG_NAMES = ( "GigaChatConfig", "GigaChatEmbeddingConfig", "DashScopeChatConfig", + "ModelScopeChatConfig", "MoonshotChatConfig", "DockerModelRunnerChatConfig", "V0ChatConfig", @@ -903,6 +905,10 @@ _LLM_CONFIGS_IMPORT_MAP = { ".llms.voyage.embedding.transformation_contextual", "VoyageContextualEmbeddingConfig", ), + "VoyageMultimodalEmbeddingConfig": ( + ".llms.voyage.embedding.transformation_multimodal", + "VoyageMultimodalEmbeddingConfig", + ), "InfinityEmbeddingConfig": ( ".llms.infinity.embedding.transformation", "InfinityEmbeddingConfig", @@ -1156,6 +1162,10 @@ _LLM_CONFIGS_IMPORT_MAP = { ".llms.dashscope.chat.transformation", "DashScopeChatConfig", ), + "ModelScopeChatConfig": ( + ".llms.modelscope.chat.transformation", + "ModelScopeChatConfig", + ), "MoonshotChatConfig": (".llms.moonshot.chat.transformation", "MoonshotChatConfig"), "DockerModelRunnerChatConfig": ( ".llms.docker_model_runner.chat.transformation", diff --git a/litellm/_logging.py b/litellm/_logging.py index 6b99f50e014..bb743c32878 100644 --- a/litellm/_logging.py +++ b/litellm/_logging.py @@ -419,7 +419,7 @@ def _enable_debugging(): def print_verbose(print_statement): try: if set_verbose: - print(redact_secrets(str(print_statement))) # noqa + print(redact_secrets(str(print_statement))) # noqa: T201 except Exception: pass diff --git a/litellm/_redis.py b/litellm/_redis.py index 5ab551453bb..1b6e1a5e4b0 100644 --- a/litellm/_redis.py +++ b/litellm/_redis.py @@ -311,7 +311,7 @@ def get_redis_url_from_environment(): return f"{redis_protocol}://{auth_part}{os.environ['REDIS_HOST']}:{os.environ['REDIS_PORT']}" -def _get_redis_client_logic(**env_overrides): # noqa: PLR0915 +def _get_redis_client_logic(**env_overrides): """ Common functionality across sync + async redis client implementations """ @@ -567,7 +567,7 @@ def get_redis_client(**env_overrides): return redis.Redis(**redis_kwargs) -def get_redis_async_client( # noqa: PLR0915 +def get_redis_async_client( connection_pool: Optional[async_redis.BlockingConnectionPool] = None, **env_overrides, ) -> Union[async_redis.Redis, async_redis.RedisCluster]: diff --git a/litellm/a2a_protocol/litellm_completion_bridge/handler.py b/litellm/a2a_protocol/litellm_completion_bridge/handler.py index 52e471ff702..a3502f21f95 100644 --- a/litellm/a2a_protocol/litellm_completion_bridge/handler.py +++ b/litellm/a2a_protocol/litellm_completion_bridge/handler.py @@ -19,6 +19,7 @@ from litellm.a2a_protocol.litellm_completion_bridge.transformation import ( A2AStreamingContext, ) from litellm.a2a_protocol.providers.config_manager import A2AProviderConfigManager +from litellm.interactions.agents.utils import merge_agent_headers # litellm_params key carrying the authenticated principal (hashed virtual key) so # A2A provider configs can scope provider-side state (e.g. LangFlow session memory) @@ -48,6 +49,7 @@ class A2ACompletionBridgeHandler: params: Dict[str, Any], litellm_params: Dict[str, Any], api_base: Optional[str] = None, + agent_extra_headers: Optional[Dict[str, str]] = None, *, _skip_a2a_provider_routing: bool = False, ) -> Dict[str, Any]: @@ -59,6 +61,8 @@ class A2ACompletionBridgeHandler: params: A2A MessageSendParams containing the message litellm_params: Agent's litellm_params (custom_llm_provider, model, etc.) api_base: API base URL from agent_card_params + agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and + admin extra_headers) to forward on the upstream HTTP call. Returns: A2A SendMessageResponse dict @@ -80,6 +84,7 @@ class A2ACompletionBridgeHandler: params=params, api_base=api_base, litellm_params=litellm_params, + agent_extra_headers=agent_extra_headers, ) # Extract message from params @@ -106,7 +111,7 @@ class A2ACompletionBridgeHandler: ) # Build completion params dict - completion_params = { + completion_params: Dict[str, Any] = { "model": full_model, "messages": openai_messages, "api_base": api_base, @@ -128,6 +133,12 @@ class A2ACompletionBridgeHandler: params=params, ) + if agent_extra_headers: + completion_params["extra_headers"] = merge_agent_headers( + dynamic_headers=agent_extra_headers, + static_headers=completion_params.get("extra_headers"), + ) + # Call litellm.acompletion response = await litellm.acompletion(**completion_params) @@ -149,6 +160,7 @@ class A2ACompletionBridgeHandler: params: Dict[str, Any], litellm_params: Dict[str, Any], api_base: Optional[str] = None, + agent_extra_headers: Optional[Dict[str, str]] = None, *, _skip_a2a_provider_routing: bool = False, ) -> AsyncIterator[Dict[str, Any]]: @@ -166,6 +178,8 @@ class A2ACompletionBridgeHandler: params: A2A MessageSendParams containing the message litellm_params: Agent's litellm_params (custom_llm_provider, model, etc.) api_base: API base URL from agent_card_params + agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and + admin extra_headers) to forward on the upstream HTTP call. Yields: A2A streaming response events @@ -187,6 +201,7 @@ class A2ACompletionBridgeHandler: params=params, api_base=api_base, litellm_params=litellm_params, + agent_extra_headers=agent_extra_headers, ): yield chunk @@ -222,7 +237,7 @@ class A2ACompletionBridgeHandler: ) # Build completion params dict - completion_params = { + completion_params: Dict[str, Any] = { "model": full_model, "messages": openai_messages, "api_base": api_base, @@ -244,6 +259,12 @@ class A2ACompletionBridgeHandler: params=params, ) + if agent_extra_headers: + completion_params["extra_headers"] = merge_agent_headers( + dynamic_headers=agent_extra_headers, + static_headers=completion_params.get("extra_headers"), + ) + # 1. Emit initial task event (kind: "task", status: "submitted") task_event = A2ACompletionBridgeTransformation.create_task_event(ctx) yield task_event @@ -305,6 +326,7 @@ async def handle_a2a_completion( params: Dict[str, Any], litellm_params: Dict[str, Any], api_base: Optional[str] = None, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Dict[str, Any]: """Convenience function for non-streaming A2A completion.""" return await A2ACompletionBridgeHandler.handle_non_streaming( @@ -312,6 +334,7 @@ async def handle_a2a_completion( params=params, litellm_params=litellm_params, api_base=api_base, + agent_extra_headers=agent_extra_headers, ) @@ -320,6 +343,7 @@ async def handle_a2a_completion_streaming( params: Dict[str, Any], litellm_params: Dict[str, Any], api_base: Optional[str] = None, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> AsyncIterator[Dict[str, Any]]: """Convenience function for streaming A2A completion.""" async for chunk in A2ACompletionBridgeHandler.handle_streaming( @@ -327,5 +351,6 @@ async def handle_a2a_completion_streaming( params=params, litellm_params=litellm_params, api_base=api_base, + agent_extra_headers=agent_extra_headers, ): yield chunk diff --git a/litellm/a2a_protocol/main.py b/litellm/a2a_protocol/main.py index 6979e1ac659..2b6f2cd12b4 100644 --- a/litellm/a2a_protocol/main.py +++ b/litellm/a2a_protocol/main.py @@ -132,6 +132,7 @@ async def _send_message_via_completion_bridge( custom_llm_provider: str, api_base: Optional[str], litellm_params: Dict[str, Any], + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> LiteLLMSendMessageResponse: """ Route a send_message through the LiteLLM completion bridge (e.g. LangGraph, Bedrock AgentCore). @@ -157,6 +158,7 @@ async def _send_message_via_completion_bridge( params=params, litellm_params=litellm_params, api_base=api_base, + agent_extra_headers=agent_extra_headers, ) return LiteLLMSendMessageResponse.from_dict( @@ -283,6 +285,7 @@ async def asend_message( custom_llm_provider=custom_llm_provider, api_base=api_base, litellm_params=litellm_params, + agent_extra_headers=agent_extra_headers, ) # Standard A2A client flow @@ -433,7 +436,7 @@ def _build_streaming_logging_obj( return logging_obj -async def asend_message_streaming( # noqa: PLR0915 +async def asend_message_streaming( a2a_client: Optional["A2AClientType"] = None, request: Optional["SendStreamingMessageRequest"] = None, api_base: Optional[str] = None, @@ -509,6 +512,7 @@ async def asend_message_streaming( # noqa: PLR0915 params=params, litellm_params=litellm_params, api_base=api_base, + agent_extra_headers=agent_extra_headers, ): yield chunk return diff --git a/litellm/a2a_protocol/providers/bedrock_agentcore/config.py b/litellm/a2a_protocol/providers/bedrock_agentcore/config.py index 679e19c23cd..e7f38c6488c 100644 --- a/litellm/a2a_protocol/providers/bedrock_agentcore/config.py +++ b/litellm/a2a_protocol/providers/bedrock_agentcore/config.py @@ -37,6 +37,7 @@ class BedrockAgentCoreA2AConfig(BaseA2AProviderConfig): request_id=request_id, params=params, litellm_params=litellm_params, + agent_extra_headers=kwargs.get("agent_extra_headers"), ) async def handle_streaming( @@ -57,5 +58,6 @@ class BedrockAgentCoreA2AConfig(BaseA2AProviderConfig): request_id=request_id, params=params, litellm_params=litellm_params, + agent_extra_headers=kwargs.get("agent_extra_headers"), ): yield chunk diff --git a/litellm/a2a_protocol/providers/bedrock_agentcore/handler.py b/litellm/a2a_protocol/providers/bedrock_agentcore/handler.py index 11676aaa895..2f93895099b 100644 --- a/litellm/a2a_protocol/providers/bedrock_agentcore/handler.py +++ b/litellm/a2a_protocol/providers/bedrock_agentcore/handler.py @@ -6,7 +6,7 @@ completion bridge that would otherwise strip the envelope. """ import json -from typing import Any, AsyncIterator, Dict, cast +from typing import Any, AsyncIterator, Dict, Optional, cast from litellm._logging import verbose_logger from litellm.a2a_protocol.providers.bedrock_agentcore.transformation import ( @@ -29,6 +29,7 @@ class BedrockAgentCoreA2AHandler: request_id: str, params: Dict[str, Any], litellm_params: Dict[str, Any], + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Dict[str, Any]: """ Handle non-streaming A2A request to AgentCore. @@ -37,6 +38,8 @@ class BedrockAgentCoreA2AHandler: request_id: A2A JSON-RPC request ID params: A2A MessageSendParams containing the message litellm_params: Agent's litellm_params (model, api_key, etc.) + agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and + admin extra_headers) to forward on the upstream HTTP call. Returns: A2A JSON-RPC response dict from the AgentCore agent @@ -47,6 +50,7 @@ class BedrockAgentCoreA2AHandler: params=params, litellm_params=litellm_params, method="message/send", + agent_extra_headers=agent_extra_headers, ) ) @@ -77,6 +81,7 @@ class BedrockAgentCoreA2AHandler: request_id: str, params: Dict[str, Any], litellm_params: Dict[str, Any], + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> AsyncIterator[Dict[str, Any]]: """ Handle streaming A2A request to AgentCore. @@ -85,6 +90,8 @@ class BedrockAgentCoreA2AHandler: request_id: A2A JSON-RPC request ID params: A2A MessageSendParams containing the message litellm_params: Agent's litellm_params (model, api_key, etc.) + agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and + admin extra_headers) to forward on the upstream HTTP call. Yields: A2A streaming response events from the AgentCore agent @@ -96,6 +103,7 @@ class BedrockAgentCoreA2AHandler: litellm_params=litellm_params, method="message/send", stream=True, + agent_extra_headers=agent_extra_headers, ) ) diff --git a/litellm/a2a_protocol/providers/bedrock_agentcore/transformation.py b/litellm/a2a_protocol/providers/bedrock_agentcore/transformation.py index 44dc10fe2b7..f868845bb58 100644 --- a/litellm/a2a_protocol/providers/bedrock_agentcore/transformation.py +++ b/litellm/a2a_protocol/providers/bedrock_agentcore/transformation.py @@ -6,11 +6,66 @@ and signs requests via AmazonAgentCoreConfig (SigV4 or JWT). """ import json -from typing import Any, AsyncIterator, Dict, Tuple +from typing import Any, AsyncIterator, Dict, Mapping, Optional, Tuple from litellm._logging import verbose_logger from litellm.llms.bedrock.chat.agentcore.transformation import AmazonAgentCoreConfig +# Reserved outbound header names that must never be sourced from per-request +# ``agent_extra_headers`` for AgentCore requests. ``agent_extra_headers`` carries +# values rewritten from the client-controlled ``x-a2a-{agent}-*`` convention, so +# allowing these would let any caller with access to the agent spoof the AWS +# request identity / SigV4 metadata by overwriting headers the proxy sets from +# trusted server-side config. +# +# The runtime headers (session / user id) are derived server-side from +# ``runtimeSessionId`` / ``runtimeUserId`` in the agent's ``litellm_params``; +# ``authorization`` is set by the AgentCore signer (JWT or SigV4); ``host`` and +# the ``x-amz-*`` family are owned by SigV4 itself. +_RESERVED_EXACT_HEADERS = frozenset( + { + "authorization", + "host", + } +) +_RESERVED_PREFIX_HEADERS: Tuple[str, ...] = ( + "x-amzn-bedrock-agentcore-runtime-", + "x-amz-", +) + + +def _filter_reserved_headers( + agent_extra_headers: Optional[Mapping[str, str]], +) -> Optional[Dict[str, str]]: + """ + Strip reserved AWS / AgentCore headers from caller-supplied + ``agent_extra_headers`` before they are merged into the signed request. + + Returns ``None`` if the result is empty. + """ + if not agent_extra_headers: + return None + + filtered: Dict[str, str] = {} + dropped: list = [] + for k, v in agent_extra_headers.items(): + k_lower = k.lower() + if k_lower in _RESERVED_EXACT_HEADERS or any( + k_lower.startswith(prefix) for prefix in _RESERVED_PREFIX_HEADERS + ): + dropped.append(k) + continue + filtered[k] = v + + if dropped: + verbose_logger.warning( + "BedrockAgentCore A2A: dropping reserved header(s) from " + "agent_extra_headers (not forwarded to AgentCore): %s", + sorted(dropped), + ) + + return filtered or None + class BedrockAgentCoreA2ATransformation: """ @@ -27,6 +82,7 @@ class BedrockAgentCoreA2ATransformation: litellm_params: Dict[str, Any], method: str = "message/send", stream: bool = False, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Tuple[str, dict, bytes]: """ Build the AgentCore URL, construct a JSON-RPC envelope, and sign the request. @@ -37,6 +93,15 @@ class BedrockAgentCoreA2ATransformation: litellm_params: Agent's litellm_params (model, api_key, etc.) method: JSON-RPC method name (default: "message/send") stream: Whether this is a streaming request + agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and + admin extra_headers) to forward on the upstream HTTP call. Merged into + the headers dict before signing so SigV4 includes them in the signature. + Reserved AWS / AgentCore identity headers (``authorization``, ``host``, + ``x-amzn-bedrock-agentcore-runtime-*``, ``x-amz-*``) are filtered out + here to prevent a caller-controlled ``x-a2a-{agent}-*`` header from + spoofing the AgentCore runtime user id or other SigV4 metadata. Use + ``api_key`` / ``runtimeUserId`` / ``runtimeSessionId`` in litellm_params + (not ``agent_extra_headers``) to override those values. Returns: Tuple of (url, signed_headers, signed_body_bytes) @@ -85,6 +150,13 @@ class BedrockAgentCoreA2ATransformation: if runtime_user_id: headers["X-Amzn-Bedrock-AgentCore-Runtime-User-Id"] = runtime_user_id + # Merge per-request agent headers before signing so SigV4 covers them. + # Reserved headers are stripped first to prevent client-controlled values + # from spoofing the AgentCore runtime identity / SigV4 metadata. + safe_extra_headers = _filter_reserved_headers(agent_extra_headers) + if safe_extra_headers: + headers.update(safe_extra_headers) + # Sign the request (SigV4 or JWT depending on api_key presence) signed_headers, signed_body = agentcore_config.sign_request( headers=headers, diff --git a/litellm/a2a_protocol/providers/pydantic_ai_agents/config.py b/litellm/a2a_protocol/providers/pydantic_ai_agents/config.py index 2f16779cc9f..6f067aecd2b 100644 --- a/litellm/a2a_protocol/providers/pydantic_ai_agents/config.py +++ b/litellm/a2a_protocol/providers/pydantic_ai_agents/config.py @@ -31,6 +31,7 @@ class PydanticAIProviderConfig(BaseA2AProviderConfig): params=params, api_base=api_base, timeout=kwargs.get("timeout", 60.0), + agent_extra_headers=kwargs.get("agent_extra_headers"), ) async def handle_streaming( @@ -50,5 +51,6 @@ class PydanticAIProviderConfig(BaseA2AProviderConfig): timeout=kwargs.get("timeout", 60.0), chunk_size=kwargs.get("chunk_size", 50), delay_ms=kwargs.get("delay_ms", 10), + agent_extra_headers=kwargs.get("agent_extra_headers"), ): yield chunk diff --git a/litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py b/litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py index 5b8d6b94ff2..b5d3f262a63 100644 --- a/litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py +++ b/litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py @@ -28,6 +28,7 @@ class PydanticAIHandler: params: Dict[str, Any], api_base: Optional[str] = None, timeout: float = 60.0, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Dict[str, Any]: """ Handle non-streaming request to Pydantic AI agent. @@ -37,6 +38,8 @@ class PydanticAIHandler: params: A2A MessageSendParams containing the message api_base: Base URL of the Pydantic AI agent timeout: Request timeout in seconds + agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and + admin extra_headers) to forward on the upstream HTTP call. Returns: A2A SendMessageResponse dict @@ -51,6 +54,7 @@ class PydanticAIHandler: request_id=request_id, params=params, timeout=timeout, + agent_extra_headers=agent_extra_headers, ) return response_data @@ -63,6 +67,7 @@ class PydanticAIHandler: timeout: float = 60.0, chunk_size: int = 50, delay_ms: int = 10, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> AsyncIterator[Dict[str, Any]]: """ Handle streaming request to Pydantic AI agent with fake streaming. @@ -78,6 +83,8 @@ class PydanticAIHandler: timeout: Request timeout in seconds chunk_size: Number of characters per chunk delay_ms: Delay between chunks in milliseconds + agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and + admin extra_headers) to forward on the upstream HTTP call. Yields: A2A streaming response events @@ -94,6 +101,7 @@ class PydanticAIHandler: request_id=request_id, params=params, timeout=timeout, + agent_extra_headers=agent_extra_headers, ) # Convert raw task response to fake streaming chunks diff --git a/litellm/a2a_protocol/providers/pydantic_ai_agents/transformation.py b/litellm/a2a_protocol/providers/pydantic_ai_agents/transformation.py index bf68a01d98c..8fac43e7ae1 100644 --- a/litellm/a2a_protocol/providers/pydantic_ai_agents/transformation.py +++ b/litellm/a2a_protocol/providers/pydantic_ai_agents/transformation.py @@ -6,7 +6,7 @@ This module provides fake streaming by converting non-streaming responses into s """ import asyncio -from typing import Any, AsyncIterator, Dict, cast +from typing import Any, AsyncIterator, Dict, Optional, cast from uuid import uuid4 from litellm._logging import verbose_logger @@ -86,6 +86,7 @@ class PydanticAITransformation: request_id: str, max_attempts: int = 30, poll_interval: float = 0.5, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Dict[str, Any]: """ Poll for task completion using tasks/get method. @@ -112,7 +113,10 @@ class PydanticAITransformation: response = await client.post( endpoint, json=poll_request, - headers={"Content-Type": "application/json"}, + headers={ + **(agent_extra_headers or {}), + "Content-Type": "application/json", + }, ) response.raise_for_status() poll_data = response.json() @@ -142,6 +146,7 @@ class PydanticAITransformation: request_id: str, params: Any, timeout: float = 60.0, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Dict[str, Any]: """ Send a request to Pydantic AI agent and return the raw task response. @@ -189,7 +194,10 @@ class PydanticAITransformation: response = await client.post( endpoint, json=a2a_request, - headers={"Content-Type": "application/json"}, + headers={ + **(agent_extra_headers or {}), + "Content-Type": "application/json", + }, ) response.raise_for_status() response_data = response.json() @@ -211,6 +219,7 @@ class PydanticAITransformation: endpoint=endpoint, task_id=task_id, request_id=request_id, + agent_extra_headers=agent_extra_headers, ) verbose_logger.info( @@ -225,6 +234,7 @@ class PydanticAITransformation: request_id: str, params: Any, timeout: float = 60.0, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Dict[str, Any]: """ Send a non-streaming A2A request to Pydantic AI agent and wait for completion. @@ -234,6 +244,7 @@ class PydanticAITransformation: request_id: A2A JSON-RPC request ID params: A2A MessageSendParams containing the message (dict or Pydantic model) timeout: Request timeout in seconds + agent_extra_headers: Per-request headers to forward on the upstream HTTP call. Returns: Standard A2A non-streaming response format with message @@ -244,6 +255,7 @@ class PydanticAITransformation: request_id=request_id, params=params, timeout=timeout, + agent_extra_headers=agent_extra_headers, ) # Transform to standard A2A non-streaming format @@ -258,6 +270,7 @@ class PydanticAITransformation: request_id: str, params: Any, timeout: float = 60.0, + agent_extra_headers: Optional[Dict[str, str]] = None, ) -> Dict[str, Any]: """ Send a request to Pydantic AI agent and return the raw task response. @@ -269,6 +282,7 @@ class PydanticAITransformation: request_id: A2A JSON-RPC request ID params: A2A MessageSendParams containing the message timeout: Request timeout in seconds + agent_extra_headers: Per-request headers to forward on the upstream HTTP call. Returns: Raw Pydantic AI task response (with history/artifacts) @@ -278,6 +292,7 @@ class PydanticAITransformation: request_id=request_id, params=params, timeout=timeout, + agent_extra_headers=agent_extra_headers, ) @staticmethod diff --git a/litellm/anthropic_beta_headers_config.json b/litellm/anthropic_beta_headers_config.json index d02afe37569..11fdb26e42d 100644 --- a/litellm/anthropic_beta_headers_config.json +++ b/litellm/anthropic_beta_headers_config.json @@ -75,7 +75,7 @@ "effort-2025-11-24": "effort-2025-11-24", "fast-mode-2026-02-01": null, "files-api-2025-04-14": null, - "fine-grained-tool-streaming-2025-05-14": null, + "fine-grained-tool-streaming-2025-05-14": "fine-grained-tool-streaming-2025-05-14", "interleaved-thinking-2025-05-14": null, "mcp-client-2025-11-20": null, "mcp-client-2025-04-04": null, @@ -106,7 +106,7 @@ "effort-2025-11-24": "effort-2025-11-24", "fast-mode-2026-02-01": null, "files-api-2025-04-14": null, - "fine-grained-tool-streaming-2025-05-14": null, + "fine-grained-tool-streaming-2025-05-14": "fine-grained-tool-streaming-2025-05-14", "interleaved-thinking-2025-05-14": null, "mcp-client-2025-11-20": null, "mcp-client-2025-04-04": null, @@ -129,7 +129,7 @@ "bash_20241022": null, "bash_20250124": null, "code-execution-2025-08-25": null, - "compact-2026-01-12": null, + "compact-2026-01-12": "compact-2026-01-12", "computer-use-2025-01-24": "computer-use-2025-01-24", "computer-use-2025-11-24": "computer-use-2025-11-24", "context-1m-2025-08-07": "context-1m-2025-08-07", diff --git a/litellm/batches/main.py b/litellm/batches/main.py index 15ee9303969..f124882b5a4 100644 --- a/litellm/batches/main.py +++ b/litellm/batches/main.py @@ -157,7 +157,7 @@ async def acreate_batch( @client -def create_batch( # noqa: PLR0915 +def create_batch( completion_window: Literal["24h"], endpoint: Literal["/v1/chat/completions", "/v1/embeddings", "/v1/completions"], input_file_id: str, diff --git a/litellm/caching/caching.py b/litellm/caching/caching.py index 11733ce4cee..cb122e90102 100644 --- a/litellm/caching/caching.py +++ b/litellm/caching/caching.py @@ -27,7 +27,7 @@ from litellm.types.utils import EmbeddingResponse, all_litellm_params from .azure_blob_cache import AzureBlobCache from .base_cache import BaseCache from .disk_cache import DiskCache -from .dual_cache import DualCache # noqa +from .dual_cache import DualCache # noqa: F401 from .gcs_cache import GCSCache from .in_memory_cache import InMemoryCache from .qdrant_semantic_cache import QdrantSemanticCache @@ -41,7 +41,7 @@ def print_verbose(print_statement): try: verbose_logger.debug(print_statement) if litellm.set_verbose: - print(print_statement) # noqa + print(print_statement) # noqa: T201 except Exception: pass @@ -100,6 +100,8 @@ class Cache: gcs_path: Optional[str] = None, redis_semantic_cache_embedding_model: str = "text-embedding-ada-002", redis_semantic_cache_index_name: Optional[str] = None, + valkey_semantic_cache_embedding_model: str = "text-embedding-ada-002", + valkey_semantic_cache_index_name: str | None = None, redis_flush_size: Optional[int] = None, redis_startup_nodes: Optional[List] = None, disk_cache_dir: Optional[str] = None, @@ -208,6 +210,21 @@ class Cache: index_name=redis_semantic_cache_index_name, **kwargs, ) + elif type == LiteLLMCacheType.VALKEY_SEMANTIC: + # Imported here, not at module top, so the optional redis dependency + # is only required when this backend is actually selected. + from .valkey_semantic_cache import ValkeySemanticCache + + self.cache = ValkeySemanticCache( + host=host, + port=port, + password=password, + similarity_threshold=similarity_threshold, + embedding_model=valkey_semantic_cache_embedding_model, + index_name=valkey_semantic_cache_index_name, + startup_nodes=redis_startup_nodes, + **kwargs, + ) elif type == LiteLLMCacheType.QDRANT_SEMANTIC: self.cache = QdrantSemanticCache( qdrant_api_base=qdrant_api_base, @@ -267,12 +284,50 @@ class Cache: if ( self.type == LiteLLMCacheType.REDIS or self.type == LiteLLMCacheType.REDIS_SEMANTIC + or self.type == LiteLLMCacheType.VALKEY_SEMANTIC ) and default_in_redis_ttl is not None: self.ttl = default_in_redis_ttl if self.namespace is not None and isinstance(self.cache, RedisCache): self.cache.namespace = self.namespace + # Params whose values carry prompt content. Excluded from semantic-cache + # scope keys so differently worded prompts share a bucket and match via + # vector similarity rather than being split into per-wording buckets. + _SEMANTIC_CACHE_SCOPE_EXCLUDED_PARAMS: frozenset = frozenset( + {"messages", "prompt", "input"} + ) + + # Server-set identity (from proxy auth) used to isolate semantic-cache + # buckets per tenant. Required once the prompt is out of the scope key, so a + # similar prompt from another key/team/org stays in a separate bucket. + _SEMANTIC_CACHE_TENANT_SCOPE_FIELDS: tuple[str, ...] = ( + "user_api_key", + "user_api_key_team_id", + "user_api_key_org_id", + ) + + def _is_semantic_cache(self) -> bool: + return self.type in ( + LiteLLMCacheType.REDIS_SEMANTIC, + LiteLLMCacheType.QDRANT_SEMANTIC, + LiteLLMCacheType.VALKEY_SEMANTIC, + ) + + def _get_semantic_cache_tenant_scope(self, kwargs: dict) -> str: + metadata: dict = kwargs.get("metadata") or {} + litellm_params: dict = kwargs.get("litellm_params") or {} + metadata_in_litellm_params: dict = litellm_params.get("metadata") or {} + + scope = "" + for field in self._SEMANTIC_CACHE_TENANT_SCOPE_FIELDS: + value = metadata.get(field) + if value is None: + value = metadata_in_litellm_params.get(field) + if value is not None: + scope += f"{field}: {value}" + return scope + def get_cache_key(self, **kwargs) -> str: """ Get the cache key for the given arguments. @@ -293,7 +348,15 @@ class Cache: combined_kwargs = ModelParamHelper._get_all_llm_api_params() litellm_param_kwargs = all_litellm_params + is_semantic_cache = self._is_semantic_cache() + scope_excluded_params = ( + self._SEMANTIC_CACHE_SCOPE_EXCLUDED_PARAMS + if is_semantic_cache + else frozenset() + ) for param in kwargs: + if param in scope_excluded_params: + continue if param in combined_kwargs: param_value: Optional[str] = self._get_param_value(param, kwargs) if param_value is not None: @@ -309,9 +372,16 @@ class Cache: param_value = kwargs[param] cache_key += f"{str(param)}: {str(param_value)}" - verbose_logger.debug("\nCreated cache key: %s", cache_key) + if is_semantic_cache: + cache_key += self._get_semantic_cache_tenant_scope(kwargs) + hashed_cache_key = Cache._get_hashed_cache_key(cache_key) hashed_cache_key = self._add_namespace_to_cache_key(hashed_cache_key, **kwargs) + verbose_logger.debug( + "\nCreated cache key: %s (source material length: %d)", + hashed_cache_key, + len(cache_key), + ) # Remove preset_cache_key from kwargs to avoid "got multiple values" TypeError # when kwargs already contains preset_cache_key from upstream callers kwargs_for_preset = {k: v for k, v in kwargs.items() if k != "preset_cache_key"} @@ -497,6 +567,34 @@ class Cache: return cached_response return cached_result + @staticmethod + def _get_safe_cache_lookup_kwargs(kwargs: Dict[str, Any]) -> Dict[str, Any]: + cache_lookup_kwargs: Dict[str, Any] = {} + for prompt_kwarg in ("messages", "input"): + if prompt_kwarg in kwargs: + cache_lookup_kwargs[prompt_kwarg] = kwargs[prompt_kwarg] + + if isinstance(kwargs.get("metadata"), dict): + cache_lookup_kwargs["metadata"] = {} + + return cache_lookup_kwargs + + @staticmethod + def _update_metadata_from_cache_lookup_kwargs( + original_kwargs: Dict[str, Any], cache_lookup_kwargs: Dict[str, Any] + ) -> None: + original_metadata = original_kwargs.get("metadata") + cache_lookup_metadata = cache_lookup_kwargs.get("metadata") + if not isinstance(original_metadata, dict) or not isinstance( + cache_lookup_metadata, dict + ): + return + + if "semantic-similarity" in cache_lookup_metadata: + original_metadata["semantic-similarity"] = cache_lookup_metadata[ + "semantic-similarity" + ] + def get_cache(self, dynamic_cache_object: Optional[BaseCache] = None, **kwargs): """ Retrieves the cached result for the given arguments. @@ -511,7 +609,6 @@ class Cache: try: # never block execution if self.should_use_cache(**kwargs) is not True: return - messages = kwargs.get("messages", []) if "cache_key" in kwargs: cache_key = kwargs["cache_key"] else: @@ -523,12 +620,19 @@ class Cache: or cache_control_args.get("s-max-age") or float("inf") ) + cache_lookup_kwargs = self._get_safe_cache_lookup_kwargs(kwargs) if dynamic_cache_object is not None: cached_result = dynamic_cache_object.get_cache( - cache_key, messages=messages + cache_key, **cache_lookup_kwargs ) else: - cached_result = self.cache.get_cache(cache_key, messages=messages) + cached_result = self.cache.get_cache( + cache_key, **cache_lookup_kwargs + ) + self._update_metadata_from_cache_lookup_kwargs( + original_kwargs=kwargs, + cache_lookup_kwargs=cache_lookup_kwargs, + ) return self._get_cache_logic( cached_result=cached_result, max_age=max_age ) @@ -549,7 +653,6 @@ class Cache: if self.should_use_cache(**kwargs) is not True: return - kwargs.get("messages", []) if "cache_key" in kwargs: cache_key = kwargs["cache_key"] else: @@ -654,6 +757,7 @@ class Cache: self, embedding_response: Any, model: Optional[str], + prompt_tokens: Optional[int] = None, prompt_tokens_details: Optional[dict] = None, ) -> CachedEmbedding: """ @@ -666,6 +770,7 @@ class Cache: "index": embedding_response.get("index"), "object": embedding_response.get("object"), "model": model, + "prompt_tokens": prompt_tokens, "prompt_tokens_details": prompt_tokens_details, } elif hasattr(embedding_response, "model_dump"): @@ -675,6 +780,7 @@ class Cache: "index": data.get("index"), "object": data.get("object"), "model": model, + "prompt_tokens": prompt_tokens, "prompt_tokens_details": prompt_tokens_details, } else: @@ -684,6 +790,7 @@ class Cache: "index": data.get("index"), "object": data.get("object"), "model": model, + "prompt_tokens": prompt_tokens, "prompt_tokens_details": prompt_tokens_details, } except KeyError as e: @@ -732,6 +839,29 @@ class Cache: per_item[key] = value return per_item if per_item else None + def _get_per_item_prompt_tokens( + self, + result: EmbeddingResponse, + idx_in_result_data: int, + ) -> Optional[int]: + """ + Extract the per-item prompt_tokens from a response for caching. + + Single-item responses store the full usage.prompt_tokens. Multi-item + responses distribute it evenly (with remainder) so that summing all + per-item values on retrieval reconstructs the original total. + """ + if result.usage is None or result.usage.prompt_tokens is None: + return None + + total = result.usage.prompt_tokens + num_items = len(result.data) + if num_items <= 1: + return total + + quotient, remainder = divmod(total, num_items) + return quotient + (1 if idx_in_result_data < remainder else 0) + def add_embedding_response_to_cache( self, result: EmbeddingResponse, @@ -743,7 +873,11 @@ class Cache: kwargs["cache_key"] = preset_cache_key embedding_response = result.data[idx_in_result_data] - # Extract per-item prompt_tokens_details from response usage + # Extract per-item prompt_tokens + details from response usage + prompt_tokens = self._get_per_item_prompt_tokens( + result=result, + idx_in_result_data=idx_in_result_data, + ) prompt_tokens_details = self._get_per_item_prompt_tokens_details( result=result, idx_in_result_data=idx_in_result_data, @@ -754,6 +888,7 @@ class Cache: embedding_dict: CachedEmbedding = self._convert_to_cached_embedding( embedding_response, model_name, + prompt_tokens=prompt_tokens, prompt_tokens_details=prompt_tokens_details, ) diff --git a/litellm/caching/caching_handler.py b/litellm/caching/caching_handler.py index 3f4e54382c9..2a8bd856040 100644 --- a/litellm/caching/caching_handler.py +++ b/litellm/caching/caching_handler.py @@ -456,7 +456,10 @@ class LLMCachingHandler: index=idx, object="embedding", ) - if isinstance(kwargs_input_as_list[idx], str): + cached_prompt_tokens = cr.get("prompt_tokens") + if cached_prompt_tokens is not None: + prompt_tokens += cached_prompt_tokens + elif isinstance(kwargs_input_as_list[idx], str): from litellm.utils import token_counter prompt_tokens += token_counter( diff --git a/litellm/caching/gcs_cache.py b/litellm/caching/gcs_cache.py index 3327e094bc2..0e6a111eb2b 100644 --- a/litellm/caching/gcs_cache.py +++ b/litellm/caching/gcs_cache.py @@ -5,6 +5,7 @@ Supports syncing responses to Google Cloud Storage Buckets using HTTP requests. import json import asyncio from typing import Optional +from urllib.parse import quote from litellm._logging import print_verbose, verbose_logger from litellm.integrations.gcs_bucket.gcs_bucket_base import GCSBucketBase @@ -48,7 +49,7 @@ class GCSCache(BaseCache): headers = self._construct_headers() object_name = self.key_prefix + key bucket_name = self.bucket_name - url = f"https://storage.googleapis.com/upload/storage/v1/b/{bucket_name}/o?uploadType=media&name={object_name}" + url = f"https://storage.googleapis.com/upload/storage/v1/b/{bucket_name}/o?uploadType=media&name={quote(object_name, safe='')}" data = json.dumps(value) self.sync_client.post(url=url, data=data, headers=headers) except Exception as e: @@ -59,7 +60,7 @@ class GCSCache(BaseCache): headers = self._construct_headers() object_name = self.key_prefix + key bucket_name = self.bucket_name - url = f"https://storage.googleapis.com/upload/storage/v1/b/{bucket_name}/o?uploadType=media&name={object_name}" + url = f"https://storage.googleapis.com/upload/storage/v1/b/{bucket_name}/o?uploadType=media&name={quote(object_name, safe='')}" data = json.dumps(value) await self.async_client.post(url=url, data=data, headers=headers) except Exception as e: @@ -72,7 +73,7 @@ class GCSCache(BaseCache): headers = self._construct_headers() object_name = self.key_prefix + key bucket_name = self.bucket_name - url = f"https://storage.googleapis.com/storage/v1/b/{bucket_name}/o/{object_name}?alt=media" + url = f"https://storage.googleapis.com/storage/v1/b/{bucket_name}/o/{quote(object_name, safe='')}?alt=media" response = self.sync_client.get(url=url, headers=headers) if response.status_code == 200: cached_response = json.loads(response.text) @@ -91,7 +92,7 @@ class GCSCache(BaseCache): headers = self._construct_headers() object_name = self.key_prefix + key bucket_name = self.bucket_name - url = f"https://storage.googleapis.com/storage/v1/b/{bucket_name}/o/{object_name}?alt=media" + url = f"https://storage.googleapis.com/storage/v1/b/{bucket_name}/o/{quote(object_name, safe='')}?alt=media" response = await self.async_client.get(url=url, headers=headers) if response.status_code == 200: return json.loads(response.text) diff --git a/litellm/caching/qdrant_semantic_cache.py b/litellm/caching/qdrant_semantic_cache.py index cb521efca05..68d3b8c20b3 100644 --- a/litellm/caching/qdrant_semantic_cache.py +++ b/litellm/caching/qdrant_semantic_cache.py @@ -28,7 +28,7 @@ from .base_cache import BaseCache class QdrantSemanticCache(BaseCache): CACHE_KEY_FIELD_NAME = "litellm_cache_key" - def __init__( # noqa: PLR0915 + def __init__( self, qdrant_api_base=None, qdrant_api_key=None, diff --git a/litellm/caching/redis_cache.py b/litellm/caching/redis_cache.py index cb9ce475d30..ba07511448a 100644 --- a/litellm/caching/redis_cache.py +++ b/litellm/caching/redis_cache.py @@ -22,6 +22,7 @@ import litellm from litellm._logging import print_verbose, verbose_logger from litellm.constants import ( DEFAULT_REDIS_MAJOR_VERSION, + REDIS_CIRCUIT_BREAKER_ENABLED, REDIS_CIRCUIT_BREAKER_FAILURE_THRESHOLD, REDIS_CIRCUIT_BREAKER_RECOVERY_TIMEOUT, ) @@ -114,15 +115,23 @@ class RedisCircuitBreaker: OPEN = "open" HALF_OPEN = "half_open" - def __init__(self, failure_threshold: int, recovery_timeout: int) -> None: + def __init__( + self, + failure_threshold: int, + recovery_timeout: int, + enabled: bool = True, + ) -> None: self.failure_threshold = failure_threshold self.recovery_timeout = recovery_timeout + self.enabled = enabled self._failure_count = 0 self._opened_at: Optional[float] = None self._state = self.CLOSED def is_open(self) -> bool: """Returns True if Redis calls should be skipped.""" + if not self.enabled: + return False if self._state == self.HALF_OPEN: # Probe already in flight — fast-fail all concurrent requests. # Only the one call that caused the OPEN→HALF_OPEN transition @@ -136,6 +145,8 @@ class RedisCircuitBreaker: return False def record_failure(self) -> None: + if not self.enabled: + return self._failure_count += 1 self._opened_at = time.time() if self._failure_count >= self.failure_threshold: @@ -149,6 +160,8 @@ class RedisCircuitBreaker: self._state = self.OPEN def record_success(self) -> None: + if not self.enabled: + return if self._state == self.HALF_OPEN: verbose_logger.info("Redis circuit breaker CLOSED — Redis recovered") self._failure_count = 0 @@ -243,6 +256,7 @@ class RedisCache(BaseCache): self._circuit_breaker = RedisCircuitBreaker( failure_threshold=REDIS_CIRCUIT_BREAKER_FAILURE_THRESHOLD, recovery_timeout=REDIS_CIRCUIT_BREAKER_RECOVERY_TIMEOUT, + enabled=REDIS_CIRCUIT_BREAKER_ENABLED, ) self._setup_health_pings() @@ -355,6 +369,8 @@ class RedisCache(BaseCache): """ Make sure each key starts with the given namespace """ + if key is None: + return key # type: ignore[return-value] if self.namespace is not None and not key.startswith(self.namespace): key = self.namespace + ":" + key @@ -887,6 +903,43 @@ class RedisCache(BaseCache): ) raise e + @_redis_circuit_breaker_guard + async def async_set_max( + self, + key: str, + value: float, + ttl: int | None = None, + ) -> float | None: + """Atomically set ``key`` to ``value`` only when ``value`` is greater + than the stored value (or the key is unset), refreshing the TTL. + + Monotonic by construction: it never lowers the stored value, so a repair + that writes an authoritative-but-slightly-stale total cannot clobber a + concurrent increment that has already pushed the counter higher. The + GET/compare/SET runs in a single Lua call, so it is also atomic across + racing callers and pods. Returns the resulting value. + """ + _redis_client = self.init_async_client() + _used_ttl = self.get_ttl(ttl=ttl) + key = self.check_and_fix_namespace(key=key) + lua = ( + "local cur = redis.call('GET', KEYS[1]) " + "if cur == false or tonumber(cur) < tonumber(ARGV[1]) then " + "redis.call('SET', KEYS[1], ARGV[1]) " + "if tonumber(ARGV[2]) > 0 then redis.call('EXPIRE', KEYS[1], ARGV[2]) end " + "return ARGV[1] end " + "return cur" + ) + result = cast( + "str | bytes | int | float | None", + await _redis_client.eval(lua, 1, key, str(value), str(int(_used_ttl or 0))), + ) + if result is None: + return None + if isinstance(result, bytes): + result = result.decode() + return float(result) + async def flush_cache_buffer(self): print_verbose( f"flushing to redis....reached size of buffer {len(self.redis_batch_writing_buffer)}" diff --git a/litellm/caching/redis_semantic_cache.py b/litellm/caching/redis_semantic_cache.py index da9e7b1e587..cce4b75795f 100644 --- a/litellm/caching/redis_semantic_cache.py +++ b/litellm/caching/redis_semantic_cache.py @@ -213,6 +213,78 @@ class RedisSemanticCache(BaseCache): ttl = int(ttl) return ttl + @classmethod + def _get_prompt_from_kwargs(cls, **kwargs) -> Optional[str]: + """ + Extract a semantic-cache prompt from chat or Responses API request kwargs. + """ + messages = kwargs.get("messages") + if messages: + return get_str_from_messages(messages) + + if "input" not in kwargs: + return None + + prompt_parts: List[str] = [] + cls._collect_responses_input_text(kwargs.get("input"), prompt_parts) + prompt = "\n".join(prompt_parts).strip() + return prompt or None + + @classmethod + def _collect_responses_input_text(cls, value: Any, prompt_parts: List[str]) -> None: + value = cls._coerce_response_input_value(value) + if value is None: + return + + if isinstance(value, str): + stripped_value = value.strip() + if stripped_value: + prompt_parts.append(stripped_value) + return + + if isinstance(value, (list, tuple)): + for item in value: + cls._collect_responses_input_text(item, prompt_parts) + return + + if isinstance(value, dict): + content = value.get("content") + if content is not None: + cls._collect_responses_input_text(content, prompt_parts) + return + + for text_key in ("text", "output", "input_text", "output_text"): + text_value = value.get(text_key) + if isinstance(text_value, str): + stripped_text = text_value.strip() + if stripped_text: + prompt_parts.append(stripped_text) + return + return + + content = getattr(value, "content", None) + if content is not None: + cls._collect_responses_input_text(content, prompt_parts) + return + + for text_key in ("text", "output", "input_text", "output_text"): + text_value = getattr(value, text_key, None) + if isinstance(text_value, str): + stripped_text = text_value.strip() + if stripped_text: + prompt_parts.append(stripped_text) + return + + @staticmethod + def _coerce_response_input_value(value: Any) -> Any: + model_dump = getattr(value, "model_dump", None) + if callable(model_dump): + return model_dump() + dict_method = getattr(value, "dict", None) + if callable(dict_method): + return dict_method() + return value + def _get_embedding(self, prompt: str) -> List[float]: """ Generate an embedding vector for the given prompt using the configured embedding model. @@ -278,13 +350,11 @@ class RedisSemanticCache(BaseCache): value_str: Optional[str] = None try: - # Extract the prompt from messages - messages = kwargs.get("messages", []) - if not messages: - print_verbose("No messages provided for semantic caching") + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + print_verbose("No prompt provided for semantic caching") return - prompt = get_str_from_messages(messages) value_str = str(value) store_kwargs: Dict[str, Any] = { @@ -315,14 +385,12 @@ class RedisSemanticCache(BaseCache): print_verbose(f"Redis semantic-cache get_cache, kwargs: {kwargs}") try: - # Extract the prompt from messages - messages = kwargs.get("messages", []) - if not messages: - print_verbose("No messages provided for semantic cache lookup") + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + print_verbose("No prompt provided for semantic cache lookup") kwargs.setdefault("metadata", {})["semantic-similarity"] = 0.0 return None - prompt = get_str_from_messages(messages) # Check the cache for semantically similar prompts in this exact # LiteLLM cache-key scope. check_kwargs: Dict[str, Any] = { @@ -428,13 +496,11 @@ class RedisSemanticCache(BaseCache): print_verbose(f"Async Redis semantic-cache set_cache, kwargs: {kwargs}") try: - # Extract the prompt from messages - messages = kwargs.get("messages", []) - if not messages: - print_verbose("No messages provided for semantic caching") + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + print_verbose("No prompt provided for semantic caching") return - prompt = get_str_from_messages(messages) value_str = str(value) # Generate embedding for the value (response) to cache @@ -471,15 +537,12 @@ class RedisSemanticCache(BaseCache): print_verbose(f"Async Redis semantic-cache get_cache, kwargs: {kwargs}") try: - # Extract the prompt from messages - messages = kwargs.get("messages", []) - if not messages: - print_verbose("No messages provided for semantic cache lookup") + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + print_verbose("No prompt provided for semantic cache lookup") kwargs.setdefault("metadata", {})["semantic-similarity"] = 0.0 return None - prompt = get_str_from_messages(messages) - # Generate embedding for the prompt prompt_embedding = await self._get_async_embedding(prompt, **kwargs) diff --git a/litellm/caching/valkey_semantic_cache.py b/litellm/caching/valkey_semantic_cache.py new file mode 100644 index 00000000000..bf368b74d07 --- /dev/null +++ b/litellm/caching/valkey_semantic_cache.py @@ -0,0 +1,353 @@ +""" +Valkey Semantic Cache implementation for LiteLLM + +Backs semantic caching with Valkey (for example AWS ElastiCache for Valkey) +running the valkey-search module. + +RedisVL cannot drive valkey-search: it gates on a RediSearch module version +that valkey-search does not report, and its SemanticCache index uses a TEXT +field that valkey-search does not implement. This backend therefore talks to +valkey-search directly over redis-py, building a vector index from the field +types valkey-search does support (TAG for cache-key isolation and VECTOR for +the prompt embedding) and running KNN queries for retrieval. Prompt extraction, +embedding generation, and cached-response parsing are reused from +RedisSemanticCache since those are backend agnostic. +""" + +import asyncio +import hashlib +import os +import struct +from dataclasses import dataclass +from typing import Any + +from redis import Redis +from redis.asyncio import Redis as AsyncRedis +from redis.commands.search.field import TagField, VectorField +from redis.commands.search.indexDefinition import IndexDefinition, IndexType +from redis.commands.search.query import Query + +from litellm._logging import print_verbose +from litellm._uuid import uuid + +from .redis_semantic_cache import RedisSemanticCache + + +@dataclass(frozen=True, slots=True) +class _ValkeyCacheHit: + response: str + distance: float + + +class ValkeySemanticCache(RedisSemanticCache): + """Valkey-backed semantic cache for LLM responses.""" + + DEFAULT_VALKEY_INDEX_NAME: str = "litellm_semantic_cache_index" + EMBEDDING_FIELD_NAME: str = "embedding" + PROMPT_FIELD_NAME: str = "prompt" + RESPONSE_FIELD_NAME: str = "response" + DISTANCE_FIELD_NAME: str = "vector_distance" + + def __init__( + self, + host: str | None = None, + port: str | None = None, + password: str | None = None, + redis_url: str | None = None, + similarity_threshold: float | None = None, + embedding_model: str = "text-embedding-ada-002", + index_name: str | None = None, + ssl: bool = False, + startup_nodes: list | None = None, + sync_client: Redis | None = None, + async_client: AsyncRedis | None = None, + **kwargs: Any, + ): + if similarity_threshold is None: + raise ValueError("similarity_threshold must be provided, passed None") + + if startup_nodes: + raise ValueError( + "valkey-semantic does not support cluster-mode-enabled (multi-shard) " + "endpoints. The async cluster client cannot route the FT.* search " + "commands reliably. Point it at a cluster-mode-disabled endpoint " + "instead (a primary with replicas is fine; only horizontal sharding " + "is unsupported), or pass a single redis_url. On AWS, vector search " + "needs ElastiCache for Valkey 8.2+ on a node-based cluster." + ) + + self.similarity_threshold = similarity_threshold + self.embedding_model = embedding_model + self.index_name = index_name or self.DEFAULT_VALKEY_INDEX_NAME + self.key_prefix = f"{self.index_name}:" + self._index_dim: int | None = None + + resolved_url = None + if sync_client is None or async_client is None: + resolved_url = redis_url or self._build_valkey_url( + host, port, password, ssl + ) + self.sync_client = ( + sync_client if sync_client is not None else Redis.from_url(resolved_url) # type: ignore[arg-type] + ) + self.async_client = ( + async_client + if async_client is not None + else AsyncRedis.from_url(resolved_url) # type: ignore[arg-type] + ) + + print_verbose(f"Valkey semantic-cache initializing index - {self.index_name}") + + @staticmethod + def _build_valkey_url( + host: str | None, port: str | None, password: str | None, ssl: bool = False + ) -> str: + host = host or os.environ.get("VALKEY_HOST") or os.environ.get("REDIS_HOST") + port = port or os.environ.get("VALKEY_PORT") or os.environ.get("REDIS_PORT") + password = ( + password + or os.environ.get("VALKEY_PASSWORD") + or os.environ.get("REDIS_PASSWORD") + ) + + if not host or not port: + raise ValueError( + "Missing required Valkey configuration. Provide host and port " + "(or VALKEY_HOST/VALKEY_PORT), or pass redis_url." + ) + + credentials = f":{password}@" if password else "" + scheme = "rediss" if ssl else "redis" + return f"{scheme}://{credentials}{host}:{port}" + + @classmethod + def _scope_tag(cls, key: str) -> str: + # valkey-search TAG fields tokenize on punctuation and do not honour + # backslash escaping, so an arbitrary cache key cannot be matched + # verbatim. Hashing to hex yields a token that is always exact-match + # safe and still uniquely isolates a caller's scope. + return hashlib.sha256(str(key).encode("utf-8")).hexdigest() + + @staticmethod + def _embedding_to_bytes(embedding: list[float]) -> bytes: + return struct.pack(f"<{len(embedding)}f", *embedding) + + def _index_schema(self, dim: int) -> tuple[TagField, VectorField]: + return ( + TagField(self.CACHE_KEY_FIELD_NAME), + VectorField( + self.EMBEDDING_FIELD_NAME, + "HNSW", + {"TYPE": "FLOAT32", "DIM": dim, "DISTANCE_METRIC": "COSINE"}, + ), + ) + + def _index_definition(self) -> IndexDefinition: + return IndexDefinition(prefix=[self.key_prefix], index_type=IndexType.HASH) + + @staticmethod + def _is_index_exists_error(exc: Exception) -> bool: + return "already exists" in str(exc).lower() + + @staticmethod + def _extract_index_dim(info: dict) -> int | None: + # FT.INFO nests the vector field's "dimensions" one level inside its + # "index" block, so flatten each field descriptor a single level and + # scan for the dimensions marker. + for field in info.get("attributes") or []: + if not isinstance(field, (list, tuple)): + continue + flat = [ + sub + for item in field + for sub in (item if isinstance(item, (list, tuple)) else [item]) + ] + for i, marker in enumerate(flat): + if marker in (b"dimensions", "dimensions") and i + 1 < len(flat): + return int(flat[i + 1]) + return None + + def _assert_dim_matches(self, info: dict, dim: int) -> None: + existing_dim = self._extract_index_dim(info) + if existing_dim is not None and existing_dim != dim: + raise ValueError( + f"Valkey semantic-cache index '{self.index_name}' already exists with " + f"embedding dimension {existing_dim}, but the configured embedding " + f"model produced dimension {dim}. Use a different " + f"valkey_semantic_cache_index_name or drop the existing index." + ) + + def _ensure_index_sync(self, dim: int) -> None: + if self._index_dim == dim: + return + try: + self.sync_client.ft(self.index_name).create_index( + self._index_schema(dim), definition=self._index_definition() + ) + except Exception as exc: + if not self._is_index_exists_error(exc): + raise + self._assert_dim_matches(self.sync_client.ft(self.index_name).info(), dim) + self._index_dim = dim + + async def _ensure_index_async(self, dim: int) -> None: + if self._index_dim == dim: + return + try: + await self.async_client.ft(self.index_name).create_index( + self._index_schema(dim), definition=self._index_definition() + ) + except Exception as exc: + if not self._is_index_exists_error(exc): + raise + info = await self.async_client.ft(self.index_name).info() + self._assert_dim_matches(info, dim) + self._index_dim = dim + + def _doc_key(self, key: str) -> str: + return f"{self.key_prefix}{self._scope_tag(key)}:{uuid.uuid4()}" + + def _doc_mapping( + self, key: str, prompt: str, value_str: str, embedding: list[float] + ) -> dict: + return { + self.CACHE_KEY_FIELD_NAME: self._scope_tag(key), + self.PROMPT_FIELD_NAME: prompt, + self.RESPONSE_FIELD_NAME: value_str, + self.EMBEDDING_FIELD_NAME: self._embedding_to_bytes(embedding), + } + + def _knn_query(self, key: str) -> Query: + scope = self._scope_tag(key) + query_string = ( + f"(@{self.CACHE_KEY_FIELD_NAME}:{{{scope}}})" + f"=>[KNN 1 @{self.EMBEDDING_FIELD_NAME} $vec AS {self.DISTANCE_FIELD_NAME}]" + ) + return ( + Query(query_string) + .return_fields(self.RESPONSE_FIELD_NAME, self.DISTANCE_FIELD_NAME) + .dialect(2) + ) + + @classmethod + def _first_hit(cls, search_result: Any) -> _ValkeyCacheHit | None: + docs = getattr(search_result, "docs", []) + if not docs: + return None + doc = docs[0] + return _ValkeyCacheHit( + response=str(getattr(doc, cls.RESPONSE_FIELD_NAME)), + distance=float(getattr(doc, cls.DISTANCE_FIELD_NAME)), + ) + + def _resolve_hit(self, hit: _ValkeyCacheHit | None, key: str, **kwargs: Any) -> Any: + if hit is None: + kwargs.setdefault("metadata", {})["semantic-similarity"] = 0.0 + return None + + similarity = 1 - hit.distance + kwargs.setdefault("metadata", {})["semantic-similarity"] = similarity + + if similarity < self.similarity_threshold: + return None + return self._get_cache_logic(cached_response=hit.response) + + def set_cache(self, key: str, value: Any, **kwargs: Any) -> None: + print_verbose(f"Valkey semantic-cache set_cache, kwargs: {kwargs}") + try: + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + print_verbose("No prompt provided for semantic caching") + return + + embedding = self._get_embedding(prompt) + self._ensure_index_sync(len(embedding)) + + doc_key = self._doc_key(key) + self.sync_client.hset( + doc_key, mapping=self._doc_mapping(key, prompt, str(value), embedding) + ) + ttl = self._get_ttl(**kwargs) + if ttl is not None: + self.sync_client.expire(doc_key, ttl) + except Exception as e: + print_verbose(f"Error in Valkey semantic-cache set_cache: {str(e)}") + + def get_cache(self, key: str, **kwargs: Any) -> Any: + print_verbose(f"Valkey semantic-cache get_cache, kwargs: {kwargs}") + try: + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + kwargs.setdefault("metadata", {})["semantic-similarity"] = 0.0 + return None + + embedding = self._get_embedding(prompt) + self._ensure_index_sync(len(embedding)) + + search_result = self.sync_client.ft(self.index_name).search( + self._knn_query(key), + query_params={"vec": self._embedding_to_bytes(embedding)}, + ) + return self._resolve_hit(self._first_hit(search_result), key, **kwargs) + except Exception as e: + print_verbose(f"Error in Valkey semantic-cache get_cache: {str(e)}") + kwargs.setdefault("metadata", {})["semantic-similarity"] = 0.0 + + async def async_set_cache(self, key: str, value: Any, **kwargs: Any) -> None: + print_verbose(f"Async Valkey semantic-cache set_cache, kwargs: {kwargs}") + try: + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + print_verbose("No prompt provided for semantic caching") + return + + embedding = await self._get_async_embedding(prompt, **kwargs) + await self._ensure_index_async(len(embedding)) + + doc_key = self._doc_key(key) + await self.async_client.hset( + doc_key, mapping=self._doc_mapping(key, prompt, str(value), embedding) + ) + ttl = self._get_ttl(**kwargs) + if ttl is not None: + await self.async_client.expire(doc_key, ttl) + except Exception as e: + print_verbose(f"Error in async Valkey semantic-cache set_cache: {str(e)}") + + async def async_get_cache(self, key: str, **kwargs: Any) -> Any: + print_verbose(f"Async Valkey semantic-cache get_cache, kwargs: {kwargs}") + try: + prompt = self._get_prompt_from_kwargs(**kwargs) + if prompt is None: + kwargs.setdefault("metadata", {})["semantic-similarity"] = 0.0 + return None + + embedding = await self._get_async_embedding(prompt, **kwargs) + await self._ensure_index_async(len(embedding)) + + search_result = await self.async_client.ft(self.index_name).search( + self._knn_query(key), + query_params={"vec": self._embedding_to_bytes(embedding)}, + ) + return self._resolve_hit(self._first_hit(search_result), key, **kwargs) + except Exception as e: + print_verbose(f"Error in async Valkey semantic-cache get_cache: {str(e)}") + kwargs.setdefault("metadata", {})["semantic-similarity"] = 0.0 + + async def async_set_cache_pipeline( + self, cache_list: list[tuple[str, Any]], **kwargs: Any + ) -> None: + try: + await asyncio.gather( + *[ + self.async_set_cache(key, value, **kwargs) + for key, value in cache_list + ] + ) + except Exception as e: + print_verbose( + f"Error in Valkey semantic-cache async_set_cache_pipeline: {str(e)}" + ) + + async def _index_info(self) -> dict: + return await self.async_client.ft(self.index_name).info() diff --git a/litellm/completion_extras/litellm_responses_transformation/handler.py b/litellm/completion_extras/litellm_responses_transformation/handler.py index 87c26b776e8..d27cfefda73 100644 --- a/litellm/completion_extras/litellm_responses_transformation/handler.py +++ b/litellm/completion_extras/litellm_responses_transformation/handler.py @@ -171,6 +171,8 @@ class ResponsesToCompletionBridgeHandler: model_response = validated_kwargs["model_response"] logging_obj = validated_kwargs["logging_obj"] custom_llm_provider = validated_kwargs["custom_llm_provider"] + if kwargs.get("stream") is True and "stream" not in optional_params: + optional_params = {**optional_params, "stream": True} request_data = self.transformation_handler.transform_request( model=model, @@ -263,6 +265,8 @@ class ResponsesToCompletionBridgeHandler: model_response = validated_kwargs["model_response"] logging_obj = validated_kwargs["logging_obj"] custom_llm_provider = validated_kwargs["custom_llm_provider"] + if kwargs.get("stream") is True and "stream" not in optional_params: + optional_params = {**optional_params, "stream": True} try: request_data = self.transformation_handler.transform_request( diff --git a/litellm/completion_extras/litellm_responses_transformation/transformation.py b/litellm/completion_extras/litellm_responses_transformation/transformation.py index 51abbbf729b..3fa6b983e5f 100644 --- a/litellm/completion_extras/litellm_responses_transformation/transformation.py +++ b/litellm/completion_extras/litellm_responses_transformation/transformation.py @@ -402,6 +402,20 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): instructions, ) = self.convert_chat_completion_messages_to_responses_api(messages) + # OpenAI's Responses API rejects an empty input. For a system-only + # request, carry the system message as a system-role input item instead + # of instructions, mirroring how non-string system content is already + # handled in convert_chat_completion_messages_to_responses_api. + if not input_items and instructions is not None: + input_items = [ + { + "type": "message", + "role": "system", + "content": [{"type": "input_text", "text": instructions}], + } + ] + instructions = None + optional_params = self._extract_extra_body_params(optional_params) # Build responses API request using the reverse transformation logic @@ -679,7 +693,7 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): original_response = model_call_details.get("original_response") return cls._recover_output_items_from_raw_sse(original_response) - def transform_response( # noqa: PLR0915 + def transform_response( self, model: str, raw_response: "BaseModel", @@ -1197,7 +1211,7 @@ class OpenAiResponsesToChatCompletionStreamIterator(BaseModelResponseIterator): return self.chunk_parser(json.loads(str_line)) @staticmethod - def translate_responses_chunk_to_openai_stream( # noqa: PLR0915 + def translate_responses_chunk_to_openai_stream( parsed_chunk: Union[dict, BaseModel], ) -> "ModelResponseStream": """ @@ -1279,9 +1293,15 @@ class OpenAiResponsesToChatCompletionStreamIterator(BaseModelResponseIterator): provider_specific_fields ) + from litellm.responses.litellm_completion_transformation.transformation import ( + LiteLLMCompletionResponsesConfig, + ) + tool_call_index = parsed_chunk.get("output_index", 0) tool_call_chunk = ChatCompletionToolCallChunk( - id=output_item.get("call_id"), + id=LiteLLMCompletionResponsesConfig._tool_call_id_from_responses_item( + output_item.get("id"), output_item.get("call_id") + ), index=tool_call_index, type="function", function=function_chunk, diff --git a/litellm/constants.py b/litellm/constants.py index 36e578bd323..c0e265c0e4a 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -190,6 +190,10 @@ DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET_GEMINI_2_5_FLASH_LITE = int( # Override with LITELLM_MAX_CALLBACKS env var for large deployments (e.g., many teams with guardrails) MAX_CALLBACKS = get_env_int("LITELLM_MAX_CALLBACKS", 100) +# Metadata key recording which pre_call guardrails the proxy loop already ran, +# so the deployment-level hook does not re-run them for the same request +PRE_CALL_EXECUTED_GUARDRAILS_KEY = "_pre_call_executed_guardrails" + # Generic fallback for unknown models DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET = int( os.getenv("DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET", 128) @@ -398,6 +402,9 @@ REDIS_CIRCUIT_BREAKER_FAILURE_THRESHOLD = int( REDIS_CIRCUIT_BREAKER_RECOVERY_TIMEOUT = int( os.getenv("REDIS_CIRCUIT_BREAKER_RECOVERY_TIMEOUT", 60) ) +REDIS_CIRCUIT_BREAKER_ENABLED = ( + os.getenv("REDIS_CIRCUIT_BREAKER_ENABLED", "true").lower() == "true" +) # Default Redis major version to assume when version cannot be determined # Using 7 as it's the modern version that supports LPOP with count parameter DEFAULT_REDIS_MAJOR_VERSION = int(os.getenv("DEFAULT_REDIS_MAJOR_VERSION", 7)) @@ -418,6 +425,7 @@ REPLICATE_POLLING_DELAY_SECONDS = float( DEFAULT_ANTHROPIC_CHAT_MAX_TOKENS = int( os.getenv("DEFAULT_ANTHROPIC_CHAT_MAX_TOKENS", 4096) ) +DEFAULT_OCI_CHAT_MAX_TOKENS = 4096 TOGETHER_AI_4_B = int(os.getenv("TOGETHER_AI_4_B", 4)) TOGETHER_AI_8_B = int(os.getenv("TOGETHER_AI_8_B", 8)) TOGETHER_AI_21_B = int(os.getenv("TOGETHER_AI_21_B", 21)) @@ -502,6 +510,8 @@ DD_TRACER_STREAMING_CHUNK_YIELD_RESOURCE = os.getenv( "DD_TRACER_STREAMING_CHUNK_YIELD_RESOURCE", "streaming.chunk.yield" ) +LITELLM_HTTP_STATUS_CLIENT_DISCONNECTED = 499 + EMAIL_BUDGET_ALERT_TTL = int( os.getenv("EMAIL_BUDGET_ALERT_TTL", 24 * 60 * 60) ) # 24 hours in seconds @@ -614,6 +624,7 @@ LITELLM_CHAT_PROVIDERS = [ "nscale", "nebius", "dashscope", + "modelscope", "moonshot", "publicai", "v0", @@ -772,6 +783,7 @@ openai_compatible_endpoints: List = [ "inference.api.nscale.com/v1", "api.studio.nebius.ai/v1", "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", + "https://api-inference.modelscope.cn/v1", "https://api.moonshot.ai/v1", "https://api.publicai.co/v1", "https://api.synthetic.new/openai/v1", @@ -789,6 +801,8 @@ openai_compatible_endpoints: List = [ "https://ai-gateway.vercel.sh/v1", "https://api.inference.wandb.ai/v1", "https://api.clarifai.com/v2/ext/openai/v1", + "https://api.libertai.io/v1", + "https://pinstripes.io/v1", ] @@ -831,10 +845,13 @@ openai_compatible_providers: List = [ "nano-gpt", # Nano-GPT - JSON-configured provider "poe", # Poe - JSON-configured provider "chutes", # Chutes - JSON-configured provider + "parasail", # Parasail - JSON-configured provider + "libertai", # LibertAI - JSON-configured provider "featherless_ai", "nscale", "nebius", "dashscope", + "modelscope", "moonshot", "v0", "helicone", @@ -849,6 +866,7 @@ openai_compatible_providers: List = [ "clarifai", "docker_model_runner", "ragflow", + "pinstripes", # Pinstripes - JSON-configured provider ] openai_text_completion_compatible_providers: List = ( [ # providers that support `/v1/completions` @@ -860,6 +878,7 @@ openai_text_completion_compatible_providers: List = ( "featherless_ai", "nebius", "dashscope", + "modelscope", "moonshot", "publicai", "synthetic", @@ -1120,6 +1139,48 @@ WANDB_MODELS: set = set( ] ) +modelscope_models: set = set( + [ + # Qwen series models + "Qwen/Qwen3-0.6B", + "Qwen/Qwen3-1.7B", + "Qwen/Qwen3-4B", + "Qwen/Qwen3-8B", + "Qwen/Qwen3-14B", + "Qwen/Qwen3-30B-A3B", + "Qwen/Qwen3-32B", + "Qwen/Qwen3-235B-A22B", + "Qwen/Qwen3-235B-A22B-Instruct-2507", + "Qwen/Qwen3-235B-A22B-Thinking-2507", + "Qwen/Qwen3-30B-A3B-Thinking-2507", + "Qwen/Qwen3-Coder-30B-A3B-Instruct", + "Qwen/Qwen3-Coder-480B-A35B-Instruct", + "Qwen/Qwen3-Next-80B-A3B-Instruct", + "Qwen/Qwen3-Next-80B-A3B-Thinking", + "Qwen/Qwen3-VL-235B-A22B-Instruct", + "Qwen/Qwen3-VL-8B-Instruct", + "Qwen/Qwen3-VL-8B-Thinking", + "Qwen/Qwen3.5-122B-A10B", + "Qwen/Qwen3.5-27B", + "Qwen/Qwen3.5-35B-A3B", + "Qwen/Qwen3.5-397B-A17B", + "Qwen/QwQ-32B", + "Qwen/QwQ-32B-Preview", + "Qwen/QVQ-72B-Preview", + "Qwen/Qwen-Image-Edit", + # DeepSeek series models + "deepseek-ai/DeepSeek-R1-0528", + "deepseek-ai/DeepSeek-R1-Distill-Llama-70B", + "deepseek-ai/DeepSeek-R1-Distill-Llama-8B", + "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B", + "deepseek-ai/DeepSeek-R1-Distill-Qwen-14B", + "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B", + "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B", + "deepseek-ai/DeepSeek-V3.2", + "deepseek-ai/DeepSeek-V4-Flash", + ] +) + BEDROCK_INVOKE_PROVIDERS_LITERAL = Literal[ "cohere", "anthropic", @@ -1157,6 +1218,7 @@ BEDROCK_CONVERSE_MODELS = [ "openai.gpt-oss-120b-1:0", "anthropic.claude-haiku-4-5-20251001-v1:0", "anthropic.claude-sonnet-4-5-20250929-v1:0", + "anthropic.claude-fable-5", "anthropic.claude-opus-4-8", "anthropic.claude-opus-4-7", "anthropic.claude-opus-4-6-v1:0", @@ -1478,6 +1540,7 @@ DB_SPEND_UPDATE_JOB_NAME = "db_spend_update_job" DB_DAILY_TAG_SPEND_UPDATE_JOB_NAME = "db_daily_tag_spend_update_job" PROMETHEUS_EMIT_BUDGET_METRICS_JOB_NAME = "prometheus_emit_budget_metrics" CLOUDZERO_EXPORT_USAGE_DATA_JOB_NAME = "cloudzero_export_usage_data" +MAVVRIK_FOCUS_EXPORT_JOB_NAME = "mavvrik_focus_export_usage_data" CLOUDZERO_MAX_FETCHED_DATA_RECORDS = int( os.getenv("CLOUDZERO_MAX_FETCHED_DATA_RECORDS", 50000) ) @@ -1492,6 +1555,10 @@ SPEND_LOG_CLEANUP_MAX_CONSECUTIVE_BATCH_FAILURES = int( SPEND_LOG_CLEANUP_BATCH_FAILURE_BACKOFF_SECONDS = float( os.getenv("SPEND_LOG_CLEANUP_BATCH_FAILURE_BACKOFF_SECONDS", 0.5) ) +SPEND_LOG_PARTITION_INTERVAL = os.getenv("SPEND_LOG_PARTITION_INTERVAL", "day") +SPEND_LOG_PARTITION_PRECREATE_AHEAD = int( + os.getenv("SPEND_LOG_PARTITION_PRECREATE_AHEAD", 7) +) SPEND_LOG_QUEUE_SIZE_THRESHOLD = int(os.getenv("SPEND_LOG_QUEUE_SIZE_THRESHOLD", 100)) SPEND_LOG_QUEUE_POLL_INTERVAL = float(os.getenv("SPEND_LOG_QUEUE_POLL_INTERVAL", 2.0)) SPEND_COUNTER_RESEED_LOCKS_MAX_SIZE = int( diff --git a/litellm/cost_calculator.py b/litellm/cost_calculator.py index 88029615ba8..27a146df7bf 100644 --- a/litellm/cost_calculator.py +++ b/litellm/cost_calculator.py @@ -94,6 +94,7 @@ from litellm.types.utils import ( LlmProviders, LlmProvidersSet, ModelInfo, + ServiceTier, StandardBuiltInToolsParams, TranscriptionUsageDurationObject, TranscriptionUsageTokensObject, @@ -288,7 +289,7 @@ def _transcription_usage_has_token_details( return (prompt_tokens_val > 0) or (completion_tokens_val > 0) -def cost_per_token( # noqa: PLR0915 +def cost_per_token( model: str = "", prompt_tokens: int = 0, completion_tokens: int = 0, @@ -614,7 +615,9 @@ def cost_per_token( # noqa: PLR0915 service_tier=service_tier, ) elif custom_llm_provider == "anthropic": - return anthropic_cost_per_token(model=model, usage=usage_block) + return anthropic_cost_per_token( + model=model, usage=usage_block, service_tier=service_tier + ) elif custom_llm_provider == "bedrock": return bedrock_cost_per_token( model=model, usage=usage_block, service_tier=service_tier @@ -885,6 +888,23 @@ def _map_traffic_type_to_service_tier(traffic_type: Optional[str]) -> Optional[s return service_tier +def _normalize_service_tier(service_tier: object) -> str | None: + """ + Reduce a service_tier value to a concrete billable tier string or None. + + "auto" is a routing preference and any non-string value is not a billable + tier, so both defer to standard pricing (or to the tier the provider reports + on the response usage) instead of crashing the downstream cost-key lookup, + which calls service_tier.lower() + """ + if ( + not isinstance(service_tier, str) + or service_tier.lower() == ServiceTier.AUTO.value + ): + return None + return service_tier + + def _get_usage_object( completion_response: Any, ) -> Optional[Usage]: @@ -1136,7 +1156,7 @@ def _store_cost_breakdown_in_logging_obj( pass -def completion_cost( # noqa: PLR0915 +def completion_cost( completion_response=None, model: Optional[str] = None, prompt="", @@ -1224,6 +1244,8 @@ def completion_cost( # noqa: PLR0915 if service_tier is None and optional_params is not None: service_tier = optional_params.get("service_tier") + service_tier = _normalize_service_tier(service_tier) + # Extract service_tier from completion_response if not provided if service_tier is None and completion_response is not None: if isinstance(completion_response, BaseModel): @@ -1231,6 +1253,8 @@ def completion_cost( # noqa: PLR0915 elif isinstance(completion_response, dict): service_tier = completion_response.get("service_tier") + service_tier = _normalize_service_tier(service_tier) + # Extract service_tier from usage object if not provided if service_tier is None and cost_per_token_usage_object is not None: if isinstance(cost_per_token_usage_object, BaseModel): @@ -1240,6 +1264,8 @@ def completion_cost( # noqa: PLR0915 elif isinstance(cost_per_token_usage_object, dict): service_tier = cost_per_token_usage_object.get("service_tier") + service_tier = _normalize_service_tier(service_tier) + selected_model = _select_model_name_for_cost_calc( model=model, completion_response=completion_response, @@ -2488,6 +2514,11 @@ class RealtimeAPITokenUsageProcessor(BaseTokenUsageProcessor): ) +_TRANSCRIPTION_COMPLETED_EVENT_TYPE = ( + "conversation.item.input_audio_transcription.completed" +) + + def handle_realtime_stream_cost_calculation( results: OpenAIRealtimeStreamList, combined_usage_object: Usage, @@ -2533,4 +2564,99 @@ def handle_realtime_stream_cost_calculation( break # exit if we find a valid model total_cost = input_cost_per_token + output_cost_per_token + if any(r.get("type") == _TRANSCRIPTION_COMPLETED_EVENT_TYPE for r in results): + total_cost += handle_realtime_transcription_cost_calculation( + results=results, + custom_llm_provider=custom_llm_provider, + litellm_model_name=litellm_model_name, + ) + return total_cost + + +def handle_realtime_transcription_cost_calculation( + results: OpenAIRealtimeStreamList, + custom_llm_provider: str, + litellm_model_name: str, +) -> float: + """ + Cost for realtime transcription sessions (e.g. gpt-realtime-whisper). + + Transcription sessions emit no `response.done` events; instead each + `conversation.item.input_audio_transcription.completed` event carries a + `usage` object billed by the ASR model. The usage is one of: + - {"type": "duration", "seconds": } → priced via input_cost_per_second + - {"type": "tokens", "input_tokens": ...} → priced via input/audio token cost + """ + completed_events = [ + cast(dict, result) + for result in results + if result.get("type") == _TRANSCRIPTION_COMPLETED_EVENT_TYPE + ] + if not completed_events: + return 0.0 + + model_name = ( + _get_transcription_model_name_from_results(results) or litellm_model_name + ) + try: + model_info = litellm.get_model_info( + model=model_name, custom_llm_provider=custom_llm_provider + ) + except Exception: + model_info = None + + total_cost = 0.0 + for event in completed_events: + usage = event.get("usage") or {} + total_cost += _transcription_usage_cost(usage, model_info) + return total_cost + + +def _get_transcription_model_name_from_results( + results: OpenAIRealtimeStreamList, +) -> Optional[str]: + """Resolve the ASR model from a transcription_session.* / session.* event.""" + for result in results: + if result.get("type") in ( + "transcription_session.created", + "transcription_session.updated", + "session.created", + "session.updated", + ): + session = cast(dict, result).get("session", {}) or {} + transcription = ( + (session.get("audio", {}) or {}).get("input", {}) or {} + ).get("transcription", {}) or session.get("input_audio_transcription", {}) + model = (transcription or {}).get("model") or session.get("model") + if model: + return model + return None + + +def _transcription_usage_cost(usage: dict, model_info: Optional[ModelInfo]) -> float: + if model_info is None: + return 0.0 + usage_type = usage.get("type") + if usage_type == "duration": + seconds = usage.get("seconds") or 0.0 + per_second = model_info.get("input_cost_per_second") or 0.0 + return float(seconds) * float(per_second) + if usage_type == "tokens": + input_token_details = usage.get("input_token_details") or {} + audio_tokens = input_token_details.get("audio_tokens") or 0 + text_tokens = input_token_details.get("text_tokens") or 0 + output_tokens = usage.get("output_tokens") or 0 + audio_cost = float(audio_tokens) * float( + model_info.get("input_cost_per_audio_token") + or model_info.get("input_cost_per_token") + or 0.0 + ) + text_cost = float(text_tokens) * float( + model_info.get("input_cost_per_token") or 0.0 + ) + output_cost = float(output_tokens) * float( + model_info.get("output_cost_per_token") or 0.0 + ) + return audio_cost + text_cost + output_cost + return 0.0 diff --git a/litellm/exceptions.py b/litellm/exceptions.py index 15f6030d4a3..1cbef6b0b49 100644 --- a/litellm/exceptions.py +++ b/litellm/exceptions.py @@ -9,13 +9,109 @@ ## LiteLLM versions of the OpenAI Exception Types -from typing import Any, Dict, Optional +import enum +from typing import Any, Dict, Optional, Union import httpx import openai from litellm.types.utils import LiteLLMCommonStrings + +class RateLimitErrorCategory(str, enum.Enum): + """ + Category of a rate limit error, allowing callers to distinguish where the rate + limit originated. Exposed on every :class:`RateLimitError` instance via the + ``category`` attribute. + + Use these values to switch on the rate limit source, e.g.:: + + try: + ... + except litellm.RateLimitError as e: + if e.category == RateLimitErrorCategory.LITELLM_RATE_LIMIT: + ... # litellm's own limiter (key/team/user/model RPM/TPM/budget) + elif e.category == RateLimitErrorCategory.VENDOR_RATE_LIMIT: + ... # the upstream LLM provider returned 429 + """ + + VENDOR_RATE_LIMIT = "vendor_rate_limit" + """The upstream LLM provider returned a rate-limit response (e.g. OpenAI 429).""" + + VENDOR_BATCH_RATE_LIMIT = "vendor_batch_rate_limit" + """The upstream LLM provider returned a rate-limit response on a batch endpoint.""" + + LITELLM_RATE_LIMIT = "litellm_rate_limit" + """LiteLLM's own rate limiter (key/team/user/model RPM/TPM, budget, parallel-requests, etc.) blocked the request.""" + + LITELLM_BATCH_RATE_LIMIT = "litellm_batch_rate_limit" + """LiteLLM's own batch rate limiter (token/request budget across a batch input file) blocked the request.""" + + +class RateLimitType(str, enum.Enum): + """ + The dimension that was exceeded when a rate-limit error fired. + + This is orthogonal to :class:`RateLimitErrorCategory` — *category* tells + callers **who** rate-limited the request (the upstream vendor vs. one of + litellm's own limiters), while *type* tells them **which limit dimension** + was exceeded (an RPM ceiling, a TPM ceiling, a max-parallel-requests + ceiling, a budget cap, or a max-iterations cap). + + Surfaced both on every :class:`RateLimitError` instance via the + ``rate_limit_type`` attribute and on the structured + ``StandardLoggingPayload.error_information.error_rate_limit_type`` field + so custom callbacks / metrics consumers can split rate-limit failures by + cause without parsing free-text error messages. + """ + + REQUESTS = "requests" + """Requests-per-minute (RPM) or requests-per-window ceiling exceeded.""" + + TOKENS = "tokens" + """Tokens-per-minute (TPM) or tokens-per-window ceiling exceeded.""" + + CONCURRENT_REQUESTS = "concurrent_requests" + """``max_parallel_requests`` — too many in-flight requests at once.""" + + BUDGET = "budget" + """Spend budget cap reached (key, team, user, or per-session).""" + + MAX_ITERATIONS = "max_iterations" + """Per-session max-iterations cap reached (agent-style flows).""" + + +_RATE_LIMIT_CATEGORY_VALUES = frozenset(c.value for c in RateLimitErrorCategory) +_RATE_LIMIT_TYPE_VALUES = frozenset(t.value for t in RateLimitType) + + +def validate_rate_limit_category(value: Any) -> Optional[str]: + """Return ``value`` only if it matches a known :class:`RateLimitErrorCategory`. + + Used at duck-typed read sites (StandardLoggingPayload extraction, Prometheus + labels) to reject `.category` strings set by unrelated third-party exceptions + — otherwise those would leak into custom-callback payloads and Prometheus + label cardinality. + """ + if isinstance(value, RateLimitErrorCategory): + return value.value + if isinstance(value, str) and value in _RATE_LIMIT_CATEGORY_VALUES: + return value + return None + + +def validate_rate_limit_type(value: Any) -> Optional[str]: + """Return ``value`` only if it matches a known :class:`RateLimitType`. + + See :func:`validate_rate_limit_category` for the rationale. + """ + if isinstance(value, RateLimitType): + return value.value + if isinstance(value, str) and value in _RATE_LIMIT_TYPE_VALUES: + return value + return None + + _MINIMAL_ERROR_RESPONSE: Optional[httpx.Response] = None @@ -321,6 +417,18 @@ class PermissionDeniedError(openai.PermissionDeniedError): # type: ignore class RateLimitError(openai.RateLimitError): # type: ignore + """ + Unified rate-limit error. + + Every rate-limit condition surfaced by litellm — whether it originated from + an upstream LLM provider, a vendor batch endpoint, or one of litellm's own + proxy-side limiters (parallel-requests, dynamic-rate, batch-rate, budget, + max-iterations, etc.) — is raised as an instance of this class. + + The :attr:`category` attribute lets callers distinguish the source. See + :class:`RateLimitErrorCategory` for the available values. + """ + def __init__( self, message, @@ -330,6 +438,12 @@ class RateLimitError(openai.RateLimitError): # type: ignore litellm_debug_info: Optional[str] = None, max_retries: Optional[int] = None, num_retries: Optional[int] = None, + category: Union[str, RateLimitErrorCategory] = ( + RateLimitErrorCategory.VENDOR_RATE_LIMIT + ), + rate_limit_type: Optional[Union[str, RateLimitType]] = None, + headers: Optional[Dict[str, str]] = None, + detail: Any = None, ): self.status_code = 429 self.message = "litellm.RateLimitError: {}".format(message) @@ -338,9 +452,39 @@ class RateLimitError(openai.RateLimitError): # type: ignore self.litellm_debug_info = litellm_debug_info self.max_retries = max_retries self.num_retries = num_retries + self.category = ( + category.value if isinstance(category, RateLimitErrorCategory) else category + ) + # Which dimension was exceeded — request count, token count, parallel + # requests, budget, max iterations. None when the source didn't + # classify the failure (e.g. legacy vendor 429 with no header hints). + self.rate_limit_type: Optional[str] = ( + rate_limit_type.value + if isinstance(rate_limit_type, RateLimitType) + else rate_limit_type + ) + # Headers explicitly attached to the error (e.g. retry-after, + # rate_limit_type, reset_at). Preserved across the proxy boundary so + # clients can react appropriately. + # + # IMPORTANT: we deliberately do NOT auto-populate self.headers from + # response.headers when only `response` is provided. A vendor 429 can + # set arbitrary response headers (Set-Cookie, CORS overrides, …); if + # those leaked into e.headers and a downstream proxy serializer + # forwarded them to the client, a malicious upstream could inject + # browser-interpreted headers for the proxy origin. Vendor response + # headers stay reachable on `e.response.headers` for callers that + # explicitly want them; only the proxy-supplied `headers=` kwarg + # makes it onto `self.headers`. _response_headers = ( getattr(response, "headers", None) if response is not None else None ) + self.headers: Optional[Dict[str, str]] = ( + {k: str(v) for k, v in headers.items()} if headers else None + ) + # Mirrors FastAPI HTTPException.detail so the same instance can be + # serialized through both the ProxyException and HTTPException paths. + self.detail = detail if detail is not None else self.message self.response = httpx.Response( status_code=429, headers=_response_headers, @@ -843,11 +987,24 @@ LITELLM_EXCEPTION_TYPES = [ class BudgetExceededError(Exception): def __init__( - self, current_cost: float, max_budget: float, message: Optional[str] = None + self, + current_cost: float, + max_budget: float, + message: Optional[str] = None, + llm_provider: Optional[str] = None, ): self.current_cost = current_cost self.max_budget = max_budget self.status_code = 429 + self.llm_provider = llm_provider or "" + # Surface unified rate-limit fields without joining the RateLimitError + # hierarchy so existing `except BudgetExceededError:` handlers keep + # working; custom callbacks reading StandardLoggingPayload pick these + # up via the same `category` / `rate_limit_type` attributes the rest + # of the unified rate-limit error path uses. Stored as plain strings + # to match the normalization RateLimitError.__init__ performs. + self.category: str = RateLimitErrorCategory.LITELLM_RATE_LIMIT.value + self.rate_limit_type: str = RateLimitType.BUDGET.value message = ( message or f"Budget has been exceeded! Current cost: {current_cost}, Max budget: {max_budget}" diff --git a/litellm/google_genai/streaming_iterator.py b/litellm/google_genai/streaming_iterator.py index 3e97b480779..a8d0e5976f0 100644 --- a/litellm/google_genai/streaming_iterator.py +++ b/litellm/google_genai/streaming_iterator.py @@ -18,6 +18,42 @@ else: GLOBAL_PASS_THROUGH_SUCCESS_HANDLER_OBJ = PassThroughEndpointLogging() +def _encode_google_genai_sse_event(event_lines: List[str]) -> bytes: + return ("\n".join(event_lines) + "\n\n").encode("utf-8") + + +def _next_google_genai_sse_chunk(line_iter) -> bytes: + event_lines: List[str] = [] + while True: + try: + line = next(line_iter) + except StopIteration: + if event_lines: + return _encode_google_genai_sse_event(event_lines) + raise + if line == "": + if event_lines: + return _encode_google_genai_sse_event(event_lines) + continue + event_lines.append(line) + + +async def _anext_google_genai_sse_chunk(line_iter) -> bytes: + event_lines: List[str] = [] + while True: + try: + line = await line_iter.__anext__() + except StopAsyncIteration: + if event_lines: + return _encode_google_genai_sse_event(event_lines) + raise + if line == "": + if event_lines: + return _encode_google_genai_sse_event(event_lines) + continue + event_lines.append(line) + + class BaseGoogleGenAIGenerateContentStreamingIterator: """ Base class for Google GenAI Generate Content streaming iterators that provides common logic @@ -91,18 +127,17 @@ class GoogleGenAIGenerateContentStreamingIterator( self.generate_content_provider_config = generate_content_provider_config self.litellm_metadata = litellm_metadata self.custom_llm_provider = custom_llm_provider - # Store the iterator once to avoid multiple stream consumption - self.stream_iterator = response.iter_bytes() + # Gemini streamGenerateContent uses SSE line framing; iter_lines keeps + # large inlineData payloads (e.g. image/jpeg) intact within one event. + self.stream_iterator = response.iter_lines() def __iter__(self): return self def __next__(self): try: - # Get the next chunk from the stored iterator - chunk = next(self.stream_iterator) + chunk = _next_google_genai_sse_chunk(self.stream_iterator) self.collected_chunks.append(chunk) - # Just yield raw bytes return chunk except StopIteration: raise StopIteration @@ -147,18 +182,17 @@ class AsyncGoogleGenAIGenerateContentStreamingIterator( self.generate_content_provider_config = generate_content_provider_config self.litellm_metadata = litellm_metadata self.custom_llm_provider = custom_llm_provider - # Store the async iterator once to avoid multiple stream consumption - self.stream_iterator = response.aiter_bytes() + # Gemini streamGenerateContent uses SSE line framing; aiter_lines keeps + # large inlineData payloads (e.g. image/jpeg) intact within one event. + self.stream_iterator = response.aiter_lines() def __aiter__(self): return self async def __anext__(self): try: - # Get the next chunk from the stored async iterator - chunk = await self.stream_iterator.__anext__() + chunk = await _anext_google_genai_sse_chunk(self.stream_iterator) self.collected_chunks.append(chunk) - # Just yield raw bytes return chunk except StopAsyncIteration: await self._handle_async_streaming_logging() diff --git a/litellm/images/main.py b/litellm/images/main.py index d95b7287d20..8b108ded4c9 100644 --- a/litellm/images/main.py +++ b/litellm/images/main.py @@ -195,7 +195,7 @@ def image_generation( @client -def image_generation( # noqa: PLR0915 +def image_generation( prompt: str, model: Optional[str] = None, n: Optional[int] = None, @@ -738,7 +738,7 @@ def image_variation( @client -def image_edit( # noqa: PLR0915 +def image_edit( image: Optional[Union[FileTypes, List[FileTypes]]] = None, prompt: Optional[str] = None, model: Optional[str] = None, diff --git a/litellm/integrations/SlackAlerting/budget_alert_types.py b/litellm/integrations/SlackAlerting/budget_alert_types.py index ea80b258540..2a19ec0b7fa 100644 --- a/litellm/integrations/SlackAlerting/budget_alert_types.py +++ b/litellm/integrations/SlackAlerting/budget_alert_types.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from typing import Literal -from litellm.proxy._types import CallInfo +from litellm.proxy._types import CallInfo, Litellm_EntityType class BaseBudgetAlertType(ABC): @@ -31,6 +31,8 @@ class SoftBudgetAlert(BaseBudgetAlertType): return "Soft Budget Crossed: " def get_id(self, user_info: CallInfo) -> str: + if user_info.event_group == Litellm_EntityType.TEAM: + return user_info.team_id or "default_id" return user_info.token or "default_id" diff --git a/litellm/integrations/SlackAlerting/hanging_request_check.py b/litellm/integrations/SlackAlerting/hanging_request_check.py index d2f70c9caf1..98f1eb2d551 100644 --- a/litellm/integrations/SlackAlerting/hanging_request_check.py +++ b/litellm/integrations/SlackAlerting/hanging_request_check.py @@ -8,6 +8,7 @@ Notes: """ import asyncio +import time from typing import TYPE_CHECKING, Any, Optional import litellm @@ -36,11 +37,15 @@ class AlertingHangingRequestCheck: slack_alerting_object: SlackAlerting, ): self.slack_alerting_object = slack_alerting_object + # checks run every alerting_threshold / 2 seconds, so entries must + # stay cached for at least 1.5x the threshold to guarantee a check + # happens after they cross it + self.hanging_request_cache_ttl = int( + self.slack_alerting_object.alerting_threshold * 1.5 + + HANGING_ALERT_BUFFER_TIME_SECONDS + ) self.hanging_request_cache = InMemoryCache( - default_ttl=int( - self.slack_alerting_object.alerting_threshold - + HANGING_ALERT_BUFFER_TIME_SECONDS - ), + default_ttl=self.hanging_request_cache_ttl, ) async def add_request_to_hanging_request_check( @@ -76,10 +81,7 @@ class AlertingHangingRequestCheck: await self.hanging_request_cache.async_set_cache( key=hanging_request_data.request_id, value=hanging_request_data, - ttl=int( - self.slack_alerting_object.alerting_threshold - + HANGING_ALERT_BUFFER_TIME_SECONDS - ), + ttl=self.hanging_request_cache_ttl, ) return @@ -111,6 +113,9 @@ class AlertingHangingRequestCheck: if hanging_request_data is None: continue + if hanging_request_data.alerted: + continue + request_status = ( await proxy_logging_obj.internal_usage_cache.async_get_cache( key="request_status:{}".format(hanging_request_data.request_id), @@ -127,12 +132,21 @@ class AlertingHangingRequestCheck: ) continue + request_age_seconds = time.time() - hanging_request_data.created_at + if request_age_seconds < self.slack_alerting_object.alerting_threshold: + # in-flight but below the alerting threshold; keep it cached + # so a later check can alert if it never completes + continue + ################ # Send the Alert on Slack ################ await self.send_hanging_request_alert( hanging_request_data=hanging_request_data ) + # flag so the entry is skipped on later ticks; one alert per hang, + # with the existing TTL still handling cleanup + hanging_request_data.alerted = True return diff --git a/litellm/integrations/SlackAlerting/slack_alerting.py b/litellm/integrations/SlackAlerting/slack_alerting.py index 0ec17bbea5d..2108ebae312 100644 --- a/litellm/integrations/SlackAlerting/slack_alerting.py +++ b/litellm/integrations/SlackAlerting/slack_alerting.py @@ -37,6 +37,8 @@ from litellm.proxy._types import ( VirtualKeyEvent, WebhookEvent, ) +from litellm.repositories.team_repository import TeamRepository +from litellm.repositories.user_repository import UserRepository from litellm.types.integrations.slack_alerting import * from ..email_templates.templates import * @@ -349,7 +351,7 @@ class SlackAlerting(CustomBatchLogger): except Exception: return 0 - async def send_daily_reports(self, router) -> bool: # noqa: PLR0915 + async def send_daily_reports(self, router) -> bool: """ Send a daily report on: - Top 5 deployments with most failed requests @@ -1177,7 +1179,7 @@ Model Info: if response.status_code == 200: return True else: - print("Error sending webhook alert. Error=", response.text) # noqa + print("Error sending webhook alert. Error=", response.text) # noqa: T201 return False @@ -1231,7 +1233,7 @@ Model Info: and recipient_user_id is not None and prisma_client is not None ): - user_row = await prisma_client.db.litellm_usertable.find_unique( + user_row = await UserRepository(prisma_client).table.find_unique( where={"user_id": recipient_user_id} ) @@ -1263,7 +1265,7 @@ Model Info: team_id = webhook_event.team_id team_name = "Default Team" if team_id is not None and prisma_client is not None: - team_row = await prisma_client.db.litellm_teamtable.find_unique( + team_row = await TeamRepository(prisma_client).table.find_unique( where={"team_id": team_id} ) if team_row is not None: @@ -1371,7 +1373,7 @@ Model Info: return False - async def send_alert( # noqa: PLR0915 + async def send_alert( self, message: str, level: Literal["Low", "Medium", "High"], diff --git a/litellm/integrations/anthropic_cache_control_hook.py b/litellm/integrations/anthropic_cache_control_hook.py index 213622cb43a..296bfb6fc85 100644 --- a/litellm/integrations/anthropic_cache_control_hook.py +++ b/litellm/integrations/anthropic_cache_control_hook.py @@ -27,6 +27,11 @@ else: LiteLLMLoggingObj = Any +# Anthropic (and Bedrock Claude) reject requests with more than 4 cache_control +# breakpoints: "A maximum of 4 blocks with cache_control may be provided." +MAX_CACHE_CONTROL_BLOCKS = 4 + + class AnthropicCacheControlHook(CustomPromptManagement): def get_chat_completion_prompt( self, @@ -61,16 +66,30 @@ class AnthropicCacheControlHook(CustomPromptManagement): processed_messages = copy.deepcopy(messages) # Separate message-level and non-message-level injection points - remaining_points = [] + message_points: List[CacheControlMessageInjectionPoint] = [] + remaining_points: List[CacheControlInjectionPoint] = [] for point in injection_points: if point.get("location") == "message": - point = cast(CacheControlMessageInjectionPoint, point) - processed_messages = self._process_message_injection( - point=point, messages=processed_messages - ) + message_points.append(cast(CacheControlMessageInjectionPoint, point)) else: remaining_points.append(point) + # Non-message points (currently Bedrock tool_config) are handled in the + # provider transform, where each tool_config point appends at most one + # cachePoint to the tools. That block also counts toward Anthropic's + # limit, so reserve a slot for it here to leave room. + reserved_blocks = ( + 1 + if any(p.get("location") == "tool_config" for p in remaining_points) + else 0 + ) + + processed_messages = self._apply_message_injections( + points=message_points, + messages=processed_messages, + max_blocks=MAX_CACHE_CONTROL_BLOCKS - reserved_blocks, + ) + # Pass through non-message injection points for provider-specific handling if remaining_points: non_default_params["cache_control_injection_points"] = remaining_points @@ -78,14 +97,71 @@ class AnthropicCacheControlHook(CustomPromptManagement): return model, processed_messages, non_default_params @staticmethod - def _process_message_injection( - point: CacheControlMessageInjectionPoint, messages: List[AllMessageValues] + def _apply_message_injections( + points: List[CacheControlMessageInjectionPoint], + messages: List[AllMessageValues], + max_blocks: int, ) -> List[AllMessageValues]: - """Process message-level cache control injection.""" - control: ChatCompletionCachedContent = point.get( - "control", None - ) or ChatCompletionCachedContent(type="ephemeral") + """Apply message-level cache control injection points in order. + Anthropic allows at most ``MAX_CACHE_CONTROL_BLOCKS`` cache_control + breakpoints per request. Client-supplied breakpoints count toward that + limit, so we never inject onto a message that already carries + cache_control (preserving the client's TTL) and we stop injecting once + ``max_blocks`` is reached. Injection points are honored in config order, + so earlier points win when slots are scarce. + """ + used_blocks = sum( + AnthropicCacheControlHook._count_cache_control_blocks(msg) + for msg in messages + ) + + limit_reached = False + for point in points: + if used_blocks >= max_blocks: + limit_reached = True + break + + control: ChatCompletionCachedContent = point.get( + "control", None + ) or ChatCompletionCachedContent(type="ephemeral") + + for target_index in AnthropicCacheControlHook._resolve_target_indices( + point=point, messages=messages + ): + if used_blocks >= max_blocks: + limit_reached = True + break + + if AnthropicCacheControlHook._message_has_cache_control( + messages[target_index] + ): + # Client already marked this message; don't overwrite it. + continue + + messages[target_index] = ( + AnthropicCacheControlHook._safe_insert_cache_control_in_message( + messages[target_index], control + ) + ) + used_blocks += 1 + + if limit_reached: + break + + if limit_reached: + verbose_logger.warning( + f"AnthropicCacheControlHook: Reached the Anthropic limit of " + f"{MAX_CACHE_CONTROL_BLOCKS} cache_control blocks. Skipping further injection." + ) + + return messages + + @staticmethod + def _resolve_target_indices( + point: CacheControlMessageInjectionPoint, messages: List[AllMessageValues] + ) -> List[int]: + """Resolve which message indices an injection point targets.""" _targetted_index: Optional[Union[int, str]] = point.get("index", None) targetted_index: Optional[int] = None if isinstance(_targetted_index, str): @@ -96,36 +172,49 @@ class AnthropicCacheControlHook(CustomPromptManagement): else: targetted_index = _targetted_index - targetted_role = point.get("role", None) - # Case 1: Target by specific index if targetted_index is not None: original_index = targetted_index - # Handle negative indices (convert to positive) if targetted_index < 0: targetted_index += len(messages) if 0 <= targetted_index < len(messages): - messages[targetted_index] = ( - AnthropicCacheControlHook._safe_insert_cache_control_in_message( - messages[targetted_index], control - ) - ) - else: - verbose_logger.warning( - f"AnthropicCacheControlHook: Provided index {original_index} is out of bounds for message list of length {len(messages)}. " - f"Targeted index was {targetted_index}. Skipping cache control injection for this point." - ) + return [targetted_index] + + verbose_logger.warning( + f"AnthropicCacheControlHook: Provided index {original_index} is out of bounds for message list of length {len(messages)}. " + f"Targeted index was {targetted_index}. Skipping cache control injection for this point." + ) + return [] + # Case 2: Target by role - elif targetted_role is not None: - for msg in messages: - if msg.get("role") == targetted_role: - msg = ( - AnthropicCacheControlHook._safe_insert_cache_control_in_message( - message=msg, control=control - ) - ) - return messages + targetted_role = point.get("role", None) + if targetted_role is not None: + return [ + idx + for idx, msg in enumerate(messages) + if msg.get("role") == targetted_role + ] + + return [] + + @staticmethod + def _count_cache_control_blocks(message: AllMessageValues) -> int: + """Count cache_control breakpoints on a message (message + content level).""" + count = 0 + if message.get("cache_control") is not None: + count += 1 + content = message.get("content") + if isinstance(content, list): + for block in content: + if isinstance(block, dict) and block.get("cache_control") is not None: + count += 1 + return count + + @staticmethod + def _message_has_cache_control(message: AllMessageValues) -> bool: + """Return True if the message already carries any cache_control.""" + return AnthropicCacheControlHook._count_cache_control_blocks(message) > 0 @staticmethod def _safe_insert_cache_control_in_message( diff --git a/litellm/integrations/braintrust_logging.py b/litellm/integrations/braintrust_logging.py index 9b1c5077882..6a6313f72e1 100644 --- a/litellm/integrations/braintrust_logging.py +++ b/litellm/integrations/braintrust_logging.py @@ -133,9 +133,7 @@ class BraintrustLogger(CustomLogger): self.default_project_id = project_dict["id"] - def log_success_event( # noqa: PLR0915 - self, kwargs, response_obj, start_time, end_time - ): + def log_success_event(self, kwargs, response_obj, start_time, end_time): verbose_logger.debug("REACHES BRAINTRUST SUCCESS") try: litellm_call_id = kwargs.get("litellm_call_id") @@ -271,9 +269,7 @@ class BraintrustLogger(CustomLogger): except Exception as e: raise e # don't use verbose_logger.exception, if exception is raised - async def async_log_success_event( # noqa: PLR0915 - self, kwargs, response_obj, start_time, end_time - ): + async def async_log_success_event(self, kwargs, response_obj, start_time, end_time): verbose_logger.debug("REACHES BRAINTRUST SUCCESS") try: litellm_call_id = kwargs.get("litellm_call_id") diff --git a/litellm/integrations/callback_configs.json b/litellm/integrations/callback_configs.json index 3a69c9a7936..590c848767a 100644 --- a/litellm/integrations/callback_configs.json +++ b/litellm/integrations/callback_configs.json @@ -290,6 +290,21 @@ }, "description": "Langsmith Logging Integration" }, + { + "id": "newrelic", + "displayName": "New Relic", + "logo": "newrelic.png", + "supports_key_team_logging": false, + "dynamic_params": { + "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED": { + "type": "text", + "ui_name": "Record AI Content (default: true)", + "description": "Whether to record AI message content. Set to false to disable.", + "required": false + } + }, + "description": "New Relic AI Monitoring Integration" + }, { "id": "openmeter", "displayName": "OpenMeter", diff --git a/litellm/integrations/compression_interception/handler.py b/litellm/integrations/compression_interception/handler.py index c6ae7d9e82b..8899089500d 100644 --- a/litellm/integrations/compression_interception/handler.py +++ b/litellm/integrations/compression_interception/handler.py @@ -72,8 +72,13 @@ class CompressionInterceptionLogger(CustomLogger): compression_params: CompressionInterceptionConfig = {} if "compression_interception_params" in litellm_settings: compression_params = litellm_settings["compression_interception_params"] - elif "compression_interception" in callback_specific_params: - compression_params = callback_specific_params["compression_interception"] + elif "compression_interception" in callback_specific_params and isinstance( + callback_specific_params["compression_interception"], dict + ): + compression_params = cast( + CompressionInterceptionConfig, + callback_specific_params["compression_interception"], + ) return CompressionInterceptionLogger.from_config_yaml(compression_params) async def async_pre_call_deployment_hook( diff --git a/litellm/integrations/custom_guardrail.py b/litellm/integrations/custom_guardrail.py index fc5f0429b63..38245a2e5ba 100644 --- a/litellm/integrations/custom_guardrail.py +++ b/litellm/integrations/custom_guardrail.py @@ -1,3 +1,4 @@ +import secrets from datetime import datetime from typing import ( TYPE_CHECKING, @@ -43,6 +44,7 @@ if TYPE_CHECKING: dc = DualCache() +from litellm.constants import PRE_CALL_EXECUTED_GUARDRAILS_KEY from litellm.exceptions import ( BlockedPiiEntityError, GuardrailRaisedException, @@ -50,6 +52,12 @@ from litellm.exceptions import ( SensitiveDataRouteException, ) +# Per-process secret tagging each recorded marker. The deployment hook only +# honors markers carrying this token, so a caller cannot forge the metadata +# field to suppress a guardrail on the direct-SDK path that never reaches the +# proxy's metadata sanitizer. +_PRE_CALL_EXECUTED_TOKEN = secrets.token_hex(16) + def get_session_id_from_request_data(request_data: Dict[str, Any]) -> Optional[str]: """Extract session_id from request data (litellm_session_id or metadata).""" @@ -458,6 +466,49 @@ class CustomGuardrail(CustomLogger): return False + def _pre_call_marker(self) -> Optional[str]: + name = self.guardrail_name + if not name: + return None + return f"{_PRE_CALL_EXECUTED_TOKEN}:{name}" + + def mark_pre_call_hook_ran(self, data: Dict[str, Any]) -> None: + """ + Record that this guardrail's ``async_pre_call_hook`` already ran for this + request, so the deployment-level hook does not run it a second time. + + The proxy runs pre-call guardrails in ``ProxyLogging.pre_call_hook``. The + router later spreads a deployment's model-level ``guardrails`` into the + top-level request kwargs, which would otherwise re-trigger the same hook + from ``async_pre_call_deployment_hook``. + """ + marker = self._pre_call_marker() + if marker is None: + return + for meta_key in ("metadata", "litellm_metadata"): + meta = data.get(meta_key) + if isinstance(meta, dict): + executed = meta.get(PRE_CALL_EXECUTED_GUARDRAILS_KEY) + if isinstance(executed, list): + if marker not in executed: + executed.append(marker) + else: + meta[PRE_CALL_EXECUTED_GUARDRAILS_KEY] = [marker] + return + data["metadata"] = {PRE_CALL_EXECUTED_GUARDRAILS_KEY: [marker]} + + def _pre_call_hook_already_ran(self, data: Dict[str, Any]) -> bool: + marker = self._pre_call_marker() + if marker is None: + return False + for meta_key in ("metadata", "litellm_metadata"): + meta = data.get(meta_key) + if isinstance(meta, dict): + executed = meta.get(PRE_CALL_EXECUTED_GUARDRAILS_KEY) + if isinstance(executed, list) and marker in executed: + return True + return False + async def async_pre_call_deployment_hook( self, kwargs: Dict[str, Any], call_type: Optional[CallTypes] ) -> Optional[dict]: @@ -468,6 +519,9 @@ class CustomGuardrail(CustomLogger): if litellm_guardrails is None or not isinstance(litellm_guardrails, list): return kwargs + if self._pre_call_hook_already_ran(kwargs): + return kwargs + if ( self.should_run_guardrail( data=kwargs, event_type=GuardrailEventHooks.pre_call @@ -567,6 +621,9 @@ class CustomGuardrail(CustomLogger): ): return False + if self.default_on is True and disable_global_guardrail is True: + return False + if self.default_on is True and disable_global_guardrail is not True: if self._event_hook_is_event_type(event_type): if isinstance(self.event_hook, Mode): diff --git a/litellm/integrations/datadog/datadog.py b/litellm/integrations/datadog/datadog.py index 79a9219a39c..b0cd0eb1172 100644 --- a/litellm/integrations/datadog/datadog.py +++ b/litellm/integrations/datadog/datadog.py @@ -92,12 +92,26 @@ class DataDogLogger( # Class variables or attributes def __init__( self, + dd_api_key: Optional[str] = None, + dd_site: Optional[str] = None, + dd_agent_host: Optional[str] = None, + dd_agent_port: Optional[str] = None, + allow_env_credentials: bool = True, **kwargs, ): """ Initializes the datadog logger, checks if the correct env variables are set - Required environment variables (Direct API): + Args: + dd_api_key: Datadog API key. Falls back to DD_API_KEY env var when allow_env_credentials is True. + dd_site: Datadog site (e.g. "us5.datadoghq.com"). Falls back to DD_SITE env var. + dd_agent_host: Hostname or IP of DataDog agent. Falls back to LITELLM_DD_AGENT_HOST env var. + dd_agent_port: Port of DataDog agent (default: 10518). Falls back to LITELLM_DD_AGENT_PORT env var. + allow_env_credentials: When False, the API key is never read from DD_API_KEY env var. Set to + False for team/key-scoped loggers whose destination (dd_agent_host/dd_site) is caller-supplied, + so the proxy's global DD_API_KEY is never sent to an untrusted host. + + Required environment variables (Direct API) when kwargs not provided: `DD_API_KEY` - your datadog api key `DD_SITE` - your datadog site, example = `"us5.datadoghq.com"` @@ -130,12 +144,21 @@ class DataDogLogger( ) # Configure DataDog endpoint (Agent or Direct API) - # Use LITELLM_DD_AGENT_HOST to avoid conflicts with ddtrace's DD_AGENT_HOST - dd_agent_host = os.getenv("LITELLM_DD_AGENT_HOST") - if dd_agent_host: - self._configure_dd_agent(dd_agent_host=dd_agent_host) + # Prefer explicit kwargs, then fall back to env vars + resolved_agent_host = dd_agent_host or os.getenv("LITELLM_DD_AGENT_HOST") + if resolved_agent_host: + self._configure_dd_agent( + dd_agent_host=resolved_agent_host, + dd_agent_port=dd_agent_port, + dd_api_key=dd_api_key, + allow_env_credentials=allow_env_credentials, + ) else: - self._configure_dd_direct_api() + self._configure_dd_direct_api( + dd_api_key=dd_api_key, + dd_site=dd_site, + allow_env_credentials=allow_env_credentials, + ) # Optional override for testing dd_base_url = get_datadog_base_url_from_env() @@ -172,34 +195,60 @@ class DataDogLogger( ).model_dump() return dict_datadog_params - def _configure_dd_agent(self, dd_agent_host: str) -> None: + def _configure_dd_agent( + self, + dd_agent_host: str, + dd_agent_port: Optional[str] = None, + dd_api_key: Optional[str] = None, + allow_env_credentials: bool = True, + ) -> None: """ Configure DataDog Agent for log forwarding Args: dd_agent_host: Hostname or IP of DataDog agent + dd_agent_port: Port of DataDog agent. Falls back to LITELLM_DD_AGENT_PORT env var (default: 10518). + dd_api_key: Datadog API key. Falls back to DD_API_KEY env var when allow_env_credentials is True. Optional when using agent. + allow_env_credentials: When False, never read the API key from DD_API_KEY env var. """ - dd_agent_port = os.getenv( + resolved_port = dd_agent_port or os.getenv( "LITELLM_DD_AGENT_PORT", "10518" ) # default port for logs - self.intake_url = f"http://{dd_agent_host}:{dd_agent_port}/api/v2/logs" - self.DD_API_KEY = os.getenv("DD_API_KEY") # Optional when using agent + self.intake_url = f"http://{dd_agent_host}:{resolved_port}/api/v2/logs" + self.DD_API_KEY = dd_api_key or ( + os.getenv("DD_API_KEY") if allow_env_credentials else None + ) # Optional when using agent verbose_logger.debug(f"Datadog: Using DD Agent at {self.intake_url}") - def _configure_dd_direct_api(self) -> None: + def _configure_dd_direct_api( + self, + dd_api_key: Optional[str] = None, + dd_site: Optional[str] = None, + allow_env_credentials: bool = True, + ) -> None: """ Configure direct DataDog API connection + Args: + dd_api_key: Datadog API key. Falls back to DD_API_KEY env var when allow_env_credentials is True. + dd_site: Datadog site. Falls back to DD_SITE env var. + allow_env_credentials: When False, never read the API key from DD_API_KEY env var. + Raises: - Exception: If required environment variables are not set + Exception: If required credentials are not provided via args or env vars """ - if os.getenv("DD_API_KEY", None) is None: + resolved_api_key = dd_api_key or ( + os.getenv("DD_API_KEY") if allow_env_credentials else None + ) + resolved_site = dd_site or os.getenv("DD_SITE") + + if resolved_api_key is None: raise Exception("DD_API_KEY is not set, set 'DD_API_KEY=<>") - if os.getenv("DD_SITE", None) is None: + if resolved_site is None: raise Exception("DD_SITE is not set in .env, set 'DD_SITE=<>") - self.DD_API_KEY = os.getenv("DD_API_KEY") - self.intake_url = f"https://http-intake.logs.{os.getenv('DD_SITE')}/api/v2/logs" + self.DD_API_KEY = resolved_api_key + self.intake_url = f"https://http-intake.logs.{resolved_site}/api/v2/logs" async def async_log_success_event(self, kwargs, response_obj, start_time, end_time): """ diff --git a/litellm/integrations/datadog/datadog_team_handler.py b/litellm/integrations/datadog/datadog_team_handler.py new file mode 100644 index 00000000000..3a5b73fc005 --- /dev/null +++ b/litellm/integrations/datadog/datadog_team_handler.py @@ -0,0 +1,124 @@ +""" +DataDog Team Handler + +Used to get the DataDogLogger for a given request. +Handles Key/Team Based Datadog Logging, following the same pattern as LangFuseHandler. +""" + +from typing import TYPE_CHECKING, Any, Dict, Optional, TypedDict + +from litellm._logging import verbose_logger +from litellm.litellm_core_utils.litellm_logging import StandardCallbackDynamicParams + +from .datadog import DataDogLogger + +if TYPE_CHECKING: + from litellm.litellm_core_utils.litellm_logging import DynamicLoggingCache +else: + DynamicLoggingCache = Any + + +class DatadogLoggingConfig(TypedDict): + dd_api_key: Optional[str] + dd_site: Optional[str] + dd_agent_host: Optional[str] + dd_agent_port: Optional[str] + + +class DataDogHandler: + @staticmethod + def get_datadog_logger_for_request( + standard_callback_dynamic_params: StandardCallbackDynamicParams, + in_memory_dynamic_logger_cache: DynamicLoggingCache, + ) -> DataDogLogger: + """ + Get a team-scoped DataDogLogger for a given request. + + Resolves and caches per-team DataDogLogger instances using DynamicLoggingCache, + keyed by the team's DD credentials. Each unique set of credentials gets its own + logger instance with its own batch/flush loop. + + Note: This handler is only called when team-scoped DD credentials are present. + The global (env-var based) DataDogLogger is managed separately by + _init_custom_logger_compatible_class via _in_memory_loggers. + """ + _credentials = DataDogHandler.get_dynamic_datadog_logging_config( + standard_callback_dynamic_params=standard_callback_dynamic_params, + ) + credentials_dict = dict(_credentials) + + # check if datadog logger is already cached + temp_datadog_logger = in_memory_dynamic_logger_cache.get_cache( + credentials=credentials_dict, service_name="datadog" + ) + + # if not cached, create a new datadog logger and cache it + if temp_datadog_logger is None: + temp_datadog_logger = ( + DataDogHandler._create_datadog_logger_from_credentials( + credentials=credentials_dict, + in_memory_dynamic_logger_cache=in_memory_dynamic_logger_cache, + ) + ) + + return temp_datadog_logger + + @staticmethod + def _create_datadog_logger_from_credentials( + credentials: Dict, + in_memory_dynamic_logger_cache: DynamicLoggingCache, + ) -> DataDogLogger: + """ + Create a DataDogLogger from the credentials and cache it. + """ + # When the destination is caller-supplied (dd_agent_host/dd_site), never fall back to the + # proxy's DD_API_KEY env var, otherwise it would be sent to a team-controlled host. + allow_env_credentials = ( + credentials.get("dd_agent_host") is None + and credentials.get("dd_site") is None + ) + datadog_logger = DataDogLogger( + dd_api_key=credentials.get("dd_api_key"), + dd_site=credentials.get("dd_site"), + dd_agent_host=credentials.get("dd_agent_host"), + dd_agent_port=credentials.get("dd_agent_port"), + allow_env_credentials=allow_env_credentials, + ) + in_memory_dynamic_logger_cache.set_cache( + credentials=credentials, + service_name="datadog", + logging_obj=datadog_logger, + ) + verbose_logger.debug( + "Datadog: Created and cached new DataDogLogger for team-scoped credentials" + ) + return datadog_logger + + @staticmethod + def get_dynamic_datadog_logging_config( + standard_callback_dynamic_params: StandardCallbackDynamicParams, + ) -> DatadogLoggingConfig: + """ + Get the Datadog logging config for a given request from dynamic params. + """ + return DatadogLoggingConfig( + dd_api_key=standard_callback_dynamic_params.get("dd_api_key"), + dd_site=standard_callback_dynamic_params.get("dd_site"), + dd_agent_host=standard_callback_dynamic_params.get("dd_agent_host"), + dd_agent_port=standard_callback_dynamic_params.get("dd_agent_port"), + ) + + @staticmethod + def _dynamic_datadog_credentials_are_passed( + standard_callback_dynamic_params: StandardCallbackDynamicParams, + ) -> bool: + """ + Check if dynamic Datadog credentials are passed in standard_callback_dynamic_params. + """ + if ( + standard_callback_dynamic_params.get("dd_api_key") is not None + or standard_callback_dynamic_params.get("dd_site") is not None + or standard_callback_dynamic_params.get("dd_agent_host") is not None + ): + return True + return False diff --git a/litellm/integrations/email_alerting.py b/litellm/integrations/email_alerting.py index b45b9aa7f5c..b721dc50464 100644 --- a/litellm/integrations/email_alerting.py +++ b/litellm/integrations/email_alerting.py @@ -7,6 +7,7 @@ from typing import List, Optional from litellm._logging import verbose_logger, verbose_proxy_logger from litellm.proxy._types import WebhookEvent +from litellm.repositories.team_repository import TeamRepository # we use this for the email header, please send a test email if you change this. verify it looks good on email LITELLM_LOGO_URL = "https://litellm-listing.s3.amazonaws.com/litellm_logo.png" @@ -24,7 +25,7 @@ async def get_all_team_member_emails(team_id: Optional[str] = None) -> list: if prisma_client is None: raise Exception("Not connected to DB!") - team_row = await prisma_client.db.litellm_teamtable.find_unique( + team_row = await TeamRepository(prisma_client).table.find_unique( where={ "team_id": team_id, } diff --git a/litellm/integrations/focus/database.py b/litellm/integrations/focus/database.py index 298254670eb..3ae3f6b53ac 100644 --- a/litellm/integrations/focus/database.py +++ b/litellm/integrations/focus/database.py @@ -80,11 +80,15 @@ class FocusLiteLLMDatabase: vt.team_id, vt.key_alias as api_key_alias, tt.team_alias, - ut.user_email as user_email + ut.user_email as user_email, + COALESCE(vt.organization_id, tt.organization_id) as organization_id, + ot.organization_alias as organization_alias FROM "LiteLLM_DailyUserSpend" dus LEFT JOIN "LiteLLM_VerificationToken" vt ON dus.api_key = vt.token LEFT JOIN "LiteLLM_TeamTable" tt ON vt.team_id = tt.team_id LEFT JOIN "LiteLLM_UserTable" ut ON dus.user_id = ut.user_id + LEFT JOIN "LiteLLM_OrganizationTable" ot + ON ot.organization_id = COALESCE(vt.organization_id, tt.organization_id) {where_clause} ORDER BY dus.date DESC, dus.created_at DESC {limit_clause} diff --git a/litellm/integrations/focus/destinations/__init__.py b/litellm/integrations/focus/destinations/__init__.py index 775d3a259d2..21945c9b457 100644 --- a/litellm/integrations/focus/destinations/__init__.py +++ b/litellm/integrations/focus/destinations/__init__.py @@ -2,13 +2,17 @@ from .base import FocusDestination, FocusTimeWindow from .factory import FocusDestinationFactory +from .gcs_destination import FocusGCSDestination from .s3_destination import FocusS3Destination +from .mavvrik_destination import FocusMavvrikDestination from .vantage_destination import FocusVantageDestination __all__ = [ "FocusDestination", "FocusDestinationFactory", + "FocusGCSDestination", "FocusTimeWindow", "FocusS3Destination", + "FocusMavvrikDestination", "FocusVantageDestination", ] diff --git a/litellm/integrations/focus/destinations/factory.py b/litellm/integrations/focus/destinations/factory.py index 706e10624ce..cd25a87729f 100644 --- a/litellm/integrations/focus/destinations/factory.py +++ b/litellm/integrations/focus/destinations/factory.py @@ -6,7 +6,9 @@ import os from typing import Any, Dict, Optional from .base import FocusDestination +from .gcs_destination import FocusGCSDestination from .s3_destination import FocusS3Destination +from .mavvrik_destination import FocusMavvrikDestination from .vantage_destination import FocusVantageDestination @@ -29,6 +31,10 @@ class FocusDestinationFactory: return FocusS3Destination(prefix=prefix, config=normalized_config) if provider_lower == "vantage": return FocusVantageDestination(prefix=prefix, config=normalized_config) + if provider_lower == "gcs": + return FocusGCSDestination(prefix=prefix, config=normalized_config) + if provider_lower == "mavvrik": + return FocusMavvrikDestination(prefix=prefix, config=normalized_config) raise NotImplementedError( f"Provider '{provider}' not supported for Focus export" ) @@ -72,6 +78,27 @@ class FocusDestinationFactory: "VANTAGE_INTEGRATION_TOKEN must be provided for Vantage exports" ) return {k: v for k, v in resolved.items() if v is not None} + if provider == "gcs": + resolved = { + "bucket_name": overrides.get("bucket_name") + or os.getenv("FOCUS_GCS_BUCKET_NAME"), + "service_account_json": overrides.get("service_account_json") + or os.getenv("FOCUS_GCS_PATH_SERVICE_ACCOUNT"), + } + if not resolved.get("bucket_name"): + raise ValueError( + "FOCUS_GCS_BUCKET_NAME must be provided for GCS exports" + ) + return {k: v for k, v in resolved.items() if v is not None} + if provider == "mavvrik": + resolved = { + "api_key": overrides.get("api_key") or os.getenv("MAVVRIK_API_KEY"), + "api_endpoint": overrides.get("api_endpoint") + or os.getenv("MAVVRIK_API_ENDPOINT"), + "connection_id": overrides.get("connection_id") + or os.getenv("MAVVRIK_CONNECTION_ID"), + } + return {k: v for k, v in resolved.items() if v is not None} raise NotImplementedError( f"Provider '{provider}' not supported for Focus export configuration" ) diff --git a/litellm/integrations/focus/destinations/gcs_destination.py b/litellm/integrations/focus/destinations/gcs_destination.py new file mode 100644 index 00000000000..b04c16c9d32 --- /dev/null +++ b/litellm/integrations/focus/destinations/gcs_destination.py @@ -0,0 +1,74 @@ +"""GCS destination for Focus export — reuses GCSBucketBase auth and httpx client.""" + +from __future__ import annotations + +from datetime import timezone +from typing import Any, Optional + +from litellm._logging import verbose_logger +from litellm.integrations.gcs_bucket.gcs_bucket_base import GCSBucketBase +from litellm.litellm_core_utils.cloud_storage_security import ( + encode_gcs_object_name_for_url, +) + +from .base import FocusDestination, FocusTimeWindow + + +class FocusGCSDestination(GCSBucketBase, FocusDestination): + """Upload serialized Focus exports to GCS using the GCS JSON API.""" + + def __init__( + self, + *, + prefix: str, + config: Optional[dict[str, Any]] = None, + ) -> None: + config = config or {} + bucket_name = config.get("bucket_name") + if not bucket_name: + raise ValueError("bucket_name must be provided for GCS destination") + super().__init__(bucket_name=bucket_name) + service_account_json = config.get("service_account_json") + if service_account_json is not None: + self.path_service_account_json = service_account_json + self.prefix = prefix.rstrip("/") + + async def deliver( + self, + *, + content: bytes, + time_window: FocusTimeWindow, + filename: str, + ) -> None: + object_name = self._build_object_key(time_window=time_window, filename=filename) + headers = await self.construct_request_headers( + service_account_json=self.path_service_account_json + ) + headers["Content-Type"] = "application/octet-stream" + encoded_name = encode_gcs_object_name_for_url(object_name) + url = ( + f"https://storage.googleapis.com/upload/storage/v1/b/" + f"{self.BUCKET_NAME}/o?uploadType=media&name={encoded_name}" + ) + response = await self.async_httpx_client.post( + url=url, headers=headers, data=content + ) + if response.status_code != 200: + raise RuntimeError( + f"GCS upload failed: status={response.status_code} body={response.text}" + ) + verbose_logger.debug( + "Focus GCS: uploaded %d bytes to gs://%s/%s", + len(content), + self.BUCKET_NAME, + object_name, + ) + + def _build_object_key(self, *, time_window: FocusTimeWindow, filename: str) -> str: + start_utc = time_window.start_time.astimezone(timezone.utc) + date_component = f"date={start_utc.strftime('%Y-%m-%d')}" + parts = [self.prefix, date_component] + if time_window.frequency == "hourly": + parts.append(f"hour={start_utc.strftime('%H')}") + key_prefix = "/".join(filter(None, parts)) + return f"{key_prefix}/{filename}" if key_prefix else filename diff --git a/litellm/integrations/focus/destinations/mavvrik_destination.py b/litellm/integrations/focus/destinations/mavvrik_destination.py new file mode 100644 index 00000000000..1e3c98b9a70 --- /dev/null +++ b/litellm/integrations/focus/destinations/mavvrik_destination.py @@ -0,0 +1,345 @@ +"""Mavvrik GCS destination for FOCUS export. + +Flow: + 1. GET /metrics/agent/ai/{connection_id}/upload-url → GCS signed URL + 2. PUT with CSV content +""" + +from __future__ import annotations + +import gzip +from typing import Any, Optional +from urllib.parse import urlparse + +from litellm._logging import verbose_logger +from litellm.llms.custom_httpx.http_handler import ( + AsyncHTTPHandler, + get_async_httpx_client, + httpxSpecialProvider, +) + +from .base import FocusDestination, FocusTimeWindow + +_MAVVRIK_ALLOWED_SUFFIXES = (".mavvrik.dev", ".mavvrik.ai", ".mavvrik.app") + +# GCS requires intermediate chunks to be a multiple of 256 KB. +# 8 MB gives a good balance between round-trips and memory pressure. +_GCS_CHUNK_SIZE = 8 * 1024 * 1024 # 8 MB + + +def _validate_api_endpoint(api_endpoint: str) -> None: + if not api_endpoint.startswith("https://"): + raise ValueError("MAVVRIK_API_ENDPOINT must be an HTTPS URL") + hostname = (urlparse(api_endpoint).hostname or "").lower() + if not any(hostname.endswith(suffix) for suffix in _MAVVRIK_ALLOWED_SUFFIXES): + raise ValueError( + "MAVVRIK_API_ENDPOINT host must be a Mavvrik domain " + "(e.g. https://api.mavvrik.dev/)" + ) + + +def _validate_gcs_url(url: str, label: str) -> None: + parsed = urlparse(url) + if parsed.scheme != "https": + raise ValueError( + f"Mavvrik FOCUS destination: {label} must be HTTPS, got scheme '{parsed.scheme}'" + ) + hostname = (parsed.hostname or "").lower() + if not ( + hostname == "storage.googleapis.com" + or hostname.endswith(".storage.googleapis.com") + ): + raise ValueError( + f"Mavvrik FOCUS destination: {label} must be a GCS endpoint " + f"(storage.googleapis.com), got '{hostname}'" + ) + + +class FocusMavvrikDestination(FocusDestination): + """Upload FOCUS CSV exports to Mavvrik via GCS signed URL.""" + + def __init__( + self, + *, + prefix: str, + config: Optional[dict[str, Any]] = None, + ) -> None: + config = config or {} + api_key = config.get("api_key") + api_endpoint = config.get("api_endpoint") + connection_id = config.get("connection_id") + + if not api_key: + raise ValueError( + "MAVVRIK_API_KEY must be provided for Mavvrik FOCUS destination " + "(set MAVVRIK_API_KEY env var or pass in destination_config)" + ) + if not api_endpoint: + raise ValueError( + "MAVVRIK_API_ENDPOINT must be provided for Mavvrik FOCUS destination " + "(set MAVVRIK_API_ENDPOINT env var or pass in destination_config)" + ) + if not connection_id: + raise ValueError( + "MAVVRIK_CONNECTION_ID must be provided for Mavvrik FOCUS destination " + "(set MAVVRIK_CONNECTION_ID env var or pass in destination_config)" + ) + + _validate_api_endpoint(api_endpoint) + + self.api_key = api_key + self.api_endpoint = api_endpoint.rstrip("/") + self.connection_id = connection_id + self.prefix = prefix + self._http: AsyncHTTPHandler = get_async_httpx_client( + llm_provider=httpxSpecialProvider.LoggingCallback + ) + self._registered = False + + @property + def _agent_url(self) -> str: + return f"{self.api_endpoint}/metrics/agent/ai/{self.connection_id}" + + @property + def _upload_url_endpoint(self) -> str: + return f"{self.api_endpoint}/metrics/agent/ai/{self.connection_id}/upload-url" + + @property + def _auth_headers(self) -> dict[str, str]: + return {"Content-Type": "application/json", "x-api-key": self.api_key} + + async def _ensure_registered(self) -> Optional[int]: + """POST agent endpoint to register/initialize the connector (once per instance). + + Returns metricsMarker from the Mavvrik response — the last date index + Mavvrik has successfully processed. Used by the logger to catch up any + dates that were missed due to previous export failures. + + Returns None if the connector was already registered (cached). + """ + if self._registered: + return None + resp = await self._http.client.request( + method="POST", + url=self._agent_url, + headers=self._auth_headers, + json={"name": self.connection_id}, + timeout=30.0, + ) + if resp.status_code == 410: + # Connector has been disconnected in Mavvrik — reset flag so next + # delivery attempt re-registers after it becomes active again. + self._registered = False + raise RuntimeError( + "Mavvrik FOCUS destination: connector is disconnected (410). " + "Re-enable the connection in the Mavvrik dashboard." + ) + if resp.status_code >= 400: + raise RuntimeError( + f"Mavvrik FOCUS destination: register failed " + f"({resp.status_code}): {resp.text[:200]}" + ) + self._registered = True + metrics_marker = resp.json().get("metricsMarker", 0) + verbose_logger.debug( + "Mavvrik FOCUS destination: connector registered (metricsMarker=%s)", + metrics_marker, + ) + return metrics_marker + + async def _get_signed_url(self, date_str: str) -> str: + """GET upload-url endpoint → GCS signed URL for the given date.""" + params = {"name": date_str, "type": "metrics", "datetime": date_str} + resp = await self._http.client.request( + method="GET", + url=self._upload_url_endpoint, + headers=self._auth_headers, + params=params, + timeout=30.0, + ) + if resp.status_code >= 400: + raise RuntimeError( + f"Mavvrik FOCUS destination: failed to get signed URL " + f"({resp.status_code}): {resp.text[:200]}" + ) + signed_url = resp.json().get("url") + if not signed_url: + raise RuntimeError( + f"Mavvrik FOCUS destination: response missing 'url' field: {resp.json()}" + ) + _validate_gcs_url(signed_url, "signed URL") + verbose_logger.debug( + "Mavvrik FOCUS destination: got signed URL for date %s", date_str + ) + return signed_url + + async def _upload_to_gcs(self, signed_url: str, content: bytes) -> None: + """Upload gzip-compressed CSV to GCS via chunked resumable upload. + + The full CSV is gzip-compressed first, then uploaded in _GCS_CHUNK_SIZE + chunks using the GCS resumable upload protocol. GCS assembles the chunks + server-side into a single complete object — the bucket receives one file + regardless of how many chunks were sent. + + Intermediate chunks: Content-Range: bytes X-Y/* → expect 308 + Final chunk: Content-Range: bytes X-Y/T → expect 200/201 + + This handles exports larger than available memory for a single PUT while + keeping the destination code self-contained (no changes to the FOCUS + pipeline upstream). + """ + gzip_bytes = gzip.compress(content) + total = len(gzip_bytes) + + # Step 1: initiate resumable upload session + metadata = b'{"contentEncoding":"gzip","contentDisposition":"attachment"}' + init_resp = await self._http.client.request( + method="POST", + url=signed_url, + headers={ + "Content-Type": "application/gzip", + "x-goog-resumable": "start", + }, + content=metadata, + timeout=30.0, + ) + if init_resp.status_code not in (200, 201): + raise RuntimeError( + f"Mavvrik FOCUS destination: GCS session init failed " + f"({init_resp.status_code}): {init_resp.text[:400]}" + ) + + session_uri = init_resp.headers.get("Location") + if not session_uri: + raise RuntimeError( + "Mavvrik FOCUS destination: GCS session init missing Location header" + ) + _validate_gcs_url(session_uri, "session URI") + + verbose_logger.debug( + "Mavvrik FOCUS destination: GCS session started, uploading %d gzip bytes " + "in %d chunk(s)", + total, + max(1, -(-total // _GCS_CHUNK_SIZE)), # ceiling division + ) + + # Step 2: upload in chunks; cancel session on any failure to avoid + # lingering GCS sessions (they stay open for ~1 week otherwise). + offset = 0 + try: + while offset < total: + chunk = gzip_bytes[offset : offset + _GCS_CHUNK_SIZE] + chunk_end = offset + len(chunk) - 1 + is_final = (offset + len(chunk)) >= total + content_range = ( + f"bytes {offset}-{chunk_end}/{total}" + if is_final + else f"bytes {offset}-{chunk_end}/*" + ) + expected_statuses = {200, 201} if is_final else {308} + + resp = await self._http.client.request( + method="PUT", + url=session_uri, + headers={ + "Content-Type": "application/gzip", + "Content-Range": content_range, + }, + content=chunk, + timeout=120.0, + ) + if resp.status_code not in expected_statuses: + raise RuntimeError( + f"Mavvrik FOCUS destination: GCS chunk upload failed " + f"(chunk offset={offset}, expected={expected_statuses}, " + f"got={resp.status_code}): {resp.text[:400]}" + ) + offset += len(chunk) + verbose_logger.debug( + "Mavvrik FOCUS destination: uploaded chunk offset=%d/%d", + offset, + total, + ) + except Exception: + # Cancel the open GCS session so it doesn't linger for up to 1 week. + try: + await self._http.client.request( + method="DELETE", url=session_uri, timeout=10.0 + ) + verbose_logger.debug( + "Mavvrik FOCUS destination: cancelled GCS session after error" + ) + except Exception: + pass + raise + + async def get_metrics_marker(self) -> Optional[int]: + """Register with Mavvrik and return the current metricsMarker. + + The metricsMarker is a Unix timestamp (seconds) representing the last + date Mavvrik has successfully ingested. Called on every scheduled run + so the logger can detect and catch up any dates missed due to previous + export failures. + + Always calls the Mavvrik register API — unlike deliver() which skips + registration once _registered is True, catch-up requires a fresh + marker value on every run. + """ + resp = await self._http.client.request( + method="POST", + url=self._agent_url, + headers=self._auth_headers, + json={"name": self.connection_id}, + timeout=30.0, + ) + if resp.status_code == 410: + self._registered = False + raise RuntimeError( + "Mavvrik FOCUS destination: connector is disconnected (410). " + "Re-enable the connection in the Mavvrik dashboard." + ) + if resp.status_code >= 400: + raise RuntimeError( + f"Mavvrik FOCUS destination: register failed " + f"({resp.status_code}): {resp.text[:200]}" + ) + self._registered = True + metrics_marker = resp.json().get("metricsMarker", 0) + verbose_logger.debug( + "Mavvrik FOCUS destination: got metricsMarker=%s", metrics_marker + ) + return metrics_marker + + async def deliver( + self, + *, + content: bytes, + time_window: FocusTimeWindow, + filename: str, + ) -> None: + """Upload FOCUS CSV to Mavvrik via GCS signed URL. + + Uses the start date of the time window as the object date key. + """ + if not content: + verbose_logger.debug( + "Mavvrik FOCUS destination: empty content, skipping upload" + ) + return + + date_str = time_window.start_time.strftime("%Y-%m-%d") + + verbose_logger.debug( + "Mavvrik FOCUS destination: uploading %d bytes for date=%s (%s)", + len(content), + date_str, + filename, + ) + + await self._ensure_registered() + signed_url = await self._get_signed_url(date_str) + await self._upload_to_gcs(signed_url, content) + + verbose_logger.debug( + "Mavvrik FOCUS destination: upload complete for date=%s", date_str + ) diff --git a/litellm/integrations/focus/transformer.py b/litellm/integrations/focus/transformer.py index 8496b7ec159..a17df29b912 100644 --- a/litellm/integrations/focus/transformer.py +++ b/litellm/integrations/focus/transformer.py @@ -12,6 +12,8 @@ from .schema import FOCUS_NORMALIZED_SCHEMA _TAG_KEYS = ( "team_id", "team_alias", + "organization_id", + "organization_alias", "user_id", "user_email", "api_key_alias", diff --git a/litellm/integrations/galileo.py b/litellm/integrations/galileo.py index 8fef90c24e0..f9ff7e8c7a1 100644 --- a/litellm/integrations/galileo.py +++ b/litellm/integrations/galileo.py @@ -26,6 +26,7 @@ from litellm.llms.custom_httpx.http_handler import ( get_async_httpx_client, httpxSpecialProvider, ) +from litellm.types.integrations.base_health_check import IntegrationHealthCheckStatus GALILEO_CLOUD_API_BASE_URL = "https://api.galileo.ai" # Cap the in-memory buffer so persistent flush failures (e.g. Galileo @@ -89,6 +90,52 @@ class GalileoObserve(CustomLogger): return bool(self.api_key) return bool(self.username and self.password) + async def async_health_check(self) -> IntegrationHealthCheckStatus: + try: + if not self.project_id: + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message="GALILEO_PROJECT_ID environment variable not set", + ) + + if not self.base_url: + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message="GALILEO_BASE_URL environment variable not set", + ) + + if not self.use_v2_api and (not self.username or not self.password): + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message=( + "GALILEO_API_KEY or GALILEO_USERNAME and GALILEO_PASSWORD " + "environment variables must be set" + ), + ) + + if not await self._ensure_headers(): + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message="Galileo authentication failed", + ) + + response = await self.async_httpx_handler.get( + url=f"{self.base_url}/current_user", + headers=self.headers, + ) + if response.status_code >= 400: + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message=(f"Galileo API returned HTTP {response.status_code}"), + ) + + return IntegrationHealthCheckStatus(status="healthy", error_message=None) + except Exception as e: + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message=f"Galileo health check failed: {str(e)}", + ) + async def async_set_galileo_headers(self) -> None: galileo_login_response = await self.async_httpx_handler.post( url=f"{self.base_url}/login", @@ -399,9 +446,9 @@ class GalileoObserve(CustomLogger): return prompt @staticmethod - def _serialize_galileo_output(value: Any) -> Optional[str]: + def _serialize_galileo_output(value: Any) -> str: if value is None: - return None + return "" if isinstance(value, str): return value @@ -460,11 +507,11 @@ class GalileoObserve(CustomLogger): response_obj: Any, level: str = "DEFAULT", status_message: Optional[str] = None, - ) -> Tuple[str, Optional[str], Any]: + ) -> Tuple[str, str, Any]: """ Mirror Langfuse _get_langfuse_input_output_content for Galileo ingest. - Returns (input_text, output_text, messages_for_span). output_text None skips ingest. + Returns (input_text, output_text, messages_for_span). """ call_type = kwargs.get("call_type") prompt = self._build_prompt(kwargs) @@ -477,10 +524,11 @@ class GalileoObserve(CustomLogger): return self._prompt_to_input_text(prompt), status_message, prompt if response_obj is not None and ( - call_type == "embedding" + call_type in ("embedding", "aembedding") or isinstance(response_obj, litellm.EmbeddingResponse) ): - return self._prompt_to_input_text(prompt), None, prompt + # Match Langfuse OTEL: log embeddings without serializing vectors. + return self._prompt_to_input_text(prompt), "embedding-output", prompt if response_obj is not None and isinstance(response_obj, litellm.ModelResponse): output = self._get_chat_content_for_galileo(response_obj) @@ -549,7 +597,7 @@ class GalileoObserve(CustomLogger): ): input_val = kwargs.get("input") return ( - self._serialize_galileo_output(input_val) or "", + self._serialize_galileo_output(input_val), self._serialize_galileo_output(response_obj), input_val, ) @@ -574,11 +622,11 @@ class GalileoObserve(CustomLogger): kwargs.get("messages") or [], ) - return self._prompt_to_input_text(prompt), None, kwargs.get("messages") or [] + return self._prompt_to_input_text(prompt), "", kwargs.get("messages") or [] def get_output_str_from_response( self, response_obj: Any, kwargs: Dict[str, Any] - ) -> Optional[str]: + ) -> str: _, output_text, _ = self._get_galileo_input_output_content( kwargs=kwargs, response_obj=response_obj ) @@ -659,11 +707,6 @@ class GalileoObserve(CustomLogger): input_text, output_text, messages = self._get_galileo_input_output_content( kwargs=kwargs, response_obj=response_obj ) - if output_text is None: - verbose_logger.debug( - "Galileo Logger: skipping %s — no text output to log", _call_type - ) - return raw_start = slo.get("startTime") raw_end = slo.get("endTime") diff --git a/litellm/integrations/langfuse/langfuse.py b/litellm/integrations/langfuse/langfuse.py index 0efc7d66876..b1c6956a16c 100644 --- a/litellm/integrations/langfuse/langfuse.py +++ b/litellm/integrations/langfuse/langfuse.py @@ -549,7 +549,7 @@ class LangFuseLogger: ) ) - def _log_langfuse_v2( # noqa: PLR0915 + def _log_langfuse_v2( self, user_id: Optional[str], metadata: dict, diff --git a/litellm/integrations/langfuse/langfuse_otel.py b/litellm/integrations/langfuse/langfuse_otel.py index b96ec72b04e..7370bcdf934 100644 --- a/litellm/integrations/langfuse/langfuse_otel.py +++ b/litellm/integrations/langfuse/langfuse_otel.py @@ -43,6 +43,7 @@ class LangfuseOtelLogger(OpenTelemetry): """ _utils.set_attributes(span, kwargs, response_obj, LangfuseLLMObsOTELAttributes) + span.set_attribute("langfuse.observation.type", "generation") ######################################################### # Set Langfuse specific attributes diff --git a/litellm/integrations/lunary.py b/litellm/integrations/lunary.py index b24a24e0881..7b1cbc32d43 100644 --- a/litellm/integrations/lunary.py +++ b/litellm/integrations/lunary.py @@ -75,16 +75,16 @@ class LunaryLogger: version = importlib.metadata.version("lunary") # type: ignore # if version < 0.1.43 then raise ImportError if packaging.version.Version(version) < packaging.version.Version("0.1.43"): # type: ignore - print( # noqa + print( # noqa: T201 "Lunary version outdated. Required: >= 0.1.43. Upgrade via 'pip install lunary --upgrade'" ) raise ImportError self.lunary_client = lunary except ImportError: - print( # noqa + print( # noqa: T201 "Lunary not installed. Please install it using 'pip install lunary'" - ) # noqa + ) raise ImportError def log_event( diff --git a/litellm/integrations/mavvrik_focus/__init__.py b/litellm/integrations/mavvrik_focus/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/litellm/integrations/mavvrik_focus/mavvrik_focus_logger.py b/litellm/integrations/mavvrik_focus/mavvrik_focus_logger.py new file mode 100644 index 00000000000..47d3e1da7bc --- /dev/null +++ b/litellm/integrations/mavvrik_focus/mavvrik_focus_logger.py @@ -0,0 +1,272 @@ +"""MavvrikFocusLogger — FOCUS-based Mavvrik export logger. + +Usage in config.yaml: + litellm_settings: + callbacks: ["mavvrik"] + +Required env vars: + MAVVRIK_API_KEY + MAVVRIK_API_ENDPOINT + MAVVRIK_CONNECTION_ID + +Optional env vars: + MAVVRIK_FOCUS_MAX_ROWS — row cap per export window (default: 500000) + +Only daily frequency is supported. The Mavvrik ingestion protocol stores one +file per calendar date (metrics/YYYY-MM-DD). Hourly or interval exports would +overwrite each other within the same day, producing incomplete data. +""" + +from __future__ import annotations + +import os +from datetime import datetime, timedelta, timezone +from typing import TYPE_CHECKING, Any, List, Optional + +import litellm +from litellm._logging import verbose_proxy_logger +from litellm.constants import MAVVRIK_FOCUS_EXPORT_JOB_NAME +from litellm.integrations.focus.destinations.base import FocusTimeWindow +from litellm.integrations.focus.focus_logger import FocusLogger + +if TYPE_CHECKING: + from apscheduler.schedulers.asyncio import AsyncIOScheduler +else: + AsyncIOScheduler = Any + + +def _parse_metrics_marker( + marker: Optional[object], +) -> Optional[datetime]: + """Parse metricsMarker from Mavvrik register response into a UTC datetime. + + Handles both formats Mavvrik may return: + - Unix timestamp (int/float): e.g. 1749340800 + - ISO date string: e.g. "2026-06-09" or "2026-06-09T00:00:00Z" + + Returns None for falsy values (0, None, empty string) which indicate + no data has been ingested yet. + """ + if not marker: + return None + try: + if isinstance(marker, (int, float)): + return datetime.fromtimestamp(float(marker), tz=timezone.utc).replace( + hour=0, minute=0, second=0, microsecond=0 + ) + if isinstance(marker, str): + marker = marker.strip() + if not marker: + return None + # Try ISO date first (YYYY-MM-DD), then full ISO datetime + for fmt in ("%Y-%m-%d", "%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%dT%H:%M:%S"): + try: + return datetime.strptime(marker, fmt).replace(tzinfo=timezone.utc) + except ValueError: + continue + except Exception: + pass + verbose_proxy_logger.warning( + "Mavvrik FOCUS: could not parse metricsMarker %r — skipping catch-up", marker + ) + return None + + +class MavvrikFocusLogger(FocusLogger): + """FOCUS-based export logger that routes to the Mavvrik destination.""" + + def __init__(self, **kwargs: Any) -> None: + frequency = os.getenv("MAVVRIK_FOCUS_FREQUENCY", "daily").lower() + if frequency != "daily": + raise ValueError( + f"MAVVRIK_FOCUS_FREQUENCY='{frequency}' is not supported. " + "Only 'daily' is allowed -- the Mavvrik ingestion protocol stores one " + "file per calendar date (metrics/YYYY-MM-DD). Hourly or interval " + "exports would overwrite each other within the same day." + ) + super().__init__( + provider="mavvrik", + export_format="csv", + frequency="daily", + prefix="mavvrik_focus_exports", + destination_config={ + "api_key": os.getenv("MAVVRIK_API_KEY"), + "api_endpoint": os.getenv("MAVVRIK_API_ENDPOINT"), + "connection_id": os.getenv("MAVVRIK_CONNECTION_ID"), + }, + **kwargs, + ) + raw = os.getenv("MAVVRIK_FOCUS_MAX_ROWS") + self._max_rows: Optional[int] = int(raw) if raw else 500_000 + + async def _export_window( + self, + *, + window: FocusTimeWindow, + limit: Optional[int], + ) -> None: + """Export with Mavvrik row cap applied when no explicit limit is passed.""" + effective_limit = limit if limit is not None else self._max_rows + engine = self._ensure_engine() + data = await engine._database.get_usage_data( + limit=effective_limit, + start_time_utc=window.start_time, + end_time_utc=window.end_time, + ) + if effective_limit is not None and len(data) >= effective_limit: + verbose_proxy_logger.warning( + "Mavvrik FOCUS export: row cap reached (%d rows). " + "Some data for window %s→%s may be excluded. " + "Increase MAVVRIK_FOCUS_MAX_ROWS to export all rows.", + effective_limit, + window.start_time.date(), + window.end_time.date(), + ) + if data.is_empty(): + verbose_proxy_logger.debug( + "Mavvrik FOCUS export: no usage data for window %s", window + ) + return + normalized = engine._transformer.transform(data) + if normalized.is_empty(): + return + payload = engine._serializer.serialize(normalized) + if not payload: + return + await engine._destination.deliver( + content=payload, + time_window=window, + filename=engine._build_filename(window), + ) + + # Maximum number of days to catch up in a single run. Prevents runaway + # loops if the connector was disabled for a long time, and avoids querying + # data that has likely been cleaned up from LiteLLM_DailyUserSpend. + _MAX_CATCHUP_DAYS = 7 + + async def _run_scheduled_export(self) -> None: + """Export today's window, catching up any dates Mavvrik has not yet received. + + On each run: + 1. Register with Mavvrik → get metricsMarker (last successfully ingested date) + 2. If metricsMarker is behind yesterday, catch up missed dates (capped at + _MAX_CATCHUP_DAYS to avoid runaway loops on long outages) + 3. Export yesterday (today's daily window) + + This ensures a failed export on day N is automatically retried on day N+1 + without any manual intervention. + """ + engine = self._ensure_engine() + from litellm.integrations.focus.destinations.mavvrik_destination import ( # noqa: PLC0415 + FocusMavvrikDestination, + ) + + destination = engine._destination + if not isinstance(destination, FocusMavvrikDestination): + await super()._run_scheduled_export() + return + + # Register and get the last date Mavvrik has processed. + # metricsMarker may be a Unix timestamp (int/float) or an ISO date string. + marker = await destination.get_metrics_marker() + + now = datetime.now(timezone.utc) + yesterday = now.replace(hour=0, minute=0, second=0, microsecond=0) - timedelta( + days=1 + ) + + last_ingested = _parse_metrics_marker(marker) + + # Catch up missed dates, capped at _MAX_CATCHUP_DAYS + if last_ingested and last_ingested < yesterday: + # Never go further back than _MAX_CATCHUP_DAYS from yesterday + earliest_catchup = yesterday - timedelta(days=self._MAX_CATCHUP_DAYS - 1) + catch_up_date = max(last_ingested + timedelta(days=1), earliest_catchup) + + if last_ingested + timedelta(days=1) < earliest_catchup: + verbose_proxy_logger.warning( + "Mavvrik FOCUS export: metricsMarker is more than %d days behind " + "(%s). Catching up from %s only; earlier data will not be re-exported.", + self._MAX_CATCHUP_DAYS, + last_ingested.date(), + catch_up_date.date(), + ) + + while catch_up_date < yesterday: + verbose_proxy_logger.info( + "Mavvrik FOCUS export: catching up missed date %s", + catch_up_date.date(), + ) + window = FocusTimeWindow( + start_time=catch_up_date, + end_time=catch_up_date + timedelta(days=1), + frequency="daily", + ) + await self._export_window(window=window, limit=None) + catch_up_date += timedelta(days=1) + + # Export yesterday's window (the normal daily run) + window = FocusTimeWindow( + start_time=yesterday, + end_time=yesterday + timedelta(days=1), + frequency="daily", + ) + await self._export_window(window=window, limit=None) + + async def initialize_mavvrik_focus_export_job(self) -> None: + """Scheduler entry point — uses Mavvrik-specific pod-lock key.""" + from litellm.proxy.proxy_server import proxy_logging_obj # noqa: PLC0415 + + pod_lock_manager = None + if proxy_logging_obj is not None: + writer = getattr(proxy_logging_obj, "db_spend_update_writer", None) + if writer is not None: + pod_lock_manager = getattr(writer, "pod_lock_manager", None) + + if pod_lock_manager and pod_lock_manager.redis_cache: + acquired = await pod_lock_manager.acquire_lock( + cronjob_id=MAVVRIK_FOCUS_EXPORT_JOB_NAME + ) + if not acquired: + verbose_proxy_logger.debug( + "Mavvrik FOCUS export: unable to acquire pod lock" + ) + return + try: + await self._run_scheduled_export() + finally: + await pod_lock_manager.release_lock( + cronjob_id=MAVVRIK_FOCUS_EXPORT_JOB_NAME + ) + else: + await self._run_scheduled_export() + + @staticmethod + async def init_mavvrik_focus_background_job( + scheduler: AsyncIOScheduler, + ) -> None: + """Register the Mavvrik FOCUS export job on the provided scheduler.""" + loggers: List[MavvrikFocusLogger] = [ + cb + for cb in litellm.logging_callback_manager.get_custom_loggers_for_type( + callback_type=MavvrikFocusLogger + ) + if type(cb) is MavvrikFocusLogger + ] + if not loggers: + verbose_proxy_logger.debug( + "No MavvrikFocusLogger registered; skipping scheduler" + ) + return + + logger = loggers[0] + trigger_kwargs = logger._build_scheduler_trigger() + scheduler.add_job( # type: ignore[attr-defined] + logger.initialize_mavvrik_focus_export_job, + id=MAVVRIK_FOCUS_EXPORT_JOB_NAME, + replace_existing=True, + **trigger_kwargs, + ) + verbose_proxy_logger.info( + "mavvrik_focus: background export job scheduled (%s)", trigger_kwargs + ) diff --git a/litellm/integrations/mock_client_factory.py b/litellm/integrations/mock_client_factory.py index 02a927fe64f..9b912ce70c8 100644 --- a/litellm/integrations/mock_client_factory.py +++ b/litellm/integrations/mock_client_factory.py @@ -107,7 +107,7 @@ def _is_url_match(url, matchers: List[str]) -> bool: return False -def create_mock_client_factory(config: MockClientConfig): # noqa: PLR0915 +def create_mock_client_factory(config: MockClientConfig): """ Factory function that creates mock client functions based on configuration. diff --git a/litellm/integrations/newrelic/__init__.py b/litellm/integrations/newrelic/__init__.py new file mode 100644 index 00000000000..5b0f5b9cb24 --- /dev/null +++ b/litellm/integrations/newrelic/__init__.py @@ -0,0 +1,10 @@ +""" +New Relic AI Monitoring Integration for LiteLLM + +This module provides integration with New Relic's AI Monitoring feature to track +LLM requests, responses, and usage metrics. +""" + +from litellm.integrations.newrelic.newrelic import NewRelicLogger + +__all__ = ["NewRelicLogger"] diff --git a/litellm/integrations/newrelic/newrelic.py b/litellm/integrations/newrelic/newrelic.py new file mode 100644 index 00000000000..753b8520337 --- /dev/null +++ b/litellm/integrations/newrelic/newrelic.py @@ -0,0 +1,926 @@ +""" +New Relic AI Monitoring Integration for LiteLLM + +This module provides integration with New Relic's AI Monitoring feature to track +LLM requests, responses, and usage metrics. + +Environment Variables (consumed by the New Relic agent at process bootstrap - +set via container env, or before invoking `newrelic-admin run-program`): + NEW_RELIC_LICENSE_KEY: Your New Relic license key (required) + NEW_RELIC_APP_NAME: Your application name (required) + +UI- and runtime-toggleable: + NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED: Whether to record message + content (optional, default: true) + +Configuration: + Message logging can be controlled via (both must agree to record): + 1. turn_off_message_logging parameter - pass via callback initialization or config YAML + 2. NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED env var + + Default behavior: Messages ARE recorded unless explicitly disabled by either method + Either method can disable recording - both must enable for recording to occur + +Usage - Python SDK: + import litellm + litellm.callbacks = ["newrelic"] + + # Or with explicit configuration: + from litellm.integrations.newrelic import NewRelicLogger + litellm.callbacks = [NewRelicLogger(turn_off_message_logging=True)] + +Usage - Proxy Server (config.yaml): + litellm_settings: + callbacks: ["newrelic"] + newrelic_params: + turn_off_message_logging: true # Disable message content recording + + # Or disable via environment variable: + # export NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED=false + + # Ensure New Relic agent is initialized (use newrelic-admin or initialize manually) + # newrelic-admin run-program python your_app.py +""" + +import json +import os +import threading +import time +import uuid +from typing import Any, Dict, List, Optional, Tuple, Union + +import litellm +from litellm._logging import verbose_logger +from litellm.integrations.custom_logger import CustomLogger +from litellm.litellm_core_utils.redact_messages import should_redact_message_logging +from litellm.types.integrations.newrelic import NewRelicInitParams +from litellm.types.integrations.base_health_check import IntegrationHealthCheckStatus +from litellm.types.utils import ModelResponse, Message, StandardLoggingPayload + +try: + import newrelic.agent as _newrelic_agent +except ImportError: + _newrelic_agent = None # type: ignore + + +class NewRelicLogger(CustomLogger): + """ + New Relic logger for LiteLLM to send AI monitoring events. + + This logger creates two types of New Relic custom events: + 1. LlmChatCompletionSummary - One per completion request + 2. LlmChatCompletionMessage - One per message (request and response) + """ + + # Class-level state for supportability metric emission, shared across all instances. + # Protected by _metric_lock to ensure thread-safe access. + _last_metric_emission_time: float = 0.0 + _metric_lock = threading.Lock() + + def __init__(self, **kwargs): + ######################################################### + # Handle newrelic_params set as litellm.newrelic_params + ######################################################### + dict_newrelic_params = self._get_newrelic_params() + + # Use setdefault so constructor kwargs take priority over global params. + # model_dump() always returns all fields (including defaults), so update() + # would silently overwrite explicit constructor args like turn_off_message_logging=True. + for k, v in dict_newrelic_params.items(): + kwargs.setdefault(k, v) + + # CustomLogger.__init__ will set self.turn_off_message_logging from kwargs + super().__init__(**kwargs) + + # Check for required environment variables + self.license_key = os.getenv("NEW_RELIC_LICENSE_KEY") + self.app_name = os.getenv("NEW_RELIC_APP_NAME") + + # Validate configuration + if not self.license_key or not self.app_name: + verbose_logger.warning( + "New Relic integration requires NEW_RELIC_LICENSE_KEY and " + "NEW_RELIC_APP_NAME environment variables. Integration will be disabled." + ) + self.enabled = False + elif _newrelic_agent is None: + verbose_logger.error( + "New Relic Python agent not installed. Review the New Relic integration documentation at https://docs.litellm.ai/docs/observability/newrelic." + ) + self.enabled = False + else: + try: + # timeout=0 forces non-blocking startup: the agent connects in a + # background thread regardless of newrelic.ini / NEW_RELIC_STARTUP_TIMEOUT. + _newrelic_agent.register_application(timeout=0) + + self.enabled = True + verbose_logger.info( + f"New Relic AI Monitoring initialized for app: {self.app_name}, " + f"content recording: {self.record_content}" + ) + except Exception as e: + verbose_logger.error( + f"Failed to initialize New Relic agent: {e}. " + "Integration will be disabled." + ) + self.enabled = False + + def _get_newrelic_params(self) -> Dict: + """ + Get the newrelic_params from litellm.newrelic_params + + These are params specific to initializing the NewRelicLogger e.g. turn_off_message_logging + """ + dict_newrelic_params: Dict = {} + if litellm.newrelic_params is not None: + if isinstance(litellm.newrelic_params, NewRelicInitParams): + dict_newrelic_params = litellm.newrelic_params.model_dump() + elif isinstance(litellm.newrelic_params, Dict): + # only allow params that are of NewRelicInitParams + dict_newrelic_params = NewRelicInitParams( + **litellm.newrelic_params + ).model_dump() + return dict_newrelic_params + + @property + def record_content(self) -> bool: + """Whether to record message content in New Relic. + + Both turn_off_message_logging param AND NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED + env var must agree to record content. If either disables recording, content will not + be recorded. Read at call time so UI config changes take effect without a restart. + Default: True (record content) unless explicitly disabled by either method. + """ + return (not self.turn_off_message_logging) and self._parse_bool_env( + "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED", True + ) + + def _parse_bool_env(self, var_name: str, default: bool = False) -> bool: + """Parse a boolean environment variable. + + Accepts true/false, 1/0, yes/no, on/off (case-insensitive, + whitespace-tolerant) — matching the convention used in + ``litellm/__init__.py`` and the standard library's + ``configparser.BOOLEAN_STATES``. Unrecognised values log a + warning and fall back to ``default`` rather than silently + flipping user intent. + """ + raw = os.getenv(var_name) + if not raw: + return default + value = raw.strip().lower() + if value in ("1", "true", "yes", "on"): + return True + if value in ("0", "false", "no", "off"): + return False + verbose_logger.warning( + f"{var_name}={raw!r} is not a recognised boolean " + f"(accepts true/false, 1/0, yes/no, on/off). " + f"Falling back to default ({default})." + ) + return default + + def _get_litellm_version(self) -> str: + """ + Get litellm version for supportability metrics. + + Returns: + Version string (e.g., "1.80.0") or "unknown" if unable to determine + """ + try: + from importlib.metadata import version + + return version("litellm") + except Exception as e: + verbose_logger.warning(f"Unable to determine litellm version: {e}") + return "unknown" + + def _emit_supportability_metric(self): + """ + Emit New Relic supportability metric for LiteLLM usage. + + Per spec, this metric should be emitted at least once every 27 hours + to indicate the library is in use. Format: + Supportability/Python/ML/LiteLLM/{version} + + This method updates _last_metric_emission_time and should + be called within a lock when checking periodic emission. + """ + try: + litellm_version = self._get_litellm_version() + metric_name = f"Supportability/Python/ML/LiteLLM/{litellm_version}" + + # Record metric with value of 1 (will be aggregated by New Relic) + app = _newrelic_agent.application() + + # Always update the timestamp so the 27-hour back-off applies + # regardless of whether the app is ready, preventing lock contention + # on every request when the agent is slow to register or never starts. + NewRelicLogger._last_metric_emission_time = time.time() + + if app and app.enabled: + app.record_custom_metric(metric_name, 1) + verbose_logger.info( + f"Emitted New Relic supportability metric: {metric_name}" + ) + else: + verbose_logger.info( + "New Relic application is not enabled; skipping metric recording." + ) + + except Exception as e: + verbose_logger.warning(f"Failed to emit supportability metric: {e}") + + def _check_and_emit_periodic_metric(self): + """ + Check if 27 hours have passed since last metric emission and re-emit if needed. + + Uses a mutex to ensure only one thread emits the metric even if multiple + requests are being processed concurrently. + """ + # Quick check without lock to avoid unnecessary locking + current_time = time.time() + time_since_last_emission = ( + current_time - NewRelicLogger._last_metric_emission_time + ) + + if time_since_last_emission >= 97200: # 27 hours = 97200 seconds + # Acquire lock to ensure only one thread emits + with NewRelicLogger._metric_lock: + # Double-check inside lock in case another thread just emitted + current_time = time.time() + time_since_last_emission = ( + current_time - NewRelicLogger._last_metric_emission_time + ) + + if time_since_last_emission >= 97200: + self._emit_supportability_metric() + + def _get_trace_context( + self, + kwargs: Dict, + standard_logging_object: Optional[StandardLoggingPayload] = None, + ) -> str: + """ + Get the New Relic trace ID for AI monitoring events. + + This integration runs in LiteLLM's async logging worker, outside the + New Relic agent's current transaction. Because we can't call + `newrelic.agent.current_trace_id()` to let the agent populate the + trace_id on AIM custom events, we manually simulate what the agent + would do. An AIM event without a trace_id is malformed per the NR + schema, so this method always returns a valid string. + + Resolution order: + 1. W3C traceparent header (litellm_params.metadata.headers.traceparent) - + what the agent would link to if we were in-transaction. + 2. StandardLoggingPayload.trace_id - LiteLLM's internal trace for + retry/fallback grouping. + 3. Generated UUID - synthetic grouping key when upstream context is + absent or parsing it fails. + + Span IDs are intentionally not emitted: any span ID recoverable from + the inbound traceparent is the caller's parent span, not ours. + + Returns: + trace_id: always a non-empty string. + """ + trace_id: Optional[str] = None + try: + litellm_params = kwargs.get("litellm_params") or {} + metadata = litellm_params.get("metadata") or {} + headers = metadata.get("headers") or {} + # Normalize header key lookup to be case-insensitive per W3C spec + traceparent = next( + (v for k, v in headers.items() if k.lower() == "traceparent"), None + ) + + if traceparent: + # Extract trace_id from traceparent header if available + # traceparent format: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00" + parts = traceparent.split("-") + if len(parts) == 4: + trace_id = parts[1] + + if not trace_id and standard_logging_object: + slo_trace_id = standard_logging_object.get("trace_id") + if slo_trace_id: + trace_id = slo_trace_id + + except Exception as e: + verbose_logger.warning( + f"Unable to parse New Relic trace context from upstream sources: {e}" + ) + + if not trace_id: + trace_id = uuid.uuid4().hex + verbose_logger.debug( + f"New Relic trace_id not available from distributed tracing headers or " + f"StandardLoggingPayload. Generated trace_id={trace_id} for AI monitoring " + f"event grouping." + ) + + return trace_id + + def _extract_completion_id(self, kwargs: Dict, response_obj: ModelResponse) -> str: + """ + Extract completion ID from kwargs or response_obj, or generate one. + """ + completion_id = None + + if response_obj: + completion_id = response_obj.get("id") + + if not completion_id: + completion_id = kwargs.get("litellm_call_id") + + # If still not found, generate UUID and log warning per spec + if not completion_id: + completion_id = str(uuid.uuid4()) + + return completion_id + + def _get_vendor( + self, + kwargs: Dict, + standard_logging_object: Optional[StandardLoggingPayload] = None, + ) -> str: + """Extract vendor/provider, preferring StandardLoggingPayload.""" + if standard_logging_object: + vendor = standard_logging_object.get("custom_llm_provider") + if vendor: + return vendor + litellm_params = kwargs.get("litellm_params", {}) or {} + return litellm_params.get("custom_llm_provider") or "litellm" + + def _get_model_names( + self, + kwargs: Dict, + response_obj: ModelResponse, + standard_logging_object: Optional[StandardLoggingPayload] = None, + ) -> Tuple[str, str]: + """ + Extract request and response model names, preferring StandardLoggingPayload + for the request model. + + Returns: + Tuple of (request_model, response_model) + """ + request_model = None + if standard_logging_object: + slo_model = standard_logging_object.get("model") + if slo_model: + request_model = str(slo_model) + if not request_model: + request_model = str(kwargs.get("model") or "unknown") + response_model: str = str(response_obj.get("model") or request_model) + return request_model, response_model + + def _extract_usage( + self, + response_obj: ModelResponse, + standard_logging_object: Optional[StandardLoggingPayload] = None, + ) -> Dict[str, int]: + """Extract usage statistics, preferring StandardLoggingPayload.""" + if standard_logging_object: + prompt = standard_logging_object.get("prompt_tokens") + completion = standard_logging_object.get("completion_tokens") + total = standard_logging_object.get("total_tokens") + if any(x is not None for x in [prompt, completion, total]): + return { + "prompt_tokens": prompt or 0, + "completion_tokens": completion or 0, + "total_tokens": total or 0, + } + + usage = response_obj.get("usage", None) + if not usage: + return {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0} + + return { + "prompt_tokens": usage.get("prompt_tokens") or 0, + "completion_tokens": usage.get("completion_tokens") or 0, + "total_tokens": usage.get("total_tokens") or 0, + } + + def _get_finish_reason(self, response_obj: ModelResponse) -> str: + """ + Extract finish reason from first choice in the response. + + Returns "unknown" if choices are not present or finish_reason is not found. + """ + choices = response_obj.get("choices") or [] + if choices and len(choices) > 0: + return choices[0].get("finish_reason") or "unknown" + return "unknown" + + def _to_epoch_ms(self, t: Any) -> float: + """Convert a datetime or float timestamp to epoch milliseconds.""" + if hasattr(t, "timestamp"): + return t.timestamp() * 1000.0 + return float(t) * 1000.0 + + def _get_duration( + self, + kwargs: Dict, + start_time: Any, + end_time: Any, + standard_logging_object: Optional[StandardLoggingPayload] = None, + ) -> Optional[float]: + """ + Extract duration in milliseconds. + + Resolution order: + 1. StandardLoggingPayload.response_time (already computed by LiteLLM) + 2. llm_api_duration_ms from kwargs + 3. Calculated from start_time and end_time + """ + if standard_logging_object: + response_time = standard_logging_object.get("response_time") + if response_time is not None: + return ( + float(response_time) * 1000.0 + ) # SLO stores seconds; convert to ms + + duration_ms = kwargs.get("llm_api_duration_ms") + if duration_ms is not None: + return float(duration_ms) + + if start_time is not None and end_time is not None: + return self._to_epoch_ms(end_time) - self._to_epoch_ms(start_time) + + return None + + def _get_request_params( + self, + kwargs: Dict, + standard_logging_object: Optional[StandardLoggingPayload] = None, + ) -> Dict[str, Any]: + """ + Extract request parameters like temperature and max_tokens, preferring + StandardLoggingPayload.model_parameters. + + Returns dict with available parameters, omitting those not present. + """ + if standard_logging_object: + source_params = standard_logging_object.get("model_parameters") or {} + else: + source_params = kwargs.get("optional_params") or {} + + params = {} + + temperature = source_params.get("temperature") + if temperature is not None: + params["temperature"] = temperature + + max_tokens = source_params.get("max_tokens") + if max_tokens is not None: + params["max_tokens"] = max_tokens + + return params + + def _extract_message_content(self, message: Union[Message, Dict]) -> str: + """ + Extract content from a message, handling various formats. + + Handles tool calls, multimodal content (as JSON), and standard text content. + Returns empty string if content is None or missing. + """ + content = message.get("content") + + # Handle tool calls + if message.get("tool_calls"): + try: + return json.dumps(message["tool_calls"]) + except Exception: + return str(message["tool_calls"]) + + # Handle None or missing content + if content is None: + return "" + + # Handle list content (multimodal) + if isinstance(content, list): + try: + return json.dumps(content) + except Exception: + return str(content) + + # Handle non-string content + if not isinstance(content, str): + return str(content) + + return content + + def _extract_all_messages( + self, + kwargs: Dict, + response_obj: ModelResponse, + response_model: str, + vendor: str, + standard_logging_object: Optional[StandardLoggingPayload] = None, + ) -> List[Dict[str, Any]]: + """ + Extract all messages (request + response) with sequence numbers and timestamps. + + Processes request messages from StandardLoggingPayload.messages (preferred) or + kwargs["messages"] (fallback), and response messages from response_obj["choices"]. + Assigns sequential numbers starting at 0. + Adds timestamps from StandardLoggingPayload (preferred) or kwargs if available + (converted to epoch milliseconds). + """ + messages = [] + sequence = 0 + + # Extract timestamps, preferring StandardLoggingPayload + start_time = None + if standard_logging_object: + start_time = standard_logging_object.get("startTime") + if not start_time: + start_time = kwargs.get("start_time") + + end_time = None + if standard_logging_object: + end_time = standard_logging_object.get("endTime") + if not end_time: + end_time = kwargs.get("end_time") + + # Content is recorded only when the NR-specific switches allow it AND + # LiteLLM's wider redaction decision (turn_off_message_logging, dynamic + # params, headers) does not require redaction. Async streaming hands the + # callback an unredacted async_complete_streaming_response, so without + # this gate generated content would still reach NR even when the user + # has globally disabled message logging. + record_content = self.record_content and not should_redact_message_logging( + kwargs + ) + + # Extract request messages, preferring StandardLoggingPayload. + # SLO messages can be a string (serialized/redacted), so only use it when it's a list. + slo_messages = ( + standard_logging_object.get("messages") if standard_logging_object else None + ) + if isinstance(slo_messages, list): + request_messages = slo_messages + else: + request_messages = kwargs.get("messages") or [] + for msg in request_messages: + message_data = { + "role": msg.get("role") or "user", + "sequence": sequence, + "response.model": response_model, + "vendor": vendor, + } + + # Add timestamp for request message if available (convert to milliseconds) + if start_time is not None: + message_data["timestamp"] = int(self._to_epoch_ms(start_time)) + + if record_content: + message_data["content"] = self._extract_message_content(msg) + + messages.append(message_data) + sequence += 1 + + # Extract response messages from choices + choices = response_obj.get("choices") or [] + if choices and len(choices) > 0: + for choice in choices: + # Prefer "message" (non-streaming); fall back to "delta" (streaming-assembled) + message = choice.get("message", None) or choice.get("delta", None) + if message: + message_data = { + "role": message.get("role") or "assistant", + "sequence": sequence, + "response.model": response_model, + "vendor": vendor, + "is_response": True, + } + + # Add timestamp for response message if available (convert to milliseconds) + if end_time is not None: + message_data["timestamp"] = int(self._to_epoch_ms(end_time)) + + if record_content: + message_data["content"] = self._extract_message_content(message) + + messages.append(message_data) + sequence += 1 + + return messages + + def _record_summary_event( + self, + request_id: str, + trace_id: Optional[str], + request_model: str, + response_model: str, + vendor: str, + finish_reason: str, + num_messages: int, + usage: Dict[str, int], + duration: Optional[float] = None, + request_params: Optional[Dict[str, Any]] = None, + ): + """Record LlmChatCompletionSummary event to New Relic.""" + try: + event_data = { + "id": request_id, + "request_id": request_id, + "request.model": request_model, + "response.model": response_model, + "response.choices.finish_reason": finish_reason, + "response.number_of_messages": num_messages, + "vendor": vendor, + "ingest_source": "litellm", + "response.usage.prompt_tokens": usage["prompt_tokens"], + "response.usage.completion_tokens": usage["completion_tokens"], + "response.usage.total_tokens": usage["total_tokens"], + } + + # Add optional attributes if present + if trace_id: + event_data["trace_id"] = trace_id + + if duration is not None: + event_data["duration"] = duration + + # Add request parameters if present + if request_params: + if "temperature" in request_params: + event_data["request.temperature"] = request_params["temperature"] + if "max_tokens" in request_params: + event_data["request.max_tokens"] = request_params["max_tokens"] + + app = _newrelic_agent.application() + + if app and app.enabled: + app.record_custom_event("LlmChatCompletionSummary", event_data) + else: + verbose_logger.warning( + "New Relic application is not enabled; skipping summary event recording." + ) + + except Exception as e: + verbose_logger.warning(f"Failed to record New Relic summary event: {e}") + self.handle_callback_failure("newrelic") + + def _record_message_events( + self, + request_id: str, + llm_response_id: str, + trace_id: Optional[str], + messages: List[Dict[str, Any]], + ): + """Record LlmChatCompletionMessage events to New Relic. + + Args: + request_id: Agent-generated UUID that links to Summary event's id + llm_response_id: LLM's response ID (e.g., "chatcmpl-...") for message id format + trace_id: Trace ID for distributed tracing (None if not available) + messages: List of message dicts to record + """ + try: + app = _newrelic_agent.application() + + if not (app and app.enabled): + verbose_logger.warning( + "New Relic application is not enabled; skipping message event recording." + ) + return + + for message in messages: + sequence = message["sequence"] + event_data = { + "id": f"{llm_response_id}-{sequence}", + "request_id": request_id, + "completion_id": request_id, + "role": message["role"], + "sequence": sequence, + "response.model": message["response.model"], + "vendor": message["vendor"], + "ingest_source": "litellm", + "token_count": 0, # Per-message token counts are not available from LiteLLM + } + + # Add trace context if available + if trace_id: + event_data["trace_id"] = trace_id + + # Add content only if it was included in the message data + if "content" in message: + event_data["content"] = message["content"] + + # Add is_response only if True (per spec, omit for request messages) + if message.get("is_response"): + event_data["is_response"] = True + + # Forward actual request/response timestamp (ms) so NR uses the + # real LLM call window rather than the async-logger fire time. + # Requires newrelic>=11.2.0 which reads params["timestamp"] as + # the intrinsic event timestamp. + if "timestamp" in message: + event_data["timestamp"] = message["timestamp"] + + app.record_custom_event("LlmChatCompletionMessage", event_data) + + except Exception as e: + verbose_logger.warning(f"Failed to record New Relic message events: {e}") + self.handle_callback_failure("newrelic") + + def _record_error_metric(self): + """Record error metric to New Relic.""" + try: + if not self.enabled: + return + + self._check_and_emit_periodic_metric() + + app = _newrelic_agent.application() + if app and app.enabled: + app.record_custom_metric("LLM/LiteLLM/Error", 1) + except Exception as e: + verbose_logger.warning(f"Failed to record New Relic error metric: {e}") + self.handle_callback_failure("newrelic") + + def _process_success( + self, + kwargs: Dict, + response_obj: ModelResponse, + start_time: Optional[float] = None, + end_time: Optional[float] = None, + ): + """ + Core logic for processing successful LLM calls. + Used by both sync and async success event handlers. + """ + # Early exit if not enabled + if not self.enabled: + return + + # Check and emit periodic supportability metric if 27 hours have passed + self._check_and_emit_periodic_metric() + + # Use StandardLoggingPayload where available for normalized, pre-computed values + standard_logging_object: Optional[StandardLoggingPayload] = kwargs.get( + "standard_logging_object" + ) + + # Get trace context + trace_id = self._get_trace_context(kwargs, standard_logging_object) + + # Generate unique request ID for this request (used as Summary event id) + request_id = str(uuid.uuid4()) + + # Extract data from response + llm_response_id = self._extract_completion_id(kwargs, response_obj) + vendor = self._get_vendor(kwargs, standard_logging_object) + request_model, response_model = self._get_model_names( + kwargs, response_obj, standard_logging_object + ) + usage = self._extract_usage(response_obj, standard_logging_object) + finish_reason = self._get_finish_reason(response_obj) + + # Extract additional summary event fields + duration = self._get_duration( + kwargs, start_time, end_time, standard_logging_object + ) + request_params = self._get_request_params(kwargs, standard_logging_object) + + # Extract all messages + messages = self._extract_all_messages( + kwargs, response_obj, response_model, vendor, standard_logging_object + ) + + # Record summary event + self._record_summary_event( + request_id=request_id, + trace_id=trace_id, + request_model=request_model, + response_model=response_model, + vendor=vendor, + finish_reason=finish_reason, + num_messages=len(messages), + usage=usage, + duration=duration, + request_params=request_params, + ) + + # Record message events + self._record_message_events( + request_id=request_id, + llm_response_id=llm_response_id, + trace_id=trace_id, + messages=messages, + ) + + async def async_health_check(self) -> IntegrationHealthCheckStatus: + """ + Check if the New Relic integration is healthy. + + Verifies that the integration is enabled and the New Relic agent + has an active, connected application, then records a small + `LiteLLMConnectionTest` custom event so the user can confirm the + end-to-end pipeline in the New Relic UI via NRQL: + `SELECT * FROM LiteLLMConnectionTest SINCE 1 hour ago`. + + The `LiteLLMConnectionTest` event type is intentionally outside the + `Llm*` family that AI Monitoring queries, so test events do not + appear in AI Monitoring dashboards. + """ + if not self.enabled: + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message="New Relic integration is disabled. Check that " + "NEW_RELIC_LICENSE_KEY and NEW_RELIC_APP_NAME are set and the " + "newrelic package is installed.", + ) + + try: + app = _newrelic_agent.application() + if not (app and app.enabled): + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message=( + "New Relic Python agent not installed. Review the New Relic integration documentation at https://docs.litellm.ai/docs/observability/newrelic." + ), + ) + + app.record_custom_event( + "LiteLLMConnectionTest", + { + "is_test_event": True, + "app_name": self.app_name, + "source": "litellm-proxy", + "timestamp": time.time(), + }, + ) + return IntegrationHealthCheckStatus(status="healthy", error_message=None) + except Exception as e: + return IntegrationHealthCheckStatus( + status="unhealthy", + error_message=str(e), + ) + + # CustomLogger interface implementation + + def log_pre_api_call(self, model, messages, kwargs): + """Unused per spec.""" + pass + + def log_post_api_call(self, kwargs, response_obj, start_time, end_time): + """Unused per spec.""" + pass + + def log_success_event(self, kwargs, response_obj, start_time, end_time): + """ + Main success path for non-streaming requests. + + Note: New Relic's record_custom_event is synchronous but non-blocking + (in-memory operation), so it's safe to call from sync context. + """ + try: + self._process_success(kwargs, response_obj, start_time, end_time) + except Exception as e: + verbose_logger.warning(f"Error in New Relic log_success_event: {e}") + self.handle_callback_failure("newrelic") + + async def async_log_success_event(self, kwargs, response_obj, start_time, end_time): + """ + Main success path for async/streaming requests. + + Note: New Relic's SDK is thread-safe and record_custom_event is fast, + so we can call it directly without asyncio.to_thread(). + """ + try: + self._process_success(kwargs, response_obj, start_time, end_time) + except Exception as e: + verbose_logger.warning(f"Error in New Relic async_log_success_event: {e}") + self.handle_callback_failure("newrelic") + + def log_failure_event(self, kwargs, response_obj, start_time, end_time): + """ + Log error metric for failed LLM calls (sync). + + Per spec: Do not send AI events on failure, only record error metric. + """ + try: + self._record_error_metric() + + except Exception as e: + verbose_logger.warning(f"Error in New Relic log_failure_event: {e}") + self.handle_callback_failure("newrelic") + + async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time): + """ + Log error metric for failed LLM calls (async). + + Per spec: Do not send AI events on failure, only record error metric. + """ + try: + self._record_error_metric() + + except Exception as e: + verbose_logger.warning(f"Error in New Relic async_log_failure_event: {e}") + self.handle_callback_failure("newrelic") diff --git a/litellm/integrations/opentelemetry.py b/litellm/integrations/opentelemetry.py index 24780eb4bfc..6b50ef49b49 100644 --- a/litellm/integrations/opentelemetry.py +++ b/litellm/integrations/opentelemetry.py @@ -1,7 +1,18 @@ import os from dataclasses import dataclass, field from datetime import datetime -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union, cast +from typing import ( + TYPE_CHECKING, + Any, + Dict, + FrozenSet, + List, + Optional, + Set, + Tuple, + Union, + cast, +) import litellm from litellm._logging import verbose_logger @@ -82,6 +93,88 @@ _VALID_CAPTURE_MODES = { CAPTURE_MODE_SPAN_AND_EVENT, } +METRIC_METADATA_KEYS: Tuple[str, ...] = ( + "user_api_key_hash", + "user_api_key_alias", + "user_api_key_team_id", + "user_api_key_org_id", + "user_api_key_user_id", + "user_api_key_team_alias", + "user_api_key_user_email", + "spend_logs_metadata", + "requester_ip_address", + "requester_metadata", + "user_api_key_end_user_id", + "prompt_management_metadata", + "applied_guardrails", + "mcp_tool_call_metadata", + "vector_store_request_metadata", +) + +TOKEN_TYPE_ATTRIBUTE: str = "gen_ai.token.type" + +VALID_METRIC_ATTRIBUTE_NAMES: FrozenSet[str] = frozenset( + ( + "gen_ai.operation.name", + "gen_ai.system", + "gen_ai.request.model", + "gen_ai.framework", + "hidden_params", + ) + + tuple(f"metadata.{key}" for key in METRIC_METADATA_KEYS) +) + + +@dataclass(frozen=True) +class OTELMetricAttributeFilter: + include_list: Optional[List[str]] = None + exclude_list: Optional[List[str]] = None + + +def _build_metric_attribute_filter(value: Any) -> OTELMetricAttributeFilter: + if isinstance(value, OTELMetricAttributeFilter): + return value + if not isinstance(value, dict): + raise ValueError( + "otel.attributes must be a mapping with optional 'include_list' / " + f"'exclude_list', got {type(value).__name__}" + ) + return OTELMetricAttributeFilter( + include_list=value.get("include_list"), + exclude_list=value.get("exclude_list"), + ) + + +def _resolve_metric_attribute_filter( + attributes: Optional[OTELMetricAttributeFilter], +) -> Tuple[Optional[FrozenSet[str]], Optional[FrozenSet[str]]]: + if attributes is None: + return None, None + include = attributes.include_list or None + exclude = attributes.exclude_list or None + if include and exclude: + raise ValueError( + "otel.attributes: include_list and exclude_list are mutually exclusive" + ) + requested = include or exclude or [] + if TOKEN_TYPE_ATTRIBUTE in requested: + raise ValueError( + f"otel.attributes: {TOKEN_TYPE_ATTRIBUTE} is a structural token-usage " + "discriminator and cannot be filtered" + ) + unknown = sorted( + name for name in requested if name not in VALID_METRIC_ATTRIBUTE_NAMES + ) + if unknown: + raise ValueError( + f"otel.attributes: unknown attribute name(s) {unknown}. " + f"Valid names: {sorted(VALID_METRIC_ATTRIBUTE_NAMES)}" + ) + return ( + frozenset(include) if include else None, + frozenset(exclude) if exclude else None, + ) + def _normalize_team_metadata_keys(value: Any) -> List[str]: """Coerce a team-metadata allowlist from a list or comma-separated string. @@ -117,6 +210,9 @@ class OpenTelemetryConfig: # under ``litellm.team.metadata``. Empty by default so none of a team's # metadata leaves the process until explicitly allowlisted. baggage_team_metadata_keys: List[str] = field(default_factory=list) + # Prometheus-style include/exclude control over which attributes are stamped + # on emitted metrics, to cap metric cardinality. + attributes: Optional[OTELMetricAttributeFilter] = None def __post_init__(self) -> None: # If endpoint is specified but exporter is still the default "console", @@ -211,15 +307,29 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger): **kwargs, ): team_metadata_keys_override = kwargs.pop("baggage_team_metadata_keys", None) + metric_attributes_override = kwargs.pop("attributes", None) if config is None: config = OpenTelemetryConfig.from_env() if team_metadata_keys_override is not None: config.baggage_team_metadata_keys = _normalize_team_metadata_keys( team_metadata_keys_override ) + if metric_attributes_override is not None: + config.attributes = _build_metric_attribute_filter( + metric_attributes_override + ) self.config = config self.callback_name = callback_name + # Resolved on first metric record, not here: the proxy populates + # callback_settings.otel.attributes after this logger is constructed, so + # reading it now would miss it. An explicit config is validated eagerly so + # a bad config still fails at startup. + self._metric_attr_include: Optional[FrozenSet[str]] = None + self._metric_attr_exclude: Optional[FrozenSet[str]] = None + self._metric_attr_filter_resolved = False + if config.attributes is not None: + self._ensure_metric_attribute_filter() self.OTEL_EXPORTER = self.config.exporter self.OTEL_ENDPOINT = self.config.endpoint self.OTEL_HEADERS = self.config.headers @@ -1318,6 +1428,38 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger): return None return safe_dumps(filtered) + def _ensure_metric_attribute_filter(self) -> None: + """Resolve the include/exclude filter once, falling back to the proxy's + callback_settings.otel.attributes when no explicit config was passed.""" + if self._metric_attr_filter_resolved: + return + attributes = self.config.attributes + if attributes is None and self.callback_name in (None, "otel"): + otel_settings = (litellm.callback_settings or {}).get("otel") or {} + raw = ( + otel_settings.get("attributes") + if isinstance(otel_settings, dict) + else None + ) + if raw is not None: + attributes = _build_metric_attribute_filter(raw) + ( + self._metric_attr_include, + self._metric_attr_exclude, + ) = _resolve_metric_attribute_filter(attributes) + self._metric_attr_filter_resolved = True + + def _filter_metric_attributes(self, attrs: Dict[str, Any]) -> Dict[str, Any]: + if not self._metric_attr_filter_resolved: + self._ensure_metric_attribute_filter() + if self._metric_attr_include is not None: + return {k: v for k, v in attrs.items() if k in self._metric_attr_include} + if self._metric_attr_exclude is not None: + return { + k: v for k, v in attrs.items() if k not in self._metric_attr_exclude + } + return attrs + def _record_metrics(self, kwargs, response_obj, start_time, end_time): duration_s = (end_time - start_time).total_seconds() params = kwargs.get("litellm_params") or {} @@ -1336,23 +1478,7 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger): std_log = kwargs.get("standard_logging_object") md = getattr(std_log, "metadata", None) or (std_log or {}).get("metadata", {}) - for key in [ - "user_api_key_hash", - "user_api_key_alias", - "user_api_key_team_id", - "user_api_key_org_id", - "user_api_key_user_id", - "user_api_key_team_alias", - "user_api_key_user_email", - "spend_logs_metadata", - "requester_ip_address", - "requester_metadata", - "user_api_key_end_user_id", - "prompt_management_metadata", - "applied_guardrails", - "mcp_tool_call_metadata", - "vector_store_request_metadata", - ]: + for key in METRIC_METADATA_KEYS: value = md.get(key) if value is None: continue @@ -1368,6 +1494,8 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger): if hidden_params: common_attrs["hidden_params"] = safe_dumps(hidden_params) + common_attrs = self._filter_metric_attributes(common_attrs) + if self._operation_duration_histogram: self._operation_duration_histogram.record( duration_s, attributes=common_attrs @@ -1377,8 +1505,8 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger): and (usage := response_obj.get("usage")) and self._token_usage_histogram ): - in_attrs = {**common_attrs, "gen_ai.token.type": "input"} - out_attrs = {**common_attrs, "gen_ai.token.type": "output"} + in_attrs = {**common_attrs, TOKEN_TYPE_ATTRIBUTE: "input"} + out_attrs = {**common_attrs, TOKEN_TYPE_ATTRIBUTE: "output"} self._token_usage_histogram.record( usage.get("prompt_tokens", 0), attributes=in_attrs ) @@ -2070,9 +2198,7 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger): return kv_pairs - def set_attributes( # noqa: PLR0915 - self, span: Span, kwargs, response_obj: Optional[Any] - ): + def set_attributes(self, span: Span, kwargs, response_obj: Optional[Any]): try: if self.callback_name == "langtrace": from litellm.integrations.langtrace import LangtraceAttributes diff --git a/litellm/integrations/otel/README.md b/litellm/integrations/otel/README.md index 3edb96ed8d9..17011bb8db7 100644 --- a/litellm/integrations/otel/README.md +++ b/litellm/integrations/otel/README.md @@ -216,7 +216,13 @@ lives in [`plumbing/`](./plumbing): `TracerProvider` so one logger serves many tenants. The cache is a bounded LRU that flushes + shuts down evicted providers, since the key derives from request-supplied credentials and must not grow (or leak threads) without limit. -- [`metrics.py`](./plumbing/metrics.py) — GenAI client metric instruments. +- [`metrics.py`](./plumbing/metrics.py) — GenAI client metric instruments. The + six `gen_ai.client.*` histograms are recorded through the meter resolved by + `providers.resolve_meter_provider`: an injected provider wins (tests/DI), + otherwise the operator's globally configured `MeterProvider` is reused so its + readers/exporters receive them alongside the server metrics, and one is built + and registered as the global only when none is set (mirroring how V2 owns trace + export). ### Adapter diff --git a/litellm/integrations/otel/emitter.py b/litellm/integrations/otel/emitter.py index 7fb7be7ab84..6feaf2734e9 100644 --- a/litellm/integrations/otel/emitter.py +++ b/litellm/integrations/otel/emitter.py @@ -17,7 +17,7 @@ from litellm.integrations.otel.model.payloads import ( ServiceSpanData, ) from litellm.integrations.otel.plumbing.providers import to_otel_span_kind -from litellm.integrations.otel.model.semconv import Error +from litellm.integrations.otel.model.semconv import Error, ExceptionEvent from litellm.integrations.otel.model.spans import ( SPAN_REGISTRY, SpanRole, @@ -179,9 +179,17 @@ class SpanEmitter: else None ) if error and (error.error_type or error.message): - span.set_attribute(Error.TYPE, error.error_type or "error") - span.set_status( - Status(StatusCode.ERROR, error.message or error.error_type or "error") + error_type = error.error_type or "error" + message = error.message or error.error_type or "error" + span.set_attribute(Error.TYPE, error_type) + span.set_status(Status(StatusCode.ERROR, message)) + # Carry the full message on the standard ``exception`` event so backends + # map it as full text under ``exception.message``. Setting it as a bare + # string attribute instead lets backends like Elasticsearch dynamic-map + # it to a ``keyword`` capped at 1024 chars, truncating the message. + span.add_event( + ExceptionEvent.NAME, + {ExceptionEvent.TYPE: error_type, ExceptionEvent.MESSAGE: message}, ) # On success leave the status UNSET (the semconv default) rather than # forcing OK — that matches the FastAPI server span and avoids implying a diff --git a/litellm/integrations/otel/logger.py b/litellm/integrations/otel/logger.py index 5e683ce7b99..79931c0796c 100644 --- a/litellm/integrations/otel/logger.py +++ b/litellm/integrations/otel/logger.py @@ -3,13 +3,14 @@ from collections import OrderedDict from contextlib import contextmanager from datetime import datetime -from typing import TYPE_CHECKING, Any, Iterator, Mapping, cast +from typing import TYPE_CHECKING, Any, Callable, Iterator, Mapping, Sequence, cast from opentelemetry.context import attach, get_current from opentelemetry.sdk.trace import TracerProvider from opentelemetry.trace import Span, Tracer, get_current_span, use_span import litellm +from litellm._logging import verbose_logger from litellm.integrations.custom_logger import CustomLogger from litellm.integrations.otel.model.baggage import promoted_baggage from litellm.integrations.otel.model.config import OpenTelemetryV2Config @@ -36,9 +37,15 @@ from litellm.integrations.otel.model.payloads import ( SpanError, is_mcp_tool_call, ) +from litellm.integrations.otel.plumbing.metrics import ( + GenAIMetricRecorder, + create_genai_metrics, +) from litellm.integrations.otel.plumbing.providers import ( build_tracer_provider, + get_meter, get_tracer, + resolve_meter_provider, ) from litellm.integrations.otel.plumbing.routing import TenantTracerCache from litellm.integrations.otel.model.spans import SpanRole, span_role_for_service @@ -95,7 +102,7 @@ class OpenTelemetryV2(CustomLogger): callback_name: str | None = None, tracer_provider: TracerProvider | None = None, logger_provider: Any | None = None, # reserved for OTel logs - meter_provider: Any | None = None, # reserved for metrics + meter_provider: Any | None = None, **kwargs: Any, ) -> None: super().__init__(**kwargs) @@ -107,6 +114,8 @@ class OpenTelemetryV2(CustomLogger): else build_tracer_provider(self.config) ) self.tracer: Tracer = get_tracer(self._tracer_provider, LITELLM_TRACER_NAME) + self._metrics_recorder = self._init_metrics(meter_provider) + self._metric_filter_error_logged = False self._emitter = SpanEmitter( self.tracer, self.config, mappers=resolve_mappers(self.config.mapper_names) ) @@ -116,6 +125,20 @@ class OpenTelemetryV2(CustomLogger): self._open_llm_calls: "OrderedDict[str, _LLMCallSpan]" = OrderedDict() self._init_otel_logger_on_litellm_proxy() + def _init_metrics(self, meter_provider: Any | None) -> "GenAIMetricRecorder | None": + """Create the six GenAI histograms when metrics are enabled, else ``None``. + + ``meter_provider`` is an explicit override (tests inject one); otherwise the + provider is resolved from the OTel global so the operator's configured + readers/exporters receive the metrics, building and registering one only + when no global provider is set. + """ + if not self.config.enable_metrics: + return None + provider = resolve_meter_provider(self.config, meter_provider) + meter = get_meter(provider, LITELLM_TRACER_NAME) + return GenAIMetricRecorder(create_genai_metrics(meter), self.callback_name) + # ====================================================================== # # Proxy global registration # ====================================================================== # @@ -208,6 +231,25 @@ class OpenTelemetryV2(CustomLogger): if self._emit_mcp_tool_call(kwargs, start_time, end_time): return self._close_llm_call(kwargs, start_time, end_time) + self._record_metrics(kwargs, response_obj, start_time, end_time) + + def _record_metrics(self, kwargs, response_obj, start_time, end_time) -> None: + """Record the GenAI metrics for a successful LLM call. Best-effort: a + recording failure (e.g. a malformed payload) must never break the span + close or the request itself.""" + if self._metrics_recorder is None: + return + try: + self._metrics_recorder.record(kwargs, response_obj, start_time, end_time) + except ValueError as exc: + if not self._metric_filter_error_logged: + verbose_logger.error( + "OpenTelemetryV2: invalid otel.attributes metric filter, metrics disabled: %s", + exc, + ) + self._metric_filter_error_logged = True + except Exception as exc: + verbose_logger.debug("OpenTelemetryV2: metric recording failed: %s", exc) async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time): if self._emit_mcp_tool_call(kwargs, start_time, end_time): @@ -504,6 +546,58 @@ class OpenTelemetryV2(CustomLogger): return span +def select_global_otel_v2_logger( + in_memory_loggers: Sequence[object], + registered: "OpenTelemetryV2 | None" = None, +) -> "OpenTelemetryV2": + """The single ``OpenTelemetryV2`` whose provider should become the OTel global. + + The callback factory designates one logger as canonical the moment it builds + the first one (``_init_otel_logger_on_litellm_proxy`` sets + ``proxy_server.open_telemetry_logger``), and every other v2 entry point — + guardrail, identity seeding, phase spans — already routes through that same + ``registered`` owner. Reuse it here too so the global provider has one source + of truth instead of a second, independently-derived guess; this is the logger + a preset (arize, langfuse, …) folds the ``OTEL_*`` base exporter and its own + exporter into, so the FastAPI server span and the gen-ai spans share one + provider and one trace. + + Fall back to ``in_memory_loggers`` for the SDK path, where no proxy global is + set (selecting from there, not ``service_callback``, which a preset logger does + not always reach), and build a generic logger from ``OTEL_*`` only when none was + configured at all. Each fallback still avoids the second generic logger that + orphaned the gen-ai spans onto a different backend than the server span. + """ + if registered is not None: + return registered + existing = next( + (cb for cb in in_memory_loggers if isinstance(cb, OpenTelemetryV2)), None + ) + return existing if existing is not None else OpenTelemetryV2() + + +def publish_global_otel_v2_provider( + in_memory_loggers: Sequence[object], + set_global_provider: Callable[[TracerProvider], None], + registered: "OpenTelemetryV2 | None" = None, +) -> "OpenTelemetryV2": + """Select the single v2 logger and publish its provider as the OTel global. + + The proxy calls this once at startup, after callbacks are initialized, so the + preset logger already exists; it passes ``registered`` (the canonical owner the + factory designated as ``proxy_server.open_telemetry_logger``) so the global + provider reuses the same logger the rest of the v2 code emits through (see + :func:`select_global_otel_v2_logger`). Both ``registered`` and + ``set_global_provider`` (the proxy passes + ``opentelemetry.trace.set_tracer_provider``) are injected so the publish step is + unit-testable without reading or mutating real global OTel state. Returns the + logger whose provider was published. + """ + logger = select_global_otel_v2_logger(in_memory_loggers, registered=registered) + set_global_provider(logger._tracer_provider) + return logger + + def _registered_v2_logger() -> "OpenTelemetryV2 | None": try: from litellm.proxy import proxy_server diff --git a/litellm/integrations/otel/mappers/genai.py b/litellm/integrations/otel/mappers/genai.py index 6c61feced4d..d9be68a06c2 100644 --- a/litellm/integrations/otel/mappers/genai.py +++ b/litellm/integrations/otel/mappers/genai.py @@ -10,7 +10,12 @@ table: one lambda per mapping operation, applied against the typed span data. from typing import Callable from litellm.integrations.otel.mappers.base import AttributeMap, AttrValue, SpanData -from litellm.integrations.otel.mappers.utils import collect, drop_none +from litellm.integrations.otel.mappers.utils import ( + collect, + drop_none, + output_messages, + serialize_messages, +) from litellm.integrations.otel.model.payloads import ( GuardrailSpanData, LLMCallSpanData, @@ -47,6 +52,8 @@ class GenAIMapper: else None ), GenAI.REQUEST_SEED: lambda d: d.request_params.seed, + GenAI.INPUT_MESSAGES: lambda d: serialize_messages(d.messages_in), + GenAI.OUTPUT_MESSAGES: lambda d: serialize_messages(output_messages(d)), GenAI.RESPONSE_MODEL: lambda d: d.response_model, GenAI.RESPONSE_ID: lambda d: d.response_id, GenAI.RESPONSE_FINISH_REASONS: lambda d: ( @@ -63,6 +70,20 @@ class GenAIMapper: # routing) onto the boundary-born LLM span — stamp it directly here. LiteLLM.PROVIDER_MODEL: lambda d: d.identity.provider_model or None, f"{LiteLLM.COST_PREFIX}total": lambda d: d.response_cost, + # Per-component cost breakdown (from the StandardLoggingPayload + # ``cost_breakdown``). Each component is omitted when the source didn't + # report it, so spans stay sparse rather than carrying zeros. + f"{LiteLLM.COST_PREFIX}input": lambda d: d.cost.input, + f"{LiteLLM.COST_PREFIX}output": lambda d: d.cost.output, + f"{LiteLLM.COST_PREFIX}cache_read": lambda d: d.cost.cache_read, + f"{LiteLLM.COST_PREFIX}cache_creation": lambda d: d.cost.cache_creation, + f"{LiteLLM.COST_PREFIX}tool_usage": lambda d: d.cost.tool_usage, + f"{LiteLLM.COST_PREFIX}original": lambda d: d.cost.original, + f"{LiteLLM.COST_PREFIX}discount_amount": lambda d: d.cost.discount_amount, + f"{LiteLLM.COST_PREFIX}discount_percent": lambda d: d.cost.discount_percent, + f"{LiteLLM.COST_PREFIX}margin_fixed_amount": lambda d: d.cost.margin_fixed_amount, + f"{LiteLLM.COST_PREFIX}margin_percent": lambda d: d.cost.margin_percent, + f"{LiteLLM.COST_PREFIX}margin_total_amount": lambda d: d.cost.margin_total_amount, LiteLLM.REQUEST_STREAMING: lambda d: d.is_streaming, } diff --git a/litellm/integrations/otel/model/config.py b/litellm/integrations/otel/model/config.py index ca46182bc66..a109ba898ff 100644 --- a/litellm/integrations/otel/model/config.py +++ b/litellm/integrations/otel/model/config.py @@ -1,5 +1,6 @@ """Typed configuration for the OpenTelemetry instrumentation.""" +from enum import Enum from typing import Any, List from pydantic import AliasChoices, BaseModel, Field, field_validator, model_validator @@ -23,6 +24,23 @@ class CaptureMessageContent(str): SPAN_AND_EVENT = "span_and_event" +class ExporterOwner(str, Enum): + """The preset that contributed an exporter. Values match the callback names + in ``presets.PRESET_BY_CALLBACK`` so per-request dynamic-credential routing + can match an exporter's owner against the credential source's callback name. + A ``str`` enum so the value compares equal to the bare callback-name string.""" + + # Arize AX (the hosted platform) and Arize Phoenix (the open-source / Phoenix + # Cloud tracer) are distinct backends with separate config and auth, so they + # are separate owners. The member value stays the public callback name. + ARIZE_AX = "arize" + ARIZE_PHOENIX = "arize_phoenix" + LANGFUSE_OTEL = "langfuse_otel" + WEAVE_OTEL = "weave_otel" + LEVO = "levo" + AGENTOPS = "agentops" + + class _OTelV2Flag(BaseSettings): model_config = SettingsConfigDict(extra="ignore") @@ -49,6 +67,15 @@ class ExporterSpec(BaseModel): ) endpoint: str | None = None headers: str | None = None + owner: ExporterOwner | None = Field( + default=None, + description=( + "The preset that contributed this exporter. Per-request dynamic OTLP " + "credentials are applied only to the exporter whose owner matches the " + "credential source, so one tenant's vendor key never lands on a " + "different backend's exporter." + ), + ) options: dict[str, str] | None = Field( default=None, description=( @@ -184,6 +211,20 @@ class OpenTelemetryV2Config(BaseSettings): ), ) + @field_validator("capture_message_content", mode="before") + @classmethod + def _normalize_capture_message_content(cls, value: object) -> object: + """Fold the capture mode to its canonical lower_snake_case form. + + V1 read this env var case-insensitively, so operators set the + UPPER_SNAKE_CASE form (e.g. ``SPAN_AND_EVENT``). The canonical values + here are lower_snake_case; normalizing at the boundary keeps both + spellings working and lets every downstream comparison stay exact. + """ + if isinstance(value, str): + return value.lower() + return value + @field_validator( "baggage_promoted_keys", "baggage_metadata_keys", diff --git a/litellm/integrations/otel/model/payloads.py b/litellm/integrations/otel/model/payloads.py index bbef40ba374..82b7df5922c 100644 --- a/litellm/integrations/otel/model/payloads.py +++ b/litellm/integrations/otel/model/payloads.py @@ -34,6 +34,7 @@ __all__ = [ "RequestIdentity", "GuardrailSpanData", "LLMCallSpanData", + "LLMCost", "LLMRequestParams", "LLMUsage", "MCPToolCallSpanData", @@ -91,6 +92,49 @@ class LLMUsage: total_tokens: int | None = None +@dataclass(frozen=True) +class LLMCost: + """Per-component cost breakdown, from the StandardLoggingPayload + ``cost_breakdown`` (``litellm.types.utils.CostBreakdown``). + + Each field is the USD cost of one component, or ``None`` when the source did + not report it — so the mapper omits absent components instead of emitting 0. + The final (post-discount/post-margin) total is carried separately on + ``LLMCallSpanData.response_cost``. Free-form ``additional_costs`` are not + surfaced here: span attributes are scalar and there is no agreed key shape + for them yet. + """ + + input: float | None = None + output: float | None = None + cache_read: float | None = None + cache_creation: float | None = None + tool_usage: float | None = None + original: float | None = None + discount_amount: float | None = None + discount_percent: float | None = None + margin_fixed_amount: float | None = None + margin_percent: float | None = None + margin_total_amount: float | None = None + + @classmethod + def from_breakdown(cls, breakdown: Mapping[str, object] | None) -> "LLMCost": + b = breakdown or {} + return cls( + input=as_float(b.get("input_cost")), + output=as_float(b.get("output_cost")), + cache_read=as_float(b.get("cache_read_cost")), + cache_creation=as_float(b.get("cache_creation_cost")), + tool_usage=as_float(b.get("tool_usage_cost")), + original=as_float(b.get("original_cost")), + discount_amount=as_float(b.get("discount_amount")), + discount_percent=as_float(b.get("discount_percent")), + margin_fixed_amount=as_float(b.get("margin_fixed_amount")), + margin_percent=as_float(b.get("margin_percent")), + margin_total_amount=as_float(b.get("margin_total_amount")), + ) + + @dataclass(frozen=True) class SpanError: error_type: str | None = None @@ -255,6 +299,7 @@ class LLMCallSpanData: server: ServerInfo | None identity: RequestIdentity is_streaming: bool | None = None + cost: LLMCost = field(default_factory=LLMCost) tools: tuple[ToolDefinition, ...] = () # Raw messages and response, needed by vendor mappers (OpenInference, # Langfuse, Weave) that stamp message-level attributes. ``messages_in`` is @@ -302,6 +347,9 @@ class LLMCallSpanData: finish_reasons=finish_reasons, error=_parse_error(payload), response_cost=as_float(payload.get("response_cost")), + cost=LLMCost.from_breakdown( + cast("Mapping[str, object] | None", payload.get("cost_breakdown")) + ), server=ServerInfo.from_api_base(context.api_base), identity=context.identity, is_streaming=as_bool(payload.get("stream")), diff --git a/litellm/integrations/otel/model/semconv.py b/litellm/integrations/otel/model/semconv.py index 7df07f30a01..6315a5a4a89 100644 --- a/litellm/integrations/otel/model/semconv.py +++ b/litellm/integrations/otel/model/semconv.py @@ -146,6 +146,21 @@ class Error: TYPE: Final = "error.type" +class ExceptionEvent: + """OTel exception-event name and attribute keys (semconv ``exception.*``). + + The full error message rides ``exception.message`` on a span event rather than + a custom string attribute. Backends recognise these semantic-convention names + and map them as full text; an unrecognised key (e.g. ``error_message``) falls + into the default dynamic template, which truncates strings to a 1024-char + ``keyword``. + """ + + NAME: Final = "exception" + TYPE: Final = "exception.type" + MESSAGE: Final = "exception.message" + + class Server: ADDRESS: Final = "server.address" PORT: Final = "server.port" @@ -215,6 +230,10 @@ class Metric: TOKEN_USAGE: Final = "gen_ai.client.token.usage" OPERATION_DURATION: Final = "gen_ai.client.operation.duration" + TOKEN_COST: Final = "gen_ai.client.token.cost" + TIME_TO_FIRST_TOKEN: Final = "gen_ai.client.response.time_to_first_token" + TIME_PER_OUTPUT_TOKEN: Final = "gen_ai.client.response.time_per_output_token" + RESPONSE_DURATION: Final = "gen_ai.client.response.duration" # litellm ``custom_llm_provider`` -> ``gen_ai.provider.name`` value. diff --git a/litellm/integrations/otel/plumbing/metrics.py b/litellm/integrations/otel/plumbing/metrics.py index edd120f91e6..95ac939ff7f 100644 --- a/litellm/integrations/otel/plumbing/metrics.py +++ b/litellm/integrations/otel/plumbing/metrics.py @@ -1,28 +1,265 @@ -"""GenAI client metrics (token usage + operation duration histograms).""" +"""GenAI client metrics: the six ``gen_ai.client.*`` histograms plus the +recorder that builds attributes, applies the shared cardinality filter, and +records a request's metrics in the success path. + +The instrument names/units/descriptions and the recording + timing math mirror +the v1 :mod:`litellm.integrations.opentelemetry` integration so both engines emit +identical metrics. The attribute cardinality filter is reused from v1 by import +(no duplication of the valid-name set or its validation). +""" from dataclasses import dataclass +from datetime import datetime +from typing import Any, FrozenSet, Mapping, Optional from opentelemetry.metrics import Histogram, Meter -from litellm.integrations.otel.model.semconv import Metric +import litellm +from litellm.integrations.opentelemetry import ( + METRIC_METADATA_KEYS, + TOKEN_TYPE_ATTRIBUTE, + _build_metric_attribute_filter, + _resolve_metric_attribute_filter, +) +from litellm.integrations.otel.model.semconv import Metric, resolve_operation +from litellm.integrations.otel.model.utils import to_seconds +from litellm.litellm_core_utils.safe_json_dumps import safe_dumps @dataclass(frozen=True) class GenAIMetrics: - token_usage: Histogram operation_duration: Histogram + token_usage: Histogram + token_cost: Histogram + time_to_first_token: Histogram + time_per_output_token: Histogram + response_duration: Histogram def create_genai_metrics(meter: Meter) -> GenAIMetrics: return GenAIMetrics( - token_usage=meter.create_histogram( - name=Metric.TOKEN_USAGE, - unit="{token}", - description="Number of tokens used per GenAI request.", - ), operation_duration=meter.create_histogram( name=Metric.OPERATION_DURATION, unit="s", - description="GenAI operation duration.", + description="GenAI operation duration", + ), + token_usage=meter.create_histogram( + name=Metric.TOKEN_USAGE, + unit="{token}", + description="GenAI token usage", + ), + token_cost=meter.create_histogram( + name=Metric.TOKEN_COST, + unit="USD", + description="GenAI request cost", + ), + time_to_first_token=meter.create_histogram( + name=Metric.TIME_TO_FIRST_TOKEN, + unit="s", + description="Time to first token for streaming requests", + ), + time_per_output_token=meter.create_histogram( + name=Metric.TIME_PER_OUTPUT_TOKEN, + unit="s", + description="Average time per output token (generation time / completion tokens)", + ), + response_duration=meter.create_histogram( + name=Metric.RESPONSE_DURATION, + unit="s", + description="Total LLM API generation time (excludes LiteLLM overhead)", ), ) + + +class GenAIMetricRecorder: + """Records the six GenAI histograms for one successful LLM call. + + The cardinality filter is resolved lazily on the first record: the proxy + populates ``callback_settings.otel.attributes`` after the logger is built, so + reading it at construction time would miss it. ``gen_ai.token.type`` is added + to the token-usage attributes after filtering so the input/output split always + survives. + """ + + def __init__( + self, metrics: GenAIMetrics, callback_name: Optional[str] = None + ) -> None: + self._metrics = metrics + self._callback_name = callback_name + self._include: Optional[FrozenSet[str]] = None + self._exclude: Optional[FrozenSet[str]] = None + self._filter_resolved = False + + def record( + self, + kwargs: Mapping[str, Any], + response_obj: Any, + start_time: datetime, + end_time: datetime, + ) -> None: + common_attrs = self._filter_attributes(self._common_attributes(kwargs)) + duration_s = (end_time - start_time).total_seconds() + + self._metrics.operation_duration.record(duration_s, attributes=common_attrs) + self._record_token_usage(response_obj, common_attrs) + + cost = kwargs.get("response_cost") + if cost: + self._metrics.token_cost.record(cost, attributes=common_attrs) + + self._record_time_to_first_token(kwargs, common_attrs) + self._record_time_per_output_token( + kwargs, response_obj, end_time, duration_s, common_attrs + ) + self._record_response_duration(kwargs, end_time, common_attrs) + + # ------------------------------------------------------------------ # + # Attribute building + cardinality filter + # ------------------------------------------------------------------ # + + def _common_attributes(self, kwargs: Mapping[str, Any]) -> dict: + params = kwargs.get("litellm_params") or {} + provider = params.get("custom_llm_provider", "Unknown") + common_attrs: dict = { + "gen_ai.operation.name": resolve_operation(kwargs.get("call_type")).value, + "gen_ai.system": provider, + "gen_ai.request.model": kwargs.get("model"), + "gen_ai.framework": "litellm", + } + + std_log = kwargs.get("standard_logging_object") + md = getattr(std_log, "metadata", None) or (std_log or {}).get("metadata", {}) + for key in METRIC_METADATA_KEYS: + value = md.get(key) + if value is None: + continue + if isinstance(value, (dict, list)): + common_attrs[f"metadata.{key}"] = safe_dumps(value) + else: + common_attrs[f"metadata.{key}"] = str(value) + + hidden_params = getattr(std_log, "hidden_params", None) or (std_log or {}).get( + "hidden_params", {} + ) + if hidden_params: + common_attrs["hidden_params"] = safe_dumps(hidden_params) + + return common_attrs + + def _ensure_filter(self) -> None: + if self._filter_resolved: + return + attributes = None + if self._callback_name in (None, "otel"): + otel_settings = (litellm.callback_settings or {}).get("otel") or {} + raw = ( + otel_settings.get("attributes") + if isinstance(otel_settings, dict) + else None + ) + if raw is not None: + attributes = _build_metric_attribute_filter(raw) + # A bad filter (include_list + exclude_list both set, an unfilterable name) + # raises here; the caller (logger._record_metrics) surfaces it once at ERROR + # so the operator-fixable config error is visible. Not cached on the raise + # path -- _filter_resolved stays False -- so a corrected config takes effect + # without reconstructing the recorder. + self._include, self._exclude = _resolve_metric_attribute_filter(attributes) + self._filter_resolved = True + + def _filter_attributes(self, attrs: dict) -> dict: + self._ensure_filter() + if self._include is not None: + return {k: v for k, v in attrs.items() if k in self._include} + if self._exclude is not None: + return {k: v for k, v in attrs.items() if k not in self._exclude} + return attrs + + # ------------------------------------------------------------------ # + # Per-metric recording + # ------------------------------------------------------------------ # + + def _record_token_usage(self, response_obj: Any, common_attrs: dict) -> None: + if not response_obj: + return + usage = response_obj.get("usage") + if not usage: + return + in_attrs = {**common_attrs, TOKEN_TYPE_ATTRIBUTE: "input"} + out_attrs = {**common_attrs, TOKEN_TYPE_ATTRIBUTE: "output"} + self._metrics.token_usage.record( + usage.get("prompt_tokens", 0), attributes=in_attrs + ) + self._metrics.token_usage.record( + usage.get("completion_tokens", 0), attributes=out_attrs + ) + + def _record_time_to_first_token( + self, kwargs: Mapping[str, Any], common_attrs: dict + ) -> None: + if not kwargs.get("optional_params", {}).get("stream", False): + return + api_call_start = to_seconds(kwargs.get("api_call_start_time")) + completion_start = to_seconds(kwargs.get("completion_start_time")) + if api_call_start is None or completion_start is None: + return + self._metrics.time_to_first_token.record( + completion_start - api_call_start, attributes=common_attrs + ) + + def _record_time_per_output_token( + self, + kwargs: Mapping[str, Any], + response_obj: Any, + end_time: datetime, + duration_s: float, + common_attrs: dict, + ) -> None: + completion_tokens = None + if response_obj and (usage := response_obj.get("usage")): + completion_tokens = usage.get("completion_tokens") + if completion_tokens is None or completion_tokens <= 0: + return + + end_ts = to_seconds(end_time) + if end_ts is None: + generation_time = duration_s + else: + completion_start_time = kwargs.get("completion_start_time") + api_call_start_time = kwargs.get("api_call_start_time") + if completion_start_time is not None: + completion_start = to_seconds(completion_start_time) + generation_time = ( + duration_s + if completion_start is None + else end_ts - completion_start + ) + elif api_call_start_time is not None: + api_call_start = to_seconds(api_call_start_time) + generation_time = ( + duration_s if api_call_start is None else end_ts - api_call_start + ) + else: + generation_time = duration_s + + if generation_time > 0: + self._metrics.time_per_output_token.record( + generation_time / completion_tokens, attributes=common_attrs + ) + + def _record_response_duration( + self, kwargs: Mapping[str, Any], end_time: datetime, common_attrs: dict + ) -> None: + api_call_start_time = kwargs.get("api_call_start_time") + if api_call_start_time is None: + return + _end_time = kwargs.get("end_time") or end_time + if _end_time is None: + _end_time = datetime.now() + api_call_start = to_seconds(api_call_start_time) + end_ts = to_seconds(_end_time) + if api_call_start is None or end_ts is None: + return + duration = end_ts - api_call_start + if duration > 0: + self._metrics.response_duration.record(duration, attributes=common_attrs) diff --git a/litellm/integrations/otel/plumbing/providers.py b/litellm/integrations/otel/plumbing/providers.py index 40a0e41b905..6d0710397a3 100644 --- a/litellm/integrations/otel/plumbing/providers.py +++ b/litellm/integrations/otel/plumbing/providers.py @@ -1,9 +1,11 @@ """Provider / exporter factory + the Baggage span processor.""" -from typing import Callable, Iterable +from typing import TYPE_CHECKING, Any, Callable, Iterable -from opentelemetry import baggage +from opentelemetry import baggage, metrics from opentelemetry.context import Context +from opentelemetry.metrics import MeterProvider, NoOpMeterProvider +from opentelemetry.sdk.metrics import MeterProvider as SDKMeterProvider from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import ReadableSpan, SpanProcessor, TracerProvider from opentelemetry.sdk.trace.export import ( @@ -17,6 +19,7 @@ from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( ) from opentelemetry.trace import Span, SpanKind, Tracer +from litellm._version import version as litellm_version from litellm.integrations.otel.model.config import ExporterSpec, OpenTelemetryV2Config from litellm.integrations.otel.model.semconv import LiteLLM from litellm.integrations.otel.model.spans import LiteLLMSpanKind @@ -24,6 +27,10 @@ from litellm.integrations.otel.model.spans import LiteLLMSpanKind # Re-exported so ``providers.parse_headers`` remains a stable entry point. from litellm.integrations.otel.model.utils import parse_headers as parse_headers +if TYPE_CHECKING: + from opentelemetry.metrics import Meter + from opentelemetry.sdk.metrics.export import MetricReader + _SPAN_KIND_BY_ROLE_KIND: dict[LiteLLMSpanKind, SpanKind] = { LiteLLMSpanKind.SERVER: SpanKind.SERVER, LiteLLMSpanKind.CLIENT: SpanKind.CLIENT, @@ -156,6 +163,120 @@ def build_span_exporter(config: OpenTelemetryV2Config) -> SpanExporter: ) +def _otlp_metrics_endpoint(endpoint: str | None) -> str | None: + """Point an OTLP/HTTP base endpoint at the ``/v1/metrics`` signal path. + + The OTLP/HTTP exporter only appends ``/v1/metrics`` when it reads + ``OTEL_EXPORTER_OTLP_ENDPOINT`` itself; an explicitly passed endpoint is used + verbatim, so a base URL would POST to the root. Mirror ``_otlp_traces_endpoint`` + for the metrics signal (rewriting a sibling signal path when present). + """ + if not endpoint: + return endpoint + endpoint = endpoint.rstrip("/") + if endpoint.endswith("/v1/metrics"): + return endpoint + for other_signal in ("/v1/traces", "/v1/logs"): + if endpoint.endswith(other_signal): + return endpoint[: -len(other_signal)] + "/v1/metrics" + return endpoint + "/v1/metrics" + + +def build_metric_reader(config: OpenTelemetryV2Config) -> "MetricReader": + """Build a metric reader mirroring v1's exporter selection. + + ``console`` (and any unrecognized kind) exports to the console; ``otlp_http`` + and ``otlp_grpc`` export over OTLP with the configured endpoint/headers. The + reader exports on a 5s period, matching v1. + """ + from opentelemetry.sdk.metrics.export import ( + ConsoleMetricExporter, + PeriodicExportingMetricReader, + ) + + kind = (config.exporter or "console").lower() + if kind in ("otlp_http", "http", "http/protobuf", "http/json"): + from opentelemetry.exporter.otlp.proto.http.metric_exporter import ( + OTLPMetricExporter as HTTPMetricExporter, + ) + from opentelemetry.sdk.metrics import Histogram + from opentelemetry.sdk.metrics.export import AggregationTemporality + + exporter: Any = HTTPMetricExporter( + endpoint=_otlp_metrics_endpoint(config.endpoint), + headers=parse_headers(config.headers), + preferred_temporality={Histogram: AggregationTemporality.DELTA}, + ) + elif kind in ("otlp_grpc", "grpc"): + from opentelemetry.sdk.metrics import Histogram + from opentelemetry.sdk.metrics.export import AggregationTemporality + + try: + from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import ( + OTLPMetricExporter as GRPCMetricExporter, + ) + except ImportError as exc: + raise ImportError( + "OpenTelemetry OTLP gRPC metric exporter is not available. Install " + "`opentelemetry-exporter-otlp` and `grpcio` (or `litellm[grpc]`)." + ) from exc + + exporter = GRPCMetricExporter( + endpoint=config.endpoint, + headers=parse_headers(config.headers), + preferred_temporality={Histogram: AggregationTemporality.DELTA}, + ) + else: + exporter = ConsoleMetricExporter() + + return PeriodicExportingMetricReader(exporter, export_interval_millis=5000) + + +def build_meter_provider( + config: OpenTelemetryV2Config, + metric_reader: "MetricReader | None" = None, +) -> SDKMeterProvider: + """Build the :class:`MeterProvider` for GenAI metrics. + + ``metric_reader`` is an explicit override (tests inject an + ``InMemoryMetricReader``); otherwise the reader is selected from the config's + exporter kind via :func:`build_metric_reader`. + """ + reader = metric_reader if metric_reader is not None else build_metric_reader(config) + return SDKMeterProvider(metric_readers=[reader], resource=build_resource(config)) + + +def resolve_meter_provider( + config: OpenTelemetryV2Config, + meter_provider: MeterProvider | None = None, +) -> MeterProvider: + """Resolve the :class:`MeterProvider` GenAI metrics record through. + + An injected provider wins (DI/tests). Otherwise reuse whatever the operator has + configured as the global, whether a real SDK provider or an explicit + ``NoOpMeterProvider``, so the GenAI histograms ride the operator's + readers/exporters and an explicit opt-out is honored. Only when the global is + still the default proxy placeholder does V2 build one from the config and + publish it as the global, mirroring how V2 owns trace export. The built + provider is the one returned, so its reader thread is always live, never + orphaned. + """ + if meter_provider is not None: + return meter_provider + + existing = metrics.get_meter_provider() + if isinstance(existing, (SDKMeterProvider, NoOpMeterProvider)): + return existing + + provider = build_meter_provider(config) + metrics.set_meter_provider(provider) + return provider + + +def get_meter(provider: MeterProvider, name: str = "litellm") -> "Meter": + return provider.get_meter(name, litellm_version) + + def build_resource(config: OpenTelemetryV2Config) -> Resource: attributes: dict[str, str] = {"service.name": config.service_name} if config.deployment_environment: @@ -207,7 +328,10 @@ def build_tracer_provider( def get_tracer(provider: TracerProvider, name: str = "litellm") -> Tracer: - return provider.get_tracer(name) + # Stamp the instrumentation scope with the LiteLLM package version so every + # emitted span carries a deterministic ``scope.version`` (the standard OTel + # location for the emitting library's version) for downstream consumers. + return provider.get_tracer(name, litellm_version) def in_memory_provider( diff --git a/litellm/integrations/otel/plumbing/routing.py b/litellm/integrations/otel/plumbing/routing.py index 4d0943a263a..1f2f1b202d9 100644 --- a/litellm/integrations/otel/plumbing/routing.py +++ b/litellm/integrations/otel/plumbing/routing.py @@ -88,13 +88,23 @@ class TenantTracerCache: return get_tracer(provider, self._tracer_name) def _config_with_headers(self, headers: Mapping[str, str]) -> OpenTelemetryV2Config: - """Clone the config, replacing OTLP exporter headers with ``headers``.""" + """Clone the config, stamping ``headers`` onto the credential's own exporter. + + ``headers`` are the per-request credentials of ``self._callback_name`` (the + integration that built this cache), so they apply only to the exporter that + integration contributed (``spec.owner``). A request that carries one + tenant's Arize key must never rewrite the headers of a co-configured + Langfuse or self-hosted collector exporter, which would leak that key to a + different backend. + """ header_str = ",".join(f"{key}={value}" for key, value in headers.items()) + header_update: dict[str, str] = {"headers": header_str} exporters = [ ( - spec - if spec.kind.lower() in _NON_OTLP_KINDS - else spec.model_copy(update={"headers": header_str}) + spec.model_copy(update=header_update) + if spec.owner == self._callback_name + and spec.kind.lower() not in _NON_OTLP_KINDS + else spec ) for spec in self._config.exporters ] diff --git a/litellm/integrations/otel/presets/agentops.py b/litellm/integrations/otel/presets/agentops.py index 5a12818fd99..7b0783935ac 100644 --- a/litellm/integrations/otel/presets/agentops.py +++ b/litellm/integrations/otel/presets/agentops.py @@ -16,7 +16,11 @@ from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict from litellm._logging import verbose_logger -from litellm.integrations.otel.model.config import ExporterSpec, OpenTelemetryV2Config +from litellm.integrations.otel.model.config import ( + ExporterOwner, + ExporterSpec, + OpenTelemetryV2Config, +) from litellm.integrations.otel.plumbing.providers import register_exporter_factory _AGENTOPS_ENDPOINT = "https://otlp.agentops.cloud/v1/traces" @@ -59,6 +63,7 @@ def agentops_preset( options=( {"api_key": settings.api_key} if settings.api_key else None ), + owner=ExporterOwner.AGENTOPS, ), ], "resource_attributes": { diff --git a/litellm/integrations/otel/presets/arize.py b/litellm/integrations/otel/presets/arize.py index 4df15125f5a..b6af88c6b34 100644 --- a/litellm/integrations/otel/presets/arize.py +++ b/litellm/integrations/otel/presets/arize.py @@ -4,7 +4,11 @@ from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict from litellm.integrations.arize.arize import ArizeLogger as _V1ArizeLogger -from litellm.integrations.otel.model.config import ExporterSpec, OpenTelemetryV2Config +from litellm.integrations.otel.model.config import ( + ExporterOwner, + ExporterSpec, + OpenTelemetryV2Config, +) from litellm.integrations.otel.presets.utils import ensure_mappers from litellm.types.utils import StandardCallbackDynamicParams @@ -34,6 +38,7 @@ def arize_preset( kind=arize_cfg.protocol or "otlp_grpc", endpoint=arize_cfg.endpoint or "https://otlp.arize.com/v1", headers=headers, + owner=ExporterOwner.ARIZE_AX, ), ], "mapper_names": ensure_mappers(base.mapper_names, "openinference"), diff --git a/litellm/integrations/otel/presets/langfuse.py b/litellm/integrations/otel/presets/langfuse.py index 011545384b9..5631da6429f 100644 --- a/litellm/integrations/otel/presets/langfuse.py +++ b/litellm/integrations/otel/presets/langfuse.py @@ -3,7 +3,11 @@ from litellm.integrations.langfuse.langfuse_otel import ( LangfuseOtelLogger as _V1Langfuse, ) -from litellm.integrations.otel.model.config import ExporterSpec, OpenTelemetryV2Config +from litellm.integrations.otel.model.config import ( + ExporterOwner, + ExporterSpec, + OpenTelemetryV2Config, +) from litellm.integrations.otel.presets.utils import ensure_mappers from litellm.types.utils import StandardCallbackDynamicParams @@ -23,6 +27,7 @@ def langfuse_preset( kind=kind, endpoint=cfg.endpoint, headers=cfg.headers, + owner=ExporterOwner.LANGFUSE_OTEL, ), ], "mapper_names": ensure_mappers(base.mapper_names, "langfuse"), diff --git a/litellm/integrations/otel/presets/levo.py b/litellm/integrations/otel/presets/levo.py index 4c4cba982a4..74a95b100cb 100644 --- a/litellm/integrations/otel/presets/levo.py +++ b/litellm/integrations/otel/presets/levo.py @@ -1,7 +1,11 @@ """Levo preset — OTLP/HTTP to a Levo collector with org+workspace headers.""" from litellm.integrations.levo.levo import LevoLogger as _V1Levo -from litellm.integrations.otel.model.config import ExporterSpec, OpenTelemetryV2Config +from litellm.integrations.otel.model.config import ( + ExporterOwner, + ExporterSpec, + OpenTelemetryV2Config, +) def levo_preset( @@ -18,6 +22,7 @@ def levo_preset( kind="otlp_http", endpoint=cfg.endpoint, headers=cfg.otlp_auth_headers, + owner=ExporterOwner.LEVO, ), ], } diff --git a/litellm/integrations/otel/presets/phoenix.py b/litellm/integrations/otel/presets/phoenix.py index 4c2b165ffca..5485b599321 100644 --- a/litellm/integrations/otel/presets/phoenix.py +++ b/litellm/integrations/otel/presets/phoenix.py @@ -6,7 +6,11 @@ from pydantic_settings import BaseSettings, SettingsConfigDict from litellm.integrations.arize.arize_phoenix import ( ArizePhoenixLogger as _V1Phoenix, ) -from litellm.integrations.otel.model.config import ExporterSpec, OpenTelemetryV2Config +from litellm.integrations.otel.model.config import ( + ExporterOwner, + ExporterSpec, + OpenTelemetryV2Config, +) from litellm.integrations.otel.presets.utils import ensure_mappers @@ -37,6 +41,7 @@ def phoenix_preset( kind=cfg.protocol if hasattr(cfg, "protocol") else "otlp_http", endpoint=cfg.endpoint, headers=headers, + owner=ExporterOwner.ARIZE_PHOENIX, ), ], "mapper_names": ensure_mappers(base.mapper_names, "openinference"), diff --git a/litellm/integrations/otel/presets/weave.py b/litellm/integrations/otel/presets/weave.py index 9fc03c84a6d..d22f7641289 100644 --- a/litellm/integrations/otel/presets/weave.py +++ b/litellm/integrations/otel/presets/weave.py @@ -1,6 +1,10 @@ """Weave (W&B) preset.""" -from litellm.integrations.otel.model.config import ExporterSpec, OpenTelemetryV2Config +from litellm.integrations.otel.model.config import ( + ExporterOwner, + ExporterSpec, + OpenTelemetryV2Config, +) from litellm.integrations.otel.presets.utils import ensure_mappers from litellm.integrations.weave.weave_otel import ( _get_weave_authorization_header, @@ -23,6 +27,7 @@ def weave_preset( kind=weave_cfg.protocol or "otlp_http", endpoint=weave_cfg.endpoint, headers=weave_cfg.otlp_auth_headers, + owner=ExporterOwner.WEAVE_OTEL, ), ], # Weave consumes OpenInference + a small Weave-specific overlay. diff --git a/litellm/integrations/prometheus.py b/litellm/integrations/prometheus.py index 648fe671140..c63f114514a 100644 --- a/litellm/integrations/prometheus.py +++ b/litellm/integrations/prometheus.py @@ -24,14 +24,18 @@ from typing import ( import litellm from litellm._logging import print_verbose, verbose_logger -from litellm.integrations.custom_logger import CustomLogger -from litellm.integrations.prometheus_helpers.bounded_prometheus_series_tracker import ( - BoundedPrometheusSeriesTracker, +from litellm.exceptions import ( + validate_rate_limit_category, + validate_rate_limit_type, ) +from litellm.integrations.custom_logger import CustomLogger from litellm.integrations.prometheus_helpers import ( PrometheusLabelFactoryContext, _get_cached_end_user_id_for_cost_tracking, ) +from litellm.integrations.prometheus_helpers.bounded_prometheus_series_tracker import ( + BoundedPrometheusSeriesTracker, +) from litellm.litellm_core_utils.core_helpers import ( get_litellm_metadata_from_kwargs, get_metadata_variable_name_from_kwargs, @@ -42,6 +46,9 @@ from litellm.proxy._types import ( LiteLLM_UserTable, UserAPIKeyAuth, ) +from litellm.repositories.organization_repository import OrganizationRepository +from litellm.repositories.team_repository import TeamRepository +from litellm.repositories.user_repository import UserRepository from litellm.types.integrations.prometheus import * from litellm.types.integrations.prometheus import ( _sanitize_prometheus_label_name, @@ -68,7 +75,7 @@ class PrometheusLogger(CustomLogger): return cb return None - def __init__( # noqa: PLR0915 + def __init__( self, **kwargs, ): @@ -78,6 +85,20 @@ class PrometheusLogger(CustomLogger): # Always initialize label_filters, even for non-premium users self.label_filters = self._parse_prometheus_config() + # Cache resolved label sets per metric. Several entries in + # ``PrometheusMetricLabels.get_labels`` read module-level toggles + # (e.g. ``litellm.prometheus_emit_stream_label``, + # ``litellm.prometheus_emit_rate_limit_labels``) that can be + # changed at runtime. Prometheus counters/gauges/histograms are + # created with a *fixed* ``labelnames`` set; if a runtime call + # to ``get_labels_for_metric`` returned a different set, the + # subsequent ``counter.labels(**_labels)`` would raise a + # ``ValueError`` from the prometheus client. Snapshotting at + # logger init time pins the label set for the lifetime of the + # logger so toggling these flags only takes effect after a + # restart, keeping init-time and runtime label sets in sync. + self._cached_metric_labels: Dict[str, List[str]] = {} + _custom_buckets = litellm.prometheus_latency_buckets self.latency_buckets = ( tuple(_custom_buckets) @@ -1033,13 +1054,27 @@ class PrometheusLogger(CustomLogger): self, metric_name: DEFINED_PROMETHEUS_METRICS ) -> List[str]: """ - Get the labels for a metric, filtered if configured + Get the labels for a metric, filtered if configured. + + The result is cached on the instance so the label set used to + construct each Prometheus metric at ``__init__`` time stays in lock + step with the label set passed to ``counter.labels(...)`` at + runtime, even if the underlying module-level toggles consulted by + :meth:`PrometheusMetricLabels.get_labels` (e.g. + ``litellm.prometheus_emit_rate_limit_labels``, + ``litellm.prometheus_emit_stream_label``) are flipped after the + logger has been created. """ + cached = self._cached_metric_labels.get(metric_name) + if cached is not None: + return cached + # Get default labels for this metric from PrometheusMetricLabels default_labels = PrometheusMetricLabels.get_labels(metric_name) # If no label filtering is configured for this metric, use default labels if metric_name not in self.label_filters: + self._cached_metric_labels[metric_name] = default_labels return default_labels # Get configured labels for this metric @@ -1050,6 +1085,7 @@ class PrometheusLogger(CustomLogger): label for label in default_labels if label in configured_labels ] + self._cached_metric_labels[metric_name] = filtered_labels return filtered_labels def _track_end_user_metric_series( @@ -2029,14 +2065,8 @@ class PrometheusLogger(CustomLogger): Proxy level tracking - failed client side requests - labelnames=[ - "end_user", - "hashed_api_key", - "api_key_alias", - REQUESTED_MODEL, - "team", - "team_alias", - ] + EXCEPTION_LABELS, + See :attr:`PrometheusMetricLabels.litellm_proxy_failed_requests_metric` + for the authoritative list of labels emitted on this metric. """ from litellm.litellm_core_utils.litellm_logging import ( StandardLoggingPayloadSetup, @@ -2059,6 +2089,9 @@ class PrometheusLogger(CustomLogger): model_id = _metadata.get("model_info", {}).get("id") or request_data.get( "model_info", {} ).get("id") + rate_limit_category, rate_limit_type = self._extract_rate_limit_labels( + original_exception + ) enum_values = UserAPIKeyLabelValues( end_user=user_api_key_dict.end_user_id, user=user_api_key_dict.user_id, @@ -2073,6 +2106,8 @@ class PrometheusLogger(CustomLogger): status_code=str(status_code), exception_status=str(status_code), exception_class=self._get_exception_class_name(original_exception), + rate_limit_category=rate_limit_category, + rate_limit_type=rate_limit_type, tags=_tags, route=user_api_key_dict.request_route, client_ip=_metadata.get("requester_ip_address"), @@ -2220,7 +2255,7 @@ class PrometheusLogger(CustomLogger): or _litellm_params_metadata.get("user_agent"), } - def set_llm_deployment_failure_metrics(self, request_kwargs: dict): # noqa: PLR0915 + def set_llm_deployment_failure_metrics(self, request_kwargs: dict): """ Sets Failure metrics when an LLM API call fails @@ -2843,6 +2878,33 @@ class PrometheusLogger(CustomLogger): @staticmethod def _get_exception_class_name(exception: Exception) -> str: + # Some exception types pin the ``exception_class`` label to a legacy + # value for back-compat with existing dashboards (e.g. proxy-side 429s + # keep reporting as "HTTPException"). Honor that opt-in marker before + # deriving the label from the runtime class name. Reading it via + # ``getattr`` keeps this core integrations module free of a transitive + # ``fastapi`` dependency. + legacy_class_name = getattr(exception, "prometheus_exception_class_name", None) + if isinstance(legacy_class_name, str) and legacy_class_name: + return legacy_class_name + + # Same back-compat reasoning for ``BudgetExceededError``: the unified + # rate-limit error work attached ``.llm_provider`` to budget errors + # too (so callbacks reading ``StandardLoggingPayload`` get provider + # attribution). Without this short-circuit, the provider prefix below + # would silently flip the label from "BudgetExceededError" to e.g. + # "Openai.BudgetExceededError" and break dashboards keyed on the + # original value. + try: + from litellm.exceptions import BudgetExceededError + except ImportError: + BudgetExceededError = None # type: ignore[assignment,misc] + + if BudgetExceededError is not None and isinstance( + exception, BudgetExceededError + ): + return "BudgetExceededError" + exception_class_name = "" if hasattr(exception, "llm_provider"): exception_class_name = getattr(exception, "llm_provider") or "" @@ -2857,6 +2919,27 @@ class PrometheusLogger(CustomLogger): exception_class_name += exception.__class__.__name__ return exception_class_name + @staticmethod + def _extract_rate_limit_labels( + exception: Optional[Exception], + ) -> Tuple[Optional[str], Optional[str]]: + """ + Pull the unified ``category`` / ``rate_limit_type`` fields off any + exception that declares them (``litellm.RateLimitError`` and bare- + Exception subclasses like ``BudgetExceededError``). + + Values are validated against the :class:`RateLimitErrorCategory` / + :class:`RateLimitType` enums so unrelated third-party exceptions that + happen to declare ``.category`` / ``.rate_limit_type`` string attributes + can't leak garbage into Prometheus label cardinality. + """ + if exception is None: + return None, None + return ( + validate_rate_limit_category(getattr(exception, "category", None)), + validate_rate_limit_type(getattr(exception, "rate_limit_type", None)), + ) + async def log_success_fallback_event( self, original_model_group: str, kwargs: dict, original_exception: Exception ): @@ -3198,12 +3281,12 @@ class PrometheusLogger(CustomLogger): page_size: int, page: int ) -> Tuple[List[LiteLLM_UserTable], Optional[int]]: skip = (page - 1) * page_size - users = await prisma_client.db.litellm_usertable.find_many( + users = await UserRepository(prisma_client).table.find_many( skip=skip, take=page_size, order={"created_at": "desc"}, ) - total_count = await prisma_client.db.litellm_usertable.count() + total_count = await UserRepository(prisma_client).table.count() return users, total_count await self._initialize_budget_metrics( @@ -3226,13 +3309,13 @@ class PrometheusLogger(CustomLogger): async def fetch_orgs(page_size: int, page: int) -> Tuple[list, Optional[int]]: skip = (page - 1) * page_size - orgs = await prisma_client.db.litellm_organizationtable.find_many( + orgs = await OrganizationRepository(prisma_client).table.find_many( skip=skip, take=page_size, order={"created_at": "desc"}, include={"litellm_budget_table": True}, ) - total_count = await prisma_client.db.litellm_organizationtable.count() + total_count = await OrganizationRepository(prisma_client).table.count() return orgs, total_count await self._initialize_budget_metrics( @@ -3300,14 +3383,14 @@ class PrometheusLogger(CustomLogger): try: # Get total user count - total_users = await prisma_client.db.litellm_usertable.count() + total_users = await UserRepository(prisma_client).table.count() self.litellm_total_users_metric.set(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() + total_teams = await TeamRepository(prisma_client).table.count() self.litellm_teams_count_metric.set(total_teams) verbose_logger.debug( f"Prometheus: set litellm_teams_count to {total_teams}" diff --git a/litellm/integrations/websearch_interception/handler.py b/litellm/integrations/websearch_interception/handler.py index 37528e7dcd5..f29b378fcde 100644 --- a/litellm/integrations/websearch_interception/handler.py +++ b/litellm/integrations/websearch_interception/handler.py @@ -1128,7 +1128,7 @@ class WebSearchInterceptionLogger(CustomLogger): ) raise - async def _execute_chat_completion_agentic_loop( # noqa: PLR0915 + async def _execute_chat_completion_agentic_loop( self, model: str, messages: List[Dict], @@ -1159,7 +1159,7 @@ class WebSearchInterceptionLogger(CustomLogger): **request_patch.kwargs, ) - async def _build_chat_completion_request_patch( # noqa: PLR0915 + async def _build_chat_completion_request_patch( self, model: str, messages: List[Dict], @@ -1339,8 +1339,13 @@ class WebSearchInterceptionLogger(CustomLogger): websearch_params: WebSearchInterceptionConfig = {} if "websearch_interception_params" in litellm_settings: websearch_params = litellm_settings["websearch_interception_params"] - elif "websearch_interception" in callback_specific_params: - websearch_params = callback_specific_params["websearch_interception"] + elif "websearch_interception" in callback_specific_params and isinstance( + callback_specific_params["websearch_interception"], dict + ): + websearch_params = cast( + WebSearchInterceptionConfig, + callback_specific_params["websearch_interception"], + ) # Use classmethod to initialize from config return WebSearchInterceptionLogger.from_config_yaml(websearch_params) diff --git a/litellm/integrations/weights_biases.py b/litellm/integrations/weights_biases.py index e9539d27e97..5f087fe219a 100644 --- a/litellm/integrations/weights_biases.py +++ b/litellm/integrations/weights_biases.py @@ -21,10 +21,11 @@ try: # contains a (known) object attribute object: Literal["chat.completion", "edit", "text_completion"] - def __getitem__(self, key: K) -> V: ... # noqa + def __getitem__(self, key: K) -> V: ... - def get(self, key: K, default: Optional[V] = None) -> Optional[V]: # noqa - ... # pragma: no cover + def get( + self, key: K, default: Optional[V] = None + ) -> Optional[V]: ... # pragma: no cover class OpenAIRequestResponseResolver: def __call__( diff --git a/litellm/interactions/agents/utils.py b/litellm/interactions/agents/utils.py index d16a9597f53..e9405928a3d 100644 --- a/litellm/interactions/agents/utils.py +++ b/litellm/interactions/agents/utils.py @@ -2,11 +2,40 @@ Utility functions for the Agents API SDK. """ -from typing import Optional +from typing import Dict, Mapping, Optional from litellm.llms.base_llm.agents.transformation import BaseAgentsAPIConfig +def merge_agent_headers( + *, + dynamic_headers: Optional[Mapping[str, str]] = None, + static_headers: Optional[Mapping[str, str]] = None, +) -> Optional[Dict[str, str]]: + """Merge outbound HTTP headers for A2A agent calls. + + Merge rules: + - Start with ``dynamic_headers`` (values extracted from the incoming client request). + - Overlay ``static_headers`` (admin-configured per agent). + - Comparison is case-insensitive (HTTP headers are case-insensitive), so a + static ``Authorization`` strips any dynamic ``authorization`` before the + static value is written. The static side's casing is preserved. + + If both contain the same header (case-insensitively), ``static_headers`` wins. + """ + merged: Dict[str, str] = {} + + if dynamic_headers: + merged.update({str(k): str(v) for k, v in dynamic_headers.items()}) + + if static_headers: + static_lower = {str(k).lower() for k in static_headers} + merged = {k: v for k, v in merged.items() if k.lower() not in static_lower} + merged.update({str(k): str(v) for k, v in static_headers.items()}) + + return merged or None + + def get_provider_agents_api_config( custom_llm_provider: Optional[str], ) -> Optional[BaseAgentsAPIConfig]: diff --git a/litellm/litellm_core_utils/cli_token_utils.py b/litellm/litellm_core_utils/cli_token_utils.py index 3776d276912..eb01359cdc0 100644 --- a/litellm/litellm_core_utils/cli_token_utils.py +++ b/litellm/litellm_core_utils/cli_token_utils.py @@ -37,7 +37,7 @@ def get_litellm_gateway_api_key( """ Get the stored CLI API key for use with LiteLLM SDK. - This function reads the token file created by `litellm-proxy login` + This function reads the token file created by `lite login` and returns the API key for use in Python scripts. Args: diff --git a/litellm/litellm_core_utils/cloud_storage_security.py b/litellm/litellm_core_utils/cloud_storage_security.py index daa3dc60320..a75d1178d5a 100644 --- a/litellm/litellm_core_utils/cloud_storage_security.py +++ b/litellm/litellm_core_utils/cloud_storage_security.py @@ -15,8 +15,23 @@ BEDROCK_MANAGED_S3_PREFIXES = ( BEDROCK_MANAGED_S3_UPLOAD_PREFIX, BEDROCK_MANAGED_S3_OUTPUT_PREFIX, ) +MANAGED_CLOUD_STORAGE_SCHEMES = ("s3://", "gs://") _MAPPING_PROXY_TYPE: type = type(MappingProxyType({})) + +def is_managed_cloud_storage_uri(file_id: str) -> bool: + """ + True if file_id is a raw cloud-storage object URI (e.g. ``s3://bucket/key``). + + These are internal provider artifacts. On the multi-tenant proxy they must be + retrieved through their managed unified file id so owner/team access is enforced; + a raw URI supplied by a caller bypasses that check. + """ + return isinstance(file_id, str) and file_id.startswith( + MANAGED_CLOUD_STORAGE_SCHEMES + ) + + _SAFE_OBJECT_COMPONENT_PATTERN = re.compile(r"[^A-Za-z0-9._-]+") diff --git a/litellm/litellm_core_utils/core_helpers.py b/litellm/litellm_core_utils/core_helpers.py index e984df82140..98b792efa59 100644 --- a/litellm/litellm_core_utils/core_helpers.py +++ b/litellm/litellm_core_utils/core_helpers.py @@ -242,9 +242,28 @@ def _get_parent_otel_span_from_kwargs( return None -def process_response_headers(response_headers: Union[httpx.Headers, dict]) -> dict: +def process_response_headers( + response_headers: Union[httpx.Headers, dict], + preserve_litellm_internal_headers: bool = False, +) -> dict: + """ + `preserve_litellm_internal_headers` must only be True when the input is a + LiteLLM-owned dict (e.g. `_hidden_params["additional_headers"]` that has + already been through one round of processing). For raw upstream provider + headers — whether passed as `httpx.Headers` or a plain dict — it must + remain False, otherwise a malicious provider returning `x-litellm-*` could + spoof LiteLLM-internal markers (e.g. `x-litellm-attempted-fallbacks`). + + When the input is an `httpx.Headers` object the flag is always treated as + False regardless of what the caller requested, because `httpx.Headers` is + always a raw provider response and can never be LiteLLM-owned. + """ from litellm.types.utils import OPENAI_RESPONSE_HEADERS + # Raw httpx.Headers objects come directly from provider HTTP responses and + # must never be treated as LiteLLM-owned, regardless of caller intent. + _preserve = preserve_litellm_internal_headers and isinstance(response_headers, dict) + openai_headers = {} processed_headers = {} additional_headers = {} @@ -256,6 +275,12 @@ def process_response_headers(response_headers: Union[httpx.Headers, dict]) -> di "llm_provider-" ): # return raw provider headers (incl. openai-compatible ones) processed_headers[k] = v + elif _preserve and k.startswith("x-litellm-"): + # LiteLLM's own internal headers (e.g. x-litellm-attempted-fallbacks, + # x-litellm-model-group) are not LLM provider headers and must not be + # prefixed. Downstream consumers (proxy override, callers checking + # whether a fallback happened) look up the bare key. + processed_headers[k] = v else: additional_headers["{}-{}".format("llm_provider", k)] = v diff --git a/litellm/litellm_core_utils/custom_logger_registry.py b/litellm/litellm_core_utils/custom_logger_registry.py index fd402b90d88..a7fae104c92 100644 --- a/litellm/litellm_core_utils/custom_logger_registry.py +++ b/litellm/litellm_core_utils/custom_logger_registry.py @@ -25,6 +25,7 @@ from litellm.integrations.datadog.datadog_metrics import DatadogMetricsLogger from litellm.integrations.deepeval import DeepEvalLogger from litellm.integrations.dotprompt import DotpromptManager from litellm.integrations.focus.focus_logger import FocusLogger +from litellm.integrations.mavvrik_focus.mavvrik_focus_logger import MavvrikFocusLogger from litellm.integrations.vantage.vantage_logger import VantageLogger from litellm.integrations.galileo import GalileoObserve from litellm.integrations.gcs_bucket.gcs_bucket import GCSBucketLogger @@ -39,6 +40,7 @@ from litellm.integrations.langsmith import LangsmithLogger from litellm.integrations.litellm_agent import LiteLLMAgentModelResolver from litellm.integrations.literal_ai import LiteralAILogger from litellm.integrations.mlflow import MlflowLogger +from litellm.integrations.newrelic import NewRelicLogger from litellm.integrations.openmeter import OpenMeterLogger from litellm.integrations.opentelemetry import OpenTelemetry from litellm.integrations.opik.opik import OpikLogger @@ -102,8 +104,10 @@ class CustomLoggerRegistry: "gitlab": GitLabPromptManager, "cloudzero": CloudZeroLogger, "focus": FocusLogger, + "mavvrik": MavvrikFocusLogger, "vantage": VantageLogger, "posthog": PostHogLogger, + "newrelic": NewRelicLogger, } try: diff --git a/litellm/litellm_core_utils/duration_parser.py b/litellm/litellm_core_utils/duration_parser.py index 6d2b4226ff4..036d691c686 100644 --- a/litellm/litellm_core_utils/duration_parser.py +++ b/litellm/litellm_core_utils/duration_parser.py @@ -131,6 +131,8 @@ def get_next_standardized_reset_time( # Handle different time units if unit == "d": return _handle_day_reset(current_time, base_midnight, value, tz) + elif unit == "w": + return _handle_day_reset(current_time, base_midnight, value * 7, tz) elif unit == "h": return _handle_hour_reset(current_time, base_midnight, value) elif unit == "m": diff --git a/litellm/litellm_core_utils/exception_mapping_utils.py b/litellm/litellm_core_utils/exception_mapping_utils.py index ffaa5140916..edb97b310d7 100644 --- a/litellm/litellm_core_utils/exception_mapping_utils.py +++ b/litellm/litellm_core_utils/exception_mapping_utils.py @@ -170,6 +170,16 @@ def get_error_message(error_obj) -> Optional[str]: ####### EXCEPTION MAPPING ################ +def _get_body_error_code(error_str: str) -> int | None: + """Return error.code from a JSON error body, or None if not parseable.""" + try: + body = json.loads(error_str) + code = body.get("error", {}).get("code") + return int(code) if code is not None else None + except Exception: + return None + + def _get_response_headers(original_exception: Exception) -> Optional[httpx.Headers]: """ Extract and return the response headers from an exception, if present. @@ -234,7 +244,7 @@ def extract_and_raise_litellm_exception( ) -def exception_type( # type: ignore # noqa: PLR0915 +def exception_type( # type: ignore model, original_exception, custom_llm_provider, @@ -250,14 +260,14 @@ def exception_type( # type: ignore # noqa: PLR0915 exception_mapping_worked = False exception_provider = custom_llm_provider if litellm.suppress_debug_info is False: - print() # noqa - print( # noqa - "\033[1;31mGive Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new\033[0m" # noqa - ) # noqa - print( # noqa - "LiteLLM.Info: If you need to debug this error, use `litellm._turn_on_debug()'." # noqa - ) # noqa - print() # noqa + print() # noqa: T201 + print( # noqa: T201 + "\033[1;31mGive Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new\033[0m" + ) + print( # noqa: T201 + "LiteLLM.Info: If you need to debug this error, use `litellm._turn_on_debug()'." + ) + print() # noqa: T201 litellm_response_headers = _get_response_headers( original_exception=original_exception @@ -1415,6 +1425,29 @@ def exception_type( # type: ignore # noqa: PLR0915 ), ), ) + elif ( + isinstance(getattr(original_exception, "status_code", None), int) + and 500 <= original_exception.status_code < 600 + and _get_body_error_code(error_str) == 429 + ): + # upstream gateway wraps a 429 inside a 5xx envelope + # e.g. HTTP 500/503 with {"error":{"code":429,...}}. + # Scoped to 5xx so HTTP 400/401 with body code:429 + # still maps to BadRequestError / AuthenticationError. + exception_mapping_worked = True + raise RateLimitError( + message=f"litellm.RateLimitError: {custom_llm_provider}Exception - {error_str}", + model=model, + llm_provider=custom_llm_provider, + litellm_debug_info=extra_information, + response=httpx.Response( + status_code=429, + request=httpx.Request( + method="POST", + url=" https://cloud.google.com/vertex-ai/", + ), + ), + ) elif ( "500 Internal Server Error" in error_str or "The model is overloaded." in error_str diff --git a/litellm/litellm_core_utils/fallback_utils.py b/litellm/litellm_core_utils/fallback_utils.py index daacca85c8a..1606b53e1f9 100644 --- a/litellm/litellm_core_utils/fallback_utils.py +++ b/litellm/litellm_core_utils/fallback_utils.py @@ -7,6 +7,9 @@ from litellm.litellm_core_utils.core_helpers import ( safe_deep_copy, filter_internal_params, ) +from litellm.router_utils.add_retry_fallback_headers import ( + add_fallback_headers_to_response, +) from .asyncify import run_async_function @@ -42,7 +45,7 @@ async def async_completion_with_fallbacks(**kwargs): # Try each fallback model most_recent_exception_str: Optional[str] = None - for fallback in fallbacks: + for attempted_fallbacks, fallback in enumerate(fallbacks): try: completion_kwargs = safe_deep_copy(base_kwargs) # Handle dictionary fallback configurations @@ -63,7 +66,10 @@ async def async_completion_with_fallbacks(**kwargs): ) if response is not None: - return response + return add_fallback_headers_to_response( + response=response, + attempted_fallbacks=attempted_fallbacks, + ) except Exception as e: verbose_logger.exception( diff --git a/litellm/litellm_core_utils/get_litellm_params.py b/litellm/litellm_core_utils/get_litellm_params.py index b32803b5dfc..fc3c25e0d95 100644 --- a/litellm/litellm_core_utils/get_litellm_params.py +++ b/litellm/litellm_core_utils/get_litellm_params.py @@ -4,7 +4,7 @@ from litellm.llms.openai.data_residency import infer_openai_data_residency # Pre-define optional kwargs keys as frozenset for O(1) lookups # These are extracted from kwargs only if present, avoiding unnecessary .get() calls -_OPTIONAL_KWARGS_KEYS = frozenset( +OPTIONAL_KWARGS_KEYS = frozenset( { "azure_ad_token", "tenant_id", @@ -32,11 +32,16 @@ _OPTIONAL_KWARGS_KEYS = frozenset( "aws_sts_endpoint", "aws_external_id", "aws_bedrock_runtime_endpoint", + "aws_bedrock_project_id", "tpm", "rpm", + "use_xai_oauth", } ) +# Backward-compatible alias for existing imports/tests. +_OPTIONAL_KWARGS_KEYS = OPTIONAL_KWARGS_KEYS + def _get_base_model_from_litellm_call_metadata( metadata: Optional[dict], @@ -164,7 +169,7 @@ def get_litellm_params( # Sparse extraction: only add kwargs keys that are actually present if kwargs: - for key in _OPTIONAL_KWARGS_KEYS: + for key in OPTIONAL_KWARGS_KEYS: if key in kwargs: litellm_params[key] = kwargs[key] diff --git a/litellm/litellm_core_utils/get_llm_provider_logic.py b/litellm/litellm_core_utils/get_llm_provider_logic.py index de65ed93312..bb8b1a82996 100644 --- a/litellm/litellm_core_utils/get_llm_provider_logic.py +++ b/litellm/litellm_core_utils/get_llm_provider_logic.py @@ -1,5 +1,5 @@ import re -from typing import Optional, Tuple +from typing import Optional, Tuple, cast from urllib.parse import urlparse import litellm @@ -7,7 +7,7 @@ from litellm.constants import REPLICATE_MODEL_NAME_WITH_ID_LENGTH from litellm.llms.openai_like.json_loader import JSONProviderRegistry from litellm.secret_managers.main import get_secret, get_secret_str -from ..types.router import LiteLLM_Params +from ..types.router import GenericLiteLLMParams, LiteLLM_Params def _endpoint_matches_api_base(endpoint: str, api_base: str) -> bool: @@ -154,12 +154,12 @@ def handle_anthropic_text_model_custom_llm_provider( return model, custom_llm_provider -def get_llm_provider( # noqa: PLR0915 +def get_llm_provider( model: str, custom_llm_provider: Optional[str] = None, api_base: Optional[str] = None, api_key: Optional[str] = None, - litellm_params: Optional[LiteLLM_Params] = None, + litellm_params: Optional[GenericLiteLLMParams] = None, ) -> Tuple[str, str, Optional[str], Optional[str]]: """ Returns the provider for a given model name - e.g. 'azure/chatgpt-v-2' -> 'azure' @@ -178,7 +178,7 @@ def get_llm_provider( # noqa: PLR0915 ) if litellm.LiteLLMProxyChatConfig._should_use_litellm_proxy_by_default( - litellm_params=litellm_params + litellm_params=cast(Optional[LiteLLM_Params], litellm_params) ): return litellm.LiteLLMProxyChatConfig.litellm_proxy_get_custom_llm_provider_info( model=model, api_base=api_base, api_key=api_key @@ -186,12 +186,10 @@ def get_llm_provider( # noqa: PLR0915 ## IF LITELLM PARAMS GIVEN ## if litellm_params: - assert ( - custom_llm_provider is None and api_base is None and api_key is None - ), "Either pass in litellm_params or the custom_llm_provider/api_base/api_key. Otherwise, these values will be overriden." - custom_llm_provider = litellm_params.custom_llm_provider - api_base = litellm_params.api_base - api_key = litellm_params.api_key + if custom_llm_provider is None and api_base is None and api_key is None: + custom_llm_provider = litellm_params.custom_llm_provider + api_base = litellm_params.api_base + api_key = litellm_params.api_key dynamic_api_key = None # check if llm provider provided @@ -235,6 +233,7 @@ def get_llm_provider( # noqa: PLR0915 api_base=api_base, api_key=api_key, dynamic_api_key=dynamic_api_key, + litellm_params=litellm_params, ) # check if llm provider part of model name @@ -250,6 +249,7 @@ def get_llm_provider( # noqa: PLR0915 api_base=api_base, api_key=api_key, dynamic_api_key=dynamic_api_key, + litellm_params=litellm_params, ) elif model.split("/", 1)[0] in litellm.provider_list: custom_llm_provider = model.split("/", 1)[0] @@ -334,6 +334,9 @@ def get_llm_provider( # noqa: PLR0915 elif endpoint == "dashscope-intl.aliyuncs.com/compatible-mode/v1": custom_llm_provider = "dashscope" dynamic_api_key = get_secret_str("DASHSCOPE_API_KEY") + elif endpoint == "https://api-inference.modelscope.cn/v1": + custom_llm_provider = "modelscope" + dynamic_api_key = get_secret_str("MODELSCOPE_API_KEY") elif endpoint == "api.moonshot.ai/v1": custom_llm_provider = "moonshot" dynamic_api_key = get_secret_str("MOONSHOT_API_KEY") @@ -385,6 +388,9 @@ def get_llm_provider( # noqa: PLR0915 elif endpoint == "https://api.inference.wandb.ai/v1": custom_llm_provider = "wandb" dynamic_api_key = get_secret_str("WANDB_API_KEY") + elif endpoint == "https://pinstripes.io/v1": + custom_llm_provider = "pinstripes" + dynamic_api_key = get_secret_str("PINSTRIPES_API_KEY") if api_base is not None and not isinstance(api_base, str): raise Exception( @@ -526,11 +532,11 @@ def get_llm_provider( # noqa: PLR0915 custom_llm_provider = "sap" if not custom_llm_provider: if litellm.suppress_debug_info is False: - print() # noqa - print( # noqa - "\033[1;31mProvider List: https://docs.litellm.ai/docs/providers\033[0m" # noqa - ) # noqa - print() # noqa + print() # noqa: T201 + print( # noqa: T201 + "\033[1;31mProvider List: https://docs.litellm.ai/docs/providers\033[0m" + ) + print() # noqa: T201 error_str = f"LLM Provider NOT provided. Pass in the LLM provider you are trying to call. You passed model={model}\n Pass model as E.g. For 'Huggingface' inference endpoints pass in `completion(model='huggingface/starcoder',..)` Learn more: https://docs.litellm.ai/docs/providers" # maps to openai.NotFoundError, this is raised when openai does not recognize the llm raise litellm.exceptions.BadRequestError( # type: ignore @@ -565,11 +571,12 @@ def get_llm_provider( # noqa: PLR0915 ) -def _get_openai_compatible_provider_info( # noqa: PLR0915 +def _get_openai_compatible_provider_info( model: str, api_base: Optional[str], api_key: Optional[str], dynamic_api_key: Optional[str], + litellm_params: Optional[GenericLiteLLMParams] = None, ) -> Tuple[str, str, Optional[str], Optional[str]]: """ Returns: @@ -637,7 +644,7 @@ def _get_openai_compatible_provider_info( # noqa: PLR0915 api_base, dynamic_api_key, ) = litellm.BedrockMantleChatConfig()._get_openai_compatible_provider_info( - api_base, api_key + api_base, api_key, litellm_params=litellm_params, model=model ) elif custom_llm_provider == "nvidia_nim": # nvidia_nim is openai compatible, we just need to set this to custom_openai and have the api_base be https://api.endpoints.anyscale.com/v1 @@ -926,6 +933,13 @@ def _get_openai_compatible_provider_info( # noqa: PLR0915 ) = litellm.DashScopeChatConfig()._get_openai_compatible_provider_info( api_base, api_key ) + elif custom_llm_provider == "modelscope": + ( + api_base, + dynamic_api_key, + ) = litellm.ModelScopeChatConfig()._get_openai_compatible_provider_info( + api_base, api_key + ) elif custom_llm_provider == "moonshot": ( api_base, diff --git a/litellm/litellm_core_utils/get_supported_openai_params.py b/litellm/litellm_core_utils/get_supported_openai_params.py index 23b51faafc7..e87042b9101 100644 --- a/litellm/litellm_core_utils/get_supported_openai_params.py +++ b/litellm/litellm_core_utils/get_supported_openai_params.py @@ -5,7 +5,7 @@ from litellm.exceptions import BadRequestError from litellm.types.utils import LlmProviders, LlmProvidersSet -def get_supported_openai_params( # noqa: PLR0915 +def get_supported_openai_params( model: str, custom_llm_provider: Optional[str] = None, request_type: Literal[ @@ -295,6 +295,15 @@ def get_supported_openai_params( # noqa: PLR0915 elif custom_llm_provider == "predibase": return litellm.PredibaseConfig().get_supported_openai_params(model=model) elif custom_llm_provider == "voyage": + if ( + request_type == "embeddings" + and litellm.VoyageMultimodalEmbeddingConfig.is_multimodal_embeddings(model) + ): + return ( + litellm.VoyageMultimodalEmbeddingConfig().get_supported_openai_params( + model=model + ) + ) return litellm.VoyageEmbeddingConfig().get_supported_openai_params(model=model) elif custom_llm_provider == "infinity": return litellm.InfinityEmbeddingConfig().get_supported_openai_params( diff --git a/litellm/litellm_core_utils/health_check_helpers.py b/litellm/litellm_core_utils/health_check_helpers.py index 9e972f1910b..5a29ea73a74 100644 --- a/litellm/litellm_core_utils/health_check_helpers.py +++ b/litellm/litellm_core_utils/health_check_helpers.py @@ -44,8 +44,8 @@ class HealthCheckHelpers: model_params["litellm_logging_obj"] = litellm_logging_obj model_params["fallbacks"] = fallback_models model_params["max_tokens"] = model_params.get( - "max_tokens", 10 - ) # gpt-5-nano throws errors for max_tokens=1 + "max_tokens", 16 + ) # GPT-5 models require max_output_tokens >= 16 await acompletion(**model_params) return {} diff --git a/litellm/litellm_core_utils/initialize_dynamic_callback_params.py b/litellm/litellm_core_utils/initialize_dynamic_callback_params.py index a89dae52316..949076aabf3 100644 --- a/litellm/litellm_core_utils/initialize_dynamic_callback_params.py +++ b/litellm/litellm_core_utils/initialize_dynamic_callback_params.py @@ -53,11 +53,19 @@ _supported_callback_params = [ "braintrust_host", "slack_webhook_url", "lunary_public_key", + "dd_api_key", + "dd_site", + "dd_agent_host", + "dd_agent_port", ] _request_blocked_callback_params = { "gcs_bucket_name", "gcs_path_service_account", + "dd_api_key", + "dd_site", + "dd_agent_host", + "dd_agent_port", } diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index f20b66790c4..d750a509054 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -37,6 +37,10 @@ from litellm import ( turn_off_message_logging, ) from litellm._logging import _is_debugging_on, _redact_string, verbose_logger +from litellm.exceptions import ( + validate_rate_limit_category, + validate_rate_limit_type, +) from litellm._uuid import uuid from litellm.batches.batch_utils import _handle_completed_batch from litellm.caching.caching import DualCache, InMemoryCache @@ -154,6 +158,7 @@ from ..integrations.litellm_agent import LiteLLMAgentModelResolver from ..integrations.literal_ai import LiteralAILogger from ..integrations.logfire_logger import LogfireLevel, LogfireLogger from ..integrations.lunary import LunaryLogger +from ..integrations.newrelic import NewRelicLogger from ..integrations.openmeter import OpenMeterLogger from ..integrations.opik.opik import OpikLogger from ..integrations.posthog import PostHogLogger @@ -376,13 +381,14 @@ class Logging(LiteLLMLoggingBaseClass): List[Union[str, Callable, CustomLogger]] ] = dynamic_async_failure_callbacks - # Process dynamic callbacks - self.process_dynamic_callbacks() - ## DYNAMIC LANGFUSE / GCS / logging callback KEYS ## self.standard_callback_dynamic_params: StandardCallbackDynamicParams = ( self.initialize_standard_callback_dynamic_params(kwargs) ) + + # Process dynamic callbacks (after standard_callback_dynamic_params is initialized, + # so team-scoped credentials are available for callback initialization) + self.process_dynamic_callbacks() self.standard_built_in_tools_params: StandardBuiltInToolsParams = ( self.initialize_standard_built_in_tools_params(kwargs) ) @@ -477,8 +483,21 @@ class Logging(LiteLLMLoggingBaseClass): isinstance(callback, str) and callback in litellm._known_custom_logger_compatible_callbacks ): + # For callbacks that support team-scoped credentials (e.g. datadog), + # pass only the relevant dynamic params as custom_logger_init_args. + _custom_logger_init_args: Optional[dict] = None + if callback == "datadog": + _custom_logger_init_args = { + k: v + for k, v in self.standard_callback_dynamic_params.items() + if k.startswith("dd_") + } + callback_class = _init_custom_logger_compatible_class( - callback, internal_usage_cache=None, llm_router=None # type: ignore + callback, # type: ignore[arg-type] + internal_usage_cache=None, + llm_router=None, # type: ignore + custom_logger_init_args=_custom_logger_init_args, ) if callback_class is not None: processed_list.append(callback_class) @@ -967,7 +986,7 @@ class Logging(LiteLLMLoggingBaseClass): self._get_masked_api_base(additional_args.get("api_base", "")) ) - def pre_call(self, input, api_key, model=None, additional_args={}): # noqa: PLR0915 + def pre_call(self, input, api_key, model=None, additional_args={}): # Log the exact input to the LLM API litellm.error_logs["PRE_CALL"] = locals() try: @@ -2100,7 +2119,7 @@ class Logging(LiteLLMLoggingBaseClass): await self.async_success_handler(result=complete_streaming_response) return - def success_handler( # noqa: PLR0915 + def success_handler( self, result=None, start_time=None, end_time=None, cache_hit=None, **kwargs ): verbose_logger.debug( @@ -2565,7 +2584,7 @@ class Logging(LiteLLMLoggingBaseClass): ), ) - async def async_success_handler( # noqa: PLR0915 + async def async_success_handler( self, result=None, start_time=None, end_time=None, cache_hit=None, **kwargs ): """ @@ -2956,7 +2975,12 @@ class Logging(LiteLLMLoggingBaseClass): ) self.model_call_details["end_time"] = end_time self.model_call_details.setdefault("original_response", None) - self.model_call_details["response_cost"] = 0 + # A stream interrupted mid-flight still billed the provider for the + # chunks already delivered; the router stashes that recovered usage as + # ``combined_usage_object`` and pre-computes its cost, so preserve it + # here instead of zeroing the spend on an otherwise-failed request. + if self.model_call_details.get("combined_usage_object") is None: + self.model_call_details["response_cost"] = 0 if hasattr(exception, "headers") and isinstance(exception.headers, dict): self.model_call_details.setdefault("litellm_params", {}) @@ -3017,7 +3041,7 @@ class Logging(LiteLLMLoggingBaseClass): kwargs=self.model_call_details, ) # type: ignore - def failure_handler( # noqa: PLR0915 + def failure_handler( self, exception, traceback_exception, start_time=None, end_time=None ): verbose_logger.debug( @@ -3503,9 +3527,7 @@ class Logging(LiteLLMLoggingBaseClass): else: return None - def _handle_anthropic_messages_response_logging( - self, result: Any - ) -> Union[ModelResponse, ResponsesAPIResponse]: + def _handle_anthropic_messages_response_logging(self, result: Any) -> ModelResponse: """ Handles logging for Anthropic messages responses. @@ -3524,15 +3546,14 @@ class Logging(LiteLLMLoggingBaseClass): return result elif isinstance(result, ModelResponse): return result - elif isinstance( + + if isinstance( result, (ResponseCompletedEvent, ResponseIncompleteEvent, ResponseFailedEvent), ): - # anthropic_messages() can route to OpenAI Responses API; in that path - # the assembled streaming result is one of these terminal events rather than - # a ModelResponse. Return the inner response so downstream handlers - # (_transform_usage_objects, normalize_logging_result) can process it. - return result.response + result = result.response + if isinstance(result, ResponsesAPIResponse): + return self._translate_responses_api_response_to_model_response(result) httpx_response = self.model_call_details.get("httpx_response", None) if httpx_response and isinstance(httpx_response, httpx.Response): @@ -3566,6 +3587,55 @@ class Logging(LiteLLMLoggingBaseClass): ) return result + def _translate_responses_api_response_to_model_response( + self, result: ResponsesAPIResponse + ) -> ModelResponse: + """ + Convert a Responses API response into a ModelResponse for spend_logs. + + The proxy UI parses spend_log rows expecting chat-completion shape + (response.choices[0].message); a raw ResponsesAPIResponse dump (output[...]) + would render as empty in the Logs tab. Translation also yields full + choices/message detail downstream consumers can rely on. + """ + from litellm.completion_extras.litellm_responses_transformation.transformation import ( + LiteLLMResponsesTransformationHandler, + ) + + try: + return LiteLLMResponsesTransformationHandler().transform_response( + model=self.model, + raw_response=result, + model_response=litellm.ModelResponse(), + logging_obj=self, + request_data={}, + messages=[], + optional_params={}, + litellm_params={}, + encoding=litellm.encoding, + ) + except Exception as e: + verbose_logger.debug( + "Responses API -> ModelResponse translation failed for " + "anthropic_messages logging (%s); falling back to minimal " + "usage-only ModelResponse to keep the spend_logs row.", + str(e), + ) + model_response = litellm.ModelResponse() + model_response.model = self.model + usage = getattr(result, "usage", None) + if usage is not None and ResponseAPILoggingUtils._is_response_api_usage( + usage + ): + setattr( + model_response, + "usage", + ResponseAPILoggingUtils._transform_response_api_usage_to_chat_usage( + usage + ), + ) + return model_response + def _handle_non_streaming_google_genai_generate_content_response_logging( self, result: Any ) -> ModelResponse: @@ -3688,7 +3758,7 @@ def _get_masked_values( } -def set_callbacks(callback_list, function_id=None): # noqa: PLR0915 +def set_callbacks(callback_list, function_id=None): """ Globally sets the callback client """ @@ -3789,7 +3859,7 @@ def set_callbacks(callback_list, function_id=None): # noqa: PLR0915 return None -def _init_custom_logger_compatible_class( # noqa: PLR0915 +def _init_custom_logger_compatible_class( logging_integration: _custom_logger_compatible_callbacks_literal, internal_usage_cache: Optional[DualCache], llm_router: Optional[ @@ -3890,6 +3960,24 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915 _in_memory_loggers.append(_prometheus_logger) return _prometheus_logger # type: ignore elif logging_integration == "datadog": + # Check if team-scoped credentials are provided + _dd_api_key = custom_logger_init_args.get("dd_api_key") + _dd_site = custom_logger_init_args.get("dd_site") + _dd_agent_host = custom_logger_init_args.get("dd_agent_host") + _dd_agent_port = custom_logger_init_args.get("dd_agent_port") + + if _dd_api_key or _dd_site or _dd_agent_host: + # Team-scoped credentials: use DynamicLoggingCache for per-credential isolation + from litellm.integrations.datadog.datadog_team_handler import ( + DataDogHandler, + ) + + return DataDogHandler.get_datadog_logger_for_request( + standard_callback_dynamic_params=custom_logger_init_args, # type: ignore + in_memory_dynamic_logger_cache=in_memory_dynamic_logger_cache, + ) + + # Global (env-var based): reuse cached instance for callback in _in_memory_loggers: if isinstance(callback, DataDogLogger): return callback # type: ignore @@ -4120,6 +4208,17 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915 focus_logger = FocusLogger() _in_memory_loggers.append(focus_logger) return focus_logger # type: ignore + elif logging_integration == "mavvrik": + from litellm.integrations.mavvrik_focus.mavvrik_focus_logger import ( + MavvrikFocusLogger, + ) + + for callback in _in_memory_loggers: + if type(callback) is MavvrikFocusLogger: + return callback # type: ignore + mavvrik_focus_logger = MavvrikFocusLogger() + _in_memory_loggers.append(mavvrik_focus_logger) + return mavvrik_focus_logger # type: ignore elif logging_integration == "vantage": from litellm.integrations.vantage.vantage_logger import VantageLogger @@ -4415,6 +4514,13 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915 gitlab_logger = GitLabPromptManager(gitlab_config=gitlab_config) _in_memory_loggers.append(gitlab_logger) return gitlab_logger # type: ignore + elif logging_integration == "newrelic": + for callback in _in_memory_loggers: + if isinstance(callback, NewRelicLogger): + return callback # type: ignore + newrelic_logger = NewRelicLogger() + _in_memory_loggers.append(newrelic_logger) + return newrelic_logger # type: ignore return None except Exception as e: verbose_logger.exception( @@ -4510,7 +4616,7 @@ def _maybe_auto_initialize_arize_phoenix(_in_memory_loggers: list) -> None: ) -def get_custom_logger_compatible_class( # noqa: PLR0915 +def get_custom_logger_compatible_class( logging_integration: _custom_logger_compatible_callbacks_literal, ) -> Optional[CustomLogger]: try: @@ -4716,6 +4822,10 @@ def get_custom_logger_compatible_class( # noqa: PLR0915 for callback in _in_memory_loggers: if isinstance(callback, SMTPEmailLogger): return callback + elif logging_integration == "newrelic": + for callback in _in_memory_loggers: + if isinstance(callback, NewRelicLogger): + return callback return None except Exception as e: @@ -5311,11 +5421,25 @@ class StandardLoggingPayloadSetup: tb_lines[:MAXIMUM_TRACEBACK_LINES_TO_LOG] ) # Limit to first 100 lines + # Prefer the `.message` attribute (set by ProxyException and every + # litellm.exceptions.* class) over str(exc); ProxyException does not + # call super().__init__() nor define __str__, so str() on it returns + # an empty string, which used to silently strip the human-readable + # message from spend_logs.metadata.error_information. + # Use isinstance, not truthiness: an explicit empty string on + # `.message` is a deliberate value and must not be replaced by + # `str(exc)`. explicit_message = getattr(original_exception, "message", None) - error_message = ( - explicit_message - if isinstance(explicit_message, str) and explicit_message - else str(original_exception) + if isinstance(explicit_message, str): + error_message = explicit_message + else: + error_message = str(original_exception) if original_exception else "" + + rate_limit_category = validate_rate_limit_category( + getattr(original_exception, "category", None) + ) + rate_limit_type = validate_rate_limit_type( + getattr(original_exception, "rate_limit_type", None) ) return StandardLoggingPayloadErrorInformation( @@ -5323,9 +5447,42 @@ class StandardLoggingPayloadSetup: error_class=error_class, llm_provider=_llm_provider_in_exception, traceback=traceback_info, - error_message=error_message if original_exception else "", + error_message=error_message, + error_rate_limit_category=rate_limit_category, + error_rate_limit_type=rate_limit_type, ) + @staticmethod + def get_error_information_for_logging_payload( + metadata: dict, + original_exception: Exception | None, + error_str: str | None, + ) -> tuple[StandardLoggingPayloadErrorInformation, str | None]: + error_information = StandardLoggingPayloadSetup.get_error_information( + original_exception=original_exception, + ) + if not metadata.get("client_disconnected"): + return error_information, error_str + + client_disconnect_error = metadata.get("error_information") + if isinstance(client_disconnect_error, dict): + error_information = cast( + StandardLoggingPayloadErrorInformation, + client_disconnect_error, + ) + else: + error_information = cast( + StandardLoggingPayloadErrorInformation, + { + "error_code": "499", + "error_message": "Client disconnected the request", + "error_class": "ClientDisconnected", + }, + ) + if not error_str: + error_str = "Client disconnected the request" + return error_information, error_str + @staticmethod def get_response_time( start_time_float: float, @@ -5653,8 +5810,12 @@ def get_standard_logging_object_payload( api_base=litellm_params.get("api_base"), ) - error_information = StandardLoggingPayloadSetup.get_error_information( - original_exception=original_exception, + error_information, error_str = ( + StandardLoggingPayloadSetup.get_error_information_for_logging_payload( + metadata=metadata, + original_exception=original_exception, + error_str=error_str, + ) ) ## get final response object ## @@ -5773,7 +5934,7 @@ def get_standard_logging_object_payload( def emit_standard_logging_payload(payload: StandardLoggingPayload): if os.getenv("LITELLM_PRINT_STANDARD_LOGGING_PAYLOAD"): - print(json.dumps(payload, indent=4)) # noqa + print(json.dumps(payload, indent=4)) # noqa: T201 def get_standard_logging_metadata( diff --git a/litellm/litellm_core_utils/llm_cost_calc/tool_call_cost_tracking.py b/litellm/litellm_core_utils/llm_cost_calc/tool_call_cost_tracking.py index 8da66d4600d..413ddb71bf8 100644 --- a/litellm/litellm_core_utils/llm_cost_calc/tool_call_cost_tracking.py +++ b/litellm/litellm_core_utils/llm_cost_calc/tool_call_cost_tracking.py @@ -6,6 +6,7 @@ from typing import Any, Dict, List, Literal, Optional, Tuple import litellm from litellm.constants import OPENAI_FILE_SEARCH_COST_PER_1K_CALLS +from litellm.litellm_core_utils.llm_cost_calc.utils import _get_web_search_requests from litellm.types.llms.openai import ( FileSearchTool, ResponsesAPIResponse, @@ -339,8 +340,7 @@ class StandardBuiltInToolCostTracking: # and _handle_web_search_cost() is never called. if ( hasattr(usage, "server_tool_use") - and usage.server_tool_use is not None - and usage.server_tool_use.web_search_requests is not None + and _get_web_search_requests(usage.server_tool_use) is not None ): return True return False @@ -352,8 +352,7 @@ class StandardBuiltInToolCostTracking: elif usage is not None: if ( hasattr(usage, "server_tool_use") - and usage.server_tool_use is not None - and usage.server_tool_use.web_search_requests is not None + and _get_web_search_requests(usage.server_tool_use) is not None ): return True elif ( diff --git a/litellm/litellm_core_utils/llm_cost_calc/utils.py b/litellm/litellm_core_utils/llm_cost_calc/utils.py index f39c942f90f..7a7fde3087e 100644 --- a/litellm/litellm_core_utils/llm_cost_calc/utils.py +++ b/litellm/litellm_core_utils/llm_cost_calc/utils.py @@ -1,7 +1,7 @@ # What is this? ## Helper utilities for cost_per_token() -from typing import Literal, Optional, Tuple, TypedDict, cast +from typing import Any, Literal, Optional, Tuple, TypedDict, cast import litellm from litellm._logging import verbose_logger @@ -42,6 +42,26 @@ def _get_token_detail_value(details: object, key: str) -> Optional[int]: return value if isinstance(value, int) else None +def _get_web_search_requests(server_tool_use: Any) -> Optional[int]: + """ + Tolerantly read ``web_search_requests`` from a ``server_tool_use`` value + that may be ``None``, a ``dict``, a ``ServerToolUse`` pydantic instance, + or any other object supporting attribute access. + + Returns ``None`` when the value cannot be resolved — callers can + distinguish "absent" from "zero" using ``is None``. + + See https://github.com/BerriAI/litellm/issues/26153 — ``stream_chunk_builder`` + historically left this as a plain ``dict``, which broke direct attribute + access in cost calculation. + """ + if server_tool_use is None: + return None + if isinstance(server_tool_use, dict): + return server_tool_use.get("web_search_requests") + return getattr(server_tool_use, "web_search_requests", None) + + def _is_above_128k(tokens: float) -> bool: if tokens > 128000: return True @@ -171,6 +191,11 @@ def _get_service_tier_cost_key(base_key: str, service_tier: Optional[str]) -> st return base_key +def _parse_above_token_threshold(key: str) -> float: + threshold_str = key.split("_above_")[1].split("_tokens")[0] + return float(threshold_str.replace("k", "")) * (1000 if "k" in threshold_str else 1) + + def _get_token_base_cost( model_info: ModelInfo, usage: Usage, service_tier: Optional[str] = None ) -> Tuple[float, float, float, float, float]: @@ -236,15 +261,13 @@ def _get_token_base_cost( # Only sort the threshold keys (typically 1-2 keys instead of 66+) threshold: Optional[float] = None - for key in sorted(threshold_keys, reverse=True): + for key in sorted(threshold_keys, key=_parse_above_token_threshold, reverse=True): value = model_info.get(key) if value is not None: try: # Handle both formats: _above_128k_tokens and _above_128_tokens threshold_str = key.split("_above_")[1].split("_tokens")[0] - threshold = float(threshold_str.replace("k", "")) * ( - 1000 if "k" in threshold_str else 1 - ) + threshold = _parse_above_token_threshold(key) if usage.prompt_tokens > threshold: # Prefer a service_tier-specific above-threshold key when available, # e.g. input_cost_per_token_priority_above_200k_tokens for Gemini @@ -283,40 +306,54 @@ def _get_token_base_cost( # Apply tiered pricing to cache costs cache_creation_tiered_key = ( - f"cache_creation_input_token_cost_above_{threshold_str}_tokens" + _get_service_tier_cost_key( + f"cache_creation_input_token_cost_above_{threshold_str}_tokens", + service_tier, + ) + if service_tier + else f"cache_creation_input_token_cost_above_{threshold_str}_tokens" + ) + cache_creation_1hr_tiered_key = ( + _get_service_tier_cost_key( + f"cache_creation_input_token_cost_above_1hr_above_{threshold_str}_tokens", + service_tier, + ) + if service_tier + else f"cache_creation_input_token_cost_above_1hr_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" + _get_service_tier_cost_key( + f"cache_read_input_token_cost_above_{threshold_str}_tokens", + service_tier, + ) + if service_tier + else f"cache_read_input_token_cost_above_{threshold_str}_tokens" ) - if cache_creation_tiered_key in model_info: - cache_creation_cost = cast( - float, - _get_cost_per_unit( - model_info, - cache_creation_tiered_key, - cache_creation_cost, - ), - ) + cache_creation_cost = cast( + float, + _get_cost_per_unit( + model_info, + cache_creation_tiered_key, + cache_creation_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, - ), - ) + 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, - _get_cost_per_unit( - model_info, cache_read_tiered_key, cache_read_cost - ), - ) + cache_read_cost = cast( + float, + _get_cost_per_unit( + model_info, cache_read_tiered_key, cache_read_cost + ), + ) break except (IndexError, ValueError): @@ -663,7 +700,7 @@ def _get_regional_uplift_multiplier( return 1.0 -def generic_cost_per_token( # noqa: PLR0915 +def generic_cost_per_token( model: str, usage: Usage, custom_llm_provider: str, @@ -929,6 +966,43 @@ def calculate_image_response_cost_from_usage( return prompt_cost + completion_cost +def calculate_image_response_web_search_cost( + image_response: ImageResponse, + custom_llm_provider: str, + model_info: ModelInfo, +) -> float: + """ + Cost of Google Search grounding performed during image generation. + + The grounding request count is carried on the image usage object by the + provider transformers; it is billed with the same per-request accounting + used for chat completions. + """ + usage = image_response.usage + if usage is None: + return 0.0 + + web_search_requests = getattr(usage, "web_search_requests", None) + if not web_search_requests: + return 0.0 + + from litellm.llms import get_cost_for_web_search_request + + synthetic_usage = Usage( + prompt_tokens_details=PromptTokensDetailsWrapper( + web_search_requests=web_search_requests + ) + ) + return ( + get_cost_for_web_search_request( + custom_llm_provider=custom_llm_provider, + usage=synthetic_usage, + model_info=model_info, + ) + or 0.0 + ) + + class CostCalculatorUtils: @staticmethod def _call_type_has_image_response(call_type: str) -> bool: 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 2547fd4d8c6..016bb6b1e22 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 @@ -471,7 +471,7 @@ def _should_convert_tool_call_to_json_mode( return False -def convert_to_model_response_object( # noqa: PLR0915 +def convert_to_model_response_object( response_object: Optional[dict] = None, model_response_object: Optional[ Union[ @@ -633,11 +633,6 @@ def convert_to_model_response_object( # noqa: PLR0915 thinking_blocks = choice["message"]["thinking_blocks"] provider_specific_fields["thinking_blocks"] = thinking_blocks - if reasoning_content: - provider_specific_fields["reasoning_content"] = ( - reasoning_content - ) - message = Message( content=content, role=choice["message"]["role"] or "assistant", diff --git a/litellm/litellm_core_utils/llm_response_utils/response_metadata.py b/litellm/litellm_core_utils/llm_response_utils/response_metadata.py index 06933a6fbcb..ba870eb9459 100644 --- a/litellm/litellm_core_utils/llm_response_utils/response_metadata.py +++ b/litellm/litellm_core_utils/llm_response_utils/response_metadata.py @@ -49,7 +49,8 @@ class ResponseMetadata: result=self.result, litellm_model_name=model, router_model_id=model_id ), "additional_headers": process_response_headers( - self._get_value_from_hidden_params("additional_headers") or {} + self._get_value_from_hidden_params("additional_headers") or {}, + preserve_litellm_internal_headers=True, ), "litellm_model_name": model, } diff --git a/litellm/litellm_core_utils/logging_callback_manager.py b/litellm/litellm_core_utils/logging_callback_manager.py index 6c749118dec..b7adda3a9a4 100644 --- a/litellm/litellm_core_utils/logging_callback_manager.py +++ b/litellm/litellm_core_utils/logging_callback_manager.py @@ -394,6 +394,22 @@ class LoggingCallbackManager: + litellm._async_failure_callback ) + def remove_callback_from_all_lists(self, obj, require_self=False) -> None: + """ + Remove a callback object from every callback list it may have been + promoted into, so a re-initialized callback leaves no stale instance behind. + """ + for callback_list in ( + litellm.callbacks, + litellm.success_callback, + litellm.failure_callback, + litellm._async_success_callback, + litellm._async_failure_callback, + ): + self.remove_callback_from_list_by_object( + callback_list, obj, require_self=require_self + ) + def get_active_additional_logging_utils_from_custom_logger( self, ) -> Set[AdditionalLoggingUtils]: diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py index 1460dbaf0a9..b95b73398ac 100644 --- a/litellm/litellm_core_utils/prompt_templates/factory.py +++ b/litellm/litellm_core_utils/prompt_templates/factory.py @@ -1475,7 +1475,7 @@ def convert_to_gemini_tool_call_invoke( ) -def convert_to_gemini_tool_call_result( # noqa: PLR0915 +def convert_to_gemini_tool_call_result( message: Union[ChatCompletionToolMessage, ChatCompletionFunctionMessage], last_message_with_tool_calls: Optional[dict], model: Optional[str] = None, @@ -2227,7 +2227,7 @@ def _sanitize_empty_text_content( return message -def _add_missing_tool_results( # noqa: PLR0915 +def _add_missing_tool_results( current_message: AllMessageValues, messages: List[AllMessageValues], current_index: int, @@ -2484,7 +2484,7 @@ def sanitize_messages_for_tool_calling( return sanitized_messages -def anthropic_messages_pt( # noqa: PLR0915 +def anthropic_messages_pt( messages: List[AllMessageValues], model: str, llm_provider: str, @@ -3278,7 +3278,7 @@ def convert_to_cohere_tool_invoke(tool_calls: list) -> List[ToolCallObject]: return cohere_tool_invoke -def cohere_messages_pt_v2( # noqa: PLR0915 +def cohere_messages_pt_v2( messages: List, model: str, llm_provider: str, @@ -3653,17 +3653,13 @@ from litellm.types.llms.bedrock import ContentBlock as BedrockContentBlock from litellm.types.llms.bedrock import DocumentBlock as BedrockDocumentBlock from litellm.types.llms.bedrock import ImageBlock as BedrockImageBlock from litellm.types.llms.bedrock import SourceBlock as BedrockSourceBlock +from litellm.types.llms.bedrock import BedrockToolSpec from litellm.types.llms.bedrock import ToolBlock as BedrockToolBlock -from litellm.types.llms.bedrock import ( - ToolInputSchemaBlock as BedrockToolInputSchemaBlock, -) -from litellm.types.llms.bedrock import ToolJsonSchemaBlock as BedrockToolJsonSchemaBlock from litellm.types.llms.bedrock import SearchResultBlock from litellm.types.llms.bedrock import ToolResultBlock as BedrockToolResultBlock from litellm.types.llms.bedrock import ( ToolResultContentBlock as BedrockToolResultContentBlock, ) -from litellm.types.llms.bedrock import ToolSpecBlock as BedrockToolSpecBlock from litellm.types.llms.bedrock import ToolUseBlock as BedrockToolUseBlock from litellm.types.llms.bedrock import VideoBlock as BedrockVideoBlock @@ -4294,6 +4290,49 @@ def _deduplicate_bedrock_tool_content( return _deduplicate_bedrock_content_blocks(tool_content, "toolResult") +def _rename_duplicate_bedrock_document_names( + contents: List[BedrockMessageBlock], +) -> List[BedrockMessageBlock]: + """ + Rename duplicate document names across all messages in a Bedrock request. + + Document names are derived from a content hash, so the same file appearing + in multiple conversation turns produces identical names and Bedrock rejects + the request with "Messages can not contain duplicate document names". The + first occurrence keeps its original name so prompt-cache prefixes stay + stable; later occurrences get a deterministic positional suffix + (``_2``, ``_3``, ...), bumped further if the suffixed name already + belongs to another document (e.g. an organic name ending in ``_2``). + """ + used_names: Set[str] = set() + for message in contents: + for block in message.get("content") or []: + document = block.get("document") + if isinstance(document, dict) and document.get("name"): + used_names.add(document["name"]) + + name_counts: Dict[str, int] = {} + for message in contents: + for block in message.get("content") or []: + document = block.get("document") + if not isinstance(document, dict): + continue + name = document.get("name") + if not name: + continue + count = name_counts.get(name, 0) + 1 + name_counts[name] = count + if count > 1: + suffix = count + new_name = f"{name}_{suffix}" + while new_name in used_names: + suffix += 1 + new_name = f"{name}_{suffix}" + used_names.add(new_name) + document["name"] = new_name + return contents + + def _sort_bedrock_assistant_content_blocks( blocks: List[BedrockContentBlock], ) -> List[BedrockContentBlock]: @@ -4664,7 +4703,7 @@ class BedrockConverseMessagesProcessor: return messages @staticmethod - async def _bedrock_converse_messages_pt_async( # noqa: PLR0915 + async def _bedrock_converse_messages_pt_async( messages: List, model: str, llm_provider: str, @@ -4702,6 +4741,12 @@ class BedrockConverseMessagesProcessor: guardContent={"text": {"text": element["text"]}} ) _parts.append(_part) + elif element["type"] in ("grounding_source", "query"): + # Contextual grounding tags are guardrail metadata; the + # model only needs the underlying text, so render them + # as plain text on the generate path. + _part = BedrockContentBlock(text=element["text"]) + _parts.append(_part) elif element["type"] == "image_url": format: Optional[str] = None if isinstance(element["image_url"], dict): @@ -4942,7 +4987,7 @@ class BedrockConverseMessagesProcessor: llm_provider=llm_provider, ) - return contents + return _rename_duplicate_bedrock_document_names(contents) @staticmethod def translate_thinking_blocks_to_reasoning_content_blocks( @@ -5088,7 +5133,7 @@ class BedrockConverseMessagesProcessor: return assistant_parts -def _bedrock_converse_messages_pt( # noqa: PLR0915 +def _bedrock_converse_messages_pt( messages: List, model: str, llm_provider: str, @@ -5134,6 +5179,12 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915 guardContent={"text": {"text": element["text"]}} ) _parts.append(_part) + elif element["type"] in ("grounding_source", "query"): + # Contextual grounding tags are guardrail metadata; the + # model only needs the underlying text, so render them as + # plain text on the generate path. + _part = BedrockContentBlock(text=element["text"]) + _parts.append(_part) elif element["type"] == "image_url": format: Optional[str] = None if isinstance(element["image_url"], dict): @@ -5364,7 +5415,7 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915 llm_provider=llm_provider, ) - return contents + return _rename_duplicate_bedrock_document_names(contents) def make_valid_bedrock_tool_name(input_tool_name: str) -> str: @@ -5496,6 +5547,7 @@ def _bedrock_tools_pt( ] """ from litellm.llms.bedrock.common_utils import ( + get_bedrock_base_model, normalize_json_schema_custom_types_to_object, ) from litellm.litellm_core_utils.prompt_templates.common_utils import unpack_defs @@ -5503,6 +5555,11 @@ def _bedrock_tools_pt( _valid_json_schema_root_types = frozenset( ("array", "boolean", "integer", "null", "number", "object", "string") ) + # Only Claude on Bedrock honours strict tool schemas; other families + # (Nova, Llama, GPT-OSS) reject the strict field outright. + supports_strict_tools = bool( + model and get_bedrock_base_model(model).startswith("anthropic") + ) tool_block_list: List[BedrockToolBlock] = [] for tool_idx, tool in enumerate(tools): # Check if tool is already a BedrockToolBlock (e.g., systemTool for Nova grounding) @@ -5548,17 +5605,16 @@ def _bedrock_tools_pt( normalize_json_schema_custom_types_to_object(parameters) if parameters.get("type") not in _valid_json_schema_root_types: parameters["type"] = "object" - tool_input_schema = BedrockToolInputSchemaBlock( - json=BedrockToolJsonSchemaBlock( - type=parameters["type"], - properties=parameters.get("properties", {}), - required=parameters.get("required", []), - ) + tool_block = cast( + BedrockToolBlock, + BedrockToolSpec( + name=name, + description=description, + parameters=parameters, + strict=tool.get("function", {}).get("strict", None), + supports_strict_tools=supports_strict_tools, + ), ) - tool_spec = BedrockToolSpecBlock( - inputSchema=tool_input_schema, name=name, description=description - ) - tool_block = BedrockToolBlock(toolSpec=tool_spec) tool_block_list.append(tool_block) ## ADD CACHE POINT TOOL BLOCK ## diff --git a/litellm/litellm_core_utils/realtime_streaming.py b/litellm/litellm_core_utils/realtime_streaming.py index 772f058d9bb..c56a70177bf 100644 --- a/litellm/litellm_core_utils/realtime_streaming.py +++ b/litellm/litellm_core_utils/realtime_streaming.py @@ -47,6 +47,7 @@ class RealTimeStreaming: user_api_key_dict: Optional[Any] = None, request_data: Optional[Dict] = None, backend_uses_beta_protocol: Optional[bool] = None, + force_transcription_model: Optional[str] = None, ): self.websocket = websocket self.backend_ws = backend_ws @@ -100,6 +101,11 @@ class RealTimeStreaming: self._flushing_pending_messages_until_setup: bool = False self._pending_messages_until_setup: List[str] = [] self._pending_messages_byte_total: int = 0 + # Whether this is a transcription-only session (session.type == "transcription", + # e.g. gpt-realtime-whisper). Such sessions must not be sent response.create and + # their input_audio_transcription.completed usage drives duration-based cost. + self._force_transcription_model = force_transcription_model + self._is_transcription_session: bool = force_transcription_model is not None # Per-connection caps for pre-setup audio frames (message count + total bytes). _MAX_BUFFERED_MESSAGES: int = 200 @@ -111,8 +117,12 @@ class RealTimeStreaming: "input_audio_buffer.append", "input_audio_buffer.commit", "input_audio_buffer.clear", + "input_audio_buffer.end", ] ) + _CLIENT_AUDIO_BUFFER_COMMIT_TYPES = frozenset( + ["input_audio_buffer.commit", "input_audio_buffer.end"] + ) _AUDIO_FORMAT_MAP: Dict[str, Dict[str, Any]] = { "pcm16": {"type": "audio/pcm", "rate": 24000}, "g711_ulaw": {"type": "audio/G711-ulaw", "rate": 8000}, @@ -144,7 +154,7 @@ class RealTimeStreaming: return True return False - def store_message(self, message: Union[str, bytes, OpenAIRealtimeEvents]): + def store_message(self, message: Union[str, bytes, dict, OpenAIRealtimeEvents]): """Store message in list""" if isinstance(message, bytes): message = message.decode("utf-8") @@ -154,22 +164,20 @@ class RealTimeStreaming: else: message_obj = cast(Dict[str, Any], json.loads(cast(str, message))) self._collect_tool_calls_from_response_done(cast(dict, message_obj)) + if not self._should_store_message(message_obj): + return try: event_type = message_obj.get("type", "") if event_type in self._SESSION_EVENT_TYPES: - typed_obj = OpenAIRealtimeStreamSessionEvents(**message_obj) # type: ignore + typed_obj: OpenAIRealtimeEvents = OpenAIRealtimeStreamSessionEvents(**message_obj) # type: ignore else: - # Use the base object as a safe catch-all for all other event types - # (both beta and GA), so unknown/new event names never raise here. + # Catch-all base object so unknown/new event names never raise. typed_obj = OpenAIRealtimeStreamResponseBaseObject(**message_obj) # type: ignore except Exception as e: verbose_logger.debug(f"Error parsing message for logging: {e}") - # Don't re-raise — a parse failure must not drop or delay the message - if self._should_store_message(message_obj): - self.messages.append(message_obj) # type: ignore[arg-type] + self.messages.append(message_obj) # type: ignore[arg-type] return - if self._should_store_message(typed_obj): - self.messages.append(typed_obj) + self.messages.append(typed_obj) def _collect_user_input_from_client_event(self, message: Union[str, dict]) -> None: """Extract user text content from client WebSocket events for spend logging.""" @@ -209,6 +217,8 @@ class RealTimeStreaming: self.session_tools = tools # GA: session.type is required; log it for traceability but no action needed verbose_logger.debug(f"Realtime session.type: {session.get('type')}") + if session.get("type") == "transcription": + self._is_transcription_session = True except (json.JSONDecodeError, AttributeError, TypeError): pass @@ -225,6 +235,55 @@ class RealTimeStreaming: except (AttributeError, TypeError): pass + def _detect_transcription_session_from_backend( + self, event_obj: Union[dict, OpenAIRealtimeEvents] + ) -> None: + """Flag transcription-only sessions from backend session events.""" + try: + event_type = event_obj.get("type", "") + if event_type in ( + "transcription_session.created", + "transcription_session.updated", + ): + self._is_transcription_session = True + elif event_type in ("session.created", "session.updated"): + session = cast(dict, event_obj).get("session", {}) or {} + if session.get("type") == "transcription": + self._is_transcription_session = True + except (AttributeError, TypeError): + pass + + def _capture_transcription_usage( + self, event_obj: Union[dict, OpenAIRealtimeEvents] + ) -> None: + """ + Append a usage-only transcription completed event to the logged results so + the cost calculator can bill it by audio duration. The default logged event + types exclude this event, so it is captured here directly for transcription + sessions rather than widening logging for every realtime session. Only the + type and usage are kept — the transcript is already captured separately in + input_messages, so it is not duplicated into the response log here. + """ + try: + usage = event_obj.get("usage") + if usage is None: + return + # If this event type is already captured by store_message (e.g. the user + # logs all realtime events), don't append a second copy. + if self._should_store_message(event_obj): + return + self.messages.append( + cast( + OpenAIRealtimeEvents, + { + "type": "conversation.item.input_audio_transcription.completed", + "usage": usage, + }, + ) + ) + except (AttributeError, TypeError): + pass + def _collect_tool_calls_from_response_done( self, event_obj: Union[dict, OpenAIRealtimeEvents] ) -> None: @@ -285,6 +344,7 @@ class RealTimeStreaming: backend, False if the provider transformation produced no output and the message was effectively dropped. """ + message = self._enforce_transcription_session_model(message) if self.provider_config: transformed = self.provider_config.transform_realtime_request( message, self.model, self.session_configuration_request @@ -304,12 +364,128 @@ class RealTimeStreaming: await self.backend_ws.send(message) # type: ignore[union-attr, attr-defined] return True + def _enforce_transcription_session_model(self, message: str) -> str: + """Force client transcription session updates to the authorized model. + + `/v1/realtime?intent=transcription` may intentionally omit `model` from + the upstream URL for Azure compatibility, but the proxy still authorizes + a resolved LiteLLM model before opening the backend websocket. If a + client later sends a transcription `session.update`, any model embedded + in that update must be rewritten to the same authorized model instead of + allowing a post-auth model/deployment switch. + + Normal realtime sessions keep their independent nested transcription + model behavior because `_force_transcription_model` is only set for + transcription-intent websocket routes. + """ + if self._force_transcription_model is None: + return message + + try: + message_obj = json.loads(message) + except (json.JSONDecodeError, TypeError): + return message + + if message_obj.get("type") not in ( + "session.update", + "transcription_session.update", + ): + return message + + session = message_obj.get("session") + if not isinstance(session, dict): + return message + + if session.get("type") == "transcription": + self._is_transcription_session = True + + authorized_model = self._force_transcription_model + changed = False + + transcription = session.get("input_audio_transcription") + if ( + isinstance(transcription, dict) + and transcription.get("model") != authorized_model + ): + session["input_audio_transcription"] = { + **transcription, + "model": authorized_model, + } + changed = True + + audio = session.get("audio") + if isinstance(audio, dict): + audio_input = audio.get("input") + if isinstance(audio_input, dict): + nested_transcription = audio_input.get("transcription") + if ( + isinstance(nested_transcription, dict) + and nested_transcription.get("model") != authorized_model + ): + session["audio"] = { + **audio, + "input": { + **audio_input, + "transcription": { + **nested_transcription, + "model": authorized_model, + }, + }, + } + changed = True + + if not changed: + return message + return json.dumps(message_obj) + def _uses_deferred_backend_setup(self) -> bool: """True when setup is deferred until the client's first session.update.""" if self.provider_config is None: return False return not self.provider_config.requires_session_configuration() + @staticmethod + def _collapse_buffered_audio_messages(messages: List[str]) -> List[str]: + """Apply ``input_audio_buffer.clear`` semantics before replaying buffered frames. + + During deferred Gemini Live setup, ``clear`` is buffered alongside appends. + On flush each append becomes a provider ``realtimeInput``; ``clear`` must + drop preceding uncommitted appends instead of being forwarded as a no-op. + """ + collapsed: List[str] = [] + pending_appends: List[str] = [] + + for message in messages: + try: + msg_type = json.loads(message).get("type") + except (json.JSONDecodeError, TypeError): + collapsed.extend(pending_appends) + pending_appends = [] + collapsed.append(message) + continue + + if msg_type == "input_audio_buffer.append": + pending_appends.append(message) + elif msg_type == "input_audio_buffer.clear": + pending_appends = [] + elif msg_type in RealTimeStreaming._CLIENT_AUDIO_BUFFER_COMMIT_TYPES: + collapsed.extend(pending_appends) + pending_appends = [] + collapsed.append(message) + else: + collapsed.extend(pending_appends) + pending_appends = [] + collapsed.append(message) + + collapsed.extend(pending_appends) + return collapsed + + def _sync_pending_messages_byte_total(self) -> None: + self._pending_messages_byte_total = sum( + len(message.encode("utf-8")) + for message in self._pending_messages_until_setup + ) + def _should_buffer_client_message_until_setup(self, message: str) -> bool: if not self._uses_deferred_backend_setup(): return False @@ -325,6 +501,18 @@ class RealTimeStreaming: return msg_obj.get("type") in RealTimeStreaming._CLIENT_AUDIO_BUFFER_TYPES def _buffer_pending_message_until_setup(self, message: str) -> None: + try: + msg_type = json.loads(message).get("type") + except (json.JSONDecodeError, TypeError): + msg_type = None + + if msg_type == "input_audio_buffer.clear": + self._pending_messages_until_setup = self._collapse_buffered_audio_messages( + self._pending_messages_until_setup + [message] + ) + self._sync_pending_messages_byte_total() + return + msg_bytes = len(message.encode("utf-8")) if ( len(self._pending_messages_until_setup) @@ -342,7 +530,9 @@ class RealTimeStreaming: ) async def _flush_pending_messages_until_setup(self) -> bool: - pending = self._pending_messages_until_setup + pending = self._collapse_buffered_audio_messages( + self._pending_messages_until_setup + ) self._pending_messages_until_setup = [] self._pending_messages_byte_total = 0 for idx, message in enumerate(pending): @@ -358,8 +548,7 @@ class RealTimeStreaming: for msg in self._pending_messages_until_setup ) verbose_logger.debug( - "Failed to flush buffered client message after setup: %s " - "(%d buffered message(s) retained)", + "Failed to flush buffered client message after setup: %s (%d buffered message(s) retained)", e, len(unsent), ) @@ -376,8 +565,7 @@ class RealTimeStreaming: return True except Exception as e: verbose_logger.warning( - "Failed to translate %s to beta protocol, forwarding " - "untranslated event to client: %s", + "Failed to translate %s to beta protocol, forwarding untranslated event to client: %s", event.get("type"), e, ) @@ -429,16 +617,13 @@ class RealTimeStreaming: if sent: self._guardrail_turn_detection_update_sent = True - def _has_realtime_guardrails(self) -> bool: - """Return True if any callback is registered for realtime guardrail event types.""" + def _has_realtime_guardrails_for_event_hooks( + self, + event_hooks: List[Any], + ) -> bool: + """Return True if any callback would run for one of ``event_hooks``.""" from litellm.integrations.custom_guardrail import CustomGuardrail - from litellm.types.guardrails import GuardrailEventHooks - _realtime_event_types = [ - GuardrailEventHooks.realtime_input_transcription, - GuardrailEventHooks.pre_call, - GuardrailEventHooks.post_call, - ] return any( isinstance(cb, CustomGuardrail) and any( @@ -446,31 +631,45 @@ class RealTimeStreaming: data=self.request_data, event_type=et, ) - for et in _realtime_event_types + for et in event_hooks ) for cb in litellm.callbacks ) + def _has_realtime_guardrails(self) -> bool: + """Return True if any callback is registered for realtime guardrail event types.""" + from litellm.types.guardrails import GuardrailEventHooks + + return self._has_realtime_guardrails_for_event_hooks( + [ + GuardrailEventHooks.realtime_input_transcription, + GuardrailEventHooks.pre_call, + GuardrailEventHooks.post_call, + ] + ) + def _has_audio_transcription_guardrails(self) -> bool: - """Return True if any callback needs to run on audio transcriptions (VAD path). + """Return True when a guardrail is configured for the audio/VAD transcript path. - When this returns True, we inject a session.update to disable the LLM's - auto-response so the guardrail can gate it first. - - Must match the same hook criteria as run_realtime_guardrails() so that - any guardrail that would actually check the transcript also disables - auto-response before the transcript arrives. + Only ``realtime_input_transcription`` hooks disable ``server_vad`` auto-response. + ``pre_call`` / ``post_call`` guardrails (e.g. Model Armor on chat completions) + must not override ``turn_detection.create_response`` on realtime sessions. """ - return self._has_realtime_guardrails() + from litellm.types.guardrails import GuardrailEventHooks + + return self._has_realtime_guardrails_for_event_hooks( + [GuardrailEventHooks.realtime_input_transcription] + ) async def run_realtime_guardrails( self, transcript: str, item_id: Optional[str] = None, pre_block_backend_message: Optional[str] = None, + event_hooks: Optional[List[Any]] = None, ) -> bool: """ - Run registered guardrails on a completed speech transcription. + Run registered guardrails on realtime text (transcript, user message, tool output). Returns True if blocked (synthetic warning already sent to client). Returns False if clean (caller should send response.create to the backend). @@ -481,15 +680,17 @@ class RealTimeStreaming: specific message to be sent first — e.g. Gemini Live requires a matching ``toolResponse`` immediately after a ``toolCall`` before any other client messages can be accepted. + + ``event_hooks`` selects which guardrail modes to evaluate. Audio/VAD + transcript completion uses ``realtime_input_transcription`` only; + typed user messages and tool outputs use ``pre_call``. """ from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.types.guardrails import GuardrailEventHooks - _realtime_event_types = [ - GuardrailEventHooks.realtime_input_transcription, - GuardrailEventHooks.pre_call, - GuardrailEventHooks.post_call, - ] + if event_hooks is None: + event_hooks = [GuardrailEventHooks.realtime_input_transcription] + _realtime_event_types = event_hooks _check_data = {**self.request_data, "transcript": transcript} _already_run: set = set() @@ -705,48 +906,58 @@ class RealTimeStreaming: self.store_message(event_str) await self._send_event_to_client(event, event_str) - async def _handle_raw_backend_message(self, raw_response) -> bool: + @staticmethod + def _parse_backend_event(raw_response: str) -> Optional[dict]: + """Parse a backend frame once. Returns None for non-JSON or non-object frames.""" + try: + event = json.loads(raw_response) + except (json.JSONDecodeError, TypeError): + return None + return event if isinstance(event, dict) else None + + async def _handle_raw_backend_message( + self, event_obj: dict, raw_response: str + ) -> bool: """Process a backend message without provider_config (raw path). Returns True if the caller should skip the default store+forward (i.e. continue the loop). """ - try: - event_obj = json.loads(raw_response) + event_type = event_obj.get("type") - # For audio/VAD guardrail path: once the session is ready, tell the backend - # not to auto-respond after VAD detects end-of-speech. We send the - # session.created to the client FIRST so the client is always in sync, then - # inject the session.update so a potential error from the backend doesn't - # arrive before the client sees session.created. - if ( - event_obj.get("type") == "session.created" - and self._has_audio_transcription_guardrails() - ): - self.store_message(raw_response) - await self.websocket.send_text(raw_response) - await self._send_to_backend(self._make_disable_auto_response_message()) + self._detect_transcription_session_from_backend(event_obj) + + # Send session.created to the client FIRST so it stays in sync, then inject + # the disable-auto-response session.update; otherwise a backend error could + # reach the client before it sees session.created. + if ( + event_type == "session.created" + and self._has_audio_transcription_guardrails() + ): + self.store_message(event_obj) + await self.websocket.send_text(raw_response) + await self._send_to_backend(self._make_disable_auto_response_message()) + return True + + if event_type == "conversation.item.input_audio_transcription.completed": + transcript = event_obj.get("transcript", "") + self._collect_user_input_from_backend_event(event_obj) + self.store_message(event_obj) + await self.websocket.send_text(raw_response) + + # Transcription-only sessions (e.g. gpt-realtime-whisper) have no + # assistant turn: capture audio-duration usage for cost and never + # trigger response.create. + if self._is_transcription_session: + self._capture_transcription_usage(event_obj) return True - if ( - event_obj.get("type") - == "conversation.item.input_audio_transcription.completed" - ): - transcript = event_obj.get("transcript", "") - self._collect_user_input_from_backend_event(event_obj) - ## LOGGING — must happen before continue below - self.store_message(raw_response) - # Forward transcript to client so user sees what they said - await self.websocket.send_text(raw_response) - blocked = await self.run_realtime_guardrails( - transcript, - item_id=event_obj.get("item_id"), - ) - if not blocked: - # Clean — trigger LLM response - await self._send_to_backend(json.dumps({"type": "response.create"})) - return True - except (json.JSONDecodeError, AttributeError): - pass + blocked = await self.run_realtime_guardrails( + transcript, + item_id=event_obj.get("item_id"), + ) + if not blocked: + await self._send_to_backend(json.dumps({"type": "response.create"})) + return True return False async def backend_to_client_send_messages(self): @@ -779,25 +990,25 @@ class RealTimeStreaming: ) continue else: - handled = await self._handle_raw_backend_message(raw_response) - if handled: - continue - ## LOGGING - self.store_message(raw_response) - - # If the client opted into beta protocol, translate GA event - # names/shapes back to the beta equivalents before forwarding. - if self._client_wants_beta: - try: - event_dict = json.loads(raw_response) - translated = self._translate_event_to_beta(event_dict) - if translated is None: - continue # drop GA-only events (e.g. conversation.item.done) - await self.websocket.send_text(json.dumps(translated)) - except Exception: - await self.websocket.send_text(raw_response) - else: + event = self._parse_backend_event(raw_response) + if event is None: await self.websocket.send_text(raw_response) + continue + + if await self._handle_raw_backend_message(event, raw_response): + continue + self.store_message(event) + + if not self._client_wants_beta: + await self.websocket.send_text(raw_response) + continue + + translated = self._translate_event_to_beta(event) + if translated is None: + continue + await self.websocket.send_text( + raw_response if translated is event else json.dumps(translated) + ) except websockets.exceptions.ConnectionClosed as e: # type: ignore verbose_logger.exception( @@ -927,41 +1138,43 @@ class RealTimeStreaming: def _translate_event_to_beta(event: dict) -> Optional[dict]: """Translate a single GA event dict to its beta equivalent. - Returns None if the event should be dropped entirely (e.g. the GA-only - conversation.item.done has no beta counterpart). - Returns the (possibly mutated copy of the) event otherwise. + Returns None when the event must be dropped (the GA-only + conversation.item.done has no beta counterpart). Returns the original + event object unchanged when no translation applies, so the caller can + forward the raw frame without re-serializing; otherwise returns a + translated copy. """ event_type = event.get("type", "") - # conversation.item.done has no beta equivalent — the client already - # received conversation.item.created (translated from .added). if event_type == "conversation.item.done": return None - # Shallow-copy so we don't mutate the stored message + renamed_type = RealTimeStreaming._GA_TO_BETA_EVENT_TYPES.get(event_type) + has_item = isinstance(event.get("item"), dict) + response = event.get("response") + has_response_output = isinstance(response, dict) and isinstance( + response.get("output"), list + ) + if renamed_type is None and not has_item and not has_response_output: + return event + translated = dict(event) - - # Rename the type field - if event_type in RealTimeStreaming._GA_TO_BETA_EVENT_TYPES: - translated["type"] = RealTimeStreaming._GA_TO_BETA_EVENT_TYPES[event_type] - - # Fix content block types inside items (response.done output list, - # conversation.item.created item content, etc.) - if "item" in translated and isinstance(translated["item"], dict): + if renamed_type is not None: + translated["type"] = renamed_type + if has_item: translated["item"] = RealTimeStreaming._translate_item_content_types( dict(translated["item"]) ) - if "response" in translated and isinstance(translated["response"], dict): + if has_response_output: resp = dict(translated["response"]) - if "output" in resp and isinstance(resp["output"], list): - resp["output"] = [ - ( - RealTimeStreaming._translate_item_content_types(dict(o)) - if isinstance(o, dict) - else o - ) - for o in resp["output"] - ] + resp["output"] = [ + ( + RealTimeStreaming._translate_item_content_types(dict(o)) + if isinstance(o, dict) + else o + ) + for o in resp["output"] + ] translated["response"] = resp return translated @@ -985,7 +1198,7 @@ class RealTimeStreaming: item["content"] = new_content return item - async def client_ack_messages(self): # noqa: PLR0915 + async def client_ack_messages(self): try: while True: message = await self.websocket.receive_text() @@ -994,6 +1207,8 @@ class RealTimeStreaming: guardrail_turn_detection_injected = False msg_type: Optional[str] = None try: + from litellm.types.guardrails import GuardrailEventHooks + msg_obj = json.loads(message) msg_type = msg_obj.get("type") @@ -1046,6 +1261,7 @@ class RealTimeStreaming: blocked = await self.run_realtime_guardrails( output_text, pre_block_backend_message=sanitized_msg, + event_hooks=[GuardrailEventHooks.pre_call], ) if blocked: # ``_pending_guardrail_message`` is @@ -1071,7 +1287,8 @@ class RealTimeStreaming: combined_text = " ".join(texts) if combined_text: blocked = await self.run_realtime_guardrails( - combined_text + combined_text, + event_hooks=[GuardrailEventHooks.pre_call], ) if blocked: # Store the guardrail reason so the next response.create diff --git a/litellm/litellm_core_utils/redact_messages.py b/litellm/litellm_core_utils/redact_messages.py index dbc9cabdc7a..763596336a0 100644 --- a/litellm/litellm_core_utils/redact_messages.py +++ b/litellm/litellm_core_utils/redact_messages.py @@ -17,6 +17,10 @@ from litellm.integrations.custom_logger import CustomLogger from litellm.litellm_core_utils.core_helpers import ( get_metadata_variable_name_from_kwargs, ) +from litellm.llms.vertex_ai.common_utils import ( + redact_vertex_ai_metadata_from_litellm_params, + redact_vertex_ai_metadata_from_logged_object, +) from litellm.secret_managers.main import str_to_bool from litellm.types.utils import StandardCallbackDynamicParams @@ -119,10 +123,12 @@ def _redact_standard_logging_object(model_call_details: dict): # ResponsesAPIResponse format - redact content in output items if isinstance(response.get("output"), list): _redact_responses_api_output_dict(response["output"], redacted_str) + redact_vertex_ai_metadata_from_logged_object(response) elif isinstance(response, dict) and "choices" in response: # ModelResponse dict format - redact content in choices if isinstance(response.get("choices"), list): _redact_model_response_dict_choices(response["choices"], redacted_str) + redact_vertex_ai_metadata_from_logged_object(response) elif isinstance(response, str): standard_logging_object["response"] = redacted_str else: @@ -164,6 +170,7 @@ def perform_redaction(model_call_details: dict, result): model_call_details["prompt"] = "" model_call_details["input"] = "" _redact_standard_logging_object(model_call_details) + redact_vertex_ai_metadata_from_litellm_params(model_call_details) # Redact streaming response if ( @@ -174,6 +181,7 @@ def perform_redaction(model_call_details: dict, result): if hasattr(_streaming_response, "choices"): for choice in _streaming_response.choices: _redact_choice_content(choice) + redact_vertex_ai_metadata_from_logged_object(_streaming_response) elif hasattr(_streaming_response, "output"): _redact_responses_api_output(_streaming_response.output) # Redact reasoning field in ResponsesAPIResponse @@ -200,12 +208,14 @@ def perform_redaction(model_call_details: dict, result): if hasattr(_result, "choices") and _result.choices is not None: for choice in _result.choices: _redact_choice_content(choice) + redact_vertex_ai_metadata_from_logged_object(_result) elif isinstance(_result, dict) and "choices" in _result: # Handle dict representation of ModelResponse (e.g., from model_dump()) if _result.get("choices") is not None: _redact_model_response_dict_choices( _result["choices"], "redacted-by-litellm" ) + redact_vertex_ai_metadata_from_logged_object(_result) elif isinstance(_result, dict) and "output" in _result: if isinstance(_result.get("output"), list): _redact_responses_api_output_dict( diff --git a/litellm/litellm_core_utils/streaming_chunk_builder_utils.py b/litellm/litellm_core_utils/streaming_chunk_builder_utils.py index fe7c62c3842..04f6b1241c3 100644 --- a/litellm/litellm_core_utils/streaming_chunk_builder_utils.py +++ b/litellm/litellm_core_utils/streaming_chunk_builder_utils.py @@ -20,6 +20,7 @@ from litellm.types.utils import ( ServerToolUse, Usage, ) +from litellm._logging import verbose_logger from litellm.utils import print_verbose, token_counter if TYPE_CHECKING: @@ -79,6 +80,54 @@ class ChunkProcessor: model_response._hidden_params = chunk.get("_hidden_params", {}) return model_response + @staticmethod + def apply_provider_assembled_streaming_metadata( + response: ModelResponse, + chunks: List[Any], + logging_obj: Optional[Any] = None, + ) -> None: + if not chunks: + return + + model = getattr(response, "model", None) + if not model: + return + + custom_llm_provider = None + if logging_obj is not None: + custom_llm_provider = logging_obj.model_call_details.get( + "custom_llm_provider" + ) + + try: + from litellm.litellm_core_utils.get_llm_provider_logic import ( + get_llm_provider, + ) + from litellm.types.utils import LlmProviders + from litellm.utils import ProviderConfigManager + + if custom_llm_provider: + provider = LlmProviders(custom_llm_provider) + else: + _, provider_str, _, _ = get_llm_provider(model) + provider = LlmProviders(provider_str) + + provider_config = ProviderConfigManager.get_provider_chat_config( + model=model, + provider=provider, + ) + if provider_config is not None: + provider_config.apply_assembled_streaming_response_metadata( + response=response, + chunks=chunks, + ) + except Exception as e: + verbose_logger.debug( + "apply_provider_assembled_streaming_metadata failed for model=%s: %s", + model, + e, + ) + @staticmethod def _get_chunk_id(chunks: List[Dict[str, Any]]) -> str: """ @@ -160,7 +209,7 @@ class ChunkProcessor: ) return response - def get_combined_tool_content( # noqa: PLR0915 + def get_combined_tool_content( self, tool_call_chunks: List[Dict[str, Any]] ) -> List[ChatCompletionMessageToolCall]: tool_calls_list: List[ChatCompletionMessageToolCall] = [] @@ -555,6 +604,8 @@ class ChunkProcessor: usage_chunk = chunk._hidden_params.get("usage", None) if usage_chunk is not None: + if isinstance(usage_chunk, dict): + usage_chunk = Usage(**usage_chunk) usage_chunk_dict = self._usage_chunk_calculation_helper(usage_chunk) if ( usage_chunk_dict["prompt_tokens"] is not None @@ -588,7 +639,18 @@ class ChunkProcessor: hasattr(usage_chunk, "server_tool_use") and usage_chunk.server_tool_use is not None ): - server_tool_use = usage_chunk.server_tool_use + # Coerce dict to ServerToolUse so downstream cost-calc code + # (which accesses .web_search_requests as an attribute) + # doesn't raise AttributeError. Some providers / streaming + # paths leave server_tool_use as a plain dict on the chunk. + if isinstance(usage_chunk.server_tool_use, dict): + server_tool_use = ServerToolUse(**usage_chunk.server_tool_use) + elif isinstance(usage_chunk.server_tool_use, ServerToolUse): + server_tool_use = usage_chunk.server_tool_use + else: + server_tool_use = ServerToolUse.model_validate( + usage_chunk.server_tool_use + ) if ( usage_chunk_dict["prompt_tokens_details"] is not None and getattr( diff --git a/litellm/litellm_core_utils/streaming_handler.py b/litellm/litellm_core_utils/streaming_handler.py index f3274151e5a..d3330c3dcec 100644 --- a/litellm/litellm_core_utils/streaming_handler.py +++ b/litellm/litellm_core_utils/streaming_handler.py @@ -92,7 +92,7 @@ def is_async_iterable(obj: Any) -> bool: def print_verbose(print_statement): try: if litellm.set_verbose: - print(print_statement) # noqa + print(print_statement) # noqa: T201 except Exception: pass @@ -295,6 +295,12 @@ class CustomStreamWrapper: if len(self.chunks) < 2: return + # Providers like Vertex Gemini (Flash / Flash Lite with web search) emit + # metadata-only / usage-only chunks with no choices. These get stored in + # self.chunks but carry no comparable content, so skip repetition detection. + if not self.chunks[-1].choices or not self.chunks[-2].choices: + return + last_content = self.chunks[-1].choices[0].delta.content if ( @@ -961,7 +967,7 @@ class CustomStreamWrapper: delta, model_response.choices[0].delta, attribute ) - def return_processed_chunk_logic( # noqa + def return_processed_chunk_logic( # noqa: C901 self, completion_obj: Dict[str, Any], model_response: ModelResponseStream, @@ -1139,7 +1145,7 @@ class CustomStreamWrapper: del model_response.choices[0].delta.reasoning_content return - def chunk_creator(self, chunk: Any): # type: ignore # noqa: PLR0915 + def chunk_creator(self, chunk: Any): # type: ignore if hasattr(chunk, "id"): self.response_id = chunk.id model_response = self.model_response_creator() @@ -1881,7 +1887,7 @@ class CustomStreamWrapper: model_response.choices[0].finish_reason = "tool_calls" return model_response - def __next__(self) -> "ModelResponseStream": # noqa: PLR0915 + def __next__(self) -> "ModelResponseStream": cache_hit = False if ( self.custom_llm_provider is not None @@ -2071,7 +2077,7 @@ class CustomStreamWrapper: return self.completion_stream - async def __anext__(self) -> "ModelResponseStream": # noqa: PLR0915 + async def __anext__(self) -> "ModelResponseStream": cache_hit = False if ( self.custom_llm_provider is not None @@ -2284,6 +2290,7 @@ class CustomStreamWrapper: litellm.request_timeout ) if self.logging_obj is not None: + self._record_partial_usage_for_failure() ## LOGGING threading.Thread( target=self.logging_obj.failure_handler, @@ -2297,6 +2304,7 @@ class CustomStreamWrapper: except Exception as e: traceback_exception = traceback.format_exc() if self.logging_obj is not None: + self._record_partial_usage_for_failure() ## LOGGING threading.Thread( target=self.logging_obj.failure_handler, @@ -2308,6 +2316,33 @@ class CustomStreamWrapper: ) self._handle_stream_fallback_error(e) + def _record_partial_usage_for_failure(self) -> None: + """ + A stream that breaks mid-flight still billed the provider for the chunks + already delivered. Recover that partial usage from the chunks seen so + far and stash it, with its cost, on the logging object so the failure + handler records the real partial spend instead of zero. A request that + later recovers via a router fallback overwrites this with the combined + success log on the same request id, so this never double counts. + """ + if self.logging_obj is None or not self.chunks: + return + try: + partial_response = litellm.stream_chunk_builder(chunks=self.chunks) + usage = cast(Optional[Usage], getattr(partial_response, "usage", None)) + if usage is None: + return + self.logging_obj.model_call_details["combined_usage_object"] = usage + self.logging_obj.model_call_details["response_cost"] = ( + self.logging_obj._response_cost_calculator(result=partial_response) + or 0.0 + ) + except Exception as recover_error: + verbose_logger.debug( + "could not recover partial usage for interrupted stream: %s", + recover_error, + ) + def _handle_stream_fallback_error(self, e: Exception) -> "NoReturn": """ Common error handling for both __next__ and __anext__. diff --git a/litellm/litellm_core_utils/token_counter.py b/litellm/litellm_core_utils/token_counter.py index 74b41062174..c766c6edec1 100644 --- a/litellm/litellm_core_utils/token_counter.py +++ b/litellm/litellm_core_utils/token_counter.py @@ -744,6 +744,17 @@ def _count_content_list( thinking_text = str(c.get("thinking", "")) if thinking_text: num_tokens += count_function(thinking_text) + elif c["type"] == "tool_reference": + # Anthropic tool-search reference block: a lightweight pointer to + # a deferred tool, e.g. {"type": "tool_reference", "tool_name": ...}. + # The full tool definition is counted via the `tools` param, so we + # only count the referenced name here. Without this branch, + # token_counter raises on tool-search traffic; on the streaming + # anthropic_messages path that nulls response_cost and causes the + # proxy to drop the SpendLogs row entirely (silent cost undercount). + tool_name = str(c.get("tool_name") or "") + if tool_name: + num_tokens += count_function(tool_name) else: content_type = ( c.get("type", type(c).__name__) @@ -752,7 +763,7 @@ def _count_content_list( ) raise ValueError( f"Invalid content item type: {content_type}. " - f"Expected str or dict with 'type' field (text, image_url, tool_use, tool_result, thinking)." + f"Expected str or dict with 'type' field (text, image_url, tool_use, tool_result, thinking, tool_reference)." ) return num_tokens except Exception as e: diff --git a/litellm/llms/anthropic/chat/handler.py b/litellm/llms/anthropic/chat/handler.py index 2fb29b32a61..5d14f3cc4ae 100644 --- a/litellm/llms/anthropic/chat/handler.py +++ b/litellm/llms/anthropic/chat/handler.py @@ -772,7 +772,7 @@ class ModelResponseIterator: ) return results - def chunk_parser(self, chunk: dict) -> ModelResponseStream: # noqa: PLR0915 + def chunk_parser(self, chunk: dict) -> ModelResponseStream: try: type_chunk = chunk.get("type", "") or "" diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index 7949e150c23..c24c990f356 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -605,7 +605,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): ) return _tool_choice - def _map_tool_helper( # noqa: PLR0915 + def _map_tool_helper( self, tool: ChatCompletionToolParam, ) -> Tuple[Optional[AllAnthropicToolsValues], Optional[AnthropicMcpServerTool]]: @@ -1399,7 +1399,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): return None - def map_openai_params( # noqa: PLR0915 + def map_openai_params( self, non_default_params: dict, optional_params: dict, @@ -1455,10 +1455,15 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): _value = self._map_stop_sequences(value) if _value is not None: optional_params["stop_sequences"] = _value - elif param == "temperature": - optional_params["temperature"] = value - elif param == "top_p": - optional_params["top_p"] = value + elif param == "temperature" or param == "top_p": + AnthropicConfig._apply_sampling_param( + optional_params=optional_params, + model=model, + param=param, + value=value, + drop_params=drop_params, + output_key=param, + ) elif param == "response_format" and isinstance(value, dict): if any( substring in model @@ -1607,6 +1612,15 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): ) return _tool + def should_strip_billing_metadata(self) -> bool: + """ + Whether to drop x-anthropic-billing-header system blocks before sending upstream. + + The first-party Anthropic API uses these blocks for Claude Code attribution, so the + base config keeps them. Providers that reject them (e.g. Bedrock) override this to True. + """ + return False + def translate_system_message( self, messages: List[AllMessageValues] ) -> List[AnthropicSystemMessageContent]: @@ -1614,7 +1628,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): Translate system message to anthropic format. Removes system message from the original list and returns a new list of anthropic system message content. - Filters out system messages containing x-anthropic-billing-header metadata. + When should_strip_billing_metadata() is True, x-anthropic-billing-header system blocks are dropped. """ system_prompt_indices = [] anthropic_system_message_list: List[AnthropicSystemMessageContent] = [] @@ -1626,10 +1640,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): # Skip empty text blocks - Anthropic API raises errors for empty text if not system_message_block["content"]: continue - # Skip system messages containing x-anthropic-billing-header metadata - if system_message_block["content"].startswith( - "x-anthropic-billing-header:" - ): + if self.should_strip_billing_metadata() and system_message_block[ + "content" + ].startswith("x-anthropic-billing-header:"): continue anthropic_system_message_content = AnthropicSystemMessageContent( type="text", @@ -1648,9 +1661,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): text_value = _content.get("text") if _content.get("type") == "text" and not text_value: continue - # Skip system messages containing x-anthropic-billing-header metadata if ( - _content.get("type") == "text" + self.should_strip_billing_metadata() + and _content.get("type") == "text" and text_value and text_value.startswith("x-anthropic-billing-header:") ): @@ -1967,6 +1980,20 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): optional_params.pop("is_vertex_request", None) optional_params.pop("client_metadata", None) + # ``top_k`` is a provider-specific kwarg that bypasses + # ``map_openai_params``; gate it here, the single boundary shared by + # the direct Anthropic, Bedrock invoke, Vertex, and Azure paths. + top_k = optional_params.pop("top_k", None) + if top_k is not None: + AnthropicConfig._apply_sampling_param( + optional_params=optional_params, + model=model, + param="top_k", + value=top_k, + drop_params=litellm_params.get("drop_params") is True, + output_key="top_k", + ) + data = { "model": model, "messages": anthropic_messages, @@ -2186,19 +2213,38 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): inference_geo: Optional[str] = None if "inference_geo" in _usage and _usage["inference_geo"] is not None: inference_geo = _usage["inference_geo"] + service_tier = cast( + str | None, + _usage.get("service_tier"), + ) - if ( - "cache_creation_input_tokens" in _usage - and _usage["cache_creation_input_tokens"] is not None - ): - cache_creation_input_tokens = _usage["cache_creation_input_tokens"] - prompt_tokens += cache_creation_input_tokens - if ( - "cache_read_input_tokens" in _usage - and _usage["cache_read_input_tokens"] is not None - ): - cache_read_input_tokens = _usage["cache_read_input_tokens"] - prompt_tokens += cache_read_input_tokens + iterations: Optional[List[Any]] = _usage.get("iterations") + if iterations: + prompt_tokens = sum(it.get("input_tokens", 0) or 0 for it in iterations) + completion_tokens = sum( + it.get("output_tokens", 0) or 0 for it in iterations + ) + cache_creation_input_tokens = sum( + it.get("cache_creation_input_tokens", 0) or 0 for it in iterations + ) + cache_read_input_tokens = sum( + it.get("cache_read_input_tokens", 0) or 0 for it in iterations + ) + prompt_tokens += cache_creation_input_tokens + cache_read_input_tokens + + if not iterations: + if ( + "cache_creation_input_tokens" in _usage + and _usage["cache_creation_input_tokens"] is not None + ): + cache_creation_input_tokens = _usage["cache_creation_input_tokens"] + prompt_tokens += cache_creation_input_tokens + if ( + "cache_read_input_tokens" in _usage + and _usage["cache_read_input_tokens"] is not None + ): + cache_read_input_tokens = _usage["cache_read_input_tokens"] + prompt_tokens += cache_read_input_tokens if "server_tool_use" in _usage and _usage["server_tool_use"] is not None: if ( "web_search_requests" in _usage["server_tool_use"] @@ -2237,7 +2283,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): ), ) - raw_input_tokens = usage_object.get("input_tokens", 0) or 0 + raw_input_tokens = ( + prompt_tokens - cache_read_input_tokens - cache_creation_input_tokens + ) prompt_tokens_details = PromptTokensDetailsWrapper( cached_tokens=cache_read_input_tokens, cache_creation_tokens=cache_creation_input_tokens, @@ -2269,6 +2317,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): cache_creation_input_tokens=cache_creation_input_tokens, cache_read_input_tokens=cache_read_input_tokens, completion_tokens_details=completion_token_details, + iterations=iterations, server_tool_use=( ServerToolUse( web_search_requests=web_search_requests, @@ -2279,6 +2328,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): ), inference_geo=inference_geo, speed=speed, + service_tier=service_tier, ) return usage diff --git a/litellm/llms/anthropic/common_utils.py b/litellm/llms/anthropic/common_utils.py index 3f002d73cbc..5741513903c 100644 --- a/litellm/llms/anthropic/common_utils.py +++ b/litellm/llms/anthropic/common_utils.py @@ -272,23 +272,68 @@ class AnthropicModelInfo(BaseLLMModelInfo): ) @staticmethod - def _supports_model_capability(model: str, key: str) -> bool: - """Check a boolean capability ``key`` in the model map. + def _supports_sampling_params(model: str) -> bool: + """Claude 4.7+ (Opus 4.7/4.8, Fable 5) removed sampling params: the API + rejects ``top_p``, ``top_k``, and any ``temperature`` other than 1 with + a 400 ("`temperature` is deprecated for this model"). - Strips bedrock/vertex prefixes so a provider-routed Claude still - resolves to the Anthropic model-map entry. - """ - from litellm.utils import _supports_factory + Driven by the ``supports_sampling_params`` flag in the model map; the + name check remains only as a fallback for provider-routed ids whose + map entries predate the flag.""" + flag = AnthropicModelInfo._get_model_capability( + model, "supports_sampling_params" + ) + if flag is not None: + return flag + model_lower = model.lower() + return not any( + v in model_lower + for v in ( + "fable", + "opus-4-7", + "opus_4_7", + "opus-4.7", + "opus_4.7", + "opus-4-8", + "opus_4_8", + "opus-4.8", + "opus_4.8", + ) + ) - try: - if _supports_factory( - model=model, - custom_llm_provider="anthropic", - key=key, - ): - return True - except Exception: - pass + @staticmethod + def _apply_sampling_param( + optional_params: dict, + model: str, + param: str, + value: Any, + drop_params: bool, + output_key: str, + ) -> None: + """Forward ``temperature``/``top_p``/``top_k`` to + ``optional_params[output_key]`` unless the model removed sampling + params, in which case drop the param (with drop_params) or raise a + clean client-side 400.""" + if AnthropicModelInfo._supports_sampling_params(model) or ( + param == "temperature" and value == 1 + ): + optional_params[output_key] = value + elif not (litellm.drop_params or drop_params): + supported_hint = ( + "Only temperature=1 is supported. " if param == "temperature" else "" + ) + raise litellm.utils.UnsupportedParamsError( + message=( + f"{model} does not support {param}={value}. {supported_hint}" + "To drop unsupported params, set `litellm.drop_params = True`." + ), + status_code=400, + ) + + @staticmethod + def _model_map_lookup_candidates(model: str) -> List[str]: + """Model-map keys to try for ``model``, stripping bedrock/vertex + prefixes so a provider-routed Claude still resolves to its entry.""" candidates = [model] for prefix in ( "bedrock/converse/", @@ -307,15 +352,40 @@ class AnthropicModelInfo(BaseLLMModelInfo): candidates.append(f"bedrock/{base}") except Exception: pass + return candidates + + @staticmethod + def _get_model_capability(model: str, key: str) -> Optional[bool]: + """Read boolean capability ``key`` from the model map, or None when + no entry declares it.""" try: - for cand in candidates: - if cand in litellm.model_cost and ( - litellm.model_cost[cand].get(key) is True - ): - return True + for cand in AnthropicModelInfo._model_map_lookup_candidates(model): + value = litellm.model_cost.get(cand, {}).get(key) + if isinstance(value, bool): + return value except Exception: pass - return False + return None + + @staticmethod + def _supports_model_capability(model: str, key: str) -> bool: + """Check a boolean capability ``key`` in the model map. + + Strips bedrock/vertex prefixes so a provider-routed Claude still + resolves to the Anthropic model-map entry. + """ + from litellm.utils import _supports_factory + + try: + if _supports_factory( + model=model, + custom_llm_provider="anthropic", + key=key, + ): + return True + except Exception: + pass + return AnthropicModelInfo._get_model_capability(model, key) is True @staticmethod def _is_adaptive_thinking_model(model: str) -> bool: diff --git a/litellm/llms/anthropic/cost_calculation.py b/litellm/llms/anthropic/cost_calculation.py index 3882d8f978c..44081ea9e79 100644 --- a/litellm/llms/anthropic/cost_calculation.py +++ b/litellm/llms/anthropic/cost_calculation.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Optional, Tuple from litellm.litellm_core_utils.llm_cost_calc.utils import ( _get_token_base_cost, + _get_web_search_requests, _parse_prompt_tokens_details, calculate_cache_writing_cost, generic_cost_per_token, @@ -17,7 +18,9 @@ if TYPE_CHECKING: import litellm -def _compute_cache_only_cost(model_info: "ModelInfo", usage: "Usage") -> float: +def _compute_cache_only_cost( + model_info: "ModelInfo", usage: "Usage", service_tier: str | None = None +) -> float: """ Return only the cache-related portion of the prompt cost (cache read + cache write). @@ -35,7 +38,9 @@ def _compute_cache_only_cost(model_info: "ModelInfo", usage: "Usage") -> float: cache_creation_cost, cache_creation_cost_above_1hr, cache_read_cost, - ) = _get_token_base_cost(model_info=model_info, usage=usage) + ) = _get_token_base_cost( + model_info=model_info, usage=usage, service_tier=service_tier + ) cache_cost = float(prompt_tokens_details["cache_hit_tokens"]) * cache_read_cost @@ -55,19 +60,26 @@ def _compute_cache_only_cost(model_info: "ModelInfo", usage: "Usage") -> float: return cache_cost -def cost_per_token(model: str, usage: "Usage") -> Tuple[float, float]: +def cost_per_token( + model: str, usage: "Usage", service_tier: str | None = None +) -> Tuple[float, float]: """ Calculates the cost per token for a given model, prompt tokens, and completion tokens. Input: - model: str, the model name without provider prefix - usage: LiteLLM Usage block, containing anthropic caching information + - service_tier: the service tier the request was served at (e.g. "priority"), + read from the Anthropic response usage and used to select tier-specific pricing Returns: Tuple[float, float] - prompt_cost_in_usd, completion_cost_in_usd """ prompt_cost, completion_cost = generic_cost_per_token( - model=model, usage=usage, custom_llm_provider="anthropic" + model=model, + usage=usage, + custom_llm_provider="anthropic", + service_tier=service_tier, ) # Apply provider_specific_entry multipliers for geo/speed routing @@ -88,7 +100,9 @@ def cost_per_token(model: str, usage: "Usage") -> Tuple[float, float]: multiplier *= provider_specific_entry.get("fast", 1.0) if multiplier != 1.0: - cache_cost = _compute_cache_only_cost(model_info=model_info, usage=usage) + cache_cost = _compute_cache_only_cost( + model_info=model_info, usage=usage, service_tier=service_tier + ) prompt_cost = (prompt_cost - cache_cost) * multiplier + cache_cost completion_cost *= multiplier except Exception: @@ -110,11 +124,12 @@ def get_cost_for_anthropic_web_search( if model_info is None: return 0.0 - if ( - usage is None - or usage.server_tool_use is None - or usage.server_tool_use.web_search_requests is None - ): + if usage is None: + return 0.0 + web_search_requests = _get_web_search_requests( + getattr(usage, "server_tool_use", None) + ) + if web_search_requests is None: return 0.0 ## Get the cost per web search request @@ -128,5 +143,5 @@ def get_cost_for_anthropic_web_search( return 0.0 ## Calculate the total cost - total_cost = cost_per_web_search_request * usage.server_tool_use.web_search_requests + total_cost = cost_per_web_search_request * web_search_requests return total_cost 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 bacb9f8ddf6..a8e2fceb4ee 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py @@ -1,5 +1,6 @@ # What is this? ## Translates OpenAI call to Anthropic `/v1/messages` format +import copy import json import traceback from collections import deque @@ -29,6 +30,98 @@ if TYPE_CHECKING: from litellm.types.utils import ModelResponseStream +class _CombinedChunkSplitter: + """ + Splits a streaming chunk that carries BOTH response content and a + ``finish_reason`` into two chunks: a content-only chunk followed by a + finish-only chunk. + + ``AnthropicStreamWrapper`` (via ``translate_streaming_openai_response_to_anthropic``) + assumes content and ``finish_reason`` never arrive in the same chunk — true for + real provider streams, but false for fake-streamed providers (e.g. Vertex AI + Gemma ``:predict``) where ``MockResponseIterator`` collapses the entire response + into a single chunk. Without this split the assumption causes all content to be + silently dropped (only the ``message_delta`` stop event is emitted). + + Supports both sync and async iteration, since ``AnthropicStreamWrapper`` exposes + both ``__next__`` and ``__anext__``. An instance is single-mode: callers must + iterate it either synchronously or asynchronously, never both — the two modes + hold independent iterator references on the upstream stream and mixing them + would advance them out of sync. + """ + + def __init__(self, completion_stream: Any): + self._stream = completion_stream + self._sync_iter: Optional[Iterator[Any]] = None + self._async_iter: Optional[AsyncIterator[Any]] = None + self._buffer: deque = deque() + + @staticmethod + def _is_combined(chunk: Any) -> bool: + """True if ``chunk`` carries response content AND a finish_reason.""" + choices = getattr(chunk, "choices", None) + if not choices: + return False + choice = choices[0] + if getattr(choice, "finish_reason", None) is None: + return False + delta = getattr(choice, "delta", None) + if delta is None: + return False + return bool( + getattr(delta, "content", None) + or getattr(delta, "tool_calls", None) + or getattr(delta, "reasoning_content", None) + or getattr(delta, "thinking_blocks", None) + ) + + @staticmethod + def _split(chunk: Any) -> List[Any]: + """Return ``[chunk]``, or ``[content_chunk, finish_chunk]`` if combined.""" + if not _CombinedChunkSplitter._is_combined(chunk): + return [chunk] + + # Content chunk: keep the delta payload, clear the finish_reason. + content_chunk = copy.deepcopy(chunk) + content_chunk.choices[0].finish_reason = None + + # Finish chunk: keep finish_reason (and usage), clear the delta payload. + finish_chunk = copy.deepcopy(chunk) + finish_delta = finish_chunk.choices[0].delta + finish_delta.content = None + if hasattr(finish_delta, "tool_calls"): + finish_delta.tool_calls = None + if hasattr(finish_delta, "reasoning_content"): + finish_delta.reasoning_content = None + if hasattr(finish_delta, "thinking_blocks"): + finish_delta.thinking_blocks = None + return [content_chunk, finish_chunk] + + def __iter__(self) -> "Iterator[Any]": + return self + + def __next__(self) -> Any: + if self._buffer: + return self._buffer.popleft() + if self._sync_iter is None: + self._sync_iter = iter(self._stream) + chunk = next(self._sync_iter) # propagates StopIteration when exhausted + self._buffer.extend(self._split(chunk)) + return self._buffer.popleft() + + def __aiter__(self) -> "AsyncIterator[Any]": + return self + + async def __anext__(self) -> Any: + if self._buffer: + return self._buffer.popleft() + if self._async_iter is None: + self._async_iter = self._stream.__aiter__() + chunk = await self._async_iter.__anext__() # propagates StopAsyncIteration + self._buffer.extend(self._split(chunk)) + return self._buffer.popleft() + + class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): """ - first chunk return 'message_start' @@ -62,7 +155,10 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): compaction_block: Optional[CompactionBlock] = None, iterations_usage: Optional[List[UsageIteration]] = None, ): - super().__init__(completion_stream) + # Wrap the upstream stream so chunks that carry both content and a + # finish_reason (fake-streamed providers) are split into two — see + # _CombinedChunkSplitter. + super().__init__(_CombinedChunkSplitter(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 {} @@ -276,7 +372,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): cache_read_input_tokens=0, ) - def __next__(self): # noqa: PLR0915 + def __next__(self): from .transformation import LiteLLMAnthropicMessagesAdapter try: @@ -373,12 +469,16 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): if should_start_new_block and not self.sent_content_block_finish: # Queue the sequence: content_block_stop -> content_block_start - # For text blocks the trigger chunk is not emitted as a separate - # delta because content_block_start carries the information. - # For tool_use blocks we must also emit the trigger chunk's delta - # when it carries input_json_delta data, because some providers - # (e.g. xAI, Gemini) include tool arguments in the same streaming - # chunk as the function name/id. + # -> (optionally) the trigger chunk's delta. + # + # The synthesized content_block_start always carries an + # empty body, so the chunk that *triggered* the transition + # also carries the new block's first delta. It must be + # re-emitted or the first token of the new block is lost. + # This applies to text_delta and thinking_delta (the first + # non-empty text/thinking token) as well as input_json_delta + # (providers like xAI/Gemini bundle tool arguments with the + # function name/id in a single chunk). # 1. Stop current content block self.chunk_queue.append( @@ -397,14 +497,9 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): } ) - # 3. If the trigger chunk carries tool argument data, queue it - # so the input_json_delta is not silently dropped. - if ( - processed_chunk.get("type") == "content_block_delta" - and isinstance(processed_chunk.get("delta"), dict) - and processed_chunk["delta"].get("type") == "input_json_delta" - and processed_chunk["delta"].get("partial_json") - ): + # 3. If the trigger chunk carries delta content, queue it + # so the first delta of the new block is not silently dropped. + if self._trigger_delta_has_content(processed_chunk): self.chunk_queue.append(processed_chunk) self.sent_content_block_finish = False @@ -523,7 +618,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): ) raise StopIteration - async def __anext__(self): # noqa: PLR0915 + async def __anext__(self): from .transformation import LiteLLMAnthropicMessagesAdapter try: @@ -615,12 +710,16 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): if not self.queued_usage_chunk: if should_start_new_block and not self.sent_content_block_finish: # Queue the sequence: content_block_stop -> content_block_start - # For text blocks the trigger chunk is not emitted as a separate - # delta because content_block_start carries the information. - # For tool_use blocks we must also emit the trigger chunk's delta - # when it carries input_json_delta data, because some providers - # (e.g. xAI, Gemini) include tool arguments in the same streaming - # chunk as the function name/id. + # -> (optionally) the trigger chunk's delta. + # + # The synthesized content_block_start always carries an + # empty body, so the chunk that *triggered* the transition + # also carries the new block's first delta. It must be + # re-emitted or the first token of the new block is lost. + # This applies to text_delta and thinking_delta (the + # first non-empty text/thinking token) as well as + # input_json_delta (providers like xAI/Gemini bundle tool + # arguments with the function name/id in a single chunk). # 1. Stop current content block self.chunk_queue.append( @@ -637,15 +736,9 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): } ) - # 3. If the trigger chunk carries tool argument data, queue it - # so the input_json_delta is not silently dropped. - if ( - processed_chunk.get("type") == "content_block_delta" - and isinstance(processed_chunk.get("delta"), dict) - and processed_chunk["delta"].get("type") - == "input_json_delta" - and processed_chunk["delta"].get("partial_json") - ): + # 3. If the trigger chunk carries delta content, queue it + # so the first delta of the new block is not silently dropped. + if self._trigger_delta_has_content(processed_chunk): self.chunk_queue.append(processed_chunk) # Reset state for new block @@ -802,6 +895,38 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): def _increment_content_block_index(self): self.current_content_block_index += 1 + @staticmethod + def _trigger_delta_has_content(processed_chunk: Dict[str, Any]) -> bool: + """Return True if a translated trigger chunk carries a non-empty + ``content_block_delta`` payload that must be re-emitted after a + block transition. + + When an upstream chunk both *triggers* a new content block (its type + differs from the active block) and *carries* delta content, that + content belongs to the new block. The synthesized + ``content_block_start`` only ever carries an empty body — see + ``_translate_streaming_openai_chunk_to_anthropic_content_block``, + which returns an empty ``TextBlock``/``ToolUseBlock``/thinking block — + so the trigger chunk's delta must be re-queued or the first token of + the new block (the first non-empty text/thinking delta, or bundled + tool arguments) is silently dropped. + """ + if processed_chunk.get("type") != "content_block_delta": + return False + delta = processed_chunk.get("delta") + if not isinstance(delta, dict): + return False + delta_type = delta.get("type") + if delta_type == "text_delta": + return bool(delta.get("text")) + if delta_type == "input_json_delta": + return bool(delta.get("partial_json")) + if delta_type == "thinking_delta": + return bool(delta.get("thinking")) + if delta_type == "signature_delta": + return bool(delta.get("signature")) + return False + def _should_start_new_content_block(self, chunk: "ModelResponseStream") -> bool: """ Determine if we should start a new content block based on the processed chunk. diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py index 150f056dc81..75a8acdfcc3 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py @@ -332,7 +332,14 @@ class LiteLLMAnthropicMessagesAdapter: if isinstance(source, dict) else getattr(source, "cache_control", None) ) - if cache_control and model and self.is_anthropic_claude_model(model): + if ( + cache_control + and model + and ( + self.is_anthropic_claude_model(model) + or self.is_bedrock_arn_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): @@ -376,7 +383,7 @@ class LiteLLMAnthropicMessagesAdapter: isinstance(tool_type, str) and tool_type.startswith("web_search") ) or tool_name == "web_search" - def translate_anthropic_messages_to_openai( # noqa: PLR0915 + def translate_anthropic_messages_to_openai( self, messages: List[ Union[ @@ -752,6 +759,20 @@ class LiteLLMAnthropicMessagesAdapter: model_lower = model.lower() return "anthropic" in model_lower or "claude" in model_lower + @staticmethod + def is_bedrock_arn_model(model: str) -> bool: + """ + Check if the model string is a Bedrock ARN, such as an Application + Inference Profile (e.g. arn:aws:bedrock:us-east-1:123:application-inference-profile/id). + + These ARNs contain neither "anthropic" nor "claude", so is_anthropic_claude_model + cannot identify them even though, on the /v1/messages endpoint, they point at Claude. + Match ":bedrock:" in the ARN service field so another service's ARN that merely names + bedrock in a resource (arn:aws:sagemaker:.../my-bedrock-endpoint) is not matched. + """ + model_lower = model.lower() + return "arn:" in model_lower and ":bedrock:" in model_lower + @staticmethod def translate_thinking_for_model( thinking: Dict[str, Any], @@ -838,7 +859,17 @@ class LiteLLMAnthropicMessagesAdapter: """ new_tools: List[ChatCompletionToolParam] = [] tool_name_mapping: Dict[str, str] = {} - mapped_tool_params = ["name", "input_schema", "description", "cache_control"] + # "type" is the Anthropic tool type (e.g. "custom"); it must not be + # merged into the OpenAI function `parameters` schema below, or it + # overwrites the real parameters.type ("object") and the provider + # rejects the request. See #30557. + mapped_tool_params = [ + "name", + "input_schema", + "description", + "cache_control", + "type", + ] for idx, tool in enumerate(tools): # Check if this is an Anthropic-native tool that should be kept as-is diff --git a/litellm/llms/anthropic/experimental_pass_through/context_management/editors/compact.py b/litellm/llms/anthropic/experimental_pass_through/context_management/editors/compact.py index 4aae85b17fe..6479ee999b0 100644 --- a/litellm/llms/anthropic/experimental_pass_through/context_management/editors/compact.py +++ b/litellm/llms/anthropic/experimental_pass_through/context_management/editors/compact.py @@ -97,7 +97,7 @@ def _read_summary_max_tokens_setting() -> int: return COMPACT_SUMMARY_MAX_TOKENS -async def _check_summary_model_access( # noqa: PLR0915 +async def _check_summary_model_access( user_api_key_auth: Any, summary_model: str, llm_router: Any, @@ -970,7 +970,7 @@ def apply_client_compaction_block_history( ) -async def apply_compact_20260112( # noqa: PLR0915 +async def apply_compact_20260112( *, model: str, messages: List[Dict[str, Any]], diff --git a/litellm/llms/anthropic/experimental_pass_through/messages/transformation.py b/litellm/llms/anthropic/experimental_pass_through/messages/transformation.py index 3a2c09f2183..07e8270b496 100644 --- a/litellm/llms/anthropic/experimental_pass_through/messages/transformation.py +++ b/litellm/llms/anthropic/experimental_pass_through/messages/transformation.py @@ -84,6 +84,15 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig): if isinstance(content, list): _process_content_list(content) + def should_strip_billing_metadata(self) -> bool: + """ + Whether to drop x-anthropic-billing-header system blocks before sending upstream. + + The first-party Anthropic API uses these blocks for Claude Code attribution, so the + base config keeps them. Providers that reject them override this to True. + """ + return False + @staticmethod def _filter_billing_headers_from_system(system_param): """ @@ -286,14 +295,12 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig): optional_params=anthropic_messages_optional_request_params, ) - # Filter out x-anthropic-billing-header from system messages system_param = anthropic_messages_optional_request_params.get("system") - if system_param is not None: + if self.should_strip_billing_metadata() and system_param is not None: filtered_system = self._filter_billing_headers_from_system(system_param) if filtered_system is not None and len(filtered_system) > 0: anthropic_messages_optional_request_params["system"] = filtered_system else: - # Remove system parameter if all content was filtered out anthropic_messages_optional_request_params.pop("system", None) # Transform context_management from OpenAI format to Anthropic format if needed diff --git a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/handler.py b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/handler.py index f8c827ab057..70855afa81c 100644 --- a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/handler.py +++ b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/handler.py @@ -102,9 +102,9 @@ def _build_responses_kwargs( from litellm.types.utils import CallTypes if isinstance(value, LiteLLMLoggingObject): - # Reclassify as acompletion so the success handler doesn't try to - # validate the Responses API event as an AnthropicResponse. - # (Mirrors the pattern used in LiteLLMMessagesToCompletionTransformationHandler.) + # Keep call_type as anthropic_messages so spend_logs are billed + # against /v1/messages; the success handler translates the + # Responses API result back to a ModelResponse for the row. setattr(value, "call_type", CallTypes.anthropic_messages.value) responses_kwargs[key] = value elif key not in excluded and key not in responses_kwargs and value is not None: diff --git a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py index 94c5200be64..04819a416a2 100644 --- a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py @@ -66,7 +66,7 @@ class AnthropicResponsesStreamWrapper: self._current_block_index += 1 return self._current_block_index - def _process_event(self, event: Any) -> None: # noqa: PLR0915 + def _process_event(self, event: Any) -> None: """Convert one Responses API event into zero or more Anthropic chunks queued for emission.""" event_type = getattr(event, "type", None) if event_type is None and isinstance(event, dict): @@ -155,10 +155,24 @@ class AnthropicResponsesStreamWrapper: event.get("delta", "") if isinstance(event, dict) else "" ) block_idx = ( - self._item_id_to_block_index.get(item_id, self._current_block_index) + self._item_id_to_block_index.get(item_id, -1) if item_id else self._current_block_index ) + if block_idx < 0: + # Some providers (e.g. LMStudio) skip response.output_item.added, + # so no text block is open yet; synthesize content_block_start + # instead of emitting a delta with index -1 + block_idx = self._next_block_index() + if item_id: + self._item_id_to_block_index[item_id] = block_idx + self._chunk_queue.append( + { + "type": "content_block_start", + "index": block_idx, + "content_block": {"type": "text", "text": ""}, + } + ) self._chunk_queue.append( { "type": "content_block_delta", diff --git a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/transformation.py b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/transformation.py index 2badc2a3276..4fb1ddf5c46 100644 --- a/litellm/llms/anthropic/experimental_pass_through/responses_adapters/transformation.py +++ b/litellm/llms/anthropic/experimental_pass_through/responses_adapters/transformation.py @@ -51,7 +51,7 @@ class LiteLLMAnthropicToResponsesAPIAdapter: return source.get("url") return None - def translate_messages_to_responses_input( # noqa: PLR0915 + def translate_messages_to_responses_input( self, messages: List[ Union[ diff --git a/litellm/llms/azure/azure.py b/litellm/llms/azure/azure.py index 734b8ecef16..5be3ce22832 100644 --- a/litellm/llms/azure/azure.py +++ b/litellm/llms/azure/azure.py @@ -43,7 +43,10 @@ from .common_utils import ( process_azure_headers, select_azure_base_url_or_endpoint, ) -from .image_generation import get_azure_image_generation_config +from .image_generation import ( + AzureFoundryMAIImageGenerationConfig, + get_azure_image_generation_config, +) from .image_generation.http_utils import azure_deployment_image_generation_json_body @@ -186,7 +189,7 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): except Exception as e: raise e - def completion( # noqa: PLR0915 + def completion( self, model: str, messages: list, @@ -1097,10 +1100,14 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): ) def create_azure_base_url( - self, azure_client_params: dict, model: Optional[str] + self, + azure_client_params: dict, + model: Optional[str], + base_model: Optional[str] = None, ) -> str: from litellm.llms.azure_ai.image_generation import ( AzureFoundryFluxImageGenerationConfig, + AzureFoundryMAIImageGenerationConfig, ) api_base: str = azure_client_params.get( @@ -1112,6 +1119,12 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): if model is None: model = "" + if AzureFoundryMAIImageGenerationConfig.is_mai_model(base_model or model): + return AzureFoundryMAIImageGenerationConfig.get_mai_image_generation_url( + api_base=api_base, + api_version=api_version, + ) + # Handle FLUX 2 models on Azure AI which use a different URL pattern # e.g., /providers/blackforestlabs/v1/flux-2-pro instead of /openai/deployments/{model}/images/generations if AzureFoundryFluxImageGenerationConfig.is_flux2_model(model): @@ -1153,10 +1166,10 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): if api_base.endswith("/"): api_base = api_base.rstrip("/") api_version: str = azure_client_params.get("api_version", "") - # Use the deployment name (model) for URL construction, not the base_model from data img_gen_api_base = self.create_azure_base_url( azure_client_params=azure_client_params, model=model or data.get("model", ""), + base_model=data.get("model", ""), ) ## LOGGING @@ -1285,9 +1298,10 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): if aimg_generation is True: return self.aimage_generation(data=data, input=input, logging_obj=logging_obj, model_response=model_response, api_key=api_key, client=client, azure_client_params=azure_client_params, timeout=timeout, headers=headers, model=model) # type: ignore - # Use the deployment name (model) for URL construction, not the base_model from data img_gen_api_base = self.create_azure_base_url( - azure_client_params=azure_client_params, model=model + azure_client_params=azure_client_params, + model=model, + base_model=base_model, ) ## LOGGING @@ -1309,6 +1323,21 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): data=data, headers=headers, ) + provider_config = get_azure_image_generation_config( + data.get("model", "dall-e-2") + ) + if isinstance(provider_config, AzureFoundryMAIImageGenerationConfig): + return provider_config.transform_image_generation_response( + model=data.get("model", "dall-e-2"), + raw_response=httpx_response, + model_response=model_response or ImageResponse(), + logging_obj=logging_obj, + request_data=data, + optional_params=data, + litellm_params=data, + encoding=litellm.encoding, + ) + response = httpx_response.json() ## LOGGING diff --git a/litellm/llms/azure/completion/handler.py b/litellm/llms/azure/completion/handler.py index 05d5e2f6c68..b8d1ad71d46 100644 --- a/litellm/llms/azure/completion/handler.py +++ b/litellm/llms/azure/completion/handler.py @@ -25,7 +25,7 @@ class AzureTextCompletion(BaseAzureLLM): headers["Authorization"] = f"Bearer {azure_ad_token}" return headers - def completion( # noqa: PLR0915 + def completion( self, model: str, messages: list, diff --git a/litellm/llms/azure/image_generation/__init__.py b/litellm/llms/azure/image_generation/__init__.py index f60e446f0c4..64636bc689d 100644 --- a/litellm/llms/azure/image_generation/__init__.py +++ b/litellm/llms/azure/image_generation/__init__.py @@ -1,4 +1,5 @@ from litellm._logging import verbose_logger +from litellm.llms.azure_ai.image_generation import AzureFoundryMAIImageGenerationConfig from litellm.llms.base_llm.image_generation.transformation import ( BaseImageGenerationConfig, ) @@ -24,6 +25,8 @@ def get_azure_image_generation_config(model: str) -> BaseImageGenerationConfig: return AzureDallE2ImageGenerationConfig() elif "dalle3" in model: return AzureDallE3ImageGenerationConfig() + elif AzureFoundryMAIImageGenerationConfig.is_mai_model(model): + return AzureFoundryMAIImageGenerationConfig() else: verbose_logger.debug( f"Using AzureGPTImageGenerationConfig for model: {model}. This follows the gpt-image model format." diff --git a/litellm/llms/azure/realtime/handler.py b/litellm/llms/azure/realtime/handler.py index 1f3357fd788..9c8de6c06a1 100644 --- a/litellm/llms/azure/realtime/handler.py +++ b/litellm/llms/azure/realtime/handler.py @@ -8,6 +8,7 @@ from typing import Any, Optional, cast from litellm._logging import _redact_string, verbose_proxy_logger from litellm.constants import REALTIME_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES +from litellm.types.realtime import RealtimeQueryParams from ....litellm_core_utils.litellm_logging import Logging as LiteLLMLogging from ....litellm_core_utils.realtime_streaming import RealTimeStreaming @@ -35,6 +36,7 @@ class AzureOpenAIRealtime(AzureChatCompletion): model: str, api_version: Optional[str], realtime_protocol: Optional[str] = None, + query_params: Optional[RealtimeQueryParams] = None, ) -> str: """ Construct Azure realtime WebSocket URL. @@ -46,6 +48,7 @@ class AzureOpenAIRealtime(AzureChatCompletion): realtime_protocol: Protocol version to use: - "GA" or "v1": Uses /openai/v1/realtime (GA path) - "beta" or None: Uses /openai/realtime (beta path, default) + query_params: Extra query params to forward (e.g. intent=transcription). Returns: WebSocket URL string @@ -54,6 +57,8 @@ class AzureOpenAIRealtime(AzureChatCompletion): beta/default: "wss://.../openai/realtime?api-version=2024-10-01-preview&deployment=gpt-4o-realtime-preview" GA/v1: "wss://.../openai/v1/realtime?model=gpt-realtime-deployment" """ + from urllib.parse import urlencode + api_base = api_base.replace("https://", "wss://") # Determine path based on realtime_protocol (case-insensitive) @@ -61,13 +66,25 @@ class AzureOpenAIRealtime(AzureChatCompletion): "GA", "V1", ) + intent = (query_params or {}).get("intent") + if _is_ga: path = "/openai/v1/realtime" - return f"{api_base}{path}?model={model}" + query_parts = [] + if intent != "transcription" and ( + query_params is None or "model" in query_params + ): + query_parts.append(urlencode({"model": model})) else: # Default to beta path for backwards compatibility path = "/openai/realtime" - return f"{api_base}{path}?api-version={api_version}&deployment={model}" + query_parts = [urlencode({"api-version": api_version, "deployment": model})] + + if intent: + query_parts.append(urlencode({"intent": intent})) + + qs = "&".join(query_parts) + return f"{api_base}{path}?{qs}" if qs else f"{api_base}{path}" async def async_realtime( self, @@ -81,6 +98,7 @@ class AzureOpenAIRealtime(AzureChatCompletion): client: Optional[Any] = None, timeout: Optional[float] = None, realtime_protocol: Optional[str] = None, + query_params: Optional[RealtimeQueryParams] = None, user_api_key_dict: Optional[Any] = None, litellm_metadata: Optional[dict] = None, ): @@ -96,7 +114,11 @@ class AzureOpenAIRealtime(AzureChatCompletion): raise ValueError("api_version is required for Azure OpenAI calls") url = self._construct_url( - api_base, model, api_version, realtime_protocol=realtime_protocol + api_base, + model, + api_version, + realtime_protocol=realtime_protocol, + query_params=query_params, ) try: @@ -113,9 +135,15 @@ class AzureOpenAIRealtime(AzureChatCompletion): websocket, cast(ClientConnection, backend_ws), logging_obj, + model=model, user_api_key_dict=user_api_key_dict, request_data={"litellm_metadata": litellm_metadata or {}}, backend_uses_beta_protocol=backend_uses_beta_protocol, + force_transcription_model=( + model + if (query_params or {}).get("intent") == "transcription" + else None + ), ) await realtime_streaming.bidirectional_forward() diff --git a/litellm/llms/azure/realtime/http_transformation.py b/litellm/llms/azure/realtime/http_transformation.py index df1e2707af2..d6bdbd24db4 100644 --- a/litellm/llms/azure/realtime/http_transformation.py +++ b/litellm/llms/azure/realtime/http_transformation.py @@ -40,6 +40,13 @@ class AzureRealtimeHTTPConfig(BaseRealtimeHTTPConfig): version = api_version or get_secret_str("AZURE_API_VERSION") or "2024-12-17" return f"{base}/openai/realtime/calls?api-version={version}" + def get_transcription_session_url( + self, api_base: Optional[str], model: str, api_version: Optional[str] = None + ) -> str: + base = self.get_api_base(api_base).rstrip("/") + version = api_version or get_secret_str("AZURE_API_VERSION") or "2024-12-17" + return f"{base}/openai/realtime/transcription_sessions?api-version={version}" + def get_realtime_calls_headers(self, ephemeral_key: str) -> dict: return { "api-key": ephemeral_key, diff --git a/litellm/llms/azure/responses/transformation.py b/litellm/llms/azure/responses/transformation.py index ca9293325ff..92ce5b49285 100644 --- a/litellm/llms/azure/responses/transformation.py +++ b/litellm/llms/azure/responses/transformation.py @@ -185,6 +185,40 @@ class AzureOpenAIResponsesAPIConfig(OpenAIResponsesAPIConfig): default_api_version=AZURE_DEFAULT_RESPONSES_API_VERSION, ) + def supports_native_websocket(self) -> bool: + return True + + def get_websocket_url( + self, + api_base: Optional[str], + litellm_params: dict, + ) -> str: + """ + Azure Responses WebSocket endpoint is at /openai/v1/responses with no + api-version query param. Auth is via Authorization header, model is sent + in the response.create body — not the URL. + """ + if api_base is None: + raise ValueError("api_base is required for Azure WebSocket") + + parsed_url = httpx.URL(api_base) + path = parsed_url.path.rstrip("/") + # Strip existing /openai/responses path if the api_base already contains it + for suffix in ("/openai/v1/responses", "/openai/responses"): + if path.endswith(suffix): + path = path[: -len(suffix)] + break + scheme = "wss" if parsed_url.scheme == "https" else "ws" + return str( + parsed_url.copy_with( + scheme=scheme, path=f"{path}/openai/v1/responses", query=None + ) + ) + + def model_in_websocket_url(self) -> bool: + # Azure sends the model in the response.create body, not the URL + return False + ######################################################### ########## DELETE RESPONSE API TRANSFORMATION ############## ######################################################### diff --git a/litellm/llms/azure_ai/anthropic/messages_transformation.py b/litellm/llms/azure_ai/anthropic/messages_transformation.py index a81218ab76a..59b6ee2b424 100644 --- a/litellm/llms/azure_ai/anthropic/messages_transformation.py +++ b/litellm/llms/azure_ai/anthropic/messages_transformation.py @@ -21,6 +21,9 @@ class AzureAnthropicMessagesConfig(AnthropicMessagesConfig): and Azure endpoint format. """ + def should_strip_billing_metadata(self) -> bool: + return True + def validate_anthropic_messages_environment( self, headers: dict, diff --git a/litellm/llms/azure_ai/anthropic/transformation.py b/litellm/llms/azure_ai/anthropic/transformation.py index e176a4d860e..367ca75c196 100644 --- a/litellm/llms/azure_ai/anthropic/transformation.py +++ b/litellm/llms/azure_ai/anthropic/transformation.py @@ -40,6 +40,9 @@ class AzureAnthropicConfig(AnthropicConfig): def custom_llm_provider(self) -> Optional[str]: return "azure_ai" + def should_strip_billing_metadata(self) -> bool: + return True + def validate_environment( self, headers: dict, diff --git a/litellm/llms/azure_ai/image_edit/__init__.py b/litellm/llms/azure_ai/image_edit/__init__.py index e3acd610446..42ece6d19ec 100644 --- a/litellm/llms/azure_ai/image_edit/__init__.py +++ b/litellm/llms/azure_ai/image_edit/__init__.py @@ -1,21 +1,33 @@ from litellm.llms.azure_ai.image_generation.flux_transformation import ( AzureFoundryFluxImageGenerationConfig, ) +from litellm.llms.azure_ai.image_generation.mai_transformation import ( + AzureFoundryMAIImageGenerationConfig, +) from litellm.llms.base_llm.image_edit.transformation import BaseImageEditConfig from .flux2_transformation import AzureFoundryFlux2ImageEditConfig +from .mai_transformation import AzureFoundryMAIImageEditConfig from .transformation import AzureFoundryFluxImageEditConfig -__all__ = ["AzureFoundryFluxImageEditConfig", "AzureFoundryFlux2ImageEditConfig"] +__all__ = [ + "AzureFoundryFluxImageEditConfig", + "AzureFoundryFlux2ImageEditConfig", + "AzureFoundryMAIImageEditConfig", +] def get_azure_ai_image_edit_config(model: str) -> BaseImageEditConfig: """ Get the appropriate image edit config for an Azure AI model. + - MAI models use /mai/v1/images/edits with multipart form data and size - FLUX 2 models use JSON with base64 image - FLUX 1 models use multipart/form-data """ + if AzureFoundryMAIImageGenerationConfig.is_mai_model(model): + return AzureFoundryMAIImageEditConfig() + # Check if it's a FLUX 2 model if AzureFoundryFluxImageGenerationConfig.is_flux2_model(model): return AzureFoundryFlux2ImageEditConfig() diff --git a/litellm/llms/azure_ai/image_edit/mai_transformation.py b/litellm/llms/azure_ai/image_edit/mai_transformation.py new file mode 100644 index 00000000000..75bfc913a8f --- /dev/null +++ b/litellm/llms/azure_ai/image_edit/mai_transformation.py @@ -0,0 +1,199 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, cast + +import httpx +from httpx._types import RequestFiles + +from litellm.llms.azure_ai.common_utils import AzureFoundryModelInfo +from litellm.llms.azure_ai.image_generation.mai_transformation import ( + AzureFoundryMAIImageGenerationConfig, +) +from litellm.llms.openai.common_utils import OpenAIError +from litellm.llms.openai.image_edit.transformation import OpenAIImageEditConfig +from litellm.secret_managers.main import get_secret_str +from litellm.types.images.main import ImageEditOptionalRequestParams +from litellm.types.llms.openai import FileTypes +from litellm.types.router import GenericLiteLLMParams +from litellm.types.utils import ImageResponse +from litellm.utils import convert_to_model_response_object + +if TYPE_CHECKING: + from litellm.litellm_core_utils.logging import Logging as LiteLLMLoggingObj + + +class AzureFoundryMAIImageEditConfig(OpenAIImageEditConfig): + """Azure AI Foundry MAI image editing (e.g. MAI-Image-2.5).""" + + DEFAULT_SIZE = "1024x1024" + + def get_supported_openai_params(self, model: str) -> list: + return ["prompt", "image", "model", "n", "size"] + + def map_openai_params( + self, + image_edit_optional_params: ImageEditOptionalRequestParams, + model: str, + drop_params: bool, + ) -> Dict: + optional_params: Dict[str, Any] = {} + supported_params = self.get_supported_openai_params(model) + + for key, value in dict(image_edit_optional_params).items(): + if value is None or key in optional_params: + continue + + if key in supported_params: + if key == "size" and value: + size_param = cast(str, value) + self._validate_size_param(size_param) + optional_params[key] = size_param + else: + optional_params[key] = value + elif not drop_params: + raise ValueError( + f"Parameter {key} is not supported for model {model}. " + f"Supported parameters are {supported_params}. " + f"Set drop_params=True to drop unsupported parameters." + ) + + if "size" not in optional_params: + optional_params["size"] = self.DEFAULT_SIZE + + return optional_params + + def _validate_size_param(self, size: str) -> None: + known_sizes = { + "1024x1024", + "1792x1024", + "1024x1792", + "512x512", + "256x256", + } + + if size in known_sizes: + return + + if "x" in size: + try: + tuple(map(int, size.lower().split("x", 1))) + return + except ValueError: + raise ValueError( + f"Invalid size format: '{size}'. Expected format 'WIDTHxHEIGHT' (e.g., '1024x1024')." + ) + + raise ValueError( + f"Unsupported size value: '{size}'. " + f"Use a known size (e.g., '1024x1024') or a custom 'WIDTHxHEIGHT' string." + ) + + def validate_environment( + self, + headers: dict, + model: str, + api_key: Optional[str] = None, + litellm_params: Optional[dict] = None, + api_base: Optional[str] = None, + ) -> dict: + api_key = AzureFoundryModelInfo.get_api_key(api_key) + + if not api_key: + raise ValueError( + f"Azure AI API key is required for model {model}. " + "Set AZURE_AI_API_KEY environment variable or pass api_key parameter." + ) + + headers.update({"api-key": api_key}) + return headers + + def get_complete_url( + self, + model: str, + api_base: Optional[str], + litellm_params: dict, + ) -> str: + api_base = AzureFoundryModelInfo.get_api_base(api_base) + + if api_base is None: + raise ValueError( + "Azure AI API base is required. Set AZURE_AI_API_BASE environment variable or pass api_base parameter." + ) + + api_version = ( + litellm_params.get("api_version") + or get_secret_str("AZURE_AI_API_VERSION") + or "preview" + ) + + return AzureFoundryMAIImageGenerationConfig.get_mai_image_edit_url( + api_base=api_base, + api_version=api_version, + ) + + def transform_image_edit_request( + self, + model: str, + prompt: Optional[str], + image: Optional[FileTypes], + image_edit_optional_request_params: Dict, + litellm_params: GenericLiteLLMParams, + headers: dict, + ) -> Tuple[Dict, RequestFiles]: + request_params = { + "model": model, + **image_edit_optional_request_params, + } + if prompt is not None: + request_params["prompt"] = prompt + + data_without_files = { + key: value + for key, value in request_params.items() + if key not in ["image", "mask"] + } + files_list: List[Tuple[str, Any]] = [] + + if image is not None: + image_list = [image] if not isinstance(image, list) else image + for _image in image_list: + if _image is not None: + self._add_image_to_files( + files_list=files_list, + image=_image, + field_name="image", + ) + break + + return data_without_files, files_list + + def transform_image_edit_response( + self, + model: str, + raw_response: httpx.Response, + logging_obj: "LiteLLMLoggingObj", + ) -> ImageResponse: + try: + response = raw_response.json() + except Exception: + raise OpenAIError( + message=raw_response.text, status_code=raw_response.status_code + ) + + if "usage" in response: + response["usage"] = ( + AzureFoundryMAIImageGenerationConfig.normalize_mai_image_usage( + response.get("usage") + ) + ) + + logging_obj.post_call( + input="", + api_key="", + additional_args={"complete_input_dict": {}}, + original_response=response, + ) + + return convert_to_model_response_object( + response_object=response, + model_response_object=ImageResponse(), + response_type="image_generation", + ) diff --git a/litellm/llms/azure_ai/image_generation/__init__.py b/litellm/llms/azure_ai/image_generation/__init__.py index cebab3de16e..70821d5d764 100644 --- a/litellm/llms/azure_ai/image_generation/__init__.py +++ b/litellm/llms/azure_ai/image_generation/__init__.py @@ -7,12 +7,14 @@ from .dall_e_2_transformation import AzureFoundryDallE2ImageGenerationConfig from .dall_e_3_transformation import AzureFoundryDallE3ImageGenerationConfig from .flux_transformation import AzureFoundryFluxImageGenerationConfig from .gpt_transformation import AzureFoundryGPTImageGenerationConfig +from .mai_transformation import AzureFoundryMAIImageGenerationConfig __all__ = [ "AzureFoundryFluxImageGenerationConfig", "AzureFoundryGPTImageGenerationConfig", "AzureFoundryDallE2ImageGenerationConfig", "AzureFoundryDallE3ImageGenerationConfig", + "AzureFoundryMAIImageGenerationConfig", ] @@ -24,6 +26,8 @@ def get_azure_ai_image_generation_config(model: str) -> BaseImageGenerationConfi return AzureFoundryDallE2ImageGenerationConfig() elif "dalle3" in model: return AzureFoundryDallE3ImageGenerationConfig() + elif AzureFoundryMAIImageGenerationConfig.is_mai_model(model): + return AzureFoundryMAIImageGenerationConfig() elif "flux" in model: return AzureFoundryFluxImageGenerationConfig() else: diff --git a/litellm/llms/azure_ai/image_generation/cost_calculator.py b/litellm/llms/azure_ai/image_generation/cost_calculator.py index b67de9cb70d..f8c876bb5be 100644 --- a/litellm/llms/azure_ai/image_generation/cost_calculator.py +++ b/litellm/llms/azure_ai/image_generation/cost_calculator.py @@ -1,6 +1,9 @@ from typing import Any import litellm +from litellm.litellm_core_utils.llm_cost_calc.utils import ( + calculate_image_response_cost_from_usage, +) from litellm.types.utils import ImageResponse @@ -9,19 +12,28 @@ def cost_calculator( image_response: Any, ) -> float: """ - Recraft image generation cost calculator + Azure AI image generation cost calculator """ _model_info = litellm.get_model_info( model=model, custom_llm_provider=litellm.LlmProviders.AZURE_AI.value, ) - output_cost_per_image: float = _model_info.get("output_cost_per_image") or 0.0 - num_images: int = 0 + if isinstance(image_response, ImageResponse): + token_based_cost = calculate_image_response_cost_from_usage( + model=model, + image_response=image_response, + custom_llm_provider=litellm.LlmProviders.AZURE_AI.value, + ) + if token_based_cost is not None: + return token_based_cost + + output_cost_per_image: float = _model_info.get("output_cost_per_image") or 0.0 + num_images: int = 0 if image_response.data: num_images = len(image_response.data) return output_cost_per_image * num_images - else: - raise ValueError( - f"image_response must be of type ImageResponse got type={type(image_response)}" - ) + + raise ValueError( + f"image_response must be of type ImageResponse got type={type(image_response)}" + ) diff --git a/litellm/llms/azure_ai/image_generation/mai_transformation.py b/litellm/llms/azure_ai/image_generation/mai_transformation.py new file mode 100644 index 00000000000..071ca9d9895 --- /dev/null +++ b/litellm/llms/azure_ai/image_generation/mai_transformation.py @@ -0,0 +1,236 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Optional + +import httpx + +from litellm.llms.base_llm.image_generation.transformation import ( + BaseImageGenerationConfig, +) +from litellm.llms.openai.common_utils import OpenAIError +from litellm.types.llms.openai import OpenAIImageGenerationOptionalParams +from litellm.types.utils import ImageResponse +from litellm.utils import convert_to_model_response_object + +if TYPE_CHECKING: + from litellm.litellm_core_utils.logging import Logging as LiteLLMLoggingObj + + +class AzureFoundryMAIImageGenerationConfig(BaseImageGenerationConfig): + """Azure AI Foundry MAI image generation (e.g. MAI-Image-2.5).""" + + DEFAULT_WIDTH = 1024 + DEFAULT_HEIGHT = 1024 + + @staticmethod + def get_mai_image_generation_url( + api_base: Optional[str], + api_version: Optional[str], + ) -> str: + if api_base is None: + raise ValueError("api_base is required for Azure AI MAI image generation") + + api_version = api_version or "preview" + path, separator, query = api_base.partition("?") + path = path.rstrip("/") + + if "/mai/" in path: + prefix, _, _ = path.partition("/images/") + path = f"{prefix}/images/generations" + else: + path = f"{path}/mai/v1/images/generations" + + if separator: + return f"{path}?{query}" + return f"{path}?api-version={api_version}" + + @staticmethod + def get_mai_image_edit_url( + api_base: Optional[str], + api_version: Optional[str], + ) -> str: + if api_base is None: + raise ValueError("api_base is required for Azure AI MAI image editing") + + api_version = api_version or "preview" + path, separator, query = api_base.partition("?") + path = path.rstrip("/") + + if "/mai/" in path: + prefix, _, _ = path.partition("/images/") + path = f"{prefix}/images/edits" + else: + path = f"{path}/mai/v1/images/edits" + + if separator: + return f"{path}?{query}" + return f"{path}?api-version={api_version}" + + @staticmethod + def is_mai_model(model: str) -> bool: + model_normalized = model.lower().replace("-", "").replace("_", "") + return "maiimage" in model_normalized + + @staticmethod + def normalize_mai_image_usage(usage: Optional[Dict[str, Any]]) -> Dict[str, Any]: + """Map Azure MAI usage fields to OpenAI ImageUsage schema.""" + if usage is None: + return { + "input_tokens": 0, + "input_tokens_details": {"image_tokens": 0, "text_tokens": 0}, + "output_tokens": 0, + "total_tokens": 0, + } + + normalized_usage = dict(usage) + input_tokens_details = normalized_usage.get("input_tokens_details") + if not isinstance(input_tokens_details, dict): + input_tokens_details = {} + + text_tokens = normalized_usage.get("num_input_text_tokens") + if text_tokens is None: + text_tokens = input_tokens_details.get("text_tokens") + if text_tokens is None: + text_tokens = normalized_usage.get("input_tokens", 0) or 0 + + image_tokens = normalized_usage.get("num_input_image_tokens") + if image_tokens is None: + image_tokens = input_tokens_details.get("image_tokens") + if image_tokens is None: + image_tokens = 0 + + output_tokens = normalized_usage.get("output_tokens") + if output_tokens is None: + output_tokens = normalized_usage.get("num_output_tokens") + if output_tokens is None: + output_tokens = normalized_usage.get("output_image_tokens") + if output_tokens is None: + output_tokens = 0 + + input_tokens = normalized_usage.get("input_tokens") + if input_tokens is None: + input_tokens = text_tokens + image_tokens + + total_tokens = normalized_usage.get("total_tokens") + if total_tokens is None: + total_tokens = input_tokens + output_tokens + + normalized_usage.update( + { + "input_tokens": input_tokens, + "input_tokens_details": { + "image_tokens": image_tokens, + "text_tokens": text_tokens, + }, + "output_tokens": output_tokens, + "total_tokens": total_tokens, + } + ) + return normalized_usage + + def get_supported_openai_params( + self, model: str + ) -> List[OpenAIImageGenerationOptionalParams]: + return ["n", "size"] + + def map_openai_params( + self, + non_default_params: dict, + optional_params: dict, + model: str, + drop_params: bool, + ) -> dict: + supported_params = self.get_supported_openai_params(model) + + for k, v in non_default_params.items(): + if k in optional_params: + continue + + if k in supported_params: + if k == "size" and v: + self._map_size_param(v, optional_params) + else: + optional_params[k] = v + elif k in ("width", "height"): + optional_params[k] = v + elif not drop_params: + raise ValueError( + f"Parameter {k} is not supported for model {model}. " + f"Supported parameters are {supported_params} and width/height. " + f"Set drop_params=True to drop unsupported parameters." + ) + + if "width" not in optional_params: + optional_params["width"] = self.DEFAULT_WIDTH + if "height" not in optional_params: + optional_params["height"] = self.DEFAULT_HEIGHT + + optional_params.pop("size", None) + return optional_params + + def _map_size_param(self, size: str, optional_params: dict) -> None: + size_mapping = { + "1024x1024": (1024, 1024), + "1792x1024": (1792, 1024), + "1024x1792": (1024, 1792), + "512x512": (512, 512), + "256x256": (256, 256), + } + + if size in size_mapping: + width, height = size_mapping[size] + optional_params["width"] = width + optional_params["height"] = height + elif "x" in size: + try: + width, height = map(int, size.lower().split("x")) + optional_params["width"] = width + optional_params["height"] = height + except ValueError: + raise ValueError( + f"Invalid size format: '{size}'. Expected format 'WIDTHxHEIGHT' (e.g., '1024x1024')." + ) + else: + raise ValueError( + f"Unsupported size value: '{size}'. " + f"Use a known size (e.g., '1024x1024') or a custom 'WIDTHxHEIGHT' string." + ) + + def transform_image_generation_response( + self, + model: str, + raw_response: httpx.Response, + model_response: ImageResponse, + logging_obj: "LiteLLMLoggingObj", + request_data: dict, + optional_params: dict, + litellm_params: dict, + encoding: Any, + api_key: Optional[str] = None, + json_mode: Optional[bool] = None, + ) -> ImageResponse: + try: + response = raw_response.json() + except Exception: + raise OpenAIError( + message=raw_response.text, status_code=raw_response.status_code + ) + + if "usage" in response: + response["usage"] = self.normalize_mai_image_usage(response.get("usage")) + + logging_obj.post_call( + input=request_data.get("prompt", ""), + api_key=api_key, + additional_args={"complete_input_dict": request_data}, + original_response=response, + ) + + image_response: ImageResponse = convert_to_model_response_object( + response_object=response, + model_response_object=model_response, + response_type="image_generation", + ) + + width = optional_params.get("width", self.DEFAULT_WIDTH) + height = optional_params.get("height", self.DEFAULT_HEIGHT) + image_response.size = f"{width}x{height}" # type: ignore[assignment] + return image_response diff --git a/litellm/llms/base_llm/base_model_iterator.py b/litellm/llms/base_llm/base_model_iterator.py index cf1fd6f786e..422ae947997 100644 --- a/litellm/llms/base_llm/base_model_iterator.py +++ b/litellm/llms/base_llm/base_model_iterator.py @@ -1,8 +1,11 @@ import json from abc import abstractmethod -from typing import List, Optional, Union, cast +from typing import TYPE_CHECKING, List, Optional, Union, cast import litellm + +if TYPE_CHECKING: + import httpx from litellm.types.utils import ( Choices, Delta, @@ -50,6 +53,11 @@ def convert_model_response_to_streaming( model=model_response.model, choices=streaming_choices, ) + # Carry usage onto the streaming chunk so fake-streamed responses + # (e.g. Vertex AI Gemma :predict) still report token counts. + usage = getattr(model_response, "usage", None) + if usage is not None: + setattr(processed_chunk, "usage", usage) return processed_chunk except Exception as e: raise ValueError( @@ -64,6 +72,18 @@ class BaseModelResponseIterator: self.streaming_response = streaming_response self.response_iterator = self.streaming_response self.json_mode = json_mode + self.http_response: Optional["httpx.Response"] = None + + async def aclose(self) -> None: + """Close the upstream HTTP response so the provider connection is + released (and a backend like vLLM aborts generation) when the stream + is abandoned before its natural end. + + ``streaming_response`` is usually a bare ``aiter_lines()`` generator + that holds no reference to the response, so the handler that owns the + response attaches it here after construction.""" + if self.http_response is not None: + await self.http_response.aclose() def chunk_parser( self, chunk: dict diff --git a/litellm/llms/base_llm/chat/transformation.py b/litellm/llms/base_llm/chat/transformation.py index 5f35a58ce1f..8f9d5cad7c4 100644 --- a/litellm/llms/base_llm/chat/transformation.py +++ b/litellm/llms/base_llm/chat/transformation.py @@ -442,6 +442,14 @@ class BaseConfig(ABC): """Hook for providers to post-process streaming responses. Default: pass-through.""" return stream + def apply_assembled_streaming_response_metadata( + self, + response: "ModelResponse", + chunks: List[Any], + ) -> None: + """Hook for providers to merge chunk metadata into assembled streaming responses.""" + return None + def calculate_additional_costs( self, model: str, prompt_tokens: int, completion_tokens: int ) -> Optional[dict]: diff --git a/litellm/llms/base_llm/realtime/http_transformation.py b/litellm/llms/base_llm/realtime/http_transformation.py index 712ec42380f..be1413a3c0b 100644 --- a/litellm/llms/base_llm/realtime/http_transformation.py +++ b/litellm/llms/base_llm/realtime/http_transformation.py @@ -59,6 +59,15 @@ class BaseRealtimeHTTPConfig(ABC): ) -> str: """Return the full URL for POST /realtime/client_secrets.""" + def get_transcription_session_url( + self, api_base: Optional[str], model: str, api_version: Optional[str] = None + ) -> str: + """Return the full URL for POST /realtime/transcription_sessions.""" + base = (api_base or "").rstrip("/") + if base.endswith("/v1"): + base = base[:-3] + return f"{base}/v1/realtime/transcription_sessions" + @abstractmethod def validate_environment( self, diff --git a/litellm/llms/base_llm/responses/transformation.py b/litellm/llms/base_llm/responses/transformation.py index 853eb282758..c61ce52b530 100644 --- a/litellm/llms/base_llm/responses/transformation.py +++ b/litellm/llms/base_llm/responses/transformation.py @@ -62,6 +62,26 @@ class BaseResponsesAPIConfig(ABC): """ return False + def sign_request( + self, + headers: dict, + optional_params: dict, + request_data: dict, + api_base: str, + api_key: Optional[str] = None, + model: Optional[str] = None, + stream: Optional[bool] = None, + fake_stream: Optional[bool] = None, + ) -> Tuple[dict, Optional[bytes]]: + """Sign the request after the body is finalized. + + Default is a no-op (returns headers unchanged, no signed body). Providers + whose endpoint requires request signing (e.g. Bedrock Mantle SigV4) + override this and return the signed body bytes so the handler sends those + exact bytes. + """ + return headers, None + @abstractmethod def get_supported_openai_params(self, model: str) -> list: pass @@ -238,6 +258,31 @@ class BaseResponsesAPIConfig(ABC): """ return False + def get_websocket_url( + self, + api_base: Optional[str], + litellm_params: dict, + ) -> str: + """ + Return the wss:// URL for the provider's native Responses WebSocket endpoint. + + Defaults to converting the HTTP URL from get_complete_url. Providers whose + WebSocket path differs from their HTTP path (e.g. Azure uses + /openai/v1/responses without api-version) should override this. + """ + http_url = self.get_complete_url( + api_base=api_base, litellm_params=litellm_params + ) + return http_url.replace("https://", "wss://").replace("http://", "ws://") + + def model_in_websocket_url(self) -> bool: + """ + Return True if the model should be appended as a ?model= query param to + the WebSocket URL. Providers that identify the model via the request body + (e.g. Azure Responses API) should override this to return False. + """ + return True + ######################################################### ########## CANCEL RESPONSE API TRANSFORMATION ########## ######################################################### diff --git a/litellm/llms/base_llm/sandbox/__init__.py b/litellm/llms/base_llm/sandbox/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/litellm/llms/base_llm/sandbox/transformation.py b/litellm/llms/base_llm/sandbox/transformation.py new file mode 100644 index 00000000000..6ad945f47a3 --- /dev/null +++ b/litellm/llms/base_llm/sandbox/transformation.py @@ -0,0 +1,79 @@ +""" +Base Sandbox transformation configuration. + +A sandbox provider runs an executable string inside an isolated container and +returns whatever the sandbox produced. The lifecycle is create container -> +run code -> delete container; `code_interpreter_tool` combines all three. +""" + +from typing import Any, Union + +from pydantic import Field, PrivateAttr + +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class ContainerHandle(LiteLLMPydanticObjectBase): + """A live sandbox container. Carries everything needed to reach it again.""" + + id: str + provider: str + domain: str | None = None + + model_config = {"extra": "allow"} + + _hidden_params: dict = PrivateAttr(default_factory=dict) + + +class CodeExecutionResult(LiteLLMPydanticObjectBase): + """Passthrough of the sandbox's own execution output.""" + + stdout: str = "" + stderr: str = "" + results: list[dict[str, Any]] = Field(default_factory=list) + error: dict[str, Any] | None = None + execution_count: int | None = None + object: str = "code_execution" + + model_config = {"extra": "allow"} + + _hidden_params: dict = PrivateAttr(default_factory=dict) + + +class BaseSandboxConfig: + """Provider-agnostic sandbox operations.""" + + def validate_environment(self, api_key: str | None = None, **kwargs) -> str: + raise NotImplementedError( + "validate_environment must be implemented by provider" + ) + + async def acreate_sandbox( + self, + *, + template: str | None = None, + timeout: int | None = None, + allow_internet_access: bool = True, + api_key: str | None = None, + **kwargs, + ) -> ContainerHandle: + raise NotImplementedError("acreate_sandbox must be implemented by provider") + + async def arun_code( + self, + *, + container: Union[ContainerHandle, str], + code: str, + api_key: str | None = None, + **kwargs, + ) -> CodeExecutionResult: + raise NotImplementedError("arun_code must be implemented by provider") + + async def adelete_sandbox( + self, + *, + container: Union[ContainerHandle, str], + api_key: str | None = None, + **kwargs, + ) -> bool: + raise NotImplementedError("adelete_sandbox must be implemented by provider") diff --git a/litellm/llms/bedrock/base_aws_llm.py b/litellm/llms/bedrock/base_aws_llm.py index b1b06829387..2c9ea187912 100644 --- a/litellm/llms/bedrock/base_aws_llm.py +++ b/litellm/llms/bedrock/base_aws_llm.py @@ -861,14 +861,58 @@ class BaseAWSLLM: with tracer.trace("boto3.client(sts)"): sts_client = boto3.client("sts", **sts_client_kwargs) + # The session policy is an IAM PERMISSION CEILING — effective + # permissions are the intersection of the role's identity policies + # and this policy. Any action not listed here is silently denied + # even when the IAM role grants it. So every Bedrock route we + # support needs a matching action statement, or it 403s on OIDC + # auth only (static creds + IRSA take other code paths). # https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sts/client/assume_role_with_web_identity.html + bedrock_session_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "BedrockLiteLLM", + "Effect": "Allow", + "Action": [ + "bedrock:InvokeModel", + "bedrock:InvokeModelWithResponseStream", + "bedrock:ApplyGuardrail", + "bedrock:GetGuardrail", + "bedrock:ListGuardrails", + ], + "Resource": "*", + "Condition": {"Bool": {"aws:SecureTransport": "true"}}, + }, + # Claude Platform on AWS (added by #27678 for the + # ``bedrock/claude_platform/`` route) lives under + # a separate IAM action namespace; without these entries + # the OIDC path 403s on every claude_platform request + # even with a fully permissive identity policy (#30200). + { + "Sid": "ClaudePlatformLiteLLM", + "Effect": "Allow", + "Action": [ + "aws-external-anthropic:CreateInference", + "aws-external-anthropic:CreateBatchInference", + "aws-external-anthropic:CancelBatchInference", + "aws-external-anthropic:DeleteBatchInference", + "aws-external-anthropic:CountTokens", + "aws-external-anthropic:Get*", + "aws-external-anthropic:List*", + ], + "Resource": "*", + "Condition": {"Bool": {"aws:SecureTransport": "true"}}, + }, + ], + } assume_role_params = { "RoleArn": aws_role_name, "RoleSessionName": aws_session_name, "WebIdentityToken": oidc_token, "DurationSeconds": 3600, - "Policy": '{"Version":"2012-10-17","Statement":[{"Sid":"BedrockLiteLLM","Effect":"Allow","Action":["bedrock:InvokeModel","bedrock:InvokeModelWithResponseStream","bedrock:ApplyGuardrail","bedrock:GetGuardrail","bedrock:ListGuardrails"],"Resource":"*","Condition":{"Bool":{"aws:SecureTransport":"true"}}}]}', + "Policy": json.dumps(bedrock_session_policy, separators=(",", ":")), } # Add ExternalId parameter if provided diff --git a/litellm/llms/bedrock/chat/agentcore/transformation.py b/litellm/llms/bedrock/chat/agentcore/transformation.py index 44ba1ce3c86..3cd3a249c33 100644 --- a/litellm/llms/bedrock/chat/agentcore/transformation.py +++ b/litellm/llms/bedrock/chat/agentcore/transformation.py @@ -218,8 +218,20 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM): - Qualifier goes as query parameter - Only the payload goes in the request body + Payload shape: + - ``prompt`` is always present and contains the text-only flatten of the + last message's content (existing behavior). + - ``content`` is added ONLY when the ``forward_multimodal_content`` litellm + param is truthy AND the last message's ``content`` is a list containing a + non-text block (e.g. ``image_url``, ``file``, ``input_audio``). The list is + forwarded verbatim so the agent's ``@app.entrypoint`` handler can parse the + OpenAI-shaped multimodal blocks. This is opt-in because an AgentCore agent + must be explicitly written to read ``payload["content"]``; by default the + payload stays byte-identical to the legacy ``{"prompt": "..."}`` shape. + Returns: - dict: Payload dict containing the prompt + dict: Payload dict containing the prompt and (optionally) the OpenAI + content list. """ verbose_logger.debug( f"AgentCore transform_request - optional_params keys: {list(optional_params.keys())}" @@ -231,6 +243,20 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM): # Create the payload - this is what goes in the body (raw JSON) payload: dict = {"prompt": prompt} + # Opt-in: when forward_multimodal_content is set, forward the OpenAI content + # list verbatim under "content" so an attachment-aware agent can read the raw + # blocks (image_url, file, etc.). Default off keeps the payload byte-identical + # to the legacy {"prompt": "..."} shape for agents that only read the prompt. + if self._should_forward_multimodal_content(optional_params, litellm_params): + last_content = messages[-1].get("content") + if isinstance(last_content, list) and any( + isinstance(block, dict) and block.get("type") not in (None, "text") + for block in last_content + ): + # Copy so the payload never aliases messages[-1]["content"]; shallow, + # not deep, to avoid cloning large base64 media on the request path. + payload["content"] = list(last_content) + # Get or generate session ID - this goes in the header runtime_session_id = self._get_runtime_session_id(optional_params) headers["X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"] = runtime_session_id @@ -246,6 +272,29 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM): verbose_logger.debug(f"PAYLOAD: {payload}") return payload + @staticmethod + def _should_forward_multimodal_content( + optional_params: dict, litellm_params: dict + ) -> bool: + """Whether to forward raw OpenAI content blocks under ``payload["content"]``. + + Opt-in via the ``forward_multimodal_content`` litellm param (default ``False``) + because AgentCore agents must be explicitly written to read the field. The + value may arrive as a bool or a config/env string ("true", "1", ...). Checks + ``optional_params`` first (where other AgentCore params land), then + ``litellm_params``. + """ + for source in (optional_params, litellm_params): + if not isinstance(source, dict): + continue + value = source.get("forward_multimodal_content") + if value is None: + continue + if isinstance(value, str): + return value.strip().lower() in ("1", "true", "yes", "on") + return bool(value) + return False + def _extract_sse_json(self, line: str) -> Optional[Dict]: """Extract and parse JSON from an SSE data line.""" if not line.startswith("data:"): diff --git a/litellm/llms/bedrock/chat/converse_handler.py b/litellm/llms/bedrock/chat/converse_handler.py index 388947a4e9b..7b1064ccef9 100644 --- a/litellm/llms/bedrock/chat/converse_handler.py +++ b/litellm/llms/bedrock/chat/converse_handler.py @@ -32,7 +32,7 @@ def make_sync_call( logging_obj: LiteLLMLoggingObject, json_mode: Optional[bool] = False, fake_stream: bool = False, - stream_chunk_size: int = 1024, + stream_chunk_size: Optional[int] = None, ): if client is None: client = _get_httpx_client() # Create a new client if none provided @@ -108,7 +108,7 @@ class BedrockConverseLLM(BaseAWSLLM): fake_stream: bool = False, json_mode: Optional[bool] = False, api_key: Optional[str] = None, - stream_chunk_size: int = 1024, + stream_chunk_size: Optional[int] = None, ) -> CustomStreamWrapper: request_data = await litellm.AmazonConverseConfig()._async_transform_request( model=model, @@ -248,7 +248,7 @@ class BedrockConverseLLM(BaseAWSLLM): encoding=encoding, ) - def completion( # noqa: PLR0915 + def completion( self, model: str, messages: list, @@ -268,7 +268,7 @@ class BedrockConverseLLM(BaseAWSLLM): ): ## SETUP ## stream = optional_params.pop("stream", None) - stream_chunk_size = optional_params.pop("stream_chunk_size", 1024) + stream_chunk_size = optional_params.pop("stream_chunk_size", None) unencoded_model_id = optional_params.pop("model_id", None) fake_stream = optional_params.pop("fake_stream", False) json_mode = optional_params.get("json_mode", False) diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index 90dfa13e938..bb261ec85b2 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -920,10 +920,15 @@ class AmazonConverseConfig(BaseConfig): continue value = [value] optional_params["stopSequences"] = value - if param == "temperature": - optional_params["temperature"] = value - if param == "top_p": - optional_params["topP"] = value + if param == "temperature" or param == "top_p": + AnthropicConfig._apply_sampling_param( + optional_params=optional_params, + model=model, + param=param, + value=value, + drop_params=drop_params, + output_key="topP" if param == "top_p" else param, + ) if param == "tools" and isinstance(value, list): self._apply_tool_call_transformation( tools=cast(List[OpenAIChatCompletionToolParam], value), @@ -1221,7 +1226,9 @@ class AmazonConverseConfig(BaseConfig): inference_params["topK"] = inference_params.pop("top_k") return InferenceConfig(**inference_params) - def _handle_top_k_value(self, model: str, inference_params: dict) -> dict: + def _handle_top_k_value( + self, model: str, inference_params: dict, drop_params: bool = False + ) -> dict: base_model = BedrockModelInfo.get_base_model(model) val_top_k = None @@ -1230,16 +1237,25 @@ class AmazonConverseConfig(BaseConfig): elif "top_k" in inference_params: val_top_k = inference_params.pop("top_k") - if val_top_k: + if val_top_k is not None: if base_model.startswith("anthropic"): - return {"top_k": val_top_k} + top_k_params: dict = {} + AnthropicConfig._apply_sampling_param( + optional_params=top_k_params, + model=model, + param="top_k", + value=val_top_k, + drop_params=drop_params, + output_key="top_k", + ) + return top_k_params if base_model.startswith("amazon.nova"): return {"inferenceConfig": {"topK": val_top_k}} return {} def _prepare_request_params( - self, optional_params: dict, model: str + self, optional_params: dict, model: str, drop_params: bool = False ) -> Tuple[dict, dict, dict, Optional[OutputConfigBlock]]: """Prepare and separate request parameters.""" # Consume the internal ``_output_config_normalized`` marker set by @@ -1338,7 +1354,7 @@ class AmazonConverseConfig(BaseConfig): # Only set the topK value in for models that support it additional_request_params.update( - self._handle_top_k_value(model, inference_params) + self._handle_top_k_value(model, inference_params, drop_params) ) # Filter out internal/MCP-related parameters that shouldn't be sent to the API @@ -1572,6 +1588,7 @@ class AmazonConverseConfig(BaseConfig): optional_params: dict, messages: Optional[List[AllMessageValues]] = None, headers: Optional[dict] = None, + drop_params: bool = False, ) -> CommonRequestObject: ## VALIDATE REQUEST """ @@ -1618,7 +1635,7 @@ class AmazonConverseConfig(BaseConfig): additional_request_params, request_metadata, output_config, - ) = self._prepare_request_params(optional_params, model) + ) = self._prepare_request_params(optional_params, model, drop_params) original_tools = inference_params.pop("tools", []) @@ -1649,12 +1666,14 @@ class AmazonConverseConfig(BaseConfig): bedrock_tool_config["toolChoice"] = tool_choice_values data: CommonRequestObject = { - "additionalModelRequestFields": additional_request_params, - "system": system_content_blocks, "inferenceConfig": self._transform_inference_params( inference_params=inference_params ), } + if additional_request_params: + data["additionalModelRequestFields"] = additional_request_params + if system_content_blocks: + data["system"] = system_content_blocks # Handle all config blocks for config_name, config_class in self.get_config_blocks().items(): @@ -1699,6 +1718,7 @@ class AmazonConverseConfig(BaseConfig): optional_params=optional_params, messages=messages, headers=headers, + drop_params=litellm_params.get("drop_params") is True, ) bedrock_messages = ( @@ -1756,6 +1776,7 @@ class AmazonConverseConfig(BaseConfig): optional_params=optional_params, messages=messages, headers=headers, + drop_params=litellm_params.get("drop_params") is True, ) ## TRANSFORMATION ## @@ -2168,7 +2189,7 @@ class AmazonConverseConfig(BaseConfig): real_tools = [t for i, t in enumerate(tools) if i not in json_tool_indices] return real_tools if real_tools else None - def _transform_response( # noqa: PLR0915 + def _transform_response( self, model: str, response: httpx.Response, diff --git a/litellm/llms/bedrock/chat/invoke_handler.py b/litellm/llms/bedrock/chat/invoke_handler.py index 7a9916f1f31..75b560b4d6d 100644 --- a/litellm/llms/bedrock/chat/invoke_handler.py +++ b/litellm/llms/bedrock/chat/invoke_handler.py @@ -197,7 +197,7 @@ async def make_call( fake_stream: bool = False, json_mode: Optional[bool] = False, bedrock_invoke_provider: Optional[litellm.BEDROCK_INVOKE_PROVIDERS_LITERAL] = None, - stream_chunk_size: int = 1024, + stream_chunk_size: Optional[int] = None, ): try: if client is None: @@ -294,7 +294,7 @@ def make_sync_call( fake_stream: bool = False, json_mode: Optional[bool] = False, bedrock_invoke_provider: Optional[litellm.BEDROCK_INVOKE_PROVIDERS_LITERAL] = None, - stream_chunk_size: int = 1024, + stream_chunk_size: Optional[int] = None, ): try: if client is None: @@ -473,7 +473,7 @@ class BedrockLLM(BaseAWSLLM): prompt += f"{message['content']}" return prompt, chat_history # type: ignore - def process_response( # noqa: PLR0915 + def process_response( self, model: str, response: httpx.Response, @@ -765,7 +765,7 @@ class BedrockLLM(BaseAWSLLM): return model_response - def completion( # noqa: PLR0915 + def completion( self, model: str, messages: list, @@ -790,7 +790,7 @@ class BedrockLLM(BaseAWSLLM): ## SETUP ## stream = optional_params.pop("stream", None) - stream_chunk_size = optional_params.pop("stream_chunk_size", 1024) + stream_chunk_size = optional_params.pop("stream_chunk_size", None) provider = self.get_bedrock_invoke_provider(model) modelId = self.get_bedrock_model_id( @@ -1203,7 +1203,7 @@ class BedrockLLM(BaseAWSLLM): extra_headers: Optional[dict] = None, timeout: Optional[Union[float, httpx.Timeout]] = None, client: Optional[AsyncHTTPHandler] = None, - stream_chunk_size: int = 1024, + stream_chunk_size: Optional[int] = None, ) -> Union[ModelResponse, CustomStreamWrapper]: transformed_request = ( await litellm.AmazonAnthropicClaudeConfig().async_transform_request( @@ -1350,7 +1350,7 @@ class BedrockLLM(BaseAWSLLM): logger_fn=None, headers={}, client: Optional[AsyncHTTPHandler] = None, - stream_chunk_size: int = 1024, + stream_chunk_size: Optional[int] = None, ) -> CustomStreamWrapper: # The call is not made here; instead, we prepare the necessary objects for the stream. 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 a13336b6c88..79153c3ceff 100644 --- a/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py @@ -60,6 +60,9 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig): def custom_llm_provider(self) -> Optional[str]: return "bedrock" + def should_strip_billing_metadata(self) -> bool: + return True + def get_supported_openai_params(self, model: str) -> List[str]: return AnthropicConfig.get_supported_openai_params(self, model) @@ -212,6 +215,7 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig): anthropic_request.pop("model", None) anthropic_request.pop("stream", None) + anthropic_request.pop("stream_chunk_size", None) output_format = anthropic_request.pop("output_format", None) output_config_format = pop_bedrock_invoke_output_config_format( anthropic_request diff --git a/litellm/llms/bedrock/chat/invoke_transformations/base_invoke_transformation.py b/litellm/llms/bedrock/chat/invoke_transformations/base_invoke_transformation.py index 43850440072..8fc2375c224 100644 --- a/litellm/llms/bedrock/chat/invoke_transformations/base_invoke_transformation.py +++ b/litellm/llms/bedrock/chat/invoke_transformations/base_invoke_transformation.py @@ -150,6 +150,7 @@ class AmazonInvokeConfig(BaseConfig, BaseAWSLLM): ) -> dict: ## SETUP ## stream = optional_params.pop("stream", None) + optional_params.pop("stream_chunk_size", None) custom_prompt_dict: dict = litellm_params.pop("custom_prompt_dict", None) or {} hf_model_name = litellm_params.get("hf_model_name", None) @@ -256,7 +257,7 @@ class AmazonInvokeConfig(BaseConfig, BaseAWSLLM): return request_data - def transform_response( # noqa: PLR0915 + def transform_response( self, model: str, raw_response: httpx.Response, diff --git a/litellm/llms/bedrock/chat/mantle/transformation.py b/litellm/llms/bedrock/chat/mantle/transformation.py index ef0199031af..cbed2232be5 100644 --- a/litellm/llms/bedrock/chat/mantle/transformation.py +++ b/litellm/llms/bedrock/chat/mantle/transformation.py @@ -48,6 +48,30 @@ class AmazonMantleConfig(AmazonAnthropicClaudeConfig): region = self._get_aws_region_name(optional_params=optional_params, model=model) return MANTLE_ENDPOINT_TEMPLATE.format(region=region) + 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: + headers = super().validate_environment( + headers=headers, + model=model, + messages=messages, + optional_params=optional_params, + litellm_params=litellm_params, + api_key=api_key, + api_base=api_base, + ) + project_id = litellm_params.get("aws_bedrock_project_id") + if project_id: + headers["anthropic-workspace"] = project_id + return headers + def transform_request( self, model: str, diff --git a/litellm/llms/bedrock/claude_platform/transformation.py b/litellm/llms/bedrock/claude_platform/transformation.py index 0167c457c96..c20dc63444f 100644 --- a/litellm/llms/bedrock/claude_platform/transformation.py +++ b/litellm/llms/bedrock/claude_platform/transformation.py @@ -17,6 +17,9 @@ class BedrockClaudePlatformConfig(BedrockClaudePlatformMixin, AnthropicConfig): def custom_llm_provider(self) -> Optional[str]: return "bedrock" + def should_strip_billing_metadata(self) -> bool: + return True + def validate_environment( self, headers: dict, diff --git a/litellm/llms/bedrock/count_tokens/transformation.py b/litellm/llms/bedrock/count_tokens/transformation.py index c967fd334bc..bdef3349e00 100644 --- a/litellm/llms/bedrock/count_tokens/transformation.py +++ b/litellm/llms/bedrock/count_tokens/transformation.py @@ -11,6 +11,11 @@ from typing import Any, Dict, List, Optional from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM from litellm.llms.bedrock.common_utils import get_bedrock_base_model +# Placeholder satisfying the Anthropic InvokeModel schema's required +# max_tokens field; CountTokens only counts input, so it has no effect +# on any generation. +DEFAULT_ANTHROPIC_INVOKE_MODEL_MAX_TOKENS = 1024 + class BedrockCountTokensConfig(BaseAWSLLM): """ @@ -32,8 +37,20 @@ class BedrockCountTokensConfig(BaseAWSLLM): Returns: 'converse' or 'invokeModel' """ - # If the request has messages in the expected Anthropic format, use converse - if "messages" in request_data and isinstance(request_data["messages"], list): + messages = request_data.get("messages") + if isinstance(messages, list): + # Anthropic content blocks carry a "type" key ({"type": "text", ...}); + # Converse blocks don't ({"text": ...}, {"toolUse": ...}). Converse + # rejects Anthropic-shape blocks, so route those to invokeModel, + # which forwards the body verbatim. + for message in messages: + if not isinstance(message, dict): + continue + content = message.get("content") + if isinstance(content, list) and any( + isinstance(block, dict) and "type" in block for block in content + ): + return "invokeModel" return "converse" # For raw text or other formats, use invokeModel @@ -68,7 +85,7 @@ class BedrockCountTokensConfig(BaseAWSLLM): { "input": { "invokeModel": { - "body": "{...raw model input...}" + "body": "" } } } @@ -168,13 +185,24 @@ class BedrockCountTokensConfig(BaseAWSLLM): self, request_data: Dict[str, Any] ) -> Dict[str, Any]: """Transform to InvokeModel input format.""" + import base64 import json # For InvokeModel, we need to provide the raw body that would be sent to the model # Remove the 'model' field from the body as it's not part of the model input body_data = {k: v for k, v in request_data.items() if k != "model"} - return {"input": {"invokeModel": {"body": json.dumps(body_data)}}} + if "messages" in body_data: + # Bedrock validates the body against the model's InvokeModel schema; + # Anthropic Messages bodies require these fields. + body_data.setdefault("anthropic_version", "bedrock-2023-05-31") + body_data.setdefault( + "max_tokens", DEFAULT_ANTHROPIC_INVOKE_MODEL_MAX_TOKENS + ) + + # The CountTokens API expects invokeModel.body as a base64-encoded blob + encoded_body = base64.b64encode(json.dumps(body_data).encode()).decode() + return {"input": {"invokeModel": {"body": encoded_body}}} def get_bedrock_count_tokens_endpoint( self, diff --git a/litellm/llms/bedrock/embed/embedding.py b/litellm/llms/bedrock/embed/embedding.py index 27dc785bf57..b6aa99842d7 100644 --- a/litellm/llms/bedrock/embed/embedding.py +++ b/litellm/llms/bedrock/embed/embedding.py @@ -388,7 +388,7 @@ class BedrockEmbedding(BaseAWSLLM): batch_data=batch_data, ) - def embeddings( # noqa: PLR0915 + def embeddings( self, model: str, input: List[str], diff --git a/litellm/llms/bedrock/files/handler.py b/litellm/llms/bedrock/files/handler.py index ecf157e12ee..b6aae2159c1 100644 --- a/litellm/llms/bedrock/files/handler.py +++ b/litellm/llms/bedrock/files/handler.py @@ -1,8 +1,6 @@ import asyncio -import base64 -import os -from types import MappingProxyType -from typing import Any, Coroutine, Mapping, Optional, Tuple, Union, cast +from collections.abc import Mapping +from typing import Any, Coroutine, Optional, Tuple, Union import httpx @@ -17,7 +15,6 @@ from litellm.types.llms.openai import ( FileContentRequest, HttpxBinaryResponseContent, ) -from litellm.types.utils import SpecialEnums from ..base_aws_llm import BaseAWSLLM @@ -37,40 +34,9 @@ class BedrockFilesHandler(BaseAWSLLM): ) def _extract_s3_uri_from_file_id(self, file_id: str) -> str: - """ - Extract S3 URI from encoded file ID. + from .transformation import extract_s3_uri_from_file_id - The file ID can be in two formats: - 1. Base64-encoded unified file ID containing: llm_output_file_id,s3://bucket/path - 2. Direct S3 URI: s3://bucket/litellm-managed-prefix/path - - Args: - file_id: Encoded file ID or direct S3 URI - - Returns: - S3 URI (e.g., "s3://bucket-name/path/to/file") - """ - # First, try to decode if it's a base64-encoded unified file ID - try: - # Add padding if needed - padded = file_id + "=" * (-len(file_id) % 4) - decoded = base64.urlsafe_b64decode(padded).decode() - - # Check if it's a unified file ID format - if decoded.startswith(SpecialEnums.LITELM_MANAGED_FILE_ID_PREFIX.value): - # Extract llm_output_file_id from the decoded string - if "llm_output_file_id," in decoded: - s3_uri = decoded.split("llm_output_file_id,")[1].split(";")[0] - return s3_uri - except Exception: - pass - - # If not base64 encoded or doesn't contain llm_output_file_id, accept only - # explicit S3 URIs. Bucket and key validation happens before any S3 call. - if file_id.startswith("s3://"): - return file_id - - raise ValueError("file_id must be a managed LiteLLM S3 file id") + return extract_s3_uri_from_file_id(file_id) def _parse_s3_uri( self, @@ -95,26 +61,12 @@ class BedrockFilesHandler(BaseAWSLLM): allow_legacy_cloud_file_ids=allow_legacy_cloud_file_ids, ) - def _get_configured_s3_bucket_name(self, litellm_params: dict) -> str: - trusted_model_credentials = litellm_params.get( - "_litellm_internal_model_credentials" - ) - bucket_name = None - if isinstance(trusted_model_credentials, type(MappingProxyType({}))): - trusted_model_credentials_mapping = cast( - Mapping[str, Any], trusted_model_credentials - ) - candidate_bucket_name = trusted_model_credentials_mapping.get( - "s3_bucket_name" - ) - if isinstance(candidate_bucket_name, str): - bucket_name = candidate_bucket_name - bucket_name = bucket_name or os.getenv("AWS_S3_BUCKET_NAME") - if not bucket_name: - raise ValueError( - "S3 bucket_name is required. Set 's3_bucket_name' in proxy config or AWS_S3_BUCKET_NAME for Bedrock file content retrieval." - ) - return bucket_name + def _get_configured_s3_bucket_name( + self, litellm_params: Mapping[str, object] + ) -> str: + from .transformation import get_configured_s3_bucket_name + + return get_configured_s3_bucket_name(litellm_params) async def afile_content( self, diff --git a/litellm/llms/bedrock/files/transformation.py b/litellm/llms/bedrock/files/transformation.py index cec2e934af8..6cfaa88275d 100644 --- a/litellm/llms/bedrock/files/transformation.py +++ b/litellm/llms/bedrock/files/transformation.py @@ -1,23 +1,37 @@ +import base64 import json import os import time -from typing import Any, Dict, List, Optional, Tuple, Union +from collections.abc import Mapping, MutableMapping +from types import MappingProxyType +from typing import ( + Any, + Dict, + List, + Optional, + Tuple, + Union, +) from urllib.parse import unquote import httpx from httpx import Headers, Response from openai.types.file_deleted import FileDeleted +from pydantic import BaseModel, ConfigDict from litellm._logging import verbose_logger from litellm._uuid import uuid from litellm.files.utils import FilesAPIUtils from litellm.litellm_core_utils.cloud_storage_security import ( BEDROCK_MANAGED_S3_BATCH_PREFIX, + BEDROCK_MANAGED_S3_PREFIXES, BEDROCK_MANAGED_S3_UPLOAD_PREFIX, build_managed_cloud_object_name, encode_s3_object_key_for_url, sanitize_cloud_object_component, + should_allow_legacy_cloud_file_ids, split_configured_cloud_bucket_name, + validate_managed_cloud_file_id, ) from litellm.litellm_core_utils.prompt_templates.common_utils import extract_file_data from litellm.llms.base_llm.chat.transformation import BaseLLMException @@ -28,18 +42,98 @@ from litellm.llms.base_llm.files.transformation import ( from litellm.types.llms.openai import ( AllMessageValues, CreateFileRequest, + FileContentRequest, FileTypes, HttpxBinaryResponseContent, OpenAICreateFileRequestOptionalParams, OpenAIFileObject, PathLike, ) -from litellm.types.utils import ExtractedFileData, LlmProviders +from litellm.types.utils import ExtractedFileData, LlmProviders, SpecialEnums from litellm.utils import get_llm_provider from ..base_aws_llm import BaseAWSLLM from ..common_utils import BedrockError +# litellm_params key used to hand the SigV4-signed GET headers from +# `transform_file_content_request` to `validate_environment` (the only hook +# the shared file-content HTTP handler exposes for setting request headers). +# Same pattern as the `upload_url` handoff in `transform_create_file_request`. +S3_SIGNED_GET_HEADERS_PARAM = "_s3_signed_get_headers" + + +class _BedrockS3RequestParams(BaseModel): + """Typed view of the credential/region params the S3 GetObject path reads.""" + + model_config = ConfigDict(extra="ignore") + + aws_access_key_id: str | None = None + aws_secret_access_key: str | None = None + aws_session_token: str | None = None + aws_region_name: str | None = None + aws_session_name: str | None = None + aws_profile_name: str | None = None + aws_role_name: str | None = None + aws_web_identity_token: str | None = None + aws_sts_endpoint: str | None = None + s3_region_name: str | None = None + s3_endpoint_url: str | None = None + + +class _TrustedS3ModelCredentials(BaseModel): + """The S3 bucket the server trusts file ids against, from the deployment snapshot.""" + + model_config = ConfigDict(extra="ignore") + + s3_bucket_name: str | None = None + + +def extract_s3_uri_from_file_id(file_id: str) -> str: + """ + Resolve a Bedrock file id to its S3 URI. + + Accepts either a base64-encoded LiteLLM unified file id (whose decoded + form carries `llm_output_file_id,s3://...`) or a direct `s3://` URI. + """ + try: + padded = file_id + "=" * (-len(file_id) % 4) + decoded = base64.urlsafe_b64decode(padded).decode() + + if decoded.startswith(SpecialEnums.LITELM_MANAGED_FILE_ID_PREFIX.value): + if "llm_output_file_id," in decoded: + return decoded.split("llm_output_file_id,")[1].split(";")[0] + except Exception: + pass + + if file_id.startswith("s3://"): + return file_id + + raise ValueError("file_id must be a managed LiteLLM S3 file id") + + +def get_configured_s3_bucket_name(litellm_params: Mapping[str, object]) -> str: + """ + Resolve the server-configured S3 bucket for Bedrock file operations. + + Only trusts the immutable server-side credential snapshot or the + environment; never a request-supplied param, since the bucket is what + `validate_managed_cloud_file_id` checks file ids against. + """ + trusted_model_credentials = litellm_params.get( + "_litellm_internal_model_credentials" + ) + bucket_name: str | None = None + if isinstance(trusted_model_credentials, MappingProxyType): + snapshot: dict[str, object] = {} + snapshot.update(trusted_model_credentials) # any-ok: untyped snapshot + bucket_name = _TrustedS3ModelCredentials.model_validate(snapshot).s3_bucket_name + bucket_name = bucket_name or os.getenv("AWS_S3_BUCKET_NAME") + if not bucket_name: + raise ValueError( + "S3 bucket_name is required. Set 's3_bucket_name' in proxy config or AWS_S3_BUCKET_NAME for Bedrock file content retrieval." + ) + return bucket_name + class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig): """ @@ -63,16 +157,21 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig): def validate_environment( self, - headers: dict, + headers: MutableMapping[str, object], model: str, messages: List[AllMessageValues], optional_params: dict, - litellm_params: dict, - api_key: Optional[str] = None, - api_base: Optional[str] = None, + litellm_params: MutableMapping[str, object], + api_key: str | None = None, + api_base: str | None = None, ) -> dict: - # No additional headers needed for S3 uploads - AWS credentials handled by BaseAWSLLM - return headers + result: dict[str, object] = {} + result.update(headers) + signed_headers = litellm_params.pop(S3_SIGNED_GET_HEADERS_PARAM, None) + if isinstance(signed_headers, Mapping): + result.update(signed_headers) # any-ok: untyped handoff headers + # otherwise no extra headers - AWS credentials are handled by BaseAWSLLM + return result def _get_content_from_openai_file(self, openai_file_content: FileTypes) -> str: """ @@ -927,23 +1026,114 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig): def transform_file_content_request( self, - file_content_request, - optional_params: dict, - litellm_params: dict, - ) -> tuple[str, dict]: - raise NotImplementedError( - "BedrockFilesConfig does not support file content retrieval" + file_content_request: FileContentRequest, + optional_params: Mapping[str, object], + litellm_params: MutableMapping[str, object], + ) -> tuple[str, dict[str, str]]: + """ + Build a SigV4-signed S3 GetObject request for a Bedrock batch file. + + Bedrock batch file ids are `s3://bucket/key` URIs (or unified ids + that decode to one); the bucket and key are validated against the + server-configured bucket before any request is signed. + """ + file_id = file_content_request.get("file_id") + if not file_id: + raise ValueError("file_id is required for Bedrock file content retrieval") + + s3_uri = extract_s3_uri_from_file_id(file_id) + bucket_name, object_key = validate_managed_cloud_file_id( + file_id=s3_uri, + scheme="s3://", + configured_bucket_name=get_configured_s3_bucket_name(litellm_params), + allowed_object_prefixes=BEDROCK_MANAGED_S3_PREFIXES, + allow_legacy_cloud_file_ids=should_allow_legacy_cloud_file_ids( + litellm_params + ), ) + # The shared file-content handler passes optional_params={}, so AWS + # credentials/region arrive via litellm_params here (unlike the upload + # path). s3_region_name wins over aws_region_name, same priority as + # get_complete_file_url above. + merged_params: dict[str, object] = {} + merged_params.update(litellm_params) + merged_params.update(optional_params) + request_params = _BedrockS3RequestParams.model_validate(merged_params) + + region_preference = ( + request_params.s3_region_name or request_params.aws_region_name + ) + region_params: dict[str, str | None] = {"aws_region_name": region_preference} + aws_region_name = self._get_aws_region_name( + optional_params=region_params, model="" + ) + + s3_endpoint_url = ( + request_params.s3_endpoint_url + or f"https://s3.{aws_region_name}.amazonaws.com" + ).rstrip("/") + url = f"{s3_endpoint_url}/{bucket_name}/{encode_s3_object_key_for_url(object_key)}" + + litellm_params[S3_SIGNED_GET_HEADERS_PARAM] = self._sign_s3_get_request( + api_base=url, + aws_region_name=aws_region_name, + request_params=request_params, + ) + return url, {} + + def _sign_s3_get_request( + self, + api_base: str, + aws_region_name: str, + request_params: _BedrockS3RequestParams, + ) -> dict[str, str]: + """ + SigV4-sign an S3 GetObject request, mirroring `_sign_s3_request` (PUT). + """ + try: + import hashlib + + from botocore.auth import SigV4Auth + from botocore.awsrequest import AWSRequest + except ImportError: + raise ImportError("Missing boto3 to call bedrock. Run 'pip install boto3'.") + + credentials = self.get_credentials( # any-ok: boto3 Credentials is untyped + aws_access_key_id=request_params.aws_access_key_id, + aws_secret_access_key=request_params.aws_secret_access_key, + aws_session_token=request_params.aws_session_token, + aws_region_name=aws_region_name, + aws_session_name=request_params.aws_session_name, + aws_profile_name=request_params.aws_profile_name, + aws_role_name=request_params.aws_role_name, + aws_web_identity_token=request_params.aws_web_identity_token, + aws_sts_endpoint=request_params.aws_sts_endpoint, + ) + + empty_body_hash = hashlib.sha256(b"").hexdigest() + aws_request = AWSRequest( # any-ok: botocore AWSRequest is untyped + method="GET", + url=api_base, + headers={"x-amz-content-sha256": empty_body_hash}, + ) + auth = SigV4Auth(credentials, "s3", aws_region_name) # any-ok: botocore untyped + auth.add_auth(aws_request) # any-ok: botocore request mutation is untyped + return dict(aws_request.headers) # any-ok: botocore headers are untyped + def transform_file_content_response( self, raw_response: httpx.Response, logging_obj: LiteLLMLoggingObj, litellm_params: dict, ) -> HttpxBinaryResponseContent: - raise NotImplementedError( - "BedrockFilesConfig does not support file content retrieval" - ) + if raw_response.status_code >= 400: + raise BedrockError( + status_code=raw_response.status_code, + message=raw_response.text, + headers=raw_response.headers, + ) + return HttpxBinaryResponseContent(response=raw_response) class BedrockJsonlFilesTransformation: diff --git a/litellm/llms/bedrock/image_edit/stability_transformation.py b/litellm/llms/bedrock/image_edit/stability_transformation.py index 2d73e47003d..d00d62a8530 100644 --- a/litellm/llms/bedrock/image_edit/stability_transformation.py +++ b/litellm/llms/bedrock/image_edit/stability_transformation.py @@ -149,7 +149,7 @@ class BedrockStabilityImageEditConfig(BaseImageEditConfig): return mapped_params - def transform_image_edit_request( # noqa: PLR0915 + def transform_image_edit_request( self, model: str, prompt: Optional[str], diff --git a/litellm/llms/bedrock/messages/mantle_transformation.py b/litellm/llms/bedrock/messages/mantle_transformation.py index a78f696a057..900d9aa97d8 100644 --- a/litellm/llms/bedrock/messages/mantle_transformation.py +++ b/litellm/llms/bedrock/messages/mantle_transformation.py @@ -6,7 +6,7 @@ AmazonAnthropicClaudeMessagesConfig. Overrides only the URL and model-prefix stripping that are specific to the bedrock-mantle endpoint. """ -from typing import TYPE_CHECKING, Any, Dict, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple from litellm.llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation import ( AmazonAnthropicClaudeMessagesConfig, @@ -45,6 +45,30 @@ class AmazonMantleMessagesConfig(AmazonAnthropicClaudeMessagesConfig): region = self._get_aws_region_name(optional_params=optional_params, model=model) return MANTLE_ENDPOINT_TEMPLATE.format(region=region) + def validate_anthropic_messages_environment( + self, + headers: dict, + model: str, + messages: List[Any], + optional_params: dict, + litellm_params: dict, + api_key: Optional[str] = None, + api_base: Optional[str] = None, + ) -> Tuple[dict, Optional[str]]: + headers, api_base = super().validate_anthropic_messages_environment( + headers=headers, + model=model, + messages=messages, + optional_params=optional_params, + litellm_params=litellm_params, + api_key=api_key, + api_base=api_base, + ) + project_id = litellm_params.get("aws_bedrock_project_id") + if project_id: + headers["anthropic-workspace"] = project_id + return headers, api_base + def transform_anthropic_messages_request( self, model: str, diff --git a/litellm/llms/bedrock/passthrough/guardrail_translation/__init__.py b/litellm/llms/bedrock/passthrough/guardrail_translation/__init__.py new file mode 100644 index 00000000000..e38044afb36 --- /dev/null +++ b/litellm/llms/bedrock/passthrough/guardrail_translation/__init__.py @@ -0,0 +1,5 @@ +from litellm.llms.bedrock.passthrough.guardrail_translation.handler import ( + BedrockPassthroughGuardrailHandler, +) + +__all__ = ["BedrockPassthroughGuardrailHandler"] diff --git a/litellm/llms/bedrock/passthrough/guardrail_translation/handler.py b/litellm/llms/bedrock/passthrough/guardrail_translation/handler.py new file mode 100644 index 00000000000..0522bb249e1 --- /dev/null +++ b/litellm/llms/bedrock/passthrough/guardrail_translation/handler.py @@ -0,0 +1,507 @@ +from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union + +from litellm._logging import verbose_proxy_logger +from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation +from litellm.llms.base_llm.guardrail_translation.utils import ( + effective_skip_system_message_for_guardrail, + effective_skip_tool_message_for_guardrail, +) +from litellm.types.utils import GenericGuardrailAPIInputs + +if TYPE_CHECKING: + from litellm.integrations.custom_guardrail import CustomGuardrail + from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj + from litellm.proxy._types import UserAPIKeyAuth + from litellm.proxy.utils import ProxyLogging + +_CONVERSE_ACTIONS = frozenset({"converse", "converse-stream"}) +_EVENT_STREAM_CONTENT_TYPE = "vnd.amazon.eventstream" +_EVENT_STREAM_MEDIA_TYPE = "application/vnd.amazon.eventstream" + + +def _is_converse_endpoint(endpoint: str) -> bool: + parts = endpoint.rstrip("/").split("/") + return bool(parts) and parts[-1] in _CONVERSE_ACTIONS + + +def _generic_passthrough_handler() -> BaseTranslation: + """ + Fallback for non-Converse Bedrock routes (e.g. invoke). The generic + handler scans the full request/response payload so blocking guardrails + still run, matching how other passthrough providers are guarded. + """ + from litellm.llms.pass_through.guardrail_translation.handler import ( + PassThroughEndpointHandler, + ) + + return PassThroughEndpointHandler() + + +_StringHolder = Tuple[Any, Union[str, int]] + + +def _collect_strings(node: Any, holders: List[_StringHolder]) -> None: + """ + Record a (container, key) holder for every non-empty string value nested + under an arbitrary JSON node, so prompt content a caller hides in fields + like ``toolUse.input`` or ``toolResult.content[].json`` is still scanned + and can be written back in place. Iterative to avoid unbounded recursion + on deeply nested payloads. + """ + stack: List[Any] = [node] + while stack: + current = stack.pop() + if isinstance(current, dict): + for key, value in current.items(): + if isinstance(value, str): + if value: + holders.append((current, key)) + else: + stack.append(value) + elif isinstance(current, list): + for index, value in enumerate(current): + if isinstance(value, str): + if value: + holders.append((current, index)) + else: + stack.append(value) + + +def _collect_block_text(block: dict, holders: List[_StringHolder]) -> None: + text = block.get("text") + if isinstance(text, str) and text: + holders.append((block, "text")) + + +def _extract_converse_texts( + body: dict, + skip_system: bool, + skip_tool: bool, +) -> Tuple[List[str], List[_StringHolder]]: + """ + Walk a Bedrock Converse request body and collect text content. + + Returns (texts, holders) where each holder is the (container, key) pair + that owns the extracted string, so write-back mutates it in place. Besides + top-level ``text`` blocks this scans the arbitrary-JSON fields a caller can + hide prompt content in -- ``toolUse.input`` and + ``toolResult.content[].json`` (alongside ``toolResult.content[].text``) -- + as well as the request-level fields still forwarded to Bedrock that a caller + can route blocked content through: ``toolConfig.tools`` (tool names, + descriptions and input schemas) and ``additionalModelRequestFields``. Tool + message blocks are skipped when tool messages are excluded, but tool + definitions are always scanned to match the chat-completions guardrail path. + """ + holders: List[_StringHolder] = [] + + if not skip_system: + for block in body.get("system") or []: + if isinstance(block, dict): + _collect_block_text(block, holders) + + for message in body.get("messages") or []: + if not isinstance(message, dict): + continue + for block in message.get("content") or []: + if not isinstance(block, dict): + continue + if skip_tool and ("toolUse" in block or "toolResult" in block): + continue + _collect_block_text(block, holders) + tool_use = block.get("toolUse") + if isinstance(tool_use, dict): + _collect_strings(tool_use.get("input"), holders) + tool_result = block.get("toolResult") + if isinstance(tool_result, dict): + for inner in tool_result.get("content") or []: + if isinstance(inner, dict): + _collect_block_text(inner, holders) + _collect_strings(inner.get("json"), holders) + + tool_config = body.get("toolConfig") + if isinstance(tool_config, dict): + _collect_strings(tool_config.get("tools"), holders) + + _collect_strings(body.get("additionalModelRequestFields"), holders) + + texts = [container[key] for container, key in holders] + return texts, holders + + +def _extract_converse_output_texts( + content_blocks: List[Any], +) -> Tuple[List[str], List[_StringHolder]]: + """ + Collect user-visible text from Bedrock Converse output content blocks. + + Covers ``text`` blocks plus the other content-bearing fields a model can + emit -- ``toolUse.input``, ``reasoningContent.reasoningText.text`` and + ``citationsContent.content[].text`` -- while leaving structural values such + as reasoning signatures and citation sources untouched. + """ + holders: List[_StringHolder] = [] + for block in content_blocks: + if not isinstance(block, dict): + continue + _collect_block_text(block, holders) + tool_use = block.get("toolUse") + if isinstance(tool_use, dict): + _collect_strings(tool_use.get("input"), holders) + reasoning = block.get("reasoningContent") + if isinstance(reasoning, dict): + reasoning_text = reasoning.get("reasoningText") + if isinstance(reasoning_text, dict): + _collect_block_text(reasoning_text, holders) + citations = block.get("citationsContent") + if isinstance(citations, dict): + for cited in citations.get("content") or []: + if isinstance(cited, dict): + _collect_block_text(cited, holders) + texts = [container[key] for container, key in holders] + return texts, holders + + +def _write_back_texts( + guardrailed_texts: List[str], + holders: List[_StringHolder], +) -> None: + if len(guardrailed_texts) < len(holders): + verbose_proxy_logger.warning( + "BedrockPassthroughGuardrailHandler: guardrail returned %d texts for %d " + "extracted fields; the unreturned fields keep their original text", + len(guardrailed_texts), + len(holders), + ) + for idx, (container, key) in enumerate(holders): + if idx >= len(guardrailed_texts): + break + container[key] = guardrailed_texts[idx] + + +_DeltaHolder = Tuple[Any, Any, Union[str, int]] + + +def _collect_stream_delta_text_holders(delta: Any) -> List[_DeltaHolder]: + """ + Collect the user-visible text strings a Bedrock Converse ``contentBlockDelta`` + can carry, matching the coverage of the non-streaming output handler. + + Each holder is ``(group_key, container, key)`` where ``container[key]`` is the + text. ``group_key`` ties together fragments that belong to the same logical + stream (e.g. a single mask token split across frames) so they are + concatenated before guardrailing and redistributed afterwards. Structural + values such as reasoning signatures, redacted reasoning and citation sources + are left out so they are never rewritten. + """ + holders: List[_DeltaHolder] = [] + if not isinstance(delta, dict): + return holders + if isinstance(delta.get("text"), str): + holders.append(("text", delta, "text")) + tool_use = delta.get("toolUse") + if isinstance(tool_use, dict) and isinstance(tool_use.get("input"), str): + holders.append(("tool", tool_use, "input")) + reasoning = delta.get("reasoningContent") + if isinstance(reasoning, dict) and isinstance(reasoning.get("text"), str): + holders.append(("reasoning", reasoning, "text")) + citations = delta.get("citationsContent") + if isinstance(citations, dict): + for index, cited in enumerate(citations.get("content") or []): + if isinstance(cited, dict) and isinstance(cited.get("text"), str): + holders.append((("citation", index), cited, "text")) + return holders + + +class BedrockPassthroughGuardrailHandler(BaseTranslation): + @staticmethod + def is_event_stream_content_type(content_type: str) -> bool: + return _EVENT_STREAM_CONTENT_TYPE in content_type + + @staticmethod + def event_stream_media_type() -> str: + return _EVENT_STREAM_MEDIA_TYPE + + @staticmethod + def event_stream_endpoint_is_de_anonymizable(endpoint: str) -> bool: + return _is_converse_endpoint(endpoint) + + @staticmethod + async def de_anonymize_event_stream( + body_bytes: bytes, + proxy_logging_obj: "ProxyLogging", + user_api_key_dict: "UserAPIKeyAuth", + data: dict, + ) -> bytes: + import json as _json + import struct + from binascii import crc32 as esm_crc32 + + from botocore.eventstream import EventStreamBuffer + + frames: list[dict] = [] + offset = 0 + + while offset + 16 <= len(body_bytes): + total_length = struct.unpack("!I", body_bytes[offset : offset + 4])[0] + if total_length < 16 or offset + total_length > len(body_bytes): + break + frame_raw = body_bytes[offset : offset + total_length] + offset += total_length + + try: + buf = EventStreamBuffer() + buf.add_data(frame_raw) + msg = next(iter(buf)) + event_type = msg.headers.get(":event-type") + payload_bytes = msg.payload + except Exception as e: + verbose_proxy_logger.debug( + "BedrockPassthroughGuardrailHandler: could not decode event-stream " + "frame, forwarding it unmodified: %s", + e, + ) + frames.append({"raw": frame_raw, "texts": []}) + continue + + texts: List[Tuple[Any, str]] = [] + if event_type == "contentBlockDelta": + try: + payload_dict = _json.loads(payload_bytes) + texts = [ + (group_key, container[key]) + for group_key, container, key in _collect_stream_delta_text_holders( + payload_dict.get("delta") + ) + ] + except Exception as e: + verbose_proxy_logger.debug( + "BedrockPassthroughGuardrailHandler: could not parse " + "contentBlockDelta payload, forwarding frame unmodified: %s", + e, + ) + + frames.append({"raw": frame_raw, "texts": texts}) + + trailing_bytes = body_bytes[offset:] + + group_order: List[Any] = [] + group_members: dict[Any, list[Tuple[int, int]]] = {} + group_texts: dict[Any, list[str]] = {} + for frame_idx, frame in enumerate(frames): + for local_idx, (group_key, text) in enumerate(frame["texts"]): + if group_key not in group_members: + group_members[group_key] = [] + group_texts[group_key] = [] + group_order.append(group_key) + group_members[group_key].append((frame_idx, local_idx)) + group_texts[group_key].append(text) + + active_groups = [gk for gk in group_order if "".join(group_texts[gk])] + if not active_groups: + return body_bytes + + synthetic_response: dict = { + "output": { + "message": { + "role": "assistant", + "content": [ + {"text": "".join(group_texts[gk])} for gk in active_groups + ], + } + }, + "stopReason": "end_turn", + } + + processed = await proxy_logging_obj.post_call_success_hook( + data=data, + user_api_key_dict=user_api_key_dict, + response=synthetic_response, # type: ignore[arg-type] + ) + + if not isinstance(processed, dict): + verbose_proxy_logger.debug( + "BedrockPassthroughGuardrailHandler: post_call_success_hook returned %s, " + "leaving event stream unmodified", + type(processed).__name__, + ) + return body_bytes + + try: + processed_blocks = processed["output"]["message"]["content"] # type: ignore[index] + de_anonymized_texts = [ + processed_blocks[i]["text"] for i in range(len(active_groups)) + ] + except (KeyError, IndexError, TypeError): + return body_bytes + + new_text_map: dict[Tuple[int, int], str] = {} + for group_key, de_anonymized_text in zip(active_groups, de_anonymized_texts): + members = group_members[group_key] + orig_texts = group_texts[group_key] + total_orig = sum(len(t) for t in orig_texts) or 1 + de_anon_len = len(de_anonymized_text) + pos = 0 + for k, member in enumerate(members): + if k == len(members) - 1: + new_text_map[member] = de_anonymized_text[pos:] + else: + end = pos + round(de_anon_len * len(orig_texts[k]) / total_orig) + new_text_map[member] = de_anonymized_text[pos:end] + pos = end + + result_parts: list[bytes] = [] + + for frame_idx, frame in enumerate(frames): + if not frame["texts"]: + result_parts.append(frame["raw"]) + continue + + frame_raw = frame["raw"] + orig_total = struct.unpack("!I", frame_raw[0:4])[0] + orig_hdrs_len = struct.unpack("!I", frame_raw[4:8])[0] + headers_bytes = frame_raw[12 : 12 + orig_hdrs_len] + + try: + payload_dict = _json.loads( + frame_raw[12 + orig_hdrs_len : orig_total - 4] + ) + for local_idx, (_, container, key) in enumerate( + _collect_stream_delta_text_holders(payload_dict.get("delta")) + ): + new_text = new_text_map.get((frame_idx, local_idx)) + if new_text is not None: + container[key] = new_text + new_payload = _json.dumps(payload_dict, separators=(",", ":")).encode() + except Exception: + result_parts.append(frame_raw) + continue + + new_total = 12 + orig_hdrs_len + len(new_payload) + 4 + prelude = struct.pack("!II", new_total, orig_hdrs_len) + prelude_crc_val = esm_crc32(prelude) & 0xFFFFFFFF + prelude_crc_b = struct.pack("!I", prelude_crc_val) + part_for_msg_crc = prelude_crc_b + headers_bytes + new_payload + msg_crc_val = esm_crc32(part_for_msg_crc, prelude_crc_val) & 0xFFFFFFFF + msg_crc_b = struct.pack("!I", msg_crc_val) + + result_parts.append( + prelude + prelude_crc_b + headers_bytes + new_payload + msg_crc_b + ) + + result_parts.append(trailing_bytes) + return b"".join(result_parts) + + async def process_input_messages( + self, + data: dict, + guardrail_to_apply: "CustomGuardrail", + litellm_logging_obj: Optional["LiteLLMLoggingObj"] = None, + ) -> Any: + endpoint = data.get("endpoint", "") + body = data.get("data") + + if not _is_converse_endpoint(endpoint): + return await _generic_passthrough_handler().process_input_messages( + data=data, + guardrail_to_apply=guardrail_to_apply, + litellm_logging_obj=litellm_logging_obj, + ) + + if not isinstance(body, dict) or not isinstance(body.get("messages"), list): + return data + + skip_system = effective_skip_system_message_for_guardrail(guardrail_to_apply) + skip_tool = effective_skip_tool_message_for_guardrail(guardrail_to_apply) + + texts, holders = _extract_converse_texts(body, skip_system, skip_tool) + + if not texts: + return data + + inputs = GenericGuardrailAPIInputs(texts=texts) + model = data.get("model") + if model: + inputs["model"] = model + + guardrailed_inputs = await guardrail_to_apply.apply_guardrail( + inputs=inputs, + request_data=data, + input_type="request", + logging_obj=litellm_logging_obj, + ) + + guardrailed_texts = guardrailed_inputs.get("texts", []) + if guardrailed_texts: + _write_back_texts(guardrailed_texts, holders) + + return data + + async def process_output_response( + self, + response: Any, + guardrail_to_apply: "CustomGuardrail", + litellm_logging_obj: Optional["LiteLLMLoggingObj"] = None, + user_api_key_dict: Optional[Any] = None, + request_data: Optional[dict] = None, + ) -> Any: + endpoint = (request_data or {}).get("endpoint", "") + if endpoint and not _is_converse_endpoint(endpoint): + return await _generic_passthrough_handler().process_output_response( + response=response, + guardrail_to_apply=guardrail_to_apply, + litellm_logging_obj=litellm_logging_obj, + user_api_key_dict=user_api_key_dict, + request_data=request_data, + ) + + if not isinstance(response, dict): + return response + + output_message = ( + response.get("output", {}).get("message", {}) + if isinstance(response.get("output"), dict) + else {} + ) + content_blocks = ( + output_message.get("content") if isinstance(output_message, dict) else None + ) + + if not isinstance(content_blocks, list): + return response + + texts, holders = _extract_converse_output_texts(content_blocks) + + if not texts: + return response + + effective_request_data = request_data or {} + if ( + "litellm_metadata" not in effective_request_data + and user_api_key_dict is not None + ): + user_metadata = self.transform_user_api_key_dict_to_metadata( + user_api_key_dict + ) + if user_metadata: + effective_request_data = { + **effective_request_data, + "litellm_metadata": user_metadata, + } + + inputs = GenericGuardrailAPIInputs(texts=texts) + model = effective_request_data.get("model") if effective_request_data else None + if model: + inputs["model"] = model + + guardrailed_inputs = await guardrail_to_apply.apply_guardrail( + inputs=inputs, + request_data=effective_request_data, + input_type="response", + logging_obj=litellm_logging_obj, + ) + + guardrailed_texts = guardrailed_inputs.get("texts", []) + if guardrailed_texts: + _write_back_texts(guardrailed_texts, holders) + + return response diff --git a/litellm/llms/bedrock_mantle/chat/transformation.py b/litellm/llms/bedrock_mantle/chat/transformation.py index 81a56030a5c..f688cea10f1 100644 --- a/litellm/llms/bedrock_mantle/chat/transformation.py +++ b/litellm/llms/bedrock_mantle/chat/transformation.py @@ -4,26 +4,38 @@ Amazon Bedrock Mantle - OpenAI-compatible inference engine in Amazon Bedrock. API docs: https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.html Base URL: https://bedrock-mantle.{region}.api.aws/v1 -Auth: AWS Bedrock API key as Bearer token (set via BEDROCK_MANTLE_API_KEY env var) - or region-aware key via BEDROCK_MANTLE_{REGION}_API_KEY. +Auth: Bearer token (litellm_params.api_key, BEDROCK_MANTLE_API_KEY, or the + standard AWS_BEARER_TOKEN_BEDROCK) when present; otherwise AWS SigV4 + (service "bedrock") over the standard credential chain. See + BedrockMantleAuthMixin in common_utils. """ -from typing import Iterator, AsyncIterator, Any, Optional, Tuple, Union +from typing import Iterator, AsyncIterator, Any, List, Optional, Tuple, Union import litellm from litellm._logging import verbose_logger +from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM +from litellm.llms.bedrock_mantle.common_utils import ( + BEDROCK_MANTLE_DEFAULT_REGION, + BedrockMantleAuthMixin, +) from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import AllMessageValues +from litellm.types.router import GenericLiteLLMParams +from ..common_utils import mantle_base_segment from ...openai_like.chat.transformation import OpenAILikeChatConfig -BEDROCK_MANTLE_DEFAULT_REGION = "us-east-1" - -class BedrockMantleChatConfig(OpenAILikeChatConfig): +class BedrockMantleChatConfig(BedrockMantleAuthMixin, OpenAILikeChatConfig): """ Transformation config for Amazon Bedrock Mantle OpenAI-compatible API. """ + def __init__(self, aws_signer: BaseAWSLLM | None = None): + super().__init__() + self._aws_signer = aws_signer or BaseAWSLLM() + @property def custom_llm_provider(self) -> Optional[str]: return "bedrock_mantle" @@ -33,21 +45,55 @@ class BedrockMantleChatConfig(OpenAILikeChatConfig): return super().get_config() def _get_openai_compatible_provider_info( - self, api_base: Optional[str], api_key: Optional[str] + self, + api_base: Optional[str], + api_key: Optional[str], + litellm_params: Optional[GenericLiteLLMParams] = None, + model: str | None = None, ) -> Tuple[Optional[str], Optional[str]]: region = ( - get_secret_str("BEDROCK_MANTLE_REGION") + (litellm_params.aws_region_name if litellm_params else None) + or get_secret_str("BEDROCK_MANTLE_REGION") + or get_secret_str("AWS_REGION_NAME") or get_secret_str("AWS_REGION") or BEDROCK_MANTLE_DEFAULT_REGION ) + BaseAWSLLM._validate_aws_region_name(region) + # The base path segment is data-driven per model (use_openai_responses_path + # flag): gemma-4-* and gpt-5.x are served on /openai/v1, everything else on + # /v1. An explicit api_base still wins over the derived default. api_base = ( api_base or get_secret_str("BEDROCK_MANTLE_API_BASE") - or f"https://bedrock-mantle.{region}.api.aws/v1" + or f"https://bedrock-mantle.{region}.api.aws/{mantle_base_segment(model, litellm.model_cost)}" ) - dynamic_api_key = api_key or get_secret_str("BEDROCK_MANTLE_API_KEY") + dynamic_api_key = self._resolve_bearer_token(api_key) return api_base, dynamic_api_key + 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: + headers = super().validate_environment( + headers=headers, + model=model, + messages=messages, + optional_params=optional_params, + litellm_params=litellm_params, + api_key=api_key, + api_base=api_base, + ) + project_id = litellm_params.get("aws_bedrock_project_id") + if project_id: + headers["OpenAI-Project"] = project_id + return headers + def get_supported_openai_params(self, model: str) -> list: base_params = super().get_supported_openai_params(model) try: diff --git a/litellm/llms/bedrock_mantle/common_utils.py b/litellm/llms/bedrock_mantle/common_utils.py new file mode 100644 index 00000000000..d517ab940ce --- /dev/null +++ b/litellm/llms/bedrock_mantle/common_utils.py @@ -0,0 +1,147 @@ +"""Shared auth, region resolution, and routing helpers for the Amazon Bedrock Mantle provider. + +Mantle authenticates with a Bearer token when one is available +(litellm_params.api_key, BEDROCK_MANTLE_API_KEY, or the standard +AWS_BEARER_TOKEN_BEDROCK); otherwise it falls back to AWS SigV4 (service +"bedrock") over the standard credential chain (IAM role / access key / profile / +web identity). The Chat Completions and Responses backends share this behaviour +through BedrockMantleAuthMixin so the two paths can never drift apart. + +The two routing helpers (mantle_supports_responses, mantle_base_segment) are +pure functions of (model, model_cost) so they can be unit-tested without patching +global state. +""" + +import re +from typing import Tuple + +from botocore.exceptions import ( + CredentialRetrievalError, + NoCredentialsError, + PartialCredentialsError, + ProfileNotFound, +) + +from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM +from litellm.secret_managers.main import get_secret_str + +BEDROCK_MANTLE_DEFAULT_REGION = "us-east-1" + +# Standard Mantle host: https://bedrock-mantle..api.aws (group 1 = region). +MANTLE_HOST_RE = re.compile( + r"^https?://bedrock-mantle\.([^/.]+)\.api\.aws", re.IGNORECASE +) + + +class BedrockMantleAuthMixin: + _aws_signer: BaseAWSLLM + + @staticmethod + def _resolve_bearer_token(api_key: str | None) -> str | None: + return ( + api_key + or get_secret_str("BEDROCK_MANTLE_API_KEY") + or get_secret_str("AWS_BEARER_TOKEN_BEDROCK") + ) + + @staticmethod + def _resolve_region(params: dict) -> str: + region = params.get("aws_region_name") + if region: + BaseAWSLLM._validate_aws_region_name(region) + return region + base = params.get("api_base") or get_secret_str("BEDROCK_MANTLE_API_BASE") + if base: + match = MANTLE_HOST_RE.match(base.rstrip("/")) + if match: + return match.group(1) + return ( + get_secret_str("BEDROCK_MANTLE_REGION") + or get_secret_str("AWS_REGION_NAME") + or get_secret_str("AWS_REGION") + or BEDROCK_MANTLE_DEFAULT_REGION + ) + + def sign_request( + self, + headers: dict, + optional_params: dict, + request_data: dict, + api_base: str, + api_key: str | None = None, + model: str | None = None, + stream: bool | None = None, + fake_stream: bool | None = None, + ) -> Tuple[dict, bytes | None]: + bearer = self._resolve_bearer_token(api_key) + if not bearer: + # Pin the credential-scope region to the region of the actual signing URL + # so the SigV4 scope and URL host can never disagree, even when a stale + # api_base and aws_region_name point at different regions. + host_match = MANTLE_HOST_RE.match(api_base.rstrip("/")) + optional_params = { + **optional_params, + "aws_region_name": ( + host_match.group(1) + if host_match + else self._resolve_region({**optional_params, "api_base": api_base}) + ), + } + headers = {k: v for k, v in headers.items() if k.lower() != "authorization"} + try: + return self._aws_signer._sign_request( + service_name="bedrock", + headers=headers, + optional_params=optional_params, + request_data=request_data, + api_base=api_base, + api_key=bearer, + model=model, + stream=stream, + fake_stream=fake_stream, + ) + except ( + NoCredentialsError, + PartialCredentialsError, + ProfileNotFound, + CredentialRetrievalError, + ) as e: + raise ValueError( + "Bedrock Mantle auth failed: no Bearer token and no usable AWS " + "credentials. Set BEDROCK_MANTLE_API_KEY (or AWS_BEARER_TOKEN_BEDROCK) " + "or pass api_key for Bearer auth, or provide AWS credentials " + "(IAM role / access key / profile / web identity) for SigV4." + ) from e + + +def mantle_supports_responses(model: str | None, model_cost: dict) -> bool: + """Whether a Bedrock Mantle model can serve the native Responses API. + + Purely data-driven from the model's price-map capability signal -- either + /v1/responses in supported_endpoints, or mode=responses -- both overridable + via register_model and proxy model_info, so onboarding a model is a JSON + change, never a code change. There is deliberately NO model-name match here: + capability is per-model, not per-family (openai.gpt-oss-120b supports + Responses while openai.gpt-oss-safeguard-120b does not, despite sharing the + gpt-oss substring), so a substring gate would be wrong. A model absent from + model_cost simply has no signal and returns False (chat-completions emulation). + """ + entry = model_cost.get(f"bedrock_mantle/{model}", {}) + if "/v1/responses" in (entry.get("supported_endpoints") or []): + return True + return entry.get("mode") == "responses" + + +def mantle_base_segment(model: str | None, model_cost: dict) -> str: + """Return the base path segment for a Bedrock Mantle model's OpenAI surface. + + Data-driven from the model's price-map use_openai_responses_path flag + (overridable via register_model / proxy model_info). Per the AWS model cards, + gpt-5.x and the google gemma-4-* family carry that flag and are served on the + /openai/v1 base (.../openai/v1/responses and .../openai/v1/chat/completions); + every other model including gpt-oss uses the standard /v1 base. The segment is + the base for the model's whole OpenAI-compatible surface, so both the chat and + responses configs derive from it -- there is no separate model-name rule. + """ + entry = model_cost.get(f"bedrock_mantle/{model}", {}) + return "openai/v1" if entry.get("use_openai_responses_path") is True else "v1" diff --git a/litellm/llms/bedrock_mantle/responses/transformation.py b/litellm/llms/bedrock_mantle/responses/transformation.py index b63fd0ecdb1..2e30f85fd0e 100644 --- a/litellm/llms/bedrock_mantle/responses/transformation.py +++ b/litellm/llms/bedrock_mantle/responses/transformation.py @@ -1,24 +1,34 @@ """ Amazon Bedrock Mantle - Responses API backend. -gpt-5.5 / gpt-5.4 on Mantle are exposed ONLY on the `/openai/v1/responses` -path (not the standard `/v1/responses`). Payloads and SSE follow the OpenAI +Mantle serves Responses on two upstream paths: gpt frontier models (gpt-5.5 / +gpt-5.4) on `/openai/v1/responses`, and everything else that supports Responses +(e.g. gpt-oss) on the standard `/v1/responses`. The gate picks the path per +model and injects it via `use_openai_path`. Payloads and SSE follow the OpenAI Responses spec, so this config inherits OpenAIResponsesAPIConfig and overrides -only the endpoint URL and Bearer authentication. +only the endpoint URL and authentication. -Auth: AWS Bedrock API key as Bearer token (BEDROCK_MANTLE_API_KEY or the -standard AWS_BEARER_TOKEN_BEDROCK), NOT SigV4. +Auth: Bearer token (BEDROCK_MANTLE_API_KEY or the standard +AWS_BEARER_TOKEN_BEDROCK, or litellm_params.api_key) when present; otherwise +AWS SigV4 (service name "bedrock") using the standard credential chain (IAM +role / access key / profile / web identity), signed via the shared +BaseAWSLLM._sign_request after the request body is finalized. """ -from typing import Optional +from typing import Any, Dict, List, Optional +from litellm._logging import verbose_logger +from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM +from litellm.llms.bedrock_mantle.common_utils import ( + MANTLE_HOST_RE, + BedrockMantleAuthMixin, +) 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.router import GenericLiteLLMParams from litellm.types.utils import LlmProviders -BEDROCK_MANTLE_DEFAULT_REGION = "us-east-1" - # Checked longest/most-specific first so a full endpoint URL collapses to host # in one pass and the appended path never doubles. _BASE_SUFFIXES_TO_STRIP = ( @@ -29,8 +39,22 @@ _BASE_SUFFIXES_TO_STRIP = ( "/v1", ) +# Per Bedrock Mantle Responses API validation errors. +_BEDROCK_MANTLE_SUPPORTED_RESPONSE_TOOL_TYPES = frozenset( + {"function", "mcp", "custom", "namespace", "tool_search"} +) + + +class BedrockMantleResponsesAPIConfig(BedrockMantleAuthMixin, OpenAIResponsesAPIConfig): + def __init__( + self, + aws_signer: Optional[BaseAWSLLM] = None, + use_openai_path: bool = True, + ): + super().__init__() + self._aws_signer = aws_signer or BaseAWSLLM() + self.use_openai_path = use_openai_path -class BedrockMantleResponsesAPIConfig(OpenAIResponsesAPIConfig): @property def custom_llm_provider(self) -> LlmProviders: return LlmProviders.BEDROCK_MANTLE @@ -40,11 +64,7 @@ class BedrockMantleResponsesAPIConfig(OpenAIResponsesAPIConfig): api_base: Optional[str], litellm_params: dict, ) -> str: - region = ( - get_secret_str("BEDROCK_MANTLE_REGION") - or get_secret_str("AWS_REGION") - or BEDROCK_MANTLE_DEFAULT_REGION - ) + region = self._resolve_region({**litellm_params, "api_base": api_base}) base = ( api_base or get_secret_str("BEDROCK_MANTLE_API_BASE") @@ -55,23 +75,23 @@ class BedrockMantleResponsesAPIConfig(OpenAIResponsesAPIConfig): if base.endswith(suffix): base = base[: -len(suffix)] break - return f"{base}/openai/v1/responses" + # For the standard Mantle host (including the default-region base that + # responses/main.py auto-injects into litellm_params.api_base), pin to the + # single resolved region so aws_region_name wins; preserve custom proxy hosts. + if MANTLE_HOST_RE.match(base): + base = f"https://bedrock-mantle.{region}.api.aws" + path = "/openai/v1/responses" if self.use_openai_path else "/v1/responses" + return f"{base}{path}" def validate_environment( self, headers: dict, model: str, litellm_params: Optional[GenericLiteLLMParams] ) -> dict: litellm_params = litellm_params or GenericLiteLLMParams() - api_key = ( - litellm_params.api_key - or get_secret_str("BEDROCK_MANTLE_API_KEY") - or get_secret_str("AWS_BEARER_TOKEN_BEDROCK") - ) - if not api_key: - raise ValueError( - "Bedrock Mantle API key is required. Set BEDROCK_MANTLE_API_KEY " - "(or AWS_BEARER_TOKEN_BEDROCK) or pass api_key." - ) - headers["Authorization"] = f"Bearer {api_key}" + bearer = self._resolve_bearer_token(litellm_params.api_key) + if bearer: + headers["Authorization"] = f"Bearer {bearer}" + if litellm_params.aws_bedrock_project_id: + headers["OpenAI-Project"] = litellm_params.aws_bedrock_project_id return headers def supports_native_file_search(self) -> bool: @@ -79,3 +99,53 @@ class BedrockMantleResponsesAPIConfig(OpenAIResponsesAPIConfig): def supports_native_websocket(self) -> bool: return False + + @staticmethod + def _filter_unsupported_tools(tools: List[Any]) -> List[Any]: + """Keep only tool types Mantle's Responses API accepts.""" + kept: List[Any] = [] + dropped_types: List[str] = [] + for tool in tools: + if not isinstance(tool, dict): + kept.append(tool) + continue + tool_type = tool.get("type") + if tool_type in _BEDROCK_MANTLE_SUPPORTED_RESPONSE_TOOL_TYPES: + kept.append(tool) + else: + dropped_types.append(str(tool_type)) + + if dropped_types: + verbose_logger.warning( + "Bedrock Mantle Responses API: dropping unsupported tool type(s) " + "%s (supported: %s).", + sorted(set(dropped_types)), + sorted(_BEDROCK_MANTLE_SUPPORTED_RESPONSE_TOOL_TYPES), + ) + + return kept + + def map_openai_params( + self, + response_api_optional_params: ResponsesAPIOptionalRequestParams, + model: str, + drop_params: bool, + ) -> Dict: + params = super().map_openai_params( + response_api_optional_params=response_api_optional_params, + model=model, + drop_params=drop_params, + ) + + tools = params.get("tools") + if not tools: + return params + + tools_list = tools if isinstance(tools, list) else [tools] + filtered = self._filter_unsupported_tools(tools_list) + if filtered: + params["tools"] = filtered + else: + params.pop("tools", None) + + return params diff --git a/litellm/llms/bytez/chat/transformation.py b/litellm/llms/bytez/chat/transformation.py index 5b08670f9f2..7d9afe01fa6 100644 --- a/litellm/llms/bytez/chat/transformation.py +++ b/litellm/llms/bytez/chat/transformation.py @@ -191,7 +191,7 @@ class BytezChatConfig(BaseConfig): api_key: Optional[str] = None, json_mode: Optional[bool] = None, ) -> ModelResponse: - json = raw_response.json() # noqa: F811 + json = raw_response.json() error = json.get("error") diff --git a/litellm/llms/custom_httpx/aiohttp_transport.py b/litellm/llms/custom_httpx/aiohttp_transport.py index 62f707b3622..b97a59a93a6 100644 --- a/litellm/llms/custom_httpx/aiohttp_transport.py +++ b/litellm/llms/custom_httpx/aiohttp_transport.py @@ -116,6 +116,16 @@ class AiohttpResponseStream(httpx.AsyncByteStream): # For other exceptions, use the normal mapping with map_aiohttp_exceptions(): raise + finally: + # Release the aiohttp connection when iteration ends for any + # reason (read timeout, cancellation from a client disconnect, + # GeneratorExit). Without this, abnormally terminated streams + # permanently hold a slot in the TCPConnector pool; once the + # pool is exhausted every request to that host times out (408) + # until the proxy is restarted, even after the backend recovers. + # On a fully-read response the connection was already released + # at EOF and close() is a no-op. + self._aiohttp_response.close() async def aclose(self) -> None: with map_aiohttp_exceptions(): diff --git a/litellm/llms/custom_httpx/llm_http_handler.py b/litellm/llms/custom_httpx/llm_http_handler.py index 31c772510ba..8ac5b47c6e7 100644 --- a/litellm/llms/custom_httpx/llm_http_handler.py +++ b/litellm/llms/custom_httpx/llm_http_handler.py @@ -33,7 +33,10 @@ from litellm.llms.base_llm.anthropic_messages.transformation import ( from litellm.llms.base_llm.audio_transcription.transformation import ( BaseAudioTranscriptionConfig, ) -from litellm.llms.base_llm.base_model_iterator import MockResponseIterator +from litellm.llms.base_llm.base_model_iterator import ( + BaseModelResponseIterator, + MockResponseIterator, +) from litellm.llms.base_llm.batches.transformation import BaseBatchesConfig from litellm.llms.base_llm.chat.transformation import BaseConfig from litellm.llms.base_llm.containers.transformation import BaseContainerConfig @@ -125,6 +128,7 @@ from litellm.types.vector_stores import ( VectorStoreSearchOptionalRequestParams, VectorStoreSearchResponse, ) +from litellm.types.realtime import RealtimeQueryParams from litellm.types.videos.main import VideoObject from litellm.utils import ( CustomStreamWrapper, @@ -813,6 +817,8 @@ class BaseLLMHTTPHandler: completion_stream = provider_config.get_model_response_iterator( streaming_response=response.aiter_lines(), sync_stream=False ) + if isinstance(completion_stream, BaseModelResponseIterator): + completion_stream.http_response = response # LOGGING logging_obj.post_call( input=messages, @@ -2305,6 +2311,7 @@ class BaseLLMHTTPHandler: if extra_body: data.update(extra_body) + stream = bool(stream or data.get("stream")) # Preserve the OpenAI-style request context (not sent to the provider) for streaming # hooks/metadata; the streaming iterator now consumes this to run deployment hooks @@ -2318,6 +2325,31 @@ class BaseLLMHTTPHandler: # but never included in the outbound provider payload. request_context["litellm_params"] = dict(litellm_params) + is_stream_request = bool(stream) + if is_stream_request and fake_stream is True: + stream, data = self._prepare_fake_stream_request( + stream=stream, + data=data, + fake_stream=fake_stream, + ) + + # Sign after the body is final (post-transform/normalize/extra_body and post + # fake-stream prep) so signed bytes match what we send. No-op for providers + # that inherit the default sign_request. + headers, signed_body = responses_api_provider_config.sign_request( + headers=headers, + optional_params=dict(litellm_params), + request_data=data, + api_base=api_base, + api_key=litellm_params.api_key, + model=model, + stream=stream, + fake_stream=fake_stream, + ) + body_kwargs: Dict[str, Any] = ( + {"data": signed_body} if signed_body is not None else {"json": data} + ) + ## LOGGING logging_obj.pre_call( input=input, @@ -2330,22 +2362,14 @@ class BaseLLMHTTPHandler: ) try: - if stream: - # For streaming, use stream=True in the request - if fake_stream is True: - stream, data = self._prepare_fake_stream_request( - stream=stream, - data=data, - fake_stream=fake_stream, - ) - + if is_stream_request: response = sync_httpx_client.post( url=api_base, headers=headers, - json=data, timeout=timeout or float(response_api_optional_request_params.get("timeout", 0)), stream=stream, + **body_kwargs, ) if fake_stream is True: return MockResponsesAPIStreamingIterator( @@ -2370,13 +2394,12 @@ class BaseLLMHTTPHandler: call_type=CallTypes.responses.value, ) else: - # For non-streaming requests response = sync_httpx_client.post( url=api_base, headers=headers, - json=data, timeout=timeout or float(response_api_optional_request_params.get("timeout", 0)), + **body_kwargs, ) except Exception as e: raise self._handle_error( @@ -2451,6 +2474,7 @@ class BaseLLMHTTPHandler: if extra_body: data.update(extra_body) + stream = bool(stream or data.get("stream")) # Preserve the OpenAI-style request context (not sent to the provider) for streaming # hooks/metadata; the streaming iterator now consumes this to run deployment hooks @@ -2464,6 +2488,28 @@ class BaseLLMHTTPHandler: # but never included in the outbound provider payload. request_context["litellm_params"] = dict(litellm_params) + is_stream_request = bool(stream) + if is_stream_request and fake_stream is True: + stream, data = self._prepare_fake_stream_request( + stream=stream, + data=data, + fake_stream=fake_stream, + ) + + headers, signed_body = responses_api_provider_config.sign_request( + headers=headers, + optional_params=dict(litellm_params), + request_data=data, + api_base=api_base, + api_key=litellm_params.api_key, + model=model, + stream=stream, + fake_stream=fake_stream, + ) + body_kwargs: Dict[str, Any] = ( + {"data": signed_body} if signed_body is not None else {"json": data} + ) + ## LOGGING logging_obj.pre_call( input=input, @@ -2476,22 +2522,14 @@ class BaseLLMHTTPHandler: ) try: - if stream: - # For streaming, we need to use stream=True in the request - if fake_stream is True: - stream, data = self._prepare_fake_stream_request( - stream=stream, - data=data, - fake_stream=fake_stream, - ) - + if is_stream_request: response = await async_httpx_client.post( url=api_base, headers=headers, - json=data, timeout=timeout or float(response_api_optional_request_params.get("timeout", 0)), stream=stream, + **body_kwargs, ) if fake_stream is True: @@ -2518,13 +2556,12 @@ class BaseLLMHTTPHandler: call_type=CallTypes.responses.value, ) else: - # For non-streaming, proceed as before response = await async_httpx_client.post( url=api_base, headers=headers, - json=data, timeout=timeout or float(response_api_optional_request_params.get("timeout", 0)), + **body_kwargs, ) except Exception as e: @@ -4005,6 +4042,18 @@ class BaseLLMHTTPHandler: ) data = BaseResponsesAPIConfig.normalize_responses_api_request_dict(data) + headers, signed_body = responses_api_provider_config.sign_request( + headers=headers, + optional_params=dict(litellm_params), + request_data=data, + api_base=url, + api_key=litellm_params.api_key, + model=model, + ) + body_kwargs: Dict[str, Any] = ( + {"data": signed_body} if signed_body is not None else {"json": data} + ) + ## LOGGING logging_obj.pre_call( input=input, @@ -4018,7 +4067,7 @@ class BaseLLMHTTPHandler: try: response = sync_httpx_client.post( - url=url, headers=headers, json=data, timeout=timeout + url=url, headers=headers, timeout=timeout, **body_kwargs ) except Exception as e: @@ -4088,6 +4137,18 @@ class BaseLLMHTTPHandler: ) data = BaseResponsesAPIConfig.normalize_responses_api_request_dict(data) + headers, signed_body = responses_api_provider_config.sign_request( + headers=headers, + optional_params=dict(litellm_params), + request_data=data, + api_base=url, + api_key=litellm_params.api_key, + model=model, + ) + body_kwargs: Dict[str, Any] = ( + {"data": signed_body} if signed_body is not None else {"json": data} + ) + ## LOGGING logging_obj.pre_call( input=input, @@ -4101,7 +4162,7 @@ class BaseLLMHTTPHandler: try: response = await async_httpx_client.post( - url=url, headers=headers, json=data, timeout=timeout + url=url, headers=headers, timeout=timeout, **body_kwargs ) except Exception as e: @@ -5262,6 +5323,23 @@ class BaseLLMHTTPHandler: headers=error_headers, ) + @staticmethod + def _append_query_params( + url: str, query_params: Optional[RealtimeQueryParams] + ) -> str: + """Append query_params to url, skipping keys already present in the URL.""" + if not query_params: + return url + from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse + + parsed = urlparse(url) + existing = dict(parse_qsl(parsed.query)) + extras = {k: v for k, v in query_params.items() if k not in existing} + if not extras: + return url + new_query = parsed.query + ("&" if parsed.query else "") + urlencode(extras) + return urlunparse(parsed._replace(query=new_query)) + async def async_realtime( self, model: str, @@ -5275,11 +5353,14 @@ class BaseLLMHTTPHandler: timeout: Optional[float] = None, user_api_key_dict: Optional[Any] = None, litellm_metadata: Optional[Dict[str, Any]] = None, + query_params: Optional[RealtimeQueryParams] = None, ): import websockets from websockets.asyncio.client import ClientConnection - url = provider_config.get_complete_url(api_base, model, api_key) + url = self._append_query_params( + provider_config.get_complete_url(api_base, model, api_key), query_params + ) headers = provider_config.validate_environment( headers=headers, model=model, @@ -5320,6 +5401,11 @@ class BaseLLMHTTPHandler: model, user_api_key_dict=user_api_key_dict, request_data=_request_data, + force_transcription_model=( + model + if (query_params or {}).get("intent") == "transcription" + else None + ), ) if _session_config: realtime_streaming.session_configuration_request = _session_config @@ -5384,6 +5470,69 @@ class BaseLLMHTTPHandler: """ Forward POST /v1/realtime/client_secrets to upstream provider. + Uses provider_config (BaseRealtimeHTTPConfig) for URL construction and + header auth when available; falls back to the legacy OpenAI-style defaults. + """ + return await self._async_realtime_session_post( + endpoint="client_secrets", + api_base=api_base, + api_key=api_key, + request_data=request_data, + logging_obj=logging_obj, + timeout=timeout, + provider_config=provider_config, + model=model, + extra_headers=extra_headers, + client=client, + api_version=api_version, + ) + + async def async_realtime_transcription_session_handler( + self, + api_base: str, + api_key: str, + request_data: Dict[str, Any], + logging_obj: LiteLLMLoggingObj, + timeout: Union[float, httpx.Timeout], + provider_config: Optional[Any] = None, + model: Optional[str] = None, + extra_headers: Optional[Dict[str, Any]] = None, + client: Optional[Union[HTTPHandler, AsyncHTTPHandler]] = None, + api_version: Optional[str] = None, + ) -> httpx.Response: + """Forward POST /v1/realtime/transcription_sessions to upstream provider.""" + return await self._async_realtime_session_post( + endpoint="transcription_sessions", + api_base=api_base, + api_key=api_key, + request_data=request_data, + logging_obj=logging_obj, + timeout=timeout, + provider_config=provider_config, + model=model, + extra_headers=extra_headers, + client=client, + api_version=api_version, + ) + + async def _async_realtime_session_post( + self, + endpoint: Literal["client_secrets", "transcription_sessions"], + api_base: str, + api_key: str, + request_data: Dict[str, Any], + logging_obj: LiteLLMLoggingObj, + timeout: Union[float, httpx.Timeout], + provider_config: Optional[Any] = None, + model: Optional[str] = None, + extra_headers: Optional[Dict[str, Any]] = None, + client: Optional[Union[HTTPHandler, AsyncHTTPHandler]] = None, + api_version: Optional[str] = None, + ) -> httpx.Response: + """ + Shared POST flow for the realtime HTTP session endpoints + (client_secrets and transcription_sessions). + Uses provider_config (BaseRealtimeHTTPConfig) for URL construction and header auth when available; falls back to the legacy OpenAI-style defaults. """ @@ -5395,14 +5544,19 @@ class BaseLLMHTTPHandler: async_httpx_client = client if provider_config is not None: - url = provider_config.get_complete_url( - api_base=api_base, model=model or "", api_version=api_version - ) + if endpoint == "transcription_sessions": + url = provider_config.get_transcription_session_url( + api_base=api_base, model=model or "", api_version=api_version + ) + else: + url = provider_config.get_complete_url( + api_base=api_base, model=model or "", api_version=api_version + ) headers: Dict[str, Any] = provider_config.validate_environment( headers={}, model=model or "", api_key=api_key ) else: - url = f"{api_base.rstrip('/')}/v1/realtime/client_secrets" + url = f"{api_base.rstrip('/')}/v1/realtime/{endpoint}" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", @@ -5575,7 +5729,11 @@ class BaseLLMHTTPHandler: import websockets from websockets.asyncio.client import ClientConnection - litellm_params = GenericLiteLLMParams() + litellm_params = GenericLiteLLMParams( + api_base=api_base, + api_key=api_key, + **kwargs, + ) headers = responses_api_provider_config.validate_environment( headers={}, model=model, @@ -5584,21 +5742,21 @@ class BaseLLMHTTPHandler: if api_key: headers["Authorization"] = f"Bearer {api_key}" - http_url = responses_api_provider_config.get_complete_url( + ws_url = responses_api_provider_config.get_websocket_url( api_base=api_base, - litellm_params={}, + litellm_params=dict(litellm_params), ) - ws_url = http_url.replace("https://", "wss://").replace("http://", "ws://") - # OpenAI's WebSocket responses endpoint requires ?model= in the URL, - # matching the Realtime API convention (wss://.../v1/realtime?model=...). - # Use urllib.parse so existing query params (e.g. api-version) are preserved. - _parsed = urlparse(ws_url) - _qs = parse_qs(_parsed.query) - if "model" not in _qs: - _qs["model"] = [model] - ws_url = urlunparse( - _parsed._replace(query=urlencode({k: v[0] for k, v in _qs.items()})) - ) + # Some providers (e.g. OpenAI) require ?model= in the WebSocket URL. + # Providers that send the model in the request body (e.g. Azure) set + # model_in_websocket_url() to False to suppress this append. + if responses_api_provider_config.model_in_websocket_url(): + _parsed = urlparse(ws_url) + _qs = parse_qs(_parsed.query) + if "model" not in _qs: + _qs["model"] = [model] + ws_url = urlunparse( + _parsed._replace(query=urlencode({k: v[0] for k, v in _qs.items()})) + ) try: ssl_context = get_shared_realtime_ssl_context() @@ -5626,6 +5784,41 @@ class BaseLLMHTTPHandler: _request_data: Dict[str, Any] = {} if litellm_metadata: _request_data["litellm_metadata"] = litellm_metadata + + _ws_guardrail_callbacks: list = [] + _ws_output_guardrail_callbacks: list = [] + try: + import litellm as _litellm + + # Use duck-typing so any guardrail that exposes the PII + # masking interface works, not just _OPTIONAL_PresidioPIIMasking. + # This avoids a layering violation (SDK importing from proxy). + _ws_guardrail_callbacks = [ + cb + for cb in _litellm.callbacks + if callable(getattr(cb, "check_pii", None)) + and callable( + getattr(cb, "get_presidio_settings_from_request_data", None) + ) + and callable(getattr(cb, "_unmask_pii_text", None)) + and getattr(cb, "output_parse_pii", False) + ] + _ws_output_guardrail_callbacks = [ + cb + for cb in _litellm.callbacks + if callable(getattr(cb, "check_pii", None)) + and callable( + getattr(cb, "get_presidio_settings_from_request_data", None) + ) + and getattr(cb, "apply_to_output", False) + ] + except Exception as _guardrail_exc: + verbose_logger.warning( + "Responses WebSocket: failed to collect guardrail " + "callbacks — PII masking will be skipped. Error: %s", + _guardrail_exc, + ) + streaming = ResponsesWebSocketStreaming( websocket=websocket, backend_ws=cast(ClientConnection, backend_ws), @@ -5633,6 +5826,9 @@ class BaseLLMHTTPHandler: user_api_key_dict=user_api_key_dict, request_data=_request_data, first_message=first_message, + guardrail_callbacks=_ws_guardrail_callbacks, + output_guardrail_callbacks=_ws_output_guardrail_callbacks, + authorized_model=model, ) await streaming.bidirectional_forward() diff --git a/litellm/llms/databricks/streaming_utils.py b/litellm/llms/databricks/streaming_utils.py index eebe3182881..7a7330227d6 100644 --- a/litellm/llms/databricks/streaming_utils.py +++ b/litellm/llms/databricks/streaming_utils.py @@ -25,6 +25,28 @@ class ModelResponseIterator: finish_reason = "" usage: Optional[ChatCompletionUsageBlock] = None + # Usage-only final chunk (OpenAI ``stream_options.include_usage``) + # arrives with an empty ``choices`` list — return usage without + # indexing ``choices[0]``. + if len(processed_chunk.choices) == 0: + final_usage = getattr(processed_chunk, "usage", None) + return GenericStreamingChunk( + text="", + tool_use=None, + is_finished=False, + finish_reason="", + usage=( + ChatCompletionUsageBlock( + prompt_tokens=final_usage.prompt_tokens or 0, + completion_tokens=final_usage.completion_tokens or 0, + total_tokens=final_usage.total_tokens or 0, + ) + if final_usage is not None + else None + ), + index=0, + ) + if processed_chunk.choices[0].delta.content is not None: # type: ignore text = processed_chunk.choices[0].delta.content # type: ignore diff --git a/litellm/llms/deepseek/messages/transformation.py b/litellm/llms/deepseek/messages/transformation.py index ad60478960e..63b736ffd1d 100644 --- a/litellm/llms/deepseek/messages/transformation.py +++ b/litellm/llms/deepseek/messages/transformation.py @@ -26,6 +26,9 @@ class DeepSeekAnthropicMessagesConfig(AnthropicMessagesConfig): def custom_llm_provider(self) -> Optional[str]: return "deepseek" + def should_strip_billing_metadata(self) -> bool: + return True + @staticmethod def get_api_key(api_key: Optional[str] = None) -> Optional[str]: return api_key or get_secret_str("DEEPSEEK_API_KEY") or litellm.api_key diff --git a/litellm/llms/e2b/__init__.py b/litellm/llms/e2b/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/litellm/llms/e2b/sandbox/__init__.py b/litellm/llms/e2b/sandbox/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/litellm/llms/e2b/sandbox/transformation.py b/litellm/llms/e2b/sandbox/transformation.py new file mode 100644 index 00000000000..1ce28bc55fb --- /dev/null +++ b/litellm/llms/e2b/sandbox/transformation.py @@ -0,0 +1,219 @@ +""" +e2b sandbox provider. + +Talks to e2b's REST API directly over httpx (no e2b SDK dependency): + - create: POST {api_base}/sandboxes + - run: POST https://{JUPYTER_PORT}-{sandboxID}.{domain}/execute (NDJSON stream) + - delete: DELETE {api_base}/sandboxes/{sandboxID} +""" + +import json +from typing import Union, cast + +import httpx + +from litellm.llms.base_llm.sandbox.transformation import ( + BaseSandboxConfig, + CodeExecutionResult, + ContainerHandle, +) +from litellm.llms.custom_httpx.http_handler import ( + AsyncHTTPHandler, + get_async_httpx_client, +) +from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.custom_http import httpxSpecialProvider + +E2B_API_BASE = "https://api.e2b.app" +E2B_DEFAULT_TEMPLATE = "code-interpreter-v1" +E2B_DEFAULT_DOMAIN = "e2b.app" +JUPYTER_PORT = 49999 +DEFAULT_SANDBOX_TIMEOUT = 300 +MAX_OUTPUT_BYTES = 10 * 1024 * 1024 + + +class E2BSandboxConfig(BaseSandboxConfig): + def _http(self, client: AsyncHTTPHandler | None) -> AsyncHTTPHandler: + if client is not None: + return client + return get_async_httpx_client(llm_provider=httpxSpecialProvider.Sandbox) + + def validate_environment(self, api_key: str | None = None, **kwargs) -> str: + key = api_key or get_secret_str("E2B_API_KEY") + if not key: + raise ValueError("E2B API key not set. Set E2B_API_KEY or pass api_key=...") + return key + + async def acreate_sandbox( + self, + *, + template: str | None = None, + timeout: int | None = None, + allow_internet_access: bool = True, + api_key: str | None = None, + metadata: dict | None = None, + client: AsyncHTTPHandler | None = None, + **kwargs, + ) -> ContainerHandle: + key = self.validate_environment(api_key=api_key) + body = { + "templateID": template or E2B_DEFAULT_TEMPLATE, + "timeout": timeout if timeout is not None else DEFAULT_SANDBOX_TIMEOUT, + "secure": True, + "allow_internet_access": allow_internet_access, + } + if metadata: + body["metadata"] = metadata + + response = cast( + httpx.Response, + await self._http(client).post( + url=f"{E2B_API_BASE}/sandboxes", + headers={"X-API-Key": key, "Content-Type": "application/json"}, + json=body, + ), + ) + data = response.json() + + handle = ContainerHandle( + id=data["sandboxID"], + provider="e2b", + domain=data.get("domain") or E2B_DEFAULT_DOMAIN, + ) + handle._hidden_params = { + "envd_access_token": data.get("envdAccessToken"), + "traffic_access_token": data.get("trafficAccessToken"), + "api_key": key, + } + return handle + + async def arun_code( + self, + *, + container: Union[ContainerHandle, str], + code: str, + api_key: str | None = None, + env_vars: dict | None = None, + client: AsyncHTTPHandler | None = None, + **kwargs, + ) -> CodeExecutionResult: + handle = self._as_handle(container) + + token = handle._hidden_params.get("envd_access_token") + if not token: + raise ValueError( + "Cannot run code from a sandbox id alone. e2b secure sandboxes " + "require the access token returned by acreate_sandbox; pass the " + "ContainerHandle it returned instead of a bare sandbox id." + ) + + headers = {"Content-Type": "application/json", "X-Access-Token": token} + traffic_token = handle._hidden_params.get("traffic_access_token") + if traffic_token: + headers["E2B-Traffic-Access-Token"] = traffic_token + + url = f"https://{JUPYTER_PORT}-{handle.id}.{handle.domain}/execute" + response = cast( + httpx.Response, + await self._http(client).post( + url=url, + headers=headers, + json={"code": code, "context_id": None, "env_vars": env_vars}, + stream=True, + ), + ) + lines = await self._read_capped_lines(response) + return self._parse_lines(lines) + + async def adelete_sandbox( + self, + *, + container: Union[ContainerHandle, str], + api_key: str | None = None, + client: AsyncHTTPHandler | None = None, + **kwargs, + ) -> bool: + handle = self._as_handle(container) + key = ( + api_key + or handle._hidden_params.get("api_key") + or self.validate_environment() + ) + try: + response = cast( + httpx.Response, + await self._http(client).delete( + url=f"{E2B_API_BASE}/sandboxes/{handle.id}", + headers={"X-API-Key": key}, + ), + ) + except httpx.HTTPStatusError as e: + if e.response.status_code == 404: + return False + raise + return 200 <= response.status_code < 300 + + @staticmethod + def _as_handle(container: Union[ContainerHandle, str]) -> ContainerHandle: + if isinstance(container, ContainerHandle): + return container + handle = ContainerHandle( + id=str(container), provider="e2b", domain=E2B_DEFAULT_DOMAIN + ) + handle._hidden_params = {} + return handle + + @staticmethod + async def _read_capped_lines(response: httpx.Response) -> list[str]: + lines: list[str] = [] + total = 0 + async for line in response.aiter_lines(): + total += len(line.encode("utf-8")) + if total > MAX_OUTPUT_BYTES: + raise ValueError( + f"Sandbox output exceeded {MAX_OUTPUT_BYTES} bytes; aborting to " + "avoid unbounded memory use." + ) + lines.append(line) + return lines + + @staticmethod + def _parse_lines(lines: list[str]) -> CodeExecutionResult: + def _try_parse(stripped: str): + try: + return json.loads(stripped) + except json.JSONDecodeError: + return None + + messages = tuple( + parsed + for stripped in (line.strip() for line in lines) + if stripped + for parsed in (_try_parse(stripped),) + if parsed is not None + ) + + def of_type(message_type: str): + return (m for m in messages if m.get("type") == message_type) + + error = next( + ( + {key: m.get(key) for key in ("name", "value", "traceback")} + for m in of_type("error") + ), + None, + ) + execution_count = next( + (m.get("execution_count") for m in of_type("number_of_executions")), + None, + ) + + return CodeExecutionResult( + stdout="".join(m.get("text", "") for m in of_type("stdout")), + stderr="".join(m.get("text", "") for m in of_type("stderr")), + results=[ + {k: v for k, v in m.items() if k != "type"} for m in of_type("result") + ], + error=error, + execution_count=execution_count, + ) diff --git a/litellm/llms/fastcrw/__init__.py b/litellm/llms/fastcrw/__init__.py new file mode 100644 index 00000000000..d65ed8d3fa1 --- /dev/null +++ b/litellm/llms/fastcrw/__init__.py @@ -0,0 +1,7 @@ +""" +fastCRW API integration module. +""" + +from litellm.llms.fastcrw.search.transformation import FastCRWSearchConfig + +__all__ = ["FastCRWSearchConfig"] diff --git a/litellm/llms/fastcrw/search/__init__.py b/litellm/llms/fastcrw/search/__init__.py new file mode 100644 index 00000000000..4f8023b2db4 --- /dev/null +++ b/litellm/llms/fastcrw/search/__init__.py @@ -0,0 +1,7 @@ +""" +fastCRW Search API module. +""" + +from litellm.llms.fastcrw.search.transformation import FastCRWSearchConfig + +__all__ = ["FastCRWSearchConfig"] diff --git a/litellm/llms/fastcrw/search/transformation.py b/litellm/llms/fastcrw/search/transformation.py new file mode 100644 index 00000000000..ce702266e7b --- /dev/null +++ b/litellm/llms/fastcrw/search/transformation.py @@ -0,0 +1,182 @@ +""" +Calls fastCRW's /v1/search endpoint to search the web. + +fastCRW is a Firecrawl-compatible web data engine (single Rust binary; self-host +or cloud). The search response uses the Firecrawl-compatible envelope +{ "success": true, "data": [ { "title", "url", "description", "markdown"? } ] }. + +fastCRW API Reference: https://fastcrw.com/docs/rest-api +""" + +from typing import Optional, TypedDict, Union + +import httpx + +from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj +from litellm.llms.base_llm.search.transformation import ( + BaseSearchConfig, + SearchResponse, + SearchResult, +) +from litellm.secret_managers.main import get_secret_str + + +class _FastCRWSearchRequestRequired(TypedDict): + """Required fields for fastCRW Search API request.""" + + query: str # Required - search query + + +class FastCRWSearchRequest(_FastCRWSearchRequestRequired, total=False): + """ + fastCRW Search API request format. + Based on: https://fastcrw.com/docs/rest-api + """ + + limit: int # Optional - maximum number of results to return + sources: list[ + str + ] # Optional - sources to search ('web', 'images'), default ['web'] + scrapeOptions: dict # Optional - options for scraping search results + + +class FastCRWSearchConfig(BaseSearchConfig): + FASTCRW_API_BASE = "https://fastcrw.com/api/v1" + + @staticmethod + def ui_friendly_name() -> str: + return "fastCRW" + + def validate_environment( + self, + headers: dict, + api_key: Optional[str] = None, + api_base: Optional[str] = None, + **kwargs, + ) -> dict: + """ + Validate environment and return headers. + """ + api_key = api_key or get_secret_str("CRW_API_KEY") + if not api_key: + raise ValueError( + "CRW_API_KEY is not set. Set `CRW_API_KEY` environment variable." + ) + headers["Authorization"] = f"Bearer {api_key}" + headers["Content-Type"] = "application/json" + return headers + + def get_complete_url( + self, + api_base: Optional[str], + optional_params: dict, + data: Optional[Union[dict, list[dict]]] = None, + **kwargs, + ) -> str: + """ + Get complete URL for Search endpoint. + """ + api_base = api_base or get_secret_str("CRW_API_BASE") or self.FASTCRW_API_BASE + + # Append "/search" to the api base if it's not already there + if not api_base.endswith("/search"): + api_base = f"{api_base}/search" + + return api_base + + def transform_search_request( + self, + query: Union[str, list[str]], + optional_params: dict, + **kwargs, + ) -> dict: + """ + Transform Search request to fastCRW API format. + + Transforms Perplexity unified spec parameters: + - query -> query (same) + - max_results -> limit + + All other fastCRW-specific parameters are passed through as-is. + + Args: + query: Search query (string or list of strings). fastCRW only supports single string queries. + optional_params: Optional parameters for the request + + Returns: + Dict with typed request data following FastCRWSearchRequest spec + """ + if isinstance(query, list): + # fastCRW only supports single string queries, join with spaces + query = " ".join(query) + + request_data: FastCRWSearchRequest = { + "query": query, + } + + # Transform Perplexity unified spec parameters to fastCRW format + if "max_results" in optional_params: + request_data["limit"] = optional_params["max_results"] + + # Convert to dict before dynamic key assignments + result_data = dict(request_data) + + # pass through all other parameters as-is + for param, value in optional_params.items(): + if ( + param not in self.get_supported_perplexity_optional_params() + and param not in result_data + ): + result_data[param] = value + + # By default, request markdown content if not explicitly specified + # fastCRW doesn't return content unless explicitly requested via scrapeOptions + if "scrapeOptions" not in result_data: + result_data["scrapeOptions"] = { + "formats": ["markdown"], + "onlyMainContent": True, + } + + return result_data + + def transform_search_response( + self, + raw_response: httpx.Response, + logging_obj: LiteLLMLoggingObj, + **kwargs, + ) -> SearchResponse: + """ + Transform fastCRW API response to LiteLLM unified SearchResponse format. + + fastCRW (Firecrawl-compatible) returns: + {"success": true, "data": [{"url": "...", "title": "...", "description": "...", "markdown"?: "..."}, ...]} + + Args: + raw_response: Raw httpx response from fastCRW API + logging_obj: Logging object for tracking + + Returns: + SearchResponse with standardized format + """ + response_json = raw_response.json() + + results = [] + + data = response_json.get("data", []) + + if isinstance(data, list): + for result in data: + snippet = result.get("markdown") or result.get("description", "") + search_result = SearchResult( + title=result.get("title", ""), + url=result.get("url", ""), + snippet=snippet, + date=None, + last_updated=None, + ) + results.append(search_result) + + return SearchResponse( + results=results, + object="search", + ) diff --git a/litellm/llms/fireworks_ai/chat/transformation.py b/litellm/llms/fireworks_ai/chat/transformation.py index cca3b3da37a..341c2fc7350 100644 --- a/litellm/llms/fireworks_ai/chat/transformation.py +++ b/litellm/llms/fireworks_ai/chat/transformation.py @@ -392,7 +392,10 @@ class FireworksAIConfig(OpenAIGPTConfig): headers: dict, ) -> dict: if not model.startswith("accounts/") and "#" not in model: - model = f"accounts/fireworks/models/{model}" + if model.endswith("-fast"): + model = f"accounts/fireworks/routers/{model}" + else: + model = f"accounts/fireworks/models/{model}" messages = self._transform_messages_helper( messages=messages, model=model, litellm_params=litellm_params ) diff --git a/litellm/llms/gemini/common_utils.py b/litellm/llms/gemini/common_utils.py index 42a807983b9..4cca2e2b850 100644 --- a/litellm/llms/gemini/common_utils.py +++ b/litellm/llms/gemini/common_utils.py @@ -174,12 +174,110 @@ def map_openai_image_params_to_gemini( mapped_params["imageConfig"] = image_config_param for key, value in filtered_params.items(): - if key not in ("n", "size", "imageConfig") and key not in optional_params: + if ( + key not in ("n", "size", "imageConfig", "tools", "web_search_options") + and key not in optional_params + ): mapped_params[key] = value return mapped_params +def _dedupe_gemini_search_tools(tools: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import ( + VertexGeminiConfig, + ) + + search_tool_keys = VertexGeminiConfig._search_tool_keys() + seen_search_keys: set[str] = set() + deduped_tools: List[Dict[str, Any]] = [] + + for tool in tools: + if not isinstance(tool, dict): + deduped_tools.append(tool) + continue + + search_key = next((key for key in search_tool_keys if key in tool), None) + if search_key is None: + deduped_tools.append(tool) + continue + + if search_key in seen_search_keys: + continue + + seen_search_keys.add(search_key) + deduped_tools.append(tool) + + return deduped_tools + + +def _has_gemini_search_tool(tools: List[Any]) -> bool: + from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import ( + VertexGeminiConfig, + ) + + search_tool_keys = VertexGeminiConfig._search_tool_keys() + return any( + isinstance(tool, dict) and any(key in tool for key in search_tool_keys) + for tool in tools + ) + + +def map_gemini_image_tools_params( + non_default_params: Dict[str, Any], + mapped_params: Dict[str, Any], +) -> Dict[str, Any]: + from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import ( + VertexGeminiConfig, + ) + + gemini_config = VertexGeminiConfig() + result = dict(mapped_params) + result.pop("web_search_options", None) + + tools_value = non_default_params.get("tools") + if isinstance(tools_value, list) and tools_value: + mapped_tools = gemini_config._map_function( + value=tools_value, optional_params=result + ) + result = gemini_config._add_tools_to_optional_params(result, mapped_tools) + + web_search_options = non_default_params.get("web_search_options") + existing_tools = result.get("tools") + if isinstance(web_search_options, dict) and not ( + isinstance(existing_tools, list) and _has_gemini_search_tool(existing_tools) + ): + search_tool = gemini_config._map_web_search_options(web_search_options) + result = gemini_config._add_tools_to_optional_params(result, [search_tool]) + + gemini_config._drop_search_tools_mixed_with_functions(result) + + if isinstance(result.get("tools"), list): + result["tools"] = _dedupe_gemini_search_tools(result["tools"]) + + return result + + +def get_gemini_image_web_search_requests( + response_data: Dict[str, Any], +) -> Optional[int]: + from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import ( + VertexGeminiConfig, + ) + + grounding_metadata: List[Dict[str, Any]] = [] + for candidate in response_data.get("candidates", []): + if not isinstance(candidate, dict): + continue + candidate_grounding = candidate.get("groundingMetadata") + if isinstance(candidate_grounding, list): + grounding_metadata.extend(candidate_grounding) + elif isinstance(candidate_grounding, dict): + grounding_metadata.append(candidate_grounding) + + return VertexGeminiConfig._calculate_web_search_requests(grounding_metadata) + + def get_gemini_image_generation_config( model: str, optional_params: Dict[str, Any], diff --git a/litellm/llms/gemini/image_generation/cost_calculator.py b/litellm/llms/gemini/image_generation/cost_calculator.py index 3c8e69374af..380e2c21e9e 100644 --- a/litellm/llms/gemini/image_generation/cost_calculator.py +++ b/litellm/llms/gemini/image_generation/cost_calculator.py @@ -7,6 +7,7 @@ from typing import Any import litellm from litellm.litellm_core_utils.llm_cost_calc.utils import ( calculate_image_response_cost_from_usage, + calculate_image_response_web_search_cost, ) from litellm.types.utils import ImageResponse @@ -23,22 +24,25 @@ def cost_calculator( custom_llm_provider="gemini", ) - if isinstance(image_response, ImageResponse): - token_based_cost = calculate_image_response_cost_from_usage( - model=model, - image_response=image_response, - custom_llm_provider="gemini", - ) - if token_based_cost is not None: - return token_based_cost - - output_cost_per_image: float = _model_info.get("output_cost_per_image") or 0.0 - num_images: int = 0 - if isinstance(image_response, ImageResponse): - if image_response.data: - num_images = len(image_response.data) - return output_cost_per_image * num_images - else: + if not isinstance(image_response, ImageResponse): raise ValueError( f"image_response must be of type ImageResponse got type={type(image_response)}" ) + + web_search_cost = calculate_image_response_web_search_cost( + image_response=image_response, + custom_llm_provider="gemini", + model_info=_model_info, + ) + + token_based_cost = calculate_image_response_cost_from_usage( + model=model, + image_response=image_response, + custom_llm_provider="gemini", + ) + if token_based_cost is not None: + return token_based_cost + web_search_cost + + output_cost_per_image: float = _model_info.get("output_cost_per_image") or 0.0 + num_images: int = len(image_response.data) if image_response.data else 0 + return output_cost_per_image * num_images + web_search_cost diff --git a/litellm/llms/gemini/image_generation/transformation.py b/litellm/llms/gemini/image_generation/transformation.py index e6770a76bcb..ebfb0d68830 100644 --- a/litellm/llms/gemini/image_generation/transformation.py +++ b/litellm/llms/gemini/image_generation/transformation.py @@ -7,7 +7,9 @@ from litellm.llms.base_llm.image_generation.transformation import ( ) from litellm.llms.gemini.common_utils import ( get_gemini_image_generation_config, + get_gemini_image_web_search_requests, is_gemini_image_model, + map_gemini_image_tools_params, map_openai_image_params_to_gemini, ) from litellm.llms.gemini.image_usage_transformation import ( @@ -41,7 +43,7 @@ class GoogleImageGenConfig(BaseImageGenerationConfig): """ supported_params = ["n", "size"] if is_gemini_image_model(model): - supported_params.append("imageConfig") + supported_params.extend(["imageConfig", "tools", "web_search_options"]) return supported_params # type: ignore[return-value] def map_openai_params( @@ -51,12 +53,17 @@ class GoogleImageGenConfig(BaseImageGenerationConfig): model: str, drop_params: bool, ) -> dict: - return map_openai_image_params_to_gemini( + mapped_params = map_openai_image_params_to_gemini( params=non_default_params, model=model, supported_params=self.get_supported_openai_params(model), optional_params=optional_params, ) + if is_gemini_image_model(model): + mapped_params = map_gemini_image_tools_params( + non_default_params, mapped_params + ) + return mapped_params def get_complete_url( self, @@ -140,6 +147,10 @@ class GoogleImageGenConfig(BaseImageGenerationConfig): optional_params=optional_params, ), } + if tools := optional_params.get("tools"): + request_body["tools"] = tools + if tool_config := optional_params.get("toolConfig"): + request_body["toolConfig"] = tool_config return request_body else: # For other Imagen models, use the original Imagen format @@ -217,6 +228,11 @@ class GoogleImageGenConfig(BaseImageGenerationConfig): model_response.usage = transform_gemini_image_usage( response_data["usageMetadata"] ) + web_search_requests = get_gemini_image_web_search_requests(response_data) + if web_search_requests and model_response.usage is not None: + setattr( + model_response.usage, "web_search_requests", web_search_requests + ) else: # Original Imagen format - predictions with generated images predictions = response_data.get("predictions", []) diff --git a/litellm/llms/gemini/realtime/transformation.py b/litellm/llms/gemini/realtime/transformation.py index 212287fb7f8..74f6cd4d831 100644 --- a/litellm/llms/gemini/realtime/transformation.py +++ b/litellm/llms/gemini/realtime/transformation.py @@ -195,13 +195,48 @@ class GeminiRealtimeConfig(BaseRealtimeConfig): def get_audio_mime_type(self, input_audio_format: str = "pcm16"): mime_types = { - "pcm16": "audio/pcm", + "pcm16": "audio/pcm;rate=24000", "g711_ulaw": "audio/pcmu", "g711_alaw": "audio/pcma", } return mime_types.get(input_audio_format, "application/octet-stream") + def _manual_turn_detection_enabled( + self, session_configuration_request: Optional[str] + ) -> bool: + if not session_configuration_request: + return False + try: + setup = json.loads(session_configuration_request).get("setup", {}) + automatic_detection = setup.get("realtimeInputConfig", {}).get( + "automaticActivityDetection", {} + ) + return ( + isinstance(automatic_detection, dict) + and automatic_detection.get("disabled") is True + ) + except (json.JSONDecodeError, TypeError, AttributeError): + return False + + def _handle_input_audio_buffer_commit_or_end( + self, session_configuration_request: Optional[str] + ) -> List[str]: + """Map OpenAI buffer commit/end to Gemini Live turn-boundary signals.""" + if self._manual_turn_detection_enabled(session_configuration_request): + realtime_input_dict: BidiGenerateContentRealtimeInput = { + "activityEnd": True, + } + verbose_logger.debug( + "Gemini Realtime: Sending activityEnd realtimeInput to backend" + ) + else: + realtime_input_dict = {"audioStreamEnd": True} + verbose_logger.debug( + "Gemini Realtime: Sending audioStreamEnd realtimeInput to backend" + ) + return [json.dumps({"realtimeInput": realtime_input_dict})] + def map_automatic_turn_detection( self, value: OpenAIRealtimeTurnDetection ) -> AutomaticActivityDetection: @@ -656,6 +691,19 @@ class GeminiRealtimeConfig(BaseRealtimeConfig): ) messages.append(gemini_msg) return messages + + if msg_type in ("input_audio_buffer.commit", "input_audio_buffer.end"): + return self._handle_input_audio_buffer_commit_or_end( + session_configuration_request + ) + + if msg_type == "input_audio_buffer.clear": + # Local OpenAI buffer op — nothing to forward to Gemini Live. + verbose_logger.debug( + "Gemini Realtime: input_audio_buffer.clear is a local buffer op" + ) + return [] + # Unknown/unsupported OpenAI event type — drop silently rather than # forwarding raw JSON as text input to the model. return [] @@ -1330,7 +1378,7 @@ class GeminiRealtimeConfig(BaseRealtimeConfig): raise ValueError(f"Unknown openai event: {key}, value: {value}") return openai_event - def transform_realtime_response( # noqa: PLR0915 + def transform_realtime_response( self, message: Union[str, bytes], model: str, diff --git a/litellm/llms/github_copilot/responses/transformation.py b/litellm/llms/github_copilot/responses/transformation.py index 0929f95cf43..299f346a7eb 100644 --- a/litellm/llms/github_copilot/responses/transformation.py +++ b/litellm/llms/github_copilot/responses/transformation.py @@ -2,7 +2,7 @@ GitHub Copilot Responses API Configuration. This module provides the configuration for GitHub Copilot's Responses API, -which is required for models like gpt-5.1-codex that only support the /responses endpoint. +which is required for models like gpt-5.3-codex that only support the /responses endpoint. Implementation based on analysis of the copilot-api project by caozhiyuan: https://github.com/caozhiyuan/copilot-api @@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union import os +import litellm from litellm._logging import verbose_logger from litellm.constants import DEFAULT_MAX_RECURSE_DEPTH from litellm.exceptions import AuthenticationError @@ -22,6 +23,7 @@ from litellm.types.llms.openai import ( ) from litellm.types.router import GenericLiteLLMParams from litellm.types.utils import LlmProviders +from litellm.utils import _cached_get_model_info_helper from ..authenticator import Authenticator from ..common_utils import ( @@ -38,6 +40,47 @@ else: LiteLLMLoggingObj = Any +def github_copilot_supports_responses_api(model: str) -> bool: + """ + Gate native /v1/responses dispatch per github_copilot model. + + Resolution (first match wins): mode "responses" -> True; mode "chat" -> + False (opt-out wins for dual-endpoint models); "/v1/responses" in + supported_endpoints -> True; else False. Unknown model -> False (the bridge + always works since every Copilot model supports /chat/completions). + + Reads merged model info (per-deployment model_info applied via the router's + register_model, which also clears the cache used here). + """ + try: + info = _cached_get_model_info_helper( + model=model, custom_llm_provider="github_copilot" + ) + except Exception as e: + verbose_logger.debug( + "github_copilot_supports_responses_api: get_model_info failed " + "for %s: %s", + model, + e, + ) + return False + + mode = info.get("mode") + if mode == "responses": + return True + if mode == "chat": + return False + + # supported_endpoints is dropped by ModelInfoBase; read it from the raw + # model_cost entry via the resolved key. + key = info.get("key") + raw_info = litellm.model_cost.get(key) if isinstance(key, str) else None + endpoints = ( + raw_info.get("supported_endpoints") if isinstance(raw_info, dict) else None + ) + return isinstance(endpoints, list) and "/v1/responses" in endpoints + + class GithubCopilotResponsesAPIConfig(OpenAIResponsesAPIConfig): """ Configuration for GitHub Copilot's Responses API. @@ -58,6 +101,7 @@ class GithubCopilotResponsesAPIConfig(OpenAIResponsesAPIConfig): def __init__(self) -> None: super().__init__() self.authenticator = Authenticator() + self._stream_item_ids_by_output_index: Dict[int, str] = {} @property def custom_llm_provider(self) -> LlmProviders: @@ -86,6 +130,61 @@ class GithubCopilotResponsesAPIConfig(OpenAIResponsesAPIConfig): """ return dict(response_api_optional_params) + def transform_streaming_response( + self, + model: str, + parsed_chunk: dict, + logging_obj: LiteLLMLoggingObj, + ) -> Any: + parsed_chunk = self._normalize_stream_item_id(parsed_chunk) + return super().transform_streaming_response( + model=model, + parsed_chunk=parsed_chunk, + logging_obj=logging_obj, + ) + + def _normalize_stream_item_id(self, parsed_chunk: dict) -> dict: + """Rewrite streamed item ids to one stable id per output_index. + + GitHub Copilot tags each event of a single output item with a different + item id, so clients that key streaming state by item id (e.g. the Vercel + AI SDK) crash with "reasoning part not found" / "text part not + found". Every sub-event carries a top-level ``item_id`` (whatever the + item type), so its presence is the rewrite signal; output_item.added / + .done instead nest the id under ``item``. The anchor is keyed by + output_index and taken from output_item.added, which the protocol always + emits first, so it is written before any sub-event reads it. Copilot + accepts that id paired with the final encrypted_content next turn, so + multi-turn replay is unaffected. + + State is keyed by output_index on this config, which + ProviderConfigManager builds fresh per request, so it is stream-scoped. + """ + output_index = parsed_chunk.get("output_index") + if not isinstance(output_index, int): + return parsed_chunk + + if parsed_chunk.get("type") == "response.output_item.added": + item = parsed_chunk.get("item") + if isinstance(item, dict) and isinstance(item.get("id"), str): + self._stream_item_ids_by_output_index[output_index] = item["id"] + return parsed_chunk + + stable_id = self._stream_item_ids_by_output_index.get(output_index) + if stable_id is None: + return parsed_chunk + + if isinstance(parsed_chunk.get("item_id"), str): + parsed_chunk = dict(parsed_chunk) + parsed_chunk["item_id"] = stable_id + elif parsed_chunk.get("type") == "response.output_item.done": + item = parsed_chunk.get("item") + if isinstance(item, dict): + parsed_chunk = dict(parsed_chunk) + parsed_chunk["item"] = {**item, "id": stable_id} + + return parsed_chunk + def validate_environment( self, headers: dict, diff --git a/litellm/llms/hosted_vllm/chat/transformation.py b/litellm/llms/hosted_vllm/chat/transformation.py index 1824314865c..7c42e6a9a00 100644 --- a/litellm/llms/hosted_vllm/chat/transformation.py +++ b/litellm/llms/hosted_vllm/chat/transformation.py @@ -2,6 +2,7 @@ Translate from OpenAI's `/v1/chat/completions` to VLLM's `/v1/chat/completions` """ +import json from typing import ( Any, Coroutine, @@ -22,7 +23,9 @@ from litellm.litellm_core_utils.prompt_templates.factory import _parse_mime_type from litellm.secret_managers.main import get_secret_str from litellm.types.llms.openai import ( AllMessageValues, + ChatCompletionAssistantToolCall, ChatCompletionFileObject, + ChatCompletionToolCallFunctionChunk, ChatCompletionVideoObject, ChatCompletionVideoUrlObject, ) @@ -101,26 +104,18 @@ class HostedVLLMChatConfig(OpenAIGPTConfig): ) -> dict: _tools = non_default_params.pop("tools", None) if _tools is not None: - # remove 'additionalProperties' from tools _tools = _remove_additional_properties(_tools) - # remove 'strict' from tools _tools = _remove_strict_from_schema(_tools) if isinstance(_tools, list): _tools = self._convert_custom_tools_to_function_tools(_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: @@ -137,20 +132,13 @@ class HostedVLLMChatConfig(OpenAIGPTConfig): def _get_openai_compatible_provider_info( self, api_base: Optional[str], api_key: Optional[str] ) -> Tuple[Optional[str], Optional[str]]: - api_base = api_base or get_secret_str("HOSTED_VLLM_API_BASE") # type: ignore + api_base = api_base or get_secret_str("HOSTED_VLLM_API_BASE") dynamic_api_key = ( api_key or get_secret_str("HOSTED_VLLM_API_KEY") or "fake-api-key" - ) # vllm does not require an api key + ) return api_base, dynamic_api_key def _is_video_file(self, content_item: ChatCompletionFileObject) -> bool: - """ - Check if the file is a video - - - format: video/ - - file_data: base64 encoded video data - - file_id: infer mp4 from extension - """ file = content_item.get("file", {}) format = file.get("format") file_data = file.get("file_data") @@ -205,29 +193,69 @@ class HostedVLLMChatConfig(OpenAIGPTConfig): """ Support translating: - video files from file_id or file_data to video_url - - thinking_blocks on assistant messages to content blocks + - thinking_blocks on assistant messages are removed, and content lists + are converted to strings for vLLM compatibility """ for message in messages: if message["role"] == "assistant": - thinking_blocks = message.pop("thinking_blocks", None) # type: ignore - if thinking_blocks: - new_content: list = [ - ( - { - "type": block["type"], - "thinking": block.get("thinking", ""), + message.pop("thinking_blocks", None) + existing_content = message.get("content") + if isinstance(existing_content, list): + text_parts = [] + tool_calls: list[ChatCompletionAssistantToolCall] = [] + content_blocks: list[object] = [] + has_structured_content = False + for c in existing_content: + if isinstance(c, dict) and c.get("type") == "text": + text_parts.append(c.get("text", "")) + content_blocks.append(c) + elif isinstance(c, dict) and c.get("type") == "tool_use": + tool_input = c.get("input", {}) + tool_calls.append( + ChatCompletionAssistantToolCall( + id=c.get("id"), + type="function", + function=ChatCompletionToolCallFunctionChunk( + name=c.get("name"), + arguments=( + tool_input + if isinstance( + tool_input, + str, + ) + else json.dumps(tool_input) + ), + ), + ) + ) + else: + content_blocks.append(c) + has_structured_content = True + if tool_calls: + existing_tool_calls = message.get("tool_calls") + if isinstance(existing_tool_calls, list): + existing_tool_call_ids = { + tool_call.get("id") + for tool_call in existing_tool_calls + if isinstance(tool_call, dict) + and tool_call.get("id") is not None } - if block.get("type") == "thinking" - else {"type": block["type"], "data": block.get("data", "")} - ) - for block in thinking_blocks - ] - existing_content = message.get("content") - if isinstance(existing_content, str): - new_content.append({"type": "text", "text": existing_content}) - elif isinstance(existing_content, list): - new_content.extend(existing_content) - message["content"] = new_content # type: ignore + new_tool_calls = [ + tool_call + for tool_call in tool_calls + if tool_call.get("id") not in existing_tool_call_ids + ] + if new_tool_calls: + message["tool_calls"] = ( + existing_tool_calls + new_tool_calls + ) + else: + message["tool_calls"] = tool_calls + content_str = "\n".join(text_parts) + new_content = ( + content_blocks if has_structured_content else content_str + ) + message["content"] = new_content # type: ignore[typeddict-item] elif message["role"] == "user": message_content = message.get("content") if message_content and isinstance(message_content, list): @@ -243,6 +271,7 @@ class HostedVLLMChatConfig(OpenAIGPTConfig): message_content[idx] = self._convert_file_to_video_url( content_item ) + if is_async: return super()._transform_messages( messages, model, is_async=cast(Literal[True], True) diff --git a/litellm/llms/huggingface/embedding/transformation.py b/litellm/llms/huggingface/embedding/transformation.py index 88d42cfcdcc..7cddda617a9 100644 --- a/litellm/llms/huggingface/embedding/transformation.py +++ b/litellm/llms/huggingface/embedding/transformation.py @@ -404,7 +404,7 @@ class HuggingFaceEmbeddingConfig(BaseConfig): ) return completion_response - def convert_to_model_response_object( # noqa: PLR0915 + def convert_to_model_response_object( self, completion_response: Union[List[Dict[str, Any]], Dict[str, Any]], model_response: ModelResponse, diff --git a/litellm/llms/litellm_proxy/skills/README.md b/litellm/llms/litellm_proxy/skills/README.md index 1dfeff1a42c..a896aa1166e 100644 --- a/litellm/llms/litellm_proxy/skills/README.md +++ b/litellm/llms/litellm_proxy/skills/README.md @@ -18,7 +18,7 @@ flowchart TB F[Request with container.skills] --> G[SkillsInjectionHook] G --> H{skill_id prefix?} - H -->|"litellm:skill_abc"| I[Fetch from LiteLLM DB] + H -->|"litellm_skill_abc"| I[Fetch from LiteLLM DB] H -->|"skill_xyz" no prefix| J[Pass to Anthropic as native skill] I --> K{Model provider?} @@ -57,7 +57,7 @@ sequenceDiagram Note over LiteLLM,PreHook: PRE-CALL HOOK LiteLLM->>PreHook: Intercept request - PreHook->>PreHook: Fetch skill from DB (litellm:skill_id) + PreHook->>PreHook: Fetch skill from DB (litellm_skill_id) PreHook->>PreHook: Extract SKILL.md from ZIP PreHook->>PreHook: Inject SKILL.md into system prompt PreHook->>PreHook: Add litellm_code_execution tool @@ -105,7 +105,7 @@ response = await litellm.acompletion( model="gpt-4o-mini", messages=[{"role": "user", "content": "Create a bouncing ball GIF"}], container={ - "skills": [{"type": "custom", "skill_id": "litellm:skill_abc123"}] + "skills": [{"type": "custom", "skill_id": "litellm_skill_abc123"}] }, ) @@ -261,7 +261,7 @@ response = litellm.completion( messages=[{"role": "user", "content": "Analyze this data..."}], container={ "skills": [ - {"type": "custom", "skill_id": "litellm:skill_abc123"} # litellm: prefix + {"type": "custom", "skill_id": "litellm_skill_abc123"} # litellm_skill_ prefix ] } ) @@ -277,7 +277,7 @@ response = litellm.completion( "messages": [{"role": "user", "content": "Help me analyze data"}], "container": { "skills": [ - {"type": "custom", "skill_id": "litellm:skill_abc123"} + {"type": "custom", "skill_id": "litellm_skill_abc123"} ] } } @@ -287,7 +287,7 @@ response = litellm.completion( The hook (`litellm/proxy/hooks/litellm_skills/main.py`) intercepts the request: -1. **Detects `litellm:` prefix** → Fetches skill from database +1. **Detects `litellm_skill_` prefix** → Fetches skill from database 2. **Checks model provider** → Bedrock is not Anthropic 3. **Extracts SKILL.md** from stored ZIP file 4. **Converts skill to tool** + **Injects content into system prompt** @@ -361,8 +361,8 @@ model LiteLLM_SkillsTable { | Create skill on Anthropic | `anthropic` | N/A | Forward to Anthropic API | | Create skill in LiteLLM DB | `litellm_proxy` | N/A | Store in database | | Use Anthropic native skill | N/A | `skill_xyz` | Pass to Anthropic container.skills | -| Use LiteLLM skill on Anthropic | N/A | `litellm:skill_abc` | Convert to tools | -| Use LiteLLM skill on Bedrock/OpenAI | N/A | `litellm:skill_abc` | Convert to tools + inject SKILL.md | +| Use LiteLLM skill on Anthropic | N/A | `litellm_skill_abc` | Convert to tools | +| Use LiteLLM skill on Bedrock/OpenAI | N/A | `litellm_skill_abc` | Convert to tools + inject SKILL.md | ## Testing diff --git a/litellm/llms/litellm_proxy/skills/constants.py b/litellm/llms/litellm_proxy/skills/constants.py index a8c2697fcee..0c60a60842a 100644 --- a/litellm/llms/litellm_proxy/skills/constants.py +++ b/litellm/llms/litellm_proxy/skills/constants.py @@ -4,6 +4,10 @@ Constants for LiteLLM Skills Centralized constants for skills processing, code execution, and sandbox configuration. """ +LITELLM_SKILL_ID_PREFIX: str = "litellm_skill_" +"""Prefix for DB-backed skill IDs. The model-facing tool name is the skill ID +with hyphens/spaces replaced by underscores, which leaves this prefix intact.""" + # Code execution loop settings DEFAULT_MAX_ITERATIONS: int = 10 """Maximum number of iterations for the automatic code execution loop.""" diff --git a/litellm/llms/litellm_proxy/skills/handler.py b/litellm/llms/litellm_proxy/skills/handler.py index 37aabd8b477..9138b9a712f 100644 --- a/litellm/llms/litellm_proxy/skills/handler.py +++ b/litellm/llms/litellm_proxy/skills/handler.py @@ -10,6 +10,7 @@ from typing import Any, Dict, List, Optional from litellm._logging import verbose_logger from litellm.caching.in_memory_cache import InMemoryCache +from litellm.llms.litellm_proxy.skills.constants import LITELLM_SKILL_ID_PREFIX from litellm.proxy._types import LiteLLM_SkillsTable, NewSkillRequest, UserAPIKeyAuth from litellm.proxy.common_utils.resource_ownership import ( get_primary_resource_owner_scope, @@ -17,6 +18,7 @@ from litellm.proxy.common_utils.resource_ownership import ( is_proxy_admin, user_can_access_resource_owner, ) +from litellm.repositories.table_repositories import SkillsRepository # Skills are looked up on every chat completion that has skills enabled # (`SkillsInjectionHook` calls ``fetch_skill_from_db``). 60s LRU/TTL cache @@ -67,7 +69,7 @@ class LiteLLMSkillsHandler: ) -> LiteLLM_SkillsTable: prisma_client = await LiteLLMSkillsHandler._get_prisma_client() - skill_id = f"litellm_skill_{uuid.uuid4()}" + skill_id = f"{LITELLM_SKILL_ID_PREFIX}{uuid.uuid4()}" owner = get_primary_resource_owner_scope(user_api_key_dict) or user_id if owner is None: # Identity-less callers (no user_id / team_id / org_id / @@ -107,7 +109,7 @@ class LiteLLMSkillsHandler: f"LiteLLMSkillsHandler: Creating skill {skill_id} with title={data.display_title}" ) - new_skill = await prisma_client.db.litellm_skillstable.create(data=skill_data) + new_skill = await SkillsRepository(prisma_client).table.create(data=skill_data) return _prisma_skill_to_litellm(new_skill) @staticmethod @@ -133,7 +135,7 @@ class LiteLLMSkillsHandler: return [] find_many_kwargs["where"] = {"created_by": {"in": owner_scopes}} - skills = await prisma_client.db.litellm_skillstable.find_many( + skills = await SkillsRepository(prisma_client).table.find_many( **find_many_kwargs ) return [_prisma_skill_to_litellm(s) for s in skills] @@ -150,7 +152,7 @@ class LiteLLMSkillsHandler: return cached prisma_client = await LiteLLMSkillsHandler._get_prisma_client() - skill = await prisma_client.db.litellm_skillstable.find_unique( + skill = await SkillsRepository(prisma_client).table.find_unique( where={"skill_id": skill_id} ) _SKILL_CACHE.set_cache( @@ -189,7 +191,7 @@ class LiteLLMSkillsHandler: ): raise ValueError(f"Skill not found: {skill_id}") - await prisma_client.db.litellm_skillstable.delete(where={"skill_id": skill_id}) + await SkillsRepository(prisma_client).table.delete(where={"skill_id": skill_id}) _SKILL_CACHE.set_cache(skill_id, _NEGATIVE_SKILL_SENTINEL) return {"id": skill_id, "type": "skill_deleted"} diff --git a/litellm/llms/minimax/messages/transformation.py b/litellm/llms/minimax/messages/transformation.py index 3190a5f5412..57cfcbf0621 100644 --- a/litellm/llms/minimax/messages/transformation.py +++ b/litellm/llms/minimax/messages/transformation.py @@ -28,6 +28,9 @@ class MinimaxMessagesConfig(AnthropicMessagesConfig): def custom_llm_provider(self) -> Optional[str]: return "minimax" + def should_strip_billing_metadata(self) -> bool: + return True + @staticmethod def get_api_key(api_key: Optional[str] = None) -> Optional[str]: """ diff --git a/litellm/llms/modelscope/chat/transformation.py b/litellm/llms/modelscope/chat/transformation.py new file mode 100644 index 00000000000..162ef1a236c --- /dev/null +++ b/litellm/llms/modelscope/chat/transformation.py @@ -0,0 +1,93 @@ +""" +Translates from OpenAI's `/v1/chat/completions` to ModelScope's `/v1/chat/completions` +""" + +from typing import Any, Coroutine, Literal, Optional, Tuple, Union, cast, overload + +from typing_extensions import override + +from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import AllMessageValues + +from ...openai.chat.gpt_transformation import OpenAIGPTConfig + + +def _has_non_text_content(message: AllMessageValues) -> bool: + """Check if a message has non-text content items (e.g. image_url).""" + content = message.get("content") + if not isinstance(content, list): + return False + return any(item.get("type") != "text" for item in content) + + +class ModelScopeChatConfig(OpenAIGPTConfig): + DEFAULT_BASE_URL: str = "https://api-inference.modelscope.cn/v1" + + @overload + def _transform_messages( + self, messages: list[AllMessageValues], model: str, is_async: Literal[True] + ) -> Coroutine[Any, Any, list[AllMessageValues]]: ... + + @overload + def _transform_messages( + self, + messages: list[AllMessageValues], + model: str, + is_async: Literal[False] = False, + ) -> list[AllMessageValues]: ... + + def _transform_messages( + self, messages: list[AllMessageValues], model: str, is_async: bool = False + ) -> Union[list[AllMessageValues], Coroutine[Any, Any, list[AllMessageValues]]]: + """ + Flatten text-only content lists to strings for ModelScope. + + Messages with non-text content (e.g. image_url for vision models) + are kept as lists so the parent class can normalize them properly. + """ + messages = [cast(AllMessageValues, {**m}) for m in messages] + for message in messages: + if _has_non_text_content(message): + continue + content = message.get("content") + if isinstance(content, list): + message["content"] = "".join(item.get("text") or "" for item in content) + + if is_async: + return super()._transform_messages( + messages=messages, model=model, is_async=True + ) + else: + return super()._transform_messages( + messages=messages, model=model, is_async=False + ) + + def _get_openai_compatible_provider_info( + self, api_base: Optional[str], api_key: Optional[str] + ) -> Tuple[Optional[str], Optional[str]]: + api_base = ( + api_base or get_secret_str("MODELSCOPE_API_BASE") or self.DEFAULT_BASE_URL + ) # type: ignore + dynamic_api_key = api_key or get_secret_str("MODELSCOPE_API_KEY") + return api_base, dynamic_api_key + + @override + 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: + """ + If api_base is not provided, use the default ModelScope /chat/completions endpoint. + """ + if not api_base: + api_base = self.DEFAULT_BASE_URL + + if not api_base.endswith("/chat/completions"): + api_base = f"{api_base}/chat/completions" + + return api_base diff --git a/litellm/llms/modelscope/image_generation/__init__.py b/litellm/llms/modelscope/image_generation/__init__.py new file mode 100644 index 00000000000..8b28ea962ce --- /dev/null +++ b/litellm/llms/modelscope/image_generation/__init__.py @@ -0,0 +1,31 @@ +""" +ModelScope Image Generation Module + +Factory function for getting the appropriate config class. +""" + +from litellm.llms.base_llm.image_generation.transformation import ( + BaseImageGenerationConfig, +) + +from .transformation import ModelScopeImageGenerationConfig + +__all__ = [ + "ModelScopeImageGenerationConfig", + "get_modelscope_image_generation_config", +] + + +def get_modelscope_image_generation_config( + model: str, +) -> BaseImageGenerationConfig: + """ + Get the ModelScope config for image generation. + + Args: + model: The model name (e.g., "modelscope/Qwen/Qwen-Image-Edit") + + Returns: + BaseImageGenerationConfig instance for ModelScope + """ + return ModelScopeImageGenerationConfig() diff --git a/litellm/llms/modelscope/image_generation/transformation.py b/litellm/llms/modelscope/image_generation/transformation.py new file mode 100644 index 00000000000..0d85f7796fb --- /dev/null +++ b/litellm/llms/modelscope/image_generation/transformation.py @@ -0,0 +1,248 @@ +""" +ModelScope Image Generation Config + +Handles transformation between OpenAI-compatible format and ModelScope API format. + +API Reference: https://modelscope.cn/docs/model-service/API-Inference/intro +""" + +from typing import TYPE_CHECKING, Optional, Union + +import httpx +from typing_extensions import override + +from litellm.llms.base_llm.chat.transformation import BaseLLMException +from litellm.llms.base_llm.image_generation.transformation import ( + BaseImageGenerationConfig, +) +from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import ( + AllMessageValues, + OpenAIImageGenerationOptionalParams, +) +from litellm.types.utils import ImageObject, ImageResponse + +if TYPE_CHECKING: + from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj + + LiteLLMLoggingObj = _LiteLLMLoggingObj +else: + LiteLLMLoggingObj = object + + +class ModelScopeImageGenerationConfig(BaseImageGenerationConfig): + """ + Configuration for ModelScope image generation. + + Supports text-to-image models like: + - Qwen/Qwen-Image-Edit + - And other ModelScope-hosted image generation models + """ + + DEFAULT_BASE_URL: str = "https://api-inference.modelscope.cn/v1" + + def get_supported_openai_params( + self, model: str + ) -> list[OpenAIImageGenerationOptionalParams]: + """ + Return list of OpenAI params supported by ModelScope. + + ModelScope supports standard OpenAI image generation parameters. + """ + return [ + "n", # Number of images to generate + "size", # Size of the generated images + "response_format", # url or b64_json + "user", # User identifier + ] + + def map_openai_params( + self, + non_default_params: dict, + optional_params: dict, + model: str, + drop_params: bool, + ) -> dict: + """ + Map OpenAI parameters to ModelScope parameters. + + ModelScope uses the same parameter names as OpenAI. + """ + supported_params = self.get_supported_openai_params(model) + if drop_params: + non_default_params = { + k: v for k, v in non_default_params.items() if k in supported_params + } + optional_params.update(non_default_params) + return optional_params + + @override + 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 the ModelScope image generation API request. + """ + base_url: str = ( + api_base or get_secret_str("MODELSCOPE_API_BASE") or self.DEFAULT_BASE_URL + ) + base_url = base_url.rstrip("/") + + # Return the images endpoint + return f"{base_url}/images/generations" + + @override + 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 ModelScope. + """ + final_api_key: Optional[str] = api_key or get_secret_str("MODELSCOPE_API_KEY") + + if not final_api_key: + raise ValueError( + "MODELSCOPE_API_KEY is not set. " + "Please set it via environment variable or pass api_key parameter." + ) + + default_headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {final_api_key}", + } + + headers = {**headers, **default_headers} + return headers + + def transform_image_generation_request( + self, + model: str, + prompt: str, + optional_params: dict, + litellm_params: dict, + headers: dict, + ) -> dict: + """ + Transform OpenAI-style request to ModelScope request format. + + ModelScope uses the same format as OpenAI for image generation. + """ + # Build the request body (same as OpenAI) + request_data: dict = { + "model": model, + "prompt": prompt, + } + + # Add optional params + for key, value in optional_params.items(): + if key.startswith("_"): + continue + request_data[key] = value + + return request_data + + @override + def transform_image_generation_response( + self, + model: str, + raw_response: httpx.Response, + model_response: ImageResponse, + logging_obj: LiteLLMLoggingObj, + request_data: dict, + optional_params: dict, + litellm_params: dict, + encoding: object, + api_key: Optional[str] = None, + json_mode: Optional[bool] = None, + ) -> ImageResponse: + """ + Transform ModelScope response to OpenAI-compatible ImageResponse. + + ModelScope returns the same format as OpenAI: + {"created": timestamp, "data": [{"url": "..."}]} + """ + try: + response_data = raw_response.json() + except Exception as e: + raise self.get_error_class( + error_message=f"Error parsing ModelScope response: {e}", + status_code=raw_response.status_code, + headers=raw_response.headers, + ) + + # Check for errors in response + if "error" in response_data: + error_msg = response_data["error"].get( + "message", str(response_data["error"]) + ) + raise self.get_error_class( + error_message=f"ModelScope error: {error_msg}", + status_code=raw_response.status_code, + headers=raw_response.headers, + ) + + # Extract images from response + data_list = response_data.get("data", []) + if not model_response.data: + model_response.data = [] + + for item in data_list: + image_obj = ImageObject( + url=item.get("url"), + b64_json=item.get("b64_json"), + revised_prompt=item.get("revised_prompt"), + ) + model_response.data.append(image_obj) + + return model_response + + def get_error_class( + self, + error_message: str, + status_code: int, + headers: Union[dict, httpx.Headers], + ) -> BaseLLMException: + """Return the appropriate error class for ModelScope.""" + from litellm.exceptions import ( + AuthenticationError, + BadRequestError, + InternalServerError, + ) + + if status_code == 400: + return BadRequestError( # type: ignore[return-value] + message=error_message, + model="", + llm_provider="modelscope", + ) + elif status_code == 401: + return AuthenticationError( # type: ignore[return-value] + message=error_message, + model="", + llm_provider="modelscope", + ) + elif status_code >= 500: + return InternalServerError( # type: ignore[return-value] + message=error_message, + model="", + llm_provider="modelscope", + ) + else: + return BadRequestError( # type: ignore[return-value] + message=error_message, + model="", + llm_provider="modelscope", + ) diff --git a/litellm/llms/oci/chat/transformation.py b/litellm/llms/oci/chat/transformation.py index f050f9eea36..d1248b6e518 100644 --- a/litellm/llms/oci/chat/transformation.py +++ b/litellm/llms/oci/chat/transformation.py @@ -25,6 +25,7 @@ from typing import ( import httpx import litellm +from litellm.constants import DEFAULT_OCI_CHAT_MAX_TOKENS from litellm.litellm_core_utils.logging_utils import track_llm_api_timing from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException from litellm.llms.custom_httpx.http_handler import ( @@ -87,15 +88,20 @@ STREAMING_TIMEOUT = 60 * 5 def _model_uses_max_completion_tokens(model: str) -> bool: """Return True for OCI-hosted models that require ``maxCompletionTokens``. - Reasoning models on OCI (e.g. the OpenAI GPT-5 family) reject ``maxTokens`` - with HTTP 400 and require ``maxCompletionTokens`` per OpenAI's reasoning-API - convention. Driven by ``supports_reasoning`` in - ``model_prices_and_context_window.json`` so new model families are picked - up via a catalog update rather than a code change. + OpenAI commercial models proxied through OCI (``openai.*``) reject + ``maxTokens`` with HTTP 400 on the reasoning families (gpt-5.x, o-series) + and accept ``maxCompletionTokens`` everywhere, so route the whole vendor + prefix to it rather than chasing each new release in + ``model_prices_and_context_window.json``. The ``openai.gpt-oss-*`` open + weights are served by OCI's own stack and keep ``maxTokens``. Any other + vendor falls back to the catalog's ``supports_reasoning`` flag. """ if not model: return False name = model[4:] if model.lower().startswith("oci/") else model + lowered = name.lower() + if lowered.startswith("openai."): + return not lowered.startswith("openai.gpt-oss") return supports_reasoning(model=name, custom_llm_provider="oci") @@ -193,19 +199,49 @@ def _normalize_response_format(selected_params: Dict, vendor: OCIVendors) -> Non rf = selected_params.get("responseFormat") if not isinstance(rf, dict) or "type" not in rf: return - rf_payload = dict(rf) - selected_params["responseFormat"] = rf_payload - response_type = rf_payload["type"] - if "json_schema" in rf_payload: - raw_schema = rf_payload.pop("json_schema") - rf_payload["jsonSchema"] = ( - dict(raw_schema) if isinstance(raw_schema, dict) else raw_schema - ) + + rf_type = str(rf["type"]).lower() + raw_schema = rf.get("json_schema") + json_schema = raw_schema if isinstance(raw_schema, dict) else None + + if rf_type == "text": + selected_params["responseFormat"] = {"type": "TEXT"} + return + if vendor == OCIVendors.COHERE: - rf_payload["type"] = response_type - else: - fmt = response_type.upper() - rf_payload["type"] = "JSON_OBJECT" if fmt == "JSON" else fmt + # OCI Cohere has no JSON_SCHEMA type; a schema rides on JSON_OBJECT. + payload: Dict[str, Any] = {"type": "JSON_OBJECT"} + if json_schema is not None and json_schema.get("schema") is not None: + payload["schema"] = json_schema["schema"] + selected_params["responseFormat"] = payload + return + + if rf_type == "json_schema": + if json_schema is None: + raise OCIError( + status_code=400, + message="response_format type 'json_schema' requires a 'json_schema' object", + ) + # OCI's ResponseJsonSchema accepts only name/description/schema/isStrict. + # OpenAI sends `strict` instead of `isStrict`; forwarding it (or any + # other extra key) makes OCI reject the whole request with HTTP 400. + oci_schema: Dict[str, Any] = {"name": json_schema.get("name") or "response"} + if json_schema.get("description") is not None: + oci_schema["description"] = json_schema["description"] + if json_schema.get("schema") is not None: + oci_schema["schema"] = json_schema["schema"] + if json_schema.get("strict") is not None: + oci_schema["isStrict"] = json_schema["strict"] + selected_params["responseFormat"] = { + "type": "JSON_SCHEMA", + "jsonSchema": oci_schema, + } + return + + fmt = rf_type.upper() + selected_params["responseFormat"] = { + "type": "JSON_OBJECT" if fmt == "JSON" else fmt + } def get_vendor_from_model(model: str) -> OCIVendors: @@ -297,6 +333,11 @@ class OCIChatConfig(BaseConfig): if get_vendor_from_model(model) == OCIVendors.COHERE else self.openai_to_oci_generic_param_map ) + # `n` is intentionally not advertised for Cohere even though n=1 is + # tolerated: Cohere has no numGenerations field, so n>1 cannot be + # honoured and advertising it would be misleading. Callers that gate on + # this list strip n=1 (a no-op, matching what map_openai_params does); + # callers that bypass it have n=1 dropped there. Both paths converge. return [key for key, value in param_map.items() if value] def map_openai_params( @@ -317,6 +358,19 @@ class OCIChatConfig(BaseConfig): for key, value in {**non_default_params, **optional_params}.items(): alias = param_map.get(key) if alias is False: + # max_retries is a litellm-level control param (litellm applies + # retries itself); it is never a generation param OCI accepts, so + # drop it silently. The litellm proxy injects it on every request, + # which otherwise 500s OCI calls unless drop_params is set. + if key == "max_retries": + continue + # n=1 (or None) is the OpenAI default: a single generation, which + # every OCI model produces anyway. Drop it silently so standard + # clients that always send n=1 (e.g. the MLflow gateway) are not + # rejected; only n>1 is genuinely unsupported on Cohere, which + # has no numGenerations field. + if key == "n" and (value is None or value == 1): + continue if drop_params or litellm.drop_params: continue raise OCIError( @@ -451,6 +505,13 @@ class OCIChatConfig(BaseConfig): elif oci_alias in optional_params: selected_params[target] = optional_params[oci_alias] # type: ignore[index] + # OCI's server-side default token cap is tiny (~20 tokens), so an + # omitted max_tokens silently truncates the response mid-string. Most + # callers never send a limit (MLflow judges among them), so inject a + # sane default when one is absent, mirroring litellm's Anthropic config. + if max_tokens_key not in selected_params: + selected_params[max_tokens_key] = DEFAULT_OCI_CHAT_MAX_TOKENS + # OCI expects uppercase reasoning levels (LOW/MEDIUM/HIGH/NONE); OpenAI # clients send lowercase. OpenAI's "disable" maps to OCI's "NONE". if "reasoningEffort" in selected_params: diff --git a/litellm/llms/openai/chat/gpt_transformation.py b/litellm/llms/openai/chat/gpt_transformation.py index 5464b5bb7ee..b8b750b8c12 100644 --- a/litellm/llms/openai/chat/gpt_transformation.py +++ b/litellm/llms/openai/chat/gpt_transformation.py @@ -18,6 +18,9 @@ from typing import ( overload, ) +import os +from urllib.parse import urlparse + import httpx import litellm @@ -426,6 +429,32 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig): ) return messages, tools + def _should_preserve_cache_control_for_endpoint( + self, + custom_llm_provider: str | None, + api_base: str | None, + ) -> bool: + """ + The generic `openai` provider also reaches OpenAI-compatible endpoints + (a LiteLLM proxy, vLLM, an Anthropic-compatible gateway) via a custom + api_base. Those can understand cache_control, so it must survive there. + Real OpenAI cannot, so it is still stripped for an openai.com host. + """ + if custom_llm_provider != "openai": + return False + resolved_api_base = ( + api_base + or litellm.api_base + or os.getenv("OPENAI_BASE_URL") + or os.getenv("OPENAI_API_BASE") + ) + if not resolved_api_base: + return False + hostname = urlparse(resolved_api_base).hostname + if hostname is None: + return False + return hostname != "openai.com" and not hostname.endswith(".openai.com") + def transform_request( self, model: str, @@ -441,11 +470,14 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig): dict: The transformed request. Sent as the body of the API call. """ messages = self._transform_messages(messages=messages, model=model) - messages, tools = self.remove_cache_control_flag_from_messages_and_tools( - model=model, messages=messages, tools=optional_params.get("tools", []) - ) - if tools is not None and len(tools) > 0: - optional_params["tools"] = tools + if not self._should_preserve_cache_control_for_endpoint( + litellm_params.get("custom_llm_provider"), litellm_params.get("api_base") + ): + messages, tools = self.remove_cache_control_flag_from_messages_and_tools( + model=model, messages=messages, tools=optional_params.get("tools", []) + ) + if tools is not None and len(tools) > 0: + optional_params["tools"] = tools optional_params.pop("max_retries", None) @@ -466,16 +498,19 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig): transformed_messages = await self._transform_messages( messages=messages, model=model, is_async=True ) - ( - transformed_messages, - tools, - ) = self.remove_cache_control_flag_from_messages_and_tools( - model=model, - messages=transformed_messages, - tools=optional_params.get("tools", []), - ) - if tools is not None and len(tools) > 0: - optional_params["tools"] = tools + if not self._should_preserve_cache_control_for_endpoint( + litellm_params.get("custom_llm_provider"), litellm_params.get("api_base") + ): + ( + transformed_messages, + tools, + ) = self.remove_cache_control_flag_from_messages_and_tools( + model=model, + messages=transformed_messages, + tools=optional_params.get("tools", []), + ) + if tools is not None and len(tools) > 0: + optional_params["tools"] = tools if self.__class__._is_base_class: return { "model": model, diff --git a/litellm/llms/openai/completion/handler.py b/litellm/llms/openai/completion/handler.py index 1641615126e..63d39151254 100644 --- a/litellm/llms/openai/completion/handler.py +++ b/litellm/llms/openai/completion/handler.py @@ -49,6 +49,8 @@ class OpenAITextCompletion(BaseLLM): headers: Optional[dict] = None, ): try: + if headers: + optional_params = {**optional_params, "extra_headers": headers} if headers is None: headers = self.validate_environment(api_key=api_key) if model is None or messages is None: diff --git a/litellm/llms/openai/openai.py b/litellm/llms/openai/openai.py index 194f29648c4..ea905d8ebca 100644 --- a/litellm/llms/openai/openai.py +++ b/litellm/llms/openai/openai.py @@ -608,7 +608,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): return streaming_response - def completion( # type: ignore # noqa: PLR0915 + def completion( # type: ignore self, model_response: ModelResponse, timeout: Union[float, httpx.Timeout], diff --git a/litellm/llms/openai/realtime/handler.py b/litellm/llms/openai/realtime/handler.py index f34dae2df09..6751004f1b1 100644 --- a/litellm/llms/openai/realtime/handler.py +++ b/litellm/llms/openai/realtime/handler.py @@ -157,8 +157,14 @@ class OpenAIRealtime(OpenAIChatCompletion): websocket, cast(ClientConnection, backend_ws), logging_obj, + model=model, user_api_key_dict=user_api_key_dict, request_data={"litellm_metadata": litellm_metadata or {}}, + force_transcription_model=( + model + if (query_params or {}).get("intent") == "transcription" + else None + ), ) await realtime_streaming.bidirectional_forward() diff --git a/litellm/llms/openai/realtime/http_transformation.py b/litellm/llms/openai/realtime/http_transformation.py index 1663fcd1fcd..7a6af39ba65 100644 --- a/litellm/llms/openai/realtime/http_transformation.py +++ b/litellm/llms/openai/realtime/http_transformation.py @@ -41,6 +41,14 @@ class OpenAIRealtimeHTTPConfig(BaseRealtimeHTTPConfig): base = base[:-3] return f"{base}/v1/realtime/calls" + def get_transcription_session_url( + self, api_base: Optional[str], model: str, api_version: Optional[str] = None + ) -> str: + base = self.get_api_base(api_base).rstrip("/") + if base.endswith("/v1"): + base = base[:-3] + return f"{base}/v1/realtime/transcription_sessions" + def validate_environment( self, headers: dict, diff --git a/litellm/llms/openai/responses/guardrail_translation/handler.py b/litellm/llms/openai/responses/guardrail_translation/handler.py index f7dd68aec55..b5319797cc6 100644 --- a/litellm/llms/openai/responses/guardrail_translation/handler.py +++ b/litellm/llms/openai/responses/guardrail_translation/handler.py @@ -35,7 +35,6 @@ from pydantic import BaseModel from litellm._logging import verbose_proxy_logger from litellm.completion_extras.litellm_responses_transformation.transformation import ( - LiteLLMResponsesTransformationHandler, OpenAiResponsesToChatCompletionStreamIterator, ) from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation @@ -479,90 +478,137 @@ class OpenAIResponsesHandler(BaseTranslation): ) -> List[Any]: """ Process output streaming response by applying guardrails to text content. + + Mirrors the Chat Completions handler pattern: extract text from the final + chunk, apply the guardrail, then write the result back in-place so the + caller sees the modified content (e.g. PII tokens replaced). + + For ``response.completed`` events (the normal end-of-stream signal) we + use the same per-item extraction + task-mapping approach as + ``process_output_response`` so that unmasking / blocking works correctly + for every output item. """ + if not responses_so_far: + return responses_so_far final_chunk = responses_so_far[-1] + # Accept both plain dicts and Pydantic models (BaseLiteLLMOpenAIResponseObject + # exposes a .get() shim, so all the .get() calls below work for both). + if not (isinstance(final_chunk, dict) or hasattr(final_chunk, "get")): + return responses_so_far + # ------------------------------------------------------------------ # + # Case 1: response.completed — full response is available in the # + # final chunk; iterate output items, apply guardrail, write back. # + # ------------------------------------------------------------------ # + if final_chunk.get("type") == "response.completed": + response_obj = final_chunk.get("response") or {} + if not hasattr(response_obj, "get"): + return responses_so_far + outputs: List[Any] = response_obj.get("output") or [] + + texts_to_check: List[str] = [] + tool_calls_to_check: List[ChatCompletionToolCallChunk] = [] + task_mappings: List[Tuple[int, int]] = [] + + for output_idx, output_item in enumerate(outputs): + self._extract_output_text_and_images( + output_item=output_item, + output_idx=output_idx, + texts_to_check=texts_to_check, + images_to_check=[], + task_mappings=task_mappings, + tool_calls_to_check=tool_calls_to_check, + ) + + if texts_to_check or tool_calls_to_check: + if request_data is None: + request_data = {} + if "response" not in request_data: + request_data["response"] = response_obj + if "litellm_metadata" not in request_data: + user_metadata = self.transform_user_api_key_dict_to_metadata( + user_api_key_dict + ) + if user_metadata: + request_data["litellm_metadata"] = user_metadata + + inputs = GenericGuardrailAPIInputs(texts=texts_to_check) + if tool_calls_to_check: + inputs["tool_calls"] = cast( + List[ChatCompletionToolCallChunk], tool_calls_to_check + ) + response_model = response_obj.get("model") + if response_model: + inputs["model"] = response_model + + guardrailed_inputs = await guardrail_to_apply.apply_guardrail( + inputs=inputs, + request_data=request_data, + input_type="response", + logging_obj=litellm_logging_obj, + ) + + guardrailed_texts = guardrailed_inputs.get("texts", []) + + # Write guardrailed texts back into the output items in-place. + # final_chunk is a reference into responses_so_far so this + # mutates the list that the caller holds. + await self._apply_guardrail_responses_to_output( + response=response_obj, + responses=guardrailed_texts, + task_mappings=task_mappings, + ) + + return responses_so_far + + # ------------------------------------------------------------------ # + # Case 2: response.output_item.done — extract tool calls only. # + # ------------------------------------------------------------------ # if final_chunk.get("type") == "response.output_item.done": - # convert openai response to model response model_response_stream = OpenAiResponsesToChatCompletionStreamIterator.translate_responses_chunk_to_openai_stream( final_chunk ) - 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( + await guardrail_to_apply.apply_guardrail( inputs=inputs, request_data=request_data if request_data is not None else {}, input_type="response", logging_obj=litellm_logging_obj, ) - return responses_so_far - elif final_chunk.get("type") == "response.completed": - # convert openai response to model response - outputs = final_chunk.get("response", {}).get("output", []) + return responses_so_far - model_response_choices = LiteLLMResponsesTransformationHandler._convert_response_output_to_choices( - output_items=outputs, - handle_raw_dict_callback=None, - ) - - 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=request_data if request_data is not None else {}, - 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 + # ------------------------------------------------------------------ # + # Fallback: apply guardrail to the accumulated text string. # + # No structured write-back is possible here; guardrails that only # + # need to block/flag (not rewrite) still work correctly. # + # ------------------------------------------------------------------ # 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): + if string_so_far: + fallback_inputs = GenericGuardrailAPIInputs(texts=[string_so_far]) 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=inputs, - request_data=request_data if request_data is not None else {}, - input_type="response", - logging_obj=litellm_logging_obj, - ) + fallback_inputs["model"] = response_model + await guardrail_to_apply.apply_guardrail( + inputs=fallback_inputs, + request_data=request_data if request_data is not None else {}, + input_type="response", + logging_obj=litellm_logging_obj, + ) return responses_so_far def _check_streaming_has_ended(self, responses_so_far: List[Any]) -> bool: @@ -721,7 +767,7 @@ class OpenAIResponsesHandler(BaseTranslation): async def _apply_guardrail_responses_to_output( self, - response: "ResponsesAPIResponse", + response: Union["ResponsesAPIResponse", Dict[Any, Any]], responses: List[str], task_mappings: List[Tuple[int, int]], ) -> None: diff --git a/litellm/llms/openai/transcriptions/whisper_transformation.py b/litellm/llms/openai/transcriptions/whisper_transformation.py index fa507e1bc26..2c01156fe05 100644 --- a/litellm/llms/openai/transcriptions/whisper_transformation.py +++ b/litellm/llms/openai/transcriptions/whisper_transformation.py @@ -1,3 +1,4 @@ +import json from typing import List, Optional, Union from httpx import Headers, Response @@ -107,9 +108,7 @@ class OpenAIWhisperAudioTranscriptionConfig(BaseAudioTranscriptionConfig): """ data = {"model": model, "file": audio_file, **optional_params} - if "response_format" not in data or ( - data["response_format"] == "text" or data["response_format"] == "json" - ): + if "response_format" not in data: data["response_format"] = ( "verbose_json" # ensures 'duration' is received - used for cost calculation ) @@ -133,10 +132,11 @@ class OpenAIWhisperAudioTranscriptionConfig(BaseAudioTranscriptionConfig): ) -> TranscriptionResponse: try: raw_response_json = raw_response.json() - except Exception as e: - raise ValueError( - f"Error transforming response to json: {str(e)}\nResponse: {raw_response.text}" - ) + except json.JSONDecodeError: + content_type = raw_response.headers.get("content-type", "").lower() + if "application/json" in content_type: + raise + return TranscriptionResponse(text=raw_response.text) if any( key in raw_response_json diff --git a/litellm/llms/openai_like/dynamic_config.py b/litellm/llms/openai_like/dynamic_config.py index fac453447fa..9ed9734edae 100644 --- a/litellm/llms/openai_like/dynamic_config.py +++ b/litellm/llms/openai_like/dynamic_config.py @@ -187,6 +187,7 @@ def create_responses_config_class(provider: SimpleProviderConfig): from litellm.llms.openai_like.responses.transformation import ( OpenAILikeResponsesConfig, ) + from litellm.types.llms.openai import ResponseInputParam from litellm.types.router import GenericLiteLLMParams class JSONProviderResponsesConfig(OpenAILikeResponsesConfig): @@ -223,5 +224,23 @@ def create_responses_config_class(provider: SimpleProviderConfig): api_base = api_base.rstrip("/") return f"{api_base}/responses" + def transform_responses_api_request( + self, + model: str, + input: Union[str, ResponseInputParam], + response_api_optional_request_params: dict, + litellm_params: GenericLiteLLMParams, + headers: dict, + ) -> dict: + if provider.special_handling.get("force_store_false"): + response_api_optional_request_params["store"] = False + return super().transform_responses_api_request( + model=model, + input=input, + response_api_optional_request_params=response_api_optional_request_params, + litellm_params=litellm_params, + headers=headers, + ) + _responses_config_cache[provider.slug] = JSONProviderResponsesConfig return JSONProviderResponsesConfig diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index 49b3801c82f..24943563937 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -131,6 +131,42 @@ "base_class": "openai_gpt", "param_mappings": { "max_completion_tokens": "max_tokens" + }, + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] + }, + "parasail": { + "base_url": "https://api.parasail.io/v1", + "api_key_env": "PARASAIL_API_KEY", + "api_base_env": "PARASAIL_API_BASE", + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"], + "special_handling": { + "force_store_false": true } + }, + "libertai": { + "base_url": "https://api.libertai.io/v1", + "api_key_env": "LIBERTAI_API_KEY", + "api_base_env": "LIBERTAI_API_BASE", + "param_mappings": { + "max_completion_tokens": "max_tokens" + } + }, + "empiriolabs": { + "base_url": "https://api.empiriolabs.ai/v1", + "api_key_env": "EMPIRIOLABS_API_KEY", + "api_base_env": "EMPIRIOLABS_API_BASE", + "param_mappings": { + "max_completion_tokens": "max_tokens" + }, + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] + }, + "pinstripes": { + "base_url": "https://pinstripes.io/v1", + "api_key_env": "PINSTRIPES_API_KEY", + "api_base_env": "PINSTRIPES_API_BASE", + "param_mappings": { + "max_completion_tokens": "max_tokens" + }, + "supported_endpoints": ["/v1/chat/completions", "/v1/responses", "/v1/embeddings"] } } diff --git a/litellm/llms/openrouter/chat/transformation.py b/litellm/llms/openrouter/chat/transformation.py index 0d7850e8c74..107d5c25e6d 100644 --- a/litellm/llms/openrouter/chat/transformation.py +++ b/litellm/llms/openrouter/chat/transformation.py @@ -50,11 +50,15 @@ class OpenrouterConfig(OpenAIGPTConfig): def map_openai_params( self, - non_default_params: dict, + non_default_params: dict[str, object], optional_params: dict, model: str, drop_params: bool, ) -> dict: + # OpenRouter expects "xhigh" instead of "max" for reasoning_effort. + if non_default_params.get("reasoning_effort") == "max": + non_default_params = {**non_default_params, "reasoning_effort": "xhigh"} + mapped_openai_params = super().map_openai_params( non_default_params, optional_params, model, drop_params ) diff --git a/litellm/llms/parallel_ai/search/transformation.py b/litellm/llms/parallel_ai/search/transformation.py index 12d570f1733..85602bf1d86 100644 --- a/litellm/llms/parallel_ai/search/transformation.py +++ b/litellm/llms/parallel_ai/search/transformation.py @@ -1,7 +1,7 @@ """ -Calls Parallel AI's /search endpoint to search the web. +Calls Parallel AI's /v1/search endpoint to search the web. -Parallel AI API Reference: https://docs.parallel.ai/api-reference/search-and-extract-api-beta/search +Parallel AI API Reference: https://docs.parallel.ai/api-reference/search/search """ from typing import Dict, List, Optional, TypedDict, Union @@ -18,36 +18,43 @@ from litellm.secret_managers.main import get_secret_str class _ParallelAISourcePolicy(TypedDict, total=False): - """Source policy for Parallel AI search results.""" - - allowed_domains: List[str] # Optional - list of allowed domains - disallowed_domains: List[str] # Optional - list of disallowed domains + include_domains: List[str] + exclude_domains: List[str] + after_date: str -class _ParallelAISearchRequestRequired(TypedDict): - """Required fields for Parallel AI Search API request.""" - - # Note: At least one of objective or search_queries must be provided - pass +class _ParallelAIExcerptSettings(TypedDict, total=False): + max_chars_per_result: int -class ParallelAISearchRequest(_ParallelAISearchRequestRequired, total=False): +class _ParallelAIAdvancedSettings(TypedDict, total=False): + source_policy: _ParallelAISourcePolicy + excerpt_settings: _ParallelAIExcerptSettings + fetch_policy: Dict + location: str + max_results: int + + +class ParallelAISearchRequest(TypedDict, total=False): """ - Parallel AI Search API request format. - Based on: https://docs.parallel.ai/api-reference/search-and-extract-api-beta/search + Parallel AI v1 Search API request format. + Based on: https://docs.parallel.ai/api-reference/search/search """ + search_queries: List[str] # Required - at least one keyword search query objective: str # Optional - natural-language description of search goal - search_queries: List[str] # Optional - list of keyword search queries - processor: str # Optional - search processor ('base', 'pro'), default 'base' - max_results: int # Optional - maximum number of results, default 10 - max_chars_per_result: int # Optional - max characters per result excerpt - source_policy: _ParallelAISourcePolicy # Optional - source policy for allowed/disallowed domains + mode: str # Optional - 'turbo', 'basic', or 'advanced' (default 'advanced') + max_chars_total: int # Optional - upper bound on total excerpt characters + session_id: str # Optional - tracks calls across search/extract requests + client_model: str # Optional - model consuming the results + advanced_settings: _ParallelAIAdvancedSettings + + +LEGACY_PROCESSOR_TO_MODE = {"base": "basic", "pro": "advanced"} class ParallelAISearchConfig(BaseSearchConfig): PARALLEL_AI_API_BASE = "https://api.parallel.ai" - PARALLEL_HEADER_SEARCH_EXTRACT_VALUE = "search-extract-2025-10-10" @staticmethod def ui_friendly_name() -> str: @@ -60,9 +67,6 @@ class ParallelAISearchConfig(BaseSearchConfig): api_base: Optional[str] = None, **kwargs, ) -> Dict: - """ - Validate environment and return headers. - """ api_key = ( api_key or get_secret_str("PARALLEL_AI_API_KEY") @@ -74,7 +78,6 @@ class ParallelAISearchConfig(BaseSearchConfig): ) headers["x-api-key"] = api_key headers["Content-Type"] = "application/json" - headers["parallel-beta"] = self.PARALLEL_HEADER_SEARCH_EXTRACT_VALUE return headers def get_complete_url( @@ -84,32 +87,18 @@ class ParallelAISearchConfig(BaseSearchConfig): data: Optional[Union[Dict, List[Dict]]] = None, **kwargs, ) -> str: - """ - Get complete URL for Search endpoint. - """ api_base = ( api_base or get_secret_str("PARALLEL_AI_API_BASE") or self.PARALLEL_AI_API_BASE ) - # Parallel AI search endpoint is at /v1beta/search - if not api_base.endswith("/v1beta/search"): - if api_base.endswith("/"): - api_base = f"{api_base}v1beta/search" - else: - api_base = f"{api_base}/v1beta/search" + api_base = api_base.rstrip("/") + if not api_base.endswith("/v1/search"): + api_base = f"{api_base.removesuffix('/v1')}/v1/search" return api_base - def _transform_query_to_objective(self, query: Union[str, List[str]]) -> str: - """ - Transform query to objective. - """ - if isinstance(query, list): - return " ".join(query) - return query - def transform_search_request( self, query: Union[str, List[str]], @@ -117,57 +106,78 @@ class ParallelAISearchConfig(BaseSearchConfig): **kwargs, ) -> Dict: """ - Transform Search request to Parallel AI API format. + Transform Search request to Parallel AI v1 API format. Args: query: Search query (string or list of strings) - - If string: maps to `objective` (natural language) + - If string: maps to `search_queries` (single item) and `objective` - If list: maps to `search_queries` (keyword queries) optional_params: Optional parameters for the request - - max_results: Maximum number of search results (default 10) - - search_domain_filter: List of domains to include -> maps to `source_policy.allowed_domains` - - exclude_domains: List of domains to exclude -> maps to `source_policy.disallowed_domains` - - processor: Search processor ('base', 'pro') - - max_chars_per_result: Max characters per result excerpt + - mode: Search mode ('turbo', 'basic', 'advanced'); defaults to 'basic' + - processor: Legacy v1beta param; 'base' maps to mode 'basic', 'pro' to 'advanced' + - max_results: Maximum number of search results -> `advanced_settings.max_results` + - search_domain_filter: Domains to include -> `advanced_settings.source_policy.include_domains` + - exclude_domains: Domains to exclude -> `advanced_settings.source_policy.exclude_domains` + - country: ISO 3166-1 alpha-2 code -> `advanced_settings.location` + - max_chars_per_result: -> `advanced_settings.excerpt_settings.max_chars_per_result` + - Any other params are passed through to the request body as-is Returns: - Dict with typed request data following ParallelAISearchRequest spec + Dict with request data following the v1 search request spec """ + params = dict(optional_params) + request_data: ParallelAISearchRequest = {} - # Map query to objective (string or list both become objective) if isinstance(query, list): - request_data["objective"] = self._transform_query_to_objective(query) + request_data["search_queries"] = query else: + request_data["search_queries"] = [query] request_data["objective"] = query - # Transform Perplexity unified spec parameters to Parallel AI format - if "max_results" in optional_params: - request_data["max_results"] = optional_params["max_results"] + mode = params.pop("mode", None) + processor = params.pop("processor", None) + if mode is None and processor is not None: + mode = LEGACY_PROCESSOR_TO_MODE.get(processor, processor) + # the v1 API defaults to 'advanced' when mode is omitted; default to 'basic' + # instead to keep v1beta's default tier (processor 'base') and litellm's + # $0.004/query cost map entry for `parallel_ai/search` accurate + request_data["mode"] = mode or "basic" + + advanced_settings: _ParallelAIAdvancedSettings = {} + + if "max_results" in params: + advanced_settings["max_results"] = params.pop("max_results") + + if "country" in params: + advanced_settings["location"] = params.pop("country") + + if "max_chars_per_result" in params: + advanced_settings["excerpt_settings"] = { + "max_chars_per_result": params.pop("max_chars_per_result") + } - # Map domain filters to source_policy source_policy: _ParallelAISourcePolicy = {} - if "search_domain_filter" in optional_params: - source_policy["allowed_domains"] = optional_params["search_domain_filter"] + if "search_domain_filter" in params: + source_policy["include_domains"] = params.pop("search_domain_filter") - if "exclude_domains" in optional_params: - source_policy["disallowed_domains"] = optional_params["exclude_domains"] + if "exclude_domains" in params: + source_policy["exclude_domains"] = params.pop("exclude_domains") if source_policy: - request_data["source_policy"] = source_policy + advanced_settings["source_policy"] = source_policy - # Convert to dict before dynamic key assignments - result_data = dict(request_data) + advanced_settings.update(params.pop("advanced_settings", {})) - # pass through all other parameters as-is - for param, value in optional_params.items(): - if ( - param not in self.get_supported_perplexity_optional_params() - and param not in result_data - ): - result_data[param] = value + if advanced_settings: + request_data["advanced_settings"] = advanced_settings + # unified-spec param with no v1 equivalent + params.pop("max_tokens_per_page", None) + + result_data: Dict = dict(request_data) + result_data.update(params) return result_data def transform_search_response( @@ -177,36 +187,27 @@ class ParallelAISearchConfig(BaseSearchConfig): **kwargs, ) -> SearchResponse: """ - Transform Parallel AI API response to LiteLLM unified SearchResponse format. + Transform Parallel AI v1 API response to LiteLLM unified SearchResponse format. - Parallel AI → LiteLLM mappings: - - results[].title → SearchResult.title - - results[].url → SearchResult.url - - results[].excerpts (array) → SearchResult.snippet (joined string) - - No date/last_updated fields in Parallel AI response (set to None) - - Args: - raw_response: Raw httpx response from Parallel AI API - logging_obj: Logging object for tracking - - Returns: - SearchResponse with standardized format + Parallel AI -> LiteLLM mappings: + - results[].title -> SearchResult.title + - results[].url -> SearchResult.url + - results[].excerpts (array) -> SearchResult.snippet (joined string) + - results[].publish_date -> SearchResult.date """ response_json = raw_response.json() - # Transform results to SearchResult objects results = [] for result in response_json.get("results", []): - # Join excerpts array into a single snippet string - excerpts = result.get("excerpts", []) + excerpts = result.get("excerpts") or [] snippet = " ... ".join(excerpts) if excerpts else "" search_result = SearchResult( - title=result.get("title", ""), - url=result.get("url", ""), + title=result.get("title") or "", + url=result.get("url") or "", snippet=snippet, - date=None, # Parallel AI doesn't provide date in response - last_updated=None, # Parallel AI doesn't provide last_updated in response + date=result.get("publish_date"), + last_updated=None, ) results.append(search_result) diff --git a/litellm/llms/pass_through/guardrail_translation/__init__.py b/litellm/llms/pass_through/guardrail_translation/__init__.py index db69c8e378a..46fea242c13 100644 --- a/litellm/llms/pass_through/guardrail_translation/__init__.py +++ b/litellm/llms/pass_through/guardrail_translation/__init__.py @@ -1,15 +1,18 @@ """Pass-Through Endpoint guardrail translation handler.""" from litellm.llms.pass_through.guardrail_translation.handler import ( + LlmPassthroughRouteHandler, PassThroughEndpointHandler, ) from litellm.types.utils import CallTypes guardrail_translation_mappings = { CallTypes.pass_through: PassThroughEndpointHandler, + CallTypes.allm_passthrough_route: LlmPassthroughRouteHandler, } __all__ = [ "guardrail_translation_mappings", + "LlmPassthroughRouteHandler", "PassThroughEndpointHandler", ] diff --git a/litellm/llms/pass_through/guardrail_translation/handler.py b/litellm/llms/pass_through/guardrail_translation/handler.py index a8cc42d7c54..db8d519d9be 100644 --- a/litellm/llms/pass_through/guardrail_translation/handler.py +++ b/litellm/llms/pass_through/guardrail_translation/handler.py @@ -6,7 +6,7 @@ It uses the field targeting configuration from litellm_logging_obj to extract specific fields for guardrail processing. """ -from typing import TYPE_CHECKING, Any, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type from litellm._logging import verbose_proxy_logger from litellm.llms.base_llm.guardrail_translation.base_translation import BaseTranslation @@ -16,6 +16,8 @@ from litellm.types.utils import GenericGuardrailAPIInputs if TYPE_CHECKING: from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj + from litellm.proxy._types import UserAPIKeyAuth + from litellm.proxy.utils import ProxyLogging class PassThroughEndpointHandler(BaseTranslation): @@ -208,3 +210,128 @@ class PassThroughEndpointHandler(BaseTranslation): ) return response + + +_PROVIDER_HANDLERS: Dict[str, Type[BaseTranslation]] = {} + + +def _get_provider_handlers() -> Dict[str, Type[BaseTranslation]]: + global _PROVIDER_HANDLERS + if not _PROVIDER_HANDLERS: + from litellm.llms.bedrock.passthrough.guardrail_translation.handler import ( + BedrockPassthroughGuardrailHandler, + ) + + _PROVIDER_HANDLERS = {"bedrock": BedrockPassthroughGuardrailHandler} + return _PROVIDER_HANDLERS + + +class LlmPassthroughRouteHandler(BaseTranslation): + """ + Dispatcher for allm_passthrough_route guardrail translation. + + Routes to a per-provider handler based on data["custom_llm_provider"]. + Unknown providers are skipped with a debug log. + """ + + async def process_input_messages( + self, + data: dict, + guardrail_to_apply: "CustomGuardrail", + litellm_logging_obj: Optional["LiteLLMLoggingObj"] = None, + ) -> Any: + provider = data.get("custom_llm_provider") + handler_cls = _get_provider_handlers().get(provider or "") + if handler_cls is None: + verbose_proxy_logger.debug( + "LlmPassthroughRouteHandler: no handler for provider=%s, skipping guardrail", + provider, + ) + return data + return await handler_cls().process_input_messages( + data=data, + guardrail_to_apply=guardrail_to_apply, + litellm_logging_obj=litellm_logging_obj, + ) + + async def process_output_response( + self, + response: Any, + guardrail_to_apply: "CustomGuardrail", + litellm_logging_obj: Optional["LiteLLMLoggingObj"] = None, + user_api_key_dict: Optional[Any] = None, + request_data: Optional[dict] = None, + ) -> Any: + provider = (request_data or {}).get("custom_llm_provider") + handler_cls = _get_provider_handlers().get(provider or "") + if handler_cls is None: + verbose_proxy_logger.debug( + "LlmPassthroughRouteHandler: no handler for provider=%s, skipping guardrail", + provider, + ) + return response + return await handler_cls().process_output_response( + response=response, + guardrail_to_apply=guardrail_to_apply, + litellm_logging_obj=litellm_logging_obj, + user_api_key_dict=user_api_key_dict, + request_data=request_data, + ) + + @staticmethod + def is_event_stream_response(provider: Optional[str], content_type: str) -> bool: + handler_cls = _get_provider_handlers().get(provider or "") + detector = getattr(handler_cls, "is_event_stream_content_type", None) + if detector is None: + return False + return detector(content_type) + + @staticmethod + def event_stream_media_type(provider: Optional[str]) -> Optional[str]: + handler_cls = _get_provider_handlers().get(provider or "") + getter = getattr(handler_cls, "event_stream_media_type", None) + if getter is None: + return None + return getter() + + @staticmethod + def _resolve_event_stream_de_anonymizer(provider: Optional[str]): + handler_cls = _get_provider_handlers().get(provider or "") + return getattr(handler_cls, "de_anonymize_event_stream", None) + + @staticmethod + def supports_event_stream_de_anonymization( + provider: Optional[str], endpoint: Optional[str] + ) -> bool: + handler_cls = _get_provider_handlers().get(provider or "") + endpoint_check = getattr( + handler_cls, "event_stream_endpoint_is_de_anonymizable", None + ) + if endpoint_check is None: + return False + return endpoint_check(endpoint or "") + + @staticmethod + async def de_anonymize_event_stream( + body_bytes: bytes, + proxy_logging_obj: "ProxyLogging", + user_api_key_dict: "UserAPIKeyAuth", + data: dict, + ) -> bytes: + provider = data.get("custom_llm_provider") + de_anonymize = LlmPassthroughRouteHandler._resolve_event_stream_de_anonymizer( + provider + ) + if de_anonymize is None: + verbose_proxy_logger.debug( + "LlmPassthroughRouteHandler: no event-stream handler for provider=%s, " + "leaving stream unmodified", + provider, + ) + return body_bytes + return await de_anonymize( + body_bytes=body_bytes, + proxy_logging_obj=proxy_logging_obj, + user_api_key_dict=user_api_key_dict, + data=data, + ) diff --git a/litellm/llms/perplexity/cost_calculator.py b/litellm/llms/perplexity/cost_calculator.py index 0f9c3cad841..bf055f91aa0 100644 --- a/litellm/llms/perplexity/cost_calculator.py +++ b/litellm/llms/perplexity/cost_calculator.py @@ -58,11 +58,8 @@ def cost_per_token(model: str, usage: Usage) -> Tuple[float, float]: ## CALCULATE OUTPUT COST output_cost_per_token = _safe_float_cast(model_info.get("output_cost_per_token")) - completion_cost: float = (usage.completion_tokens or 0) * output_cost_per_token - ## ADD REASONING TOKENS COST (if present) reasoning_tokens = getattr(usage, "reasoning_tokens", 0) or 0 - # Also check completion_tokens_details if reasoning_tokens is not directly available if ( reasoning_tokens == 0 and hasattr(usage, "completion_tokens_details") @@ -73,9 +70,19 @@ def cost_per_token(model: str, usage: Usage) -> Tuple[float, float]: ) reasoning_cost_value = model_info.get("output_cost_per_reasoning_token") + + # `completion_tokens` includes `reasoning_tokens` per the OpenAI/Perplexity usage + # convention (codified for the central path in PR #18607). When a reasoning rate is + # configured we subtract before the output-rate multiplication so the reasoning + # tokens are not billed twice. if reasoning_tokens > 0 and reasoning_cost_value is not None: - reasoning_cost_per_token = _safe_float_cast(reasoning_cost_value) - completion_cost += reasoning_tokens * reasoning_cost_per_token + non_reasoning_completion_tokens = max( + 0, (usage.completion_tokens or 0) - reasoning_tokens + ) + completion_cost: float = non_reasoning_completion_tokens * output_cost_per_token + completion_cost += reasoning_tokens * _safe_float_cast(reasoning_cost_value) + else: + completion_cost = (usage.completion_tokens or 0) * output_cost_per_token ## ADD SEARCH QUERIES COST (if present) num_search_queries = 0 diff --git a/litellm/llms/predibase/chat/transformation.py b/litellm/llms/predibase/chat/transformation.py index 3d251d24b0d..ce004f60bfc 100644 --- a/litellm/llms/predibase/chat/transformation.py +++ b/litellm/llms/predibase/chat/transformation.py @@ -129,7 +129,7 @@ class PredibaseConfig(BaseConfig): optional_params["response_format"] = value return optional_params - def transform_response( # noqa: PLR0915 + def transform_response( self, model: str, raw_response: Response, diff --git a/litellm/llms/sagemaker/completion/handler.py b/litellm/llms/sagemaker/completion/handler.py index de7be18e8ba..aa4663666c2 100644 --- a/litellm/llms/sagemaker/completion/handler.py +++ b/litellm/llms/sagemaker/completion/handler.py @@ -138,7 +138,7 @@ class SagemakerLLM(BaseAWSLLM): return prepped_request - def completion( # noqa: PLR0915 + def completion( self, model: str, messages: list, diff --git a/litellm/llms/snowflake/chat/transformation.py b/litellm/llms/snowflake/chat/transformation.py index 23bb6f44757..ed30522876a 100644 --- a/litellm/llms/snowflake/chat/transformation.py +++ b/litellm/llms/snowflake/chat/transformation.py @@ -1,17 +1,32 @@ """ -Support for Snowflake REST API +Snowflake Cortex REST API — Chat Transformation + +Routes to native Cortex REST API endpoints based on model: + - Claude models → POST /api/v2/cortex/v1/messages (Anthropic format) + - All other models → POST /api/v2/cortex/v1/chat/completions (OpenAI format) + +Ref: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-rest-api """ import json -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional import httpx -from litellm.types.llms.openai import AllMessageValues -from litellm.types.utils import ChatCompletionMessageToolCall, Function, ModelResponse +from litellm.types.llms.openai import AllMessageValues, ChatCompletionToolCallChunk +from litellm.types.utils import ( + ChatCompletionMessageToolCall, + ChatCompletionUsageBlock, + Choices, + Function, + GenericStreamingChunk, + Message, + ModelResponse, + Usage, +) +from ...base_llm.base_model_iterator import BaseModelResponseIterator from ...openai_like.chat.transformation import OpenAIGPTConfig - from ..utils import SnowflakeBaseConfig if TYPE_CHECKING: @@ -21,69 +36,343 @@ if TYPE_CHECKING: else: LiteLLMLoggingObj = Any +ANTHROPIC_VERSION = "2023-06-01" + +_CLAUDE_MODEL_PREFIXES = ( + "claude-", + "claude_", +) + + +def _is_claude_model(model: str) -> bool: + """Return True if model name (after stripping snowflake/ prefix) is a Claude model.""" + name = model.lower().removeprefix("snowflake/") + return any(name.startswith(p) for p in _CLAUDE_MODEL_PREFIXES) + class SnowflakeConfig(SnowflakeBaseConfig, OpenAIGPTConfig): """ - Reference: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-llm-rest-api + Snowflake Cortex REST API — unified provider. - Snowflake Cortex LLM REST API supports function calling with specific models (e.g., Claude 3.5 Sonnet). - This config handles transformation between OpenAI format and Snowflake's tool_spec format. + Auto-routes based on model name: + - Claude models → /api/v2/cortex/v1/messages (Anthropic Messages format) + - All others → /api/v2/cortex/v1/chat/completions (OpenAI format) + + Auth: + PAT: api_key="pat/" → X-Snowflake-Authorization-Token-Type: PROGRAMMATIC_ACCESS_TOKEN + JWT: api_key="" → X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT """ @classmethod def get_config(cls): return super().get_config() - def _transform_tool_calls_from_snowflake_to_openai( - self, content_list: List[Dict[str, Any]] - ) -> Tuple[str, Optional[List[ChatCompletionMessageToolCall]]]: + def get_supported_openai_params(self, model: str) -> List[str]: + params = [ + "temperature", + "max_tokens", + "max_completion_tokens", + "top_p", + "stream", + "tools", + "tool_choice", + ] + if _is_claude_model(model): + params.append("thinking") + return params + + 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: + api_base = self._get_api_base(api_base, optional_params) + if _is_claude_model(model): + return f"{api_base}/cortex/v1/messages" + return f"{api_base}/cortex/v1/chat/completions" + + 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: + headers = super().validate_environment( + headers=headers, + model=model, + messages=messages, + optional_params=optional_params, + litellm_params=litellm_params, + api_key=api_key, + api_base=api_base, + ) + if _is_claude_model(model): + headers["anthropic-version"] = ANTHROPIC_VERSION + return headers + + def _transform_tools_to_anthropic(self, tools: List[Dict]) -> List[Dict]: """ - Transform Snowflake tool calls to OpenAI format. + Convert tools from OpenAI format to Anthropic format. - Args: - content_list: Snowflake's content_list array containing text and tool_use items + OpenAI: {"type": "function", "function": {"name": ..., "parameters": {...}}} + Anthropic: {"name": ..., "description": ..., "input_schema": {...}} + """ + anthropic_tools = [] + for tool in tools: + if tool.get("type") == "function" and "function" in tool: + func = tool["function"] + anthropic_tool: Dict[str, Any] = { + "name": func.get("name", ""), + } + if "description" in func: + anthropic_tool["description"] = func["description"] + if "parameters" in func: + anthropic_tool["input_schema"] = func["parameters"] + else: + anthropic_tool["input_schema"] = { + "type": "object", + "properties": {}, + } + anthropic_tools.append(anthropic_tool) + else: + anthropic_tools.append(tool) + return anthropic_tools - Returns: - Tuple of (text_content, tool_calls) + def _extract_system_and_messages( + self, messages: List[AllMessageValues] + ) -> tuple[Optional[str], List[Dict]]: + """ + Split messages into system prompt and conversation turns for Anthropic format. - Snowflake format in content_list: - { - "type": "tool_use", - "tool_use": { - "tool_use_id": "tooluse_...", - "name": "get_weather", - "input": {"location": "Paris"} - } + - system messages → collected and joined (preserves guardrail prompts) + - assistant messages with tool_calls → tool_use content blocks + - tool role messages → user role with tool_result content blocks + """ + system_parts: List[str] = [] + conversation: List[Dict] = [] + + for msg in messages: + if isinstance(msg, dict): + role = msg.get("role", "") + content: Any = msg.get("content", "") + else: + role = getattr(msg, "role", "") + content = getattr(msg, "content", "") + + if role == "system": + if isinstance(content, str) and content: + system_parts.append(content) + elif isinstance(content, list): + system_parts.append( + "\n".join( + b.get("text", "") + for b in content + if b.get("type") == "text" + ) + ) + elif role == "assistant": + tool_calls = ( + msg.get("tool_calls") + if isinstance(msg, dict) + else getattr(msg, "tool_calls", None) + ) + if tool_calls: # type: ignore[truthy-bool] + content_blocks: List[Dict[str, Any]] = [] + if content: + content_blocks.append({"type": "text", "text": content}) + for tc in tool_calls: # type: ignore[attr-defined] + func = ( + tc.get("function", {}) + if isinstance(tc, dict) + else getattr(tc, "function", {}) + ) + tc_id = ( + tc.get("id", "") + if isinstance(tc, dict) + else getattr(tc, "id", "") + ) + func_name = ( + func.get("name", "") + if isinstance(func, dict) + else getattr(func, "name", "") + ) + func_args = ( + func.get("arguments", "{}") + if isinstance(func, dict) + else getattr(func, "arguments", "{}") + ) + try: + input_data = ( + json.loads(func_args) + if isinstance(func_args, str) + else func_args + ) + except (json.JSONDecodeError, TypeError): + input_data = {} + content_blocks.append( + { + "type": "tool_use", + "id": tc_id, + "name": func_name, + "input": input_data, + } + ) + conversation.append( + {"role": "assistant", "content": content_blocks} + ) + else: + conversation.append({"role": "assistant", "content": content}) + elif role == "tool": + tool_call_id = ( + msg.get("tool_call_id", "") + if isinstance(msg, dict) + else getattr(msg, "tool_call_id", "") + ) + tool_content = ( + content if isinstance(content, str) else json.dumps(content) + ) + tool_result_block = { + "type": "tool_result", + "tool_use_id": tool_call_id, + "content": tool_content, + } + if ( + conversation + and conversation[-1]["role"] == "user" + and isinstance(conversation[-1]["content"], list) + and conversation[-1]["content"] + and conversation[-1]["content"][0].get("type") == "tool_result" + ): + conversation[-1]["content"].append(tool_result_block) + else: + conversation.append( + {"role": "user", "content": [tool_result_block]} + ) + else: + conversation.append({"role": role, "content": content}) + + system: Optional[str] = "\n\n".join(system_parts) if system_parts else None + return system, conversation + + def transform_request( + self, + model: str, + messages: List[AllMessageValues], + optional_params: dict, + litellm_params: dict, + headers: dict, + ) -> dict: + stream: bool = optional_params.pop("stream", False) or False + extra_body = optional_params.pop("extra_body", {}) + + if _is_claude_model(model): + return self._transform_request_anthropic( + model, messages, optional_params, stream, extra_body + ) + return self._transform_request_openai( + model, messages, optional_params, stream, extra_body + ) + + def _transform_request_openai( + self, + model: str, + messages: List[AllMessageValues], + optional_params: dict, + stream: bool, + extra_body: dict, + ) -> dict: + """OpenAI format for /chat/completions endpoint.""" + max_tokens = optional_params.pop("max_tokens", None) + max_completion_tokens = optional_params.pop("max_completion_tokens", None) + resolved_max = max_completion_tokens or max_tokens + + body: dict = { + "model": model.removeprefix("snowflake/"), + "messages": messages, + "stream": stream, + **optional_params, + **extra_body, } - OpenAI format (returned tool_calls): - ChatCompletionMessageToolCall( - id="tooluse_...", - type="function", - function=Function(name="get_weather", arguments='{"location": "Paris"}') - ) + if resolved_max is not None: + body["max_completion_tokens"] = resolved_max + + return body + + def _transform_tool_choice_to_anthropic(self, tool_choice: Any) -> Dict[str, Any]: """ - text_content = "" - tool_calls: List[ChatCompletionMessageToolCall] = [] + Convert tool_choice from OpenAI format to Anthropic format. - for idx, content_item in enumerate(content_list): - if content_item.get("type") == "text": - text_content += content_item.get("text", "") + OpenAI string values: "auto", "required", "none" + OpenAI dict: {"type": "function", "function": {"name": "..."}} + Anthropic: {"type": "auto"}, {"type": "any"}, {"type": "tool", "name": "..."} + """ + if isinstance(tool_choice, str): + mapping = { + "auto": {"type": "auto"}, + "required": {"type": "any"}, + "none": {"type": "none"}, + } + return mapping.get(tool_choice, {"type": "auto"}) + elif isinstance(tool_choice, dict): + if tool_choice.get("type") == "function": + func = tool_choice.get("function", {}) + return {"type": "tool", "name": func.get("name", "")} + return tool_choice + return {"type": "auto"} - ## TOOL CALLING - elif content_item.get("type") == "tool_use": - tool_use_data = content_item.get("tool_use", {}) - tool_call = ChatCompletionMessageToolCall( - id=tool_use_data.get("tool_use_id", ""), - type="function", - function=Function( - name=tool_use_data.get("name", ""), - arguments=json.dumps(tool_use_data.get("input", {})), - ), - ) - tool_calls.append(tool_call) + def _transform_request_anthropic( + self, + model: str, + messages: List[AllMessageValues], + optional_params: dict, + stream: bool, + extra_body: dict, + ) -> dict: + """Anthropic Messages format for /messages endpoint.""" + system, conversation = self._extract_system_and_messages(messages) - return text_content, tool_calls if tool_calls else None + if "tools" in optional_params: + optional_params["tools"] = self._transform_tools_to_anthropic( + optional_params["tools"] + ) + + if "tool_choice" in optional_params: + optional_params["tool_choice"] = self._transform_tool_choice_to_anthropic( + optional_params["tool_choice"] + ) + + max_completion_tokens = optional_params.pop("max_completion_tokens", None) + if max_completion_tokens and "max_tokens" not in optional_params: + optional_params["max_tokens"] = max_completion_tokens + + model_name = model.removeprefix("snowflake/") + + body: Dict[str, Any] = { + "model": model_name, + "messages": conversation, + "stream": stream, + **optional_params, + **extra_body, + } + + if system is not None: + body["system"] = system + + if "max_tokens" not in body: + body["max_tokens"] = ( + 4096 # reasonable default; Anthropic API max varies by model + ) + + return body def transform_response( self, @@ -99,6 +388,24 @@ class SnowflakeConfig(SnowflakeBaseConfig, OpenAIGPTConfig): api_key: Optional[str] = None, json_mode: Optional[bool] = None, ) -> ModelResponse: + if _is_claude_model(model): + return self._transform_response_anthropic( + model, raw_response, model_response, logging_obj, request_data, messages + ) + return self._transform_response_openai( + model, raw_response, model_response, logging_obj, request_data, messages + ) + + def _transform_response_openai( + self, + model: str, + raw_response: httpx.Response, + model_response: ModelResponse, + logging_obj: LiteLLMLoggingObj, + request_data: dict, + messages: List[AllMessageValues], + ) -> ModelResponse: + """Parse standard OpenAI chat completions response.""" response_json = raw_response.json() logging_obj.post_call( @@ -108,180 +415,278 @@ class SnowflakeConfig(SnowflakeBaseConfig, OpenAIGPTConfig): additional_args={"complete_input_dict": request_data}, ) - ## RESPONSE TRANSFORMATION - # Snowflake returns content_list (not content) with tool_use objects - # We need to transform this to OpenAI's format with content + tool_calls - if "choices" in response_json and len(response_json["choices"]) > 0: - choice = response_json["choices"][0] - if "message" in choice and "content_list" in choice["message"]: - content_list = choice["message"]["content_list"] - ( - text_content, - tool_calls, - ) = self._transform_tool_calls_from_snowflake_to_openai(content_list) - - # Update the choice message with OpenAI format - choice["message"]["content"] = text_content - if tool_calls: - choice["message"]["tool_calls"] = tool_calls - - # Remove Snowflake-specific content_list - del choice["message"]["content_list"] - returned_response = ModelResponse(**response_json) - returned_response.model = "snowflake/" + (returned_response.model or "") if model is not None: returned_response._hidden_params["model"] = model + return returned_response - 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: - """ - If api_base is not provided, use the default DeepSeek /chat/completions endpoint. - """ - - api_base = self._get_api_base(api_base, optional_params) - - return f"{api_base}/cortex/inference:complete" - - def _transform_tools(self, tools: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """ - Transform OpenAI tool format to Snowflake tool format. - - Args: - tools: List of tools in OpenAI format - - Returns: - List of tools in Snowflake format - - OpenAI format: - { - "type": "function", - "function": { - "name": "get_weather", - "description": "...", - "parameters": {...} - } - } - - Snowflake format: - { - "tool_spec": { - "type": "generic", - "name": "get_weather", - "description": "...", - "input_schema": {...} - } - } - """ - snowflake_tools: List[Dict[str, Any]] = [] - for tool in tools: - if tool.get("type") == "function": - function = tool.get("function", {}) - snowflake_tool: Dict[str, Any] = { - "tool_spec": { - "type": "generic", - "name": function.get("name"), - "input_schema": function.get( - "parameters", - {"type": "object", "properties": {}}, - ), - } - } - # Add description if present - if "description" in function: - snowflake_tool["tool_spec"]["description"] = function["description"] - - snowflake_tools.append(snowflake_tool) - - return snowflake_tools - - def _transform_tool_choice( - self, tool_choice: Union[str, Dict[str, Any]] - ) -> Dict[str, Any]: - """ - Transform OpenAI tool_choice format to Snowflake format. - - Snowflake requires tool_choice to be an object, not a string. - Ref: https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/reference/cortex-inference#post--api-v2-cortex-inference-complete-req-body-schema - - Args: - tool_choice: Tool choice in OpenAI format (str or dict) - - Returns: - Tool choice in Snowflake format (always an object, never a string) - - OpenAI format (string): - "auto", "required", "none" - - OpenAI format (dict): - {"type": "function", "function": {"name": "get_weather"}} - - Snowflake format: - {"type": "auto"} / {"type": "any"} / {"type": "none"} - {"type": "tool", "name": ["get_weather"]} - - Snowflake's API (like Anthropic) requires tool_choice as an object - with a "type" field, not as a bare string. - """ - if isinstance(tool_choice, str): - # Snowflake requires object format, not string. - # Map OpenAI string values to Snowflake object format. - # "required" maps to "any" (Snowflake/Anthropic convention). - _type_map = { - "auto": "auto", - "required": "any", - "none": "none", - } - mapped_type = _type_map.get(tool_choice, tool_choice) - return {"type": mapped_type} - - if isinstance(tool_choice, dict): - if tool_choice.get("type") == "function": - function_name = tool_choice.get("function", {}).get("name") - if function_name: - return { - "type": "tool", - "name": [function_name], # Snowflake expects array - } - - return tool_choice - - def transform_request( + def _transform_response_anthropic( self, model: str, + raw_response: httpx.Response, + model_response: ModelResponse, + logging_obj: LiteLLMLoggingObj, + request_data: dict, messages: List[AllMessageValues], - optional_params: dict, - litellm_params: dict, - headers: dict, - ) -> dict: - stream: bool = optional_params.pop("stream", None) or False - extra_body = optional_params.pop("extra_body", {}) + ) -> ModelResponse: + """Parse Anthropic Messages response into OpenAI format.""" + response_json = raw_response.json() - ## TOOL CALLING - # Transform tools from OpenAI format to Snowflake's tool_spec format - tools = optional_params.pop("tools", None) - if tools: - optional_params["tools"] = self._transform_tools(tools) + logging_obj.post_call( + input=messages, + api_key="", + original_response=response_json, + additional_args={"complete_input_dict": request_data}, + ) - # Transform tool_choice from OpenAI format to Snowflake's tool name array format - tool_choice = optional_params.pop("tool_choice", None) - if tool_choice: - optional_params["tool_choice"] = self._transform_tool_choice(tool_choice) + text_content = "" + tool_calls = [] - return { - "model": model, - "messages": messages, - "stream": stream, - **optional_params, - **extra_body, + for block in response_json.get("content", []): + if block.get("type") == "text": + text_content += block.get("text", "") + elif block.get("type") == "tool_use": + tool_calls.append( + ChatCompletionMessageToolCall( + id=block.get("id", ""), + type="function", + function=Function( + name=block.get("name", ""), + arguments=json.dumps(block.get("input", {})), + ), + ) + ) + + _stop_reason_map = { + "end_turn": "stop", + "max_tokens": "length", + "tool_use": "tool_calls", + "stop_sequence": "stop", } + finish_reason = _stop_reason_map.get( + response_json.get("stop_reason", "end_turn"), "stop" + ) + + message = Message(content=text_content or None, role="assistant") + if tool_calls: + message.tool_calls = tool_calls + + choice = Choices( + finish_reason=finish_reason, + index=0, + message=message, + ) + + usage_data = response_json.get("usage", {}) + usage = Usage( + prompt_tokens=usage_data.get("input_tokens", 0), + completion_tokens=usage_data.get("output_tokens", 0), + total_tokens=usage_data.get("input_tokens", 0) + + usage_data.get("output_tokens", 0), + ) + + model_response.choices = [choice] + model_response.usage = usage # type: ignore[attr-defined] + model_response.model = "snowflake/" + response_json.get("model", model) + model_response.id = response_json.get("id", "") + + if model is not None: + model_response._hidden_params["model"] = model + + return model_response + + def get_model_response_iterator( + self, + streaming_response: Any, + sync_stream: bool, + json_mode: Optional[bool] = False, + ) -> Any: + return SnowflakeStreamingHandler( + streaming_response=streaming_response, + sync_stream=sync_stream, + json_mode=json_mode, + ) + + +class SnowflakeStreamingHandler(BaseModelResponseIterator): + """ + Parse streaming events from both Snowflake endpoints. + + - /chat/completions: OpenAI SSE format (has "choices" key) + - /messages: Anthropic SSE format (has "type" key like content_block_delta) + """ + + def __init__( + self, + streaming_response: Any, + sync_stream: bool, + json_mode: Optional[bool] = False, + ): + super().__init__(streaming_response=streaming_response, sync_stream=sync_stream) + self._tool_index = 0 + self._tool_id = "" + self._tool_name = "" + self._input_tokens = 0 + + def chunk_parser(self, chunk: dict) -> GenericStreamingChunk: + if "choices" in chunk: + return self._parse_openai_chunk(chunk) + return self._parse_anthropic_chunk(chunk) + + def _parse_openai_chunk(self, chunk: dict) -> GenericStreamingChunk: + choices = chunk.get("choices", []) + if not choices: + return GenericStreamingChunk( + text="", + is_finished=False, + finish_reason="", + usage=None, + index=0, + tool_use=None, + ) + + choice = choices[0] + delta = choice.get("delta", {}) + finish_reason = choice.get("finish_reason") or "" + text = delta.get("content") or "" + + tool_use = None + tool_calls = delta.get("tool_calls") + if tool_calls: + tc = tool_calls[0] + func = tc.get("function", {}) + tool_use = ChatCompletionToolCallChunk( + id=tc.get("id", ""), + type="function", + function={ + "name": func.get("name", ""), + "arguments": func.get("arguments", ""), + }, + index=tc.get("index", 0), + ) + + return GenericStreamingChunk( + text=text, + is_finished=finish_reason != "", + finish_reason=finish_reason, + usage=None, + index=choice.get("index", 0), + tool_use=tool_use, + ) + + def _parse_anthropic_chunk(self, chunk: dict) -> GenericStreamingChunk: + event_type = chunk.get("type", "") + + if event_type == "message_start": + message = chunk.get("message", {}) + usage_data = message.get("usage", {}) + self._input_tokens = usage_data.get("input_tokens", 0) + return GenericStreamingChunk( + text="", + is_finished=False, + finish_reason="", + usage=None, + index=0, + tool_use=None, + ) + + elif event_type == "content_block_delta": + delta = chunk.get("delta", {}) + delta_type = delta.get("type", "") + + if delta_type == "text_delta": + return GenericStreamingChunk( + text=delta.get("text", ""), + is_finished=False, + finish_reason="", + usage=None, + index=chunk.get("index", 0), + tool_use=None, + ) + elif delta_type == "input_json_delta": + return GenericStreamingChunk( + text="", + is_finished=False, + finish_reason="", + usage=None, + index=chunk.get("index", 0), + tool_use=ChatCompletionToolCallChunk( + id=self._tool_id, + type="function", + function={ + "name": self._tool_name, + "arguments": delta.get("partial_json", ""), + }, + index=self._tool_index, + ), + ) + + elif event_type == "content_block_start": + content_block = chunk.get("content_block", {}) + if content_block.get("type") == "tool_use": + self._tool_id = content_block.get("id", "") + self._tool_name = content_block.get("name", "") + self._tool_index = chunk.get("index", 0) + return GenericStreamingChunk( + text="", + is_finished=False, + finish_reason="", + usage=None, + index=chunk.get("index", 0), + tool_use=ChatCompletionToolCallChunk( + id=self._tool_id, + type="function", + function={"name": self._tool_name, "arguments": ""}, + index=self._tool_index, + ), + ) + + elif event_type == "message_delta": + delta = chunk.get("delta", {}) + stop_reason = delta.get("stop_reason", "") + usage_data = chunk.get("usage", {}) + _stop_map = { + "end_turn": "stop", + "max_tokens": "length", + "tool_use": "tool_calls", + "stop_sequence": "stop", + } + usage = None + if usage_data or self._input_tokens: + output_t = usage_data.get("output_tokens", 0) + input_t = self._input_tokens or usage_data.get("input_tokens", 0) + usage = ChatCompletionUsageBlock( + prompt_tokens=input_t, + completion_tokens=output_t, + total_tokens=input_t + output_t, + ) + return GenericStreamingChunk( + text="", + is_finished=True, + finish_reason=_stop_map.get(stop_reason, "stop"), + usage=usage, + index=0, + tool_use=None, + ) + + elif event_type == "message_stop": + return GenericStreamingChunk( + text="", + is_finished=True, + finish_reason="stop", + usage=None, + index=0, + tool_use=None, + ) + + return GenericStreamingChunk( + text="", + is_finished=False, + finish_reason="", + usage=None, + index=0, + tool_use=None, + ) diff --git a/litellm/llms/tinyfish/search/__init__.py b/litellm/llms/tinyfish/search/__init__.py new file mode 100644 index 00000000000..9777e735aac --- /dev/null +++ b/litellm/llms/tinyfish/search/__init__.py @@ -0,0 +1,3 @@ +from litellm.llms.tinyfish.search.transformation import TinyfishSearchConfig + +__all__ = ["TinyfishSearchConfig"] diff --git a/litellm/llms/tinyfish/search/transformation.py b/litellm/llms/tinyfish/search/transformation.py new file mode 100644 index 00000000000..c4949380e3a --- /dev/null +++ b/litellm/llms/tinyfish/search/transformation.py @@ -0,0 +1,164 @@ +""" +TinyFish Search API. +Endpoint: GET https://api.search.tinyfish.ai +Docs: https://docs.tinyfish.ai/search-api +""" + +from __future__ import annotations + +from typing import Literal, TypedDict +from urllib.parse import urlencode + +import httpx +from pydantic import BaseModel, TypeAdapter, ValidationError + +from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj +from litellm.llms.base_llm.search.transformation import ( + BaseSearchConfig, + SearchResponse, + SearchResult, +) +from litellm.secret_managers.main import get_secret_str + + +class _TinyfishSearchRequestRequired(TypedDict): + query: str + + +class TinyfishSearchRequest(_TinyfishSearchRequestRequired, total=False): + location: str + language: str + page: int + include_thumbnail: bool + max_results: int + + +class _TinyfishResultItem(BaseModel, frozen=True): + title: str = "" + url: str = "" + snippet: str = "" + + +class _TinyfishApiResponse(BaseModel, frozen=True): + results: tuple[_TinyfishResultItem, ...] = () + + +_UrlEncodableParams = TypeAdapter(dict[str, str | int | bool]) +_StrList = TypeAdapter(list[str]) +_StrFrozenSet = TypeAdapter(frozenset[str]) + +_TINYFISH_PARAMS_KEY = "_tinyfish_params" + + +class TinyfishSearchConfig(BaseSearchConfig): + TINYFISH_API_BASE = "https://api.search.tinyfish.ai" + + @staticmethod + def ui_friendly_name() -> str: + return "TinyFish" + + def get_http_method(self) -> Literal["GET", "POST"]: + return "GET" + + def validate_environment( + self, + headers: dict[str, str], + api_key: str | None = None, + api_base: str | None = None, + **kwargs: object, + ) -> dict[str, str]: + resolved_key = api_key or get_secret_str("TINYFISH_API_KEY") + if not resolved_key: + raise ValueError( + "TINYFISH_API_KEY is not set. Set `TINYFISH_API_KEY` environment variable." + ) + return {**headers, "X-API-Key": resolved_key, "Accept": "application/json"} + + def get_complete_url( + self, + api_base: str | None, + optional_params: dict[str, object], + data: dict[str, object] | list[dict[str, object]] | None = None, + **kwargs: object, + ) -> str: + resolved_base = ( + api_base or get_secret_str("TINYFISH_API_BASE") or self.TINYFISH_API_BASE + ) + if isinstance(data, dict) and _TINYFISH_PARAMS_KEY in data: + validated_params = _UrlEncodableParams.validate_python( + data[_TINYFISH_PARAMS_KEY] + ) + return f"{resolved_base}?{urlencode(validated_params, doseq=True)}" + return resolved_base + + def transform_search_request( + self, + query: str | list[str], + optional_params: dict[str, object], + **kwargs: object, + ) -> dict[str, object]: + resolved_query = " ".join(query) if isinstance(query, list) else query + + request_data: TinyfishSearchRequest = {"query": resolved_query} + + country = optional_params.get("country") + if isinstance(country, str): + request_data["location"] = country + + raw_max = optional_params.get("max_results") + if isinstance(raw_max, (int, float, str)): + request_data["max_results"] = max(1, min(int(raw_max), 20)) + + try: + domains = _StrList.validate_python( + optional_params.get("search_domain_filter") + ) + except (ValidationError, TypeError): + domains = [] + if domains: + request_data["query"] = _append_domain_filters( + request_data["query"], domains + ) + + result_data: dict[str, object] = dict(request_data) + + raw_supported: object = ( + self.get_supported_perplexity_optional_params() # any-ok: base class returns bare set + ) + supported_perplexity = _StrFrozenSet.validate_python(raw_supported) + for param, value in optional_params.items(): + if param not in supported_perplexity and param not in result_data: + result_data[param] = value + + return {_TINYFISH_PARAMS_KEY: result_data} + + def transform_search_response( + self, + raw_response: httpx.Response, + logging_obj: LiteLLMLoggingObj | None, + **kwargs: object, + ) -> SearchResponse: + raw_json: object = raw_response.json() # any-ok: httpx Response.json() -> Any + parsed = _TinyfishApiResponse.model_validate(raw_json) + + max_results_str: str = "20" + if raw_response.request: + raw_param: object = ( + raw_response.request.url.params.get( # any-ok: httpx QueryParams.get() -> Any + "max_results", "20" + ) + ) + max_results_str = str(raw_param) + max_results: int = min(int(max_results_str), 20) + + results = [ + SearchResult(title=item.title, url=item.url, snippet=item.snippet) + for item in parsed.results[:max_results] + ] + + return SearchResponse(results=results, object="search") + + +def _append_domain_filters(query: str, domains: list[str]) -> str: + domain_clauses = " OR ".join(f"site:{d}" for d in domains) + return f"({query}) ({domain_clauses})" diff --git a/litellm/llms/vertex_ai/common_utils.py b/litellm/llms/vertex_ai/common_utils.py index e6e39651109..5028c0cf5c8 100644 --- a/litellm/llms/vertex_ai/common_utils.py +++ b/litellm/llms/vertex_ai/common_utils.py @@ -12,7 +12,11 @@ from litellm.litellm_core_utils.prompt_templates.common_utils import unpack_defs from litellm.llms.base_llm.base_utils import BaseLLMModelInfo, BaseTokenCounter from litellm.llms.base_llm.chat.transformation import BaseLLMException from litellm.types.llms.openai import AllMessageValues -from litellm.types.llms.vertex_ai import PartType, Schema +from litellm.types.llms.vertex_ai import ( + VERTEX_AI_PROVIDER_METADATA_FIELDS, + PartType, + Schema, +) from litellm.types.utils import TokenCountResponse from litellm.utils import supports_response_schema, supports_system_messages @@ -27,6 +31,47 @@ class VertexAIError(BaseLLMException): super().__init__(message=message, status_code=status_code, headers=headers) +def redact_vertex_ai_metadata_from_logged_object(obj: Any) -> None: + if isinstance(obj, dict): + for field in VERTEX_AI_PROVIDER_METADATA_FIELDS: + if field in obj: + obj[field] = [] + hidden_params = obj.get("_hidden_params") + if isinstance(hidden_params, dict): + for field in VERTEX_AI_PROVIDER_METADATA_FIELDS: + hidden_params.pop(field, None) + return + + for field in VERTEX_AI_PROVIDER_METADATA_FIELDS: + if hasattr(obj, field): + setattr(obj, field, []) + hidden_params = getattr(obj, "_hidden_params", None) + if isinstance(hidden_params, dict): + for field in VERTEX_AI_PROVIDER_METADATA_FIELDS: + hidden_params.pop(field, None) + + +def redact_vertex_ai_metadata_from_litellm_params(model_call_details: dict) -> None: + """ + success_handler() merges response._hidden_params into + litellm_params.metadata['hidden_params'] before redaction runs, so the Vertex + metadata must be scrubbed from that copy too. + """ + litellm_params = model_call_details.get("litellm_params") + if not isinstance(litellm_params, dict): + return + + for metadata_key in ("metadata", "litellm_metadata"): + metadata = litellm_params.get(metadata_key) + if not isinstance(metadata, dict): + continue + hidden_params = metadata.get("hidden_params") + if not isinstance(hidden_params, dict): + continue + for field in VERTEX_AI_PROVIDER_METADATA_FIELDS: + hidden_params.pop(field, None) + + def vertex_request_labels_from_litellm_params( litellm_params: Optional[dict], ) -> Optional[Dict[str, str]]: @@ -226,7 +271,7 @@ def supports_response_json_schema(model: str) -> bool: # Gemini 2.0+ and 2.5+ models support responseJsonSchema # Pattern matches: gemini-2.0-*, gemini-2.5-*, gemini-3-*, etc. - gemini_2_plus_pattern = re.compile(r"gemini-([2-9]|[1-9]\d+)\.") + gemini_2_plus_pattern = re.compile(r"gemini-(?:[2-9]|[1-9]\d+)(?:\.|\-)") return bool(gemini_2_plus_pattern.search(model_lower)) 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 e9f08f403f9..103801a1e8d 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 @@ -19,7 +19,7 @@ from litellm.types.llms.vertex_ai import ( VertexAICachedContentResponseObject, ) -from ..common_utils import VertexAIError +from ..common_utils import VertexAIError, get_vertex_base_url from ..vertex_llm_base import VertexBase from .transformation import ( separate_cached_messages, @@ -69,17 +69,13 @@ class ContextCachingEndpoints(VertexBase): elif custom_llm_provider == "vertex_ai": auth_header = vertex_auth_header endpoint = "cachedContents" - if vertex_location == "global": - url = f"https://aiplatform.googleapis.com/v1/projects/{vertex_project}/locations/{vertex_location}/{endpoint}" - else: - url = f"https://{vertex_location}-aiplatform.googleapis.com/v1/projects/{vertex_project}/locations/{vertex_location}/{endpoint}" + base_url = get_vertex_base_url(vertex_location) + url = f"{base_url}/v1/projects/{vertex_project}/locations/{vertex_location}/{endpoint}" else: auth_header = vertex_auth_header endpoint = "cachedContents" - if vertex_location == "global": - url = f"https://aiplatform.googleapis.com/v1beta1/projects/{vertex_project}/locations/{vertex_location}/{endpoint}" - else: - url = f"https://{vertex_location}-aiplatform.googleapis.com/v1beta1/projects/{vertex_project}/locations/{vertex_location}/{endpoint}" + base_url = get_vertex_base_url(vertex_location) + url = f"{base_url}/v1beta1/projects/{vertex_project}/locations/{vertex_location}/{endpoint}" return self._check_custom_proxy( api_base=api_base, diff --git a/litellm/llms/vertex_ai/gemini/transformation.py b/litellm/llms/vertex_ai/gemini/transformation.py index c578d6cd28b..f5a2b268263 100644 --- a/litellm/llms/vertex_ai/gemini/transformation.py +++ b/litellm/llms/vertex_ai/gemini/transformation.py @@ -678,7 +678,7 @@ def check_if_part_exists_in_parts( return False -def _gemini_convert_messages_with_history( # noqa: PLR0915 +def _gemini_convert_messages_with_history( messages: List[AllMessageValues], model: Optional[str] = None, litellm_params: Optional[dict] = None, @@ -1176,7 +1176,7 @@ def _rewrite_google_maps_response_format(data: RequestBody) -> None: _rewrite_mime_type_to_response_format(generation_config) -def _transform_request_body( # noqa: PLR0915 +def _transform_request_body( messages: List[AllMessageValues], model: str, optional_params: dict, 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 5cd02293f14..c171538b9c0 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 @@ -63,6 +63,7 @@ from litellm.types.llms.openai import ( OpenAIChatCompletionFinishReason, ) from litellm.types.llms.vertex_ai import ( + VERTEX_AI_PROVIDER_METADATA_FIELDS, VERTEX_CREDENTIALS_TYPES, Candidates, ContentType, @@ -613,9 +614,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): return googleSearch, googleSearchRetrieval, enterpriseWebSearch, urlContext - def _map_function( # noqa: PLR0915 - self, value: List[dict], optional_params: dict - ) -> List[Tools]: + def _map_function(self, value: List[dict], optional_params: dict) -> List[Tools]: """ Map OpenAI-style tools/functions to Vertex AI format. @@ -1111,6 +1110,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): { "voice": "alloy", "format": "mp3", + "language_code": "en-US", } Expected output: @@ -1119,7 +1119,8 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): prebuiltVoiceConfig: { voiceName: "alloy", } - } + }, + languageCode: "en-US", } """ from litellm.types.llms.vertex_ai import ( @@ -1145,6 +1146,9 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): voice_config: VoiceConfig = {"prebuiltVoiceConfig": prebuilt_voice_config} speech_config["voiceConfig"] = voice_config + if "language_code" in value: + speech_config["languageCode"] = value["language_code"] + return cast(dict, speech_config) @staticmethod @@ -1167,7 +1171,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): optional_params["include_server_side_tool_invocations"] = True return - def map_openai_params( # noqa: PLR0915 + def map_openai_params( self, non_default_params: Dict, optional_params: Dict, @@ -1898,7 +1902,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): return False @staticmethod - def _calculate_usage( # noqa: PLR0915 + def _calculate_usage( completion_response: Union[ GenerateContentResponseBody, BidiGenerateContentServerMessage ], @@ -2253,6 +2257,71 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): citation_metadata, ) + @staticmethod + def _get_stream_chunk_attr(chunk: Any, field_name: str) -> Any: + if isinstance(chunk, dict): + value = chunk.get(field_name) + if value is not None: + return value + model_extra = chunk.get("model_extra") + if isinstance(model_extra, dict): + value = model_extra.get(field_name) + if value is not None: + return value + hidden_params = chunk.get("_hidden_params") + if isinstance(hidden_params, dict): + return hidden_params.get(field_name) + return None + return getattr(chunk, field_name, None) + + @staticmethod + def _set_stream_metadata_on_response( + model_response: Any, + grounding_metadata: List[dict], + url_context_metadata: List[dict], + safety_ratings: List[dict], + citation_metadata: List[dict], + ) -> None: + setattr(model_response, "vertex_ai_grounding_metadata", grounding_metadata) # type: ignore + if grounding_metadata: + model_response._hidden_params["vertex_ai_grounding_metadata"] = ( + grounding_metadata + ) + setattr(model_response, "vertex_ai_url_context_metadata", url_context_metadata) # type: ignore + if url_context_metadata: + model_response._hidden_params["vertex_ai_url_context_metadata"] = ( + url_context_metadata + ) + setattr(model_response, "vertex_ai_safety_ratings", safety_ratings) # type: ignore + setattr(model_response, "vertex_ai_safety_results", safety_ratings) # type: ignore + if safety_ratings: + model_response._hidden_params["vertex_ai_safety_ratings"] = safety_ratings + model_response._hidden_params["vertex_ai_safety_results"] = safety_ratings + setattr(model_response, "vertex_ai_citation_metadata", citation_metadata) # type: ignore + if citation_metadata: + model_response._hidden_params["vertex_ai_citation_metadata"] = ( + citation_metadata + ) + + def apply_assembled_streaming_response_metadata( + self, + response: ModelResponse, + chunks: List[Any], + ) -> None: + for field_name in VERTEX_AI_PROVIDER_METADATA_FIELDS: + merged: List[Any] = [] + for chunk in chunks: + value = VertexGeminiConfig._get_stream_chunk_attr(chunk, field_name) + if not value: + continue + if isinstance(value, list): + merged.extend(value) + else: + merged.append(value) + if merged: + setattr(response, field_name, merged) + response._hidden_params[field_name] = merged + @staticmethod def _convert_grounding_metadata_to_annotations( grounding_metadata: List[dict], @@ -2309,7 +2378,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig): return annotations @staticmethod - def _process_candidates( # noqa: PLR0915 + def _process_candidates( _candidates: List[Candidates], model_response: Union[ModelResponse, "ModelResponseStream"], standard_optional_params: dict, @@ -2775,6 +2844,7 @@ async def make_call( sync_stream=False, logging_obj=logging_obj, response_headers=response.headers, + response=response, ) # LOGGING logging_obj.post_call( @@ -2818,6 +2888,7 @@ def make_sync_call( sync_stream=True, logging_obj=logging_obj, response_headers=response.headers, + response=response, ) # LOGGING @@ -3279,12 +3350,14 @@ class ModelResponseIterator: sync_stream: bool, logging_obj: LoggingClass, response_headers: Optional[Dict[str, str]] = None, + response: httpx.Response | None = None, ): from litellm.litellm_core_utils.prompt_templates.common_utils import ( check_is_function_call, ) self.streaming_response = streaming_response + self.response = response self.chunk_type: Literal["valid_json", "accumulated_json"] = "valid_json" self.accumulated_json = "" self.sent_first_chunk = False @@ -3351,14 +3424,18 @@ class ModelResponseIterator: self.has_seen_tool_calls = True break - # Handle final chunk with finishReason but no content. - # _process_candidates skips candidates without "content", - # so the finish_reason from the final chunk is lost. + # _process_candidates skips candidates without a "content" part, so a + # content-less chunk leaves choices empty and the downstream streaming + # handler hits IndexError on choices[0]. This covers the final chunk + # (finishReason, no content) and mid-stream metadata-only chunks + # (grounding/web-search/thought, no content and no finishReason — seen + # with web_search + reasoning) by emitting an empty-delta choice. if not model_response.choices and _candidates: from litellm.types.utils import Delta, StreamingChoices for candidate in _candidates: finish_reason_str = candidate.get("finishReason") + mapped_finish_reason = None if finish_reason_str is not None: if self.has_seen_tool_calls: mapped_finish_reason = "tool_calls" @@ -3366,14 +3443,14 @@ class ModelResponseIterator: mapped_finish_reason = VertexGeminiConfig._check_finish_reason( None, finish_reason_str ) - choice = StreamingChoices( - finish_reason=mapped_finish_reason, - index=candidate.get("index", 0), - delta=Delta(content=None, role=None), - logprobs=None, - enhancements=None, - ) - model_response.choices.append(choice) + choice = StreamingChoices( + finish_reason=mapped_finish_reason, + index=candidate.get("index", 0), + delta=Delta(content=None, role=None), + logprobs=None, + enhancements=None, + ) + model_response.choices.append(choice) # Also handle the case where the final chunk has empty # content (e.g. text:"") WITH finishReason. In this case @@ -3385,10 +3462,13 @@ class ModelResponseIterator: if choice.finish_reason == "stop": choice.finish_reason = "tool_calls" - setattr(model_response, "vertex_ai_grounding_metadata", grounding_metadata) # type: ignore - setattr(model_response, "vertex_ai_url_context_metadata", url_context_metadata) # type: ignore - setattr(model_response, "vertex_ai_safety_ratings", safety_ratings) # type: ignore - setattr(model_response, "vertex_ai_citation_metadata", citation_metadata) # type: ignore + VertexGeminiConfig._set_stream_metadata_on_response( + model_response, + grounding_metadata, + url_context_metadata, + safety_ratings, + citation_metadata, + ) return ( grounding_metadata, @@ -3579,3 +3659,41 @@ class ModelResponseIterator: raise StopAsyncIteration except ValueError as e: raise RuntimeError(f"Error parsing chunk: {e},\nReceived chunk: {chunk}") + + async def aclose(self) -> None: + iterator = getattr( + self, + "async_response_iterator", + self.streaming_response, + ) + if iterator is not None and hasattr(iterator, "aclose"): + try: + await iterator.aclose() + except Exception as e: # noqa: BLE001 + verbose_logger.debug( + "ModelResponseIterator.aclose: error closing iterator: %s", e + ) + if self.response is not None: + try: + await self.response.aclose() + except Exception as e: # noqa: BLE001 + verbose_logger.debug( + "ModelResponseIterator.aclose: error closing response: %s", e + ) + + def close(self) -> None: + iterator = getattr(self, "response_iterator", self.streaming_response) + if iterator is not None and hasattr(iterator, "close"): + try: + iterator.close() + except Exception as e: # noqa: BLE001 + verbose_logger.debug( + "ModelResponseIterator.close: error closing iterator: %s", e + ) + if self.response is not None: + try: + self.response.close() + except Exception as e: # noqa: BLE001 + verbose_logger.debug( + "ModelResponseIterator.close: error closing response: %s", e + ) diff --git a/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py b/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py index 99165c37c93..165dac24903 100644 --- a/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py +++ b/litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py @@ -124,7 +124,7 @@ class GoogleBatchEmbeddings(VertexLLM): return resolved_files - def batch_embeddings( # noqa: PLR0915 + def batch_embeddings( self, model: str, input: GeminiEmbeddingInput, diff --git a/litellm/llms/vertex_ai/image_generation/cost_calculator.py b/litellm/llms/vertex_ai/image_generation/cost_calculator.py index 012de5498cb..5c04ebf79ee 100644 --- a/litellm/llms/vertex_ai/image_generation/cost_calculator.py +++ b/litellm/llms/vertex_ai/image_generation/cost_calculator.py @@ -5,6 +5,7 @@ Vertex AI Image Generation Cost Calculator import litellm from litellm.litellm_core_utils.llm_cost_calc.utils import ( calculate_image_response_cost_from_usage, + calculate_image_response_web_search_cost, ) from litellm.types.utils import ImageResponse @@ -21,16 +22,20 @@ def cost_calculator( custom_llm_provider="vertex_ai", ) + web_search_cost = calculate_image_response_web_search_cost( + image_response=image_response, + custom_llm_provider="vertex_ai", + model_info=_model_info, + ) + token_based_cost = calculate_image_response_cost_from_usage( model=model, image_response=image_response, custom_llm_provider="vertex_ai", ) if token_based_cost is not None: - return token_based_cost + return token_based_cost + web_search_cost output_cost_per_image: float = _model_info.get("output_cost_per_image") or 0.0 - num_images: int = 0 - if image_response.data: - num_images = len(image_response.data) - return output_cost_per_image * num_images + num_images: int = len(image_response.data) if image_response.data else 0 + return output_cost_per_image * num_images + web_search_cost 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 f4bda8d1bed..103c7b2a28a 100644 --- a/litellm/llms/vertex_ai/image_generation/vertex_gemini_transformation.py +++ b/litellm/llms/vertex_ai/image_generation/vertex_gemini_transformation.py @@ -7,6 +7,10 @@ import litellm from litellm.llms.base_llm.image_generation.transformation import ( BaseImageGenerationConfig, ) +from litellm.llms.gemini.common_utils import ( + get_gemini_image_web_search_requests, + map_gemini_image_tools_params, +) from litellm.llms.vertex_ai.common_utils import get_vertex_base_url from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import VertexLLM from litellm.secret_managers.main import get_secret_str @@ -52,6 +56,8 @@ class VertexAIGeminiImageGenerationConfig(BaseImageGenerationConfig, VertexLLM): "aspect_ratio", "imageSize", "image_size", + "tools", + "web_search_options", ] def map_openai_params( @@ -77,9 +83,10 @@ class VertexAIGeminiImageGenerationConfig(BaseImageGenerationConfig, VertexLLM): mapped_params["aspectRatio"] = v elif k in ("imageSize", "image_size"): mapped_params["imageSize"] = v - else: + elif k not in ("tools", "web_search_options"): mapped_params[k] = v + mapped_params = map_gemini_image_tools_params(non_default_params, mapped_params) return mapped_params def _map_size_to_aspect_ratio(self, size: str) -> str: @@ -247,6 +254,11 @@ class VertexAIGeminiImageGenerationConfig(BaseImageGenerationConfig, VertexLLM): "generationConfig": generation_config, } + if tools := optional_params.get("tools"): + request_body["tools"] = tools + if tool_config := optional_params.get("toolConfig"): + request_body["toolConfig"] = tool_config + return request_body def _transform_image_usage(self, usage: dict) -> ImageUsage: @@ -324,4 +336,8 @@ class VertexAIGeminiImageGenerationConfig(BaseImageGenerationConfig, VertexLLM): if usage_metadata := response_data.get("usageMetadata", None): model_response.usage = self._transform_image_usage(usage_metadata) + web_search_requests = get_gemini_image_web_search_requests(response_data) + if web_search_requests and model_response.usage is not None: + setattr(model_response.usage, "web_search_requests", web_search_requests) + return model_response diff --git a/litellm/llms/vertex_ai/realtime/transformation.py b/litellm/llms/vertex_ai/realtime/transformation.py index ea4dbccc8c8..d6441db7856 100644 --- a/litellm/llms/vertex_ai/realtime/transformation.py +++ b/litellm/llms/vertex_ai/realtime/transformation.py @@ -90,7 +90,8 @@ class VertexAIRealtimeConfig(GeminiRealtimeConfig): def get_audio_mime_type(self, input_audio_format: str = "pcm16") -> str: mime_types = { - "pcm16": "audio/pcm;rate=16000", + # Gemini Live native audio (OpenAI GA realtime default) is 24kHz PCM. + "pcm16": "audio/pcm;rate=24000", "g711_ulaw": "audio/pcmu", "g711_alaw": "audio/pcma", } diff --git a/litellm/llms/vertex_ai/vertex_ai_non_gemini.py b/litellm/llms/vertex_ai/vertex_ai_non_gemini.py index cfbab584f6a..c134dee7ad4 100644 --- a/litellm/llms/vertex_ai/vertex_ai_non_gemini.py +++ b/litellm/llms/vertex_ai/vertex_ai_non_gemini.py @@ -77,7 +77,7 @@ def _set_client_in_cache(client_cache_key: str, vertex_llm_model: Any): ) -def completion( # noqa: PLR0915 +def completion( model: str, messages: list, model_response: ModelResponse, @@ -485,7 +485,7 @@ def completion( # noqa: PLR0915 ) -async def async_completion( # noqa: PLR0915 +async def async_completion( llm_model, mode: str, prompt: str, @@ -650,7 +650,7 @@ async def async_completion( # noqa: PLR0915 raise VertexAIError(status_code=500, message=str(e)) -async def async_streaming( # noqa: PLR0915 +async def async_streaming( llm_model, mode: str, prompt: str, 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 1e92754857b..8a92e7ec4a5 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 @@ -17,6 +17,9 @@ from ..output_params_utils import sanitize_vertex_anthropic_output_params class VertexAIPartnerModelsAnthropicMessagesConfig(AnthropicMessagesConfig, VertexBase): + def should_strip_billing_metadata(self) -> bool: + return True + def validate_anthropic_messages_environment( self, headers: dict, diff --git a/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/transformation.py b/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/transformation.py index c852909d475..ae8bdc55443 100644 --- a/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/transformation.py +++ b/litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/transformation.py @@ -52,6 +52,9 @@ class VertexAIAnthropicConfig(AnthropicConfig): def custom_llm_provider(self) -> Optional[str]: return "vertex_ai" + def should_strip_billing_metadata(self) -> bool: + return True + def _add_context_management_beta_headers( self, beta_set: set, context_management: dict ) -> None: diff --git a/litellm/llms/voyage/embedding/transformation_multimodal.py b/litellm/llms/voyage/embedding/transformation_multimodal.py new file mode 100644 index 00000000000..55e221b065b --- /dev/null +++ b/litellm/llms/voyage/embedding/transformation_multimodal.py @@ -0,0 +1,183 @@ +""" +Transform request/response for Voyage multimodal embeddings. + +Voyage multimodal models use /v1/multimodalembeddings and accept `inputs` +containing content blocks, unlike standard Voyage embeddings which use +/v1/embeddings and a string/list `input` field. +""" + +from typing import Any, Dict, List, Optional, Union + +import httpx + +from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj +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, Usage + + +class VoyageMultimodalEmbeddingError(BaseLLMException): + def __init__( + self, + status_code: int, + message: str, + headers: Union[dict, httpx.Headers] = {}, + ): + self.status_code = status_code + self.message = message + self.request = httpx.Request( + method="POST", url="https://api.voyageai.com/v1/multimodalembeddings" + ) + self.response = httpx.Response(status_code=status_code, request=self.request) + super().__init__( + status_code=status_code, + message=message, + headers=headers, + ) + + +class VoyageMultimodalEmbeddingConfig(BaseEmbeddingConfig): + """ + Reference: https://docs.voyageai.com/reference/multimodal-embeddings-api + """ + + @staticmethod + def is_multimodal_embeddings(model: str) -> bool: + return "multimodal" in model.lower() + + 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: + if api_base: + if not api_base.endswith("/multimodalembeddings"): + api_base = f"{api_base}/multimodalembeddings" + return api_base + return "https://api.voyageai.com/v1/multimodalembeddings" + + def get_supported_openai_params(self, model: str) -> list: + return ["dimensions"] + + def map_openai_params( + self, + non_default_params: dict, + optional_params: dict, + model: str, + drop_params: bool, + ) -> dict: + if "dimensions" in non_default_params: + optional_params["output_dimension"] = non_default_params["dimensions"] + 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: + if api_key is None: + api_key = ( + get_secret_str("VOYAGE_API_KEY") + or get_secret_str("VOYAGE_AI_API_KEY") + or get_secret_str("VOYAGE_AI_TOKEN") + ) + if not api_key: + raise ValueError( + "Voyage API key is required for multimodal embeddings. " + "Set VOYAGE_API_KEY / VOYAGE_AI_API_KEY / VOYAGE_AI_TOKEN " + "or pass `api_key` explicitly." + ) + return {"Authorization": f"Bearer {api_key}"} + + def _normalize_content_item(self, item: Dict[str, Any]) -> Dict[str, Any]: + item_type = item.get("type") + if item_type == "image_url": + image_url = item.get("image_url") + if isinstance(image_url, dict): + image_url = image_url.get("url") + if image_url is None: + raise ValueError( + "Voyage multimodal embeddings require a non-empty `image_url`. " + "Got an image content block without a `url`." + ) + if isinstance(image_url, str) and image_url.startswith("data:image/"): + _, _, encoded = image_url.partition(",") + return {"type": "image_base64", "image_base64": encoded} + return {"type": "image_url", "image_url": image_url} + return item + + def _normalize_input_item(self, item: Any) -> Dict[str, Any]: + if isinstance(item, str): + return {"content": [{"type": "text", "text": item}]} + if isinstance(item, dict) and "content" in item: + content = item.get("content") or [] + return { + **item, + "content": [ + self._normalize_content_item(content_item) + for content_item in content + ], + } + return item + + def transform_embedding_request( + self, + model: str, + input: AllEmbeddingInputValues, + optional_params: dict, + headers: dict, + ) -> dict: + inputs = input if isinstance(input, list) else [input] + return { + "inputs": [self._normalize_input_item(item) for item in inputs], + "model": model, + **optional_params, + } + + def transform_embedding_response( + self, + model: str, + raw_response: httpx.Response, + model_response: EmbeddingResponse, + logging_obj: LiteLLMLoggingObj, + api_key: Optional[str] = None, + request_data: dict = {}, + optional_params: dict = {}, + litellm_params: dict = {}, + ) -> EmbeddingResponse: + try: + raw_response_json = raw_response.json() + except Exception: + raise VoyageMultimodalEmbeddingError( + message=raw_response.text, status_code=raw_response.status_code + ) + + model_response.model = raw_response_json.get("model") + model_response.data = raw_response_json.get("data") + model_response.object = raw_response_json.get("object") + + usage_payload = raw_response_json.get("usage", {}) + total_tokens = usage_payload.get("total_tokens", 0) + model_response.usage = Usage( + prompt_tokens=total_tokens, + total_tokens=total_tokens, + ) + return model_response + + def get_error_class( + self, error_message: str, status_code: int, headers: Union[dict, httpx.Headers] + ) -> BaseLLMException: + return VoyageMultimodalEmbeddingError( + message=error_message, status_code=status_code, headers=headers + ) diff --git a/litellm/llms/watsonx/embed/transformation.py b/litellm/llms/watsonx/embed/transformation.py index 930212e3ef3..ae873d63fe9 100644 --- a/litellm/llms/watsonx/embed/transformation.py +++ b/litellm/llms/watsonx/embed/transformation.py @@ -43,8 +43,19 @@ class IBMWatsonXEmbeddingConfig(IBMWatsonXMixin, BaseEmbeddingConfig): api_params=watsonx_api_params, ) + if isinstance(input, str): + inputs: list[str] = [input] + elif isinstance(input, list): + if len(input) > 0 and isinstance(input[0], (list, int)): + raise ValueError( + "WatsonX embeddings require a string or list of strings" + ) + inputs = input + else: + inputs = [input] + return { - "inputs": input, + "inputs": inputs, "parameters": optional_params, **watsonx_auth_payload, } diff --git a/litellm/llms/xai/chat/transformation.py b/litellm/llms/xai/chat/transformation.py index c06928516ef..8019bb67991 100644 --- a/litellm/llms/xai/chat/transformation.py +++ b/litellm/llms/xai/chat/transformation.py @@ -5,6 +5,7 @@ import httpx import litellm from litellm._logging import verbose_logger from litellm.constants import XAI_API_BASE +from litellm.exceptions import AuthenticationError from litellm.litellm_core_utils.prompt_templates.common_utils import ( filter_value_from_dict, strip_name_from_messages, @@ -39,6 +40,72 @@ class XAIChatConfig(OpenAIGPTConfig): dynamic_api_key = XAIModelInfo.get_api_key(api_key) return api_base, dynamic_api_key + 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: + from litellm.llms.xai.oauth import ( + XAIOAuthAuthenticator, + XAIOAuthError, + should_use_xai_oauth, + ) + + dynamic_api_key = XAIModelInfo.get_api_key(api_key) + if should_use_xai_oauth(litellm_params) and not dynamic_api_key: + try: + headers["Authorization"] = ( + f"Bearer {XAIOAuthAuthenticator().get_access_token()}" + ) + except XAIOAuthError as exc: + raise AuthenticationError( + model=model, + llm_provider=self.custom_llm_provider or "xai", + message=str(exc), + ) from exc + if "content-type" not in headers and "Content-Type" not in headers: + headers["Content-Type"] = "application/json" + return headers + + return super().validate_environment( + headers=headers, + model=model, + messages=messages, + optional_params=optional_params, + litellm_params=litellm_params, + api_key=dynamic_api_key, + api_base=api_base, + ) + + 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: + from litellm.llms.xai.oauth import XAIOAuthAuthenticator, should_use_xai_oauth + + dynamic_api_key = XAIModelInfo.get_api_key(api_key) + if should_use_xai_oauth(litellm_params) and not dynamic_api_key: + api_base = XAIOAuthAuthenticator().get_api_base() + + return super().get_complete_url( + api_base=api_base, + api_key=dynamic_api_key, + model=model, + optional_params=optional_params, + litellm_params=litellm_params, + stream=stream, + ) + def get_supported_openai_params(self, model: str) -> list: base_openai_params = [ "logit_bias", diff --git a/litellm/llms/xai/oauth.py b/litellm/llms/xai/oauth.py new file mode 100644 index 00000000000..30c717b7ca0 --- /dev/null +++ b/litellm/llms/xai/oauth.py @@ -0,0 +1,421 @@ +import base64 +import hashlib +import json +import os +import secrets +import sys +import threading +import time +import uuid +import webbrowser +from http.server import BaseHTTPRequestHandler, HTTPServer +from typing import Any, Dict, Optional, Tuple, Union +from urllib.parse import parse_qs, urlencode, urlparse + +import httpx + +from litellm._logging import verbose_logger +from litellm.constants import XAI_API_BASE +from litellm.llms.custom_httpx.http_handler import HTTPHandler, _get_httpx_client +from litellm.secret_managers.main import get_secret_str + +XAI_OAUTH_ISSUER = "https://auth.x.ai" +XAI_OAUTH_DISCOVERY_URL = f"{XAI_OAUTH_ISSUER}/.well-known/openid-configuration" +XAI_OAUTH_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828" +XAI_OAUTH_SCOPE = "openid profile email offline_access grok-cli:access api:access" +XAI_OAUTH_REDIRECT_HOST = "127.0.0.1" +XAI_OAUTH_REDIRECT_PORT = 56121 +XAI_OAUTH_REDIRECT_PATH = "/callback" +XAI_OAUTH_EXPIRY_SKEW_SECONDS = 120 +XAI_OAUTH_CALLBACK_TIMEOUT_SECONDS = 180 +_XAI_OAUTH_REFRESH_LOCK = threading.Lock() + + +class XAIOAuthError(Exception): + pass + + +class XAIOAuthLoginRequiredError(XAIOAuthError): + pass + + +class _CallbackHandler(BaseHTTPRequestHandler): + server: "_CallbackServer" + + def do_GET(self) -> None: + parsed = urlparse(self.path) + if parsed.path != XAI_OAUTH_REDIRECT_PATH: + self.send_response(404) + self.end_headers() + return + + params = parse_qs(parsed.query) + result = { + "code": params.get("code", [None])[0], + "state": params.get("state", [None])[0], + "error": params.get("error", [None])[0], + "error_description": params.get("error_description", [None])[0], + } + self.server.callback_result = result + + if result["state"] != self.server.expected_state: + self.send_response(400) + self.send_header("Content-Type", "text/html; charset=utf-8") + self.end_headers() + self.wfile.write( + b"

xAI authorization state mismatch.

" + ) + return + + self.send_response(200) + self.send_header("Content-Type", "text/html; charset=utf-8") + self.end_headers() + body = ( + b"

xAI authorization failed.

You can close this tab." + if result["error"] + else b"

xAI authorization received.

You can close this tab." + ) + self.wfile.write(body) + + def log_message(self, format: str, *args: Any) -> None: + return + + +class _CallbackServer(HTTPServer): + expected_state: str + callback_result: Optional[Dict[str, Optional[str]]] + + +class XAIOAuthAuthenticator: + def __init__( + self, http_client: Optional[Union[httpx.Client, HTTPHandler]] = None + ) -> None: + self.token_dir = get_secret_str("XAI_OAUTH_TOKEN_DIR") or os.path.expanduser( + "~/.config/litellm/xai_oauth" + ) + self.auth_file = os.path.join( + self.token_dir, get_secret_str("XAI_OAUTH_AUTH_FILE") or "auth.json" + ) + self.http_client = http_client + + def get_api_base(self) -> str: + return ( + get_secret_str("XAI_OAUTH_API_BASE") + or get_secret_str("XAI_API_BASE") + or XAI_API_BASE + ) + + def get_access_token(self) -> str: + auth_data = self._read_auth_file() + if not auth_data: + raise XAIOAuthLoginRequiredError( + "xAI OAuth login required. Run `litellm xai-oauth login`." + ) + + access_token = auth_data.get("access_token") + if access_token and not self._is_expired(auth_data): + return access_token + + refresh_token = auth_data.get("refresh_token") + if not refresh_token: + raise XAIOAuthLoginRequiredError( + "xAI OAuth refresh token missing. Run `litellm xai-oauth login`." + ) + + with _XAI_OAUTH_REFRESH_LOCK: + locked_auth_data = self._read_auth_file() or auth_data + access_token = locked_auth_data.get("access_token") + if access_token and not self._is_expired(locked_auth_data): + return access_token + + refreshed = self._refresh_tokens(locked_auth_data) + return refreshed["access_token"] + + def login(self, force: bool = False, no_browser: bool = False) -> Dict[str, Any]: + existing = self._read_auth_file() + if existing and not force and existing.get("access_token"): + if not self._is_expired(existing): + return existing + if existing.get("refresh_token"): + try: + return self._refresh_tokens(existing) + except XAIOAuthError: + pass + + discovery = self._discover() + verifier, challenge = self._pkce_pair() + state = uuid.uuid4().hex + nonce = uuid.uuid4().hex + server, redirect_uri = self._start_callback_server(state) + authorize_url = self._build_authorize_url( + authorization_endpoint=discovery["authorization_endpoint"], + redirect_uri=redirect_uri, + challenge=challenge, + state=state, + nonce=nonce, + ) + + if no_browser or not webbrowser.open(authorize_url): + sys.stdout.write( + f"Open this URL to authenticate with xAI:\n{authorize_url}\n" + ) + sys.stdout.flush() + + result = self._wait_for_callback(server) + if result.get("state") != state: + raise XAIOAuthError("xAI OAuth state mismatch") + if result.get("error"): + description = result.get("error_description") or result["error"] + raise XAIOAuthError(f"xAI authorization failed: {description}") + code = result.get("code") + if not code: + raise XAIOAuthError("xAI authorization failed: no code returned") + + token_payload = self._exchange_token( + discovery["token_endpoint"], + { + "grant_type": "authorization_code", + "code": code, + "redirect_uri": redirect_uri, + "client_id": XAI_OAUTH_CLIENT_ID, + "code_verifier": verifier, + }, + ) + auth_data = self._build_auth_record(token_payload, discovery["token_endpoint"]) + self._write_auth_file(auth_data) + return auth_data + + def _client(self) -> Union[httpx.Client, HTTPHandler]: + return self.http_client or _get_httpx_client() + + def _ensure_token_dir(self) -> None: + os.makedirs(self.token_dir, mode=0o700, exist_ok=True) + try: + os.chmod(self.token_dir, 0o700) + except OSError: + verbose_logger.debug("Could not chmod xAI OAuth token directory") + + def _read_auth_file(self) -> Optional[Dict[str, Any]]: + try: + with open(self.auth_file, "r") as f: + data = json.load(f) + return data if isinstance(data, dict) else None + except (IOError, json.JSONDecodeError): + return None + + def _write_auth_file(self, data: Dict[str, Any]) -> None: + self._ensure_token_dir() + tmp_file = os.path.join( + self.token_dir, + f".{os.path.basename(self.auth_file)}.{uuid.uuid4().hex}.tmp", + ) + flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL + if hasattr(os, "O_NOFOLLOW"): + flags |= os.O_NOFOLLOW + fd = os.open(tmp_file, flags, 0o600) + try: + with os.fdopen(fd, "w") as f: + json.dump(data, f) + f.flush() + os.fsync(f.fileno()) + os.replace(tmp_file, self.auth_file) + try: + os.chmod(self.auth_file, 0o600) + except OSError: + verbose_logger.debug("Could not chmod xAI OAuth auth file") + except Exception: + try: + os.close(fd) + except OSError: + pass + try: + os.unlink(tmp_file) + except OSError: + pass + raise + + def _is_expired(self, auth_data: Dict[str, Any]) -> bool: + expires_at = auth_data.get("expires_at") + if expires_at is None: + return True + try: + return time.time() >= float(expires_at) - XAI_OAUTH_EXPIRY_SKEW_SECONDS + except (TypeError, ValueError): + return True + + def _discover(self) -> Dict[str, str]: + try: + response = self._client().get( + XAI_OAUTH_DISCOVERY_URL, headers={"Accept": "application/json"} + ) + response.raise_for_status() + except httpx.HTTPStatusError as exc: + raise XAIOAuthError( + f"xAI OAuth discovery request failed: {exc.response.status_code} {exc.response.text}" + ) from exc + try: + data = response.json() + except ValueError as exc: + raise XAIOAuthError( + "xAI OAuth discovery response was not valid JSON" + ) from exc + authorization_endpoint = data.get("authorization_endpoint") + token_endpoint = data.get("token_endpoint") + if not authorization_endpoint or not token_endpoint: + raise XAIOAuthError("xAI OAuth discovery missing endpoints") + return { + "authorization_endpoint": self._validate_xai_endpoint( + authorization_endpoint + ), + "token_endpoint": self._validate_xai_endpoint(token_endpoint), + } + + def _validate_xai_endpoint(self, url: str) -> str: + parsed = urlparse(url) + host = (parsed.hostname or "").lower() + if parsed.scheme != "https" or (host != "x.ai" and not host.endswith(".x.ai")): + raise XAIOAuthError( + f"xAI OAuth discovery returned unexpected endpoint: {url}" + ) + return url + + def _pkce_pair(self) -> Tuple[str, str]: + verifier = ( + base64.urlsafe_b64encode(secrets.token_bytes(32)).rstrip(b"=").decode() + ) + challenge = ( + base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()) + .rstrip(b"=") + .decode() + ) + return verifier, challenge + + def _start_callback_server(self, state: str) -> Tuple[_CallbackServer, str]: + last_error: Optional[OSError] = None + for port in (XAI_OAUTH_REDIRECT_PORT, 0): + try: + server = _CallbackServer( + (XAI_OAUTH_REDIRECT_HOST, port), _CallbackHandler + ) + server.expected_state = state + server.callback_result = None + actual_port = server.server_address[1] + redirect_uri = f"http://{XAI_OAUTH_REDIRECT_HOST}:{actual_port}{XAI_OAUTH_REDIRECT_PATH}" + return server, redirect_uri + except OSError as exc: + last_error = exc + raise XAIOAuthError(f"Could not start xAI OAuth callback server: {last_error}") + + def _build_authorize_url( + self, + authorization_endpoint: str, + redirect_uri: str, + challenge: str, + state: str, + nonce: str, + ) -> str: + params = { + "response_type": "code", + "client_id": XAI_OAUTH_CLIENT_ID, + "redirect_uri": redirect_uri, + "scope": XAI_OAUTH_SCOPE, + "code_challenge": challenge, + "code_challenge_method": "S256", + "state": state, + "nonce": nonce, + } + return f"{authorization_endpoint}?{urlencode(params)}" + + def _wait_for_callback(self, server: _CallbackServer) -> Dict[str, Optional[str]]: + server.timeout = 1 + deadline = time.time() + XAI_OAUTH_CALLBACK_TIMEOUT_SECONDS + try: + while time.time() < deadline: + server.handle_request() + if server.callback_result is not None: + return server.callback_result + finally: + server.server_close() + raise XAIOAuthError("Timed out waiting for xAI OAuth callback") + + def _exchange_token( + self, token_endpoint: str, data: Dict[str, str] + ) -> Dict[str, Any]: + try: + response = self._client().post( + token_endpoint, + headers={ + "Accept": "application/json", + "Content-Type": "application/x-www-form-urlencoded", + }, + data=data, + ) + response.raise_for_status() + except httpx.HTTPStatusError as exc: + raise XAIOAuthError( + f"xAI OAuth token request failed: {exc.response.status_code} {exc.response.text}" + ) from exc + try: + body = response.json() + except ValueError as exc: + raise XAIOAuthError("xAI OAuth token response was not valid JSON") from exc + if not isinstance(body, dict): + raise XAIOAuthError("xAI OAuth token response was not an object") + return body + + def _build_auth_record( + self, + token_payload: Dict[str, Any], + token_endpoint: str, + fallback_refresh_token: Optional[str] = None, + ) -> Dict[str, Any]: + access_token = token_payload.get("access_token") + refresh_token = token_payload.get("refresh_token") or fallback_refresh_token + if not access_token: + raise XAIOAuthError("xAI OAuth token response missing access_token") + if not refresh_token: + raise XAIOAuthError("xAI OAuth token response missing refresh_token") + expires_in = token_payload.get("expires_in") or 3600 + try: + expires_at = int(time.time() + int(expires_in)) + except (TypeError, ValueError): + expires_at = int(time.time() + 3600) + return { + "access_token": access_token, + "refresh_token": refresh_token, + "id_token": token_payload.get("id_token"), + "token_type": token_payload.get("token_type") or "Bearer", + "token_endpoint": token_endpoint, + "expires_at": expires_at, + } + + def _refresh_tokens(self, auth_data: Dict[str, Any]) -> Dict[str, Any]: + token_endpoint = auth_data.get("token_endpoint") + if not token_endpoint: + token_endpoint = self._discover()["token_endpoint"] + token_endpoint = self._validate_xai_endpoint(token_endpoint) + refresh_token = auth_data.get("refresh_token") + if not refresh_token: + raise XAIOAuthLoginRequiredError( + "xAI OAuth refresh token missing. Run `litellm xai-oauth login`." + ) + + token_payload = self._exchange_token( + token_endpoint, + { + "grant_type": "refresh_token", + "refresh_token": refresh_token, + "client_id": XAI_OAUTH_CLIENT_ID, + }, + ) + refreshed = self._build_auth_record( + token_payload, + token_endpoint, + fallback_refresh_token=refresh_token, + ) + self._write_auth_file(refreshed) + return refreshed + + +def should_use_xai_oauth(litellm_params: Optional[Dict[str, Any]]) -> bool: + return bool((litellm_params or {}).get("use_xai_oauth")) diff --git a/litellm/llms/xai/responses/transformation.py b/litellm/llms/xai/responses/transformation.py index 55805ddaede..f81e860a8ce 100644 --- a/litellm/llms/xai/responses/transformation.py +++ b/litellm/llms/xai/responses/transformation.py @@ -3,6 +3,7 @@ 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.exceptions import AuthenticationError from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig from litellm.llms.xai.common_utils import XAIModelInfo from litellm.secret_managers.main import get_secret_str @@ -220,10 +221,27 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): litellm_params.api_key, legacy_generic_before_env=True ) + if not api_key: + from litellm.llms.xai.oauth import ( + XAIOAuthAuthenticator, + XAIOAuthError, + should_use_xai_oauth, + ) + + if should_use_xai_oauth(litellm_params.model_dump()): + try: + api_key = XAIOAuthAuthenticator().get_access_token() + except XAIOAuthError as exc: + raise AuthenticationError( + model=model, + llm_provider=self.custom_llm_provider.value, + message=str(exc), + ) from exc + if not api_key: raise ValueError( "XAI API key is required. Set api_key, litellm.xai_key, " - "litellm.api_key, or XAI_API_KEY." + "litellm.api_key, XAI_API_KEY, or use_xai_oauth=True." ) headers.update( @@ -244,12 +262,20 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): Returns: str: The full URL for the XAI /responses endpoint """ - api_base = ( - api_base - or litellm.api_base - or get_secret_str("XAI_API_BASE") - or XAI_API_BASE + from litellm.llms.xai.oauth import XAIOAuthAuthenticator, should_use_xai_oauth + + api_key = XAIModelInfo.get_api_key( + litellm_params.get("api_key"), legacy_generic_before_env=True ) + if should_use_xai_oauth(litellm_params) and not api_key: + api_base = XAIOAuthAuthenticator().get_api_base() + else: + api_base = ( + api_base + or litellm.api_base + or get_secret_str("XAI_API_BASE") + or XAI_API_BASE + ) # Remove trailing slashes api_base = api_base.rstrip("/") diff --git a/litellm/main.py b/litellm/main.py index 64891e2def9..63c5798e70a 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -86,6 +86,7 @@ from litellm.litellm_core_utils.audio_utils.utils import ( get_audio_file_for_health_check, ) from litellm.litellm_core_utils.completion_timeout import CompletionTimeout +from litellm.litellm_core_utils.get_litellm_params import OPTIONAL_KWARGS_KEYS from litellm.litellm_core_utils.dd_tracing import tracer from litellm.litellm_core_utils.get_provider_specific_headers import ( ProviderSpecificHeaderUtils, @@ -391,7 +392,7 @@ class AsyncCompletions: @tracer.wrap() @client -async def acompletion( # noqa: PLR0915 +async def acompletion( model: str, # Optional OpenAI params: see https://platform.openai.com/docs/api-reference/chat/create messages: List = [], @@ -1085,7 +1086,7 @@ def _build_custom_pricing_entry( @tracer.wrap() @client -def completion( # type: ignore # noqa: PLR0915 +def completion( # type: ignore model: str, # Optional OpenAI params: see https://platform.openai.com/docs/api-reference/chat/create messages: List = [], @@ -1407,11 +1408,19 @@ def completion( # type: ignore # noqa: PLR0915 if deployment_id is not None: # azure llms model = deployment_id custom_llm_provider = "azure" + _supplemental_provider_params = { + k: kwargs[k] for k in OPTIONAL_KWARGS_KEYS if k in kwargs + } model, custom_llm_provider, dynamic_api_key, api_base = get_llm_provider( model=model, custom_llm_provider=custom_llm_provider, api_base=api_base, api_key=api_key, + litellm_params=( + GenericLiteLLMParams(**_supplemental_provider_params) + if _supplemental_provider_params + else None + ), ) ## RESPONSES API BRIDGE LOGIC ## - check early and normalize model name @@ -1638,6 +1647,8 @@ def completion( # type: ignore # noqa: PLR0915 litellm_request_debug=kwargs.get("litellm_request_debug", False), tpm=kwargs.get("tpm"), rpm=kwargs.get("rpm"), + use_xai_oauth=kwargs.get("use_xai_oauth", False), + aws_bedrock_project_id=kwargs.get("aws_bedrock_project_id"), ) cast(LiteLLMLoggingObj, logging).update_environment_variables( model=model, @@ -2134,9 +2145,6 @@ def completion( # type: ignore # noqa: PLR0915 headers = headers or litellm.headers - if extra_headers is not None: - optional_params["extra_headers"] = extra_headers - ## LOAD CONFIG - if set config = litellm.OpenAITextCompletionConfig.get_config() for k, v in config.items(): @@ -2162,6 +2170,7 @@ def completion( # type: ignore # noqa: PLR0915 _response = openai_text_completions.completion( model=model, messages=messages, + headers=headers, model_response=model_response, print_verbose=print_verbose, api_key=api_key, @@ -4869,7 +4878,7 @@ def embedding( @client -def embedding( # noqa: PLR0915 +def embedding( model, input=[], # Optional params @@ -6116,7 +6125,7 @@ async def atext_completion( @client -def text_completion( # noqa: PLR0915 +def text_completion( prompt: Union[ str, List[Union[str, List[Union[str, List[int]]]]] ], # Required: The prompt(s) to generate completions for. @@ -6655,7 +6664,7 @@ async def atranscription(*args, **kwargs) -> TranscriptionResponse: @client -def transcription( # noqa: PLR0915 +def transcription( model: str, file: FileTypes, ## OPTIONAL OPENAI PARAMS ## @@ -6962,7 +6971,7 @@ async def aspeech(*args, **kwargs) -> HttpxBinaryResponseContent: @client -def speech( # noqa: PLR0915 +def speech( model: str, input: str, voice: Optional[Union[str, dict]] = None, @@ -7425,22 +7434,7 @@ def speech( # noqa: PLR0915 async def ahealth_check( model_params: dict, - mode: Optional[ - Literal[ - "chat", - "completion", - "embedding", - "audio_speech", - "audio_transcription", - "image_generation", - "video_generation", - "batch", - "rerank", - "realtime", - "responses", - "ocr", - ] - ] = "chat", + mode: str | None = "chat", prompt: Optional[str] = None, input: Optional[List] = None, ): @@ -7563,7 +7557,7 @@ def print_verbose(print_statement): try: verbose_logger.debug(print_statement) if litellm.set_verbose: - print(print_statement) # noqa + print(print_statement) # noqa: T201 except Exception: pass @@ -7653,7 +7647,7 @@ def stream_chunk_builder_text_completion( return TextCompletionResponse(**response) -def stream_chunk_builder( # noqa: PLR0915 +def stream_chunk_builder( chunks: list, messages: Optional[list] = None, start_time=None, @@ -7761,6 +7755,9 @@ def stream_chunk_builder( # noqa: PLR0915 "cost", logging_obj._response_cost_calculator(result=response), ) + processor.apply_provider_assembled_streaming_metadata( + response, chunks, logging_obj + ) return response tool_call_chunks = [ @@ -7940,6 +7937,9 @@ def stream_chunk_builder( # noqa: PLR0915 usage, "cost", logging_obj._response_cost_calculator(result=response) ) + processor.apply_provider_assembled_streaming_metadata( + response, chunks, logging_obj + ) return response except Exception as e: verbose_logger.exception( diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 757aacf1caf..7a5f8b9e1e3 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -2528,6 +2528,100 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "azure_ai/gpt-5.5": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_272k_tokens": 1e-06, + "cache_read_input_token_cost_priority": 1e-06, + "cache_read_input_token_cost_above_272k_tokens_priority": 2e-06, + "input_cost_per_token": 5e-06, + "input_cost_per_token_above_272k_tokens": 1e-05, + "input_cost_per_token_priority": 1e-05, + "input_cost_per_token_above_272k_tokens_priority": 2e-05, + "litellm_provider": "azure_ai", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "output_cost_per_token": 3e-05, + "output_cost_per_token_above_272k_tokens": 4.5e-05, + "output_cost_per_token_priority": 6e-05, + "output_cost_per_token_above_272k_tokens_priority": 9e-05, + "source": "https://ai.azure.com/catalog/models/gpt-5.5", + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/batch", + "/v1/responses" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text" + ], + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_service_tier": true, + "supports_vision": true, + "supports_web_search": true, + "supports_none_reasoning_effort": true, + "supports_xhigh_reasoning_effort": true, + "supports_minimal_reasoning_effort": false + }, + "azure_ai/gpt-5.5-2026-04-23": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_272k_tokens": 1e-06, + "cache_read_input_token_cost_priority": 1e-06, + "cache_read_input_token_cost_above_272k_tokens_priority": 2e-06, + "input_cost_per_token": 5e-06, + "input_cost_per_token_above_272k_tokens": 1e-05, + "input_cost_per_token_priority": 1e-05, + "input_cost_per_token_above_272k_tokens_priority": 2e-05, + "litellm_provider": "azure_ai", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "output_cost_per_token": 3e-05, + "output_cost_per_token_above_272k_tokens": 4.5e-05, + "output_cost_per_token_priority": 6e-05, + "output_cost_per_token_above_272k_tokens_priority": 9e-05, + "source": "https://ai.azure.com/catalog/models/gpt-5.5", + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/batch", + "/v1/responses" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text" + ], + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_service_tier": true, + "supports_vision": true, + "supports_web_search": true, + "supports_none_reasoning_effort": true, + "supports_xhigh_reasoning_effort": true, + "supports_minimal_reasoning_effort": false + }, "azure_ai/gpt-5.4": { "cache_read_input_token_cost": 2.5e-07, "cache_read_input_token_cost_above_272k_tokens": 5e-07, @@ -4409,6 +4503,23 @@ "/v1/audio/transcriptions" ] }, + "azure/gpt-realtime-whisper": { + "input_cost_per_second": 0.0002833333333333333, + "litellm_provider": "azure", + "mode": "audio_transcription", + "source": "https://learn.microsoft.com/en-us/azure/ai-foundry/openai/concepts/gpt-realtime-whisper", + "supported_endpoints": [ + "/v1/realtime", + "/v1/realtime/transcription_sessions" + ], + "supported_modalities": [ + "audio" + ], + "supported_output_modalities": [ + "text" + ], + "supports_audio_input": true + }, "azure/gpt-5.1-2025-11-13": { "cache_read_input_token_cost": 1.25e-07, "cache_read_input_token_cost_priority": 2.5e-07, @@ -7064,6 +7175,43 @@ "/v1/images/generations" ] }, + "azure_ai/MAI-Image-2.5": { + "input_cost_per_image_token": 8e-06, + "input_cost_per_token": 5e-06, + "litellm_provider": "azure_ai", + "mode": "image_generation", + "output_cost_per_image": 0.05, + "output_cost_per_image_token": 4.7e-05, + "source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/new-mai-models-in-microsoft-foundry-across-text-image-voice-and-speech/4524632", + "supported_endpoints": [ + "/v1/images/generations", + "/v1/images/edits" + ] + }, + "azure_ai/MAI-Image-2.5-Flash": { + "input_cost_per_image_token": 1.75e-06, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "azure_ai", + "mode": "image_generation", + "output_cost_per_image": 0.0338, + "output_cost_per_image_token": 3.3e-05, + "source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/new-mai-models-in-microsoft-foundry-across-text-image-voice-and-speech/4524632", + "supported_endpoints": [ + "/v1/images/generations", + "/v1/images/edits" + ] + }, + "azure_ai/MAI-Image-2e": { + "input_cost_per_token": 5e-06, + "litellm_provider": "azure_ai", + "mode": "image_generation", + "output_cost_per_image": 0.02, + "output_cost_per_image_token": 1.95e-05, + "source": "https://aka.ms/mai-image-2e-foundryblog", + "supported_endpoints": [ + "/v1/images/generations" + ] + }, "azure_ai/Llama-3.2-11B-Vision-Instruct": { "input_cost_per_token": 3.7e-07, "litellm_provider": "azure_ai", @@ -7520,6 +7668,45 @@ "supports_function_calling": true, "supports_tool_choice": true }, + "azure_ai/deepseek-v3.1": { + "input_cost_per_token": 1.23e-06, + "litellm_provider": "azure_ai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 4.94e-06, + "source": "https://azure.microsoft.com/en-us/pricing/details/ai-foundry-models/deepseek/", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "azure_ai/deepseek-v4-pro": { + "input_cost_per_token": 1.74e-06, + "litellm_provider": "azure_ai", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 3.48e-06, + "source": "https://azure.microsoft.com/en-us/pricing/details/ai-foundry-models/deepseek/", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "azure_ai/deepseek-v4-flash": { + "input_cost_per_token": 1.9e-07, + "litellm_provider": "azure_ai", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 5.1e-07, + "source": "https://azure.microsoft.com/en-us/pricing/details/ai-foundry-models/deepseek/", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, "azure_ai/embed-v-4-0": { "input_cost_per_token": 1.2e-07, "litellm_provider": "azure_ai", @@ -9975,6 +10162,8 @@ }, "claude-sonnet-4-5": { "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_1hr": 6e-06, + "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.2e-05, "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "input_cost_per_token_above_200k_tokens": 6e-06, @@ -10004,6 +10193,8 @@ }, "claude-sonnet-4-5-20250929": { "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_1hr": 6e-06, + "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.2e-05, "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "input_cost_per_token_above_200k_tokens": 6e-06, @@ -10034,6 +10225,7 @@ }, "claude-sonnet-4-6": { "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_1hr": 6e-06, "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "litellm_provider": "anthropic", @@ -10062,6 +10254,8 @@ }, "claude-sonnet-4-5-20250929-v1:0": { "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_1hr": 6e-06, + "cache_creation_input_token_cost_above_1hr_above_200k_tokens": 1.2e-05, "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 3e-06, "input_cost_per_token_above_200k_tokens": 6e-06, @@ -10718,13 +10912,13 @@ "supports_tool_choice": true }, "command-r7b-12-2024": { - "input_cost_per_token": 1.5e-07, + "input_cost_per_token": 3.75e-08, "litellm_provider": "cohere_chat", "max_input_tokens": 128000, "max_output_tokens": 4096, "max_tokens": 4096, "mode": "chat", - "output_cost_per_token": 3.75e-08, + "output_cost_per_token": 1.5e-07, "source": "https://docs.cohere.com/v2/docs/command-r7b", "supports_function_calling": true, "supports_tool_choice": true @@ -14418,6 +14612,38 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "fireworks_ai/accounts/fireworks/models/deepseek-v4-flash": { + "cache_read_input_token_cost": 2.8e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 1048576, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/accounts/fireworks/models/deepseek-v4-pro": { + "cache_read_input_token_cost": 1.45e-07, + "input_cost_per_token": 1.74e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 1048576, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 3.48e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, "fireworks_ai/accounts/fireworks/models/firefunction-v2": { "input_cost_per_token": 9e-07, "litellm_provider": "fireworks_ai", @@ -14493,43 +14719,64 @@ "input_cost_per_token": 1.4e-06, "litellm_provider": "fireworks_ai", "max_input_tokens": 202800, - "max_output_tokens": 202800, - "max_tokens": 202800, + "max_output_tokens": 131072, + "max_tokens": 131072, "mode": "chat", "output_cost_per_token": 4.4e-06, - "source": "https://fireworks.ai/models/fireworks/glm-5p1", - "supports_function_calling": false, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, "supports_reasoning": true, - "supports_response_schema": false, - "supports_tool_choice": false + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/accounts/fireworks/models/glm-5p2": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 4.4e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false }, "fireworks_ai/accounts/fireworks/models/gpt-oss-120b": { + "cache_read_input_token_cost": 1.5e-08, "input_cost_per_token": 1.5e-07, "litellm_provider": "fireworks_ai", "max_input_tokens": 131072, - "max_output_tokens": 131072, - "max_tokens": 131072, + "max_output_tokens": 32768, + "max_tokens": 32768, "mode": "chat", "output_cost_per_token": 6e-07, - "source": "https://fireworks.ai/pricing", + "source": "https://docs.fireworks.ai/serverless/pricing", "supports_function_calling": true, "supports_reasoning": true, "supports_response_schema": true, - "supports_tool_choice": true + "supports_tool_choice": true, + "supports_vision": false }, "fireworks_ai/accounts/fireworks/models/gpt-oss-20b": { - "input_cost_per_token": 5e-08, + "cache_read_input_token_cost": 3.5e-08, + "input_cost_per_token": 7e-08, "litellm_provider": "fireworks_ai", "max_input_tokens": 131072, - "max_output_tokens": 131072, - "max_tokens": 131072, + "max_output_tokens": 32768, + "max_tokens": 32768, "mode": "chat", - "output_cost_per_token": 2e-07, - "source": "https://fireworks.ai/pricing", + "output_cost_per_token": 3e-07, + "source": "https://docs.fireworks.ai/serverless/pricing", "supports_function_calling": true, "supports_reasoning": true, "supports_response_schema": true, - "supports_tool_choice": true + "supports_tool_choice": true, + "supports_vision": false }, "fireworks_ai/accounts/fireworks/models/kimi-k2-instruct": { "input_cost_per_token": 6e-07, @@ -14585,6 +14832,38 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "fireworks_ai/accounts/fireworks/models/kimi-k2p6": { + "cache_read_input_token_cost": 1.6e-07, + "input_cost_per_token": 9.5e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "fireworks_ai/accounts/fireworks/models/kimi-k2p7-code": { + "cache_read_input_token_cost": 1.9e-07, + "input_cost_per_token": 9.5e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, "fireworks_ai/accounts/fireworks/models/llama-v3p1-405b-instruct": { "input_cost_per_token": 3e-06, "litellm_provider": "fireworks_ai", @@ -14702,6 +14981,38 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "fireworks_ai/accounts/fireworks/models/minimax-m2p7": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 196608, + "max_output_tokens": 196608, + "max_tokens": 196608, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/accounts/fireworks/models/minimax-m3": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 512000, + "max_output_tokens": 512000, + "max_tokens": 512000, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, "fireworks_ai/accounts/fireworks/models/mixtral-8x22b-instruct-hf": { "input_cost_per_token": 1.2e-06, "litellm_provider": "fireworks_ai", @@ -14754,6 +15065,38 @@ "supports_response_schema": true, "supports_tool_choice": false }, + "fireworks_ai/deepseek-v4-flash": { + "cache_read_input_token_cost": 2.8e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 1048576, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/deepseek-v4-pro": { + "cache_read_input_token_cost": 1.45e-07, + "input_cost_per_token": 1.74e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 1048576, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 3.48e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, "fireworks_ai/glm-4p7": { "cache_read_input_token_cost": 3e-07, "input_cost_per_token": 6e-07, @@ -14774,15 +15117,80 @@ "input_cost_per_token": 1.4e-06, "litellm_provider": "fireworks_ai", "max_input_tokens": 202800, - "max_output_tokens": 202800, - "max_tokens": 202800, + "max_output_tokens": 131072, + "max_tokens": 131072, "mode": "chat", "output_cost_per_token": 4.4e-06, - "source": "https://fireworks.ai/models/fireworks/glm-5p1", - "supports_function_calling": false, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, "supports_reasoning": true, - "supports_response_schema": false, - "supports_tool_choice": false + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/glm-5p1-fast": { + "cache_read_input_token_cost": 5.2e-07, + "input_cost_per_token": 2.8e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 202800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 8.8e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/glm-5p2": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 4.4e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/gpt-oss-120b": { + "cache_read_input_token_cost": 1.5e-08, + "input_cost_per_token": 1.5e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 131072, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 6e-07, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/gpt-oss-20b": { + "cache_read_input_token_cost": 3.5e-08, + "input_cost_per_token": 7e-08, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 131072, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 3e-07, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false }, "fireworks_ai/kimi-k2p5": { "cache_read_input_token_cost": 1e-07, @@ -14798,6 +15206,70 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "fireworks_ai/kimi-k2p6": { + "cache_read_input_token_cost": 1.6e-07, + "input_cost_per_token": 9.5e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "fireworks_ai/kimi-k2p6-fast": { + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 2e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 8e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "fireworks_ai/kimi-k2p7-code": { + "cache_read_input_token_cost": 1.9e-07, + "input_cost_per_token": 9.5e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "fireworks_ai/kimi-k2p7-code-fast": { + "cache_read_input_token_cost": 3.8e-07, + "input_cost_per_token": 1.9e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 8e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, "fireworks_ai/minimax-m2p1": { "cache_read_input_token_cost": 3e-08, "input_cost_per_token": 3e-07, @@ -14812,6 +15284,54 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "fireworks_ai/minimax-m2p7": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 196608, + "max_output_tokens": 196608, + "max_tokens": 196608, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/minimax-m3": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 512000, + "max_output_tokens": 512000, + "max_tokens": 512000, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/qwen3p7-plus": { + "cache_read_input_token_cost": 8e-08, + "input_cost_per_token": 4e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "output_cost_per_token": 1.6e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, "fireworks_ai/nomic-ai/nomic-embed-text-v1": { "input_cost_per_token": 8e-09, "litellm_provider": "fireworks_ai-embedding-models", @@ -18729,6 +19249,38 @@ "supports_response_schema": true, "supports_vision": true }, + "github_copilot/mai-code-1-flash": { + "cache_read_input_token_cost": 7.5e-08, + "input_cost_per_token": 7.5e-07, + "litellm_provider": "github_copilot", + "max_input_tokens": 128000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "output_cost_per_token": 4.5e-06, + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_response_schema": true + }, + "github_copilot/mai-code-1-flash-internal": { + "cache_read_input_token_cost": 7.5e-08, + "input_cost_per_token": 7.5e-07, + "litellm_provider": "github_copilot", + "max_input_tokens": 128000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "output_cost_per_token": 4.5e-06, + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_response_schema": true + }, "github_copilot/text-embedding-3-small": { "litellm_provider": "github_copilot", "max_input_tokens": 8191, @@ -24355,9 +24907,12 @@ "max_output_tokens": 8192 }, "minimax/MiniMax-M3": { - "input_cost_per_token": 6e-07, - "output_cost_per_token": 2.4e-06, - "cache_read_input_token_cost": 1.2e-07, + "input_cost_per_token": 3e-07, + "input_cost_per_token_above_512k_tokens": 6e-07, + "output_cost_per_token": 1.2e-06, + "output_cost_per_token_above_512k_tokens": 2.4e-06, + "cache_read_input_token_cost": 6e-08, + "cache_read_input_token_cost_above_512k_tokens": 1.2e-07, "litellm_provider": "minimax", "mode": "chat", "supports_function_calling": true, @@ -24366,7 +24921,7 @@ "supports_reasoning": true, "supports_system_messages": true, "supports_vision": true, - "max_input_tokens": 512000, + "max_input_tokens": 1000000, "max_output_tokens": 128000 }, "mistral.devstral-2-123b": { @@ -24975,6 +25530,21 @@ "supports_tool_choice": true, "supports_vision": true }, + "mistral/mistral-medium-3-5": { + "input_cost_per_token": 1.5e-06, + "litellm_provider": "mistral", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 7.5e-06, + "source": "https://docs.mistral.ai/models/model-cards/mistral-medium-3-5-26-04", + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, "mistral/mistral-small": { "input_cost_per_token": 1e-07, "litellm_provider": "mistral", @@ -35756,7 +36326,17 @@ "max_input_tokens": 32000, "max_tokens": 32000, "mode": "embedding", - "output_cost_per_token": 0.0 + "output_cost_per_token": 0.0, + "supports_vision": true + }, + "voyage/voyage-multimodal-3.5": { + "input_cost_per_token": 1.2e-07, + "litellm_provider": "voyage", + "max_input_tokens": 32000, + "max_tokens": 32000, + "mode": "embedding", + "output_cost_per_token": 0.0, + "supports_vision": true }, "wandb/openai/gpt-oss-120b": { "max_tokens": 131072, @@ -39213,6 +39793,22 @@ "litellm_provider": "fireworks_ai", "mode": "chat" }, + "fireworks_ai/accounts/fireworks/models/qwen3p7-plus": { + "cache_read_input_token_cost": 8e-08, + "input_cost_per_token": 4e-07, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "output_cost_per_token": 1.6e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, "fireworks_ai/accounts/fireworks/models/qwq-32b": { "max_tokens": 131072, "max_input_tokens": 131072, @@ -39375,6 +39971,54 @@ "litellm_provider": "fireworks_ai", "mode": "chat" }, + "fireworks_ai/accounts/fireworks/routers/glm-5p1-fast": { + "cache_read_input_token_cost": 5.2e-07, + "input_cost_per_token": 2.8e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 202800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 8.8e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "fireworks_ai/accounts/fireworks/routers/kimi-k2p6-fast": { + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 2e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 8e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "fireworks_ai/accounts/fireworks/routers/kimi-k2p7-code-fast": { + "cache_read_input_token_cost": 3.8e-07, + "input_cost_per_token": 1.9e-06, + "litellm_provider": "fireworks_ai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 8e-06, + "source": "https://docs.fireworks.ai/serverless/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, "novita/deepseek/deepseek-v3.2": { "litellm_provider": "novita", "mode": "chat", @@ -40678,6 +41322,174 @@ "litellm_provider": "llamagate", "mode": "embedding" }, + "libertai/hermes-3-8b-tee": { + "max_tokens": 16000, + "max_input_tokens": 16000, + "max_output_tokens": 16000, + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 6e-07, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": false, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/gemma-4-31b-it": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 4e-07, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/gemma-4-31b-it-thinking": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 4e-07, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "supports_reasoning": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/qwen3.6-27b": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 5e-07, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/qwen3.6-27b-thinking": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 5e-07, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "supports_reasoning": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/qwen3.6-35b-a3b": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 5e-07, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/qwen3.6-35b-a3b-thinking": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 5e-07, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "supports_reasoning": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/qwen3.5-122b-a10b": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 2.5e-07, + "output_cost_per_token": 1.75e-06, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/qwen3.5-122b-a10b-thinking": { + "max_tokens": 262144, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "input_cost_per_token": 2.5e-07, + "output_cost_per_token": 1.75e-06, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": true, + "supports_reasoning": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/deepseek-v4-flash": { + "max_tokens": 200000, + "max_input_tokens": 200000, + "max_output_tokens": 200000, + "input_cost_per_token": 2.5e-07, + "output_cost_per_token": 1.75e-06, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": false, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/deepseek-v4-flash-thinking": { + "max_tokens": 200000, + "max_input_tokens": 200000, + "max_output_tokens": 200000, + "input_cost_per_token": 2.5e-07, + "output_cost_per_token": 1.75e-06, + "litellm_provider": "libertai", + "mode": "chat", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_vision": false, + "supports_reasoning": true, + "source": "https://docs.libertai.io/apis/text/" + }, + "libertai/bge-m3": { + "max_tokens": 8192, + "max_input_tokens": 8192, + "input_cost_per_token": 1e-08, + "output_cost_per_token": 0.0, + "litellm_provider": "libertai", + "mode": "embedding", + "source": "https://docs.libertai.io/apis/text/" + }, "sarvam/sarvam-m": { "cache_creation_input_token_cost": 0, "cache_creation_input_token_cost_above_1hr": 0, @@ -40876,6 +41688,23 @@ "supports_system_messages": true, "supports_tool_choice": true }, + "gpt-realtime-whisper": { + "input_cost_per_second": 0.0002833333333333333, + "litellm_provider": "openai", + "mode": "audio_transcription", + "source": "https://platform.openai.com/docs/models/gpt-realtime-whisper", + "supported_endpoints": [ + "/v1/realtime", + "/v1/realtime/transcription_sessions" + ], + "supported_modalities": [ + "audio" + ], + "supported_output_modalities": [ + "text" + ], + "supports_audio_input": true + }, "sora-2": { "litellm_provider": "openai", "mode": "video_generation", @@ -41554,6 +42383,7 @@ "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"], "supports_function_calling": true, "supports_parallel_function_calling": true, "supports_reasoning": true, @@ -41568,6 +42398,7 @@ "max_output_tokens": 32768, "max_tokens": 32768, "mode": "chat", + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"], "supports_function_calling": true, "supports_parallel_function_calling": true, "supports_reasoning": true, @@ -41582,6 +42413,7 @@ "max_output_tokens": 65536, "max_tokens": 65536, "mode": "chat", + "supported_endpoints": ["/v1/chat/completions"], "supports_function_calling": true, "supports_reasoning": true, "supports_response_schema": true, @@ -41595,6 +42427,7 @@ "max_output_tokens": 65536, "max_tokens": 65536, "mode": "chat", + "supported_endpoints": ["/v1/chat/completions"], "supports_function_calling": true, "supports_reasoning": true, "supports_response_schema": true, @@ -41609,6 +42442,7 @@ "max_output_tokens": 128000, "max_tokens": 128000, "mode": "responses", + "use_openai_responses_path": true, "supported_endpoints": ["/v1/responses"], "supported_modalities": ["text", "image"], "supported_output_modalities": ["text"], @@ -41628,6 +42462,7 @@ "max_output_tokens": 128000, "max_tokens": 128000, "mode": "responses", + "use_openai_responses_path": true, "supported_endpoints": ["/v1/responses"], "supported_modalities": ["text", "image"], "supported_output_modalities": ["text"], @@ -41638,6 +42473,54 @@ "supports_tool_choice": true, "supports_vision": true }, + "bedrock_mantle/google.gemma-4-31b": { + "input_cost_per_token": 1.4e-07, + "output_cost_per_token": 4e-07, + "litellm_provider": "bedrock_mantle", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "chat", + "use_openai_responses_path": true, + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"], + "supports_function_calling": true, + "supports_parallel_function_calling": false, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "bedrock_mantle/google.gemma-4-26b-a4b": { + "input_cost_per_token": 1.3e-07, + "output_cost_per_token": 4e-07, + "litellm_provider": "bedrock_mantle", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "chat", + "use_openai_responses_path": true, + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"], + "supports_function_calling": true, + "supports_parallel_function_calling": false, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "bedrock_mantle/google.gemma-4-e2b": { + "input_cost_per_token": 4e-08, + "output_cost_per_token": 8e-08, + "litellm_provider": "bedrock_mantle", + "max_input_tokens": 128000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "use_openai_responses_path": true, + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"], + "supports_function_calling": true, + "supports_parallel_function_calling": false, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, "volcengine/doubao-seed-2-0-pro-260215": { "litellm_provider": "volcengine", "max_input_tokens": 256000, @@ -41929,5 +42812,278 @@ "/v1/audio/transcriptions" ], "supports_audio_input": true + }, + "soniox/stt-async-v5": { + "litellm_provider": "soniox", + "max_output_tokens": 8000, + "max_tokens": 8000, + "input_cost_per_second": 0.0, + "output_cost_per_second": 0.0000277778, + "mode": "audio_transcription", + "source": "https://soniox.com/pricing", + "supported_endpoints": [ + "/v1/audio/transcriptions" + ], + "supports_audio_input": true + }, + "tensormesh/Qwen/Qwen3.5-397B-A17B-FP8": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 6e-07, + "output_cost_per_token": 3.6e-06, + "cache_read_input_token_cost": 0, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 4.5e-07, + "output_cost_per_token": 1.8e-06, + "cache_read_input_token_cost": 0, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/Qwen/Qwen3.6-27B-FP8": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 3.2e-07, + "output_cost_per_token": 3.2e-06, + "cache_read_input_token_cost": 0, + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/lukealonso/GLM-5.1-NVFP4-MTP": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 1.4e-06, + "output_cost_per_token": 4.4e-06, + "cache_read_input_token_cost": 0, + "max_input_tokens": 202752, + "max_output_tokens": 202752, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/deepseek-ai/DeepSeek-V4-Flash": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 1.4e-07, + "output_cost_per_token": 2.8e-07, + "cache_read_input_token_cost": 0, + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/moonshotai/Kimi-K2.6": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 9.6e-07, + "output_cost_per_token": 4e-06, + "cache_read_input_token_cost": 0, + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/MiniMaxAI/MiniMax-M2.5": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 3e-07, + "output_cost_per_token": 1.2e-06, + "cache_read_input_token_cost": 0, + "max_input_tokens": 196608, + "max_output_tokens": 196608, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/google/gemma-4-31B-it": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 1.4e-07, + "output_cost_per_token": 5.6e-07, + "cache_read_input_token_cost": 0, + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/openai/gpt-oss-120b": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 1.5e-07, + "output_cost_per_token": 6e-07, + "cache_read_input_token_cost": 0, + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" + }, + "tensormesh/openai/gpt-oss-20b": { + "litellm_provider": "tensormesh", + "mode": "chat", + "input_cost_per_token": 7e-08, + "output_cost_per_token": 2.8e-07, + "cache_read_input_token_cost": 0, + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_reasoning": true, + "source": "https://serverless.tensormesh.ai/v1/models/openrouter" } -} \ No newline at end of file +, + "deepseek-v4-flash": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 2.8e-09, + "input_cost_per_token": 1.4e-07, + "input_cost_per_token_cache_hit": 2.8e-09, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 8192, + "max_tokens": 8192, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "deepseek-v4-pro": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 3.625e-09, + "input_cost_per_token": 4.35e-07, + "input_cost_per_token_cache_hit": 3.625e-09, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 8192, + "max_tokens": 8192, + "mode": "chat", + "output_cost_per_token": 8.7e-07, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "deepseek/deepseek-v4-flash": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 2.8e-09, + "input_cost_per_token": 1.4e-07, + "input_cost_per_token_cache_hit": 2.8e-09, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 8192, + "max_tokens": 8192, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_vision": false + }, + "deepseek/deepseek-v4-pro": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 3.625e-09, + "input_cost_per_token": 4.35e-07, + "input_cost_per_token_cache_hit": 3.625e-09, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 8192, + "max_tokens": 8192, + "mode": "chat", + "output_cost_per_token": 8.7e-07, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_vision": false + } +} diff --git a/litellm/models/__init__.py b/litellm/models/__init__.py new file mode 100644 index 00000000000..7e2d2c0ed9d --- /dev/null +++ b/litellm/models/__init__.py @@ -0,0 +1,66 @@ +""" +Domain models for LiteLLM backend. +""" + +from litellm.models.access_group import LiteLLM_AccessGroupTable +from litellm.models.budget import ( + LiteLLM_BudgetTable, + LiteLLM_BudgetTableFull, + LiteLLM_TeamMemberTable, +) +from litellm.models.config import LiteLLM_Config +from litellm.models.credentials import ( + CreateCredentialItem, + CredentialBase, + CredentialItem, +) +from litellm.models.end_user import LiteLLM_EndUserTable +from litellm.models.managed_files import ( + LiteLLM_ManagedFileTable, + LiteLLM_ManagedObjectTable, + LiteLLM_ManagedVectorStoresTable, + LiteLLM_ManagedVectorStoreTable, +) +from litellm.models.mcp_server import LiteLLM_MCPServerTable +from litellm.models.model import LiteLLM_ProxyModelTable +from litellm.models.object_permission import LiteLLM_ObjectPermissionTable +from litellm.models.organization import LiteLLM_OrganizationTable +from litellm.models.organization_membership import LiteLLM_OrganizationMembershipTable +from litellm.models.project import LiteLLM_ProjectTable +from litellm.models.skills import LiteLLM_SkillsTable +from litellm.models.spend_logs import LiteLLM_ErrorLogs, LiteLLM_SpendLogs +from litellm.models.tag import LiteLLM_TagTable +from litellm.models.team import LiteLLM_TeamTable +from litellm.models.team_membership import LiteLLM_TeamMembership +from litellm.models.user import LiteLLM_UserTable +from litellm.models.verification_token import LiteLLM_VerificationToken + +__all__ = [ + "LiteLLM_AccessGroupTable", + "LiteLLM_BudgetTable", + "LiteLLM_BudgetTableFull", + "LiteLLM_TeamMemberTable", + "LiteLLM_Config", + "CredentialBase", + "CredentialItem", + "CreateCredentialItem", + "LiteLLM_EndUserTable", + "LiteLLM_ManagedFileTable", + "LiteLLM_ManagedObjectTable", + "LiteLLM_ManagedVectorStoreTable", + "LiteLLM_ManagedVectorStoresTable", + "LiteLLM_MCPServerTable", + "LiteLLM_ProxyModelTable", + "LiteLLM_ObjectPermissionTable", + "LiteLLM_OrganizationTable", + "LiteLLM_OrganizationMembershipTable", + "LiteLLM_ProjectTable", + "LiteLLM_SkillsTable", + "LiteLLM_ErrorLogs", + "LiteLLM_SpendLogs", + "LiteLLM_TagTable", + "LiteLLM_TeamTable", + "LiteLLM_TeamMembership", + "LiteLLM_UserTable", + "LiteLLM_VerificationToken", +] diff --git a/litellm/models/access_group.py b/litellm/models/access_group.py new file mode 100644 index 00000000000..682e779e531 --- /dev/null +++ b/litellm/models/access_group.py @@ -0,0 +1,26 @@ +""" +Access group table model. + +Canonical definition for ``litellm_accessgrouptable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import List, Optional + +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_AccessGroupTable(LiteLLMPydanticObjectBase): + access_group_id: str + access_group_name: str + description: Optional[str] = None + access_model_names: List[str] = [] + access_mcp_server_ids: List[str] = [] + access_agent_ids: List[str] = [] + assigned_team_ids: List[str] = [] + assigned_key_ids: List[str] = [] + created_at: Optional[datetime] = None + created_by: Optional[str] = None + updated_at: Optional[datetime] = None + updated_by: Optional[str] = None diff --git a/litellm/models/base.py b/litellm/models/base.py new file mode 100644 index 00000000000..01981297bd5 --- /dev/null +++ b/litellm/models/base.py @@ -0,0 +1,38 @@ +""" +Base model class for domain models. +""" + +from datetime import datetime +from typing import Any, Dict, Optional + +from pydantic import BaseModel, ConfigDict + + +class DomainModel(BaseModel): + """Base class for all domain models.""" + + model_config = ConfigDict( + from_attributes=True, + protected_namespaces=(), + extra="ignore", + ) + + created_at: Optional[datetime] = None + updated_at: Optional[datetime] = None + + @classmethod + def from_db_record(cls, record: Any) -> "DomainModel": + """Create a domain model from a database record.""" + if record is None: + raise ValueError("Cannot create domain model from None record") + if isinstance(record, dict): + return cls(**record) + if hasattr(record, "model_dump") and callable(record.model_dump): + return cls(**record.model_dump()) + if hasattr(record, "dict") and callable(record.dict): + return cls(**record.dict()) + return cls(**dict(record)) + + def to_db_dict(self, exclude_unset: bool = False) -> Dict[str, Any]: + """Convert domain model to a dictionary for database operations.""" + return self.model_dump(exclude_none=True, exclude_unset=exclude_unset) diff --git a/litellm/models/budget.py b/litellm/models/budget.py new file mode 100644 index 00000000000..e7dfe2f8fbc --- /dev/null +++ b/litellm/models/budget.py @@ -0,0 +1,56 @@ +""" +Budget table model. + +Canonical definition for ``litellm_budgettable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import List, Optional + +from pydantic import ConfigDict + +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_BudgetTable(LiteLLMPydanticObjectBase): + """Represents user-controllable params for a LiteLLM_BudgetTable record. + + Budget-write paths use `model_fields.keys()` on this class as an allowlist + for user input. Keep server-managed fields (e.g. `budget_reset_at`) on + `LiteLLM_BudgetTableFull` so they aren't user-settable. + """ + + budget_id: Optional[str] = None + soft_budget: Optional[float] = None + max_budget: Optional[float] = None + max_parallel_requests: Optional[int] = None + tpm_limit: Optional[int] = None + rpm_limit: Optional[int] = None + model_max_budget: Optional[dict] = None + budget_duration: Optional[str] = None + allowed_models: Optional[List[str]] = ( + None # per-member model scope; empty = inherit team models + ) + + model_config = ConfigDict(protected_namespaces=()) + + +class LiteLLM_BudgetTableFull(LiteLLM_BudgetTable): + """LiteLLM_BudgetTable + server-managed fields returned on API responses.""" + + budget_reset_at: Optional[datetime] = None + created_at: datetime + + +class LiteLLM_TeamMemberTable(LiteLLM_BudgetTable): + """ + Used to track spend of a user_id within a team_id + """ + + spend: Optional[float] = None + user_id: Optional[str] = None + team_id: Optional[str] = None + budget_id: Optional[str] = None + + model_config = ConfigDict(protected_namespaces=()) diff --git a/litellm/models/config.py b/litellm/models/config.py new file mode 100644 index 00000000000..99b5c5692fd --- /dev/null +++ b/litellm/models/config.py @@ -0,0 +1,15 @@ +""" +Config table model. + +Canonical definition for ``litellm_config``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from typing import Dict + +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_Config(LiteLLMPydanticObjectBase): + param_name: str + param_value: Dict diff --git a/litellm/models/credentials.py b/litellm/models/credentials.py new file mode 100644 index 00000000000..b74ea055d21 --- /dev/null +++ b/litellm/models/credentials.py @@ -0,0 +1,31 @@ +""" +Credential table models. + +These are the canonical credential types for the proxy. They live in the model +layer; ``litellm.types.utils`` re-exports them for backwards compatibility. +""" + +from typing import Optional + +from pydantic import BaseModel, model_validator + + +class CredentialBase(BaseModel): + credential_name: str + credential_info: dict + + +class CredentialItem(CredentialBase): + credential_values: dict + + +class CreateCredentialItem(CredentialBase): + credential_values: Optional[dict] = None + model_id: Optional[str] = None + + @model_validator(mode="before") + @classmethod + def check_credential_params(cls, values): + if not values.get("credential_values") and not values.get("model_id"): + raise ValueError("Either credential_values or model_id must be set") + return values diff --git a/litellm/models/end_user.py b/litellm/models/end_user.py new file mode 100644 index 00000000000..15fd03ec2ca --- /dev/null +++ b/litellm/models/end_user.py @@ -0,0 +1,35 @@ +""" +End-user table model. + +Canonical definition for ``litellm_endusertable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from typing import Literal, Optional + +from pydantic import ConfigDict, model_validator + +from litellm.models.budget import LiteLLM_BudgetTable +from litellm.models.object_permission import LiteLLM_ObjectPermissionTable +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_EndUserTable(LiteLLMPydanticObjectBase): + user_id: str + blocked: bool + alias: Optional[str] = None + spend: float = 0.0 + allowed_model_region: Optional[Literal["eu", "us"]] = None + default_model: Optional[str] = None + litellm_budget_table: Optional[LiteLLM_BudgetTable] = None + object_permission_id: Optional[str] = None + object_permission: Optional[LiteLLM_ObjectPermissionTable] = None + + @model_validator(mode="before") + @classmethod + def set_model_info(cls, values): + if values.get("spend") is None: + values.update({"spend": 0.0}) + return values + + model_config = ConfigDict(protected_namespaces=()) diff --git a/litellm/models/managed_files.py b/litellm/models/managed_files.py new file mode 100644 index 00000000000..24154768860 --- /dev/null +++ b/litellm/models/managed_files.py @@ -0,0 +1,62 @@ +""" +Managed file, object, and vector store table models. + +Canonical definitions for the ``litellm_managed*`` tables. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional, Union + +from litellm.types.llms.base import LiteLLMPydanticObjectBase +from litellm.types.llms.openai import OpenAIFileObject, ResponsesAPIResponse +from litellm.types.utils import LiteLLMBatch, LiteLLMFineTuningJob + + +class LiteLLM_ManagedFileTable(LiteLLMPydanticObjectBase): + unified_file_id: str + file_object: Optional[OpenAIFileObject] = None + model_mappings: Dict[str, str] + flat_model_file_ids: List[str] + created_by: Optional[str] = None + team_id: Optional[str] = None + updated_by: Optional[str] = None + storage_backend: Optional[str] = None + storage_url: Optional[str] = None + + +class LiteLLM_ManagedObjectTable(LiteLLMPydanticObjectBase): + unified_object_id: str + model_object_id: str + file_purpose: Literal["batch", "fine-tune", "response", "container"] + file_object: Union[LiteLLMBatch, LiteLLMFineTuningJob, ResponsesAPIResponse] + created_by: Optional[str] = None + team_id: Optional[str] = None + + +class LiteLLM_ManagedVectorStoreTable(LiteLLMPydanticObjectBase): + """Table for managing vector stores with target_model_names support.""" + + unified_resource_id: str + resource_object: Optional[Any] = None + model_mappings: Dict[str, str] + flat_model_resource_ids: List[str] + created_by: Optional[str] = None + team_id: Optional[str] = None + updated_by: Optional[str] = None + storage_backend: Optional[str] = None + storage_url: Optional[str] = None + + +class LiteLLM_ManagedVectorStoresTable(LiteLLMPydanticObjectBase): + vector_store_id: str + custom_llm_provider: str + vector_store_name: Optional[str] + vector_store_description: Optional[str] + vector_store_metadata: Optional[Dict[str, Any]] + created_at: Optional[datetime] + updated_at: Optional[datetime] + litellm_credential_name: Optional[str] + litellm_params: Optional[Dict[str, Any]] + team_id: Optional[str] + user_id: Optional[str] diff --git a/litellm/models/mcp_server.py b/litellm/models/mcp_server.py new file mode 100644 index 00000000000..3d03eff6df8 --- /dev/null +++ b/litellm/models/mcp_server.py @@ -0,0 +1,103 @@ +""" +MCP server table model. + +Canonical definition for ``litellm_mcpservertable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +import enum +from datetime import datetime +from typing import Dict, List, Literal, Optional + +from pydantic import Field + +from litellm.types.llms.base import LiteLLMPydanticObjectBase +from litellm.types.mcp import MCPAuthType, MCPCredentials, MCPTransportType +from litellm.types.mcp_server.mcp_server_manager import MCPInfo + + +class MCPEnvVarScope(str, enum.Enum): + """Scope for an MCP server environment variable. + + - ``global``: value is provided by the admin and used for all users. + - ``user``: each user must provide their own value via the per-user + env-var endpoint. The admin-supplied ``value`` is treated as a + placeholder/hint and is not used at request time. + """ + + global_ = "global" + user = "user" + + +class MCPEnvVar(LiteLLMPydanticObjectBase): + """One environment variable for an MCP server. + + Variables can be interpolated into ``static_headers`` using ``${NAME}`` + syntax. ``scope=global`` values are stored on the server. ``scope=user`` + values are stored per-user in ``LiteLLM_MCPUserEnvVars`` and supplied by + each user. + """ + + name: str + value: str = "" + scope: MCPEnvVarScope = MCPEnvVarScope.global_ + description: Optional[str] = None + + +class LiteLLM_MCPServerTable(LiteLLMPydanticObjectBase): + """Represents a LiteLLM_MCPServerTable record""" + + server_id: str + server_name: Optional[str] = None + alias: Optional[str] = None + description: Optional[str] = None + url: Optional[str] = None + spec_path: Optional[str] = None + transport: MCPTransportType + auth_type: Optional[MCPAuthType] = None + credentials: Optional[MCPCredentials] = None + instructions: Optional[str] = None + created_at: Optional[datetime] = None + created_by: Optional[str] = None + updated_at: Optional[datetime] = None + updated_by: Optional[str] = None + teams: List[Dict[str, Optional[str]]] = Field(default_factory=list) + mcp_access_groups: List[str] = Field(default_factory=list) + allowed_tools: List[str] = Field(default_factory=list) + tool_name_to_display_name: Optional[Dict[str, str]] = None + tool_name_to_description: Optional[Dict[str, str]] = None + extra_headers: List[str] = Field(default_factory=list) + mcp_info: Optional[MCPInfo] = None + static_headers: Optional[Dict[str, str]] = None + env_vars: Optional[List[MCPEnvVar]] = None + status: Optional[Literal["healthy", "unhealthy", "unknown"]] = Field( + default="unknown", + description="Health status: 'healthy', 'unhealthy', 'unknown'", + ) + last_health_check: Optional[datetime] = None + health_check_error: Optional[str] = None + command: Optional[str] = None + args: List[str] = Field(default_factory=list) + env: Dict[str, str] = Field(default_factory=dict) + authorization_url: Optional[str] = None + token_url: Optional[str] = None + registration_url: Optional[str] = None + oauth2_flow: Optional[Literal["client_credentials", "authorization_code"]] = None + allow_all_keys: bool = False + available_on_public_internet: bool = True + delegate_auth_to_upstream: bool = False + oauth_passthrough: bool = False + is_byok: bool = False + byok_description: List[str] = Field(default_factory=list) + byok_api_key_help_url: Optional[str] = None + has_user_credential: Optional[bool] = None + source_url: Optional[str] = None + timeout: Optional[float] = None + approval_status: Optional[str] = Field( + default="active", + description="Approval status: 'pending_review', 'active', 'rejected'", + ) + submitted_by: Optional[str] = None + submitted_at: Optional[datetime] = None + reviewed_at: Optional[datetime] = None + review_notes: Optional[str] = None diff --git a/litellm/models/model.py b/litellm/models/model.py new file mode 100644 index 00000000000..7657e4d30f8 --- /dev/null +++ b/litellm/models/model.py @@ -0,0 +1,59 @@ +""" +Proxy model table model. + +Canonical definition for ``litellm_proxymodeltable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +import json +from datetime import datetime +from typing import Optional + +from pydantic import ConfigDict, model_validator + +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_ProxyModelTable(LiteLLMPydanticObjectBase): + model_id: str + model_name: str + litellm_params: dict + model_info: Optional[dict] = None + blocked: bool = False + created_at: Optional[datetime] = None + created_by: Optional[str] = None + updated_at: Optional[datetime] = None + updated_by: Optional[str] = None + + model_config = ConfigDict(protected_namespaces=()) + + @model_validator(mode="before") + @classmethod + def check_potential_json_str(cls, values): + if isinstance(values.get("litellm_params"), str): + try: + values["litellm_params"] = json.loads(values["litellm_params"]) + except json.JSONDecodeError: + pass + if isinstance(values.get("model_info"), str): + try: + values["model_info"] = json.loads(values["model_info"]) + except json.JSONDecodeError: + pass + return values + + @property + def is_blocked(self) -> bool: + return self.blocked + + @property + def team_id(self) -> Optional[str]: + if self.model_info: + return self.model_info.get("team_id") + return None + + @property + def team_public_model_name(self) -> Optional[str]: + if self.model_info: + return self.model_info.get("team_public_model_name") + return None diff --git a/litellm/models/object_permission.py b/litellm/models/object_permission.py new file mode 100644 index 00000000000..6c0d100046c --- /dev/null +++ b/litellm/models/object_permission.py @@ -0,0 +1,26 @@ +""" +Object permission table model. + +Canonical definition for ``litellm_objectpermissiontable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from typing import Dict, List, Optional + +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_ObjectPermissionTable(LiteLLMPydanticObjectBase): + """Represents a LiteLLM_ObjectPermissionTable record""" + + object_permission_id: str + mcp_servers: Optional[List[str]] = [] + mcp_access_groups: Optional[List[str]] = [] + mcp_tool_permissions: Optional[Dict[str, List[str]]] = None + vector_stores: Optional[List[str]] = [] + agents: Optional[List[str]] = [] + agent_access_groups: Optional[List[str]] = [] + models: Optional[List[str]] = [] + mcp_toolsets: Optional[List[str]] = None + blocked_tools: Optional[List[str]] = [] + search_tools: Optional[List[str]] = [] diff --git a/litellm/models/organization.py b/litellm/models/organization.py new file mode 100644 index 00000000000..8b2d95c3e09 --- /dev/null +++ b/litellm/models/organization.py @@ -0,0 +1,31 @@ +""" +Organization table model. + +Canonical definition for ``litellm_organizationtable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from typing import List, Optional + +from litellm.models.budget import LiteLLM_BudgetTable +from litellm.models.object_permission import LiteLLM_ObjectPermissionTable +from litellm.models.user import LiteLLM_UserTable +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_OrganizationTable(LiteLLMPydanticObjectBase): + """Represents user-controllable params for a LiteLLM_OrganizationTable record""" + + organization_id: Optional[str] = None + organization_alias: Optional[str] = None + budget_id: str + spend: float = 0.0 + metadata: Optional[dict] = None + models: List[str] = [] + model_spend: Optional[dict] = {} + created_by: str + updated_by: str + users: Optional[List[LiteLLM_UserTable]] = None + litellm_budget_table: Optional[LiteLLM_BudgetTable] = None + object_permission: Optional[LiteLLM_ObjectPermissionTable] = None + object_permission_id: Optional[str] = None diff --git a/litellm/models/organization_membership.py b/litellm/models/organization_membership.py new file mode 100644 index 00000000000..9957c0c21af --- /dev/null +++ b/litellm/models/organization_membership.py @@ -0,0 +1,40 @@ +""" +Organization membership table model. + +Canonical definition for ``litellm_organizationmembership``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import Any, Optional + +from pydantic import ConfigDict, model_validator + +from litellm.models.budget import LiteLLM_BudgetTable +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_OrganizationMembershipTable(LiteLLMPydanticObjectBase): + """Tracks which organizations a user belongs to and their spend within it.""" + + user_id: str + organization_id: str + user_role: Optional[str] = None + spend: float = 0.0 + budget_id: Optional[str] = None + created_at: datetime + updated_at: datetime + user: Optional[Any] = None + litellm_budget_table: Optional[LiteLLM_BudgetTable] = None + user_email: Optional[str] = None + + model_config = ConfigDict(protected_namespaces=()) + + @model_validator(mode="after") + def populate_user_email(self) -> "LiteLLM_OrganizationMembershipTable": + if self.user_email is None and self.user is not None: + if isinstance(self.user, dict): + self.user_email = self.user.get("user_email") + else: + self.user_email = getattr(self.user, "user_email", None) + return self diff --git a/litellm/models/project.py b/litellm/models/project.py new file mode 100644 index 00000000000..083c7ee3cc5 --- /dev/null +++ b/litellm/models/project.py @@ -0,0 +1,41 @@ +""" +Project table model. + +Canonical definition for ``litellm_projecttable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import List, Optional + +from litellm.models.budget import LiteLLM_BudgetTable +from litellm.models.object_permission import LiteLLM_ObjectPermissionTable +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_ProjectTable(LiteLLMPydanticObjectBase): + """Database model representation for project""" + + project_id: str + project_alias: Optional[str] = None + description: Optional[str] = None + team_id: Optional[str] = None + budget_id: Optional[str] = None + metadata: Optional[dict] = None + models: List[str] = [] + spend: float = 0.0 + model_spend: Optional[dict] = None + model_rpm_limit: Optional[dict] = None + model_tpm_limit: Optional[dict] = None + blocked: bool = False + object_permission_id: Optional[str] = None + created_by: Optional[str] = None + updated_by: Optional[str] = None + created_at: Optional[datetime] = None + updated_at: Optional[datetime] = None + litellm_budget_table: Optional[LiteLLM_BudgetTable] = None + object_permission: Optional[LiteLLM_ObjectPermissionTable] = None + + @property + def is_blocked(self) -> bool: + return self.blocked diff --git a/litellm/models/skills.py b/litellm/models/skills.py new file mode 100644 index 00000000000..62091c0ca01 --- /dev/null +++ b/litellm/models/skills.py @@ -0,0 +1,30 @@ +""" +Skills table model. + +Canonical definition for ``litellm_skillstable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import Any, Dict, Optional + +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_SkillsTable(LiteLLMPydanticObjectBase): + """Represents a LiteLLM_SkillsTable record""" + + skill_id: str + display_title: Optional[str] = None + description: Optional[str] = None + instructions: Optional[str] = None + source: str = "custom" + latest_version: Optional[str] = None + file_content: Optional[bytes] = None + file_name: Optional[str] = None + file_type: Optional[str] = None + metadata: Optional[Dict[str, Any]] = None + created_at: Optional[datetime] = None + created_by: Optional[str] = None + updated_at: Optional[datetime] = None + updated_by: Optional[str] = None diff --git a/litellm/models/spend_logs.py b/litellm/models/spend_logs.py new file mode 100644 index 00000000000..96bd328c3ca --- /dev/null +++ b/litellm/models/spend_logs.py @@ -0,0 +1,50 @@ +""" +Spend and error log table models. + +Canonical definitions for ``litellm_spendlogs`` and ``litellm_errorlogs``. +Re-exported from ``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import Optional, Union + +from pydantic import Json + +from litellm._uuid import uuid +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_SpendLogs(LiteLLMPydanticObjectBase): + request_id: str + api_key: str + model: Optional[str] = "" + api_base: Optional[str] = "" + call_type: str + spend: Optional[float] = 0.0 + total_tokens: Optional[int] = 0 + prompt_tokens: Optional[int] = 0 + completion_tokens: Optional[int] = 0 + startTime: Union[str, datetime, None] + endTime: Union[str, datetime, None] + user: Optional[str] = "" + metadata: Optional[Json] = {} + cache_hit: Optional[str] = "False" + cache_key: Optional[str] = None + request_tags: Optional[Json] = None + requester_ip_address: Optional[str] = None + messages: Optional[Union[str, list, dict]] + response: Optional[Union[str, list, dict]] + + +class LiteLLM_ErrorLogs(LiteLLMPydanticObjectBase): + request_id: Optional[str] = str(uuid.uuid4()) + api_base: Optional[str] = "" + model_group: Optional[str] = "" + litellm_model_name: Optional[str] = "" + model_id: Optional[str] = "" + request_kwargs: Optional[dict] = {} + exception_type: Optional[str] = "" + status_code: Optional[str] = "" + exception_string: Optional[str] = "" + startTime: Union[str, datetime, None] + endTime: Union[str, datetime, None] diff --git a/litellm/models/tag.py b/litellm/models/tag.py new file mode 100644 index 00000000000..02d8f58916d --- /dev/null +++ b/litellm/models/tag.py @@ -0,0 +1,36 @@ +""" +Tag table model. + +Canonical definition for ``litellm_tagtable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import List, Optional + +from pydantic import model_validator + +from litellm.models.budget import LiteLLM_BudgetTable +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_TagTable(LiteLLMPydanticObjectBase): + tag_name: str + description: Optional[str] = None + models: List[str] = [] + model_info: Optional[dict] = None + spend: float = 0.0 + budget_id: Optional[str] = None + litellm_budget_table: Optional[LiteLLM_BudgetTable] = None + created_at: Optional[datetime] = None + created_by: Optional[str] = None + updated_at: Optional[datetime] = None + + @model_validator(mode="before") + @classmethod + def set_model_info(cls, values): + if values.get("spend") is None: + values.update({"spend": 0.0}) + if values.get("models") is None: + values.update({"models": []}) + return values diff --git a/litellm/models/team.py b/litellm/models/team.py new file mode 100644 index 00000000000..aa0798955f2 --- /dev/null +++ b/litellm/models/team.py @@ -0,0 +1,154 @@ +""" +Team table models. + +Canonical definitions for ``litellm_teamtable`` (plus the shared Member and +budget-window value types and the team-model alias table). Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +import json +from datetime import datetime +from typing import List, Literal, Optional, Union + +from pydantic import BaseModel, ConfigDict, Field, model_validator + +from litellm.models.object_permission import LiteLLM_ObjectPermissionTable +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class MemberBase(LiteLLMPydanticObjectBase): + user_id: Optional[str] = Field( + default=None, + description="The unique ID of the user to add. Either user_id or user_email must be provided", + ) + user_email: Optional[str] = Field( + default=None, + description="The email address of the user to add. Either user_id or user_email must be provided", + ) + + @model_validator(mode="before") + @classmethod + def check_user_info(cls, values): + if not isinstance(values, dict): + raise ValueError("input needs to be a dictionary") + if values.get("user_id") is None and values.get("user_email") is None: + raise ValueError("Either user id or user email must be provided") + return values + + +class Member(MemberBase): + role: Literal["admin", "user"] = Field( + description="The role of the user within the team. 'admin' users can manage team settings and members, 'user' is a regular team member" + ) + + +class BudgetLimitEntry(LiteLLMPydanticObjectBase): + """A single budget window with its own limit and independent reset schedule.""" + + budget_duration: str + max_budget: float + reset_at: Optional[datetime] = None + + +class LiteLLM_ModelTable(LiteLLMPydanticObjectBase): + id: Optional[int] = None + model_aliases: Optional[Union[str, dict]] = None + created_by: str + updated_by: str + team: Optional["LiteLLM_TeamTable"] = None + + model_config = ConfigDict(protected_namespaces=()) + + +class TeamBase(LiteLLMPydanticObjectBase): + team_alias: Optional[str] = None + team_id: Optional[str] = None + organization_id: Optional[str] = None + admins: list = [] + members: list = [] + members_with_roles: List[Member] = [] + team_member_permissions: Optional[List[str]] = None + metadata: Optional[dict] = None + tpm_limit: Optional[int] = None + rpm_limit: Optional[int] = None + max_budget: Optional[float] = None + soft_budget: Optional[float] = None + budget_duration: Optional[str] = None + budget_limits: Optional[List[BudgetLimitEntry]] = None + models: list = [] + blocked: bool = False + router_settings: Optional[dict] = None + access_group_ids: Optional[List[str]] = None + default_team_member_models: Optional[List[str]] = None + + +class LiteLLM_TeamTable(TeamBase): + team_id: str # type: ignore + spend: Optional[float] = None + max_parallel_requests: Optional[int] = None + budget_duration: Optional[str] = None + budget_reset_at: Optional[datetime] = None + model_id: Optional[int] = None + model_spend: Optional[dict] = {} + model_max_budget: Optional[dict] = {} + policies: Optional[List[str]] = None + allow_team_guardrail_config: Optional[bool] = False + litellm_model_table: Optional[LiteLLM_ModelTable] = None + object_permission: Optional[LiteLLM_ObjectPermissionTable] = None + object_permission_id: Optional[str] = None + updated_at: Optional[datetime] = None + created_at: Optional[datetime] = None + + model_config = ConfigDict(protected_namespaces=()) + + @model_validator(mode="before") + @classmethod + def set_model_info(cls, values): + dict_fields = [ + "metadata", + "aliases", + "config", + "permissions", + "model_max_budget", + "model_aliases", + "router_settings", + "budget_limits", + ] + + if isinstance(values, BaseModel): + values = values.model_dump() + + if ( + isinstance(values.get("members_with_roles"), dict) + and not values["members_with_roles"] + ): + values["members_with_roles"] = [] + + for field in dict_fields: + value = values.get(field) + if value is not None and isinstance(value, str): + try: + values[field] = json.loads(value) + except json.JSONDecodeError: + raise ValueError(f"Field {field} should be a valid dictionary") + + return values + + +class LiteLLM_TeamTableCachedObj(LiteLLM_TeamTable): + last_refreshed_at: Optional[float] = None + + +class LiteLLM_DeletedTeamTable(LiteLLM_TeamTable): + """Audit record for deleted teams; mirrors the team plus deletion metadata.""" + + id: Optional[str] = None + deleted_at: Optional[datetime] = None + deleted_by: Optional[str] = None + deleted_by_api_key: Optional[str] = None + litellm_changed_by: Optional[str] = None + + model_config = ConfigDict(protected_namespaces=()) + + +LiteLLM_ModelTable.model_rebuild() diff --git a/litellm/models/team_membership.py b/litellm/models/team_membership.py new file mode 100644 index 00000000000..d0a1308ce7c --- /dev/null +++ b/litellm/models/team_membership.py @@ -0,0 +1,32 @@ +""" +Team membership table model. + +Canonical definition for ``litellm_teammembership``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from typing import Optional, Union + +from litellm.models.budget import LiteLLM_BudgetTable, LiteLLM_BudgetTableFull +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_TeamMembership(LiteLLMPydanticObjectBase): + user_id: str + team_id: str + budget_id: Optional[str] = None + spend: Optional[float] = 0.0 + total_spend: Optional[float] = 0.0 + litellm_budget_table: Optional[ + Union[LiteLLM_BudgetTableFull, LiteLLM_BudgetTable] + ] = None + + def safe_get_team_member_rpm_limit(self) -> Optional[int]: + if self.litellm_budget_table is not None: + return self.litellm_budget_table.rpm_limit + return None + + def safe_get_team_member_tpm_limit(self) -> Optional[int]: + if self.litellm_budget_table is not None: + return self.litellm_budget_table.tpm_limit + return None diff --git a/litellm/models/user.py b/litellm/models/user.py new file mode 100644 index 00000000000..cd7e9db4aec --- /dev/null +++ b/litellm/models/user.py @@ -0,0 +1,70 @@ +""" +User table model. + +Canonical definition for ``litellm_usertable``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import Dict, List, Optional + +from pydantic import ConfigDict, Field, model_validator + +from litellm.models.object_permission import LiteLLM_ObjectPermissionTable +from litellm.models.organization_membership import ( + LiteLLM_OrganizationMembershipTable, +) +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_UserTable(LiteLLMPydanticObjectBase): + user_id: str + user_alias: Optional[str] = None + team_id: Optional[str] = None + sso_user_id: Optional[str] = None + organization_id: Optional[str] = None + object_permission_id: Optional[str] = None + password: Optional[str] = Field(default=None, exclude=True) + teams: List[str] = [] + user_role: Optional[str] = None + max_budget: Optional[float] = None + spend: float = 0.0 + user_email: Optional[str] = None + models: list = [] + metadata: Optional[dict] = None + max_parallel_requests: Optional[int] = None + tpm_limit: Optional[int] = None + rpm_limit: Optional[int] = None + budget_duration: Optional[str] = None + budget_reset_at: Optional[datetime] = None + allowed_cache_controls: List[str] = [] + policies: List[str] = [] + model_spend: Optional[Dict] = {} + model_max_budget: Optional[Dict] = {} + created_at: Optional[datetime] = None + updated_at: Optional[datetime] = None + organization_memberships: Optional[List[LiteLLM_OrganizationMembershipTable]] = None + object_permission: Optional[LiteLLM_ObjectPermissionTable] = None + + model_config = ConfigDict(protected_namespaces=()) + + @model_validator(mode="before") + @classmethod + def set_model_info(cls, values): + if values.get("spend") is None: + values.update({"spend": 0.0}) + if values.get("models") is None: + values.update({"models": []}) + if values.get("teams") is None: + values.update({"teams": []}) + return values + + def is_over_budget(self) -> bool: + if self.max_budget is None: + return False + return self.spend >= self.max_budget + + def has_model_access(self, model_name: str) -> bool: + if not self.models: + return True + return model_name in self.models diff --git a/litellm/models/verification_token.py b/litellm/models/verification_token.py new file mode 100644 index 00000000000..8bddd1c1619 --- /dev/null +++ b/litellm/models/verification_token.py @@ -0,0 +1,74 @@ +""" +Verification token table model. + +Canonical definition for ``litellm_verificationtoken``. Re-exported from +``litellm.proxy._types`` for backwards compatibility. +""" + +from datetime import datetime +from typing import Dict, List, Optional, Union + +from pydantic import ConfigDict + +from litellm.models.object_permission import LiteLLM_ObjectPermissionTable +from litellm.types.llms.base import LiteLLMPydanticObjectBase + + +class LiteLLM_VerificationToken(LiteLLMPydanticObjectBase): + token: Optional[str] = None + key_name: Optional[str] = None + key_alias: Optional[str] = None + spend: float = 0.0 + max_budget: Optional[float] = None + expires: Optional[Union[str, datetime]] = None + models: List = [] + aliases: Dict = {} + config: Dict = {} + user_id: Optional[str] = None + team_id: Optional[str] = None + agent_id: Optional[str] = None + project_id: Optional[str] = None + max_parallel_requests: Optional[int] = None + metadata: Dict = {} + tpm_limit: Optional[int] = None + rpm_limit: Optional[int] = None + budget_duration: Optional[str] = None + budget_reset_at: Optional[datetime] = None + allowed_cache_controls: Optional[list] = [] + allowed_routes: Optional[list] = [] + permissions: Dict = {} + model_spend: Dict = {} + model_max_budget: Dict = {} + soft_budget_cooldown: bool = False + blocked: Optional[bool] = None + litellm_budget_table: Optional[dict] = None + budget_id: Optional[str] = None + org_id: Optional[str] = None # org id for a given key + created_at: Optional[datetime] = None + created_by: Optional[str] = None + updated_at: Optional[datetime] = None + updated_by: Optional[str] = None + last_active: Optional[datetime] = None + object_permission_id: Optional[str] = None + object_permission: Optional[LiteLLM_ObjectPermissionTable] = None + access_group_ids: Optional[List[str]] = None + rotation_count: Optional[int] = 0 + auto_rotate: Optional[bool] = False + rotation_interval: Optional[str] = None + last_rotation_at: Optional[datetime] = None + key_rotation_at: Optional[datetime] = None + router_settings: Optional[dict] = None + budget_limits: Optional[List[dict]] = None + model_config = ConfigDict(protected_namespaces=()) + + +class LiteLLM_DeletedVerificationToken(LiteLLM_VerificationToken): + """Audit record for deleted keys; mirrors the token plus deletion metadata.""" + + id: Optional[str] = None + deleted_at: Optional[datetime] = None + deleted_by: Optional[str] = None + deleted_by_api_key: Optional[str] = None + litellm_changed_by: Optional[str] = None + + model_config = ConfigDict(protected_namespaces=()) diff --git a/litellm/mypy.ini b/litellm/mypy.ini deleted file mode 100644 index 4702b591124..00000000000 --- a/litellm/mypy.ini +++ /dev/null @@ -1,19 +0,0 @@ -[mypy] -warn_return_any = False -ignore_missing_imports = True -mypy_path = litellm/stubs -namespace_packages = True -disable_error_code = - valid-type, - annotation-unchecked, - import-untyped - -[mypy-google.*] -ignore_missing_imports = True - -[mypy-cryptography.hazmat.bindings._rust.x509] -ignore_errors = True - -[mypy-fastuuid.*] -ignore_missing_imports = True -ignore_errors = True \ No newline at end of file diff --git a/litellm/passthrough/main.py b/litellm/passthrough/main.py index c4c9aea6f64..3e60988b9e7 100644 --- a/litellm/passthrough/main.py +++ b/litellm/passthrough/main.py @@ -20,7 +20,6 @@ from typing import ( import httpx from httpx._types import CookieTypes, QueryParamTypes, RequestFiles -import litellm from litellm._logging import verbose_logger from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler @@ -201,12 +200,6 @@ def llm_passthrough_route( _is_async = allm_passthrough_route - if client is None: - if _is_async: - client = litellm.module_level_aclient - else: - client = litellm.module_level_client - litellm_logging_obj = cast("LiteLLMLoggingObj", kwargs.get("litellm_logging_obj")) model, custom_llm_provider, api_key, api_base = get_llm_provider( @@ -218,6 +211,26 @@ def llm_passthrough_route( litellm_params_dict = get_litellm_params(**kwargs) + if client is None: + from litellm.llms.custom_httpx.http_handler import ( + _get_httpx_client, + get_async_httpx_client, + ) + from litellm.passthrough.timeout_utils import resolve_llm_passthrough_timeout + from litellm.types.llms.custom_http import httpxSpecialProvider + + resolved_timeout = resolve_llm_passthrough_timeout( + kwargs=kwargs, + litellm_params=litellm_params_dict, + ) + if _is_async: + client = get_async_httpx_client( + llm_provider=httpxSpecialProvider.PassThroughEndpoint, + params={"timeout": resolved_timeout}, + ) + else: + client = _get_httpx_client(params={"timeout": resolved_timeout}) + # Add model_id to litellm_params if present in kwargs (for Bedrock Application Inference Profiles) if "model_id" in kwargs: litellm_params_dict["model_id"] = kwargs["model_id"] diff --git a/litellm/passthrough/timeout_utils.py b/litellm/passthrough/timeout_utils.py new file mode 100644 index 00000000000..a423db2aa91 --- /dev/null +++ b/litellm/passthrough/timeout_utils.py @@ -0,0 +1,58 @@ +import sys +from typing import Optional + +DEFAULT_PASS_THROUGH_REQUEST_TIMEOUT_SECONDS = 600.0 + + +def resolve_pass_through_request_timeout( + endpoint_timeout: Optional[float] = None, +) -> float: + """ + Resolve the upstream httpx timeout for pass_through_request. + + Precedence: per-endpoint timeout -> general_settings.pass_through_request_timeout -> 600s default. + + Uses sys.modules to read general_settings only when the proxy module is already + loaded, avoiding a fastapi transitive import in pure SDK contexts. + """ + if endpoint_timeout is not None: + return float(endpoint_timeout) + + try: + proxy_server = sys.modules.get("litellm.proxy.proxy_server") + if proxy_server is not None: + global_timeout = getattr(proxy_server, "general_settings", {}).get( + "pass_through_request_timeout" + ) + if global_timeout is not None: + return float(global_timeout) + except Exception: + pass + + return DEFAULT_PASS_THROUGH_REQUEST_TIMEOUT_SECONDS + + +def resolve_llm_passthrough_timeout( + kwargs: Optional[dict] = None, + litellm_params: Optional[dict] = None, + router_timeout: Optional[float] = None, +) -> float: + """ + Resolve upstream httpx timeout for SDK native passthrough (e.g. Bedrock /converse). + + Precedence: kwargs timeout/request_timeout -> litellm_params timeout/request_timeout + -> router_timeout -> general_settings.pass_through_request_timeout -> 600s default. + """ + kwargs = kwargs or {} + litellm_params = litellm_params or {} + + for source in (kwargs, litellm_params): + for key in ("timeout", "request_timeout"): + val = source.get(key) + if val is not None: + return float(val) + + if router_timeout is not None: + return float(router_timeout) + + return resolve_pass_through_request_timeout() diff --git a/litellm/provider_endpoints_support_backup.json b/litellm/provider_endpoints_support_backup.json index e0eeb014c51..db6183edaa0 100644 --- a/litellm/provider_endpoints_support_backup.json +++ b/litellm/provider_endpoints_support_backup.json @@ -1288,6 +1288,23 @@ "interactions": true } }, + "libertai": { + "display_name": "LibertAI (`libertai`)", + "url": "https://docs.litellm.ai/docs/providers/libertai", + "endpoints": { + "chat_completions": true, + "messages": true, + "responses": false, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false + } + }, "litellm_proxy": { "display_name": "LiteLLM Proxy (`litellm_proxy`)", "url": "https://docs.litellm.ai/docs/providers/litellm_proxy", 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 863e6acd41e..e47fc84b533 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 @@ -14,8 +14,12 @@ from litellm.proxy._types import ( SpecialHeaders, UserAPIKeyAuth, ) -from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.proxy.auth.ip_address_utils import IPAddressUtils +from litellm.proxy.auth.user_api_key_auth import user_api_key_auth +from litellm.repositories.table_repositories import ( + AgentsRepository, + MCPServerRepository, +) def _parse_mcp_server_names_from_path( @@ -63,9 +67,10 @@ def _is_mcp_passthrough_cold_start( spec-compliant WWW-Authenticate challenge instead of surfacing a generic admission error. - Uses "all" semantics (mirrors :meth:`MCPRequestHandler._target_servers_use_oauth2`): - one non-passthrough target in a co-targeted set must not flip the bypass - open for the others. Fails closed when any target cannot be resolved.""" + Uses "all" semantics (mirrors + :meth:`MCPRequestHandler._target_servers_delegate_auth_to_upstream`): one + non-passthrough target in a co-targeted set must not flip the bypass open + for the others. Fails closed when any target cannot be resolved.""" if not mcp_servers: return False from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( @@ -120,7 +125,7 @@ class MCPRequestHandler: LITELLM_MCP_ACCESS_GROUPS_HEADER_NAME = SpecialHeaders.mcp_access_groups.value @staticmethod - async def process_mcp_request( # noqa: PLR0915 + async def process_mcp_request( scope: Scope, ) -> Tuple[ UserAPIKeyAuth, @@ -210,101 +215,64 @@ class MCPRequestHandler: # Only OAuth metadata routes registered under /.well-known/ are public. if request_route.startswith("/.well-known/"): validated_user_api_key_auth = UserAPIKeyAuth() - elif ( - not litellm_api_key - and MCPRequestHandler._target_servers_delegate_auth_to_upstream( # noqa: E501 - path=request_route, - mcp_servers=mcp_servers, - client_ip=IPAddressUtils.get_mcp_client_ip(request), - ) - ): - # Operator opted this oauth2 server into upstream-delegated auth - # (PKCE passthrough): skip LiteLLM API-key/SSO entirely so the - # client authenticates directly with the upstream MCP server. - # Fires ONLY when neither x-litellm-api-key nor Authorization is - # present. If any LiteLLM key is supplied (primary or secondary - # header), we fall through so user_id is resolved, spend/rate - # limiting apply, and any stored OAuth token can be retrieved - # and forwarded upstream. Gated by - # _target_servers_delegate_auth_to_upstream, which only returns - # True when EVERY target is auth_type=oauth2 AND has the - # delegate_auth_to_upstream flag set — fails closed otherwise. - validated_user_api_key_auth = UserAPIKeyAuth() elif has_explicit_litellm_key: - # Explicit x-litellm-api-key provided - always validate normally + # An explicit x-litellm-api-key is always a LiteLLM credential, even + # for a delegated server, so validate it: identity / spend / rate + # limits resolve and any stored upstream token can be forwarded. validated_user_api_key_auth = await user_api_key_auth( api_key=litellm_api_key, request=request ) + elif MCPRequestHandler._target_servers_delegate_auth_to_upstream( + path=request_route, + mcp_servers=mcp_servers, + client_ip=IPAddressUtils.get_mcp_client_ip(request), + ): + # Operator opted this oauth2 server into upstream-delegated auth: the + # client authenticates directly with the upstream MCP server, so any + # Authorization bearer is an upstream token, never a LiteLLM key. Skip + # LiteLLM validation entirely — covering both the no-credential + # discovery request and the authenticated call carrying the upstream + # bearer — so a tool call that succeeds never carries a phantom 401 + # auth span; the bearer is forwarded upstream unchanged. Gated by + # _target_servers_delegate_auth_to_upstream, which returns True only + # when EVERY target is auth_type=oauth2 with delegate_auth_to_upstream + # set; fails closed otherwise. + validated_user_api_key_auth = UserAPIKeyAuth() elif oauth2_headers: - # No x-litellm-api-key, but Authorization header present. - # Could be a LiteLLM key (backward compat) OR an opaque OAuth2 token - # the operator wants forwarded to an upstream OAuth2-mode MCP server. - # Try LiteLLM auth first; on auth failure, only fall back to anonymous - # passthrough when the request actually targets a server whose operator - # configured ``auth_type=oauth2``. For any other server (api_key, - # bearer_token, basic, etc.), a failed LiteLLM auth is a real failure - # and must propagate — otherwise an attacker can exchange any garbage - # bearer for an anonymous session. + # Authorization on a non-delegated server: the bearer must be a real + # LiteLLM credential, so a failed validation is a genuine 401/403 and + # propagates. The sole anonymous fallback is the auth_type=none + # pass-through cold-start (RFC 9728 discovery return), gated on a 401 + # so a recognized-but-forbidden key still fails closed. + client_ip = IPAddressUtils.get_mcp_client_ip(request) try: validated_user_api_key_auth = await user_api_key_auth( api_key=litellm_api_key, request=request ) except (HTTPException, ProxyException) as e: - # HTTPException.status_code is int; ProxyException.code is - # normalized to str in its __init__ but can be ``"None"`` or any - # non-numeric string when the caller didn't supply a numeric - # code, so we compare against both int and str forms rather - # than coercing (``int("None")`` would raise ValueError and - # rewrite the auth error as a 500). + # ProxyException.code is normalized to str (possibly "None"), so + # compare both int and str forms rather than coercing. status = e.status_code if isinstance(e, HTTPException) else e.code - is_auth_error = status in (401, 403, "401", "403") is_unauthenticated = status in (401, "401") - client_ip = IPAddressUtils.get_mcp_client_ip(request) - if is_auth_error and MCPRequestHandler._target_servers_use_oauth2( - path=request_route, - mcp_servers=mcp_servers, - client_ip=client_ip, + mcp_servers_from_path = _parse_mcp_server_names_from_path( + request_route, mcp_servers + ) + if ( + is_unauthenticated + and mcp_servers_from_path is not None + and not _has_client_supplied_mcp_auth( + mcp_auth_header, + mcp_server_auth_headers, + ) + and _is_mcp_passthrough_cold_start( + mcp_servers_from_path, client_ip=client_ip + ) ): verbose_logger.debug( - "MCP OAuth2: target server is OAuth2-mode, treating " - "Authorization as upstream OAuth2 token passthrough" + "MCP pass-through return: forwarding Authorization as " + "upstream OAuth token for delegated auth" ) validated_user_api_key_auth = UserAPIKeyAuth() - elif is_unauthenticated: - # Pass-through cold-start return: per RFC 9728 / MCP - # Authorization spec the client completes upstream OAuth - # discovery and returns with ``Authorization: Bearer - # ``. For ``auth_type=none`` passthrough - # servers that bearer is not a LiteLLM key (auth above - # failed) but is meant to be forwarded upstream - # unchanged. Fall back to anonymous admission so the - # caller is not rejected for following the discovery - # flow without also setting ``x-litellm-api-key``. - # Only trigger on 401 (token unrecognized); a 403 means - # the key WAS recognized but is forbidden (e.g. over - # budget / rate limited) and must propagate so those - # controls are not bypassed via anonymous admission. - mcp_servers_from_path = _parse_mcp_server_names_from_path( - request_route, mcp_servers - ) - if ( - mcp_servers_from_path is not None - and not _has_client_supplied_mcp_auth( - mcp_auth_header, - mcp_server_auth_headers, - ) - and _is_mcp_passthrough_cold_start( - mcp_servers_from_path, client_ip=client_ip - ) - ): - verbose_logger.debug( - "MCP pass-through return: target server is " - "passthrough, treating Authorization as " - "upstream OAuth token for delegated auth" - ) - validated_user_api_key_auth = UserAPIKeyAuth() - else: - raise else: raise else: @@ -408,45 +376,6 @@ class MCPRequestHandler: return [single_server_match.group(1)] return [servers_and_path] - @staticmethod - def _target_servers_use_oauth2( - path: str, mcp_servers: Optional[List[str]], client_ip: Optional[str] - ) -> bool: - """ - True only when EVERY MCP server the request targets is configured for - ``auth_type == oauth2``. If any target is non-OAuth2 — or if the target - cannot be resolved at all — return False so the caller fails closed. - - Used to gate the "treat Authorization as opaque OAuth2 token" fallback - in :meth:`process_mcp_request` so a failed LiteLLM-auth cannot be - exchanged for an anonymous session against a non-OAuth2 server. - """ - # Inline imports avoid a circular dependency: mcp_server_manager imports - # from this module. - from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( - global_mcp_server_manager, - ) - from litellm.types.mcp import MCPAuth - - # Resolve the same target list downstream routing will use. For - # ``/mcp/...`` routes, ``extract_mcp_auth_context`` overrides the - # ``x-mcp-servers`` header with path-derived names, so we must mirror - # that here — otherwise a caller could set the header to a permissive - # server while the path targets a stricter one (header/path TOCTOU). - target_names = MCPRequestHandler._resolve_target_server_names( - path=path, mcp_servers_header=mcp_servers - ) - if not target_names: - return False - - for name in target_names: - server = global_mcp_server_manager.get_mcp_server_by_name( - name, client_ip=client_ip - ) - if server is None or server.auth_type != MCPAuth.oauth2: - return False - return True - @staticmethod def _target_servers_delegate_auth_to_upstream( path: str, mcp_servers: Optional[List[str]], client_ip: Optional[str] @@ -468,8 +397,8 @@ class MCPRequestHandler: ) from litellm.types.mcp import MCPAuth - # See _target_servers_use_oauth2: must mirror the downstream - # header-vs-path override or an attacker could set + # Must mirror the downstream header-vs-path override + # (``extract_mcp_auth_context``) or an attacker could set # ``x-mcp-servers`` to a delegate-enabled server while the URL path # targets a non-delegate server, skipping LiteLLM auth for it. target_names = MCPRequestHandler._resolve_target_server_names( @@ -1445,7 +1374,7 @@ class MCPRequestHandler: return None if object_permission_id is None: - agent_row = await prisma_client.db.litellm_agentstable.find_unique( + agent_row = await AgentsRepository(prisma_client).table.find_unique( where={"agent_id": agent_id}, ) object_permission_id = ( @@ -1600,7 +1529,7 @@ class MCPRequestHandler: server_ids: Set[str] = set() if access_groups and prisma_client is not None: try: - mcp_servers = await prisma_client.db.litellm_mcpservertable.find_many( + mcp_servers = await MCPServerRepository(prisma_client).table.find_many( where={"mcp_access_groups": {"hasSome": access_groups}} ) for server in mcp_servers: diff --git a/litellm/proxy/_experimental/mcp_server/db.py b/litellm/proxy/_experimental/mcp_server/db.py index 0ba0181200f..8edb831a9df 100644 --- a/litellm/proxy/_experimental/mcp_server/db.py +++ b/litellm/proxy/_experimental/mcp_server/db.py @@ -8,6 +8,7 @@ from typing import Any, Dict, Iterable, List, Optional, Set, Union, cast from litellm._logging import verbose_proxy_logger from litellm._uuid import uuid from litellm.constants import MCP_PER_USER_TOKEN_EXPIRY_BUFFER_SECONDS +from litellm.llms.custom_httpx.http_handler import get_async_httpx_client from litellm.proxy._types import ( LiteLLM_MCPServerTable, LiteLLM_ObjectPermissionTable, @@ -25,8 +26,16 @@ from litellm.proxy.common_utils.encrypt_decrypt_utils import ( decrypt_value_helper, encrypt_value_helper, ) -from litellm.llms.custom_httpx.http_handler import get_async_httpx_client from litellm.proxy.utils import PrismaClient +from litellm.repositories.object_permission_repository import ObjectPermissionRepository +from litellm.repositories.table_repositories import ( + MCPServerRepository, + MCPUserCredentialsRepository, +) +from litellm.repositories.team_repository import TeamRepository +from litellm.repositories.verification_token_repository import ( + VerificationTokenRepository, +) from litellm.types.llms.custom_http import httpxSpecialProvider from litellm.types.mcp import MCPCredentials @@ -354,7 +363,7 @@ async def get_all_mcp_servers( where: Dict[str, Any] = {} if approval_status is not None: where["approval_status"] = approval_status - mcp_servers = await prisma_client.db.litellm_mcpservertable.find_many( + mcp_servers = await MCPServerRepository(prisma_client).table.find_many( where=where if where else {} ) @@ -380,7 +389,9 @@ async def get_mcp_server( """ Returns the matching mcp server from the db iff exists """ - mcp_server = await prisma_client.db.litellm_mcpservertable.find_unique( + mcp_server: Optional[LiteLLM_MCPServerTable] = await MCPServerRepository( + prisma_client + ).table.find_unique( where={ "server_id": server_id, } @@ -398,12 +409,12 @@ async def get_mcp_servers( """ Returns the matching mcp servers from the db with the server_ids """ - _mcp_servers: List[LiteLLM_MCPServerTable] = ( - await prisma_client.db.litellm_mcpservertable.find_many( - where={ - "server_id": {"in": server_ids}, - } - ) + _mcp_servers: List[LiteLLM_MCPServerTable] = await MCPServerRepository( + prisma_client + ).table.find_many( + where={ + "server_id": {"in": server_ids}, + } ) final_mcp_servers: List[LiteLLM_MCPServerTable] = [] for _mcp_server in _mcp_servers: @@ -420,15 +431,15 @@ async def get_mcp_servers_by_verificationtoken( """ Returns the mcp servers from the db for the verification token """ - verification_token_record: LiteLLM_TeamTable = ( - await prisma_client.db.litellm_verificationtoken.find_unique( - where={ - "token": token, - }, - include={ - "object_permission": True, - }, - ) + verification_token_record: LiteLLM_TeamTable = await VerificationTokenRepository( + prisma_client + ).table.find_unique( + where={ + "token": token, + }, + include={ + "object_permission": True, + }, ) mcp_servers: Optional[List[str]] = [] @@ -446,15 +457,15 @@ async def get_mcp_servers_by_team( """ Returns the mcp servers from the db for the team id """ - team_record: LiteLLM_TeamTable = ( - await prisma_client.db.litellm_teamtable.find_unique( - where={ - "team_id": team_id, - }, - include={ - "object_permission": True, - }, - ) + team_record: LiteLLM_TeamTable = await TeamRepository( + prisma_client + ).table.find_unique( + where={ + "team_id": team_id, + }, + include={ + "object_permission": True, + }, ) mcp_servers: Optional[List[str]] = [] @@ -505,16 +516,16 @@ async def get_objectpermissions_for_mcp_server( """ Get all the object permissions records and the associated team and verficiationtoken records that have access to the mcp server """ - object_permission_records = ( - await prisma_client.db.litellm_objectpermissiontable.find_many( - where={ - "mcp_servers": {"has": mcp_server_id}, - }, - include={ - "teams": True, - "verification_tokens": True, - }, - ) + object_permission_records = await ObjectPermissionRepository( + prisma_client + ).table.find_many( + where={ + "mcp_servers": {"has": mcp_server_id}, + }, + include={ + "teams": True, + "verification_tokens": True, + }, ) return object_permission_records @@ -526,7 +537,7 @@ async def get_virtualkeys_for_mcp_server( """ Get all the virtual keys that have access to the mcp server """ - virtual_keys = await prisma_client.db.litellm_verificationtoken.find_many( + virtual_keys = await VerificationTokenRepository(prisma_client).table.find_many( where={ "mcp_servers": {"has": server_id}, }, @@ -557,30 +568,35 @@ async def delete_mcp_server( """ Delete the mcp server from the db by server_id - The server-row delete is the commit point. Per-user env var rows have no FK - cascade, so they are cleaned up afterwards on a best-effort basis: a transient - failure there leaves only orphaned rows pointing at a now-missing server and - must not turn a successful delete into a caller-visible error. + The server-row delete is the commit point. Per-user credential and env var + rows have no FK cascade, so they are cleaned up afterwards on a best-effort + basis: a transient failure there leaves only orphaned rows pointing at a + now-missing server and must not turn a successful delete into a + caller-visible error. Each table is cleaned independently so a failure on one + still attempts the other. Returns the deleted mcp server record if it exists, otherwise None """ - deleted_server = await prisma_client.db.litellm_mcpservertable.delete( + deleted_server = await MCPServerRepository(prisma_client).table.delete( where={ "server_id": server_id, }, ) if deleted_server is not None: - try: - await prisma_client.db.litellm_mcpuserenvvars.delete_many( - where={"server_id": server_id} - ) - except Exception as e: - verbose_proxy_logger.warning( - "MCP server %s deleted but per-user env var cleanup failed; " - "orphaned rows can be removed on a later delete: %s", - server_id, - e, - ) + for model, label in ( + (prisma_client.db.litellm_mcpusercredentials, "credential"), + (prisma_client.db.litellm_mcpuserenvvars, "env var"), + ): + try: + await model.delete_many(where={"server_id": server_id}) + except Exception as e: + verbose_proxy_logger.warning( + "MCP server %s deleted but per-user %s cleanup failed; " + "orphaned rows can be removed on a later delete: %s", + server_id, + label, + e, + ) return deleted_server @@ -600,7 +616,7 @@ async def create_mcp_server( data_dict["created_by"] = touched_by data_dict["updated_by"] = touched_by - new_mcp_server = await prisma_client.db.litellm_mcpservertable.create( + new_mcp_server = await MCPServerRepository(prisma_client).table.create( data=data_dict # type: ignore ) @@ -635,7 +651,7 @@ async def update_mcp_server( "credentials" in data_dict and data_dict["credentials"] is not None ) if data.auth_type or has_credentials: - existing = await prisma_client.db.litellm_mcpservertable.find_unique( + existing = await MCPServerRepository(prisma_client).table.find_unique( where={"server_id": data.server_id} ) @@ -678,7 +694,7 @@ async def update_mcp_server( # Add audit fields data_dict["updated_by"] = touched_by - updated_mcp_server = await prisma_client.db.litellm_mcpservertable.update( + updated_mcp_server = await MCPServerRepository(prisma_client).table.update( where={"server_id": data.server_id}, data=data_dict # type: ignore ) @@ -691,7 +707,7 @@ async def rotate_mcp_server_credentials_master_key( ): from litellm.litellm_core_utils.safe_json_dumps import safe_dumps - mcp_servers = await prisma_client.db.litellm_mcpservertable.find_many() + mcp_servers = await MCPServerRepository(prisma_client).table.find_many() updated = 0 for mcp_server in mcp_servers: @@ -719,7 +735,7 @@ async def rotate_mcp_server_credentials_master_key( continue update_data["updated_by"] = touched_by - await prisma_client.db.litellm_mcpservertable.update( + await MCPServerRepository(prisma_client).table.update( where={"server_id": mcp_server.server_id}, data=update_data, ) @@ -781,7 +797,7 @@ async def rotate_mcp_user_credentials_master_key( under the new master key. Rows that are unreadable under both paths are logged and skipped so one corrupt row does not abort the rotation. """ - rows = await prisma_client.db.litellm_mcpusercredentials.find_many() + rows = await MCPUserCredentialsRepository(prisma_client).table.find_many() rotated = 0 skipped = 0 for row in rows: @@ -798,7 +814,7 @@ async def rotate_mcp_user_credentials_master_key( re_encrypted = encrypt_value_helper( plaintext, new_encryption_key=new_master_key ) - await prisma_client.db.litellm_mcpusercredentials.update( + await MCPUserCredentialsRepository(prisma_client).table.update( where={ "user_id_server_id": { "user_id": row.user_id, @@ -873,7 +889,7 @@ async def store_user_credential( """Store a user credential for a BYOK MCP server.""" encoded = encrypt_value_helper(credential) - await prisma_client.db.litellm_mcpusercredentials.upsert( + await MCPUserCredentialsRepository(prisma_client).table.upsert( where={"user_id_server_id": {"user_id": user_id, "server_id": server_id}}, data={ "create": { @@ -893,7 +909,7 @@ async def get_user_credential( ) -> Optional[str]: """Return credential for a user+server pair, or None.""" - row = await prisma_client.db.litellm_mcpusercredentials.find_unique( + row = await MCPUserCredentialsRepository(prisma_client).table.find_unique( where={"user_id_server_id": {"user_id": user_id, "server_id": server_id}} ) if row is None: @@ -907,7 +923,7 @@ async def has_user_credential( server_id: str, ) -> bool: """Return True if the user has a stored credential for this server.""" - row = await prisma_client.db.litellm_mcpusercredentials.find_unique( + row = await MCPUserCredentialsRepository(prisma_client).table.find_unique( where={"user_id_server_id": {"user_id": user_id, "server_id": server_id}} ) return row is not None @@ -919,7 +935,7 @@ async def delete_user_credential( server_id: str, ) -> None: """Delete the user's stored credential for a BYOK MCP server.""" - await prisma_client.db.litellm_mcpusercredentials.delete( + await MCPUserCredentialsRepository(prisma_client).table.delete( where={"user_id_server_id": {"user_id": user_id, "server_id": server_id}} ) @@ -966,7 +982,7 @@ async def store_user_oauth_credential( # Skip the guard when the caller knows the row is already an OAuth2 credential # (e.g. during token refresh), saving an extra DB round-trip. if not skip_byok_guard: - existing = await prisma_client.db.litellm_mcpusercredentials.find_unique( + existing = await MCPUserCredentialsRepository(prisma_client).table.find_unique( where={"user_id_server_id": {"user_id": user_id, "server_id": server_id}} ) if ( @@ -984,7 +1000,7 @@ async def store_user_oauth_credential( ) encoded = encrypt_value_helper(json.dumps(payload)) - await prisma_client.db.litellm_mcpusercredentials.upsert( + await MCPUserCredentialsRepository(prisma_client).table.upsert( where={"user_id_server_id": {"user_id": user_id, "server_id": server_id}}, data={ "create": { @@ -1025,7 +1041,7 @@ async def get_user_oauth_credential( ) -> Optional[Dict[str, Any]]: """Return the decoded OAuth2 payload dict for a user+server pair, or None.""" - row = await prisma_client.db.litellm_mcpusercredentials.find_unique( + row = await MCPUserCredentialsRepository(prisma_client).table.find_unique( where={"user_id_server_id": {"user_id": user_id, "server_id": server_id}} ) if row is None: @@ -1039,7 +1055,7 @@ async def list_user_oauth_credentials( ) -> List[Dict[str, Any]]: """Return all OAuth2 credential payloads for a user, tagged with server_id.""" - rows = await prisma_client.db.litellm_mcpusercredentials.find_many( + rows = await MCPUserCredentialsRepository(prisma_client).table.find_many( where={"user_id": user_id} ) results: List[Dict[str, Any]] = [] @@ -1212,7 +1228,7 @@ async def approve_mcp_server( ) -> LiteLLM_MCPServerTable: """Set approval_status=active and record reviewed_at.""" now = datetime.now(timezone.utc) - updated = await prisma_client.db.litellm_mcpservertable.update( + updated = await MCPServerRepository(prisma_client).table.update( where={"server_id": server_id}, data={ "approval_status": MCPApprovalStatus.active, @@ -1240,7 +1256,7 @@ async def reject_mcp_server( } if review_notes is not None: data["review_notes"] = review_notes - updated = await prisma_client.db.litellm_mcpservertable.update( + updated = await MCPServerRepository(prisma_client).table.update( where={"server_id": server_id}, data=data, ) @@ -1257,7 +1273,7 @@ async def get_mcp_submissions( along with a summary count breakdown by approval_status. Mirrors get_guardrail_submissions() from guardrail_endpoints.py. """ - rows = await prisma_client.db.litellm_mcpservertable.find_many( + rows = await MCPServerRepository(prisma_client).table.find_many( where={"submitted_at": {"not": None}}, order={"submitted_at": "desc"}, take=500, # safety cap; paginate if needed in a future iteration diff --git a/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py b/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py index ed374635fea..3beddd2c435 100644 --- a/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py +++ b/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py @@ -512,12 +512,13 @@ async def exchange_token_with_server( result = { "access_token": access_token, "token_type": token_response.get("token_type", "Bearer"), - "expires_in": token_response.get("expires_in", 3600), } - if "refresh_token" in token_response and token_response["refresh_token"]: + if token_response.get("expires_in") is not None: + result["expires_in"] = token_response["expires_in"] + if token_response.get("refresh_token"): result["refresh_token"] = token_response["refresh_token"] - if "scope" in token_response and token_response["scope"]: + if token_response.get("scope"): result["scope"] = token_response["scope"] # RFC 6749 §5.1: token responses must not be cached. diff --git a/litellm/proxy/_experimental/mcp_server/exceptions.py b/litellm/proxy/_experimental/mcp_server/exceptions.py index fd8fc3d5e58..a00e797a6bd 100644 --- a/litellm/proxy/_experimental/mcp_server/exceptions.py +++ b/litellm/proxy/_experimental/mcp_server/exceptions.py @@ -10,8 +10,9 @@ class MCPUpstreamAuthError(Exception): (typically HTTP 401) and the gateway should surface it transparently to the client instead of swallowing it. - Only relevant for pass-through MCP servers (see - ``MCPServer.is_oauth_passthrough``). The gateway converts this exception + Relevant for MCP servers that delegate OAuth to the upstream server, + including pass-through servers and OAuth2 servers with + ``delegate_auth_to_upstream`` enabled. The gateway converts this exception into an HTTP 401 response on single-server routes, preserving any ``WWW-Authenticate`` challenge emitted by the upstream so standards- compliant MCP clients can trigger the upstream OAuth flow. diff --git a/litellm/proxy/_experimental/mcp_server/mcp_context.py b/litellm/proxy/_experimental/mcp_server/mcp_context.py index a60138dd340..51918509441 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_context.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_context.py @@ -19,3 +19,9 @@ _mcp_active_toolset_id: ContextVar[Optional[str]] = ContextVar( _mcp_gateway_initialize_instructions: ContextVar[Optional[str]] = ContextVar( "_mcp_gateway_initialize_instructions", default=None ) + +# Per-request scoped server name; set in MCP HTTP/SSE handlers when the path +# identifies exactly one upstream server. Never populated from client-supplied headers. +_mcp_gateway_server_name: ContextVar[Optional[str]] = ContextVar( + "_mcp_gateway_server_name", default=None +) diff --git a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py index 7048f5bf7c4..afec884cd96 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py @@ -42,8 +42,8 @@ from litellm.constants import ( MCP_TOOL_LISTING_TIMEOUT, ) from litellm.exceptions import BlockedPiiEntityError, GuardrailRaisedException -from litellm.litellm_core_utils.url_utils import SSRFError, async_safe_get from litellm.experimental_mcp_client.client import MCPClient, MCPSigV4Auth +from litellm.litellm_core_utils.url_utils import SSRFError, async_safe_get from litellm.llms.custom_httpx.http_handler import get_async_httpx_client from litellm.proxy._experimental.mcp_server.auth.user_api_key_auth_mcp import ( MCPRequestHandler, @@ -85,6 +85,7 @@ from litellm.proxy._types import ( from litellm.proxy.auth.ip_address_utils import IPAddressUtils from litellm.proxy.common_utils.encrypt_decrypt_utils import decrypt_value_helper from litellm.proxy.utils import ProxyLogging +from litellm.repositories.table_repositories import MCPServerRepository from litellm.types.llms.custom_http import httpxSpecialProvider from litellm.types.mcp import MCPAuth, MCPStdioConfig from litellm.types.mcp_server.mcp_server_manager import ( @@ -353,6 +354,52 @@ def _deserialize_json_list(data: Any) -> Optional[List[Dict[str, Any]]]: ] +def _normalize_mcp_server_cost_info(mcp_info: MCPInfo) -> None: + """Coerce ``mcp_server_cost_info`` numeric fields to ``float`` at ingest. + + YAML 1.1 parses scientific notation without a decimal point (e.g. + ``7e-05``) as a string, and ``MCPServerCostInfo`` is a TypedDict with no + runtime validation, so string-typed costs flow through to the UI and + crash its ``.toFixed`` formatting. Values that cannot be coerced are + dropped with a warning instead of failing the server load. + """ + cost_info = mcp_info.get("mcp_server_cost_info") + if not isinstance(cost_info, dict): + return + + server_name = mcp_info.get("server_name") + normalized = dict(cost_info) + + default_cost = normalized.get("default_cost_per_query") + if default_cost is not None: + try: + normalized["default_cost_per_query"] = float(default_cost) + except (TypeError, ValueError): + verbose_logger.warning( + "MCP server '%s' has non-numeric default_cost_per_query %r; ignoring it", + server_name, + default_cost, + ) + del normalized["default_cost_per_query"] + + tool_costs = normalized.get("tool_name_to_cost_per_query") + if isinstance(tool_costs, dict): + normalized_tool_costs = {} + for tool_name, cost in tool_costs.items(): + try: + normalized_tool_costs[tool_name] = float(cost) + except (TypeError, ValueError): + verbose_logger.warning( + "MCP server '%s' has non-numeric cost %r for tool '%s'; ignoring it", + server_name, + cost, + tool_name, + ) + normalized["tool_name_to_cost_per_query"] = normalized_tool_costs + + mcp_info["mcp_server_cost_info"] = normalized + + def _create_sampling_callback(user_api_key_auth: Optional[Any] = None): """ Create a sampling callback for MCP ClientSession. @@ -620,6 +667,7 @@ class MCPServerManager: mcp_info["server_name"] = server_name if "description" not in mcp_info and server_config.get("description"): mcp_info["description"] = server_config.get("description") + _normalize_mcp_server_cost_info(mcp_info) # Use alias for name if present, else server_name alias = server_config.get("alias", None) @@ -1090,6 +1138,7 @@ class MCPServerManager: mcp_info["server_name"] = mcp_server.server_name or mcp_server.server_id if "description" not in mcp_info and mcp_server.description: mcp_info["description"] = mcp_server.description + _normalize_mcp_server_cost_info(mcp_info) auth_type = cast(MCPAuthType, mcp_server.auth_type) server_url = mcp_server.url @@ -1372,8 +1421,11 @@ class MCPServerManager: "No allowed MCP Servers found for user api key auth." ) return list(combined_servers) - except Exception as e: - verbose_logger.warning(f"Failed to get allowed MCP servers: {str(e)}.") + except Exception: # noqa: BLE001 + verbose_logger.exception( + "Failed to get allowed MCP servers; team-level object_permission " + "grants may be dropped. Falling back to global servers only." + ) return allow_all_server_ids async def resolve_toolset_tool_permissions( @@ -2728,28 +2780,40 @@ class MCPServerManager: Uses anyio.fail_after() instead of asyncio.wait_for() to avoid conflicts with the MCP SDK's anyio TaskGroup. See GitHub issue #20715 for details. - For pass-through MCP servers (``MCPServer.is_oauth_passthrough``) an + For OAuth pass-through and upstream-delegated OAuth2 MCP servers, an upstream HTTP 401 is converted into :class:`MCPUpstreamAuthError` instead of being swallowed to an empty tool list. That lets the single-server HTTP routes surface a proper 401 + ``WWW-Authenticate`` challenge so standards-compliant MCP clients trigger the upstream - OAuth flow. Non-pass-through servers keep today's swallow-and-log - behaviour so the multi-server ``/mcp`` aggregator doesn't get - tainted by a single bad server. + OAuth flow. Other servers keep today's swallow-and-log behaviour so + the multi-server ``/mcp`` aggregator doesn't get tainted by a single + bad server. Args: client: MCP client instance server_name: Name of the server for logging - server: Optional MCPServer; when pass-through, auth errors are - re-raised as :class:`MCPUpstreamAuthError`. + server: Optional MCPServer; when upstream auth is delegated, auth + errors are re-raised as :class:`MCPUpstreamAuthError`. Returns: List of tools from the server """ - is_passthrough = bool(server is not None and server.is_oauth_passthrough) + should_surface_upstream_auth = bool( + server is not None + and ( + server.is_oauth_passthrough + or ( + server.auth_type == MCPAuth.oauth2 + and getattr(server, "delegate_auth_to_upstream", False) is True + and not server.has_client_credentials + ) + ) + ) try: with anyio.fail_after(MCP_TOOL_LISTING_TIMEOUT): - tools = await client.list_tools(raise_on_error=is_passthrough) + tools = await client.list_tools( + raise_on_error=should_surface_upstream_auth + ) verbose_logger.debug(f"Tools from {server_name}: {tools}") return tools except TimeoutError: @@ -2766,12 +2830,12 @@ class MCPServerManager: ) return [] except Exception as e: - if is_passthrough: + if should_surface_upstream_auth: auth_info = _extract_upstream_auth_failure(e) if auth_info is not None: status_code, www_authenticate = auth_info verbose_logger.info( - f"Upstream auth failure from pass-through MCP server " + f"Upstream auth failure from MCP server " f"{server_name}: HTTP {status_code}" ) raise MCPUpstreamAuthError( @@ -3294,7 +3358,7 @@ class MCPServerManager: ) ) - async def _call_regular_mcp_tool( # noqa: PLR0915 + async def _call_regular_mcp_tool( self, mcp_server: MCPServer, original_tool_name: str, @@ -3817,7 +3881,7 @@ class MCPServerManager: # Pending/rejected servers are excluded at the DB level so we never load them. from litellm.proxy._experimental.mcp_server.db import LiteLLM_MCPServerTable - raw_rows = await prisma_client.db.litellm_mcpservertable.find_many( + raw_rows = await MCPServerRepository(prisma_client).table.find_many( where={ "OR": [ {"approval_status": None}, diff --git a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py index 725f7a335bc..2149f079a3d 100644 --- a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py +++ b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py @@ -386,8 +386,15 @@ if MCP_AVAILABLE: raw_headers: Optional[Dict[str, str]] = None, user_api_key_auth: Optional[UserAPIKeyAuth] = None, extra_headers: Optional[Dict[str, str]] = None, + apply_tool_filters: bool = True, ): - """Helper function to get tools for a single server.""" + """Helper function to get tools for a single server. + + When ``apply_tool_filters`` is False the raw server catalog is returned + without the allowed_tools/disallowed_tools gate or the per-key tool + permissions. This is the admin-only configuration view; every runtime + path keeps the default True so callable tools stay filtered. + """ tools = await global_mcp_server_manager._get_tools_from_server( server=server, mcp_auth_header=server_auth_header, @@ -397,6 +404,9 @@ if MCP_AVAILABLE: user_api_key_auth=user_api_key_auth, ) + if not apply_tool_filters: + return _create_tool_response_objects(tools, server.mcp_info) + # Always apply allowed_tools/disallowed_tools so the blacklist is # enforced even when no allowlist is set (matches the SSE/HTTP path). tools = filter_tools_by_allowed_tools(tools, server) @@ -463,6 +473,7 @@ if MCP_AVAILABLE: mcp_auth_header: Optional[str], raw_headers_from_request: dict, user_api_key_dict: UserAPIKeyAuth, + apply_tool_filters: bool = True, ) -> dict: """Handle tool listing for a single server_id request.""" # Resolve a server name to its UUID if needed @@ -527,6 +538,7 @@ if MCP_AVAILABLE: raw_headers_from_request, user_api_key_dict, extra_headers=user_oauth_extra_headers, + apply_tool_filters=apply_tool_filters, ) except MCPUpstreamAuthError: # Surface the upstream 401/403 to the caller so it can emit the @@ -552,6 +564,14 @@ if MCP_AVAILABLE: server_id: Optional[str] = Query( None, description="The server id to list tools for" ), + include_disabled_tools: bool = Query( + False, + description=( + "Admin only. Return the full server tool catalog without the " + "allowed_tools filter or per-key tool permissions, so the MCP " + "settings UI can configure the allowlist. Ignored for non-admins." + ), + ), user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), ) -> dict: """ @@ -579,6 +599,13 @@ if MCP_AVAILABLE: ) try: + # The full catalog (allowlist filter skipped) is admin-only so the + # REST endpoint can't be used to enumerate deliberately-disabled tools. + apply_tool_filters = not ( + include_disabled_tools + and user_api_key_dict.user_role == LitellmUserRoles.PROXY_ADMIN + ) + # Extract auth headers from request headers = request.headers raw_headers_from_request = dict(headers) @@ -620,6 +647,7 @@ if MCP_AVAILABLE: mcp_auth_header=mcp_auth_header, raw_headers_from_request=raw_headers_from_request, user_api_key_dict=user_api_key_dict, + apply_tool_filters=apply_tool_filters, ) else: if not allowed_server_ids: @@ -677,6 +705,7 @@ if MCP_AVAILABLE: raw_headers_from_request, user_api_key_dict, extra_headers=user_oauth_extra_headers, + apply_tool_filters=apply_tool_filters, ) list_tools_result.extend(tools_result) except Exception as e: diff --git a/litellm/proxy/_experimental/mcp_server/sampling_handler.py b/litellm/proxy/_experimental/mcp_server/sampling_handler.py index 1637c9eb0b9..b659ba6f813 100644 --- a/litellm/proxy/_experimental/mcp_server/sampling_handler.py +++ b/litellm/proxy/_experimental/mcp_server/sampling_handler.py @@ -661,7 +661,7 @@ def _convert_openai_response_to_mcp_result( ) -async def _check_model_access( # noqa: PLR0915 +async def _check_model_access( model: str, user_api_key_auth: Any ) -> Optional["ErrorData"]: """Enforce model-permission checks for MCP sampling requests. diff --git a/litellm/proxy/_experimental/mcp_server/server.py b/litellm/proxy/_experimental/mcp_server/server.py index 0477a5d3244..08e42e918e9 100644 --- a/litellm/proxy/_experimental/mcp_server/server.py +++ b/litellm/proxy/_experimental/mcp_server/server.py @@ -47,6 +47,7 @@ from litellm.proxy._experimental.mcp_server.discoverable_endpoints import ( from litellm.proxy._experimental.mcp_server.mcp_context import ( _mcp_active_toolset_id, _mcp_gateway_initialize_instructions, + _mcp_gateway_server_name, ) from litellm.proxy._experimental.mcp_server.mcp_debug import MCPDebug from litellm.proxy._experimental.mcp_server.utils import ( @@ -269,6 +270,9 @@ if MCP_AVAILABLE: global_mcp_tool_registry, ) from litellm.proxy._experimental.mcp_server.utils import ( + MCP_TOOL_PREFIX_SEPARATOR, + is_tool_name_prefixed, + normalize_server_name, split_server_prefix_from_name, ) @@ -323,10 +327,14 @@ if MCP_AVAILABLE: notification_options=notification_options, experimental_capabilities=experimental_capabilities or {}, ) + updates: Dict[str, Any] = {} merged = _mcp_gateway_initialize_instructions.get() if merged is not None: - return opts.model_copy(update={"instructions": merged}) - return opts + updates["instructions"] = merged + scoped_server_name = _mcp_gateway_server_name.get() + if scoped_server_name is not None: + updates["server_name"] = scoped_server_name + return opts.model_copy(update=updates) if updates else opts ######################################################## ############ Initialize the MCP Server ################# @@ -609,7 +617,7 @@ if MCP_AVAILABLE: active_mcp_session_var.reset(_session_reset_token) @server.call_tool() - async def mcp_server_tool_call( # noqa: PLR0915 + async def mcp_server_tool_call( name: str, arguments: Dict[str, Any] | None ) -> CallToolResult: """ @@ -1028,7 +1036,14 @@ if MCP_AVAILABLE: allowed_mcp_servers: List[MCPServer], ) -> List[MCPServer]: """ - Get the filtered MCP servers from the MCP server names + Get the filtered MCP servers from the MCP server names. + + Fails closed when ``mcp_servers`` is explicitly provided (path- or + header-derived) but none of the names resolve to a server alias or + access group the caller can access. The previous behavior returned + the full ``allowed_mcp_servers`` set, which silently widened scope + when a client targeted ``/mcp//`` and made URL/header + namespacing appear to work when it did not. """ filtered_server: dict[str, MCPServer] = {} @@ -1068,6 +1083,17 @@ if MCP_AVAILABLE: if filtered_server: return list(filtered_server.values()) + if mcp_servers is not None: + # Caller asked for a specific scope but nothing resolved. Fail + # closed so URL/header namespacing cannot silently fall back to + # the caller's full allowed-server set. + verbose_logger.debug( + "MCP scope filter resolved to no servers for requested names %s; " + "returning empty list (fail-closed).", + mcp_servers, + ) + return [] + return allowed_mcp_servers def _tool_name_matches(tool_name: str, filter_list: List[str]) -> bool: @@ -1544,6 +1570,7 @@ if MCP_AVAILABLE: user_api_key_auth: Optional[UserAPIKeyAuth], mcp_servers: Optional[List[str]], client_ip: Optional[str], + scoped_server_endpoint: bool = False, ) -> AsyncIterator[None]: allowed = await _get_allowed_mcp_servers( user_api_key_auth=user_api_key_auth, @@ -1565,13 +1592,24 @@ if MCP_AVAILABLE: return_exceptions=True, ) merged = _merge_gateway_initialize_instructions(allowed_mcp_servers=allowed) - tok = _mcp_gateway_initialize_instructions.set(merged) + scoped_server_name = None + if scoped_server_endpoint and len(allowed) == 1: + scoped_server = allowed[0] + scoped_server_name = ( + scoped_server.alias + or scoped_server.server_name + or scoped_server.name + or scoped_server.server_id + ) + instructions_token = _mcp_gateway_initialize_instructions.set(merged) + server_name_token = _mcp_gateway_server_name.set(scoped_server_name) try: yield finally: - _mcp_gateway_initialize_instructions.reset(tok) + _mcp_gateway_initialize_instructions.reset(instructions_token) + _mcp_gateway_server_name.reset(server_name_token) - async def _get_tools_from_mcp_servers( # noqa: PLR0915 + async def _get_tools_from_mcp_servers( user_api_key_auth: Optional[UserAPIKeyAuth], mcp_auth_header: Optional[str], mcp_servers: Optional[List[str]], @@ -2415,7 +2453,7 @@ if MCP_AVAILABLE: }, ) - async def execute_mcp_tool( # noqa: PLR0915 + async def execute_mcp_tool( name: str, arguments: Dict[str, Any], allowed_mcp_servers: List[MCPServer], @@ -2466,47 +2504,60 @@ if MCP_AVAILABLE: None, ) - # Resolve the actual MCP server up-front so the permission check uses - # the canonical server.name even when the tool name is prefixed with a - # short ID (LITELLM_USE_SHORT_MCP_TOOL_PREFIX) that doesn't match the - # server's display name directly. - mcp_server = global_mcp_server_manager._get_mcp_server_from_tool_name(name) - if mcp_server is None and requested_server is not None: - # REST callers may pass the raw tool name (no prefix) plus a - # ``requested_server_id``. The mapping might only contain the - # prefixed form, so retry the lookup with every known prefix of - # the requested server before treating the tool as unresolved — - # otherwise the tool_server_mismatch guard below is silently - # bypassed. - for known_prefix in iter_known_server_prefixes(requested_server): - candidate = global_mcp_server_manager._get_mcp_server_from_tool_name( - add_server_prefix_to_name(name, known_prefix) - ) - if candidate is not None: - mcp_server = candidate - break - if mcp_server is not None: - server_name = mcp_server.name + name_is_prefixed = False + if requested_server is not None and MCP_TOOL_PREFIX_SEPARATOR in name: + all_registry_prefixes: Set[str] = set() + for registry_server in global_mcp_server_manager.get_registry().values(): + for known_prefix in iter_known_server_prefixes(registry_server): + all_registry_prefixes.add(normalize_server_name(known_prefix)) + name_is_prefixed = is_tool_name_prefixed( + name, known_server_prefixes=all_registry_prefixes + ) - # REST /mcp-rest/tools/call passes server_id — tool must belong to that server - if requested_server is not None: - if ( - mcp_server is not None - and mcp_server.server_id != requested_server.server_id - ): - raise HTTPException( - status_code=403, - detail={ - "error": "tool_server_mismatch", - "message": ( - f"Tool '{name}' belongs to MCP server '{mcp_server.name}' " - f"but request specified server_id for '{requested_server.name}'." - ), - }, - ) - if mcp_server is None: - mcp_server = requested_server - server_name = requested_server.name + if requested_server is not None and not name_is_prefixed: + # REST callers may pass server_id with the upstream tool name (no + # LiteLLM prefix). The first segment is not a registered server + # prefix, so the whole string is the upstream tool name and may + # legitimately contain the separator (e.g. "text-to-speech"). + # server_id is authoritative for routing and auth. + mcp_server = requested_server + server_name = requested_server.name + original_tool_name = name + else: + # Resolve from tool name (MCP JSON-RPC or prefixed REST tool names). + mcp_server = global_mcp_server_manager._get_mcp_server_from_tool_name(name) + if mcp_server is None and requested_server is not None: + for known_prefix in iter_known_server_prefixes(requested_server): + candidate = ( + global_mcp_server_manager._get_mcp_server_from_tool_name( + add_server_prefix_to_name(name, known_prefix) + ) + ) + if candidate is not None: + mcp_server = candidate + break + if mcp_server is not None: + server_name = mcp_server.name + + if requested_server is not None: + if ( + mcp_server is not None + and mcp_server.server_id != requested_server.server_id + ): + raise HTTPException( + status_code=403, + detail={ + "error": "tool_server_mismatch", + "message": ( + f"Tool '{name}' belongs to MCP server " + f"'{mcp_server.name}' but request specified " + f"server_id for '{requested_server.name}'." + ), + }, + ) + if mcp_server is None: + mcp_server = requested_server + server_name = requested_server.name # Only enforce server-level permissions when we can resolve a server if server_name: @@ -2535,6 +2586,7 @@ if MCP_AVAILABLE: standard_logging_mcp_tool_call ) litellm_logging_obj.model = f"MCP: {name}" + litellm_logging_obj.model_call_details["model"] = f"MCP: {name}" # Resolve the MCP server early so BYOK checks and credential injection # apply to ALL dispatch paths (local tool registry AND managed MCP server). if mcp_server is None: @@ -3409,6 +3461,8 @@ if MCP_AVAILABLE: ) if stored_oauth_headers: continue + if getattr(server, "delegate_auth_to_upstream", False) is True: + continue request = StarletteRequest(scope) base_url = get_request_base_url(request) @@ -3606,7 +3660,7 @@ if MCP_AVAILABLE: detail="Forbidden", ) - async def handle_streamable_http_mcp( # noqa: PLR0915 + async def handle_streamable_http_mcp( scope: Scope, receive: Receive, send: Send ) -> None: """Handle MCP requests through StreamableHTTP.""" @@ -3620,6 +3674,7 @@ if MCP_AVAILABLE: oauth2_headers, raw_headers, ) = await extract_mcp_auth_context(scope, path) + scoped_server_endpoint = len(_get_mcp_servers_in_path(path) or []) == 1 # Extract client IP for MCP access control _client_ip = IPAddressUtils.get_mcp_client_ip(StarletteRequest(scope)) @@ -3896,6 +3951,7 @@ if MCP_AVAILABLE: user_api_key_auth, mcp_servers, _client_ip, + scoped_server_endpoint=scoped_server_endpoint, ): await target_manager.handle_request(scope, receive, local_send) if use_stateful and session_id and scope.get("method") == "DELETE": @@ -3941,7 +3997,7 @@ if MCP_AVAILABLE: ): _stateful_session_locks.pop(active_request_session_id, None) except MCPUpstreamAuthError as e: - # Pass-through server returned 401 — surface it to the client so + # Upstream delegated auth returned 401; surface it to the client so # standards-compliant MCP clients trigger the upstream OAuth flow. raise e.to_http_exception( base_url=get_request_base_url(StarletteRequest(scope)), @@ -3980,6 +4036,7 @@ if MCP_AVAILABLE: oauth2_headers, raw_headers, ) = await extract_mcp_auth_context(scope, path) + scoped_server_endpoint = len(_get_mcp_servers_in_path(path) or []) == 1 # Extract client IP for MCP access control _sse_client_ip = IPAddressUtils.get_mcp_client_ip(StarletteRequest(scope)) @@ -4052,10 +4109,11 @@ if MCP_AVAILABLE: user_api_key_auth, mcp_servers, _sse_client_ip, + scoped_server_endpoint=scoped_server_endpoint, ): await sse_session_manager.handle_request(scope, receive, send) except MCPUpstreamAuthError as e: - # Pass-through server returned 401 — surface it to the client so + # Upstream delegated auth returned 401; surface it to the client so # standards-compliant MCP clients trigger the upstream OAuth flow. raise e.to_http_exception( base_url=get_request_base_url(StarletteRequest(scope)), diff --git a/litellm/proxy/_experimental/mcp_server/toolset_db.py b/litellm/proxy/_experimental/mcp_server/toolset_db.py index 08ac7dbd33b..a996131653f 100644 --- a/litellm/proxy/_experimental/mcp_server/toolset_db.py +++ b/litellm/proxy/_experimental/mcp_server/toolset_db.py @@ -4,6 +4,7 @@ from typing import List, Optional from litellm._logging import verbose_proxy_logger from litellm._uuid import uuid from litellm.proxy.utils import PrismaClient +from litellm.repositories.table_repositories import MCPToolsetRepository from litellm.types.mcp_server.mcp_toolset import ( MCPToolset, NewMCPToolsetRequest, @@ -30,7 +31,7 @@ async def create_mcp_toolset( data_dict["tools"] = json.dumps(data_dict.get("tools", [])) data_dict["created_by"] = touched_by data_dict["updated_by"] = touched_by - row = await prisma_client.db.litellm_mcptoolsettable.create(data=data_dict) + row = await MCPToolsetRepository(prisma_client).table.create(data=data_dict) return _toolset_from_row(row) @@ -38,7 +39,7 @@ async def get_mcp_toolset( prisma_client: PrismaClient, toolset_id: str, ) -> Optional[MCPToolset]: - row = await prisma_client.db.litellm_mcptoolsettable.find_unique( + row = await MCPToolsetRepository(prisma_client).table.find_unique( where={"toolset_id": toolset_id} ) if row is None: @@ -54,7 +55,7 @@ async def list_mcp_toolsets( where = {} if toolset_ids is not None: where = {"toolset_id": {"in": toolset_ids}} - rows = await prisma_client.db.litellm_mcptoolsettable.find_many(where=where) + rows = await MCPToolsetRepository(prisma_client).table.find_many(where=where) return [_toolset_from_row(r) for r in rows] except Exception as e: verbose_proxy_logger.warning( @@ -69,7 +70,7 @@ async def get_mcp_toolset_by_name( prisma_client: PrismaClient, toolset_name: str, ) -> Optional[MCPToolset]: - row = await prisma_client.db.litellm_mcptoolsettable.find_first( + row = await MCPToolsetRepository(prisma_client).table.find_first( where={"toolset_name": toolset_name} ) if row is None: @@ -87,7 +88,7 @@ async def update_mcp_toolset( data_dict["tools"] = json.dumps(data_dict["tools"]) data_dict["updated_by"] = touched_by try: - row = await prisma_client.db.litellm_mcptoolsettable.update( + row = await MCPToolsetRepository(prisma_client).table.update( where={"toolset_id": data.toolset_id}, data=data_dict, ) @@ -105,7 +106,7 @@ async def delete_mcp_toolset( toolset_id: str, ) -> Optional[MCPToolset]: try: - row = await prisma_client.db.litellm_mcptoolsettable.delete( + row = await MCPToolsetRepository(prisma_client).table.delete( where={"toolset_id": toolset_id} ) except Exception as e: diff --git a/litellm/proxy/_experimental/mcp_server/utils.py b/litellm/proxy/_experimental/mcp_server/utils.py index 97cfa74ea45..b0141d3207c 100644 --- a/litellm/proxy/_experimental/mcp_server/utils.py +++ b/litellm/proxy/_experimental/mcp_server/utils.py @@ -23,9 +23,20 @@ import os from urllib.parse import quote # Constants -LITELLM_MCP_SERVER_NAME = "litellm-mcp-server" +# +# NOTE: The environment-backed values below are read once, when this module is +# first imported, and cached for the lifetime of the process. Changing the +# corresponding environment variables after import has no effect unless the +# module is reloaded (e.g. ``importlib.reload``). Tests that override these +# variables must reload this module — see +# ``tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server_identity_env.py``. +LITELLM_MCP_SERVER_NAME = os.environ.get( + "LITELLM_MCP_SERVER_NAME", "litellm-mcp-server" +) LITELLM_MCP_SERVER_VERSION = "1.0.0" -LITELLM_MCP_SERVER_DESCRIPTION = "MCP Server for LiteLLM" +LITELLM_MCP_SERVER_DESCRIPTION = os.environ.get( + "LITELLM_MCP_SERVER_DESCRIPTION", "MCP Server for LiteLLM" +) MCP_TOOL_PREFIX_SEPARATOR = os.environ.get("MCP_TOOL_PREFIX_SEPARATOR", "-") MCP_TOOL_PREFIX_FORMAT = "{server_name}{separator}{tool_name}" diff --git a/litellm/proxy/_experimental/out/404.html b/litellm/proxy/_experimental/out/404.html index 45de348c4d5..6d246c81652 100644 --- a/litellm/proxy/_experimental/out/404.html +++ b/litellm/proxy/_experimental/out/404.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/404/index.html b/litellm/proxy/_experimental/out/404/index.html index 45de348c4d5..6d246c81652 100644 --- a/litellm/proxy/_experimental/out/404/index.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.!KGRhc2hib2FyZCk.__PAGE__.txt b/litellm/proxy/_experimental/out/__next.!KGRhc2hib2FyZCk.__PAGE__.txt new file mode 100644 index 00000000000..650adb6b757 --- /dev/null +++ b/litellm/proxy/_experimental/out/__next.!KGRhc2hib2FyZCk.__PAGE__.txt @@ -0,0 +1,9 @@ +1:"$Sreact.fragment" +2:I[347257,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ClientPageRoot"] +3:I[871135,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js","/litellm-asset-prefix/_next/static/chunks/0a6c418370a8c183.js","/litellm-asset-prefix/_next/static/chunks/832ddb9b0d31572d.js","/litellm-asset-prefix/_next/static/chunks/5be4dad131b2e215.js","/litellm-asset-prefix/_next/static/chunks/d822f57dff3b67b9.js","/litellm-asset-prefix/_next/static/chunks/95d00009e9d5f9b7.js","/litellm-asset-prefix/_next/static/chunks/aa582f16c8866dd8.js","/litellm-asset-prefix/_next/static/chunks/00ff280cdb7d7ee5.js","/litellm-asset-prefix/_next/static/chunks/a4a51ad6586a4936.js","/litellm-asset-prefix/_next/static/chunks/7b788dd93ad868b3.js","/litellm-asset-prefix/_next/static/chunks/945f24285ff1ffdf.js","/litellm-asset-prefix/_next/static/chunks/6d5b1e69e87af9ca.js","/litellm-asset-prefix/_next/static/chunks/1683ea4bc387a0e0.js","/litellm-asset-prefix/_next/static/chunks/7f375817c88ba600.js","/litellm-asset-prefix/_next/static/chunks/b6093ff35368ddd0.js","/litellm-asset-prefix/_next/static/chunks/1d5cb651ca79a976.js","/litellm-asset-prefix/_next/static/chunks/6c4c97f1ea6e7d77.js","/litellm-asset-prefix/_next/static/chunks/43164991d3581805.js","/litellm-asset-prefix/_next/static/chunks/c6a1d77d2da7b533.js","/litellm-asset-prefix/_next/static/chunks/c2b633d80a28ed33.js","/litellm-asset-prefix/_next/static/chunks/ee97701fb3b5781f.js","/litellm-asset-prefix/_next/static/chunks/5f9c3b92a016f382.js","/litellm-asset-prefix/_next/static/chunks/a6615835e862bb65.js","/litellm-asset-prefix/_next/static/chunks/1a1bd0064a7cceca.js","/litellm-asset-prefix/_next/static/chunks/908828a91f602d8b.js","/litellm-asset-prefix/_next/static/chunks/2c1f9d7eb08aad46.js","/litellm-asset-prefix/_next/static/chunks/c058ac3e89dc33df.js","/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","/litellm-asset-prefix/_next/static/chunks/3b30ab8eaa03bc21.js","/litellm-asset-prefix/_next/static/chunks/054be755a9981063.js"],"default"] +6:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"OutletBoundary"] +7:"$Sreact.suspense" +0:{"buildId":"WL7_sh-6Yp06TbwG9Go-Z","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/6d5b1e69e87af9ca.js","async":true}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/1683ea4bc387a0e0.js","async":true}],["$","script","script-2",{"src":"/litellm-asset-prefix/_next/static/chunks/7f375817c88ba600.js","async":true}],["$","script","script-3",{"src":"/litellm-asset-prefix/_next/static/chunks/b6093ff35368ddd0.js","async":true}],["$","script","script-4",{"src":"/litellm-asset-prefix/_next/static/chunks/1d5cb651ca79a976.js","async":true}],["$","script","script-5",{"src":"/litellm-asset-prefix/_next/static/chunks/6c4c97f1ea6e7d77.js","async":true}],["$","script","script-6",{"src":"/litellm-asset-prefix/_next/static/chunks/43164991d3581805.js","async":true}],["$","script","script-7",{"src":"/litellm-asset-prefix/_next/static/chunks/c6a1d77d2da7b533.js","async":true}],["$","script","script-8",{"src":"/litellm-asset-prefix/_next/static/chunks/c2b633d80a28ed33.js","async":true}],["$","script","script-9",{"src":"/litellm-asset-prefix/_next/static/chunks/ee97701fb3b5781f.js","async":true}],["$","script","script-10",{"src":"/litellm-asset-prefix/_next/static/chunks/5f9c3b92a016f382.js","async":true}],["$","script","script-11",{"src":"/litellm-asset-prefix/_next/static/chunks/a6615835e862bb65.js","async":true}],["$","script","script-12",{"src":"/litellm-asset-prefix/_next/static/chunks/1a1bd0064a7cceca.js","async":true}],["$","script","script-13",{"src":"/litellm-asset-prefix/_next/static/chunks/908828a91f602d8b.js","async":true}],["$","script","script-14",{"src":"/litellm-asset-prefix/_next/static/chunks/2c1f9d7eb08aad46.js","async":true}],["$","script","script-15",{"src":"/litellm-asset-prefix/_next/static/chunks/c058ac3e89dc33df.js","async":true}],["$","script","script-16",{"src":"/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","async":true}],["$","script","script-17",{"src":"/litellm-asset-prefix/_next/static/chunks/3b30ab8eaa03bc21.js","async":true}],["$","script","script-18",{"src":"/litellm-asset-prefix/_next/static/chunks/054be755a9981063.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false} +4:{} +5:{} +8:null diff --git a/litellm/proxy/_experimental/out/__next.!KGRhc2hib2FyZCk.txt b/litellm/proxy/_experimental/out/__next.!KGRhc2hib2FyZCk.txt new file mode 100644 index 00000000000..5bc2f7758db --- /dev/null +++ b/litellm/proxy/_experimental/out/__next.!KGRhc2hib2FyZCk.txt @@ -0,0 +1,7 @@ +1:"$Sreact.fragment" +2:I[92825,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ClientSegmentRoot"] +3:I[216370,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js","/litellm-asset-prefix/_next/static/chunks/0a6c418370a8c183.js","/litellm-asset-prefix/_next/static/chunks/832ddb9b0d31572d.js","/litellm-asset-prefix/_next/static/chunks/5be4dad131b2e215.js","/litellm-asset-prefix/_next/static/chunks/d822f57dff3b67b9.js","/litellm-asset-prefix/_next/static/chunks/95d00009e9d5f9b7.js","/litellm-asset-prefix/_next/static/chunks/aa582f16c8866dd8.js","/litellm-asset-prefix/_next/static/chunks/00ff280cdb7d7ee5.js","/litellm-asset-prefix/_next/static/chunks/a4a51ad6586a4936.js","/litellm-asset-prefix/_next/static/chunks/7b788dd93ad868b3.js","/litellm-asset-prefix/_next/static/chunks/945f24285ff1ffdf.js"],"default"] +4:I[339756,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"default"] +5:I[837457,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"default"] +0:{"buildId":"WL7_sh-6Yp06TbwG9Go-Z","rsc":["$","$1","c",{"children":[[["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/0a6c418370a8c183.js","async":true}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/832ddb9b0d31572d.js","async":true}],["$","script","script-2",{"src":"/litellm-asset-prefix/_next/static/chunks/5be4dad131b2e215.js","async":true}],["$","script","script-3",{"src":"/litellm-asset-prefix/_next/static/chunks/d822f57dff3b67b9.js","async":true}],["$","script","script-4",{"src":"/litellm-asset-prefix/_next/static/chunks/95d00009e9d5f9b7.js","async":true}],["$","script","script-5",{"src":"/litellm-asset-prefix/_next/static/chunks/aa582f16c8866dd8.js","async":true}],["$","script","script-6",{"src":"/litellm-asset-prefix/_next/static/chunks/00ff280cdb7d7ee5.js","async":true}],["$","script","script-7",{"src":"/litellm-asset-prefix/_next/static/chunks/a4a51ad6586a4936.js","async":true}],["$","script","script-8",{"src":"/litellm-asset-prefix/_next/static/chunks/7b788dd93ad868b3.js","async":true}],["$","script","script-9",{"src":"/litellm-asset-prefix/_next/static/chunks/945f24285ff1ffdf.js","async":true}]],["$","$L2",null,{"Component":"$3","slots":{"children":["$","$L4",null,{"parallelRouterKey":"children","template":["$","$L5",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]},"serverProvidedParams":{"params":{},"promises":["$@6"]}}]]}],"loading":null,"isPartial":false} +6:"$0:rsc:props:children:1:props:serverProvidedParams:params" diff --git a/litellm/proxy/_experimental/out/__next.__PAGE__.txt b/litellm/proxy/_experimental/out/__next.__PAGE__.txt deleted file mode 100644 index 095c8f4339f..00000000000 --- a/litellm/proxy/_experimental/out/__next.__PAGE__.txt +++ /dev/null @@ -1,10 +0,0 @@ -1:"$Sreact.fragment" -2:I[347257,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ClientPageRoot"] -3:I[952683,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js","/litellm-asset-prefix/_next/static/chunks/bee4095c26818f05.js","/litellm-asset-prefix/_next/static/chunks/81937424fe90f746.js","/litellm-asset-prefix/_next/static/chunks/e2257d8308d35cf4.js","/litellm-asset-prefix/_next/static/chunks/2954392b7a60a6a1.js","/litellm-asset-prefix/_next/static/chunks/04711b0f8ffa7bbd.js","/litellm-asset-prefix/_next/static/chunks/eb1ba04e211a533f.js","/litellm-asset-prefix/_next/static/chunks/88c74f8b4b20d25a.js","/litellm-asset-prefix/_next/static/chunks/4cb93eefa53f21a3.js","/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","/litellm-asset-prefix/_next/static/chunks/40a2744137b1aec2.js","/litellm-asset-prefix/_next/static/chunks/542a1a209eb732c6.js","/litellm-asset-prefix/_next/static/chunks/84a27349dda457cd.js","/litellm-asset-prefix/_next/static/chunks/8ddf82e7e0b331fc.js","/litellm-asset-prefix/_next/static/chunks/1d7b3500478e93ae.js","/litellm-asset-prefix/_next/static/chunks/f0e079183e7bb90c.js","/litellm-asset-prefix/_next/static/chunks/10757c2146f43db4.js","/litellm-asset-prefix/_next/static/chunks/786e88f4abdd5c58.js","/litellm-asset-prefix/_next/static/chunks/ffa46de7b8384155.js","/litellm-asset-prefix/_next/static/chunks/31275eb5c6f6332f.js","/litellm-asset-prefix/_next/static/chunks/80f4410629229bf9.js","/litellm-asset-prefix/_next/static/chunks/75ee9aba04c74e23.js","/litellm-asset-prefix/_next/static/chunks/193886179a5779b5.js","/litellm-asset-prefix/_next/static/chunks/2063ca6435a47940.js","/litellm-asset-prefix/_next/static/chunks/7e417dd24c8becd0.js","/litellm-asset-prefix/_next/static/chunks/b323e0ef008e6348.js","/litellm-asset-prefix/_next/static/chunks/4ac3235460262f36.js","/litellm-asset-prefix/_next/static/chunks/51494a4a4b6fc437.js","/litellm-asset-prefix/_next/static/chunks/d7c18aec4a87a237.js","/litellm-asset-prefix/_next/static/chunks/dac86522fa98e760.js"],"default"] -6:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"OutletBoundary"] -7:"$Sreact.suspense" -:HL["/litellm-asset-prefix/_next/static/chunks/3f3fa56b5786d58c.css","style"] -0:{"buildId":"LpqGBJeKQM0vUG-9uVaiY","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","link","0",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/3f3fa56b5786d58c.css","precedence":"next"}],["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/bee4095c26818f05.js","async":true}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/81937424fe90f746.js","async":true}],["$","script","script-2",{"src":"/litellm-asset-prefix/_next/static/chunks/e2257d8308d35cf4.js","async":true}],["$","script","script-3",{"src":"/litellm-asset-prefix/_next/static/chunks/2954392b7a60a6a1.js","async":true}],["$","script","script-4",{"src":"/litellm-asset-prefix/_next/static/chunks/04711b0f8ffa7bbd.js","async":true}],["$","script","script-5",{"src":"/litellm-asset-prefix/_next/static/chunks/eb1ba04e211a533f.js","async":true}],["$","script","script-6",{"src":"/litellm-asset-prefix/_next/static/chunks/88c74f8b4b20d25a.js","async":true}],["$","script","script-7",{"src":"/litellm-asset-prefix/_next/static/chunks/4cb93eefa53f21a3.js","async":true}],["$","script","script-8",{"src":"/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","async":true}],["$","script","script-9",{"src":"/litellm-asset-prefix/_next/static/chunks/40a2744137b1aec2.js","async":true}],["$","script","script-10",{"src":"/litellm-asset-prefix/_next/static/chunks/542a1a209eb732c6.js","async":true}],["$","script","script-11",{"src":"/litellm-asset-prefix/_next/static/chunks/84a27349dda457cd.js","async":true}],["$","script","script-12",{"src":"/litellm-asset-prefix/_next/static/chunks/8ddf82e7e0b331fc.js","async":true}],["$","script","script-13",{"src":"/litellm-asset-prefix/_next/static/chunks/1d7b3500478e93ae.js","async":true}],["$","script","script-14",{"src":"/litellm-asset-prefix/_next/static/chunks/f0e079183e7bb90c.js","async":true}],["$","script","script-15",{"src":"/litellm-asset-prefix/_next/static/chunks/10757c2146f43db4.js","async":true}],["$","script","script-16",{"src":"/litellm-asset-prefix/_next/static/chunks/786e88f4abdd5c58.js","async":true}],["$","script","script-17",{"src":"/litellm-asset-prefix/_next/static/chunks/ffa46de7b8384155.js","async":true}],["$","script","script-18",{"src":"/litellm-asset-prefix/_next/static/chunks/31275eb5c6f6332f.js","async":true}],["$","script","script-19",{"src":"/litellm-asset-prefix/_next/static/chunks/80f4410629229bf9.js","async":true}],["$","script","script-20",{"src":"/litellm-asset-prefix/_next/static/chunks/75ee9aba04c74e23.js","async":true}],["$","script","script-21",{"src":"/litellm-asset-prefix/_next/static/chunks/193886179a5779b5.js","async":true}],["$","script","script-22",{"src":"/litellm-asset-prefix/_next/static/chunks/2063ca6435a47940.js","async":true}],["$","script","script-23",{"src":"/litellm-asset-prefix/_next/static/chunks/7e417dd24c8becd0.js","async":true}],["$","script","script-24",{"src":"/litellm-asset-prefix/_next/static/chunks/b323e0ef008e6348.js","async":true}],["$","script","script-25",{"src":"/litellm-asset-prefix/_next/static/chunks/4ac3235460262f36.js","async":true}],["$","script","script-26",{"src":"/litellm-asset-prefix/_next/static/chunks/51494a4a4b6fc437.js","async":true}],["$","script","script-27",{"src":"/litellm-asset-prefix/_next/static/chunks/d7c18aec4a87a237.js","async":true}],["$","script","script-28",{"src":"/litellm-asset-prefix/_next/static/chunks/dac86522fa98e760.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false} -4:{} -5:"$0:rsc:props:children:0:props:serverProvidedParams:params" -8:null diff --git a/litellm/proxy/_experimental/out/__next._full.txt b/litellm/proxy/_experimental/out/__next._full.txt index 2b2b3850207..6fc958eb4ac 100644 --- a/litellm/proxy/_experimental/out/__next._full.txt +++ b/litellm/proxy/_experimental/out/__next._full.txt @@ -1,39 +1,48 @@ 1:"$Sreact.fragment" -2:I[867271,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js"],"default"] -3:I[71195,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js"],"default"] -4:I[557951,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js"],"AuthProvider"] +2:I[867271,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js"],"default"] +3:I[71195,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js"],"default"] +4:I[557951,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js"],"AuthProvider"] 5:I[339756,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"default"] 6:I[837457,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"default"] -7:I[347257,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ClientPageRoot"] -8:I[952683,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js","/litellm-asset-prefix/_next/static/chunks/bee4095c26818f05.js","/litellm-asset-prefix/_next/static/chunks/81937424fe90f746.js","/litellm-asset-prefix/_next/static/chunks/e2257d8308d35cf4.js","/litellm-asset-prefix/_next/static/chunks/2954392b7a60a6a1.js","/litellm-asset-prefix/_next/static/chunks/04711b0f8ffa7bbd.js","/litellm-asset-prefix/_next/static/chunks/eb1ba04e211a533f.js","/litellm-asset-prefix/_next/static/chunks/88c74f8b4b20d25a.js","/litellm-asset-prefix/_next/static/chunks/4cb93eefa53f21a3.js","/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","/litellm-asset-prefix/_next/static/chunks/40a2744137b1aec2.js","/litellm-asset-prefix/_next/static/chunks/542a1a209eb732c6.js","/litellm-asset-prefix/_next/static/chunks/84a27349dda457cd.js","/litellm-asset-prefix/_next/static/chunks/8ddf82e7e0b331fc.js","/litellm-asset-prefix/_next/static/chunks/1d7b3500478e93ae.js","/litellm-asset-prefix/_next/static/chunks/f0e079183e7bb90c.js","/litellm-asset-prefix/_next/static/chunks/10757c2146f43db4.js","/litellm-asset-prefix/_next/static/chunks/786e88f4abdd5c58.js","/litellm-asset-prefix/_next/static/chunks/ffa46de7b8384155.js","/litellm-asset-prefix/_next/static/chunks/31275eb5c6f6332f.js","/litellm-asset-prefix/_next/static/chunks/80f4410629229bf9.js","/litellm-asset-prefix/_next/static/chunks/75ee9aba04c74e23.js","/litellm-asset-prefix/_next/static/chunks/193886179a5779b5.js","/litellm-asset-prefix/_next/static/chunks/2063ca6435a47940.js","/litellm-asset-prefix/_next/static/chunks/7e417dd24c8becd0.js","/litellm-asset-prefix/_next/static/chunks/b323e0ef008e6348.js","/litellm-asset-prefix/_next/static/chunks/4ac3235460262f36.js","/litellm-asset-prefix/_next/static/chunks/51494a4a4b6fc437.js","/litellm-asset-prefix/_next/static/chunks/d7c18aec4a87a237.js","/litellm-asset-prefix/_next/static/chunks/dac86522fa98e760.js"],"default"] -1a:I[168027,[],"default"] +7:I[92825,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ClientSegmentRoot"] +8:I[216370,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js","/litellm-asset-prefix/_next/static/chunks/0a6c418370a8c183.js","/litellm-asset-prefix/_next/static/chunks/832ddb9b0d31572d.js","/litellm-asset-prefix/_next/static/chunks/5be4dad131b2e215.js","/litellm-asset-prefix/_next/static/chunks/d822f57dff3b67b9.js","/litellm-asset-prefix/_next/static/chunks/95d00009e9d5f9b7.js","/litellm-asset-prefix/_next/static/chunks/aa582f16c8866dd8.js","/litellm-asset-prefix/_next/static/chunks/00ff280cdb7d7ee5.js","/litellm-asset-prefix/_next/static/chunks/a4a51ad6586a4936.js","/litellm-asset-prefix/_next/static/chunks/7b788dd93ad868b3.js","/litellm-asset-prefix/_next/static/chunks/945f24285ff1ffdf.js"],"default"] +20:I[168027,[],"default"] :HL["/litellm-asset-prefix/_next/static/chunks/4e20891f2fd03463.css","style"] -:HL["/litellm-asset-prefix/_next/static/chunks/47150bfa067220d3.css","style"] +:HL["/litellm-asset-prefix/_next/static/chunks/1b8c5c205e8923d6.css","style"] :HL["/litellm-asset-prefix/_next/static/media/83afe278b6a6bb3c-s.p.3a6ba036.woff2","font",{"crossOrigin":"","type":"font/woff2"}] -:HL["/litellm-asset-prefix/_next/static/chunks/3f3fa56b5786d58c.css","style"] -0:{"P":null,"b":"LpqGBJeKQM0vUG-9uVaiY","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/4e20891f2fd03463.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/47150bfa067220d3.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"inter_5972bc34-module__OU16Qa__className","children":["$","$L2",null,{"children":["$","$L3",null,{"children":["$","$L4",null,{"children":["$","$L5",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L7",null,{"Component":"$8","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@9","$@a"]}}],[["$","link","0",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/3f3fa56b5786d58c.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/bee4095c26818f05.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/81937424fe90f746.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/litellm-asset-prefix/_next/static/chunks/e2257d8308d35cf4.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/litellm-asset-prefix/_next/static/chunks/2954392b7a60a6a1.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/litellm-asset-prefix/_next/static/chunks/04711b0f8ffa7bbd.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/litellm-asset-prefix/_next/static/chunks/eb1ba04e211a533f.js","async":true,"nonce":"$undefined"}],["$","script","script-6",{"src":"/litellm-asset-prefix/_next/static/chunks/88c74f8b4b20d25a.js","async":true,"nonce":"$undefined"}],["$","script","script-7",{"src":"/litellm-asset-prefix/_next/static/chunks/4cb93eefa53f21a3.js","async":true,"nonce":"$undefined"}],["$","script","script-8",{"src":"/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","async":true,"nonce":"$undefined"}],["$","script","script-9",{"src":"/litellm-asset-prefix/_next/static/chunks/40a2744137b1aec2.js","async":true,"nonce":"$undefined"}],["$","script","script-10",{"src":"/litellm-asset-prefix/_next/static/chunks/542a1a209eb732c6.js","async":true,"nonce":"$undefined"}],["$","script","script-11",{"src":"/litellm-asset-prefix/_next/static/chunks/84a27349dda457cd.js","async":true,"nonce":"$undefined"}],["$","script","script-12",{"src":"/litellm-asset-prefix/_next/static/chunks/8ddf82e7e0b331fc.js","async":true,"nonce":"$undefined"}],["$","script","script-13",{"src":"/litellm-asset-prefix/_next/static/chunks/1d7b3500478e93ae.js","async":true,"nonce":"$undefined"}],["$","script","script-14",{"src":"/litellm-asset-prefix/_next/static/chunks/f0e079183e7bb90c.js","async":true,"nonce":"$undefined"}],["$","script","script-15",{"src":"/litellm-asset-prefix/_next/static/chunks/10757c2146f43db4.js","async":true,"nonce":"$undefined"}],"$Lb","$Lc","$Ld","$Le","$Lf","$L10","$L11","$L12","$L13","$L14","$L15","$L16","$L17"],"$L18"]}],{},null,false,false]},null,false,false],"$L19",false]],"m":"$undefined","G":["$1a",[]],"S":true} -1b:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"OutletBoundary"] -1c:"$Sreact.suspense" -1e:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ViewportBoundary"] -20:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"MetadataBoundary"] -b:["$","script","script-16",{"src":"/litellm-asset-prefix/_next/static/chunks/786e88f4abdd5c58.js","async":true,"nonce":"$undefined"}] -c:["$","script","script-17",{"src":"/litellm-asset-prefix/_next/static/chunks/ffa46de7b8384155.js","async":true,"nonce":"$undefined"}] -d:["$","script","script-18",{"src":"/litellm-asset-prefix/_next/static/chunks/31275eb5c6f6332f.js","async":true,"nonce":"$undefined"}] -e:["$","script","script-19",{"src":"/litellm-asset-prefix/_next/static/chunks/80f4410629229bf9.js","async":true,"nonce":"$undefined"}] -f:["$","script","script-20",{"src":"/litellm-asset-prefix/_next/static/chunks/75ee9aba04c74e23.js","async":true,"nonce":"$undefined"}] -10:["$","script","script-21",{"src":"/litellm-asset-prefix/_next/static/chunks/193886179a5779b5.js","async":true,"nonce":"$undefined"}] -11:["$","script","script-22",{"src":"/litellm-asset-prefix/_next/static/chunks/2063ca6435a47940.js","async":true,"nonce":"$undefined"}] -12:["$","script","script-23",{"src":"/litellm-asset-prefix/_next/static/chunks/7e417dd24c8becd0.js","async":true,"nonce":"$undefined"}] -13:["$","script","script-24",{"src":"/litellm-asset-prefix/_next/static/chunks/b323e0ef008e6348.js","async":true,"nonce":"$undefined"}] -14:["$","script","script-25",{"src":"/litellm-asset-prefix/_next/static/chunks/4ac3235460262f36.js","async":true,"nonce":"$undefined"}] -15:["$","script","script-26",{"src":"/litellm-asset-prefix/_next/static/chunks/51494a4a4b6fc437.js","async":true,"nonce":"$undefined"}] -16:["$","script","script-27",{"src":"/litellm-asset-prefix/_next/static/chunks/d7c18aec4a87a237.js","async":true,"nonce":"$undefined"}] -17:["$","script","script-28",{"src":"/litellm-asset-prefix/_next/static/chunks/dac86522fa98e760.js","async":true,"nonce":"$undefined"}] -18:["$","$L1b",null,{"children":["$","$1c",null,{"name":"Next.MetadataOutlet","children":"$@1d"}]}] -19:["$","$1","h",{"children":[null,["$","$L1e",null,{"children":"$L1f"}],["$","div",null,{"hidden":true,"children":["$","$L20",null,{"children":["$","$1c",null,{"name":"Next.Metadata","children":"$L21"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}] -9:{} -a:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params" -1f:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] -22:I[27201,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"IconMark"] -1d:null -21:[["$","title","0",{"children":"LiteLLM Dashboard"}],["$","meta","1",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.1d32c690.ico","sizes":"48x48","type":"image/x-icon"}],["$","link","3",{"rel":"icon","href":"/get_favicon"}],["$","$L22","4",{}]] +0:{"P":null,"b":"WL7_sh-6Yp06TbwG9Go-Z","c":["",""],"q":"","i":false,"f":[[["",{"children":["(dashboard)",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/4e20891f2fd03463.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/1b8c5c205e8923d6.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"inter_5972bc34-module__OU16Qa__className","children":["$","$L2",null,{"children":["$","$L3",null,{"children":["$","$L4",null,{"children":["$","$L5",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]}]}]]}],{"children":[["$","$1","c",{"children":[[["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/0a6c418370a8c183.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/832ddb9b0d31572d.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/litellm-asset-prefix/_next/static/chunks/5be4dad131b2e215.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/litellm-asset-prefix/_next/static/chunks/d822f57dff3b67b9.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/litellm-asset-prefix/_next/static/chunks/95d00009e9d5f9b7.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/litellm-asset-prefix/_next/static/chunks/aa582f16c8866dd8.js","async":true,"nonce":"$undefined"}],["$","script","script-6",{"src":"/litellm-asset-prefix/_next/static/chunks/00ff280cdb7d7ee5.js","async":true,"nonce":"$undefined"}],["$","script","script-7",{"src":"/litellm-asset-prefix/_next/static/chunks/a4a51ad6586a4936.js","async":true,"nonce":"$undefined"}],["$","script","script-8",{"src":"/litellm-asset-prefix/_next/static/chunks/7b788dd93ad868b3.js","async":true,"nonce":"$undefined"}],["$","script","script-9",{"src":"/litellm-asset-prefix/_next/static/chunks/945f24285ff1ffdf.js","async":true,"nonce":"$undefined"}]],["$","$L7",null,{"Component":"$8","slots":{"children":["$","$L5",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]},"serverProvidedParams":{"params":{},"promises":["$@9"]}}]]}],{"children":[["$","$1","c",{"children":["$La",["$Lb","$Lc","$Ld","$Le","$Lf","$L10","$L11","$L12","$L13","$L14","$L15","$L16","$L17","$L18","$L19","$L1a","$L1b","$L1c","$L1d"],"$L1e"]}],{},null,false,false]},null,false,false]},null,false,false],"$L1f",false]],"m":"$undefined","G":["$20",[]],"S":true} +21:I[347257,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ClientPageRoot"] +22:I[871135,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js","/litellm-asset-prefix/_next/static/chunks/0a6c418370a8c183.js","/litellm-asset-prefix/_next/static/chunks/832ddb9b0d31572d.js","/litellm-asset-prefix/_next/static/chunks/5be4dad131b2e215.js","/litellm-asset-prefix/_next/static/chunks/d822f57dff3b67b9.js","/litellm-asset-prefix/_next/static/chunks/95d00009e9d5f9b7.js","/litellm-asset-prefix/_next/static/chunks/aa582f16c8866dd8.js","/litellm-asset-prefix/_next/static/chunks/00ff280cdb7d7ee5.js","/litellm-asset-prefix/_next/static/chunks/a4a51ad6586a4936.js","/litellm-asset-prefix/_next/static/chunks/7b788dd93ad868b3.js","/litellm-asset-prefix/_next/static/chunks/945f24285ff1ffdf.js","/litellm-asset-prefix/_next/static/chunks/6d5b1e69e87af9ca.js","/litellm-asset-prefix/_next/static/chunks/1683ea4bc387a0e0.js","/litellm-asset-prefix/_next/static/chunks/7f375817c88ba600.js","/litellm-asset-prefix/_next/static/chunks/b6093ff35368ddd0.js","/litellm-asset-prefix/_next/static/chunks/1d5cb651ca79a976.js","/litellm-asset-prefix/_next/static/chunks/6c4c97f1ea6e7d77.js","/litellm-asset-prefix/_next/static/chunks/43164991d3581805.js","/litellm-asset-prefix/_next/static/chunks/c6a1d77d2da7b533.js","/litellm-asset-prefix/_next/static/chunks/c2b633d80a28ed33.js","/litellm-asset-prefix/_next/static/chunks/ee97701fb3b5781f.js","/litellm-asset-prefix/_next/static/chunks/5f9c3b92a016f382.js","/litellm-asset-prefix/_next/static/chunks/a6615835e862bb65.js","/litellm-asset-prefix/_next/static/chunks/1a1bd0064a7cceca.js","/litellm-asset-prefix/_next/static/chunks/908828a91f602d8b.js","/litellm-asset-prefix/_next/static/chunks/2c1f9d7eb08aad46.js","/litellm-asset-prefix/_next/static/chunks/c058ac3e89dc33df.js","/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","/litellm-asset-prefix/_next/static/chunks/3b30ab8eaa03bc21.js","/litellm-asset-prefix/_next/static/chunks/054be755a9981063.js"],"default"] +25:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"OutletBoundary"] +26:"$Sreact.suspense" +28:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"ViewportBoundary"] +2a:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"MetadataBoundary"] +a:["$","$L21",null,{"Component":"$22","serverProvidedParams":{"searchParams":{},"params":"$0:f:0:1:1:children:0:props:children:1:props:serverProvidedParams:params","promises":["$@23","$@24"]}}] +b:["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/6d5b1e69e87af9ca.js","async":true,"nonce":"$undefined"}] +c:["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/1683ea4bc387a0e0.js","async":true,"nonce":"$undefined"}] +d:["$","script","script-2",{"src":"/litellm-asset-prefix/_next/static/chunks/7f375817c88ba600.js","async":true,"nonce":"$undefined"}] +e:["$","script","script-3",{"src":"/litellm-asset-prefix/_next/static/chunks/b6093ff35368ddd0.js","async":true,"nonce":"$undefined"}] +f:["$","script","script-4",{"src":"/litellm-asset-prefix/_next/static/chunks/1d5cb651ca79a976.js","async":true,"nonce":"$undefined"}] +10:["$","script","script-5",{"src":"/litellm-asset-prefix/_next/static/chunks/6c4c97f1ea6e7d77.js","async":true,"nonce":"$undefined"}] +11:["$","script","script-6",{"src":"/litellm-asset-prefix/_next/static/chunks/43164991d3581805.js","async":true,"nonce":"$undefined"}] +12:["$","script","script-7",{"src":"/litellm-asset-prefix/_next/static/chunks/c6a1d77d2da7b533.js","async":true,"nonce":"$undefined"}] +13:["$","script","script-8",{"src":"/litellm-asset-prefix/_next/static/chunks/c2b633d80a28ed33.js","async":true,"nonce":"$undefined"}] +14:["$","script","script-9",{"src":"/litellm-asset-prefix/_next/static/chunks/ee97701fb3b5781f.js","async":true,"nonce":"$undefined"}] +15:["$","script","script-10",{"src":"/litellm-asset-prefix/_next/static/chunks/5f9c3b92a016f382.js","async":true,"nonce":"$undefined"}] +16:["$","script","script-11",{"src":"/litellm-asset-prefix/_next/static/chunks/a6615835e862bb65.js","async":true,"nonce":"$undefined"}] +17:["$","script","script-12",{"src":"/litellm-asset-prefix/_next/static/chunks/1a1bd0064a7cceca.js","async":true,"nonce":"$undefined"}] +18:["$","script","script-13",{"src":"/litellm-asset-prefix/_next/static/chunks/908828a91f602d8b.js","async":true,"nonce":"$undefined"}] +19:["$","script","script-14",{"src":"/litellm-asset-prefix/_next/static/chunks/2c1f9d7eb08aad46.js","async":true,"nonce":"$undefined"}] +1a:["$","script","script-15",{"src":"/litellm-asset-prefix/_next/static/chunks/c058ac3e89dc33df.js","async":true,"nonce":"$undefined"}] +1b:["$","script","script-16",{"src":"/litellm-asset-prefix/_next/static/chunks/a1ef280b7ad5ae6a.js","async":true,"nonce":"$undefined"}] +1c:["$","script","script-17",{"src":"/litellm-asset-prefix/_next/static/chunks/3b30ab8eaa03bc21.js","async":true,"nonce":"$undefined"}] +1d:["$","script","script-18",{"src":"/litellm-asset-prefix/_next/static/chunks/054be755a9981063.js","async":true,"nonce":"$undefined"}] +1e:["$","$L25",null,{"children":["$","$26",null,{"name":"Next.MetadataOutlet","children":"$@27"}]}] +1f:["$","$1","h",{"children":[null,["$","$L28",null,{"children":"$L29"}],["$","div",null,{"hidden":true,"children":["$","$L2a",null,{"children":["$","$26",null,{"name":"Next.Metadata","children":"$L2b"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}] +9:"$0:f:0:1:1:children:0:props:children:1:props:serverProvidedParams:params" +23:{} +24:"$0:f:0:1:1:children:0:props:children:1:props:serverProvidedParams:params" +29:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] +2c:I[27201,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"IconMark"] +27:null +2b:[["$","title","0",{"children":"LiteLLM Dashboard"}],["$","meta","1",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.1d32c690.ico","sizes":"48x48","type":"image/x-icon"}],["$","link","3",{"rel":"icon","href":"/get_favicon"}],["$","$L2c","4",{}]] diff --git a/litellm/proxy/_experimental/out/__next._head.txt b/litellm/proxy/_experimental/out/__next._head.txt index 870c89c7e11..a018e5d0bbd 100644 --- a/litellm/proxy/_experimental/out/__next._head.txt +++ b/litellm/proxy/_experimental/out/__next._head.txt @@ -3,4 +3,4 @@ 3:I[897367,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"MetadataBoundary"] 4:"$Sreact.suspense" 5:I[27201,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"IconMark"] -0:{"buildId":"LpqGBJeKQM0vUG-9uVaiY","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"LiteLLM Dashboard"}],["$","meta","1",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.1d32c690.ico","sizes":"48x48","type":"image/x-icon"}],["$","link","3",{"rel":"icon","href":"/get_favicon"}],["$","$L5","4",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"loading":null,"isPartial":false} +0:{"buildId":"WL7_sh-6Yp06TbwG9Go-Z","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"LiteLLM Dashboard"}],["$","meta","1",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.1d32c690.ico","sizes":"48x48","type":"image/x-icon"}],["$","link","3",{"rel":"icon","href":"/get_favicon"}],["$","$L5","4",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"loading":null,"isPartial":false} diff --git a/litellm/proxy/_experimental/out/__next._index.txt b/litellm/proxy/_experimental/out/__next._index.txt index 67c452e8c21..f544b3717cc 100644 --- a/litellm/proxy/_experimental/out/__next._index.txt +++ b/litellm/proxy/_experimental/out/__next._index.txt @@ -1,9 +1,9 @@ 1:"$Sreact.fragment" -2:I[867271,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js"],"default"] -3:I[71195,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js"],"default"] -4:I[557951,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js"],"AuthProvider"] +2:I[867271,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js"],"default"] +3:I[71195,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js"],"default"] +4:I[557951,["/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js"],"AuthProvider"] 5:I[339756,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"default"] 6:I[837457,["/litellm-asset-prefix/_next/static/chunks/d96012bcfc98706a.js","/litellm-asset-prefix/_next/static/chunks/dbca964212122d58.js"],"default"] :HL["/litellm-asset-prefix/_next/static/chunks/4e20891f2fd03463.css","style"] -:HL["/litellm-asset-prefix/_next/static/chunks/47150bfa067220d3.css","style"] -0:{"buildId":"LpqGBJeKQM0vUG-9uVaiY","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/4e20891f2fd03463.css","precedence":"next"}],["$","link","1",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/47150bfa067220d3.css","precedence":"next"}],["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","async":true}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/25c705f79a0254af.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"inter_5972bc34-module__OU16Qa__className","children":["$","$L2",null,{"children":["$","$L3",null,{"children":["$","$L4",null,{"children":["$","$L5",null,{"parallelRouterKey":"children","template":["$","$L6",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]}]}]]}],"loading":null,"isPartial":false} +:HL["/litellm-asset-prefix/_next/static/chunks/1b8c5c205e8923d6.css","style"] +0:{"buildId":"WL7_sh-6Yp06TbwG9Go-Z","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/4e20891f2fd03463.css","precedence":"next"}],["$","link","1",{"rel":"stylesheet","href":"/litellm-asset-prefix/_next/static/chunks/1b8c5c205e8923d6.css","precedence":"next"}],["$","script","script-0",{"src":"/litellm-asset-prefix/_next/static/chunks/59002382e3e0d318.js","async":true}],["$","script","script-1",{"src":"/litellm-asset-prefix/_next/static/chunks/00435a7c4cda2b39.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"inter_5972bc34-module__OU16Qa__className","children":["$","$L2",null,{"children":["$","$L3",null,{"children":["$","$L4",null,{"children":["$","$L5",null,{"parallelRouterKey":"children","template":["$","$L6",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]}]}]]}],"loading":null,"isPartial":false} diff --git a/litellm/proxy/_experimental/out/__next._tree.txt b/litellm/proxy/_experimental/out/__next._tree.txt index 86dc121c5f9..883fe73f16a 100644 --- a/litellm/proxy/_experimental/out/__next._tree.txt +++ b/litellm/proxy/_experimental/out/__next._tree.txt @@ -1,5 +1,4 @@ :HL["/litellm-asset-prefix/_next/static/chunks/4e20891f2fd03463.css","style"] -:HL["/litellm-asset-prefix/_next/static/chunks/47150bfa067220d3.css","style"] +:HL["/litellm-asset-prefix/_next/static/chunks/1b8c5c205e8923d6.css","style"] :HL["/litellm-asset-prefix/_next/static/media/83afe278b6a6bb3c-s.p.3a6ba036.woff2","font",{"crossOrigin":"","type":"font/woff2"}] -:HL["/litellm-asset-prefix/_next/static/chunks/3f3fa56b5786d58c.css","style"] -0:{"buildId":"LpqGBJeKQM0vUG-9uVaiY","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300} +0:{"buildId":"WL7_sh-6Yp06TbwG9Go-Z","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"(dashboard)","paramType":null,"paramKey":"(dashboard)","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":false}},"isRootLayout":true},"staleTime":300} diff --git a/litellm/proxy/_experimental/out/_next/static/LpqGBJeKQM0vUG-9uVaiY/_buildManifest.js b/litellm/proxy/_experimental/out/_next/static/WL7_sh-6Yp06TbwG9Go-Z/_buildManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/LpqGBJeKQM0vUG-9uVaiY/_buildManifest.js rename to litellm/proxy/_experimental/out/_next/static/WL7_sh-6Yp06TbwG9Go-Z/_buildManifest.js diff --git a/litellm/proxy/_experimental/out/_next/static/LpqGBJeKQM0vUG-9uVaiY/_clientMiddlewareManifest.json b/litellm/proxy/_experimental/out/_next/static/WL7_sh-6Yp06TbwG9Go-Z/_clientMiddlewareManifest.json similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/LpqGBJeKQM0vUG-9uVaiY/_clientMiddlewareManifest.json rename to litellm/proxy/_experimental/out/_next/static/WL7_sh-6Yp06TbwG9Go-Z/_clientMiddlewareManifest.json diff --git a/litellm/proxy/_experimental/out/_next/static/LpqGBJeKQM0vUG-9uVaiY/_ssgManifest.js b/litellm/proxy/_experimental/out/_next/static/WL7_sh-6Yp06TbwG9Go-Z/_ssgManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/LpqGBJeKQM0vUG-9uVaiY/_ssgManifest.js rename to litellm/proxy/_experimental/out/_next/static/WL7_sh-6Yp06TbwG9Go-Z/_ssgManifest.js diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/00435a7c4cda2b39.js b/litellm/proxy/_experimental/out/_next/static/chunks/00435a7c4cda2b39.js new file mode 100644 index 00000000000..2a323cf4dad --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/00435a7c4cda2b39.js @@ -0,0 +1,143 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,738275,e=>{"use strict";let t=e.i(271645).default.createContext({});e.s(["AppConfigContext",0,t])},815199,e=>{"use strict";function t(e){if(Array.isArray(e))return e}e.s(["default",()=>t])},557443,e=>{"use strict";function t(e,t){var r=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,o,a,i,l=[],s=!0,c=!1;try{if(a=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;s=!1}else for(;!(s=(n=a.call(r)).done)&&(l.push(n.value),l.length!==t);s=!0);}catch(e){c=!0,o=e}finally{try{if(!s&&null!=r.return&&(i=r.return(),Object(i)!==i))return}finally{if(c)throw o}}return l}}e.s(["default",()=>t])},949616,e=>{"use strict";function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);rt])},713882,e=>{"use strict";var t=e.i(949616);function r(e,r){if(e){if("string"==typeof e)return(0,t.default)(e,r);var n=({}).toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?(0,t.default)(e,r):void 0}}e.s(["default",()=>r])},523699,e=>{"use strict";function t(){throw TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}e.s(["default",()=>t])},392221,e=>{"use strict";var t=e.i(815199),r=e.i(557443),n=e.i(713882),o=e.i(523699);function a(e,a){return(0,t.default)(e)||(0,r.default)(e,a)||(0,n.default)(e,a)||(0,o.default)()}e.s(["default",()=>a])},410160,e=>{"use strict";function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}e.s(["default",()=>t])},211577,394257,e=>{"use strict";var t=e.i(410160);function r(e){var r=function(e,r){if("object"!=(0,t.default)(e)||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var o=n.call(e,r||"default");if("object"!=(0,t.default)(o))return o;throw TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(e)}(e,"string");return"symbol"==(0,t.default)(r)?r:r+""}function n(e,t,n){return(t=r(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}e.s(["default",()=>r],394257),e.s(["default",()=>n],211577)},308665,962837,e=>{"use strict";var t=e.i(949616);function r(e){if(Array.isArray(e))return(0,t.default)(e)}function n(e){if("u">typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}e.s(["default",()=>r],308665),e.s(["default",()=>n],962837)},8211,e=>{"use strict";var t=e.i(308665),r=e.i(962837),n=e.i(713882);function o(e){return(0,t.default)(e)||(0,r.default)(e)||(0,n.default)(e)||function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}e.s(["default",()=>o],8211)},209428,e=>{"use strict";var t=e.i(211577);function r(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,n)}return r}function n(e){for(var n=1;nn])},841888,e=>{"use strict";e.s(["default",0,function(e){for(var t,r=0,n=0,o=e.length;o>=4;++n,o-=4)t=(65535&(t=255&e.charCodeAt(n)|(255&e.charCodeAt(++n))<<8|(255&e.charCodeAt(++n))<<16|(255&e.charCodeAt(++n))<<24))*0x5bd1e995+((t>>>16)*59797<<16),t^=t>>>24,r=(65535&t)*0x5bd1e995+((t>>>16)*59797<<16)^(65535&r)*0x5bd1e995+((r>>>16)*59797<<16);switch(o){case 3:r^=(255&e.charCodeAt(n+2))<<16;case 2:r^=(255&e.charCodeAt(n+1))<<8;case 1:r^=255&e.charCodeAt(n),r=(65535&r)*0x5bd1e995+((r>>>16)*59797<<16)}return r^=r>>>13,(((r=(65535&r)*0x5bd1e995+((r>>>16)*59797<<16))^r>>>15)>>>0).toString(36)}])},654310,e=>{"use strict";function t(){return!!("u">typeof window&&window.document&&window.document.createElement)}e.s(["default",()=>t])},575943,216459,e=>{"use strict";var t=e.i(209428),r=e.i(654310);function n(e,t){if(!e)return!1;if(e.contains)return e.contains(t);for(var r=t;r;){if(r===e)return!0;r=r.parentNode}return!1}e.s(["default",()=>n],216459);var o="data-rc-order",a="data-rc-priority",i=new Map;function l(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.mark;return t?t.startsWith("data-")?t:"data-".concat(t):"rc-util-key"}function s(e){return e.attachTo?e.attachTo:document.querySelector("head")||document.body}function c(e){return Array.from((i.get(e)||e).children).filter(function(e){return"STYLE"===e.tagName})}function u(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!(0,r.default)())return null;var n=t.csp,i=t.prepend,l=t.priority,u=void 0===l?0:l,d="queue"===i?"prependQueue":i?"prepend":"append",f="prependQueue"===d,p=document.createElement("style");p.setAttribute(o,d),f&&u&&p.setAttribute(a,"".concat(u)),null!=n&&n.nonce&&(p.nonce=null==n?void 0:n.nonce),p.innerHTML=e;var m=s(t),g=m.firstChild;if(i){if(f){var h=(t.styles||c(m)).filter(function(e){return!!["prepend","prependQueue"].includes(e.getAttribute(o))&&u>=Number(e.getAttribute(a)||0)});if(h.length)return m.insertBefore(p,h[h.length-1].nextSibling),p}m.insertBefore(p,g)}else m.appendChild(p);return p}function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=s(t);return(t.styles||c(r)).find(function(r){return r.getAttribute(l(t))===e})}function f(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=d(e,t);r&&s(t).removeChild(r)}function p(e,r){var o,a,f,p=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},m=s(p),g=c(m),h=(0,t.default)((0,t.default)({},p),{},{styles:g}),v=i.get(m);if(!v||!n(document,v)){var y=u("",h),b=y.parentNode;i.set(m,b),m.removeChild(y)}var w=d(r,h);if(w)return null!=(o=h.csp)&&o.nonce&&w.nonce!==(null==(a=h.csp)?void 0:a.nonce)&&(w.nonce=null==(f=h.csp)?void 0:f.nonce),w.innerHTML!==e&&(w.innerHTML=e),w;var C=u(e,h);return C.setAttribute(l(h),r),C}e.s(["removeCSS",()=>f,"updateCSS",()=>p],575943)},915874,e=>{"use strict";function t(e,t){if(null==e)return{};var r={};for(var n in e)if(({}).hasOwnProperty.call(e,n)){if(-1!==t.indexOf(n))continue;r[n]=e[n]}return r}e.s(["default",()=>t])},703923,e=>{"use strict";var t=e.i(915874);function r(e,r){if(null==e)return{};var n,o,a=(0,t.default)(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;or])},182585,e=>{"use strict";var t=e.i(271645);function r(e,r,n){var o=t.useRef({});return(!("value"in o.current)||n(o.current.condition,r))&&(o.current.value=e(),o.current.condition=r),o.current.value}e.s(["default",()=>r])},883110,e=>{"use strict";var t={},r=[];function n(e,t){}function o(e,t){}function a(){t={}}function i(e,r,n){r||t[n]||(e(!1,n),t[n]=!0)}function l(e,t){i(n,e,t)}function s(e,t){i(o,e,t)}l.preMessage=function(e){r.push(e)},l.resetWarned=a,l.noteOnce=s,e.s(["default",0,l,"noteOnce",()=>s,"resetWarned",()=>a,"warning",()=>n])},929123,e=>{"use strict";var t=e.i(410160),r=e.i(883110);e.s(["default",0,function(e,n){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a=new Set;return function e(n,i){var l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,s=a.has(n);if((0,r.default)(!s,"Warning: There may be circular references"),s)return!1;if(n===i)return!0;if(o&&l>1)return!1;a.add(n);var c=l+1;if(Array.isArray(n)){if(!Array.isArray(i)||n.length!==i.length)return!1;for(var u=0;u{"use strict";function t(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}e.s(["default",()=>t],278409);var r=e.i(394257);function n(e,t){for(var n=0;no],233848)},415584,578054,e=>{"use strict";var t=e.i(209428),r=e.i(703923),n=e.i(182585),o=e.i(929123),a=e.i(271645),i=e.i(278409),l=e.i(233848),s=e.i(211577);function c(e){return e.join("%")}var u=function(){function e(t){(0,i.default)(this,e),(0,s.default)(this,"instanceId",void 0),(0,s.default)(this,"cache",new Map),(0,s.default)(this,"extracted",new Set),this.instanceId=t}return(0,l.default)(e,[{key:"get",value:function(e){return this.opGet(c(e))}},{key:"opGet",value:function(e){return this.cache.get(e)||null}},{key:"update",value:function(e,t){return this.opUpdate(c(e),t)}},{key:"opUpdate",value:function(e,t){var r=t(this.cache.get(e));null===r?this.cache.delete(e):this.cache.set(e,r)}}]),e}();e.s(["default",0,u,"pathKey",()=>c],578054);var d=["children"],f="data-css-hash",p="__cssinjs_instance__";function m(){var e=Math.random().toString(12).slice(2);if("u">typeof document&&document.head&&document.body){var t=document.body.querySelectorAll("style[".concat(f,"]"))||[],r=document.head.firstChild;Array.from(t).forEach(function(t){t[p]=t[p]||e,t[p]===e&&document.head.insertBefore(t,r)});var n={};Array.from(document.querySelectorAll("style[".concat(f,"]"))).forEach(function(t){var r,o=t.getAttribute(f);n[o]?t[p]===e&&(null==(r=t.parentNode)||r.removeChild(t)):n[o]=!0})}return new u(e)}var g=a.createContext({hashPriority:"low",cache:m(),defaultCache:!0}),h=function(e){var i=e.children,l=(0,r.default)(e,d),s=a.useContext(g),c=(0,n.default)(function(){var e=(0,t.default)({},s);Object.keys(l).forEach(function(t){var r=l[t];void 0!==l[t]&&(e[t]=r)});var r=l.cache;return e.cache=e.cache||m(),e.defaultCache=!r&&s.defaultCache,e},[s,l],function(e,t){return!(0,o.default)(e[0],t[0],!0)||!(0,o.default)(e[1],t[1],!0)});return a.createElement(g.Provider,{value:c},i)};e.s(["ATTR_MARK",()=>f,"ATTR_TOKEN",()=>"data-token-hash","CSS_IN_JS_INSTANCE",()=>p,"StyleProvider",()=>h,"createCache",()=>m,"default",0,g],415584)},971151,e=>{"use strict";function t(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}e.s(["default",()=>t])},885963,e=>{"use strict";function t(e,r){return(t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,r)}e.s(["default",()=>t])},868917,487806,479671,e=>{"use strict";var t=e.i(885963);function r(e,r){if("function"!=typeof r&&null!==r)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(r&&r.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),r&&(0,t.default)(e,r)}function n(e){return(n=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function o(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(o=function(){return!!e})()}e.s(["default",()=>r],868917),e.s(["default",()=>n],487806),e.s(["default",()=>o],479671)},674813,480002,e=>{"use strict";var t=e.i(487806),r=e.i(479671),n=e.i(410160),o=e.i(971151);function a(e,t){if(t&&("object"==(0,n.default)(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return(0,o.default)(e)}function i(e){var n=(0,r.default)();return function(){var r,o=(0,t.default)(e);return r=n?Reflect.construct(o,arguments,(0,t.default)(this).constructor):o.apply(this,arguments),a(this,r)}}e.s(["default",()=>a],480002),e.s(["default",()=>i],674813)},915654,534878,240983,82348,947007,608648,e=>{"use strict";e.i(247167);var t=e.i(211577),r=e.i(209428),n=e.i(410160),o=e.i(841888),a=e.i(654310),i=e.i(575943),l=e.i(415584),s=e.i(278409),c=e.i(233848),u=e.i(971151),d=e.i(868917),f=e.i(674813),p=(0,c.default)(function e(){(0,s.default)(this,e)}),m="CALC_UNIT",g=RegExp(m,"g");function h(e){return"number"==typeof e?"".concat(e).concat(m):e}var v=function(e){(0,d.default)(o,e);var r=(0,f.default)(o);function o(e,a){(0,s.default)(this,o),i=r.call(this),(0,t.default)((0,u.default)(i),"result",""),(0,t.default)((0,u.default)(i),"unitlessCssVar",void 0),(0,t.default)((0,u.default)(i),"lowPriority",void 0);var i,l=(0,n.default)(e);return i.unitlessCssVar=a,e instanceof o?i.result="(".concat(e.result,")"):"number"===l?i.result=h(e):"string"===l&&(i.result=e),i}return(0,c.default)(o,[{key:"add",value:function(e){return e instanceof o?this.result="".concat(this.result," + ").concat(e.getResult()):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," + ").concat(h(e))),this.lowPriority=!0,this}},{key:"sub",value:function(e){return e instanceof o?this.result="".concat(this.result," - ").concat(e.getResult()):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," - ").concat(h(e))),this.lowPriority=!0,this}},{key:"mul",value:function(e){return this.lowPriority&&(this.result="(".concat(this.result,")")),e instanceof o?this.result="".concat(this.result," * ").concat(e.getResult(!0)):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," * ").concat(e)),this.lowPriority=!1,this}},{key:"div",value:function(e){return this.lowPriority&&(this.result="(".concat(this.result,")")),e instanceof o?this.result="".concat(this.result," / ").concat(e.getResult(!0)):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," / ").concat(e)),this.lowPriority=!1,this}},{key:"getResult",value:function(e){return this.lowPriority||e?"(".concat(this.result,")"):this.result}},{key:"equal",value:function(e){var t=this,r=(e||{}).unit,n=!0;return("boolean"==typeof r?n=r:Array.from(this.unitlessCssVar).some(function(e){return t.result.includes(e)})&&(n=!1),this.result=this.result.replace(g,n?"px":""),void 0!==this.lowPriority)?"calc(".concat(this.result,")"):this.result}}]),o}(p),y=function(e){(0,d.default)(n,e);var r=(0,f.default)(n);function n(e){var o;return(0,s.default)(this,n),o=r.call(this),(0,t.default)((0,u.default)(o),"result",0),e instanceof n?o.result=e.result:"number"==typeof e&&(o.result=e),o}return(0,c.default)(n,[{key:"add",value:function(e){return e instanceof n?this.result+=e.result:"number"==typeof e&&(this.result+=e),this}},{key:"sub",value:function(e){return e instanceof n?this.result-=e.result:"number"==typeof e&&(this.result-=e),this}},{key:"mul",value:function(e){return e instanceof n?this.result*=e.result:"number"==typeof e&&(this.result*=e),this}},{key:"div",value:function(e){return e instanceof n?this.result/=e.result:"number"==typeof e&&(this.result/=e),this}},{key:"equal",value:function(){return this.result}}]),n}(p);e.s(["default",0,function(e,t){var r="css"===e?v:y;return function(e){return new r(e,t)}}],534878);var b=e.i(392221),w=function(){function e(){(0,s.default)(this,e),(0,t.default)(this,"cache",void 0),(0,t.default)(this,"keys",void 0),(0,t.default)(this,"cacheCallTimes",void 0),this.cache=new Map,this.keys=[],this.cacheCallTimes=0}return(0,c.default)(e,[{key:"size",value:function(){return this.keys.length}},{key:"internalGet",value:function(e){var t,r,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o={map:this.cache};return e.forEach(function(e){if(o){var t;o=null==(t=o)||null==(t=t.map)?void 0:t.get(e)}else o=void 0}),null!=(t=o)&&t.value&&n&&(o.value[1]=this.cacheCallTimes++),null==(r=o)?void 0:r.value}},{key:"get",value:function(e){var t;return null==(t=this.internalGet(e,!0))?void 0:t[0]}},{key:"has",value:function(e){return!!this.internalGet(e)}},{key:"set",value:function(t,r){var n=this;if(!this.has(t)){if(this.size()+1>e.MAX_CACHE_SIZE+e.MAX_CACHE_OFFSET){var o=this.keys.reduce(function(e,t){var r=(0,b.default)(e,2)[1];return n.internalGet(t)[1]0,"[Ant Design CSS-in-JS] Theme should have at least one derivative function."),x+=1}return(0,c.default)(e,[{key:"getDerivativeToken",value:function(e){return this.derivatives.reduce(function(t,r){return r(e,t)},void 0)}}]),e}(),$=new w;function E(e){var t=Array.isArray(e)?e:[e];return $.has(t)||$.set(t,new S(t)),$.get(t)}e.s(["default",()=>E],240983),e.s([],82348),e.s(["Theme",()=>S],947007);var k=new WeakMap,O={};function j(e,t){for(var r=k,n=0;n3&&void 0!==arguments[3]?arguments[3]:{},i=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if(i)return e;var s=(0,r.default)((0,r.default)({},a),{},(0,t.default)((0,t.default)({},l.ATTR_TOKEN,n),l.ATTR_MARK,o)),c=Object.keys(s).map(function(e){var t=s[e];return t?"".concat(e,'="').concat(t,'"'):null}).filter(function(e){return e}).join(" ");return"")}e.s(["flattenToken",()=>_,"isClientSide",()=>z,"memoResult",()=>j,"supportLogicProps",()=>B,"supportWhere",()=>M,"toStyleStr",()=>H,"token2key",()=>P,"unit",()=>L],915654);var D=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return"--".concat(t?"".concat(t,"-"):"").concat(e).replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z0-9]+)/g,"$1-$2").replace(/([a-z])([A-Z0-9])/g,"$1-$2").toLowerCase()},V=function(e,t,r){var n,o={},a={};return Object.entries(e).forEach(function(e){var t=(0,b.default)(e,2),n=t[0],i=t[1];if(null!=r&&null!=(l=r.preserve)&&l[n])a[n]=i;else if(("string"==typeof i||"number"==typeof i)&&!(null!=r&&null!=(s=r.ignore)&&s[n])){var l,s,c,u=D(n,null==r?void 0:r.prefix);o[u]="number"!=typeof i||null!=r&&null!=(c=r.unitless)&&c[n]?String(i):"".concat(i,"px"),a[n]="var(".concat(u,")")}}),[a,(n={scope:null==r?void 0:r.scope},Object.keys(o).length?".".concat(t).concat(null!=n&&n.scope?".".concat(n.scope):"","{").concat(Object.entries(o).map(function(e){var t=(0,b.default)(e,2),r=t[0],n=t[1];return"".concat(r,":").concat(n,";")}).join(""),"}"):"")]};e.s(["token2CSSVar",()=>D,"transformToken",()=>V],608648)},174428,e=>{"use strict";var t=e.i(271645),r=(0,e.i(654310).default)()?t.useLayoutEffect:t.useEffect,n=function(e,n){var o=t.useRef(!0);r(function(){return e(o.current)},n),r(function(){return o.current=!1,function(){o.current=!0}},[])},o=function(e,t){n(function(t){if(!t)return e()},t)};e.s(["default",0,n,"useLayoutUpdateEffect",()=>o])},732961,608586,e=>{"use strict";e.i(247167);var t=e.i(392221),r=e.i(8211),n=e.i(209428),o=e.i(841888),a=e.i(575943),i=e.i(271645),l=e.i(415584),s=e.i(915654),c=e.i(608648),u=e.i(578054),d=e.i(174428),f=(0,n.default)({},i).useInsertionEffect,p=f?function(e,t,r){return f(function(){return e(),t()},r)}:function(e,t,r){i.useMemo(e,r),(0,d.default)(function(){return t(!0)},r)};e.i(883110);var m=void 0!==(0,n.default)({},i).useInsertionEffect?function(e){var t=[],r=!1;return i.useEffect(function(){return r=!1,function(){r=!0,t.length&&t.forEach(function(e){return e()})}},e),function(e){r||t.push(e)}}:function(){return function(e){e()}};function g(e,n,o,a,s){var c=i.useContext(l.default).cache,d=[e].concat((0,r.default)(n)),f=(0,u.pathKey)(d),g=m([f]),h=function(e){c.opUpdate(f,function(r){var n=(0,t.default)(r||[void 0,void 0],2),a=n[0],i=[void 0===a?0:a,n[1]||o()];return e?e(i):i})};i.useMemo(function(){h()},[f]);var v=c.opGet(f)[1];return p(function(){null==s||s(v)},function(e){return h(function(r){var n=(0,t.default)(r,2),o=n[0],a=n[1];return e&&0===o&&(null==s||s(v)),[o+1,a]}),function(){c.opUpdate(f,function(r){var n=(0,t.default)(r||[],2),o=n[0],i=void 0===o?0:o,l=n[1];return 0==i-1?(g(function(){(e||!c.opGet(f))&&(null==a||a(l,!1))}),null):[i-1,l]})}},[f]),v}e.s(["default",()=>g],608586);var h={},v=new Map,y=function(e,t,r,o){var a=r.getDerivativeToken(e),i=(0,n.default)((0,n.default)({},a),t);return o&&(i=o(i)),i},b="token";function w(e,u){var d=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},f=(0,i.useContext)(l.default),p=f.cache.instanceId,m=f.container,w=d.salt,C=void 0===w?"":w,x=d.override,S=void 0===x?h:x,$=d.formatToken,E=d.getComputedToken,k=d.cssVar,O=(0,s.memoResult)(function(){return Object.assign.apply(Object,[{}].concat((0,r.default)(u)))},u),j=(0,s.flattenToken)(O),T=(0,s.flattenToken)(S),_=k?(0,s.flattenToken)(k):"";return g(b,[C,e.id,j,T,_],function(){var r,a=E?E(O,S,e):y(O,S,e,$),i=(0,n.default)({},a),l="";if(k){var u=(0,c.transformToken)(a,k.key,{prefix:k.prefix,ignore:k.ignore,unitless:k.unitless,preserve:k.preserve}),d=(0,t.default)(u,2);a=d[0],l=d[1]}var f=(0,s.token2key)(a,C);a._tokenKey=f,i._tokenKey=(0,s.token2key)(i,C);var p=null!=(r=null==k?void 0:k.key)?r:f;a._themeKey=p,v.set(p,(v.get(p)||0)+1);var m="".concat("css","-").concat((0,o.default)(f));return a._hashId=m,[a,m,i,l,(null==k?void 0:k.key)||""]},function(e){var t,r;t=e[0]._themeKey,v.set(t,(v.get(t)||0)-1),r=new Set,v.forEach(function(e,t){e<=0&&r.add(t)}),v.size-r.size>0&&r.forEach(function(e){"u">typeof document&&document.querySelectorAll("style[".concat(l.ATTR_TOKEN,'="').concat(e,'"]')).forEach(function(e){if(e[l.CSS_IN_JS_INSTANCE]===p){var t;null==(t=e.parentNode)||t.removeChild(e)}}),v.delete(e)})},function(e){var r=(0,t.default)(e,4),n=r[0],i=r[3];if(k&&i){var s=(0,a.updateCSS)(i,(0,o.default)("css-variables-".concat(n._themeKey)),{mark:l.ATTR_MARK,prepend:"queue",attachTo:m,priority:-999});s[l.CSS_IN_JS_INSTANCE]=p,s.setAttribute(l.ATTR_TOKEN,n._themeKey)}})}var C=function(e,r,n){var o=(0,t.default)(e,5),a=o[2],i=o[3],l=o[4],c=(n||{}).plain;if(!i)return null;var u=a._tokenKey,d=(0,s.toStyleStr)(i,l,u,{"data-rc-order":"prependQueue","data-rc-priority":"".concat(-999)},c);return[-999,u,d]};e.s(["TOKEN_PREFIX",()=>b,"default",()=>w,"extract",()=>C,"getComputedToken",()=>y],732961)},931067,e=>{"use strict";function t(){return(t=Object.assign.bind()).apply(null,arguments)}e.s(["default",()=>t])},296059,952103,512150,717813,868297,e=>{"use strict";var t,r=e.i(392221),n=e.i(211577),o=e.i(732961),a=e.i(8211),i=e.i(575943),l=e.i(271645),s=e.i(415584),c=e.i(915654),u=e.i(608648),d=e.i(608586);e.i(247167);var f=e.i(931067),p=e.i(209428),m=e.i(410160),g=e.i(841888);let h={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1};var v="comm",y="rule",b="decl",w=Math.abs,C=String.fromCharCode;function x(e,t,r){return e.replace(t,r)}function S(e,t){return 0|e.charCodeAt(t)}function $(e,t,r){return e.slice(t,r)}function E(e){return e.length}function k(e,t){return t.push(e),e}var O=1,j=1,T=0,_=0,P=0,I="";function F(e,t,r,n,o,a,i,l){return{value:e,root:t,parent:r,type:n,props:o,children:a,line:O,column:j,length:i,return:"",siblings:l}}function N(){return P=_0?p[b]+" "+C:x(C,/&\f/g,p[b])).trim())&&(s[v++]=S);return F(e,t,r,0===o?y:l,s,c,u,d)}function z(e,t,r,n,o){return F(e,t,r,b,$(e,0,n),$(e,n+1,-1),n,o)}function L(e,t){for(var r="",n=0;n2||M(P)>3?"":" "}(H);break;case 92:J+=function(e,t){for(var r;--t&&N()&&!(P<48)&&!(P>102)&&(!(P>57)||!(P<65))&&(!(P>70)||!(P<97)););return r=_+(t<6&&32==R()&&32==N()),$(I,e,r)}(_-1,7);continue;case 47:switch(R()){case 42:case 47:k((u=function(e,t){for(;N();)if(e+P===57)break;else if(e+P===84&&47===R())break;return"/*"+$(I,t,_-1)+"*"+C(47===e?e:N())}(N(),_),d=r,f=n,p=c,F(u,d,f,v,C(P),$(u,2,-2),0,p)),c),(5==M(H||1)||5==M(R()||1))&&E(J)&&" "!==$(J,-1,void 0)&&(J+=" ");break;default:J+="/"}break;case 123*D:s[h++]=E(J)*W;case 125*D:case 59:case 0:switch(U){case 0:case 125:V=0;case 59+y:-1==W&&(J=x(J,/\f/g,"")),L>0&&(E(J)-b||0===D&&47===H)&&k(L>32?z(J+";",o,n,b-1,c):z(x(J," ","")+";",o,n,b-2,c),c);break;case 59:J+=";";default:if(k(X=B(J,r,n,h,y,a,s,G,q=[],K=[],b,i),i),123===U)if(0===y)e(J,r,X,X,q,i,b,s,K);else{switch(T){case 99:if(110===S(J,3))break;case 108:if(97===S(J,2))break;default:y=0;case 100:case 109:case 115:}y?e(t,X,X,o&&k(B(t,X,X,0,0,a,s,G,a,q=[],b,K),K),a,K,b,s,o?q:K):e(J,X,X,X,[""],K,0,s,K)}}h=y=L=0,D=W=1,G=J="",b=l;break;case 58:b=1+E(J),L=H;default:if(D<1){if(123==U)--D;else if(125==U&&0==D++&&125==(P=_>0?S(I,--_):0,j--,10===P&&(j=1,O--),P))continue}switch(J+=C(U),U*D){case 38:W=y>0?1:(J+="\f",-1);break;case 44:s[h++]=(E(J)-1)*W,W=1;break;case 64:45===R()&&(J+=A(N())),T=R(),y=b=E(G=J+=function(e){for(;!M(R());)N();return $(I,e,_)}(_)),U++;break;case 45:45===H&&2==E(J)&&(D=0)}}return i}("",null,null,null,[""],(r=t=e,O=j=1,T=E(I=r),_=0,t=[]),0,[0],t),I="",n),H).replace(/\{%%%\:[^;];}/g,";")}function K(e,t,r){if(!t)return e;var n=".".concat(t),o="low"===r?":where(".concat(n,")"):n;return e.split(",").map(function(e){var t,r=e.trim().split(/\s+/),n=r[0]||"",i=(null==(t=n.match(/^\w+/))?void 0:t[0])||"";return[n="".concat(i).concat(o).concat(n.slice(i.length))].concat((0,a.default)(r.slice(1))).join(" ")}).join(",")}var X=function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{root:!0,parentSelectors:[]},i=o.root,l=o.injectHash,s=o.parentSelectors,c=n.hashId,u=n.layer,d=(n.path,n.hashPriority),f=n.transformers,g=void 0===f?[]:f,v=(n.linters,""),y={};function b(t){var o=t.getName(c);if(!y[o]){var a=e(t.style,n,{root:!1,parentSelectors:s}),i=(0,r.default)(a,1)[0];y[o]="@keyframes ".concat(t.getName(c)).concat(i)}}return(function e(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return t.forEach(function(t){Array.isArray(t)?e(t,r):t&&r.push(t)}),r})(Array.isArray(t)?t:[t]).forEach(function(t){var o="string"!=typeof t||i?t:{};if("string"==typeof o)v+="".concat(o,"\n");else if(o._keyframe)b(o);else{var u=g.reduce(function(e,t){var r;return(null==t||null==(r=t.visit)?void 0:r.call(t,e))||e},o);Object.keys(u).forEach(function(t){var o=u[t];if("object"!==(0,m.default)(o)||!o||"animationName"===t&&o._keyframe||"object"===(0,m.default)(o)&&o&&("_skip_check_"in o||G in o)){function f(e,t){var r=e.replace(/[A-Z]/g,function(e){return"-".concat(e.toLowerCase())}),n=t;h[e]||"number"!=typeof n||0===n||(n="".concat(n,"px")),"animationName"===e&&null!=t&&t._keyframe&&(b(t),n=t.getName(c)),v+="".concat(r,":").concat(n,";")}var g,w=null!=(g=null==o?void 0:o.value)?g:o;"object"===(0,m.default)(o)&&null!=o&&o[G]&&Array.isArray(w)?w.forEach(function(e){f(t,e)}):f(t,w)}else{var C=!1,x=t.trim(),S=!1;(i||l)&&c?x.startsWith("@")?C=!0:x="&"===x?K("",c,d):K(t,c,d):i&&!c&&("&"===x||""===x)&&(x="",S=!0);var $=e(o,n,{root:S,injectHash:C,parentSelectors:[].concat((0,a.default)(s),[x])}),E=(0,r.default)($,2),k=E[0],O=E[1];y=(0,p.default)((0,p.default)({},y),O),v+="".concat(x).concat(k)}})}}),i?u&&(v&&(v="@layer ".concat(u.name," {").concat(v,"}")),u.dependencies&&(y["@layer ".concat(u.name)]=u.dependencies.map(function(e){return"@layer ".concat(e,", ").concat(u.name,";")}).join("\n"))):v="{".concat(v,"}"),[v,y]};function J(e,t){return(0,g.default)("".concat(e.join("%")).concat(t))}function Y(){return null}var Q="style";function Z(e,o){var u=e.token,m=e.path,g=e.hashId,h=e.layer,v=e.nonce,y=e.clientOnly,b=e.order,w=void 0===b?0:b,C=l.useContext(s.default),x=C.autoClear,S=(C.mock,C.defaultCache),$=C.hashPriority,E=C.container,k=C.ssrInline,O=C.transformers,j=C.linters,T=C.cache,_=C.layer,P=u._tokenKey,I=[P];_&&I.push("layer"),I.push.apply(I,(0,a.default)(m));var F=c.isClientSide,N=(0,d.default)(Q,I,function(){var e=I.join("|");if(function(e){if(!t&&(t={},(0,D.default)())){var n,o=document.createElement("div");o.className=V,o.style.position="fixed",o.style.visibility="hidden",o.style.top="-9999px",document.body.appendChild(o);var a=getComputedStyle(o).content||"";(a=a.replace(/^"/,"").replace(/"$/,"")).split(";").forEach(function(e){var n=e.split(":"),o=(0,r.default)(n,2),a=o[0],i=o[1];t[a]=i});var i=document.querySelector("style[".concat(V,"]"));i&&(U=!1,null==(n=i.parentNode)||n.removeChild(i)),document.body.removeChild(o)}return!!t[e]}(e)){var n=function(e){var r=t[e],n=null;if(r&&(0,D.default)())if(U)n=W;else{var o=document.querySelector("style[".concat(s.ATTR_MARK,'="').concat(t[e],'"]'));o?n=o.innerHTML:delete t[e]}return[n,r]}(e),a=(0,r.default)(n,2),i=a[0],l=a[1];if(i)return[i,P,l,{},y,w]}var c=X(o(),{hashId:g,hashPriority:$,layer:_?h:void 0,path:m.join("-"),transformers:O,linters:j}),u=(0,r.default)(c,2),d=u[0],f=u[1],p=q(d),v=J(I,p);return[p,P,v,f,y,w]},function(e,t){var n=(0,r.default)(e,3)[2];(t||x)&&c.isClientSide&&(0,i.removeCSS)(n,{mark:s.ATTR_MARK,attachTo:E})},function(e){var t=(0,r.default)(e,4),n=t[0],o=(t[1],t[2]),a=t[3];if(F&&n!==W){var l={mark:s.ATTR_MARK,prepend:!_&&"queue",attachTo:E,priority:w},c="function"==typeof v?v():v;c&&(l.csp={nonce:c});var u=[],d=[];Object.keys(a).forEach(function(e){e.startsWith("@layer")?u.push(e):d.push(e)}),u.forEach(function(e){(0,i.updateCSS)(q(a[e]),"_layer-".concat(e),(0,p.default)((0,p.default)({},l),{},{prepend:!0}))});var f=(0,i.updateCSS)(n,o,l);f[s.CSS_IN_JS_INSTANCE]=T.instanceId,f.setAttribute(s.ATTR_TOKEN,P),d.forEach(function(e){(0,i.updateCSS)(q(a[e]),"_effect-".concat(e),l)})}}),R=(0,r.default)(N,3),M=R[0],A=R[1],B=R[2];return function(e){var t;return t=k&&!F&&S?l.createElement("style",(0,f.default)({},(0,n.default)((0,n.default)({},s.ATTR_TOKEN,A),s.ATTR_MARK,B),{dangerouslySetInnerHTML:{__html:M}})):l.createElement(Y,null),l.createElement(l.Fragment,null,t,e)}}var ee=function(e,t,n){var o=(0,r.default)(e,6),a=o[0],i=o[1],l=o[2],s=o[3],u=o[4],d=o[5],f=(n||{}).plain;if(u)return null;var p=a,m={"data-rc-order":"prependQueue","data-rc-priority":"".concat(d)};return p=(0,c.toStyleStr)(a,i,l,m,f),s&&Object.keys(s).forEach(function(e){if(!t[e]){t[e]=!0;var r=q(s[e]),n=(0,c.toStyleStr)(r,i,"_effect-".concat(e),m,f);e.startsWith("@layer")?p=n+p:p+=n}}),[d,l,p]};e.s(["STYLE_PREFIX",()=>Q,"default",()=>Z,"extract",()=>ee,"uniqueHash",()=>J],952103);var et="cssVar",er=function(e,t,n){var o=(0,r.default)(e,4),a=o[1],i=o[2],l=o[3],s=(n||{}).plain;if(!a)return null;var u=(0,c.toStyleStr)(a,l,i,{"data-rc-order":"prependQueue","data-rc-priority":"".concat(-999)},s);return[-999,i,u]};e.s(["CSS_VAR_PREFIX",()=>et,"default",0,function(e,t){var n=e.key,o=e.prefix,f=e.unitless,p=e.ignore,m=e.token,g=e.scope,h=void 0===g?"":g,v=(0,l.useContext)(s.default),y=v.cache.instanceId,b=v.container,w=m._tokenKey,C=[].concat((0,a.default)(e.path),[n,h,w]);return(0,d.default)(et,C,function(){var e=t(),a=(0,u.transformToken)(e,n,{prefix:o,unitless:f,ignore:p,scope:h}),i=(0,r.default)(a,2),l=i[0],s=i[1],c=J(C,s);return[l,s,c,n]},function(e){var t=(0,r.default)(e,3)[2];c.isClientSide&&(0,i.removeCSS)(t,{mark:s.ATTR_MARK,attachTo:b})},function(e){var t=(0,r.default)(e,3),o=t[1],a=t[2];if(o){var l=(0,i.updateCSS)(o,a,{mark:s.ATTR_MARK,prepend:"queue",attachTo:b,priority:-999});l[s.CSS_IN_JS_INSTANCE]=y,l.setAttribute(s.ATTR_TOKEN,n)}})},"extract",()=>er],512150),(0,n.default)((0,n.default)((0,n.default)({},Q,ee),o.TOKEN_PREFIX,o.extract),et,er);var en=e.i(278409),eo=e.i(233848),ea=function(){function e(t,r){(0,en.default)(this,e),(0,n.default)(this,"name",void 0),(0,n.default)(this,"style",void 0),(0,n.default)(this,"_keyframe",!0),this.name=t,this.style=r}return(0,eo.default)(e,[{key:"getName",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return e?"".concat(e,"-").concat(this.name):this.name}}]),e}();e.s(["default",0,ea],717813),e.i(82348);var ei=e.i(240983);e.s(["createTheme",()=>ei.default],868297);var ei=ei;function el(e){return e.notSplit=!0,e}e.i(534878),e.i(947007),el(["borderTop","borderBottom"]),el(["borderTop"]),el(["borderBottom"]),el(["borderLeft","borderRight"]),el(["borderLeft"]),el(["borderRight"]),e.s([],296059)},790887,e=>{"use strict";var t=e.i(415584);e.s(["StyleContext",()=>t.default])},327256,e=>{"use strict";var t=(0,e.i(271645).createContext)({});e.s(["default",0,t])},865610,e=>{"use strict";var t=e.i(815199),r=e.i(962837),n=e.i(713882),o=e.i(523699);function a(e){return(0,t.default)(e)||(0,r.default)(e)||(0,n.default)(e)||(0,o.default)()}e.s(["default",()=>a])},657791,e=>{"use strict";function t(e,t){for(var r=e,n=0;nt])},349057,e=>{"use strict";var t=e.i(410160),r=e.i(209428),n=e.i(8211),o=e.i(865610),a=e.i(657791);function i(e,t,i){var l=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return t.length&&l&&void 0===i&&!(0,a.default)(e,t.slice(0,-1))?e:function e(t,a,i,l){if(!a.length)return i;var s,c=(0,o.default)(a),u=c[0],d=c.slice(1);return s=t||"number"!=typeof u?Array.isArray(t)?(0,n.default)(t):(0,r.default)({},t):[],l&&void 0===i&&1===d.length?delete s[u][d[0]]:s[u]=e(s[u],d,i,l),s}(e,t,i,l)}function l(e){return Array.isArray(e)?[]:{}}var s="u"i,"merge",()=>c])},747656,e=>{"use strict";var t=e.i(271645);function r(){}e.i(883110);let n=t.createContext({});e.s(["WarningContext",0,n,"devUseWarning",0,()=>{let e=()=>{};return e.deprecated=r,e}])},819828,e=>{"use strict";let t=(0,e.i(271645).createContext)(void 0);e.s(["default",0,t])},87414,727214,e=>{"use strict";let t={items_per_page:"/ page",jump_to:"Go to",jump_to_confirm:"confirm",page:"Page",prev_page:"Previous Page",next_page:"Next Page",prev_5:"Previous 5 Pages",next_5:"Next 5 Pages",prev_3:"Previous 3 Pages",next_3:"Next 3 Pages",page_size:"Page Size"};e.s(["default",0,t],727214);var r=e.i(209428),n=(0,r.default)((0,r.default)({},{yearFormat:"YYYY",dayFormat:"D",cellMeridiemFormat:"A",monthBeforeYear:!0}),{},{locale:"en_US",today:"Today",now:"Now",backToToday:"Back to today",ok:"OK",clear:"Clear",week:"Week",month:"Month",year:"Year",timeSelect:"select time",dateSelect:"select date",weekSelect:"Choose a week",monthSelect:"Choose a month",yearSelect:"Choose a year",decadeSelect:"Choose a decade",dateFormat:"M/D/YYYY",dateTimeFormat:"M/D/YYYY HH:mm:ss",previousMonth:"Previous month (PageUp)",nextMonth:"Next month (PageDown)",previousYear:"Last year (Control + left)",nextYear:"Next year (Control + right)",previousDecade:"Last decade",nextDecade:"Next decade",previousCentury:"Last century",nextCentury:"Next century"});let o={placeholder:"Select time",rangePlaceholder:["Start time","End time"]},a={lang:Object.assign({placeholder:"Select date",yearPlaceholder:"Select year",quarterPlaceholder:"Select quarter",monthPlaceholder:"Select month",weekPlaceholder:"Select week",rangePlaceholder:["Start date","End date"],rangeYearPlaceholder:["Start year","End year"],rangeQuarterPlaceholder:["Start quarter","End quarter"],rangeMonthPlaceholder:["Start month","End month"],rangeWeekPlaceholder:["Start week","End week"]},n),timePickerLocale:Object.assign({},o)},i="${label} is not a valid ${type}";e.s(["default",0,{locale:"en",Pagination:t,DatePicker:a,TimePicker:o,Calendar:a,global:{placeholder:"Please select",close:"Close"},Table:{filterTitle:"Filter menu",filterConfirm:"OK",filterReset:"Reset",filterEmptyText:"No filters",filterCheckAll:"Select all items",filterSearchPlaceholder:"Search in filters",emptyText:"No data",selectAll:"Select current page",selectInvert:"Invert current page",selectNone:"Clear all data",selectionAll:"Select all data",sortTitle:"Sort",expand:"Expand row",collapse:"Collapse row",triggerDesc:"Click to sort descending",triggerAsc:"Click to sort ascending",cancelSort:"Click to cancel sorting"},Tour:{Next:"Next",Previous:"Previous",Finish:"Finish"},Modal:{okText:"OK",cancelText:"Cancel",justOkText:"OK"},Popconfirm:{okText:"OK",cancelText:"Cancel"},Transfer:{titles:["",""],searchPlaceholder:"Search here",itemUnit:"item",itemsUnit:"items",remove:"Remove",selectCurrent:"Select current page",removeCurrent:"Remove current page",selectAll:"Select all data",deselectAll:"Deselect all data",removeAll:"Remove all data",selectInvert:"Invert current page"},Upload:{uploading:"Uploading...",removeFile:"Remove file",uploadError:"Upload error",previewFile:"Preview file",downloadFile:"Download file"},Empty:{description:"No data"},Icon:{icon:"icon"},Text:{edit:"Edit",copy:"Copy",copied:"Copied",expand:"Expand",collapse:"Collapse"},Form:{optional:"(optional)",defaultValidateMessages:{default:"Field validation error for ${label}",required:"Please enter ${label}",enum:"${label} must be one of [${enum}]",whitespace:"${label} cannot be a blank character",date:{format:"${label} date format is invalid",parse:"${label} cannot be converted to a date",invalid:"${label} is an invalid date"},types:{string:i,method:i,array:i,object:i,number:i,date:i,boolean:i,integer:i,float:i,regexp:i,email:i,url:i,hex:i},string:{len:"${label} must be ${len} characters",min:"${label} must be at least ${min} characters",max:"${label} must be up to ${max} characters",range:"${label} must be between ${min}-${max} characters"},number:{len:"${label} must be equal to ${len}",min:"${label} must be minimum ${min}",max:"${label} must be maximum ${max}",range:"${label} must be between ${min}-${max}"},array:{len:"Must be ${len} ${label}",min:"At least ${min} ${label}",max:"At most ${max} ${label}",range:"The amount of ${label} must be between ${min}-${max}"},pattern:{mismatch:"${label} does not match the pattern ${pattern}"}}},Image:{preview:"Preview"},QRCode:{expired:"QR code expired",refresh:"Refresh",scanned:"Scanned"},ColorPicker:{presetEmpty:"Empty",transparent:"Transparent",singleColor:"Single",gradientColor:"Gradient"}}],87414)},606780,e=>{"use strict";var t=e.i(87414);let r=Object.assign({},t.default.Modal),n=[],o=()=>n.reduce((e,t)=>Object.assign(Object.assign({},e),t),t.default.Modal);function a(e){if(e){let t=Object.assign({},e);return n.push(t),r=o(),()=>{n=n.filter(e=>e!==t),r=o()}}r=Object.assign({},t.default.Modal)}function i(){return r}e.s(["changeConfirmLocale",()=>a,"getConfirmLocale",()=>i])},595575,e=>{"use strict";let t=(0,e.i(271645).createContext)(void 0);e.s(["default",0,t])},289863,e=>{"use strict";var t=e.i(271645),r=e.i(606780),n=e.i(595575);e.s(["ANT_MARK",0,"internalMark","default",0,e=>{let{locale:o={},children:a,_ANT_MARK__:i}=e;t.useEffect(()=>(0,r.changeConfirmLocale)(null==o?void 0:o.Modal),[o]);let l=t.useMemo(()=>Object.assign(Object.assign({},o),{exist:!0}),[o]);return t.createElement(n.default.Provider,{value:l},a)}])},765846,135551,262370,814534,896091,e=>{"use strict";var t=e.i(211577);let r=Math.round;function n(e,t){let r=e.replace(/^[^(]*\((.*)/,"$1").replace(/\).*/,"").match(/\d*\.?\d+%?/g)||[],n=r.map(e=>parseFloat(e));for(let e=0;e<3;e+=1)n[e]=t(n[e]||0,r[e]||"",e);return r[3]?n[3]=r[3].includes("%")?n[3]/100:n[3]:n[3]=1,n}let o=(e,t,r)=>0===r?e:e/100;function a(e,t){let r=t||255;return e>r?r:e<0?0:e}class i{constructor(e){function r(t){return t[0]in e&&t[1]in e&&t[2]in e}if((0,t.default)(this,"isValid",!0),(0,t.default)(this,"r",0),(0,t.default)(this,"g",0),(0,t.default)(this,"b",0),(0,t.default)(this,"a",1),(0,t.default)(this,"_h",void 0),(0,t.default)(this,"_s",void 0),(0,t.default)(this,"_l",void 0),(0,t.default)(this,"_v",void 0),(0,t.default)(this,"_max",void 0),(0,t.default)(this,"_min",void 0),(0,t.default)(this,"_brightness",void 0),e)if("string"==typeof e){const t=e.trim();function n(e){return t.startsWith(e)}/^#?[A-F\d]{3,8}$/i.test(t)?this.fromHexString(t):n("rgb")?this.fromRgbString(t):n("hsl")?this.fromHslString(t):(n("hsv")||n("hsb"))&&this.fromHsvString(t)}else if(e instanceof i)this.r=e.r,this.g=e.g,this.b=e.b,this.a=e.a,this._h=e._h,this._s=e._s,this._l=e._l,this._v=e._v;else if(r("rgb"))this.r=a(e.r),this.g=a(e.g),this.b=a(e.b),this.a="number"==typeof e.a?a(e.a,1):1;else if(r("hsl"))this.fromHsl(e);else if(r("hsv"))this.fromHsv(e);else throw Error("@ant-design/fast-color: unsupported input "+JSON.stringify(e))}setR(e){return this._sc("r",e)}setG(e){return this._sc("g",e)}setB(e){return this._sc("b",e)}setA(e){return this._sc("a",e,1)}setHue(e){let t=this.toHsv();return t.h=e,this._c(t)}getLuminance(){function e(e){let t=e/255;return t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)}return .2126*e(this.r)+.7152*e(this.g)+.0722*e(this.b)}getHue(){if(void 0===this._h){let e=this.getMax()-this.getMin();0===e?this._h=0:this._h=r(60*(this.r===this.getMax()?(this.g-this.b)/e+6*(this.g1&&(n=1),this._c({h:t,s:r,l:n,a:this.a})}mix(e,t=50){let n=this._c(e),o=t/100,a=e=>(n[e]-this[e])*o+this[e],i={r:r(a("r")),g:r(a("g")),b:r(a("b")),a:r(100*a("a"))/100};return this._c(i)}tint(e=10){return this.mix({r:255,g:255,b:255,a:1},e)}shade(e=10){return this.mix({r:0,g:0,b:0,a:1},e)}onBackground(e){let t=this._c(e),n=this.a+t.a*(1-this.a),o=e=>r((this[e]*this.a+t[e]*t.a*(1-this.a))/n);return this._c({r:o("r"),g:o("g"),b:o("b"),a:n})}isDark(){return 128>this.getBrightness()}isLight(){return this.getBrightness()>=128}equals(e){return this.r===e.r&&this.g===e.g&&this.b===e.b&&this.a===e.a}clone(){return this._c(this)}toHexString(){let e="#",t=(this.r||0).toString(16);e+=2===t.length?t:"0"+t;let n=(this.g||0).toString(16);e+=2===n.length?n:"0"+n;let o=(this.b||0).toString(16);if(e+=2===o.length?o:"0"+o,"number"==typeof this.a&&this.a>=0&&this.a<1){let t=r(255*this.a).toString(16);e+=2===t.length?t:"0"+t}return e}toHsl(){return{h:this.getHue(),s:this.getSaturation(),l:this.getLightness(),a:this.a}}toHslString(){let e=this.getHue(),t=r(100*this.getSaturation()),n=r(100*this.getLightness());return 1!==this.a?`hsla(${e},${t}%,${n}%,${this.a})`:`hsl(${e},${t}%,${n}%)`}toHsv(){return{h:this.getHue(),s:this.getSaturation(),v:this.getValue(),a:this.a}}toRgb(){return{r:this.r,g:this.g,b:this.b,a:this.a}}toRgbString(){return 1!==this.a?`rgba(${this.r},${this.g},${this.b},${this.a})`:`rgb(${this.r},${this.g},${this.b})`}toString(){return this.toRgbString()}_sc(e,t,r){let n=this.clone();return n[e]=a(t,r),n}_c(e){return new this.constructor(e)}getMax(){return void 0===this._max&&(this._max=Math.max(this.r,this.g,this.b)),this._max}getMin(){return void 0===this._min&&(this._min=Math.min(this.r,this.g,this.b)),this._min}fromHexString(e){let t=e.replace("#","");function r(e,r){return parseInt(t[e]+t[r||e],16)}t.length<6?(this.r=r(0),this.g=r(1),this.b=r(2),this.a=t[3]?r(3)/255:1):(this.r=r(0,1),this.g=r(2,3),this.b=r(4,5),this.a=t[6]?r(6,7)/255:1)}fromHsl({h:e,s:t,l:n,a:o}){if(this._h=e%360,this._s=t,this._l=n,this.a="number"==typeof o?o:1,t<=0){let e=r(255*n);this.r=e,this.g=e,this.b=e}let a=0,i=0,l=0,s=e/60,c=(1-Math.abs(2*n-1))*t,u=c*(1-Math.abs(s%2-1));s>=0&&s<1?(a=c,i=u):s>=1&&s<2?(a=u,i=c):s>=2&&s<3?(i=c,l=u):s>=3&&s<4?(i=u,l=c):s>=4&&s<5?(a=u,l=c):s>=5&&s<6&&(a=c,l=u);let d=n-c/2;this.r=r((a+d)*255),this.g=r((i+d)*255),this.b=r((l+d)*255)}fromHsv({h:e,s:t,v:n,a:o}){this._h=e%360,this._s=t,this._v=n,this.a="number"==typeof o?o:1;let a=r(255*n);if(this.r=a,this.g=a,this.b=a,t<=0)return;let i=e/60,l=Math.floor(i),s=i-l,c=r(n*(1-t)*255),u=r(n*(1-t*s)*255),d=r(n*(1-t*(1-s))*255);switch(l){case 0:this.g=d,this.b=c;break;case 1:this.r=u,this.b=c;break;case 2:this.r=c,this.b=d;break;case 3:this.r=c,this.g=u;break;case 4:this.r=d,this.g=c;break;default:this.g=c,this.b=u}}fromHsvString(e){let t=n(e,o);this.fromHsv({h:t[0],s:t[1],v:t[2],a:t[3]})}fromHslString(e){let t=n(e,o);this.fromHsl({h:t[0],s:t[1],l:t[2],a:t[3]})}fromRgbString(e){let t=n(e,(e,t)=>t.includes("%")?r(e/100*255):e);this.r=t[0],this.g=t[1],this.b=t[2],this.a=t[3]}}e.s(["FastColor",()=>i],135551),e.s([],262370);var l=[{index:7,amount:15},{index:6,amount:25},{index:5,amount:30},{index:5,amount:45},{index:5,amount:65},{index:5,amount:85},{index:4,amount:90},{index:3,amount:95},{index:2,amount:97},{index:1,amount:98}];function s(e,t,r){var n;return(n=Math.round(e.h)>=60&&240>=Math.round(e.h)?r?Math.round(e.h)-2*t:Math.round(e.h)+2*t:r?Math.round(e.h)+2*t:Math.round(e.h)-2*t)<0?n+=360:n>=360&&(n-=360),n}function c(e,t,r){var n;return 0===e.h&&0===e.s?e.s:((n=r?e.s-.16*t:4===t?e.s+.16:e.s+.05*t)>1&&(n=1),r&&5===t&&n>.1&&(n=.1),n<.06&&(n=.06),Math.round(100*n)/100)}function u(e,t,r){return Math.round(100*Math.max(0,Math.min(1,r?e.v+.05*t:e.v-.15*t)))/100}function d(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=[],n=new i(e),o=n.toHsv(),a=5;a>0;a-=1){var d=new i({h:s(o,a,!0),s:c(o,a,!0),v:u(o,a,!0)});r.push(d)}r.push(n);for(var f=1;f<=4;f+=1){var p=new i({h:s(o,f),s:c(o,f),v:u(o,f)});r.push(p)}return"dark"===t.theme?l.map(function(e){var n=e.index,o=e.amount;return new i(t.backgroundColor||"#141414").mix(r[n],o).toHexString()}):r.map(function(e){return e.toHexString()})}e.s(["default",()=>d],814534);var f={red:"#F5222D",volcano:"#FA541C",orange:"#FA8C16",gold:"#FAAD14",yellow:"#FADB14",lime:"#A0D911",green:"#52C41A",cyan:"#13C2C2",blue:"#1677FF",geekblue:"#2F54EB",purple:"#722ED1",magenta:"#EB2F96",grey:"#666666"},p=["#fff1f0","#ffccc7","#ffa39e","#ff7875","#ff4d4f","#f5222d","#cf1322","#a8071a","#820014","#5c0011"];p.primary=p[5];var m=["#fff2e8","#ffd8bf","#ffbb96","#ff9c6e","#ff7a45","#fa541c","#d4380d","#ad2102","#871400","#610b00"];m.primary=m[5];var g=["#fff7e6","#ffe7ba","#ffd591","#ffc069","#ffa940","#fa8c16","#d46b08","#ad4e00","#873800","#612500"];g.primary=g[5];var h=["#fffbe6","#fff1b8","#ffe58f","#ffd666","#ffc53d","#faad14","#d48806","#ad6800","#874d00","#613400"];h.primary=h[5];var v=["#feffe6","#ffffb8","#fffb8f","#fff566","#ffec3d","#fadb14","#d4b106","#ad8b00","#876800","#614700"];v.primary=v[5];var y=["#fcffe6","#f4ffb8","#eaff8f","#d3f261","#bae637","#a0d911","#7cb305","#5b8c00","#3f6600","#254000"];y.primary=y[5];var b=["#f6ffed","#d9f7be","#b7eb8f","#95de64","#73d13d","#52c41a","#389e0d","#237804","#135200","#092b00"];b.primary=b[5];var w=["#e6fffb","#b5f5ec","#87e8de","#5cdbd3","#36cfc9","#13c2c2","#08979c","#006d75","#00474f","#002329"];w.primary=w[5];var C=["#e6f4ff","#bae0ff","#91caff","#69b1ff","#4096ff","#1677ff","#0958d9","#003eb3","#002c8c","#001d66"];C.primary=C[5];var x=["#f0f5ff","#d6e4ff","#adc6ff","#85a5ff","#597ef7","#2f54eb","#1d39c4","#10239e","#061178","#030852"];x.primary=x[5];var S=["#f9f0ff","#efdbff","#d3adf7","#b37feb","#9254de","#722ed1","#531dab","#391085","#22075e","#120338"];S.primary=S[5];var $=["#fff0f6","#ffd6e7","#ffadd2","#ff85c0","#f759ab","#eb2f96","#c41d7f","#9e1068","#780650","#520339"];$.primary=$[5];var E=["#a6a6a6","#999999","#8c8c8c","#808080","#737373","#666666","#404040","#1a1a1a","#000000","#000000"];E.primary=E[5];var k={red:p,volcano:m,orange:g,gold:h,yellow:v,lime:y,green:b,cyan:w,blue:C,geekblue:x,purple:S,magenta:$,grey:E},O=["#2a1215","#431418","#58181c","#791a1f","#a61d24","#d32029","#e84749","#f37370","#f89f9a","#fac8c3"];O.primary=O[5];var j=["#2b1611","#441d12","#592716","#7c3118","#aa3e19","#d84a1b","#e87040","#f3956a","#f8b692","#fad4bc"];j.primary=j[5];var T=["#2b1d11","#442a11","#593815","#7c4a15","#aa6215","#d87a16","#e89a3c","#f3b765","#f8cf8d","#fae3b7"];T.primary=T[5];var _=["#2b2111","#443111","#594214","#7c5914","#aa7714","#d89614","#e8b339","#f3cc62","#f8df8b","#faedb5"];_.primary=_[5];var P=["#2b2611","#443b11","#595014","#7c6e14","#aa9514","#d8bd14","#e8d639","#f3ea62","#f8f48b","#fafab5"];P.primary=P[5];var I=["#1f2611","#2e3c10","#3e4f13","#536d13","#6f9412","#8bbb11","#a9d134","#c9e75d","#e4f88b","#f0fab5"];I.primary=I[5];var F=["#162312","#1d3712","#274916","#306317","#3c8618","#49aa19","#6abe39","#8fd460","#b2e58b","#d5f2bb"];F.primary=F[5];var N=["#112123","#113536","#144848","#146262","#138585","#13a8a8","#33bcb7","#58d1c9","#84e2d8","#b2f1e8"];N.primary=N[5];var R=["#111a2c","#112545","#15325b","#15417e","#1554ad","#1668dc","#3c89e8","#65a9f3","#8dc5f8","#b7dcfa"];R.primary=R[5];var M=["#131629","#161d40","#1c2755","#203175","#263ea0","#2b4acb","#5273e0","#7f9ef3","#a8c1f8","#d2e0fa"];M.primary=M[5];var A=["#1a1325","#24163a","#301c4d","#3e2069","#51258f","#642ab5","#854eca","#ab7ae0","#cda8f0","#ebd7fa"];A.primary=A[5];var B=["#291321","#40162f","#551c3b","#75204f","#a02669","#cb2b83","#e0529c","#f37fb7","#f8a8cc","#fad2e3"];B.primary=B[5];var z=["#151515","#1f1f1f","#2d2d2d","#393939","#494949","#5a5a5a","#6a6a6a","#7b7b7b","#888888","#969696"];z.primary=z[5],e.s(["blue",()=>C,"gold",()=>h,"presetPalettes",()=>k,"presetPrimaryColors",()=>f],896091),e.s([],765846)},602716,e=>{"use strict";var t=e.i(814534);e.s(["generate",()=>t.default])},310751,170517,328052,8398,988317,279728,722319,289882,320890,e=>{"use strict";e.i(296059);var t=e.i(868297);e.i(765846);var r=e.i(602716),n=e.i(896091);let o={blue:"#1677FF",purple:"#722ED1",cyan:"#13C2C2",green:"#52C41A",magenta:"#EB2F96",pink:"#EB2F96",red:"#F5222D",orange:"#FA8C16",yellow:"#FADB14",volcano:"#FA541C",geekblue:"#2F54EB",gold:"#FAAD14",lime:"#A0D911"},a=Object.assign(Object.assign({},o),{colorPrimary:"#1677ff",colorSuccess:"#52c41a",colorWarning:"#faad14",colorError:"#ff4d4f",colorInfo:"#1677ff",colorLink:"",colorTextBase:"",colorBgBase:"",fontFamily:`-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, +'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', +'Noto Color Emoji'`,fontFamilyCode:"'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace",fontSize:14,lineWidth:1,lineType:"solid",motionUnit:.1,motionBase:0,motionEaseOutCirc:"cubic-bezier(0.08, 0.82, 0.17, 1)",motionEaseInOutCirc:"cubic-bezier(0.78, 0.14, 0.15, 0.86)",motionEaseOut:"cubic-bezier(0.215, 0.61, 0.355, 1)",motionEaseInOut:"cubic-bezier(0.645, 0.045, 0.355, 1)",motionEaseOutBack:"cubic-bezier(0.12, 0.4, 0.29, 1.46)",motionEaseInBack:"cubic-bezier(0.71, -0.46, 0.88, 0.6)",motionEaseInQuint:"cubic-bezier(0.755, 0.05, 0.855, 0.06)",motionEaseOutQuint:"cubic-bezier(0.23, 1, 0.32, 1)",borderRadius:6,sizeUnit:4,sizeStep:4,sizePopupArrow:16,controlHeight:32,zIndexBase:0,zIndexPopupBase:1e3,opacityImage:1,wireframe:!1,motion:!0});e.s(["default",0,a,"defaultPresetColors",0,o],170517),e.i(262370);var i=e.i(135551);function l(e,{generateColorPalettes:t,generateNeutralColorPalettes:r}){let{colorSuccess:n,colorWarning:o,colorError:a,colorInfo:l,colorPrimary:s,colorBgBase:c,colorTextBase:u}=e,d=t(s),f=t(n),p=t(o),m=t(a),g=t(l),h=r(c,u),v=t(e.colorLink||e.colorInfo),y=new i.FastColor(m[1]).mix(new i.FastColor(m[3]),50).toHexString();return Object.assign(Object.assign({},h),{colorPrimaryBg:d[1],colorPrimaryBgHover:d[2],colorPrimaryBorder:d[3],colorPrimaryBorderHover:d[4],colorPrimaryHover:d[5],colorPrimary:d[6],colorPrimaryActive:d[7],colorPrimaryTextHover:d[8],colorPrimaryText:d[9],colorPrimaryTextActive:d[10],colorSuccessBg:f[1],colorSuccessBgHover:f[2],colorSuccessBorder:f[3],colorSuccessBorderHover:f[4],colorSuccessHover:f[4],colorSuccess:f[6],colorSuccessActive:f[7],colorSuccessTextHover:f[8],colorSuccessText:f[9],colorSuccessTextActive:f[10],colorErrorBg:m[1],colorErrorBgHover:m[2],colorErrorBgFilledHover:y,colorErrorBgActive:m[3],colorErrorBorder:m[3],colorErrorBorderHover:m[4],colorErrorHover:m[5],colorError:m[6],colorErrorActive:m[7],colorErrorTextHover:m[8],colorErrorText:m[9],colorErrorTextActive:m[10],colorWarningBg:p[1],colorWarningBgHover:p[2],colorWarningBorder:p[3],colorWarningBorderHover:p[4],colorWarningHover:p[4],colorWarning:p[6],colorWarningActive:p[7],colorWarningTextHover:p[8],colorWarningText:p[9],colorWarningTextActive:p[10],colorInfoBg:g[1],colorInfoBgHover:g[2],colorInfoBorder:g[3],colorInfoBorderHover:g[4],colorInfoHover:g[4],colorInfo:g[6],colorInfoActive:g[7],colorInfoTextHover:g[8],colorInfoText:g[9],colorInfoTextActive:g[10],colorLinkHover:v[4],colorLink:v[6],colorLinkActive:v[7],colorBgMask:new i.FastColor("#000").setA(.45).toRgbString(),colorWhite:"#fff"})}e.s(["default",()=>l],328052);let s=e=>{let{controlHeight:t}=e;return{controlHeightSM:.75*t,controlHeightXS:.5*t,controlHeightLG:1.25*t}};function c(e){return(e+8)/e}function u(e){let t=Array.from({length:10}).map((t,r)=>{let n=e*Math.pow(Math.E,(r-1)/5);return 2*Math.floor((r>1?Math.floor(n):Math.ceil(n))/2)});return t[1]=e,t.map(e=>({size:e,lineHeight:c(e)}))}e.s(["default",0,s],8398),e.s(["default",()=>u,"getLineHeight",()=>c],988317);let d=e=>{let t=u(e),r=t.map(e=>e.size),n=t.map(e=>e.lineHeight),o=r[1],a=r[0],i=r[2],l=n[1],s=n[0],c=n[2];return{fontSizeSM:a,fontSize:o,fontSizeLG:i,fontSizeXL:r[3],fontSizeHeading1:r[6],fontSizeHeading2:r[5],fontSizeHeading3:r[4],fontSizeHeading4:r[3],fontSizeHeading5:r[2],lineHeight:l,lineHeightLG:c,lineHeightSM:s,fontHeight:Math.round(l*o),fontHeightLG:Math.round(c*i),fontHeightSM:Math.round(s*a),lineHeightHeading1:n[6],lineHeightHeading2:n[5],lineHeightHeading3:n[4],lineHeightHeading4:n[3],lineHeightHeading5:n[2]}};e.s(["default",0,d],279728);let f=(e,t)=>new i.FastColor(e).setA(t).toRgbString(),p=(e,t)=>new i.FastColor(e).darken(t).toHexString(),m=e=>{let t=(0,r.generate)(e);return{1:t[0],2:t[1],3:t[2],4:t[3],5:t[4],6:t[5],7:t[6],8:t[4],9:t[5],10:t[6]}},g=(e,t)=>{let r=e||"#fff",n=t||"#000";return{colorBgBase:r,colorTextBase:n,colorText:f(n,.88),colorTextSecondary:f(n,.65),colorTextTertiary:f(n,.45),colorTextQuaternary:f(n,.25),colorFill:f(n,.15),colorFillSecondary:f(n,.06),colorFillTertiary:f(n,.04),colorFillQuaternary:f(n,.02),colorBgSolid:f(n,1),colorBgSolidHover:f(n,.75),colorBgSolidActive:f(n,.95),colorBgLayout:p(r,4),colorBgContainer:p(r,0),colorBgElevated:p(r,0),colorBgSpotlight:f(n,.85),colorBgBlur:"transparent",colorBorder:p(r,15),colorBorderSecondary:p(r,6)}};function h(e){n.presetPrimaryColors.pink=n.presetPrimaryColors.magenta,n.presetPalettes.pink=n.presetPalettes.magenta;let t=Object.keys(o).map(t=>{let o=e[t]===n.presetPrimaryColors[t]?n.presetPalettes[t]:(0,r.generate)(e[t]);return Array.from({length:10},()=>1).reduce((e,r,n)=>(e[`${t}-${n+1}`]=o[n],e[`${t}${n+1}`]=o[n],e),{})}).reduce((e,t)=>e=Object.assign(Object.assign({},e),t),{});return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},e),t),l(e,{generateColorPalettes:m,generateNeutralColorPalettes:g})),d(e.fontSize)),function(e){let{sizeUnit:t,sizeStep:r}=e;return{sizeXXL:t*(r+8),sizeXL:t*(r+4),sizeLG:t*(r+2),sizeMD:t*(r+1),sizeMS:t*r,size:t*r,sizeSM:t*(r-1),sizeXS:t*(r-2),sizeXXS:t*(r-3)}}(e)),s(e)),function(e){let t,r,n,o,{motionUnit:a,motionBase:i,borderRadius:l,lineWidth:s}=e;return Object.assign({motionDurationFast:`${(i+a).toFixed(1)}s`,motionDurationMid:`${(i+2*a).toFixed(1)}s`,motionDurationSlow:`${(i+3*a).toFixed(1)}s`,lineWidthBold:s+1},(t=l,r=l,n=l,o=l,l<6&&l>=5?t=l+1:l<16&&l>=6?t=l+2:l>=16&&(t=16),l<7&&l>=5?r=4:l<8&&l>=7?r=5:l<14&&l>=8?r=6:l<16&&l>=14?r=7:l>=16&&(r=8),l<6&&l>=2?n=1:l>=6&&(n=2),l>4&&l<8?o=4:l>=8&&(o=6),{borderRadius:l,borderRadiusXS:n,borderRadiusSM:r,borderRadiusLG:t,borderRadiusOuter:o}))}(e))}e.s(["default",()=>h],722319);let v=(0,t.createTheme)(h);e.s(["default",0,v],289882),e.s(["defaultTheme",0,v],310751);var y=e.i(271645);let b={token:a,override:{override:a},hashed:!0},w=y.default.createContext(b);e.s(["DesignTokenContext",0,w,"defaultConfig",0,b],320890)},242064,e=>{"use strict";var t=e.i(271645);let r="anticon",n=t.createContext({getPrefixCls:(e,t)=>t||(e?`ant-${e}`:"ant"),iconPrefixCls:r}),{Consumer:o}=n,a={};function i(e){let r=t.useContext(n),{getPrefixCls:o,direction:i,getPopupContainer:l}=r;return Object.assign(Object.assign({classNames:a,styles:a},r[e]),{getPrefixCls:o,direction:i,getPopupContainer:l})}e.s(["ConfigConsumer",0,o,"ConfigContext",0,n,"Variants",0,["outlined","borderless","filled","underlined"],"defaultIconPrefixCls",0,r,"defaultPrefixCls",0,"ant","useComponentConfig",()=>i])},328542,e=>{"use strict";e.i(765846);var t=e.i(602716);e.i(262370);var r=e.i(135551),n=e.i(654310),o=e.i(575943);let a=`-ant-${Date.now()}-${Math.random()}`;function i(e,i){let l=function(e,n){let o={},a=(e,t)=>{let r=e.clone();return(r=(null==t?void 0:t(r))||r).toRgbString()},i=(e,n)=>{let i=new r.FastColor(e),l=(0,t.generate)(i.toRgbString());o[`${n}-color`]=a(i),o[`${n}-color-disabled`]=l[1],o[`${n}-color-hover`]=l[4],o[`${n}-color-active`]=l[6],o[`${n}-color-outline`]=i.clone().setA(.2).toRgbString(),o[`${n}-color-deprecated-bg`]=l[0],o[`${n}-color-deprecated-border`]=l[2]};if(n.primaryColor){i(n.primaryColor,"primary");let e=new r.FastColor(n.primaryColor),l=(0,t.generate)(e.toRgbString());l.forEach((e,t)=>{o[`primary-${t+1}`]=e}),o["primary-color-deprecated-l-35"]=a(e,e=>e.lighten(35)),o["primary-color-deprecated-l-20"]=a(e,e=>e.lighten(20)),o["primary-color-deprecated-t-20"]=a(e,e=>e.tint(20)),o["primary-color-deprecated-t-50"]=a(e,e=>e.tint(50)),o["primary-color-deprecated-f-12"]=a(e,e=>e.setA(.12*e.a));let s=new r.FastColor(l[0]);o["primary-color-active-deprecated-f-30"]=a(s,e=>e.setA(.3*e.a)),o["primary-color-active-deprecated-d-02"]=a(s,e=>e.darken(2))}n.successColor&&i(n.successColor,"success"),n.warningColor&&i(n.warningColor,"warning"),n.errorColor&&i(n.errorColor,"error"),n.infoColor&&i(n.infoColor,"info");let l=Object.keys(o).map(t=>`--${e}-${t}: ${o[t]};`);return` + :root { + ${l.join("\n")} + } + `.trim()}(e,i);(0,n.default)()&&(0,o.updateCSS)(l,`${a}-dynamic-theme`)}e.s(["registerTheme",()=>i])},937328,e=>{"use strict";var t=e.i(271645);let r=t.createContext(!1);e.s(["DisabledContextProvider",0,({children:e,disabled:n})=>{let o=t.useContext(r);return t.createElement(r.Provider,{value:null!=n?n:o},e)},"default",0,r])},666365,e=>{"use strict";var t=e.i(271645);let r=t.createContext(void 0);e.s(["SizeContextProvider",0,({children:e,size:n})=>{let o=t.useContext(r);return t.createElement(r.Provider,{value:n||o},e)},"default",0,r])},80527,308978,e=>{"use strict";var t=e.i(271645),r=e.i(937328),n=e.i(666365);e.s(["default",0,function(){return{componentDisabled:(0,t.useContext)(r.default),componentSize:(0,t.useContext)(n.default)}}],80527),e.i(247167);var o=e.i(182585),a=e.i(929123),i=e.i(747656),l=e.i(320890);let{useId:s}=Object.assign({},t),c=void 0===s?()=>"":s;function u(e,t,r){var n;(0,i.devUseWarning)("ConfigProvider");let s=e||{},u=!1!==s.inherit&&t?t:Object.assign(Object.assign({},l.defaultConfig),{hashed:null!=(n=null==t?void 0:t.hashed)?n:l.defaultConfig.hashed,cssVar:null==t?void 0:t.cssVar}),d=c();return(0,o.default)(()=>{var n,o;if(!e)return t;let a=Object.assign({},u.components);Object.keys(e.components||{}).forEach(t=>{a[t]=Object.assign(Object.assign({},a[t]),e.components[t])});let i=`css-var-${d.replace(/:/g,"")}`,l=(null!=(n=s.cssVar)?n:u.cssVar)&&Object.assign(Object.assign(Object.assign({prefix:null==r?void 0:r.prefixCls},"object"==typeof u.cssVar?u.cssVar:{}),"object"==typeof s.cssVar?s.cssVar:{}),{key:"object"==typeof s.cssVar&&(null==(o=s.cssVar)?void 0:o.key)||i});return Object.assign(Object.assign(Object.assign({},u),s),{token:Object.assign(Object.assign({},u.token),s.token),components:a,cssVar:l})},[s,u],(e,t)=>e.some((e,r)=>{let n=t[r];return!(0,a.default)(e,n,!0)}))}e.s(["default",()=>u],308978)},343794,(e,t,r)=>{!function(){"use strict";var r={}.hasOwnProperty;function n(){for(var e="",t=0;t{"use strict";var t=e.i(410160),r=e.i(271645),n=e.i(174080);function o(e){return e instanceof HTMLElement||e instanceof SVGElement}function a(e){return e&&"object"===(0,t.default)(e)&&o(e.nativeElement)?e.nativeElement:o(e)?e:null}function i(e){var t,o=a(e);return o||(e instanceof r.default.Component?null==(t=n.default.findDOMNode)?void 0:t.call(n.default,e):null)}e.s(["default",()=>i,"getDOM",()=>a,"isDOM",()=>o])},65300,(e,t,r)=>{"use strict";var n,o=Symbol.for("react.element"),a=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),l=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),c=Symbol.for("react.provider"),u=Symbol.for("react.context"),d=Symbol.for("react.server_context"),f=Symbol.for("react.forward_ref"),p=Symbol.for("react.suspense"),m=Symbol.for("react.suspense_list"),g=Symbol.for("react.memo"),h=Symbol.for("react.lazy"),v=Symbol.for("react.offscreen");function y(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case o:switch(e=e.type){case i:case s:case l:case p:case m:return e;default:switch(e=e&&e.$$typeof){case d:case u:case f:case h:case g:case c:return e;default:return t}}case a:return t}}}n=Symbol.for("react.module.reference"),r.ContextConsumer=u,r.ContextProvider=c,r.Element=o,r.ForwardRef=f,r.Fragment=i,r.Lazy=h,r.Memo=g,r.Portal=a,r.Profiler=s,r.StrictMode=l,r.Suspense=p,r.SuspenseList=m,r.isAsyncMode=function(){return!1},r.isConcurrentMode=function(){return!1},r.isContextConsumer=function(e){return y(e)===u},r.isContextProvider=function(e){return y(e)===c},r.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===o},r.isForwardRef=function(e){return y(e)===f},r.isFragment=function(e){return y(e)===i},r.isLazy=function(e){return y(e)===h},r.isMemo=function(e){return y(e)===g},r.isPortal=function(e){return y(e)===a},r.isProfiler=function(e){return y(e)===s},r.isStrictMode=function(e){return y(e)===l},r.isSuspense=function(e){return y(e)===p},r.isSuspenseList=function(e){return y(e)===m},r.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===i||e===s||e===l||e===p||e===m||e===v||"object"==typeof e&&null!==e&&(e.$$typeof===h||e.$$typeof===g||e.$$typeof===c||e.$$typeof===u||e.$$typeof===f||e.$$typeof===n||void 0!==e.getModuleId)||!1},r.typeOf=y},428383,(e,t,r)=>{"use strict";t.exports=e.r(65300)},565924,e=>{"use strict";var t=e.i(410160),r=Symbol.for("react.element"),n=Symbol.for("react.transitional.element"),o=Symbol.for("react.fragment");function a(e){return e&&"object"===(0,t.default)(e)&&(e.$$typeof===r||e.$$typeof===n)&&e.type===o}e.s(["default",()=>a])},611935,e=>{"use strict";var t=e.i(410160),r=e.i(271645),n=e.i(428383),o=e.i(182585),a=e.i(565924),i=Number(r.version.split(".")[0]),l=function(e,r){"function"==typeof e?e(r):"object"===(0,t.default)(e)&&e&&"current"in e&&(e.current=r)},s=function(){for(var e=arguments.length,t=Array(e),r=0;r=19)return!0;var t,r,o=(0,n.isMemo)(e)?e.type.type:e.type;return("function"!=typeof o||!!(null!=(t=o.prototype)&&t.render)||o.$$typeof===n.ForwardRef)&&("function"!=typeof e||!!(null!=(r=e.prototype)&&r.render)||e.$$typeof===n.ForwardRef)};function d(e){return(0,r.isValidElement)(e)&&!(0,a.default)(e)}var f=function(e){return d(e)&&u(e)},p=function(e){return e&&d(e)?e.props.propertyIsEnumerable("ref")?e.props.ref:e.ref:null};e.s(["composeRef",()=>s,"fillRef",()=>l,"getNodeRef",()=>p,"supportNodeRef",()=>f,"supportRef",()=>u,"useComposeRef",()=>c])},865623,e=>{"use strict";var t=e.i(703923),r=e.i(271645),n=["children"],o=r.createContext({});function a(e){var a=e.children,i=(0,t.default)(e,n);return r.createElement(o.Provider,{value:i},a)}e.s(["Context",()=>o,"default",()=>a])},533812,e=>{"use strict";var t=e.i(278409),r=e.i(233848),n=e.i(868917),o=e.i(674813),a=function(e){(0,n.default)(i,e);var a=(0,o.default)(i);function i(){return(0,t.default)(this,i),a.apply(this,arguments)}return(0,r.default)(i,[{key:"render",value:function(){return this.props.children}}]),i}(e.i(271645).Component);e.s(["default",0,a])},175066,e=>{"use strict";var t=e.i(271645);function r(e){var r=t.useRef();return r.current=e,t.useCallback(function(){for(var e,t=arguments.length,n=Array(t),o=0;or])},914949,290967,e=>{"use strict";var t=e.i(392221),r=e.i(175066),n=e.i(174428),o=e.i(271645);function a(e){var r=o.useRef(!1),n=o.useState(e),a=(0,t.default)(n,2),i=a[0],l=a[1];return o.useEffect(function(){return r.current=!1,function(){r.current=!0}},[]),[i,function(e,t){t&&r.current||l(e)}]}function i(e){return void 0!==e}function l(e,o){var l=o||{},s=l.defaultValue,c=l.value,u=l.onChange,d=l.postState,f=a(function(){return i(c)?c:i(s)?"function"==typeof s?s():s:"function"==typeof e?e():e}),p=(0,t.default)(f,2),m=p[0],g=p[1],h=void 0!==c?c:m,v=d?d(h):h,y=(0,r.default)(u),b=a([h]),w=(0,t.default)(b,2),C=w[0],x=w[1];return(0,n.useLayoutUpdateEffect)(function(){var e=C[0];m!==e&&y(m,e)},[C]),(0,n.useLayoutUpdateEffect)(function(){i(c)||g(c)},[c]),[v,(0,r.default)(function(e,t){g(e,t),x([h],t)})]}e.s(["default",()=>a],290967),e.s(["default",()=>l],914949)},62664,e=>{"use strict";e.i(175066),e.i(914949),e.i(611935),e.i(657791),e.i(349057),e.i(883110),e.s([])},697539,328599,18684,973663,28823,947065,e=>{"use strict";var t,r,n,o=e.i(175066);e.s(["useEvent",()=>o.default],697539);var a=e.i(392221),i=e.i(271645);function l(e){var t=i.useReducer(function(e){return e+1},0),r=(0,a.default)(t,2)[1],n=i.useRef(e);return[(0,o.default)(function(){return n.current}),(0,o.default)(function(e){n.current="function"==typeof e?e(n.current):e,r()})]}e.s(["default",()=>l],328599),e.s(["STATUS_APPEAR",()=>"appear","STATUS_ENTER",()=>"enter","STATUS_LEAVE",()=>"leave","STATUS_NONE",()=>"none","STEP_ACTIVATED",()=>"end","STEP_ACTIVE",()=>"active","STEP_NONE",()=>"none","STEP_PREPARE",()=>"prepare","STEP_PREPARED",()=>"prepared","STEP_START",()=>"start"],18684);var s=e.i(410160),c=e.i(654310);function u(e,t){var r={};return r[e.toLowerCase()]=t.toLowerCase(),r["Webkit".concat(e)]="webkit".concat(t),r["Moz".concat(e)]="moz".concat(t),r["ms".concat(e)]="MS".concat(t),r["O".concat(e)]="o".concat(t.toLowerCase()),r}var d=(t=(0,c.default)(),r="u">typeof window?window:{},n={animationend:u("Animation","AnimationEnd"),transitionend:u("Transition","TransitionEnd")},t&&("AnimationEvent"in r||delete n.animationend.animation,"TransitionEvent"in r||delete n.transitionend.transition),n),f={};(0,c.default)()&&(f=document.createElement("div").style);var p={};function m(e){if(p[e])return p[e];var t=d[e];if(t)for(var r=Object.keys(t),n=r.length,o=0;oy,"getTransitionName",()=>w,"supportTransition",()=>v,"transitionEndName",()=>b],973663),e.s(["default",0,function(e){var t=(0,i.useRef)();function r(t){t&&(t.removeEventListener(b,e),t.removeEventListener(y,e))}return i.useEffect(function(){return function(){r(t.current)}},[]),[function(n){t.current&&t.current!==n&&r(t.current),n&&n!==t.current&&(n.addEventListener(b,e),n.addEventListener(y,e),t.current=n)},r]}],28823);var C=(0,c.default)()?i.useLayoutEffect:i.useEffect;e.s(["default",0,C],947065)},963188,e=>{"use strict";var t=function(e){return+setTimeout(e,16)},r=function(e){return clearTimeout(e)};"u">typeof window&&"requestAnimationFrame"in window&&(t=function(e){return window.requestAnimationFrame(e)},r=function(e){return window.cancelAnimationFrame(e)});var n=0,o=new Map,a=function(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,a=n+=1;return!function r(n){if(0===n)o.delete(a),e();else{var i=t(function(){r(n-1)});o.set(a,i)}}(r),a};a.cancel=function(e){var t=o.get(e);return o.delete(e),r(t)},e.s(["default",0,a])},361275,26432,e=>{"use strict";var t,r,n,o=e.i(211577),a=e.i(209428),i=e.i(392221),l=e.i(410160),s=e.i(343794),c=e.i(279697),u=e.i(611935),d=e.i(271645),f=e.i(865623),p=e.i(533812);e.i(62664);var m=e.i(697539),g=e.i(290967),h=e.i(328599),v=e.i(18684),y=e.i(28823),b=e.i(947065),w=e.i(963188);let C=function(){var e=d.useRef(null);function t(){w.default.cancel(e.current)}return d.useEffect(function(){return function(){t()}},[]),[function r(n){var o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;t();var a=(0,w.default)(function(){o<=1?n({isCanceled:function(){return a!==e.current}}):r(n,o-1)});e.current=a},t]};var x=[v.STEP_PREPARE,v.STEP_START,v.STEP_ACTIVE,v.STEP_ACTIVATED],S=[v.STEP_PREPARE,v.STEP_PREPARED];function $(e){return e===v.STEP_ACTIVE||e===v.STEP_ACTIVATED}let E=function(e,t,r){var n=(0,g.default)(v.STEP_NONE),o=(0,i.default)(n,2),a=o[0],l=o[1],s=C(),c=(0,i.default)(s,2),u=c[0],f=c[1],p=t?S:x;return(0,b.default)(function(){if(a!==v.STEP_NONE&&a!==v.STEP_ACTIVATED){var e=p.indexOf(a),t=p[e+1],n=r(a);!1===n?l(t,!0):t&&u(function(e){function r(){e.isCanceled()||l(t,!0)}!0===n?r():Promise.resolve(n).then(r)})}},[e,a]),d.useEffect(function(){return function(){f()}},[]),[function(){l(v.STEP_PREPARE,!0)},a]};var k=e.i(973663);let O=(r=t=k.supportTransition,"object"===(0,l.default)(t)&&(r=t.transitionSupport),(n=d.forwardRef(function(e,t){var n=e.visible,l=void 0===n||n,w=e.removeOnLeave,C=void 0===w||w,x=e.forceRender,S=e.children,O=e.motionName,j=e.leavedClassName,T=e.eventProps,_=d.useContext(f.Context).motion,P=!!(e.motionName&&r&&!1!==_),I=(0,d.useRef)(),F=(0,d.useRef)(),N=function(e,t,r,n){var l=n.motionEnter,s=void 0===l||l,c=n.motionAppear,u=void 0===c||c,f=n.motionLeave,p=void 0===f||f,w=n.motionDeadline,C=n.motionLeaveImmediately,x=n.onAppearPrepare,S=n.onEnterPrepare,k=n.onLeavePrepare,O=n.onAppearStart,j=n.onEnterStart,T=n.onLeaveStart,_=n.onAppearActive,P=n.onEnterActive,I=n.onLeaveActive,F=n.onAppearEnd,N=n.onEnterEnd,R=n.onLeaveEnd,M=n.onVisibleChanged,A=(0,g.default)(),B=(0,i.default)(A,2),z=B[0],L=B[1],H=(0,h.default)(v.STATUS_NONE),D=(0,i.default)(H,2),V=D[0],W=D[1],U=(0,g.default)(null),G=(0,i.default)(U,2),q=G[0],K=G[1],X=V(),J=(0,d.useRef)(!1),Y=(0,d.useRef)(null),Q=(0,d.useRef)(!1);function Z(){W(v.STATUS_NONE),K(null,!0)}var ee=(0,m.useEvent)(function(e){var t,n=V();if(n!==v.STATUS_NONE){var o=r();if(!e||e.deadline||e.target===o){var a=Q.current;n===v.STATUS_APPEAR&&a?t=null==F?void 0:F(o,e):n===v.STATUS_ENTER&&a?t=null==N?void 0:N(o,e):n===v.STATUS_LEAVE&&a&&(t=null==R?void 0:R(o,e)),a&&!1!==t&&Z()}}}),et=(0,y.default)(ee),er=(0,i.default)(et,1)[0],en=function(e){switch(e){case v.STATUS_APPEAR:return(0,o.default)((0,o.default)((0,o.default)({},v.STEP_PREPARE,x),v.STEP_START,O),v.STEP_ACTIVE,_);case v.STATUS_ENTER:return(0,o.default)((0,o.default)((0,o.default)({},v.STEP_PREPARE,S),v.STEP_START,j),v.STEP_ACTIVE,P);case v.STATUS_LEAVE:return(0,o.default)((0,o.default)((0,o.default)({},v.STEP_PREPARE,k),v.STEP_START,T),v.STEP_ACTIVE,I);default:return{}}},eo=d.useMemo(function(){return en(X)},[X]),ea=E(X,!e,function(e){if(e===v.STEP_PREPARE){var t,n=eo[v.STEP_PREPARE];return!!n&&n(r())}return es in eo&&K((null==(t=eo[es])?void 0:t.call(eo,r(),null))||null),es===v.STEP_ACTIVE&&X!==v.STATUS_NONE&&(er(r()),w>0&&(clearTimeout(Y.current),Y.current=setTimeout(function(){ee({deadline:!0})},w))),es===v.STEP_PREPARED&&Z(),!0}),ei=(0,i.default)(ea,2),el=ei[0],es=ei[1];Q.current=$(es);var ec=(0,d.useRef)(null);(0,b.default)(function(){if(!J.current||ec.current!==t){L(t);var r,n=J.current;J.current=!0,!n&&t&&u&&(r=v.STATUS_APPEAR),n&&t&&s&&(r=v.STATUS_ENTER),(n&&!t&&p||!n&&C&&!t&&p)&&(r=v.STATUS_LEAVE);var o=en(r);r&&(e||o[v.STEP_PREPARE])?(W(r),el()):W(v.STATUS_NONE),ec.current=t}},[t]),(0,d.useEffect)(function(){(X!==v.STATUS_APPEAR||u)&&(X!==v.STATUS_ENTER||s)&&(X!==v.STATUS_LEAVE||p)||W(v.STATUS_NONE)},[u,s,p]),(0,d.useEffect)(function(){return function(){J.current=!1,clearTimeout(Y.current)}},[]);var eu=d.useRef(!1);(0,d.useEffect)(function(){z&&(eu.current=!0),void 0!==z&&X===v.STATUS_NONE&&((eu.current||z)&&(null==M||M(z)),eu.current=!0)},[z,X]);var ed=q;return eo[v.STEP_PREPARE]&&es===v.STEP_START&&(ed=(0,a.default)({transition:"none"},ed)),[X,es,ed,null!=z?z:t]}(P,l,function(){try{return I.current instanceof HTMLElement?I.current:(0,c.default)(F.current)}catch(e){return null}},e),R=(0,i.default)(N,4),M=R[0],A=R[1],B=R[2],z=R[3],L=d.useRef(z);z&&(L.current=!0);var H=d.useCallback(function(e){I.current=e,(0,u.fillRef)(t,e)},[t]),D=(0,a.default)((0,a.default)({},T),{},{visible:l});if(S)if(M===v.STATUS_NONE)V=z?S((0,a.default)({},D),H):!C&&L.current&&j?S((0,a.default)((0,a.default)({},D),{},{className:j}),H):!x&&(C||j)?null:S((0,a.default)((0,a.default)({},D),{},{style:{display:"none"}}),H);else{A===v.STEP_PREPARE?W="prepare":$(A)?W="active":A===v.STEP_START&&(W="start");var V,W,U=(0,k.getTransitionName)(O,"".concat(M,"-").concat(W));V=S((0,a.default)((0,a.default)({},D),{},{className:(0,s.default)((0,k.getTransitionName)(O,M),(0,o.default)((0,o.default)({},U,U&&W),O,"string"==typeof O)),style:B}),H)}else V=null;return d.isValidElement(V)&&(0,u.supportRef)(V)&&((0,u.getNodeRef)(V)||(V=d.cloneElement(V,{ref:H}))),d.createElement(p.default,{ref:F},V)})).displayName="CSSMotion",n);var j=e.i(931067),T=e.i(703923),_=e.i(278409),P=e.i(233848),I=e.i(971151),F=e.i(868917),N=e.i(674813),R="keep",M="remove",A="removed";function B(e){var t;return t=e&&"object"===(0,l.default)(e)&&"key"in e?e:{key:e},(0,a.default)((0,a.default)({},t),{},{key:String(t.key)})}function z(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return e.map(B)}var L=["component","children","onVisibleChanged","onAllRemoved"],H=["status"],D=["eventProps","visible","children","motionName","motionAppear","motionEnter","motionLeave","motionLeaveImmediately","motionDeadline","removeOnLeave","leavedClassName","onAppearPrepare","onAppearStart","onAppearActive","onAppearEnd","onEnterStart","onEnterActive","onEnterEnd","onLeaveStart","onLeaveActive","onLeaveEnd"];let V=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:O,r=function(e){(0,F.default)(n,e);var r=(0,N.default)(n);function n(){var e;(0,_.default)(this,n);for(var t=arguments.length,i=Array(t),l=0;l0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],r=[],n=0,o=t.length,i=z(e),l=z(t);i.forEach(function(e){for(var t=!1,i=n;i1}).forEach(function(e){(r=r.filter(function(t){var r=t.key,n=t.status;return r!==e||n!==M})).forEach(function(t){t.key===e&&(t.status=R)})}),r})(n,z(r)).filter(function(e){var t=n.find(function(t){var r=t.key;return e.key===r});return!t||t.status!==A||e.status!==M})}}}]),n}(d.Component);return(0,o.default)(r,"defaultProps",{component:"div"}),r}(k.supportTransition);e.s(["default",0,V],26432),e.s(["default",0,O],361275)},702680,e=>{"use strict";var t=e.i(865623);e.s(["Provider",()=>t.default])},241368,686746,e=>{"use strict";var t=e.i(732961);e.s(["useCacheToken",()=>t.default],241368),e.s(["default",0,"5.29.3"],686746)},719581,745978,628882,e=>{"use strict";var t=e.i(271645);e.i(296059);var r=e.i(241368),n=e.i(686746),o=e.i(310751),a=e.i(320890),i=e.i(170517);e.i(262370);var l=e.i(135551);function s(e){return e>=0&&e<=255}let c=function(e,t){let{r:r,g:n,b:o,a:a}=new l.FastColor(e).toRgb();if(a<1)return e;let{r:i,g:c,b:u}=new l.FastColor(t).toRgb();for(let e=.01;e<=1;e+=.01){let t=Math.round((r-i*(1-e))/e),a=Math.round((n-c*(1-e))/e),d=Math.round((o-u*(1-e))/e);if(s(t)&&s(a)&&s(d))return new l.FastColor({r:t,g:a,b:d,a:Math.round(100*e)/100}).toRgbString()}return new l.FastColor({r:r,g:n,b:o,a:1}).toRgbString()};e.s(["default",0,c],745978);var u=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};function d(e){let{override:t}=e,r=u(e,["override"]),n=Object.assign({},t);Object.keys(i.default).forEach(e=>{delete n[e]});let o=Object.assign(Object.assign({},r),n);return!1===o.motion&&(o.motionDurationFast="0s",o.motionDurationMid="0s",o.motionDurationSlow="0s"),Object.assign(Object.assign(Object.assign({},o),{colorFillContent:o.colorFillSecondary,colorFillContentHover:o.colorFill,colorFillAlter:o.colorFillQuaternary,colorBgContainerDisabled:o.colorFillTertiary,colorBorderBg:o.colorBgContainer,colorSplit:c(o.colorBorderSecondary,o.colorBgContainer),colorTextPlaceholder:o.colorTextQuaternary,colorTextDisabled:o.colorTextQuaternary,colorTextHeading:o.colorText,colorTextLabel:o.colorTextSecondary,colorTextDescription:o.colorTextTertiary,colorTextLightSolid:o.colorWhite,colorHighlight:o.colorError,colorBgTextHover:o.colorFillSecondary,colorBgTextActive:o.colorFill,colorIcon:o.colorTextTertiary,colorIconHover:o.colorText,colorErrorOutline:c(o.colorErrorBg,o.colorBgContainer),colorWarningOutline:c(o.colorWarningBg,o.colorBgContainer),fontSizeIcon:o.fontSizeSM,lineWidthFocus:3*o.lineWidth,lineWidth:o.lineWidth,controlOutlineWidth:2*o.lineWidth,controlInteractiveSize:o.controlHeight/2,controlItemBgHover:o.colorFillTertiary,controlItemBgActive:o.colorPrimaryBg,controlItemBgActiveHover:o.colorPrimaryBgHover,controlItemBgActiveDisabled:o.colorFill,controlTmpOutline:o.colorFillQuaternary,controlOutline:c(o.colorPrimaryBg,o.colorBgContainer),lineType:o.lineType,borderRadius:o.borderRadius,borderRadiusXS:o.borderRadiusXS,borderRadiusSM:o.borderRadiusSM,borderRadiusLG:o.borderRadiusLG,fontWeightStrong:600,opacityLoading:.65,linkDecoration:"none",linkHoverDecoration:"none",linkFocusDecoration:"none",controlPaddingHorizontal:12,controlPaddingHorizontalSM:8,paddingXXS:o.sizeXXS,paddingXS:o.sizeXS,paddingSM:o.sizeSM,padding:o.size,paddingMD:o.sizeMD,paddingLG:o.sizeLG,paddingXL:o.sizeXL,paddingContentHorizontalLG:o.sizeLG,paddingContentVerticalLG:o.sizeMS,paddingContentHorizontal:o.sizeMS,paddingContentVertical:o.sizeSM,paddingContentHorizontalSM:o.size,paddingContentVerticalSM:o.sizeXS,marginXXS:o.sizeXXS,marginXS:o.sizeXS,marginSM:o.sizeSM,margin:o.size,marginMD:o.sizeMD,marginLG:o.sizeLG,marginXL:o.sizeXL,marginXXL:o.sizeXXL,boxShadow:` + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowSecondary:` + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowTertiary:` + 0 1px 2px 0 rgba(0, 0, 0, 0.03), + 0 1px 6px -1px rgba(0, 0, 0, 0.02), + 0 2px 4px 0 rgba(0, 0, 0, 0.02) + `,screenXS:480,screenXSMin:480,screenXSMax:575,screenSM:576,screenSMMin:576,screenSMMax:767,screenMD:768,screenMDMin:768,screenMDMax:991,screenLG:992,screenLGMin:992,screenLGMax:1199,screenXL:1200,screenXLMin:1200,screenXLMax:1599,screenXXL:1600,screenXXLMin:1600,boxShadowPopoverArrow:"2px 2px 5px rgba(0, 0, 0, 0.05)",boxShadowCard:` + 0 1px 2px -2px ${new l.FastColor("rgba(0, 0, 0, 0.16)").toRgbString()}, + 0 3px 6px 0 ${new l.FastColor("rgba(0, 0, 0, 0.12)").toRgbString()}, + 0 5px 12px 4px ${new l.FastColor("rgba(0, 0, 0, 0.09)").toRgbString()} + `,boxShadowDrawerRight:` + -6px 0 16px 0 rgba(0, 0, 0, 0.08), + -3px 0 6px -4px rgba(0, 0, 0, 0.12), + -9px 0 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowDrawerLeft:` + 6px 0 16px 0 rgba(0, 0, 0, 0.08), + 3px 0 6px -4px rgba(0, 0, 0, 0.12), + 9px 0 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowDrawerUp:` + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowDrawerDown:` + 0 -6px 16px 0 rgba(0, 0, 0, 0.08), + 0 -3px 6px -4px rgba(0, 0, 0, 0.12), + 0 -9px 28px 8px rgba(0, 0, 0, 0.05) + `,boxShadowTabsOverflowLeft:"inset 10px 0 8px -8px rgba(0, 0, 0, 0.08)",boxShadowTabsOverflowRight:"inset -10px 0 8px -8px rgba(0, 0, 0, 0.08)",boxShadowTabsOverflowTop:"inset 0 10px 8px -8px rgba(0, 0, 0, 0.08)",boxShadowTabsOverflowBottom:"inset 0 -10px 8px -8px rgba(0, 0, 0, 0.08)"}),n)}e.s(["default",()=>d],628882);var 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 p={lineHeight:!0,lineHeightSM:!0,lineHeightLG:!0,lineHeightHeading1:!0,lineHeightHeading2:!0,lineHeightHeading3:!0,lineHeightHeading4:!0,lineHeightHeading5:!0,opacityLoading:!0,fontWeightStrong:!0,zIndexPopupBase:!0,zIndexBase:!0,opacityImage:!0},m={motionBase:!0,motionUnit:!0},g={screenXS:!0,screenXSMin:!0,screenXSMax:!0,screenSM:!0,screenSMMin:!0,screenSMMax:!0,screenMD:!0,screenMDMin:!0,screenMDMax:!0,screenLG:!0,screenLGMin:!0,screenLGMax:!0,screenXL:!0,screenXLMin:!0,screenXLMax:!0,screenXXL:!0,screenXXLMin:!0},h=(e,t,r)=>{let n=r.getDerivativeToken(e),{override:o}=t,a=f(t,["override"]),i=Object.assign(Object.assign({},n),{override:o});return i=d(i),a&&Object.entries(a).forEach(([e,t])=>{let{theme:r}=t,n=f(t,["theme"]),o=n;r&&(o=h(Object.assign(Object.assign({},i),n),{override:n},r)),i[e]=o}),i};function v(){let{token:e,hashed:l,theme:s,override:c,cssVar:u}=t.default.useContext(a.DesignTokenContext),f=`${n.default}-${l||""}`,v=s||o.defaultTheme,[y,b,w]=(0,r.useCacheToken)(v,[i.default,e],{salt:f,override:c,getComputedToken:h,formatToken:d,cssVar:u&&{prefix:u.prefix,key:u.key,unitless:p,ignore:m,preserve:g}});return[v,w,l?b:"",y,u]}e.s(["default",()=>v,"unitless",0,p],719581)},104458,e=>{"use strict";var t=e.i(719581);e.s(["useToken",()=>t.default])},450522,198652,e=>{"use strict";e.i(247167);var t=e.i(271645);e.i(361275);var r=e.i(702680),n=e.i(104458);let o=t.createContext(!0);function a(e){let a=t.useContext(o),{children:i}=e,[,l]=(0,n.useToken)(),{motion:s}=l,c=t.useRef(!1);return(c.current||(c.current=a!==s),c.current)?t.createElement(o.Provider,{value:s},t.createElement(r.Provider,{motion:s},i)):i}e.s(["default",()=>a],450522),e.i(747656),e.s(["default",0,()=>null],198652)},299615,e=>{"use strict";var t=e.i(952103);e.s(["useStyleRegister",()=>t.default])},183293,e=>{"use strict";e.i(296059);var t=e.i(915654);let r=()=>({display:"inline-flex",alignItems:"center",color:"inherit",fontStyle:"normal",lineHeight:0,textAlign:"center",textTransform:"none",verticalAlign:"-0.125em",textRendering:"optimizeLegibility","-webkit-font-smoothing":"antialiased","-moz-osx-font-smoothing":"grayscale","> *":{lineHeight:1},svg:{display:"inline-block"}}),n=(e,r)=>({outline:`${(0,t.unit)(e.lineWidthFocus)} solid ${e.colorPrimaryBorder}`,outlineOffset:null!=r?r:1,transition:"outline-offset 0s, outline 0s"}),o=(e,t)=>({"&:focus-visible":n(e,t)});e.s(["clearFix",0,()=>({"&::before":{display:"table",content:'""'},"&::after":{display:"table",clear:"both",content:'""'}}),"genCommonStyle",0,(e,t,r,n)=>{let o=`[class^="${t}"], [class*=" ${t}"]`,a=r?`.${r}`:o,i={boxSizing:"border-box","&::before, &::after":{boxSizing:"border-box"}},l={};return!1!==n&&(l={fontFamily:e.fontFamily,fontSize:e.fontSize}),{[a]:Object.assign(Object.assign(Object.assign({},l),i),{[o]:i})}},"genFocusOutline",0,n,"genFocusStyle",0,o,"genIconStyle",0,e=>({[`.${e}`]:Object.assign(Object.assign({},r()),{[`.${e} .${e}-icon`]:{display:"block"}})}),"genLinkStyle",0,e=>({a:{color:e.colorLink,textDecoration:e.linkDecoration,backgroundColor:"transparent",outline:"none",cursor:"pointer",transition:`color ${e.motionDurationSlow}`,"-webkit-text-decoration-skip":"objects","&:hover":{color:e.colorLinkHover},"&:active":{color:e.colorLinkActive},"&:active, &:hover":{textDecoration:e.linkHoverDecoration,outline:0},"&:focus":{textDecoration:e.linkFocusDecoration,outline:0},"&[disabled]":{color:e.colorTextDisabled,cursor:"not-allowed"}}}),"operationUnit",0,e=>Object.assign(Object.assign({color:e.colorLink,textDecoration:e.linkDecoration,outline:"none",cursor:"pointer",transition:`all ${e.motionDurationSlow}`,border:0,padding:0,background:"none",userSelect:"none"},o(e)),{"&:hover":{color:e.colorLinkHover,textDecoration:e.linkHoverDecoration},"&:focus":{color:e.colorLinkHover,textDecoration:e.linkFocusDecoration},"&:active":{color:e.colorLinkActive,textDecoration:e.linkHoverDecoration}}),"resetComponent",0,(e,t=!1)=>({boxSizing:"border-box",margin:0,padding:0,color:e.colorText,fontSize:e.fontSize,lineHeight:e.lineHeight,listStyle:"none",fontFamily:t?"inherit":e.fontFamily}),"resetIcon",0,r,"textEllipsis",0,{overflow:"hidden",whiteSpace:"nowrap",textOverflow:"ellipsis"}])},609587,e=>{"use strict";let t,r,n,o;e.i(247167);var a=e.i(271645);e.i(296059);var i=e.i(868297),l=e.i(790887),s=e.i(327256),c=e.i(182585),u=e.i(349057),d=e.i(747656),f=e.i(819828),p=e.i(289863),m=e.i(595575),g=e.i(87414),h=e.i(310751),v=e.i(320890),y=e.i(170517),b=e.i(242064),w=e.i(328542),C=e.i(937328),x=e.i(80527),S=e.i(308978),$=e.i(450522),E=e.i(198652),k=e.i(666365),O=e.i(299615),j=e.i(183293),T=e.i(719581),_=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 P=["getTargetContainer","getPopupContainer","renderEmpty","input","pagination","form","select","button"];function I(){return t||b.defaultPrefixCls}function F(){return r||b.defaultIconPrefixCls}let N=e=>{let{children:t,csp:r,autoInsertSpaceInButton:n,alert:o,anchor:m,form:w,locale:x,componentSize:I,direction:F,space:N,splitter:R,virtual:M,dropdownMatchSelectWidth:A,popupMatchSelectWidth:B,popupOverflow:z,legacyLocale:L,parentContext:H,iconPrefixCls:D,theme:V,componentDisabled:W,segmented:U,statistic:G,spin:q,calendar:K,carousel:X,cascader:J,collapse:Y,typography:Q,checkbox:Z,descriptions:ee,divider:et,drawer:er,skeleton:en,steps:eo,image:ea,layout:ei,list:el,mentions:es,modal:ec,progress:eu,result:ed,slider:ef,breadcrumb:ep,menu:em,pagination:eg,input:eh,textArea:ev,empty:ey,badge:eb,radio:ew,rate:eC,switch:ex,transfer:eS,avatar:e$,message:eE,tag:ek,table:eO,card:ej,tabs:eT,timeline:e_,timePicker:eP,upload:eI,notification:eF,tree:eN,colorPicker:eR,datePicker:eM,rangePicker:eA,flex:eB,wave:ez,dropdown:eL,warning:eH,tour:eD,tooltip:eV,popover:eW,popconfirm:eU,floatButton:eG,floatButtonGroup:eq,variant:eK,inputNumber:eX,treeSelect:eJ}=e,eY=a.useCallback((t,r)=>{let{prefixCls:n}=e;if(r)return r;let o=n||H.getPrefixCls("");return t?`${o}-${t}`:o},[H.getPrefixCls,e.prefixCls]),eQ=D||H.iconPrefixCls||b.defaultIconPrefixCls,eZ=r||H.csp;((e,t)=>{let[r,n]=(0,T.default)();return(0,O.useStyleRegister)({theme:r,token:n,hashId:"",path:["ant-design-icons",e],nonce:()=>null==t?void 0:t.nonce,layer:{name:"antd"}},()=>(0,j.genIconStyle)(e))})(eQ,eZ);let e0=(0,S.default)(V,H.theme,{prefixCls:eY("")}),e1={csp:eZ,autoInsertSpaceInButton:n,alert:o,anchor:m,locale:x||L,direction:F,space:N,splitter:R,virtual:M,popupMatchSelectWidth:null!=B?B:A,popupOverflow:z,getPrefixCls:eY,iconPrefixCls:eQ,theme:e0,segmented:U,statistic:G,spin:q,calendar:K,carousel:X,cascader:J,collapse:Y,typography:Q,checkbox:Z,descriptions:ee,divider:et,drawer:er,skeleton:en,steps:eo,image:ea,input:eh,textArea:ev,layout:ei,list:el,mentions:es,modal:ec,progress:eu,result:ed,slider:ef,breadcrumb:ep,menu:em,pagination:eg,empty:ey,badge:eb,radio:ew,rate:eC,switch:ex,transfer:eS,avatar:e$,message:eE,tag:ek,table:eO,card:ej,tabs:eT,timeline:e_,timePicker:eP,upload:eI,notification:eF,tree:eN,colorPicker:eR,datePicker:eM,rangePicker:eA,flex:eB,wave:ez,dropdown:eL,warning:eH,tour:eD,tooltip:eV,popover:eW,popconfirm:eU,floatButton:eG,floatButtonGroup:eq,variant:eK,inputNumber:eX,treeSelect:eJ},e2=Object.assign({},H);Object.keys(e1).forEach(e=>{void 0!==e1[e]&&(e2[e]=e1[e])}),P.forEach(t=>{let r=e[t];r&&(e2[t]=r)}),void 0!==n&&(e2.button=Object.assign({autoInsertSpace:n},e2.button));let e4=(0,c.default)(()=>e2,e2,(e,t)=>{let r=Object.keys(e),n=Object.keys(t);return r.length!==n.length||r.some(r=>e[r]!==t[r])}),{layer:e6}=a.useContext(l.StyleContext),e5=a.useMemo(()=>({prefixCls:eQ,csp:eZ,layer:e6?"antd":void 0}),[eQ,eZ,e6]),e3=a.createElement(a.Fragment,null,a.createElement(E.default,{dropdownMatchSelectWidth:A}),t),e7=a.useMemo(()=>{var e,t,r,n;return(0,u.merge)((null==(e=g.default.Form)?void 0:e.defaultValidateMessages)||{},(null==(r=null==(t=e4.locale)?void 0:t.Form)?void 0:r.defaultValidateMessages)||{},(null==(n=e4.form)?void 0:n.validateMessages)||{},(null==w?void 0:w.validateMessages)||{})},[e4,null==w?void 0:w.validateMessages]);Object.keys(e7).length>0&&(e3=a.createElement(f.default.Provider,{value:e7},e3)),x&&(e3=a.createElement(p.default,{locale:x,_ANT_MARK__:p.ANT_MARK},e3)),(eQ||eZ)&&(e3=a.createElement(s.default.Provider,{value:e5},e3)),I&&(e3=a.createElement(k.SizeContextProvider,{size:I},e3)),e3=a.createElement($.default,null,e3);let e8=a.useMemo(()=>{let e=e0||{},{algorithm:t,token:r,components:n,cssVar:o}=e,a=_(e,["algorithm","token","components","cssVar"]),l=t&&(!Array.isArray(t)||t.length>0)?(0,i.createTheme)(t):h.defaultTheme,s={};Object.entries(n||{}).forEach(([e,t])=>{let r=Object.assign({},t);"algorithm"in r&&(!0===r.algorithm?r.theme=l:(Array.isArray(r.algorithm)||"function"==typeof r.algorithm)&&(r.theme=(0,i.createTheme)(r.algorithm)),delete r.algorithm),s[e]=r});let c=Object.assign(Object.assign({},y.default),r);return Object.assign(Object.assign({},a),{theme:l,token:c,components:s,override:Object.assign({override:c},s),cssVar:o})},[e0]);return V&&(e3=a.createElement(v.DesignTokenContext.Provider,{value:e8},e3)),e4.warning&&(e3=a.createElement(d.WarningContext.Provider,{value:e4.warning},e3)),void 0!==W&&(e3=a.createElement(C.DisabledContextProvider,{disabled:W},e3)),a.createElement(b.ConfigContext.Provider,{value:e4},e3)},R=e=>{let t=a.useContext(b.ConfigContext),r=a.useContext(m.default);return a.createElement(N,Object.assign({parentContext:t,legacyLocale:r},e))};R.ConfigContext=b.ConfigContext,R.SizeContext=k.default,R.config=e=>{let{prefixCls:a,iconPrefixCls:i,theme:l,holderRender:s}=e;void 0!==a&&(t=a),void 0!==i&&(r=i),"holderRender"in e&&(o=s),l&&(Object.keys(l).some(e=>e.endsWith("Color"))?(0,w.registerTheme)(I(),l):n=l)},R.useConfig=x.default,Object.defineProperty(R,"SizeContext",{get:()=>k.default}),e.s(["default",0,R,"globalConfig",0,()=>({getPrefixCls:(e,t)=>t||(e?`${I()}-${e}`:I()),getIconPrefixCls:F,getRootPrefixCls:()=>t||I(),getTheme:()=>n,holderRender:o})],609587)},514117,315906,446388,547044,415271,588852,e=>{"use strict";function t(e,t){this.v=e,this.k=t}function r(e,t,n,o){var a=Object.defineProperty;try{a({},"",{})}catch(e){a=0}(r=function(e,t,n,o){function i(t,n){r(e,t,function(e){return this._invoke(t,n,e)})}t?a?a(e,t,{value:n,enumerable:!o,configurable:!o,writable:!o}):e[t]=n:(i("next",0),i("throw",1),i("return",2))})(e,t,n,o)}function n(){var e,t,o="function"==typeof Symbol?Symbol:{},a=o.iterator||"@@iterator",i=o.toStringTag||"@@toStringTag";function l(n,o,a,i){var l=Object.create((o&&o.prototype instanceof c?o:c).prototype);return r(l,"_invoke",function(r,n,o){var a,i,l,c=0,u=o||[],d=!1,f={p:0,n:0,v:e,a:p,f:p.bind(e,4),d:function(t,r){return a=t,i=0,l=e,f.n=r,s}};function p(r,n){for(i=r,l=n,t=0;!d&&c&&!o&&t3?(o=m===n)&&(l=a[(i=a[4])?5:(i=3,3)],a[4]=a[5]=e):a[0]<=p&&((o=r<2&&pn||n>m)&&(a[4]=r,a[5]=n,f.n=m,i=0))}if(o||r>1)return s;throw d=!0,n}return function(o,u,m){if(c>1)throw TypeError("Generator is already running");for(d&&1===u&&p(u,m),i=u,l=m;(t=i<2?e:l)||!d;){a||(i?i<3?(i>1&&(f.n=-1),p(i,l)):f.n=l:f.v=l);try{if(c=2,a){if(i||(o="next"),t=a[o]){if(!(t=t.call(a,l)))throw TypeError("iterator result is not an object");if(!t.done)return t;l=t.value,i<2&&(i=0)}else 1===i&&(t=a.return)&&t.call(a),i<2&&(l=TypeError("The iterator does not provide a '"+o+"' method"),i=1);a=e}else if((t=(d=f.n<0)?l:r.call(n,f))!==s)break}catch(t){a=e,i=1,l=t}finally{c=1}}return{value:t,done:d}}}(n,a,i),!0),l}var s={};function c(){}function u(){}function d(){}t=Object.getPrototypeOf;var f=d.prototype=c.prototype=Object.create([][a]?t(t([][a]())):(r(t={},a,function(){return this}),t));function p(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,d):(e.__proto__=d,r(e,i,"GeneratorFunction")),e.prototype=Object.create(f),e}return u.prototype=d,r(f,"constructor",d),r(d,"constructor",u),u.displayName="GeneratorFunction",r(d,i,"GeneratorFunction"),r(f),r(f,i,"Generator"),r(f,a,function(){return this}),r(f,"toString",function(){return"[object Generator]"}),(n=function(){return{w:l,m:p}})()}function o(e,n){var a;this.next||(r(o.prototype),r(o.prototype,"function"==typeof Symbol&&Symbol.asyncIterator||"@asyncIterator",function(){return this})),r(this,"_invoke",function(r,o,i){function l(){return new n(function(o,a){!function r(o,a,i,l){try{var s=e[o](a),c=s.value;return c instanceof t?n.resolve(c.v).then(function(e){r("next",e,i,l)},function(e){r("throw",e,i,l)}):n.resolve(c).then(function(e){s.value=e,i(s)},function(e){return r("throw",e,i,l)})}catch(e){l(e)}}(r,i,o,a)})}return a=a?a.then(l,l):l()},!0)}function a(e,t,r,a,i){return new o(n().w(e,t,r,a),i||Promise)}function i(e,t,r,n,o){var i=a(e,t,r,n,o);return i.next().then(function(e){return e.done?e.value:i.next()})}function l(e){var t=Object(e),r=[];for(var n in t)r.unshift(n);return function e(){for(;r.length;)if((n=r.pop())in t)return e.value=n,e.done=!1,e;return e.done=!0,e}}e.s(["default",()=>t],514117),e.s(["default",()=>n],315906),e.s(["default",()=>o],446388),e.s(["default",()=>a],547044),e.s(["default",()=>i],415271),e.s(["default",()=>l],588852)},31575,33968,e=>{"use strict";var t=e.i(514117),r=e.i(315906),n=e.i(415271),o=e.i(547044),a=e.i(446388),i=e.i(588852),l=e.i(410160);function s(e){if(null!=e){var t=e["function"==typeof Symbol&&Symbol.iterator||"@@iterator"],r=0;if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length))return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}}}throw TypeError((0,l.default)(e)+" is not iterable")}function c(){var e=(0,r.default)(),l=e.m(c),u=(Object.getPrototypeOf?Object.getPrototypeOf(l):l.__proto__).constructor;function d(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===u||"GeneratorFunction"===(t.displayName||t.name))}var f={throw:1,return:2,break:3,continue:3};function p(e){var t,r;return function(n){t||(t={stop:function(){return r(n.a,2)},catch:function(){return n.v},abrupt:function(e,t){return r(n.a,f[e],t)},delegateYield:function(e,o,a){return t.resultName=o,r(n.d,s(e),a)},finish:function(e){return r(n.f,e)}},r=function(e,r,o){n.p=t.prev,n.n=t.next;try{return e(r,o)}finally{t.next=n.n}}),t.resultName&&(t[t.resultName]=n.v,t.resultName=void 0),t.sent=n.v,t.next=n.n;try{return e.call(this,t)}finally{n.p=t.prev,n.n=t.next}}}return(c=function(){return{wrap:function(t,r,n,o){return e.w(p(t),r,n,o&&o.reverse())},isGeneratorFunction:d,mark:e.m,awrap:function(e,r){return new t.default(e,r)},AsyncIterator:a.default,async:function(e,t,r,a,i){return(d(t)?o.default:n.default)(p(e),t,r,a,i)},keys:i.default,values:s}})()}function u(e,t,r,n,o,a,i){try{var l=e[a](i),s=l.value}catch(e){return void r(e)}l.done?t(s):Promise.resolve(s).then(n,o)}function d(e){return function(){var t=this,r=arguments;return new Promise(function(n,o){var a=e.apply(t,r);function i(e){u(a,n,o,i,l,"next",e)}function l(e){u(a,n,o,i,l,"throw",e)}i(void 0)})}}e.s(["default",()=>c],31575),e.s(["default",()=>d],33968)},783164,e=>{"use strict";e.i(247167),e.i(271645);var t,r=e.i(174080),n=e.i(31575),o=e.i(33968),a=e.i(410160),i=(0,e.i(209428).default)({},r),l=i.version,s=i.render,c=i.unmountComponentAtNode;try{Number((l||"").split(".")[0])>=18&&(t=i.createRoot)}catch(e){}function u(e){var t=i.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;t&&"object"===(0,a.default)(t)&&(t.usingClientEntryPoint=e)}var d="__rc_react_root__";function f(){return(f=(0,o.default)((0,n.default)().mark(function e(t){return(0,n.default)().wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",Promise.resolve().then(function(){var e;null==(e=t[d])||e.unmount(),delete t[d]}));case 1:case"end":return e.stop()}},e)}))).apply(this,arguments)}function p(){return(p=(0,o.default)((0,n.default)().mark(function e(r){return(0,n.default)().wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(void 0===t){e.next=2;break}return e.abrupt("return",function(e){return f.apply(this,arguments)}(r));case 2:c(r);case 3:case"end":return e.stop()}},e)}))).apply(this,arguments)}let m=(e,r)=>(!function(e,r){var n;if(t)return u(!0),n=r[d]||t(r),u(!1),n.render(e),r[d]=n;null==s||s(e,r)}(e,r),()=>(function(e){return p.apply(this,arguments)})(r));function g(e){return e&&(m=e),m}e.s(["unstableSetRender",()=>g],783164)},693238,e=>{"use strict";e.s(["default",0,{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 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"}}]},name:"check-circle",theme:"filled"}])},909887,e=>{"use strict";function t(e){var t;return null==e||null==(t=e.getRootNode)?void 0:t.call(e)}function r(e){return t(e)instanceof ShadowRoot?t(e):null}e.s(["getShadowRoot",()=>r])},9583,e=>{"use strict";var t=e.i(931067),r=e.i(392221),n=e.i(211577),o=e.i(703923),a=e.i(271645),i=e.i(343794);e.i(765846);var l=e.i(896091),s=e.i(327256),c=e.i(209428),u=e.i(410160),d=e.i(602716),f=e.i(575943),p=e.i(909887),m=e.i(883110);function g(e){return"object"===(0,u.default)(e)&&"string"==typeof e.name&&"string"==typeof e.theme&&("object"===(0,u.default)(e.icon)||"function"==typeof e.icon)}function h(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return Object.keys(e).reduce(function(t,r){var n=e[r];return"class"===r?(t.className=n,delete t.class):(delete t[r],t[r.replace(/-(.)/g,function(e,t){return t.toUpperCase()})]=n),t},{})}function v(e){return(0,d.generate)(e)[0]}function y(e){return e?Array.isArray(e)?e:[e]:[]}var b=function(e){var t=(0,a.useContext)(s.default),r=t.csp,n=t.prefixCls,o=t.layer,i="\n.anticon {\n display: inline-flex;\n align-items: center;\n color: inherit;\n font-style: normal;\n line-height: 0;\n text-align: center;\n text-transform: none;\n vertical-align: -0.125em;\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n.anticon > * {\n line-height: 1;\n}\n\n.anticon svg {\n display: inline-block;\n}\n\n.anticon::before {\n display: none;\n}\n\n.anticon .anticon-icon {\n display: block;\n}\n\n.anticon[tabindex] {\n cursor: pointer;\n}\n\n.anticon-spin::before,\n.anticon-spin {\n display: inline-block;\n -webkit-animation: loadingCircle 1s infinite linear;\n animation: loadingCircle 1s infinite linear;\n}\n\n@-webkit-keyframes loadingCircle {\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n\n@keyframes loadingCircle {\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n";n&&(i=i.replace(/anticon/g,n)),o&&(i="@layer ".concat(o," {\n").concat(i,"\n}")),(0,a.useEffect)(function(){var t=e.current,n=(0,p.getShadowRoot)(t);(0,f.updateCSS)(i,"@ant-design-icons",{prepend:!o,csp:r,attachTo:n})},[])},w=["icon","className","onClick","style","primaryColor","secondaryColor"],C={primaryColor:"#333",secondaryColor:"#E6E6E6",calculated:!1},x=function(e){var t,r,n=e.icon,i=e.className,l=e.onClick,s=e.style,u=e.primaryColor,d=e.secondaryColor,f=(0,o.default)(e,w),p=a.useRef(),y=C;if(u&&(y={primaryColor:u,secondaryColor:d||v(u)}),b(p),t=g(n),r="icon should be icon definiton, but got ".concat(n),(0,m.default)(t,"[@ant-design/icons] ".concat(r)),!g(n))return null;var x=n;return x&&"function"==typeof x.icon&&(x=(0,c.default)((0,c.default)({},x),{},{icon:x.icon(y.primaryColor,y.secondaryColor)})),function e(t,r,n){return n?a.default.createElement(t.tag,(0,c.default)((0,c.default)({key:r},h(t.attrs)),n),(t.children||[]).map(function(n,o){return e(n,"".concat(r,"-").concat(t.tag,"-").concat(o))})):a.default.createElement(t.tag,(0,c.default)({key:r},h(t.attrs)),(t.children||[]).map(function(n,o){return e(n,"".concat(r,"-").concat(t.tag,"-").concat(o))}))}(x.icon,"svg-".concat(x.name),(0,c.default)((0,c.default)({className:i,onClick:l,style:s,"data-icon":x.name,width:"1em",height:"1em",fill:"currentColor","aria-hidden":"true"},f),{},{ref:p}))};function S(e){var t=y(e),n=(0,r.default)(t,2),o=n[0],a=n[1];return x.setTwoToneColors({primaryColor:o,secondaryColor:a})}x.displayName="IconReact",x.getTwoToneColors=function(){return(0,c.default)({},C)},x.setTwoToneColors=function(e){var t=e.primaryColor,r=e.secondaryColor;C.primaryColor=t,C.secondaryColor=r||v(t),C.calculated=!!r};var $=["className","icon","spin","rotate","tabIndex","onClick","twoToneColor"];S(l.blue.primary);var E=a.forwardRef(function(e,l){var c=e.className,u=e.icon,d=e.spin,f=e.rotate,p=e.tabIndex,m=e.onClick,g=e.twoToneColor,h=(0,o.default)(e,$),v=a.useContext(s.default),b=v.prefixCls,w=void 0===b?"anticon":b,C=v.rootClassName,S=(0,i.default)(C,w,(0,n.default)((0,n.default)({},"".concat(w,"-").concat(u.name),!!u.name),"".concat(w,"-spin"),!!d||"loading"===u.name),c),E=p;void 0===E&&m&&(E=-1);var k=y(g),O=(0,r.default)(k,2),j=O[0],T=O[1];return a.createElement("span",(0,t.default)({role:"img","aria-label":u.name},h,{ref:l,tabIndex:E,onClick:m,className:S}),a.createElement(x,{icon:u,primaryColor:j,secondaryColor:T,style:f?{msTransform:"rotate(".concat(f,"deg)"),transform:"rotate(".concat(f,"deg)")}:void 0}))});E.displayName="AntdIcon",E.getTwoToneColor=function(){var e=x.getTwoToneColors();return e.calculated?[e.primaryColor,e.secondaryColor]:e.primaryColor},E.setTwoToneColor=S,e.s(["default",0,E],9583)},201072,e=>{"use strict";var t=e.i(931067),r=e.i(271645),n=e.i(693238),o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n.default}))});e.s(["default",0,a])},726289,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={icon:{tag:"svg",attrs:{"fill-rule":"evenodd",viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm127.98 274.82h-.04l-.08.06L512 466.75 384.14 338.88c-.04-.05-.06-.06-.08-.06a.12.12 0 00-.07 0c-.03 0-.05.01-.09.05l-45.02 45.02a.2.2 0 00-.05.09.12.12 0 000 .07v.02a.27.27 0 00.06.06L466.75 512 338.88 639.86c-.05.04-.06.06-.06.08a.12.12 0 000 .07c0 .03.01.05.05.09l45.02 45.02a.2.2 0 00.09.05.12.12 0 00.07 0c.02 0 .04-.01.08-.05L512 557.25l127.86 127.87c.04.04.06.05.08.05a.12.12 0 00.07 0c.03 0 .05-.01.09-.05l45.02-45.02a.2.2 0 00.05-.09.12.12 0 000-.07v-.02a.27.27 0 00-.05-.06L557.25 512l127.87-127.86c.04-.04.05-.06.05-.08a.12.12 0 000-.07c0-.03-.01-.05-.05-.09l-45.02-45.02a.2.2 0 00-.09-.05.12.12 0 00-.07 0z"}}]},name:"close-circle",theme:"filled"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],726289)},445898,e=>{"use strict";e.s(["default",0,{icon:{tag:"svg",attrs:{"fill-rule":"evenodd",viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"}}]},name:"close",theme:"outlined"}])},864517,e=>{"use strict";var t=e.i(931067),r=e.i(271645),n=e.i(445898),o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n.default}))});e.s(["default",0,a])},562901,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={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 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"}}]},name:"exclamation-circle",theme:"filled"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],562901)},779573,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={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 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"}}]},name:"info-circle",theme:"filled"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],779573)},882345,e=>{"use strict";e.s(["default",0,{icon:{tag:"svg",attrs:{viewBox:"0 0 1024 1024",focusable:"false"},children:[{tag:"path",attrs:{d:"M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"}}]},name:"loading",theme:"outlined"}])},739295,e=>{"use strict";var t=e.i(931067),r=e.i(271645),n=e.i(882345),o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n.default}))});e.s(["default",0,a])},629587,e=>{"use strict";var t=e.i(26432);e.s(["CSSMotionList",()=>t.default])},404948,e=>{"use strict";var t={MAC_ENTER:3,BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,QUESTION_MARK:63,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,META:91,WIN_KEY_RIGHT:92,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,NUMLOCK:144,SEMICOLON:186,DASH:189,EQUALS:187,COMMA:188,PERIOD:190,SLASH:191,APOSTROPHE:192,SINGLE_QUOTE:222,OPEN_SQUARE_BRACKET:219,BACKSLASH:220,CLOSE_SQUARE_BRACKET:221,WIN_KEY:224,MAC_FF_META:224,WIN_IME:229,isTextModifyingKeyEvent:function(e){var r=e.keyCode;if(e.altKey&&!e.ctrlKey||e.metaKey||r>=t.F1&&r<=t.F12)return!1;switch(r){case t.ALT:case t.CAPS_LOCK:case t.CONTEXT_MENU:case t.CTRL:case t.DOWN:case t.END:case t.ESC:case t.HOME:case t.INSERT:case t.LEFT:case t.MAC_FF_META:case t.META:case t.NUMLOCK:case t.NUM_CENTER:case t.PAGE_DOWN:case t.PAGE_UP:case t.PAUSE:case t.PRINT_SCREEN:case t.RIGHT:case t.SHIFT:case t.UP:case t.WIN_KEY:case t.WIN_KEY_RIGHT:return!1;default:return!0}},isCharacterKey:function(e){if(e>=t.ZERO&&e<=t.NINE||e>=t.NUM_ZERO&&e<=t.NUM_MULTIPLY||e>=t.A&&e<=t.Z||-1!==window.navigator.userAgent.indexOf("WebKit")&&0===e)return!0;switch(e){case t.SPACE:case t.QUESTION_MARK:case t.NUM_PLUS:case t.NUM_MINUS:case t.NUM_PERIOD:case t.NUM_DIVISION:case t.SEMICOLON:case t.DASH:case t.EQUALS:case t.COMMA:case t.PERIOD:case t.SLASH:case t.APOSTROPHE:case t.SINGLE_QUOTE:case t.OPEN_SQUARE_BRACKET:case t.BACKSLASH:case t.CLOSE_SQUARE_BRACKET:return!0;default:return!1}}};e.s(["default",0,t])},244009,e=>{"use strict";var t=e.i(209428),r="".concat("accept acceptCharset accessKey action allowFullScreen allowTransparency\n alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge\n charSet checked classID className colSpan cols content contentEditable contextMenu\n controls coords crossOrigin data dateTime default defer dir disabled download draggable\n encType form formAction formEncType formMethod formNoValidate formTarget frameBorder\n headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity\n is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media\n mediaGroup method min minLength multiple muted name noValidate nonce open\n optimum pattern placeholder poster preload radioGroup readOnly rel required\n reversed role rowSpan rows sandbox scope scoped scrolling seamless selected\n shape size sizes span spellCheck src srcDoc srcLang srcSet start step style\n summary tabIndex target title type useMap value width wmode wrap"," ").concat("onCopy onCut onPaste onCompositionEnd onCompositionStart onCompositionUpdate onKeyDown\n onKeyPress onKeyUp onFocus onBlur onChange onInput onSubmit onClick onContextMenu onDoubleClick\n onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown\n onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel\n onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough\n onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata\n onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError").split(/[\s\n]+/);function n(e,t){return 0===e.indexOf(t)}function o(e){var o,a=arguments.length>1&&void 0!==arguments[1]&&arguments[1];o=!1===a?{aria:!0,data:!0,attr:!0}:!0===a?{aria:!0}:(0,t.default)({},a);var i={};return Object.keys(e).forEach(function(t){(o.aria&&("role"===t||n(t,"aria-"))||o.data&&n(t,"data-")||o.attr&&r.includes(t))&&(i[t]=e[t])}),i}e.s(["default",()=>o])},792131,198197,404556,10183,e=>{"use strict";var t=e.i(8211),r=e.i(392221),n=e.i(703923),o=e.i(271645);e.i(247167);var a=e.i(209428),i=e.i(174080),l=e.i(931067),s=e.i(211577),c=e.i(343794);e.i(361275);var u=e.i(629587),d=e.i(410160),f=e.i(404948),p=e.i(244009),m=o.forwardRef(function(e,t){var n=e.prefixCls,a=e.style,i=e.className,u=e.duration,m=void 0===u?4.5:u,g=e.showProgress,h=e.pauseOnHover,v=void 0===h||h,y=e.eventKey,b=e.content,w=e.closable,C=e.closeIcon,x=void 0===C?"x":C,S=e.props,$=e.onClick,E=e.onNoticeClose,k=e.times,O=e.hovering,j=o.useState(!1),T=(0,r.default)(j,2),_=T[0],P=T[1],I=o.useState(0),F=(0,r.default)(I,2),N=F[0],R=F[1],M=o.useState(0),A=(0,r.default)(M,2),B=A[0],z=A[1],L=O||_,H=m>0&&g,D=function(){E(y)};o.useEffect(function(){if(!L&&m>0){var e=Date.now()-B,t=setTimeout(function(){D()},1e3*m-B);return function(){v&&clearTimeout(t),z(Date.now()-e)}}},[m,L,k]),o.useEffect(function(){if(!L&&H&&(v||0===B)){var e,t=performance.now();return!function r(){cancelAnimationFrame(e),e=requestAnimationFrame(function(e){var n=Math.min((e+B-t)/(1e3*m),1);R(100*n),n<1&&r()})}(),function(){v&&cancelAnimationFrame(e)}}},[m,B,L,H,k]);var V=o.useMemo(function(){return"object"===(0,d.default)(w)&&null!==w?w:w?{closeIcon:x}:{}},[w,x]),W=(0,p.default)(V,!0),U=100-(!N||N<0?0:N>100?100:N),G="".concat(n,"-notice");return o.createElement("div",(0,l.default)({},S,{ref:t,className:(0,c.default)(G,i,(0,s.default)({},"".concat(G,"-closable"),w)),style:a,onMouseEnter:function(e){var t;P(!0),null==S||null==(t=S.onMouseEnter)||t.call(S,e)},onMouseLeave:function(e){var t;P(!1),null==S||null==(t=S.onMouseLeave)||t.call(S,e)},onClick:$}),o.createElement("div",{className:"".concat(G,"-content")},b),w&&o.createElement("a",(0,l.default)({tabIndex:0,className:"".concat(G,"-close"),onKeyDown:function(e){("Enter"===e.key||"Enter"===e.code||e.keyCode===f.default.ENTER)&&D()},"aria-label":"Close"},W,{onClick:function(e){e.preventDefault(),e.stopPropagation(),D()}}),V.closeIcon),H&&o.createElement("progress",{className:"".concat(G,"-progress"),max:"100",value:U},U+"%"))}),g=o.default.createContext({});e.s(["NotificationContext",()=>g,"default",0,function(e){var t=e.children,r=e.classNames;return o.default.createElement(g.Provider,{value:{classNames:r}},t)}],198197);let h=function(e){var t,r,n,o={offset:8,threshold:3,gap:16};return e&&"object"===(0,d.default)(e)&&(o.offset=null!=(t=e.offset)?t:8,o.threshold=null!=(r=e.threshold)?r:3,o.gap=null!=(n=e.gap)?n:16),[!!e,o]};var v=["className","style","classNames","styles"];let y=function(e){var i=e.configList,d=e.placement,f=e.prefixCls,p=e.className,y=e.style,b=e.motion,w=e.onAllNoticeRemoved,C=e.onNoticeClose,x=e.stack,S=(0,o.useContext)(g).classNames,$=(0,o.useRef)({}),E=(0,o.useState)(null),k=(0,r.default)(E,2),O=k[0],j=k[1],T=(0,o.useState)([]),_=(0,r.default)(T,2),P=_[0],I=_[1],F=i.map(function(e){return{config:e,key:String(e.key)}}),N=h(x),R=(0,r.default)(N,2),M=R[0],A=R[1],B=A.offset,z=A.threshold,L=A.gap,H=M&&(P.length>0||F.length<=z),D="function"==typeof b?b(d):b;return(0,o.useEffect)(function(){M&&P.length>1&&I(function(e){return e.filter(function(e){return F.some(function(t){return e===t.key})})})},[P,F,M]),(0,o.useEffect)(function(){var e,t;M&&$.current[null==(e=F[F.length-1])?void 0:e.key]&&j($.current[null==(t=F[F.length-1])?void 0:t.key])},[F,M]),o.default.createElement(u.CSSMotionList,(0,l.default)({key:d,className:(0,c.default)(f,"".concat(f,"-").concat(d),null==S?void 0:S.list,p,(0,s.default)((0,s.default)({},"".concat(f,"-stack"),!!M),"".concat(f,"-stack-expanded"),H)),style:y,keys:F,motionAppear:!0},D,{onAllRemoved:function(){w(d)}}),function(e,r){var i=e.config,s=e.className,u=e.style,p=e.index,g=i.key,h=i.times,y=String(g),b=i.className,w=i.style,x=i.classNames,E=i.styles,k=(0,n.default)(i,v),j=F.findIndex(function(e){return e.key===y}),T={};if(M){var _=F.length-1-(j>-1?j:p-1),N="top"===d||"bottom"===d?"-50%":"0";if(_>0){T.height=H?null==(R=$.current[y])?void 0:R.offsetHeight:null==O?void 0:O.offsetHeight;for(var R,A,z,D,V=0,W=0;W<_;W++)V+=(null==(D=$.current[F[F.length-1-W].key])?void 0:D.offsetHeight)+L;var U=(H?V:_*B)*(d.startsWith("top")?1:-1),G=!H&&null!=O&&O.offsetWidth&&null!=(A=$.current[y])&&A.offsetWidth?((null==O?void 0:O.offsetWidth)-2*B*(_<3?_:3))/(null==(z=$.current[y])?void 0:z.offsetWidth):1;T.transform="translate3d(".concat(N,", ").concat(U,"px, 0) scaleX(").concat(G,")")}else T.transform="translate3d(".concat(N,", 0, 0)")}return o.default.createElement("div",{ref:r,className:(0,c.default)("".concat(f,"-notice-wrapper"),s,null==x?void 0:x.wrapper),style:(0,a.default)((0,a.default)((0,a.default)({},u),T),null==E?void 0:E.wrapper),onMouseEnter:function(){return I(function(e){return e.includes(y)?e:[].concat((0,t.default)(e),[y])})},onMouseLeave:function(){return I(function(e){return e.filter(function(e){return e!==y})})}},o.default.createElement(m,(0,l.default)({},k,{ref:function(e){j>-1?$.current[y]=e:delete $.current[y]},prefixCls:f,classNames:x,styles:E,className:(0,c.default)(b,null==S?void 0:S.notice),style:w,times:h,key:g,eventKey:g,onNoticeClose:C,hovering:M&&P.length>0})))})};var b=o.forwardRef(function(e,n){var l=e.prefixCls,s=void 0===l?"rc-notification":l,c=e.container,u=e.motion,d=e.maxCount,f=e.className,p=e.style,m=e.onAllRemoved,g=e.stack,h=e.renderNotifications,v=o.useState([]),b=(0,r.default)(v,2),w=b[0],C=b[1],x=function(e){var t,r=w.find(function(t){return t.key===e});null==r||null==(t=r.onClose)||t.call(r),C(function(t){return t.filter(function(t){return t.key!==e})})};o.useImperativeHandle(n,function(){return{open:function(e){C(function(r){var n,o=(0,t.default)(r),i=o.findIndex(function(t){return t.key===e.key}),l=(0,a.default)({},e);return i>=0?(l.times=((null==(n=r[i])?void 0:n.times)||0)+1,o[i]=l):(l.times=0,o.push(l)),d>0&&o.length>d&&(o=o.slice(-d)),o})},close:function(e){x(e)},destroy:function(){C([])}}});var S=o.useState({}),$=(0,r.default)(S,2),E=$[0],k=$[1];o.useEffect(function(){var e={};w.forEach(function(t){var r=t.placement,n=void 0===r?"topRight":r;n&&(e[n]=e[n]||[],e[n].push(t))}),Object.keys(E).forEach(function(t){e[t]=e[t]||[]}),k(e)},[w]);var O=function(e){k(function(t){var r=(0,a.default)({},t);return(r[e]||[]).length||delete r[e],r})},j=o.useRef(!1);if(o.useEffect(function(){Object.keys(E).length>0?j.current=!0:j.current&&(null==m||m(),j.current=!1)},[E]),!c)return null;var T=Object.keys(E);return(0,i.createPortal)(o.createElement(o.Fragment,null,T.map(function(e){var t=E[e],r=o.createElement(y,{key:e,configList:t,placement:e,prefixCls:s,className:null==f?void 0:f(e),style:null==p?void 0:p(e),motion:u,onNoticeClose:x,onAllNoticeRemoved:O,stack:g});return h?h(r,{prefixCls:s,key:e}):r})),c)});e.i(62664);var w=e.i(697539),C=["getContainer","motion","prefixCls","maxCount","className","style","onAllRemoved","stack","renderNotifications"],x=function(){return document.body},S=0;function $(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},a=e.getContainer,i=void 0===a?x:a,l=e.motion,s=e.prefixCls,c=e.maxCount,u=e.className,d=e.style,f=e.onAllRemoved,p=e.stack,m=e.renderNotifications,g=(0,n.default)(e,C),h=o.useState(),v=(0,r.default)(h,2),y=v[0],$=v[1],E=o.useRef(),k=o.createElement(b,{container:y,ref:E,prefixCls:s,motion:l,maxCount:c,className:u,style:d,onAllRemoved:f,stack:p,renderNotifications:m}),O=o.useState([]),j=(0,r.default)(O,2),T=j[0],_=j[1],P=(0,w.useEvent)(function(e){var r=function(){for(var e={},t=arguments.length,r=Array(t),n=0;n$],404556),e.s([],792131),e.s(["Notice",0,m],10183)},321883,e=>{"use strict";var t=e.i(104458);e.s(["default",0,e=>{let[,,,,r]=(0,t.useToken)();return r?`${e}-css-var`:""}])},694758,e=>{"use strict";var t=e.i(717813);e.s(["Keyframes",()=>t.default])},122767,340010,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(719581);let n=t.default.createContext(void 0);e.s(["default",0,n],340010);let o={Modal:100,Drawer:100,Popover:100,Popconfirm:100,Tooltip:100,Tour:100,FloatButton:100},a={SelectLike:50,Dropdown:50,DatePicker:50,Menu:50,ImagePreview:1};e.s(["CONTAINER_MAX_OFFSET",0,1e3,"useZIndex",0,(e,i)=>{let l,[,s]=(0,r.default)(),c=t.default.useContext(n),u=e in o;if(void 0!==i)l=[i,i];else{let t=null!=c?c:0;u?t+=(c?0:s.zIndexPopupBase)+o[e]:t+=a[e],l=[void 0===c?i:t,t]}return l}],122767)},869153,e=>{"use strict";var t=e.i(512150);e.s(["useCSSVarRegister",()=>t.default])},559069,196607,e=>{"use strict";var t=e.i(410160),r=e.i(278409),n=e.i(233848),o=e.i(971151),a=e.i(868917),i=e.i(674813),l=e.i(211577),s=(0,n.default)(function e(){(0,r.default)(this,e)}),c="CALC_UNIT",u=RegExp(c,"g");function d(e){return"number"==typeof e?"".concat(e).concat(c):e}var f=function(e){(0,a.default)(c,e);var s=(0,i.default)(c);function c(e,n){(0,r.default)(this,c),a=s.call(this),(0,l.default)((0,o.default)(a),"result",""),(0,l.default)((0,o.default)(a),"unitlessCssVar",void 0),(0,l.default)((0,o.default)(a),"lowPriority",void 0);var a,i=(0,t.default)(e);return a.unitlessCssVar=n,e instanceof c?a.result="(".concat(e.result,")"):"number"===i?a.result=d(e):"string"===i&&(a.result=e),a}return(0,n.default)(c,[{key:"add",value:function(e){return e instanceof c?this.result="".concat(this.result," + ").concat(e.getResult()):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," + ").concat(d(e))),this.lowPriority=!0,this}},{key:"sub",value:function(e){return e instanceof c?this.result="".concat(this.result," - ").concat(e.getResult()):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," - ").concat(d(e))),this.lowPriority=!0,this}},{key:"mul",value:function(e){return this.lowPriority&&(this.result="(".concat(this.result,")")),e instanceof c?this.result="".concat(this.result," * ").concat(e.getResult(!0)):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," * ").concat(e)),this.lowPriority=!1,this}},{key:"div",value:function(e){return this.lowPriority&&(this.result="(".concat(this.result,")")),e instanceof c?this.result="".concat(this.result," / ").concat(e.getResult(!0)):("number"==typeof e||"string"==typeof e)&&(this.result="".concat(this.result," / ").concat(e)),this.lowPriority=!1,this}},{key:"getResult",value:function(e){return this.lowPriority||e?"(".concat(this.result,")"):this.result}},{key:"equal",value:function(e){var t=this,r=(e||{}).unit,n=!0;return("boolean"==typeof r?n=r:Array.from(this.unitlessCssVar).some(function(e){return t.result.includes(e)})&&(n=!1),this.result=this.result.replace(u,n?"px":""),void 0!==this.lowPriority)?"calc(".concat(this.result,")"):this.result}}]),c}(s),p=function(e){(0,a.default)(s,e);var t=(0,i.default)(s);function s(e){var n;return(0,r.default)(this,s),n=t.call(this),(0,l.default)((0,o.default)(n),"result",0),e instanceof s?n.result=e.result:"number"==typeof e&&(n.result=e),n}return(0,n.default)(s,[{key:"add",value:function(e){return e instanceof s?this.result+=e.result:"number"==typeof e&&(this.result+=e),this}},{key:"sub",value:function(e){return e instanceof s?this.result-=e.result:"number"==typeof e&&(this.result-=e),this}},{key:"mul",value:function(e){return e instanceof s?this.result*=e.result:"number"==typeof e&&(this.result*=e),this}},{key:"div",value:function(e){return e instanceof s?this.result/=e.result:"number"==typeof e&&(this.result/=e),this}},{key:"equal",value:function(){return this.result}}]),s}(s);e.s(["default",0,function(e,t){var r="css"===e?f:p;return function(e){return new r(e,t)}}],559069),e.s(["default",0,function(e,t){return"".concat([t,e.replace(/([A-Z]+)([A-Z][a-z]+)/g,"$1-$2").replace(/([a-z])([A-Z])/g,"$1-$2")].filter(Boolean).join("-"))}],196607)},310137,252070,885662,e=>{"use strict";e.i(247167);var t=e.i(410160),r=e.i(392221),n=e.i(211577),o=e.i(209428),a=e.i(271645);e.i(296059);var i=e.i(608648),l=e.i(869153),s=e.i(299615),c=e.i(559069),u=e.i(196607);e.i(62664);let d=function(e,t,n,a){var i=(0,o.default)({},t[e]);null!=a&&a.deprecatedTokens&&a.deprecatedTokens.forEach(function(e){var t=(0,r.default)(e,2),n=t[0],o=t[1];(null!=i&&i[n]||null!=i&&i[o])&&(null!=i[o]||(i[o]=null==i?void 0:i[n]))});var l=(0,o.default)((0,o.default)({},n),i);return Object.keys(l).forEach(function(e){l[e]===t[e]&&delete l[e]}),l};var f="u">typeof CSSINJS_STATISTIC,p=!0;function m(){for(var e=arguments.length,r=Array(e),n=0;ntypeof Proxy&&(t=new Set,r=new Proxy(e,{get:function(e,r){if(p){var n;null==(n=t)||n.add(r)}return e[r]}}),n=function(e,r){var n;g[e]={global:Array.from(t),component:(0,o.default)((0,o.default)({},null==(n=g[e])?void 0:n.component),r)}}),{token:r,keys:t,flush:n}};e.s(["default",0,v,"merge",()=>m],252070);let y=function(e,t,r){if("function"==typeof r){var n;return r(m(t,null!=(n=t[e])?n:{}))}return null!=r?r:{}};var b=e.i(915654),w=e.i(278409),C=e.i(233848),x=new(function(){function e(){(0,w.default)(this,e),(0,n.default)(this,"map",new Map),(0,n.default)(this,"objectIDMap",new WeakMap),(0,n.default)(this,"nextID",0),(0,n.default)(this,"lastAccessBeat",new Map),(0,n.default)(this,"accessBeat",0)}return(0,C.default)(e,[{key:"set",value:function(e,t){this.clear();var r=this.getCompositeKey(e);this.map.set(r,t),this.lastAccessBeat.set(r,Date.now())}},{key:"get",value:function(e){var t=this.getCompositeKey(e),r=this.map.get(t);return this.lastAccessBeat.set(t,Date.now()),this.accessBeat+=1,r}},{key:"getCompositeKey",value:function(e){var r=this;return e.map(function(e){return e&&"object"===(0,t.default)(e)?"obj_".concat(r.getObjectID(e)):"".concat((0,t.default)(e),"_").concat(e)}).join("|")}},{key:"getObjectID",value:function(e){if(this.objectIDMap.has(e))return this.objectIDMap.get(e);var t=this.nextID;return this.objectIDMap.set(e,t),this.nextID+=1,t}},{key:"clear",value:function(){var e=this;if(this.accessBeat>1e4){var t=Date.now();this.lastAccessBeat.forEach(function(r,n){t-r>6e5&&(e.map.delete(n),e.lastAccessBeat.delete(n))}),this.accessBeat=0}}}]),e}());let S=function(){return{}};e.s([],310137),e.s(["genStyleUtils",0,function(e){var f=e.useCSP,p=void 0===f?S:f,g=e.useToken,h=e.usePrefix,w=e.getResetStyles,C=e.getCommonStyle,$=e.getCompUnitless;function E(n,l,f){var S=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},$=Array.isArray(n)?n:[n,n],E=(0,r.default)($,1)[0],k=$.join("-"),O=e.layer||{name:"antd"};return function(e){var r,n,$=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e,j=g(),T=j.theme,_=j.realToken,P=j.hashId,I=j.token,F=j.cssVar,N=h(),R=N.rootPrefixCls,M=N.iconPrefixCls,A=p(),B=F?"css":"js",z=(r=function(){var e=new Set;return F&&Object.keys(S.unitless||{}).forEach(function(t){e.add((0,i.token2CSSVar)(t,F.prefix)),e.add((0,i.token2CSSVar)(t,(0,u.default)(E,F.prefix)))}),(0,c.default)(B,e)},n=[B,E,null==F?void 0:F.prefix],a.default.useMemo(function(){var e=x.get(n);if(e)return e;var t=r();return x.set(n,t),t},n)),L="js"===B?{max:Math.max,min:Math.min}:{max:function(){for(var e=arguments.length,t=Array(e),r=0;r1&&void 0!==arguments[1]?arguments[1]:e,n=T(e,t),o=(0,r.default)(n,2)[1],a=_(t),i=(0,r.default)(a,2);return[i[0],o,i[1]]}},genSubStyleComponent:function(e,t,r){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=E(e,t,r,(0,o.default)({resetStyle:!1,order:-998},n));return function(e){var t=e.prefixCls,r=e.rootCls,n=void 0===r?t:r;return a(t,n),null}},genComponentStyleHook:E}}],885662)},246422,e=>{"use strict";var t=e.i(271645);e.i(310137);var r=e.i(885662),n=e.i(242064),o=e.i(183293),a=e.i(719581);let{genStyleHooks:i,genComponentStyleHook:l,genSubStyleComponent:s}=(0,r.genStyleUtils)({usePrefix:()=>{let{getPrefixCls:e,iconPrefixCls:r}=(0,t.useContext)(n.ConfigContext);return{rootPrefixCls:e(),iconPrefixCls:r}},useToken:()=>{let[e,t,r,n,o]=(0,a.default)();return{theme:e,realToken:t,hashId:r,token:n,cssVar:o}},useCSP:()=>{let{csp:e}=(0,t.useContext)(n.ConfigContext);return null!=e?e:{}},getResetStyles:(e,t)=>{var r;let a=(0,o.genLinkStyle)(e);return[a,{"&":a},(0,o.genIconStyle)(null!=(r=null==t?void 0:t.prefix.iconPrefixCls)?r:n.defaultIconPrefixCls)]},getCommonStyle:o.genCommonStyle,getCompUnitless:()=>a.unitless});e.s(["genComponentStyleHook",0,l,"genStyleHooks",0,i,"genSubStyleComponent",0,s])},838378,e=>{"use strict";var t=e.i(252070);e.s(["mergeToken",()=>t.merge])},645384,628918,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(201072),n=e.i(726289),o=e.i(864517),a=e.i(562901),i=e.i(779573),l=e.i(739295),s=e.i(343794);e.i(792131);var c=e.i(10183),u=e.i(242064),d=e.i(321883);e.i(296059);var f=e.i(694758),p=e.i(915654),m=e.i(122767),g=e.i(183293),h=e.i(246422),v=e.i(838378);let y=["top","topLeft","topRight","bottom","bottomLeft","bottomRight"],b={topLeft:"left",topRight:"right",bottomLeft:"left",bottomRight:"right",top:"left",bottom:"left"},w=e=>{let{iconCls:t,componentCls:r,boxShadow:n,fontSizeLG:o,notificationMarginBottom:a,borderRadiusLG:i,colorSuccess:l,colorInfo:s,colorWarning:c,colorError:u,colorTextHeading:d,notificationBg:f,notificationPadding:m,notificationMarginEdge:h,notificationProgressBg:v,notificationProgressHeight:y,fontSize:b,lineHeight:w,width:C,notificationIconSize:x,colorText:S,colorSuccessBg:$,colorErrorBg:E,colorInfoBg:k,colorWarningBg:O}=e,j=`${r}-notice`;return{position:"relative",marginBottom:a,marginInlineStart:"auto",background:f,borderRadius:i,boxShadow:n,[j]:{padding:m,width:C,maxWidth:`calc(100vw - ${(0,p.unit)(e.calc(h).mul(2).equal())})`,lineHeight:w,wordWrap:"break-word",borderRadius:i,overflow:"hidden","&-success":$?{background:$}:{},"&-error":E?{background:E}:{},"&-info":k?{background:k}:{},"&-warning":O?{background:O}:{}},[`${j}-message`]:{color:d,fontSize:o,lineHeight:e.lineHeightLG},[`${j}-description`]:{fontSize:b,color:S,marginTop:e.marginXS},[`${j}-closable ${j}-message`]:{paddingInlineEnd:e.paddingLG},[`${j}-with-icon ${j}-message`]:{marginInlineStart:e.calc(e.marginSM).add(x).equal(),fontSize:o},[`${j}-with-icon ${j}-description`]:{marginInlineStart:e.calc(e.marginSM).add(x).equal(),fontSize:b},[`${j}-icon`]:{position:"absolute",fontSize:x,lineHeight:1,[`&-success${t}`]:{color:l},[`&-info${t}`]:{color:s},[`&-warning${t}`]:{color:c},[`&-error${t}`]:{color:u}},[`${j}-close`]:Object.assign({position:"absolute",top:e.notificationPaddingVertical,insetInlineEnd:e.notificationPaddingHorizontal,color:e.colorIcon,outline:"none",width:e.notificationCloseButtonSize,height:e.notificationCloseButtonSize,borderRadius:e.borderRadiusSM,transition:`background-color ${e.motionDurationMid}, color ${e.motionDurationMid}`,display:"flex",alignItems:"center",justifyContent:"center",background:"none",border:"none","&:hover":{color:e.colorIconHover,backgroundColor:e.colorBgTextHover},"&:active":{backgroundColor:e.colorBgTextActive}},(0,g.genFocusStyle)(e)),[`${j}-progress`]:{position:"absolute",display:"block",appearance:"none",inlineSize:`calc(100% - ${(0,p.unit)(i)} * 2)`,left:{_skip_check_:!0,value:i},right:{_skip_check_:!0,value:i},bottom:0,blockSize:y,border:0,"&, &::-webkit-progress-bar":{borderRadius:i,backgroundColor:"rgba(0, 0, 0, 0.04)"},"&::-moz-progress-bar":{background:v},"&::-webkit-progress-value":{borderRadius:i,background:v}},[`${j}-actions`]:{float:"right",marginTop:e.marginSM}}},C=e=>({zIndexPopup:e.zIndexPopupBase+m.CONTAINER_MAX_OFFSET+50,width:384,colorSuccessBg:void 0,colorErrorBg:void 0,colorInfoBg:void 0,colorWarningBg:void 0}),x=e=>{let t=e.paddingMD,r=e.paddingLG;return(0,v.mergeToken)(e,{notificationBg:e.colorBgElevated,notificationPaddingVertical:t,notificationPaddingHorizontal:r,notificationIconSize:e.calc(e.fontSizeLG).mul(e.lineHeightLG).equal(),notificationCloseButtonSize:e.calc(e.controlHeightLG).mul(.55).equal(),notificationMarginBottom:e.margin,notificationPadding:`${(0,p.unit)(e.paddingMD)} ${(0,p.unit)(e.paddingContentHorizontalLG)}`,notificationMarginEdge:e.marginLG,animationMaxHeight:150,notificationStackLayer:3,notificationProgressHeight:2,notificationProgressBg:`linear-gradient(90deg, ${e.colorPrimaryBorderHover}, ${e.colorPrimary})`})},S=(0,h.genStyleHooks)("Notification",e=>{let t=x(e);return[(e=>{let{componentCls:t,notificationMarginBottom:r,notificationMarginEdge:n,motionDurationMid:o,motionEaseInOut:a}=e,i=`${t}-notice`,l=new f.Keyframes("antNotificationFadeOut",{"0%":{maxHeight:e.animationMaxHeight,marginBottom:r},"100%":{maxHeight:0,marginBottom:0,paddingTop:0,paddingBottom:0,opacity:0}});return[{[t]:Object.assign(Object.assign({},(0,g.resetComponent)(e)),{position:"fixed",zIndex:e.zIndexPopup,marginRight:{value:n,_skip_check_:!0},[`${t}-hook-holder`]:{position:"relative"},[`${t}-fade-appear-prepare`]:{opacity:"0 !important"},[`${t}-fade-enter, ${t}-fade-appear`]:{animationDuration:e.motionDurationMid,animationTimingFunction:a,animationFillMode:"both",opacity:0,animationPlayState:"paused"},[`${t}-fade-leave`]:{animationTimingFunction:a,animationFillMode:"both",animationDuration:o,animationPlayState:"paused"},[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationPlayState:"running"},[`${t}-fade-leave${t}-fade-leave-active`]:{animationName:l,animationPlayState:"running"},"&-rtl":{direction:"rtl",[`${i}-actions`]:{float:"left"}}})},{[t]:{[`${i}-wrapper`]:w(e)}}]})(t),(e=>{let{componentCls:t,notificationMarginEdge:r,animationMaxHeight:n}=e,o=`${t}-notice`,a=new f.Keyframes("antNotificationFadeIn",{"0%":{transform:"translate3d(100%, 0, 0)",opacity:0},"100%":{transform:"translate3d(0, 0, 0)",opacity:1}});return{[t]:{[`&${t}-top, &${t}-bottom`]:{marginInline:0,[o]:{marginInline:"auto auto"}},[`&${t}-top`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:new f.Keyframes("antNotificationTopFadeIn",{"0%":{top:-n,opacity:0},"100%":{top:0,opacity:1}})}},[`&${t}-bottom`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:new f.Keyframes("antNotificationBottomFadeIn",{"0%":{bottom:e.calc(n).mul(-1).equal(),opacity:0},"100%":{bottom:0,opacity:1}})}},[`&${t}-topRight, &${t}-bottomRight`]:{[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:a}},[`&${t}-topLeft, &${t}-bottomLeft`]:{marginRight:{value:0,_skip_check_:!0},marginLeft:{value:r,_skip_check_:!0},[o]:{marginInlineEnd:"auto",marginInlineStart:0},[`${t}-fade-enter${t}-fade-enter-active, ${t}-fade-appear${t}-fade-appear-active`]:{animationName:new f.Keyframes("antNotificationLeftFadeIn",{"0%":{transform:"translate3d(-100%, 0, 0)",opacity:0},"100%":{transform:"translate3d(0, 0, 0)",opacity:1}})}}}}})(t),(e=>{let{componentCls:t}=e;return Object.assign({[`${t}-stack`]:{[`& > ${t}-notice-wrapper`]:Object.assign({transition:`transform ${e.motionDurationSlow}, backdrop-filter 0s`,willChange:"transform, opacity",position:"absolute"},(e=>{let t={};for(let r=1;r ${e.componentCls}-notice`]:{opacity:0,transition:`opacity ${e.motionDurationMid}`}};return Object.assign({[`&:not(:nth-last-child(-n+${e.notificationStackLayer}))`]:{opacity:0,overflow:"hidden",color:"transparent",pointerEvents:"none"}},t)})(e))},[`${t}-stack:not(${t}-stack-expanded)`]:{[`& > ${t}-notice-wrapper`]:Object.assign({},(e=>{let t={};for(let r=1;r ${t}-notice-wrapper`]:{"&:not(:nth-last-child(-n + 1))":{opacity:1,overflow:"unset",color:"inherit",pointerEvents:"auto",[`& > ${e.componentCls}-notice`]:{opacity:1}},"&:after":{content:'""',position:"absolute",height:e.margin,width:"100%",insetInline:0,bottom:e.calc(e.margin).mul(-1).equal(),background:"transparent",pointerEvents:"auto"}}}},y.map(t=>((e,t)=>{let{componentCls:r}=e;return{[`${r}-${t}`]:{[`&${r}-stack > ${r}-notice-wrapper`]:{[t.startsWith("top")?"top":"bottom"]:0,[b[t]]:{value:0,_skip_check_:!0}}}}})(e,t)).reduce((e,t)=>Object.assign(Object.assign({},e),t),{}))})(t)]},C);e.s(["default",0,S,"genNoticeStyle",0,w,"prepareComponentToken",0,C,"prepareNotificationToken",0,x],628918);let $=(0,h.genSubStyleComponent)(["Notification","PurePanel"],e=>{let t=`${e.componentCls}-notice`,r=x(e);return{[`${t}-pure-panel`]:Object.assign(Object.assign({},w(r)),{width:r.width,maxWidth:`calc(100vw - ${(0,p.unit)(e.calc(r.notificationMarginEdge).mul(2).equal())})`,margin:0})}},C);var E=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};function k(e,r){return null===r||!1===r?null:r||t.createElement(o.default,{className:`${e}-close-icon`})}i.default,r.default,n.default,a.default,l.default;let O={success:r.default,info:i.default,error:n.default,warning:a.default},j=e=>{let{prefixCls:r,icon:n,type:o,message:a,description:i,actions:l,role:c="alert"}=e,u=null;return n?u=t.createElement("span",{className:`${r}-icon`},n):o&&(u=t.createElement(O[o]||null,{className:(0,s.default)(`${r}-icon`,`${r}-icon-${o}`)})),t.createElement("div",{className:(0,s.default)({[`${r}-with-icon`]:u}),role:c},u,t.createElement("div",{className:`${r}-message`},a),i&&t.createElement("div",{className:`${r}-description`},i),l&&t.createElement("div",{className:`${r}-actions`},l))};e.s(["PureContent",0,j,"default",0,e=>{let{prefixCls:r,className:n,icon:o,type:a,message:i,description:l,btn:f,actions:p,closable:m=!0,closeIcon:g,className:h}=e,v=E(e,["prefixCls","className","icon","type","message","description","btn","actions","closable","closeIcon","className"]),{getPrefixCls:y}=t.useContext(u.ConfigContext),b=r||y("notification"),w=`${b}-notice`,C=(0,d.default)(b),[x,O,T]=S(b,C);return x(t.createElement("div",{className:(0,s.default)(`${w}-pure-panel`,O,n,T,C)},t.createElement($,{prefixCls:b}),t.createElement(c.Notice,Object.assign({},v,{prefixCls:b,eventKey:"pure",duration:null,closable:m,className:(0,s.default)({notificationClassName:h}),closeIcon:k(b,g),content:t.createElement(j,{prefixCls:w,icon:o,type:a,message:i,description:l,actions:null!=p?p:f})}))))},"getCloseIcon",()=>k],645384)},194732,513139,e=>{"use strict";var t=e.i(198197);e.s(["NotificationProvider",()=>t.default],194732);var r=e.i(404556);e.s(["useNotification",()=>r.default],513139)},983320,208224,e=>{"use strict";var t=e.i(271645),r=e.i(201072),n=e.i(726289),o=e.i(562901),a=e.i(779573),i=e.i(739295),l=e.i(343794);e.i(792131);var s=e.i(10183),c=e.i(242064),u=e.i(321883);e.i(296059);var d=e.i(694758),f=e.i(122767),p=e.i(183293),m=e.i(246422),g=e.i(838378);let h=(0,m.genStyleHooks)("Message",e=>(e=>{let{componentCls:t,iconCls:r,boxShadow:n,colorText:o,colorSuccess:a,colorError:i,colorWarning:l,colorInfo:s,fontSizeLG:c,motionEaseInOutCirc:u,motionDurationSlow:f,marginXS:m,paddingXS:g,borderRadiusLG:h,zIndexPopup:v,contentPadding:y,contentBg:b}=e,w=`${t}-notice`,C=new d.Keyframes("MessageMoveIn",{"0%":{padding:0,transform:"translateY(-100%)",opacity:0},"100%":{padding:g,transform:"translateY(0)",opacity:1}}),x=new d.Keyframes("MessageMoveOut",{"0%":{maxHeight:e.height,padding:g,opacity:1},"100%":{maxHeight:0,padding:0,opacity:0}}),S={padding:g,textAlign:"center",[`${t}-custom-content`]:{display:"flex",alignItems:"center"},[`${t}-custom-content > ${r}`]:{marginInlineEnd:m,fontSize:c},[`${w}-content`]:{display:"inline-block",padding:y,background:b,borderRadius:h,boxShadow:n,pointerEvents:"all"},[`${t}-success > ${r}`]:{color:a},[`${t}-error > ${r}`]:{color:i},[`${t}-warning > ${r}`]:{color:l},[`${t}-info > ${r}, + ${t}-loading > ${r}`]:{color:s}};return[{[t]:Object.assign(Object.assign({},(0,p.resetComponent)(e)),{color:o,position:"fixed",top:m,width:"100%",pointerEvents:"none",zIndex:v,[`${t}-move-up`]:{animationFillMode:"forwards"},[` + ${t}-move-up-appear, + ${t}-move-up-enter + `]:{animationName:C,animationDuration:f,animationPlayState:"paused",animationTimingFunction:u},[` + ${t}-move-up-appear${t}-move-up-appear-active, + ${t}-move-up-enter${t}-move-up-enter-active + `]:{animationPlayState:"running"},[`${t}-move-up-leave`]:{animationName:x,animationDuration:f,animationPlayState:"paused",animationTimingFunction:u},[`${t}-move-up-leave${t}-move-up-leave-active`]:{animationPlayState:"running"},"&-rtl":{direction:"rtl",span:{direction:"rtl"}}})},{[t]:{[`${w}-wrapper`]:Object.assign({},S)}},{[`${t}-notice-pure-panel`]:Object.assign(Object.assign({},S),{padding:0,textAlign:"start"})}]})((0,g.mergeToken)(e,{height:150})),e=>({zIndexPopup:e.zIndexPopupBase+f.CONTAINER_MAX_OFFSET+10,contentBg:e.colorBgElevated,contentPadding:`${(e.controlHeightLG-e.fontSize*e.lineHeight)/2}px ${e.paddingSM}px`}));e.s(["default",0,h],208224);var v=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 y={info:t.createElement(a.default,null),success:t.createElement(r.default,null),error:t.createElement(n.default,null),warning:t.createElement(o.default,null),loading:t.createElement(i.default,null)},b=({prefixCls:e,type:r,icon:n,children:o})=>t.createElement("div",{className:(0,l.default)(`${e}-custom-content`,`${e}-${r}`)},n||y[r],t.createElement("span",null,o));e.s(["PureContent",0,b,"default",0,e=>{let{prefixCls:r,className:n,type:o,icon:a,content:i}=e,d=v(e,["prefixCls","className","type","icon","content"]),{getPrefixCls:f}=t.useContext(c.ConfigContext),p=r||f("message"),m=(0,u.default)(p),[g,y,w]=h(p,m);return g(t.createElement(s.Notice,Object.assign({},d,{prefixCls:p,className:(0,l.default)(n,y,`${p}-notice-pure-panel`,w,m),eventKey:"pure",duration:null,content:t.createElement(b,{prefixCls:p,type:o,icon:a},i)})))}],983320)},727749,698173,190702,e=>{"use strict";var t=e.i(271645);e.i(247167);var r=e.i(738275),n=e.i(609587),o=e.i(242064),a=e.i(783164),i=e.i(645384),l=e.i(343794);e.i(792131);var s=e.i(194732),c=e.i(513139),u=e.i(747656),d=e.i(321883),f=e.i(104458),p=e.i(628918),m=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 g=({children:e,prefixCls:r})=>{let n=(0,d.default)(r),[o,a,i]=(0,p.default)(r,n);return o(t.default.createElement(s.NotificationProvider,{classNames:{list:(0,l.default)(a,i,n)}},e))},h=(e,{prefixCls:r,key:n})=>t.default.createElement(g,{prefixCls:r,key:n},e),v=t.default.forwardRef((e,r)=>{let{top:n,bottom:a,prefixCls:s,getContainer:u,maxCount:d,rtl:p,onAllRemoved:m,stack:g,duration:v,pauseOnHover:y=!0,showProgress:b}=e,{getPrefixCls:w,getPopupContainer:C,notification:x,direction:S}=(0,t.useContext)(o.ConfigContext),[,$]=(0,f.useToken)(),E=s||w("notification"),[k,O]=(0,c.useNotification)({prefixCls:E,style:e=>(function(e,t,r){let n;switch(e){case"top":n={left:"50%",transform:"translateX(-50%)",right:"auto",top:t,bottom:"auto"};break;case"topLeft":n={left:0,top:t,bottom:"auto"};break;case"topRight":n={right:0,top:t,bottom:"auto"};break;case"bottom":n={left:"50%",transform:"translateX(-50%)",right:"auto",top:"auto",bottom:r};break;case"bottomLeft":n={left:0,top:"auto",bottom:r};break;default:n={right:0,top:"auto",bottom:r}}return n})(e,null!=n?n:24,null!=a?a:24),className:()=>(0,l.default)({[`${E}-rtl`]:null!=p?p:"rtl"===S}),motion:()=>({motionName:`${E}-fade`}),closable:!0,closeIcon:(0,i.getCloseIcon)(E),duration:null!=v?v:4.5,getContainer:()=>(null==u?void 0:u())||(null==C?void 0:C())||document.body,maxCount:d,pauseOnHover:y,showProgress:b,onAllRemoved:m,renderNotifications:h,stack:!1!==g&&{threshold:"object"==typeof g?null==g?void 0:g.threshold:void 0,offset:8,gap:$.margin}});return t.default.useImperativeHandle(r,()=>Object.assign(Object.assign({},k),{prefixCls:E,notification:x})),O});function y(e){let r=t.default.useRef(null);return(0,u.devUseWarning)("Notification"),[t.default.useMemo(()=>{let n=n=>{var o;if(!r.current)return;let{open:a,prefixCls:s,notification:c}=r.current,u=`${s}-notice`,{message:d,description:f,icon:p,type:g,btn:h,actions:v,className:y,style:b,role:w="alert",closeIcon:C,closable:x}=n,S=m(n,["message","description","icon","type","btn","actions","className","style","role","closeIcon","closable"]),$=(0,i.getCloseIcon)(u,void 0!==C?C:void 0!==(null==e?void 0:e.closeIcon)?e.closeIcon:null==c?void 0:c.closeIcon);return a(Object.assign(Object.assign({placement:null!=(o=null==e?void 0:e.placement)?o:"topRight"},S),{content:t.default.createElement(i.PureContent,{prefixCls:u,icon:p,type:g,message:d,description:f,actions:null!=v?v:h,role:w}),className:(0,l.default)(g&&`${u}-${g}`,y,null==c?void 0:c.className),style:Object.assign(Object.assign({},null==c?void 0:c.style),b),closeIcon:$,closable:null!=x?x:!!$}))},o={open:n,destroy:e=>{var t,n;void 0!==e?null==(t=r.current)||t.close(e):null==(n=r.current)||n.destroy()}};return["success","info","warning","error"].forEach(e=>{o[e]=t=>n(Object.assign(Object.assign({},t),{type:e}))}),o},[]),t.default.createElement(v,Object.assign({key:"notification-holder"},e,{ref:r}))]}let b=null,w=[],C={};function x(){let{getContainer:e,rtl:t,maxCount:r,top:n,bottom:o,showProgress:a,pauseOnHover:i}=C,l=(null==e?void 0:e())||document.body;return{getContainer:()=>l,rtl:t,maxCount:r,top:n,bottom:o,showProgress:a,pauseOnHover:i}}let S=t.default.forwardRef((e,n)=>{let{notificationConfig:a,sync:i}=e,{getPrefixCls:l}=(0,t.useContext)(o.ConfigContext),s=C.prefixCls||l("notification"),c=(0,t.useContext)(r.AppConfigContext),[u,d]=y(Object.assign(Object.assign(Object.assign({},a),{prefixCls:s}),c.notification));return t.default.useEffect(i,[]),t.default.useImperativeHandle(n,()=>{let e=Object.assign({},u);return Object.keys(e).forEach(t=>{e[t]=(...e)=>(i(),u[t].apply(u,e))}),{instance:e,sync:i}}),d}),$=t.default.forwardRef((e,r)=>{let[o,a]=t.default.useState(x),i=()=>{a(x)};t.default.useEffect(i,[]);let l=(0,n.globalConfig)(),s=l.getRootPrefixCls(),c=l.getIconPrefixCls(),u=l.getTheme(),d=t.default.createElement(S,{ref:r,sync:i,notificationConfig:o});return t.default.createElement(n.default,{prefixCls:s,iconPrefixCls:c,theme:u},l.holderRender?l.holderRender(d):d)}),E=()=>{if(!b){let e=document.createDocumentFragment(),r={fragment:e};b=r,(()=>{(0,a.unstableSetRender)()(t.default.createElement($,{ref:e=>{let{instance:t,sync:n}=e||{};Promise.resolve().then(()=>{!r.instance&&t&&(r.instance=t,r.sync=n,E())})}}),e)})();return}b.instance&&(w.forEach(e=>{switch(e.type){case"open":b.instance.open(Object.assign(Object.assign({},C),e.config));break;case"destroy":var t;null==(t=null==b?void 0:b.instance)||t.destroy(e.key)}}),w=[])};function k(e){(0,n.globalConfig)(),w.push({type:"open",config:e}),E()}let O={open:k,destroy:e=>{w.push({type:"destroy",key:e}),E()},config:function(e){C=Object.assign(Object.assign({},C),e),(()=>{var e;null==(e=null==b?void 0:b.sync)||e.call(b)})()},useNotification:function(e){return y(e)},_InternalPanelDoNotUseOrYouWillBeFired:i.default};["success","info","warning","error"].forEach(e=>{O[e]=t=>k(Object.assign(Object.assign({},t),{type:e}))});e.s(["notification",0,O],698173);let j=e=>{if(!e)return"An unknown error occurred";if("string"==typeof e)return e;if(e.message)try{let t=JSON.parse(e.message);if(t.error&&t.error.message)return t.error.message;return"string"==typeof t?t:JSON.stringify(t,null,2)}catch(t){return e.message}if(e.response&&e.response.data){if("string"==typeof e.response.data)return e.response.data;if(e.response.data.message)return e.response.data.message;if(e.response.data.error)return"string"==typeof e.response.data.error?e.response.data.error:e.response.data.error.message||JSON.stringify(e.response.data.error)}return String(e)};e.s(["parseErrorMessage",0,j],190702);let T=null;function _(){return"topRight"}function P(e,t){return"string"==typeof e?{message:t,description:e}:{message:e.message??t,...e}}function I(e){return"number"==typeof e?e:"string"==typeof e&&/^\d+$/.test(e)?parseInt(e,10):void 0}let F=["invalid api key","invalid authorization header format","authentication error","invalid proxy server token","invalid jwt token","invalid jwt submitted","unauthorized access to metrics endpoint"],N=["admin-only endpoint","not allowed to access model","user does not have permission","access forbidden","invalid credentials used to access ui","user not allowed to access proxy"],R=["db not connected","database not initialized","no db connected","prisma client not initialized","service unhealthy"],M=["no models configured on proxy","llm router not initialized","no deployments available","no healthy deployment available","not allowed to access model due to tags configuration","invalid model name passed in"],A=["deployment over user-defined ratelimit","crossed tpm / rpm / max parallel request limit","max parallel request limit"],B=["budget exceeded","crossed budget","provider budget"],z=["must be a litellm enterprise user","only be available for liteLLM enterprise users","missing litellm-enterprise package","only available on the docker image","enterprise feature","premium user"],L=["invalid json payload","invalid request type","invalid key format","invalid hash key","invalid sort column","invalid sort order","invalid limit","invalid file type","invalid field","invalid date format"],H=["model not found","model with id","credential not found","user not found","team not found","organization not found","mcp server with id","tool '"],D=["already exists","team member is already in team","user already exists"],V=["violated openai moderation policy","violated jailbreak threshold","violated prompt_injection threshold","violated content safety policy","violated lasso guardrail policy","blocked by pillar security guardrail","violated azure prompt shield guardrail policy","content blocked by model armor","response blocked by model armor","streaming response blocked by model armor","guardrail","moderation"],W=["invalid purpose","service must be specified","invalid response - response.response is none"],U=["cloudzero settings not configured","failed to decrypt cloudzero api key","cloudzero settings not found"],G=["created successfully","updated successfully","deleted successfully","credential created successfully","model added successfully","team created successfully","user created successfully","organization created successfully","cloudzero settings initialized successfully","cloudzero settings updated successfully","cloudzero export completed successfully","mock llm request made","mock slack alert sent","mock email alert sent","spend for all api keys and teams reset successfully","monthlyglobalspend view refreshed","cache cleared successfully","cache set successfully","ip ","deleted successfully"],q=["rate limit reached for deployment","deployment cooldown period active"],K=["this feature is only available for litellm enterprise users","enterprise features are not available","regenerating virtual keys is an enterprise feature","trying to set allowed_routes. this is an enterprise feature"],X=["invalid maximum_spend_logs_retention_interval value","error has invalid or non-convertible code","failed to save health check to database"],J={showProgress:!0,pauseOnHover:!0};e.s(["default",0,{error(e){let t=P(e,"Error");(T||O).error({...J,...t,placement:t.placement??_(),duration:t.duration??6})},warning(e){let t=P(e,"Warning");(T||O).warning({...J,...t,placement:t.placement??_(),duration:t.duration??5})},info(e){let t=P(e,"Info");(T||O).info({...J,...t,placement:t.placement??_(),duration:t.duration??4})},success(e){if(t.default.isValidElement(e))return void(T||O).success({...J,message:"Success",description:e,placement:_(),duration:3.5});let r=P(e,"Success");(T||O).success({...J,...r,placement:r.placement??_(),duration:r.duration??3.5})},fromBackend(e,t){let r,n=I(e?.response?.status)??I(e?.status_code)??I(e?.code),o="string"==typeof e?e:j(e?.response?.data?.error?.message??e?.response?.data?.message??e?.response?.data?.error??e?.detail??e?.message??e),a={...t??{},description:o,placement:t?.placement??_()};if(void 0!==n||e instanceof Error||"string"==typeof e||e&&"object"==typeof e&&("error"in e||"detail"in e)){let e,r=(e=(o||"").toLowerCase(),F.some(t=>e.includes(t))?"Authentication Error":N.some(t=>e.includes(t))?"Access Denied":R?.some?.(t=>e.includes(t))||503===n?"Service Unavailable":B?.some?.(t=>e.includes(t))?"Budget Exceeded":z?.some?.(t=>e.includes(t))?"Feature Unavailable":M?.some?.(t=>e.includes(t))?"Routing Error":D.some(t=>e.includes(t))?"Already Exists":V.some(t=>e.includes(t))?"Content Blocked":W.some(t=>e.includes(t))?"Validation Error":U.some(t=>e.includes(t))?"Integration Error":L.some(t=>e.includes(t))?"Validation Error":404===n||e.includes("not found")||H.some(t=>e.includes(t))?"Not Found":429===n||e.includes("rate limit")||e.includes("tpm")||e.includes("rpm")||A?.some?.(t=>e.includes(t))?"Rate Limit Exceeded":n&&n>=500?"Server Error":401===n?"Authentication Error":403===n?"Access Denied":e.includes("enterprise")||e.includes("premium")?"Info":n&&n>=400?"Request Error":"Error"),i={...a,message:r};return"Rate Limit Exceeded"===r||"Info"===r||"Budget Exceeded"===r||"Feature Unavailable"===r||"Content Blocked"===r||"Integration Error"===r?void(T||O).warning({...J,...i,duration:t?.duration??7}):"Server Error"===r?void(T||O).error({...J,...i,duration:t?.duration??8}):"Request Error"===r||"Authentication Error"===r||"Access Denied"===r||"Not Found"===r||"Error"===r||"Already Exists"===r?void(T||O).error({...J,...i,duration:t?.duration??6}):void(T||O).info({...J,...i,duration:t?.duration??4})}let i=(r=(o||"").toLowerCase(),G.some(e=>r.includes(e))?{kind:"success",title:"Success"}:K.some(e=>r.includes(e))?{kind:"warning",title:"Feature Notice"}:X.some(e=>r.includes(e))?{kind:"warning",title:"Configuration Warning"}:q.some(e=>r.includes(e))?{kind:"warning",title:"Rate Limit"}:null),l={...a,message:i?.title??"Info"};i?.kind==="success"?(T||O).success({...J,...l,duration:t?.duration??3.5}):i?.kind==="warning"?(T||O).warning({...J,...l,duration:t?.duration??6}):(T||O).info({...J,...l,duration:t?.duration??4})},clear(){(T||O).destroy()}},"setNotificationInstance",0,e=>{T=e}],727749)},888259,998573,e=>{"use strict";e.i(247167);var t=e.i(8211),r=e.i(271645),n=e.i(738275),o=e.i(609587),a=e.i(242064),i=e.i(783164),l=e.i(983320),s=e.i(864517),c=e.i(343794);e.i(792131);var u=e.i(194732),d=e.i(513139),f=e.i(747656),p=e.i(321883),m=e.i(208224);function g(e){let t,r=new Promise(r=>{t=e(()=>{r(!0)})}),n=()=>{null==t||t()};return n.then=(e,t)=>r.then(e,t),n.promise=r,n}var h=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 v=({children:e,prefixCls:t})=>{let n=(0,p.default)(t),[o,a,i]=(0,m.default)(t,n);return o(r.createElement(u.NotificationProvider,{classNames:{list:(0,c.default)(a,i,n)}},e))},y=(e,{prefixCls:t,key:n})=>r.createElement(v,{prefixCls:t,key:n},e),b=r.forwardRef((e,t)=>{let{top:n,prefixCls:o,getContainer:i,maxCount:l,duration:u=3,rtl:f,transitionName:p,onAllRemoved:m}=e,{getPrefixCls:g,getPopupContainer:h,message:v,direction:b}=r.useContext(a.ConfigContext),w=o||g("message"),C=r.createElement("span",{className:`${w}-close-x`},r.createElement(s.default,{className:`${w}-close-icon`})),[x,S]=(0,d.useNotification)({prefixCls:w,style:()=>({left:"50%",transform:"translateX(-50%)",top:null!=n?n:8}),className:()=>(0,c.default)({[`${w}-rtl`]:null!=f?f:"rtl"===b}),motion:()=>({motionName:null!=p?p:`${w}-move-up`}),closable:!1,closeIcon:C,duration:u,getContainer:()=>(null==i?void 0:i())||(null==h?void 0:h())||document.body,maxCount:l,onAllRemoved:m,renderNotifications:y});return r.useImperativeHandle(t,()=>Object.assign(Object.assign({},x),{prefixCls:w,message:v})),S}),w=0;function C(e){let t=r.useRef(null);return(0,f.devUseWarning)("Message"),[r.useMemo(()=>{let e=e=>{var r;null==(r=t.current)||r.close(e)},n=n=>{if(!t.current){let e=()=>{};return e.then=()=>{},e}let{open:o,prefixCls:a,message:i}=t.current,s=`${a}-notice`,{content:u,icon:d,type:f,key:p,className:m,style:v,onClose:y}=n,b=h(n,["content","icon","type","key","className","style","onClose"]),C=p;return null==C&&(w+=1,C=`antd-message-${w}`),g(t=>(o(Object.assign(Object.assign({},b),{key:C,content:r.createElement(l.PureContent,{prefixCls:a,type:f,icon:d},u),placement:"top",className:(0,c.default)(f&&`${s}-${f}`,m,null==i?void 0:i.className),style:Object.assign(Object.assign({},null==i?void 0:i.style),v),onClose:()=>{null==y||y(),t()}})),()=>{e(C)}))},o={open:n,destroy:r=>{var n;void 0!==r?e(r):null==(n=t.current)||n.destroy()}};return["info","success","warning","error","loading"].forEach(e=>{o[e]=(t,r,o)=>{let a,i,l;return a=t&&"object"==typeof t&&"content"in t?t:{content:t},"function"==typeof r?l=r:(i=r,l=o),n(Object.assign(Object.assign({onClose:l,duration:i},a),{type:e}))}}),o},[]),r.createElement(b,Object.assign({key:"message-holder"},e,{ref:t}))]}let x=null,S=[],$={};function E(){let{getContainer:e,duration:t,rtl:r,maxCount:n,top:o}=$,a=(null==e?void 0:e())||document.body;return{getContainer:()=>a,duration:t,rtl:r,maxCount:n,top:o}}let k=r.default.forwardRef((e,t)=>{let{messageConfig:o,sync:i}=e,{getPrefixCls:l}=(0,r.useContext)(a.ConfigContext),s=$.prefixCls||l("message"),c=(0,r.useContext)(n.AppConfigContext),[u,d]=C(Object.assign(Object.assign(Object.assign({},o),{prefixCls:s}),c.message));return r.default.useImperativeHandle(t,()=>{let e=Object.assign({},u);return Object.keys(e).forEach(t=>{e[t]=(...e)=>(i(),u[t].apply(u,e))}),{instance:e,sync:i}}),d}),O=r.default.forwardRef((e,t)=>{let[n,a]=r.default.useState(E),i=()=>{a(E)};r.default.useEffect(i,[]);let l=(0,o.globalConfig)(),s=l.getRootPrefixCls(),c=l.getIconPrefixCls(),u=l.getTheme(),d=r.default.createElement(k,{ref:t,sync:i,messageConfig:n});return r.default.createElement(o.default,{prefixCls:s,iconPrefixCls:c,theme:u},l.holderRender?l.holderRender(d):d)}),j=()=>{if(!x){let e=document.createDocumentFragment(),t={fragment:e};x=t,(()=>{(0,i.unstableSetRender)()(r.default.createElement(O,{ref:e=>{let{instance:r,sync:n}=e||{};Promise.resolve().then(()=>{!t.instance&&r&&(t.instance=r,t.sync=n,j())})}}),e)})();return}x.instance&&(S.forEach(e=>{let{type:r,skipped:n}=e;if(!n)switch(r){case"open":{let t=x.instance.open(Object.assign(Object.assign({},$),e.config));null==t||t.then(e.resolve),e.setCloseFn(t)}break;case"destroy":null==x||x.instance.destroy(e.key);break;default:{var o;let n=(o=x.instance)[r].apply(o,(0,t.default)(e.args));null==n||n.then(e.resolve),e.setCloseFn(n)}}}),S=[])},T={open:function(e){let t=g(t=>{let r,n={type:"open",config:e,resolve:t,setCloseFn:e=>{r=e}};return S.push(n),()=>{r?(()=>{r()})():n.skipped=!0}});return j(),t},destroy:e=>{S.push({type:"destroy",key:e}),j()},config:function(e){$=Object.assign(Object.assign({},$),e),(()=>{var e;null==(e=null==x?void 0:x.sync)||e.call(x)})()},useMessage:function(e){return C(e)},_InternalPanelDoNotUseOrYouWillBeFired:l.default};["success","info","warning","error","loading"].forEach(e=>{T[e]=(...t)=>{let r;return(0,o.globalConfig)(),r=g(r=>{let n,o={type:e,args:t,resolve:r,setCloseFn:e=>{n=e}};return S.push(o),()=>{n?(()=>{n()})():o.skipped=!0}}),j(),r}});e.s(["message",0,T],998573);let _=null;e.s(["default",0,{success(e,t){(_||T).success(e,t)},error(e,t){(_||T).error(e,t)},warning(e,t){(_||T).warning(e,t)},info(e,t){(_||T).info(e,t)},loading:(e,t)=>(_||T).loading(e,t),destroy(){(_||T).destroy()}},"setMessageInstance",0,e=>{_=e}],888259)},947293,e=>{"use strict";class t extends Error{}function r(e,r){let n;if("string"!=typeof e)throw new t("Invalid token specified: must be a string");r||(r={});let o=+(!0!==r.header),a=e.split(".")[o];if("string"!=typeof a)throw new t(`Invalid token specified: missing part #${o+1}`);try{n=function(e){let t=e.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:t+="==";break;case 3:t+="=";break;default:throw Error("base64 string is not of the correct length")}try{var r;return r=t,decodeURIComponent(atob(r).replace(/(.)/g,(e,t)=>{let r=t.charCodeAt(0).toString(16).toUpperCase();return r.length<2&&(r="0"+r),"%"+r}))}catch(e){return atob(t)}}(a)}catch(e){throw new t(`Invalid token specified: invalid base64 for part #${o+1} (${e.message})`)}try{return JSON.parse(n)}catch(e){throw new t(`Invalid token specified: invalid json for part #${o+1} (${e.message})`)}}t.prototype.name="InvalidTokenError",e.s(["jwtDecode",()=>r])},268004,909119,e=>{"use strict";let t="mcp-session-token:";function r(e,r){let n=r?.trim()||"_anonymous";return`${t}${n}:${e}`}function n(e,t,n){let o={access_token:t.access_token,expires_at:Date.now()+(null!=t.expires_in?1e3*t.expires_in:36e5),token_type:t.token_type??"bearer",...t.refresh_token?{refresh_token:t.refresh_token}:{}};try{window.sessionStorage.setItem(r(e,n),JSON.stringify(o))}catch{}}function o(e,t){try{let n=window.sessionStorage.getItem(r(e,t));if(!n)return null;return JSON.parse(n)}catch{return null}}function a(e,t){try{window.sessionStorage.removeItem(r(e,t))}catch{}}function i(e,t){let r=o(e,t);return!!r&&r.expires_at>Date.now()}function l(){try{let e=[];for(let r=0;rwindow.sessionStorage.removeItem(e))}catch{}}function s(){let e=window.location.pathname.match(/\/ui(?=\/|$)/);return e&&void 0!==e.index?window.location.pathname.substring(0,e.index+3):"/ui"}function c(){if("u"{document.cookie=`token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${t};`,document.cookie=`token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${t}; domain=${e};`,n.forEach(r=>{let n="None"===r?" Secure;":"";document.cookie=`token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${t}; SameSite=${r};${n}`,document.cookie=`token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${t}; domain=${e}; SameSite=${r};${n}`})});try{sessionStorage.removeItem("token")}catch{}l()}function u(e){if(e&&e.trim()){try{let t="https:"===window.location.protocol?"; Secure":"",r=s();document.cookie=`token=${encodeURIComponent(e)}; path=${r}; SameSite=Lax${t}`}catch{}try{sessionStorage.setItem("token",e)}catch{}}}function d(e){if("u"t.startsWith(e+"="));if(!t)return null;let r=t.split("=").slice(1).join("=");try{return decodeURIComponent(r)}catch{return r}}function f(e){let t=d(e);if(null!==t)return t;if("token"===e)try{return sessionStorage.getItem(e)}catch{}return null}e.s(["clearAllMcpTokens",()=>l,"getToken",()=>o,"isTokenValid",()=>i,"removeToken",()=>a,"setToken",()=>n],909119),e.s(["clearTokenCookies",()=>c,"getCookie",()=>f,"getCookieFromDocument",()=>d,"storeLoginToken",()=>u],268004)},876556,e=>{"use strict";var t=e.i(565924),r=e.i(271645);e.s(["default",()=>function e(n){var o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=[];return r.default.Children.forEach(n,function(r){(null!=r||o.keepEmpty)&&(Array.isArray(r)?a=a.concat(e(r)):(0,t.default)(r)&&r.props?a=a.concat(e(r.props.children,o)):a.push(r))}),a}])},495347,177886,786944,162129,197091,787894,696752,621796,e=>{"use strict";var t,r=e.i(271645);e.i(247167);var n=e.i(931067),o=e.i(703923),a=e.i(31575),i=e.i(33968),l=e.i(209428),s=e.i(8211),c=e.i(278409),u=e.i(233848),d=e.i(971151),f=e.i(868917),p=e.i(674813),m=e.i(211577),g=e.i(876556),h=e.i(929123),v=e.i(883110),y="RC_FORM_INTERNAL_HOOKS",b=function(){(0,v.default)(!1,"Can not find FormContext. Please make sure you wrap Field under Form.")},w=r.createContext({getFieldValue:b,getFieldsValue:b,getFieldError:b,getFieldWarning:b,getFieldsError:b,isFieldsTouched:b,isFieldTouched:b,isFieldValidating:b,isFieldsValidating:b,resetFields:b,setFields:b,setFieldValue:b,setFieldsValue:b,validateFields:b,submit:b,getInternalHooks:function(){return b(),{dispatch:b,initEntityValue:b,registerField:b,useSubscribe:b,setInitialValues:b,destroyForm:b,setCallbacks:b,registerWatch:b,getFields:b,setValidateMessages:b,setPreserve:b,getInitialValue:b}}});e.s(["HOOK_MARK",()=>y,"default",0,w],177886);var C=r.createContext(null);function x(e){return null==e?[]:Array.isArray(e)?e:[e]}e.s(["default",0,C],786944);var S=e.i(410160);function $(){return{default:"Validation error on field %s",required:"%s is required",enum:"%s must be one of %s",whitespace:"%s cannot be empty",date:{format:"%s date %s is invalid for format %s",parse:"%s date could not be parsed, %s is invalid ",invalid:"%s date %s is invalid"},types:{string:"%s is not a %s",method:"%s is not a %s (function)",array:"%s is not an %s",object:"%s is not an %s",number:"%s is not a %s",date:"%s is not a %s",boolean:"%s is not a %s",integer:"%s is not an %s",float:"%s is not a %s",regexp:"%s is not a valid %s",email:"%s is not a valid %s",tel:"%s is not a valid %s",url:"%s is not a valid %s",hex:"%s is not a valid %s"},string:{len:"%s must be exactly %s characters",min:"%s must be at least %s characters",max:"%s cannot be longer than %s characters",range:"%s must be between %s and %s characters"},number:{len:"%s must equal %s",min:"%s cannot be less than %s",max:"%s cannot be greater than %s",range:"%s must be between %s and %s"},array:{len:"%s must be exactly %s in length",min:"%s cannot be less than %s in length",max:"%s cannot be greater than %s in length",range:"%s must be between %s and %s in length"},pattern:{mismatch:"%s value %s does not match pattern %s"},clone:function(){var e=JSON.parse(JSON.stringify(this));return e.clone=this.clone,e}}}var E=$(),k=e.i(487806),O=e.i(885963),j=e.i(479671);function T(e){var t="function"==typeof Map?new Map:void 0;return(T=function(e){if(null===e||!function(e){try{return -1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return function(e,t,r){if((0,j.default)())return Reflect.construct.apply(null,arguments);var n=[null];n.push.apply(n,t);var o=new(e.bind.apply(e,n));return r&&(0,O.default)(o,r.prototype),o}(e,arguments,(0,k.default)(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),(0,O.default)(r,e)})(e)}var _=/%[sdj%]/g;function P(e){if(!e||!e.length)return null;var t={};return e.forEach(function(e){var r=e.field;t[r]=t[r]||[],t[r].push(e)}),t}function I(e){for(var t=arguments.length,r=Array(t>1?t-1:0),n=1;n=a)return e;switch(e){case"%s":return String(r[o++]);case"%d":return Number(r[o++]);case"%j":try{return JSON.stringify(r[o++])}catch(e){return"[Circular]"}default:return e}}):e}function F(e,t){return!!(null==e||"array"===t&&Array.isArray(e)&&!e.length)||("string"===t||"url"===t||"hex"===t||"email"===t||"date"===t||"pattern"===t||"tel"===t)&&"string"==typeof e&&!e||!1}function N(e,t,r){var n=0,o=e.length;!function a(i){if(i&&i.length)return void r(i);var l=n;n+=1,l()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,D=/^(\+[0-9]{1,3}[-\s\u2011]?)?(\([0-9]{1,4}\)[-\s\u2011]?)?([0-9]+[-\s\u2011]?)*[0-9]+$/,V=/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i,W={integer:function(e){return W.number(e)&&parseInt(e,10)===e},float:function(e){return W.number(e)&&!W.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return new RegExp(e),!0}catch(e){return!1}},date:function(e){return"function"==typeof e.getTime&&"function"==typeof e.getMonth&&"function"==typeof e.getYear&&!isNaN(e.getTime())},number:function(e){return!isNaN(e)&&"number"==typeof e},object:function(e){return"object"===(0,S.default)(e)&&!W.array(e)},method:function(e){return"function"==typeof e},email:function(e){return"string"==typeof e&&e.length<=320&&!!e.match(H)},tel:function(e){return"string"==typeof e&&e.length<=32&&!!e.match(D)},url:function(e){return"string"==typeof e&&e.length<=2048&&!!e.match(L())},hex:function(e){return"string"==typeof e&&!!e.match(V)}};let U=z,G=function(e,t,r,n,o){(/^\s+$/.test(t)||""===t)&&n.push(I(o.messages.whitespace,e.fullField))},q=function(e,t,r,n,o){if(e.required&&void 0===t)return void z(e,t,r,n,o);var a=e.type;["integer","float","array","regexp","object","method","email","tel","number","date","url","hex"].indexOf(a)>-1?W[a](t)||n.push(I(o.messages.types[a],e.fullField,e.type)):a&&(0,S.default)(t)!==e.type&&n.push(I(o.messages.types[a],e.fullField,e.type))},K=function(e,t,r,n,o){var a="number"==typeof e.len,i="number"==typeof e.min,l="number"==typeof e.max,s=t,c=null,u="number"==typeof t,d="string"==typeof t,f=Array.isArray(t);if(u?c="number":d?c="string":f&&(c="array"),!c)return!1;f&&(s=t.length),d&&(s=t.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"_").length),a?s!==e.len&&n.push(I(o.messages[c].len,e.fullField,e.len)):i&&!l&&se.max?n.push(I(o.messages[c].max,e.fullField,e.max)):i&&l&&(se.max)&&n.push(I(o.messages[c].range,e.fullField,e.min,e.max))},X=function(e,t,r,n,o){e[B]=Array.isArray(e[B])?e[B]:[],-1===e[B].indexOf(t)&&n.push(I(o.messages[B],e.fullField,e[B].join(", ")))},J=function(e,t,r,n,o){e.pattern&&(e.pattern instanceof RegExp?(e.pattern.lastIndex=0,e.pattern.test(t)||n.push(I(o.messages.pattern.mismatch,e.fullField,t,e.pattern))):"string"==typeof e.pattern&&(new RegExp(e.pattern).test(t)||n.push(I(o.messages.pattern.mismatch,e.fullField,t,e.pattern))))},Y=function(e,t,r,n,o){var a=e.type,i=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t,a)&&!e.required)return r();U(e,t,n,i,o,a),F(t,a)||q(e,t,n,i,o)}r(i)},Q={string:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t,"string")&&!e.required)return r();U(e,t,n,a,o,"string"),F(t,"string")||(q(e,t,n,a,o),K(e,t,n,a,o),J(e,t,n,a,o),!0===e.whitespace&&G(e,t,n,a,o))}r(a)},method:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o),void 0!==t&&q(e,t,n,a,o)}r(a)},number:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(""===t&&(t=void 0),F(t)&&!e.required)return r();U(e,t,n,a,o),void 0!==t&&(q(e,t,n,a,o),K(e,t,n,a,o))}r(a)},boolean:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o),void 0!==t&&q(e,t,n,a,o)}r(a)},regexp:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o),F(t)||q(e,t,n,a,o)}r(a)},integer:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o),void 0!==t&&(q(e,t,n,a,o),K(e,t,n,a,o))}r(a)},float:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o),void 0!==t&&(q(e,t,n,a,o),K(e,t,n,a,o))}r(a)},array:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(null==t&&!e.required)return r();U(e,t,n,a,o,"array"),null!=t&&(q(e,t,n,a,o),K(e,t,n,a,o))}r(a)},object:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o),void 0!==t&&q(e,t,n,a,o)}r(a)},enum:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o),void 0!==t&&X(e,t,n,a,o)}r(a)},pattern:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t,"string")&&!e.required)return r();U(e,t,n,a,o),F(t,"string")||J(e,t,n,a,o)}r(a)},date:function(e,t,r,n,o){var a,i=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t,"date")&&!e.required)return r();U(e,t,n,i,o),!F(t,"date")&&(a=t instanceof Date?t:new Date(t),q(e,a,n,i,o),a&&K(e,a.getTime(),n,i,o))}r(i)},url:Y,hex:Y,email:Y,tel:Y,required:function(e,t,r,n,o){var a=[],i=Array.isArray(t)?"array":(0,S.default)(t);U(e,t,n,a,o,i),r(a)},any:function(e,t,r,n,o){var a=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(F(t)&&!e.required)return r();U(e,t,n,a,o)}r(a)}};var Z=function(){function e(t){(0,c.default)(this,e),(0,m.default)(this,"rules",null),(0,m.default)(this,"_messages",E),this.define(t)}return(0,u.default)(e,[{key:"define",value:function(e){var t=this;if(!e)throw Error("Cannot configure a schema with no rules");if("object"!==(0,S.default)(e)||Array.isArray(e))throw Error("Rules must be an object");this.rules={},Object.keys(e).forEach(function(r){var n=e[r];t.rules[r]=Array.isArray(n)?n:[n]})}},{key:"messages",value:function(e){return e&&(this._messages=A($(),e)),this._messages}},{key:"validate",value:function(t){var r=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},a=t,i=n,c=o;if("function"==typeof i&&(c=i,i={}),!this.rules||0===Object.keys(this.rules).length)return c&&c(null,a),Promise.resolve(a);if(i.messages){var u=this.messages();u===E&&(u=$()),A(u,i.messages),i.messages=u}else i.messages=this.messages();var d={};(i.keys||Object.keys(this.rules)).forEach(function(e){var n=r.rules[e],o=a[e];n.forEach(function(n){var i=n;"function"==typeof i.transform&&(a===t&&(a=(0,l.default)({},a)),null!=(o=a[e]=i.transform(o))&&(i.type=i.type||(Array.isArray(o)?"array":(0,S.default)(o)))),(i="function"==typeof i?{validator:i}:(0,l.default)({},i)).validator=r.getValidationMethod(i),i.validator&&(i.field=e,i.fullField=i.fullField||e,i.type=r.getType(i),d[e]=d[e]||[],d[e].push({rule:i,value:o,source:a,field:e}))})});var f={};return function(e,t,r,n,o){if(t.first){var a=new Promise(function(t,a){var i;N((i=[],Object.keys(e).forEach(function(t){i.push.apply(i,(0,s.default)(e[t]||[]))}),i),r,function(e){return n(e),e.length?a(new R(e,P(e))):t(o)})});return a.catch(function(e){return e}),a}var i=!0===t.firstFields?Object.keys(e):t.firstFields||[],l=Object.keys(e),c=l.length,u=0,d=[],f=new Promise(function(t,a){var f=function(e){if(d.push.apply(d,e),++u===c)return n(d),d.length?a(new R(d,P(d))):t(o)};l.length||(n(d),t(o)),l.forEach(function(t){var n=e[t];if(-1!==i.indexOf(t))N(n,r,f);else{var o=[],a=0,l=n.length;function c(e){o.push.apply(o,(0,s.default)(e||[])),++a===l&&f(o)}n.forEach(function(e){r(e,c)})}})});return f.catch(function(e){return e}),f}(d,i,function(t,r){var n,o,c,u=t.rule,d=("object"===u.type||"array"===u.type)&&("object"===(0,S.default)(u.fields)||"object"===(0,S.default)(u.defaultField));function p(e,t){return(0,l.default)((0,l.default)({},t),{},{fullField:"".concat(u.fullField,".").concat(e),fullFields:u.fullFields?[].concat((0,s.default)(u.fullFields),[e]):[e]})}function m(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],o=Array.isArray(n)?n:[n];!i.suppressWarning&&o.length&&e.warning("async-validator:",o),o.length&&void 0!==u.message&&null!==u.message&&(o=[].concat(u.message));var c=o.map(M(u,a));if(i.first&&c.length)return f[u.field]=1,r(c);if(d){if(u.required&&!t.value)return void 0!==u.message?c=[].concat(u.message).map(M(u,a)):i.error&&(c=[i.error(u,I(i.messages.required,u.field))]),r(c);var m={};u.defaultField&&Object.keys(t.value).map(function(e){m[e]=u.defaultField});var g={};Object.keys(m=(0,l.default)((0,l.default)({},m),t.rule.fields)).forEach(function(e){var t=m[e],r=Array.isArray(t)?t:[t];g[e]=r.map(p.bind(null,e))});var h=new e(g);h.messages(i.messages),t.rule.options&&(t.rule.options.messages=i.messages,t.rule.options.error=i.error),h.validate(t.value,t.rule.options||i,function(e){var t=[];c&&c.length&&t.push.apply(t,(0,s.default)(c)),e&&e.length&&t.push.apply(t,(0,s.default)(e)),r(t.length?t:null)})}else r(c)}if(d=d&&(u.required||!u.required&&t.value),u.field=t.field,u.asyncValidator)n=u.asyncValidator(u,t.value,m,t.source,i);else if(u.validator){try{n=u.validator(u,t.value,m,t.source,i)}catch(e){null==(o=(c=console).error)||o.call(c,e),i.suppressValidatorError||setTimeout(function(){throw e},0),m(e.message)}!0===n?m():!1===n?m("function"==typeof u.message?u.message(u.fullField||u.field):u.message||"".concat(u.fullField||u.field," fails")):n instanceof Array?m(n):n instanceof Error&&m(n.message)}n&&n.then&&n.then(function(){return m()},function(e){return m(e)})},function(e){for(var t=[],r={},n=0;n0)){e.next=23;break}return e.next=21,Promise.all(n.map(function(e,r){return eo("".concat(t,".").concat(r),e,f,i,c)}));case 21:return v=e.sent,e.abrupt("return",v.reduce(function(e,t){return[].concat((0,s.default)(e),(0,s.default)(t))},[]));case 23:return y=(0,l.default)((0,l.default)({},o),{},{name:t,enum:(o.enum||[]).join(", ")},c),b=h.map(function(e){return"string"==typeof e?function(e,t){return e.replace(/\\?\$\{\w+\}/g,function(e){return e.startsWith("\\")?e.slice(1):t[e.slice(2,-1)]})}(e,y):e}),e.abrupt("return",b);case 26:case"end":return e.stop()}},e,null,[[10,15]])}))).apply(this,arguments)}function ei(){return(ei=(0,i.default)((0,a.default)().mark(function e(t){return(0,a.default)().wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",Promise.all(t).then(function(e){var t;return(t=[]).concat.apply(t,(0,s.default)(e))}));case 1:case"end":return e.stop()}},e)}))).apply(this,arguments)}function el(){return(el=(0,i.default)((0,a.default)().mark(function e(t){var r;return(0,a.default)().wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return r=0,e.abrupt("return",new Promise(function(e){t.forEach(function(n){n.then(function(n){n.errors.length&&e([n]),(r+=1)===t.length&&e([])})})}));case 2:case"end":return e.stop()}},e)}))).apply(this,arguments)}var es=e.i(657791);function ec(e){return x(e)}function eu(e,t){var r={};return t.forEach(function(t){var n=(0,es.default)(e,t);r=(0,er.default)(r,t,n)}),r}function ed(e,t){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return e&&e.some(function(e){return ef(t,e,r)})}function ef(e,t){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return!!e&&!!t&&(!!r||e.length===t.length)&&t.every(function(t,r){return e[r]===t})}function ep(e){var t=arguments.length<=1?void 0:arguments[1];return t&&t.target&&"object"===(0,S.default)(t.target)&&e in t.target?t.target[e]:t}function em(e,t,r){var n=e.length;if(t<0||t>=n||r<0||r>=n)return e;var o=e[t],a=t-r;return a>0?[].concat((0,s.default)(e.slice(0,r)),[o],(0,s.default)(e.slice(r,t)),(0,s.default)(e.slice(t+1,n))):a<0?[].concat((0,s.default)(e.slice(0,t)),(0,s.default)(e.slice(t+1,r+1)),[o],(0,s.default)(e.slice(r+1,n))):e}var eg=es,eh=["name"],ev=[];function ey(e,t,r,n,o,a){return"function"==typeof e?e(t,r,"source"in a?{source:a.source}:{}):n!==o}var eb=function(e){(0,f.default)(n,e);var t=(0,p.default)(n);function n(e){var o;return(0,c.default)(this,n),o=t.call(this,e),(0,m.default)((0,d.default)(o),"state",{resetCount:0}),(0,m.default)((0,d.default)(o),"cancelRegisterFunc",null),(0,m.default)((0,d.default)(o),"mounted",!1),(0,m.default)((0,d.default)(o),"touched",!1),(0,m.default)((0,d.default)(o),"dirty",!1),(0,m.default)((0,d.default)(o),"validatePromise",void 0),(0,m.default)((0,d.default)(o),"prevValidating",void 0),(0,m.default)((0,d.default)(o),"errors",ev),(0,m.default)((0,d.default)(o),"warnings",ev),(0,m.default)((0,d.default)(o),"cancelRegister",function(){var e=o.props,t=e.preserve,r=e.isListField,n=e.name;o.cancelRegisterFunc&&o.cancelRegisterFunc(r,t,ec(n)),o.cancelRegisterFunc=null}),(0,m.default)((0,d.default)(o),"getNamePath",function(){var e=o.props,t=e.name,r=e.fieldContext.prefixName;return void 0!==t?[].concat((0,s.default)(void 0===r?[]:r),(0,s.default)(t)):[]}),(0,m.default)((0,d.default)(o),"getRules",function(){var e=o.props,t=e.rules,r=e.fieldContext;return(void 0===t?[]:t).map(function(e){return"function"==typeof e?e(r):e})}),(0,m.default)((0,d.default)(o),"refresh",function(){o.mounted&&o.setState(function(e){return{resetCount:e.resetCount+1}})}),(0,m.default)((0,d.default)(o),"metaCache",null),(0,m.default)((0,d.default)(o),"triggerMetaEvent",function(e){var t=o.props.onMetaChange;if(t){var r=(0,l.default)((0,l.default)({},o.getMeta()),{},{destroy:e});(0,h.default)(o.metaCache,r)||t(r),o.metaCache=r}else o.metaCache=null}),(0,m.default)((0,d.default)(o),"onStoreChange",function(e,t,r){var n=o.props,a=n.shouldUpdate,i=n.dependencies,l=void 0===i?[]:i,s=n.onReset,c=r.store,u=o.getNamePath(),d=o.getValue(e),f=o.getValue(c),p=t&&ed(t,u);switch("valueUpdate"===r.type&&"external"===r.source&&!(0,h.default)(d,f)&&(o.touched=!0,o.dirty=!0,o.validatePromise=null,o.errors=ev,o.warnings=ev,o.triggerMetaEvent()),r.type){case"reset":if(!t||p){o.touched=!1,o.dirty=!1,o.validatePromise=void 0,o.errors=ev,o.warnings=ev,o.triggerMetaEvent(),null==s||s(),o.refresh();return}break;case"remove":if(a&&ey(a,e,c,d,f,r))return void o.reRender();break;case"setField":var m=r.data;if(p){"touched"in m&&(o.touched=m.touched),"validating"in m&&!("originRCField"in m)&&(o.validatePromise=m.validating?Promise.resolve([]):null),"errors"in m&&(o.errors=m.errors||ev),"warnings"in m&&(o.warnings=m.warnings||ev),o.dirty=!0,o.triggerMetaEvent(),o.reRender();return}if("value"in m&&ed(t,u,!0)||a&&!u.length&&ey(a,e,c,d,f,r))return void o.reRender();break;case"dependenciesUpdate":if(l.map(ec).some(function(e){return ed(r.relatedFields,e)}))return void o.reRender();break;default:if(p||(!l.length||u.length||a)&&ey(a,e,c,d,f,r))return void o.reRender()}!0===a&&o.reRender()}),(0,m.default)((0,d.default)(o),"validateRules",function(e){var t=o.getNamePath(),r=o.getValue(),n=e||{},c=n.triggerName,u=n.validateOnly,d=Promise.resolve().then((0,i.default)((0,a.default)().mark(function n(){var u,f,p,m,g,h,y;return(0,a.default)().wrap(function(n){for(;;)switch(n.prev=n.next){case 0:if(o.mounted){n.next=2;break}return n.abrupt("return",[]);case 2:if(p=void 0!==(f=(u=o.props).validateFirst)&&f,m=u.messageVariables,g=u.validateDebounce,h=o.getRules(),c&&(h=h.filter(function(e){return e}).filter(function(e){var t=e.validateTrigger;return!t||x(t).includes(c)})),!(g&&c)){n.next=10;break}return n.next=8,new Promise(function(e){setTimeout(e,g)});case 8:if(o.validatePromise===d){n.next=10;break}return n.abrupt("return",[]);case 10:return(y=function(e,t,r,n,o,s){var c,u,d=e.join("."),f=r.map(function(e,t){var r=e.validator,n=(0,l.default)((0,l.default)({},e),{},{ruleIndex:t});return r&&(n.validator=function(e,t,n){var o=!1,a=r(e,t,function(){for(var e=arguments.length,t=Array(e),r=0;r0&&void 0!==arguments[0]?arguments[0]:ev;if(o.validatePromise===d){o.validatePromise=null;var t,r=[],n=[];null==(t=e.forEach)||t.call(e,function(e){var t=e.rule.warningOnly,o=e.errors,a=void 0===o?ev:o;t?n.push.apply(n,(0,s.default)(a)):r.push.apply(r,(0,s.default)(a))}),o.errors=r,o.warnings=n,o.triggerMetaEvent(),o.reRender()}}),n.abrupt("return",y);case 13:case"end":return n.stop()}},n)})));return void 0!==u&&u||(o.validatePromise=d,o.dirty=!0,o.errors=ev,o.warnings=ev,o.triggerMetaEvent(),o.reRender()),d}),(0,m.default)((0,d.default)(o),"isFieldValidating",function(){return!!o.validatePromise}),(0,m.default)((0,d.default)(o),"isFieldTouched",function(){return o.touched}),(0,m.default)((0,d.default)(o),"isFieldDirty",function(){return!!o.dirty||void 0!==o.props.initialValue||void 0!==(0,o.props.fieldContext.getInternalHooks(y).getInitialValue)(o.getNamePath())}),(0,m.default)((0,d.default)(o),"getErrors",function(){return o.errors}),(0,m.default)((0,d.default)(o),"getWarnings",function(){return o.warnings}),(0,m.default)((0,d.default)(o),"isListField",function(){return o.props.isListField}),(0,m.default)((0,d.default)(o),"isList",function(){return o.props.isList}),(0,m.default)((0,d.default)(o),"isPreserve",function(){return o.props.preserve}),(0,m.default)((0,d.default)(o),"getMeta",function(){return o.prevValidating=o.isFieldValidating(),{touched:o.isFieldTouched(),validating:o.prevValidating,errors:o.errors,warnings:o.warnings,name:o.getNamePath(),validated:null===o.validatePromise}}),(0,m.default)((0,d.default)(o),"getOnlyChild",function(e){if("function"==typeof e){var t=o.getMeta();return(0,l.default)((0,l.default)({},o.getOnlyChild(e(o.getControlled(),t,o.props.fieldContext))),{},{isFunction:!0})}var n=(0,g.default)(e);return 1===n.length&&r.isValidElement(n[0])?{child:n[0],isFunction:!1}:{child:n,isFunction:!1}}),(0,m.default)((0,d.default)(o),"getValue",function(e){var t=o.props.fieldContext.getFieldsValue,r=o.getNamePath();return(0,eg.default)(e||t(!0),r)}),(0,m.default)((0,d.default)(o),"getControlled",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=o.props,r=t.name,n=t.trigger,a=t.validateTrigger,i=t.getValueFromEvent,s=t.normalize,c=t.valuePropName,u=t.getValueProps,d=t.fieldContext,f=void 0!==a?a:d.validateTrigger,p=o.getNamePath(),g=d.getInternalHooks,h=d.getFieldsValue,v=g(y).dispatch,b=o.getValue(),w=u||function(e){return(0,m.default)({},c,e)},C=e[n],S=void 0!==r?w(b):{},$=(0,l.default)((0,l.default)({},e),S);return $[n]=function(){o.touched=!0,o.dirty=!0,o.triggerMetaEvent();for(var e,t=arguments.length,r=Array(t),n=0;n=0&&t<=r.length?(f.keys=[].concat((0,s.default)(f.keys.slice(0,t)),[f.id],(0,s.default)(f.keys.slice(t))),n([].concat((0,s.default)(r.slice(0,t)),[e],(0,s.default)(r.slice(t))))):(f.keys=[].concat((0,s.default)(f.keys),[f.id]),n([].concat((0,s.default)(r),[e]))),f.id+=1},remove:function(e){var t=i(),r=new Set(Array.isArray(e)?e:[e]);r.size<=0||(f.keys=f.keys.filter(function(e,t){return!r.has(t)}),n(t.filter(function(e,t){return!r.has(t)})))},move:function(e,t){if(e!==t){var r=i();e<0||e>=r.length||t<0||t>=r.length||(f.keys=em(f.keys,e,t),n(em(r,e,t)))}}},t)})))};e.s(["default",0,eC],197091);var ex=e.i(392221),eS="__@field_split__";function e$(e){return e.map(function(e){return"".concat((0,S.default)(e),":").concat(e)}).join(eS)}var eE=function(){function e(){(0,c.default)(this,e),(0,m.default)(this,"kvs",new Map)}return(0,u.default)(e,[{key:"set",value:function(e,t){this.kvs.set(e$(e),t)}},{key:"get",value:function(e){return this.kvs.get(e$(e))}},{key:"update",value:function(e,t){var r=t(this.get(e));r?this.set(e,r):this.delete(e)}},{key:"delete",value:function(e){this.kvs.delete(e$(e))}},{key:"map",value:function(e){return(0,s.default)(this.kvs.entries()).map(function(t){var r=(0,ex.default)(t,2),n=r[0],o=r[1];return e({key:n.split(eS).map(function(e){var t=e.match(/^([^:]*):(.*)$/),r=(0,ex.default)(t,3),n=r[1],o=r[2];return"number"===n?Number(o):o}),value:o})})}},{key:"toJSON",value:function(){var e={};return this.map(function(t){var r=t.key,n=t.value;return e[r.join(".")]=n,null}),e}}]),e}(),eg=es,ek=["name"],eO=(0,u.default)(function e(t){var r=this;(0,c.default)(this,e),(0,m.default)(this,"formHooked",!1),(0,m.default)(this,"forceRootUpdate",void 0),(0,m.default)(this,"subscribable",!0),(0,m.default)(this,"store",{}),(0,m.default)(this,"fieldEntities",[]),(0,m.default)(this,"initialValues",{}),(0,m.default)(this,"callbacks",{}),(0,m.default)(this,"validateMessages",null),(0,m.default)(this,"preserve",null),(0,m.default)(this,"lastValidatePromise",null),(0,m.default)(this,"getForm",function(){return{getFieldValue:r.getFieldValue,getFieldsValue:r.getFieldsValue,getFieldError:r.getFieldError,getFieldWarning:r.getFieldWarning,getFieldsError:r.getFieldsError,isFieldsTouched:r.isFieldsTouched,isFieldTouched:r.isFieldTouched,isFieldValidating:r.isFieldValidating,isFieldsValidating:r.isFieldsValidating,resetFields:r.resetFields,setFields:r.setFields,setFieldValue:r.setFieldValue,setFieldsValue:r.setFieldsValue,validateFields:r.validateFields,submit:r.submit,_init:!0,getInternalHooks:r.getInternalHooks}}),(0,m.default)(this,"getInternalHooks",function(e){return e===y?(r.formHooked=!0,{dispatch:r.dispatch,initEntityValue:r.initEntityValue,registerField:r.registerField,useSubscribe:r.useSubscribe,setInitialValues:r.setInitialValues,destroyForm:r.destroyForm,setCallbacks:r.setCallbacks,setValidateMessages:r.setValidateMessages,getFields:r.getFields,setPreserve:r.setPreserve,getInitialValue:r.getInitialValue,registerWatch:r.registerWatch}):((0,v.default)(!1,"`getInternalHooks` is internal usage. Should not call directly."),null)}),(0,m.default)(this,"useSubscribe",function(e){r.subscribable=e}),(0,m.default)(this,"prevWithoutPreserves",null),(0,m.default)(this,"setInitialValues",function(e,t){if(r.initialValues=e||{},t){var n,o=(0,er.merge)(e,r.store);null==(n=r.prevWithoutPreserves)||n.map(function(t){var r=t.key;o=(0,er.default)(o,r,(0,eg.default)(e,r))}),r.prevWithoutPreserves=null,r.updateStore(o)}}),(0,m.default)(this,"destroyForm",function(e){if(e)r.updateStore({});else{var t=new eE;r.getFieldEntities(!0).forEach(function(e){r.isMergedPreserve(e.isPreserve())||t.set(e.getNamePath(),!0)}),r.prevWithoutPreserves=t}}),(0,m.default)(this,"getInitialValue",function(e){var t=(0,eg.default)(r.initialValues,e);return e.length?(0,er.merge)(t):t}),(0,m.default)(this,"setCallbacks",function(e){r.callbacks=e}),(0,m.default)(this,"setValidateMessages",function(e){r.validateMessages=e}),(0,m.default)(this,"setPreserve",function(e){r.preserve=e}),(0,m.default)(this,"watchList",[]),(0,m.default)(this,"registerWatch",function(e){return r.watchList.push(e),function(){r.watchList=r.watchList.filter(function(t){return t!==e})}}),(0,m.default)(this,"notifyWatch",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];if(r.watchList.length){var t=r.getFieldsValue(),n=r.getFieldsValue(!0);r.watchList.forEach(function(r){r(t,n,e)})}}),(0,m.default)(this,"timeoutId",null),(0,m.default)(this,"warningUnhooked",function(){}),(0,m.default)(this,"updateStore",function(e){r.store=e}),(0,m.default)(this,"getFieldEntities",function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return e?r.fieldEntities.filter(function(e){return e.getNamePath().length}):r.fieldEntities}),(0,m.default)(this,"getFieldsMap",function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=new eE;return r.getFieldEntities(e).forEach(function(e){var r=e.getNamePath();t.set(r,e)}),t}),(0,m.default)(this,"getFieldEntitiesForNamePathList",function(e){if(!e)return r.getFieldEntities(!0);var t=r.getFieldsMap(!0);return e.map(function(e){var r=ec(e);return t.get(r)||{INVALIDATE_NAME_PATH:ec(e)}})}),(0,m.default)(this,"getFieldsValue",function(e,t){if(r.warningUnhooked(),!0===e||Array.isArray(e)?(n=e,o=t):e&&"object"===(0,S.default)(e)&&(a=e.strict,o=e.filter),!0===n&&!o)return r.store;var n,o,a,i=r.getFieldEntitiesForNamePathList(Array.isArray(n)?n:null),l=[];return i.forEach(function(e){var t,r,i,s="INVALIDATE_NAME_PATH"in e?e.INVALIDATE_NAME_PATH:e.getNamePath();if(a){if(null!=(i=e.isList)&&i.call(e))return}else if(!n&&null!=(t=(r=e).isListField)&&t.call(r))return;if(o){var c="getMeta"in e?e.getMeta():null;o(c)&&l.push(s)}else l.push(s)}),eu(r.store,l.map(ec))}),(0,m.default)(this,"getFieldValue",function(e){r.warningUnhooked();var t=ec(e);return(0,eg.default)(r.store,t)}),(0,m.default)(this,"getFieldsError",function(e){return r.warningUnhooked(),r.getFieldEntitiesForNamePathList(e).map(function(t,r){return!t||"INVALIDATE_NAME_PATH"in t?{name:ec(e[r]),errors:[],warnings:[]}:{name:t.getNamePath(),errors:t.getErrors(),warnings:t.getWarnings()}})}),(0,m.default)(this,"getFieldError",function(e){r.warningUnhooked();var t=ec(e);return r.getFieldsError([t])[0].errors}),(0,m.default)(this,"getFieldWarning",function(e){r.warningUnhooked();var t=ec(e);return r.getFieldsError([t])[0].warnings}),(0,m.default)(this,"isFieldsTouched",function(){r.warningUnhooked();for(var e,t=arguments.length,n=Array(t),o=0;o0&&void 0!==arguments[0]?arguments[0]:{},n=new eE,o=r.getFieldEntities(!0);o.forEach(function(e){var t=e.props.initialValue,r=e.getNamePath();if(void 0!==t){var o=n.get(r)||new Set;o.add({entity:e,value:t}),n.set(r,o)}}),t.entities?e=t.entities:t.namePathList?(e=[],t.namePathList.forEach(function(t){var r,o=n.get(t);o&&(r=e).push.apply(r,(0,s.default)((0,s.default)(o).map(function(e){return e.entity})))})):e=o,e.forEach(function(e){if(void 0!==e.props.initialValue){var o=e.getNamePath();if(void 0!==r.getInitialValue(o))(0,v.default)(!1,"Form already set 'initialValues' with path '".concat(o.join("."),"'. Field can not overwrite it."));else{var a=n.get(o);if(a&&a.size>1)(0,v.default)(!1,"Multiple Field with path '".concat(o.join("."),"' set 'initialValue'. Can not decide which one to pick."));else if(a){var i=r.getFieldValue(o);e.isListField()||t.skipExist&&void 0!==i||r.updateStore((0,er.default)(r.store,o,(0,s.default)(a)[0].value))}}}})}),(0,m.default)(this,"resetFields",function(e){r.warningUnhooked();var t=r.store;if(!e){r.updateStore((0,er.merge)(r.initialValues)),r.resetWithFieldInitialValue(),r.notifyObservers(t,null,{type:"reset"}),r.notifyWatch();return}var n=e.map(ec);n.forEach(function(e){var t=r.getInitialValue(e);r.updateStore((0,er.default)(r.store,e,t))}),r.resetWithFieldInitialValue({namePathList:n}),r.notifyObservers(t,n,{type:"reset"}),r.notifyWatch(n)}),(0,m.default)(this,"setFields",function(e){r.warningUnhooked();var t=r.store,n=[];e.forEach(function(e){var a=e.name,i=(0,o.default)(e,ek),l=ec(a);n.push(l),"value"in i&&r.updateStore((0,er.default)(r.store,l,i.value)),r.notifyObservers(t,[l],{type:"setField",data:e})}),r.notifyWatch(n)}),(0,m.default)(this,"getFields",function(){return r.getFieldEntities(!0).map(function(e){var t=e.getNamePath(),n=e.getMeta(),o=(0,l.default)((0,l.default)({},n),{},{name:t,value:r.getFieldValue(t)});return Object.defineProperty(o,"originRCField",{value:!0}),o})}),(0,m.default)(this,"initEntityValue",function(e){var t=e.props.initialValue;if(void 0!==t){var n=e.getNamePath();void 0===(0,eg.default)(r.store,n)&&r.updateStore((0,er.default)(r.store,n,t))}}),(0,m.default)(this,"isMergedPreserve",function(e){var t=void 0!==e?e:r.preserve;return null==t||t}),(0,m.default)(this,"registerField",function(e){r.fieldEntities.push(e);var t=e.getNamePath();if(r.notifyWatch([t]),void 0!==e.props.initialValue){var n=r.store;r.resetWithFieldInitialValue({entities:[e],skipExist:!0}),r.notifyObservers(n,[e.getNamePath()],{type:"valueUpdate",source:"internal"})}return function(n,o){var a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];if(r.fieldEntities=r.fieldEntities.filter(function(t){return t!==e}),!r.isMergedPreserve(o)&&(!n||a.length>1)){var i=n?void 0:r.getInitialValue(t);if(t.length&&r.getFieldValue(t)!==i&&r.fieldEntities.every(function(e){return!ef(e.getNamePath(),t)})){var l=r.store;r.updateStore((0,er.default)(l,t,i,!0)),r.notifyObservers(l,[t],{type:"remove"}),r.triggerDependenciesUpdate(l,t)}}r.notifyWatch([t])}}),(0,m.default)(this,"dispatch",function(e){switch(e.type){case"updateValue":var t=e.namePath,n=e.value;r.updateValue(t,n);break;case"validateField":var o=e.namePath,a=e.triggerName;r.validateFields([o],{triggerName:a})}}),(0,m.default)(this,"notifyObservers",function(e,t,n){if(r.subscribable){var o=(0,l.default)((0,l.default)({},n),{},{store:r.getFieldsValue(!0)});r.getFieldEntities().forEach(function(r){(0,r.onStoreChange)(e,t,o)})}else r.forceRootUpdate()}),(0,m.default)(this,"triggerDependenciesUpdate",function(e,t){var n=r.getDependencyChildrenFields(t);return n.length&&r.validateFields(n),r.notifyObservers(e,n,{type:"dependenciesUpdate",relatedFields:[t].concat((0,s.default)(n))}),n}),(0,m.default)(this,"updateValue",function(e,t){var n=ec(e),o=r.store;r.updateStore((0,er.default)(r.store,n,t)),r.notifyObservers(o,[n],{type:"valueUpdate",source:"internal"}),r.notifyWatch([n]);var a=r.triggerDependenciesUpdate(o,n),i=r.callbacks.onValuesChange;i&&i(eu(r.store,[n]),r.getFieldsValue()),r.triggerOnFieldsChange([n].concat((0,s.default)(a)))}),(0,m.default)(this,"setFieldsValue",function(e){r.warningUnhooked();var t=r.store;if(e){var n=(0,er.merge)(r.store,e);r.updateStore(n)}r.notifyObservers(t,null,{type:"valueUpdate",source:"external"}),r.notifyWatch()}),(0,m.default)(this,"setFieldValue",function(e,t){r.setFields([{name:e,value:t,errors:[],warnings:[]}])}),(0,m.default)(this,"getDependencyChildrenFields",function(e){var t=new Set,n=[],o=new eE;return r.getFieldEntities().forEach(function(e){(e.props.dependencies||[]).forEach(function(t){var r=ec(t);o.update(r,function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:new Set;return t.add(e),t})})}),!function e(r){(o.get(r)||new Set).forEach(function(r){if(!t.has(r)){t.add(r);var o=r.getNamePath();r.isFieldDirty()&&o.length&&(n.push(o),e(o))}})}(e),n}),(0,m.default)(this,"triggerOnFieldsChange",function(e,t){var n=r.callbacks.onFieldsChange;if(n){var o=r.getFields();if(t){var a=new eE;t.forEach(function(e){var t=e.name,r=e.errors;a.set(t,r)}),o.forEach(function(e){e.errors=a.get(e.name)||e.errors})}var i=o.filter(function(t){return ed(e,t.name)});i.length&&n(i,o)}}),(0,m.default)(this,"validateFields",function(e,t){r.warningUnhooked(),Array.isArray(e)||"string"==typeof e||"string"==typeof t?(i=e,c=t):c=e;var n,o,a,i,c,u=!!i,d=u?i.map(ec):[],f=[],p=String(Date.now()),m=new Set,g=c||{},h=g.recursive,v=g.dirty;r.getFieldEntities(!0).forEach(function(e){if((u||d.push(e.getNamePath()),e.props.rules&&e.props.rules.length)&&(!v||e.isFieldDirty())){var t=e.getNamePath();if(m.add(t.join(p)),!u||ed(d,t,h)){var n=e.validateRules((0,l.default)({validateMessages:(0,l.default)((0,l.default)({},et),r.validateMessages)},c));f.push(n.then(function(){return{name:t,errors:[],warnings:[]}}).catch(function(e){var r,n=[],o=[];return(null==(r=e.forEach)||r.call(e,function(e){var t=e.rule.warningOnly,r=e.errors;t?o.push.apply(o,(0,s.default)(r)):n.push.apply(n,(0,s.default)(r))}),n.length)?Promise.reject({name:t,errors:n,warnings:o}):{name:t,errors:n,warnings:o}}))}}});var y=(n=!1,o=f.length,a=[],f.length?new Promise(function(e,t){f.forEach(function(r,i){r.catch(function(e){return n=!0,e}).then(function(r){o-=1,a[i]=r,o>0||(n&&t(a),e(a))})})}):Promise.resolve([]));r.lastValidatePromise=y,y.catch(function(e){return e}).then(function(e){var t=e.map(function(e){return e.name});r.notifyObservers(r.store,t,{type:"validateFinish"}),r.triggerOnFieldsChange(t,e)});var b=y.then(function(){return r.lastValidatePromise===y?Promise.resolve(r.getFieldsValue(d)):Promise.reject([])}).catch(function(e){var t=e.filter(function(e){return e&&e.errors.length});return Promise.reject({values:r.getFieldsValue(d),errorFields:t,outOfDate:r.lastValidatePromise!==y})});b.catch(function(e){return e});var w=d.filter(function(e){return m.has(e.join(p))});return r.triggerOnFieldsChange(w),b}),(0,m.default)(this,"submit",function(){r.warningUnhooked(),r.validateFields().then(function(e){var t=r.callbacks.onFinish;if(t)try{t(e)}catch(e){console.error(e)}}).catch(function(e){var t=r.callbacks.onFinishFailed;t&&t(e)})}),this.forceRootUpdate=t});let ej=function(e){var t=r.useRef(),n=r.useState({}),o=(0,ex.default)(n,2)[1];return t.current||(e?t.current=e:t.current=new eO(function(){o({})}).getForm()),[t.current]};e.s(["default",0,ej],787894);var eT=r.createContext({triggerFormChange:function(){},triggerFormFinish:function(){},registerForm:function(){},unregisterForm:function(){}}),e_=function(e){var t=e.validateMessages,n=e.onFormChange,o=e.onFormFinish,a=e.children,i=r.useContext(eT),s=r.useRef({});return r.createElement(eT.Provider,{value:(0,l.default)((0,l.default)({},i),{},{validateMessages:(0,l.default)((0,l.default)({},i.validateMessages),t),triggerFormChange:function(e,t){n&&n(e,{changedFields:t,forms:s.current}),i.triggerFormChange(e,t)},triggerFormFinish:function(e,t){o&&o(e,{values:t,forms:s.current}),i.triggerFormFinish(e,t)},registerForm:function(e,t){e&&(s.current=(0,l.default)((0,l.default)({},s.current),{},(0,m.default)({},e,t))),i.registerForm(e,t)},unregisterForm:function(e){var t=(0,l.default)({},s.current);delete t[e],s.current=t,i.unregisterForm(e)}})},a)};e.s(["FormProvider",()=>e_,"default",0,eT],696752);var eP=["name","initialValues","fields","form","preserve","children","component","validateMessages","validateTrigger","onValuesChange","onFieldsChange","onFinish","onFinishFailed","clearOnDestroy"],eg=es;function eI(e){try{return JSON.stringify(e)}catch(e){return Math.random()}}var eF=function(){};let eN=function(){for(var e=arguments.length,t=Array(e),n=0;n1?t-1:0),n=1;n{"use strict";function t(e,t){var r=Object.assign({},e);return Array.isArray(t)&&t.forEach(function(e){delete r[e]}),r}e.s(["default",()=>t])},62139,e=>{"use strict";var t=e.i(271645);e.i(495347);var r=e.i(696752),n=e.i(529681);let o=t.createContext({labelAlign:"right",layout:"horizontal",itemRef:()=>{}}),a=t.createContext(null),i=t.createContext({prefixCls:""}),l=t.createContext({}),s=t.createContext(void 0);e.s(["FormContext",0,o,"FormItemInputContext",0,l,"FormItemPrefixContext",0,i,"FormProvider",0,e=>{let o=(0,n.default)(e,["prefixCls"]);return t.createElement(r.FormProvider,Object.assign({},o))},"NoFormStyle",0,({children:e,status:r,override:n})=>{let o=t.useContext(l),a=t.useMemo(()=>{let e=Object.assign({},o);return n&&delete e.isFormItemInput,r&&(delete e.status,delete e.hasFeedback,delete e.feedbackIcon),e},[r,n,o]);return t.createElement(l.Provider,{value:a},e)},"NoStyleItemContext",0,a,"VariantContext",0,s])},613541,e=>{"use strict";var t=e.i(242064);let r=()=>({height:0,opacity:0}),n=e=>{let{scrollHeight:t}=e;return{height:t,opacity:1}},o=e=>({height:e?e.offsetHeight:0}),a=(e,t)=>(null==t?void 0:t.deadline)===!0||"height"===t.propertyName,i=(e,t,r)=>void 0!==r?r:`${e}-${t}`;e.s(["default",0,(e=t.defaultPrefixCls)=>({motionName:`${e}-motion-collapse`,onAppearStart:r,onEnterStart:r,onAppearActive:n,onEnterActive:n,onLeaveStart:o,onLeaveActive:r,onAppearEnd:a,onEnterEnd:a,onLeaveEnd:a,motionDeadline:500}),"getTransitionName",()=>i])},830919,e=>{"use strict";var t=e.i(271645);function r(e){let[r,n]=t.useState(e);return t.useEffect(()=>{let t=setTimeout(()=>{n(e)},10*!e.length);return()=>{clearTimeout(t)}},[e]),r}e.s(["default",()=>r])},447580,e=>{"use strict";e.s(["genCollapseMotion",0,e=>({[e.componentCls]:{[`${e.antCls}-motion-collapse-legacy`]:{overflow:"hidden","&-active":{transition:`height ${e.motionDurationMid} ${e.motionEaseInOut}, + opacity ${e.motionDurationMid} ${e.motionEaseInOut} !important`}},[`${e.antCls}-motion-collapse`]:{overflow:"hidden",transition:`height ${e.motionDurationMid} ${e.motionEaseInOut}, + opacity ${e.motionDurationMid} ${e.motionEaseInOut} !important`}}})],447580)},402366,e=>{"use strict";e.s(["initMotion",0,(e,t,r,n,o=!1)=>{let a=o?"&":"";return{[` + ${a}${e}-enter, + ${a}${e}-appear + `]:Object.assign(Object.assign({},{animationDuration:n,animationFillMode:"both"}),{animationPlayState:"paused"}),[`${a}${e}-leave`]:Object.assign(Object.assign({},{animationDuration:n,animationFillMode:"both"}),{animationPlayState:"paused"}),[` + ${a}${e}-enter${e}-enter-active, + ${a}${e}-appear${e}-appear-active + `]:{animationName:t,animationPlayState:"running"},[`${a}${e}-leave${e}-leave-active`]:{animationName:r,animationPlayState:"running",pointerEvents:"none"}}}])},717356,e=>{"use strict";e.i(296059);var t=e.i(694758),r=e.i(402366);let n=new t.Keyframes("antZoomIn",{"0%":{transform:"scale(0.2)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),o=new t.Keyframes("antZoomOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.2)",opacity:0}}),a=new t.Keyframes("antZoomBigIn",{"0%":{transform:"scale(0.8)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),i=new t.Keyframes("antZoomBigOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.8)",opacity:0}}),l=new t.Keyframes("antZoomUpIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 0%"}}),s=new t.Keyframes("antZoomUpOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 0%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0}}),c={zoom:{inKeyframes:n,outKeyframes:o},"zoom-big":{inKeyframes:a,outKeyframes:i},"zoom-big-fast":{inKeyframes:a,outKeyframes:i},"zoom-left":{inKeyframes:new t.Keyframes("antZoomLeftIn",{"0%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"0% 50%"}}),outKeyframes:new t.Keyframes("antZoomLeftOut",{"0%":{transform:"scale(1)",transformOrigin:"0% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0}})},"zoom-right":{inKeyframes:new t.Keyframes("antZoomRightIn",{"0%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"100% 50%"}}),outKeyframes:new t.Keyframes("antZoomRightOut",{"0%":{transform:"scale(1)",transformOrigin:"100% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0}})},"zoom-up":{inKeyframes:l,outKeyframes:s},"zoom-down":{inKeyframes:new t.Keyframes("antZoomDownIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 100%"}}),outKeyframes:new t.Keyframes("antZoomDownOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 100%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0}})}};e.s(["initZoomMotion",0,(e,t)=>{let{antCls:n}=e,o=`${n}-${t}`,{inKeyframes:a,outKeyframes:i}=c[t];return[(0,r.initMotion)(o,a,i,"zoom-big-fast"===t?e.motionDurationFast:e.motionDurationMid),{[` + ${o}-enter, + ${o}-appear + `]:{transform:"scale(0)",opacity:0,animationTimingFunction:e.motionEaseOutCirc,"&-prepare":{transform:"none"}},[`${o}-leave`]:{animationTimingFunction:e.motionEaseInOutCirc}}]},"zoomIn",0,n])},782074,908709,53058,923624,e=>{"use strict";var t=e.i(8211),r=e.i(271645),n=e.i(343794),o=e.i(361275),a=e.i(629587),i=e.i(613541),l=e.i(321883),s=e.i(62139),c=e.i(830919);e.i(296059);var u=e.i(915654),d=e.i(183293),f=e.i(447580),p=e.i(717356),m=e.i(246422),g=e.i(838378);let h=(e,t)=>{let{formItemCls:r}=e;return{[r]:{[`${r}-label > label`]:{height:t},[`${r}-control-input`]:{minHeight:t}}}},v=e=>({padding:e.verticalLabelPadding,margin:e.verticalLabelMargin,whiteSpace:"initial",textAlign:"start","> label":{margin:0,"&::after":{visibility:"hidden"}}}),y=(e,t)=>(0,g.mergeToken)(e,{formItemCls:`${e.componentCls}-item`,rootPrefixCls:t}),b=(0,m.genStyleHooks)("Form",(e,{rootPrefixCls:t})=>{let r=y(e,t);return[(e=>{let{componentCls:t}=e;return{[e.componentCls]:Object.assign(Object.assign(Object.assign({},(0,d.resetComponent)(e)),{legend:{display:"block",width:"100%",marginBottom:e.marginLG,padding:0,color:e.colorTextDescription,fontSize:e.fontSizeLG,lineHeight:"inherit",border:0,borderBottom:`${(0,u.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`},'input[type="search"]':{boxSizing:"border-box"},'input[type="radio"], input[type="checkbox"]':{lineHeight:"normal"},'input[type="file"]':{display:"block"},'input[type="range"]':{display:"block",width:"100%"},"select[multiple], select[size]":{height:"auto"},[`input[type='file']:focus, + input[type='radio']:focus, + input[type='checkbox']:focus`]:{outline:0,boxShadow:`0 0 0 ${(0,u.unit)(e.controlOutlineWidth)} ${e.controlOutline}`},output:{display:"block",paddingTop:15,color:e.colorText,fontSize:e.fontSize,lineHeight:e.lineHeight}}),{[`${t}-text`]:{display:"inline-block",paddingInlineEnd:e.paddingSM},"&-small":Object.assign({},h(e,e.controlHeightSM)),"&-large":Object.assign({},h(e,e.controlHeightLG))})}})(r),(e=>{let{formItemCls:t,iconCls:r,rootPrefixCls:n,antCls:o,labelRequiredMarkColor:a,labelColor:i,labelFontSize:l,labelHeight:s,labelColonMarginInlineStart:c,labelColonMarginInlineEnd:u,itemMarginBottom:f}=e;return{[t]:Object.assign(Object.assign({},(0,d.resetComponent)(e)),{marginBottom:f,verticalAlign:"top","&-with-help":{transition:"none"},[`&-hidden, + &-hidden${o}-row`]:{display:"none"},"&-has-warning":{[`${t}-split`]:{color:e.colorError}},"&-has-error":{[`${t}-split`]:{color:e.colorWarning}},[`${t}-label`]:{flexGrow:0,overflow:"hidden",whiteSpace:"nowrap",textAlign:"end",verticalAlign:"middle","&-left":{textAlign:"start"},"&-wrap":{overflow:"unset",lineHeight:e.lineHeight,whiteSpace:"unset","> label":{verticalAlign:"middle",textWrap:"balance"}},"> label":{position:"relative",display:"inline-flex",alignItems:"center",maxWidth:"100%",height:s,color:i,fontSize:l,[`> ${r}`]:{fontSize:e.fontSize,verticalAlign:"top"},[`&${t}-required`]:{"&::before":{display:"inline-block",marginInlineEnd:e.marginXXS,color:a,fontSize:e.fontSize,fontFamily:"SimSun, sans-serif",lineHeight:1,content:'"*"'},[`&${t}-required-mark-hidden, &${t}-required-mark-optional`]:{"&::before":{display:"none"}}},[`${t}-optional`]:{display:"inline-block",marginInlineStart:e.marginXXS,color:e.colorTextDescription,[`&${t}-required-mark-hidden`]:{display:"none"}},[`${t}-tooltip`]:{color:e.colorTextDescription,cursor:"help",writingMode:"horizontal-tb",marginInlineStart:e.marginXXS},"&::after":{content:'":"',position:"relative",marginBlock:0,marginInlineStart:c,marginInlineEnd:u},[`&${t}-no-colon::after`]:{content:'"\\a0"'}}},[`${t}-control`]:{"--ant-display":"flex",flexDirection:"column",flexGrow:1,[`&:first-child:not([class^="'${n}-col-'"]):not([class*="' ${n}-col-'"])`]:{width:"100%"},"&-input":{position:"relative",display:"flex",alignItems:"center",minHeight:e.controlHeight,"&-content":{flex:"auto",maxWidth:"100%",[`&:has(> ${o}-switch:only-child, > ${o}-rate:only-child)`]:{display:"flex",alignItems:"center"}}}},[t]:{"&-additional":{display:"flex",flexDirection:"column"},"&-explain, &-extra":{clear:"both",color:e.colorTextDescription,fontSize:e.fontSize,lineHeight:e.lineHeight},"&-explain-connected":{width:"100%"},"&-extra":{minHeight:e.controlHeightSM,transition:`color ${e.motionDurationMid} ${e.motionEaseOut}`},"&-explain":{"&-error":{color:e.colorError},"&-warning":{color:e.colorWarning}}},[`&-with-help ${t}-explain`]:{height:"auto",opacity:1},[`${t}-feedback-icon`]:{fontSize:e.fontSize,textAlign:"center",visibility:"visible",animationName:p.zoomIn,animationDuration:e.motionDurationMid,animationTimingFunction:e.motionEaseOutBack,pointerEvents:"none","&-success":{color:e.colorSuccess},"&-error":{color:e.colorError},"&-warning":{color:e.colorWarning},"&-validating":{color:e.colorPrimary}}})}})(r),(e=>{let{componentCls:t}=e,r=`${t}-show-help`,n=`${t}-show-help-item`;return{[r]:{transition:`opacity ${e.motionDurationFast} ${e.motionEaseInOut}`,"&-appear, &-enter":{opacity:0,"&-active":{opacity:1}},"&-leave":{opacity:1,"&-active":{opacity:0}},[n]:{overflow:"hidden",transition:`height ${e.motionDurationFast} ${e.motionEaseInOut}, + opacity ${e.motionDurationFast} ${e.motionEaseInOut}, + transform ${e.motionDurationFast} ${e.motionEaseInOut} !important`,[`&${n}-appear, &${n}-enter`]:{transform:"translateY(-5px)",opacity:0,"&-active":{transform:"translateY(0)",opacity:1}},[`&${n}-leave-active`]:{transform:"translateY(-5px)"}}}}})(r),(e=>{let{antCls:t,formItemCls:r}=e;return{[`${r}-horizontal`]:{[`${r}-label`]:{flexGrow:0},[`${r}-control`]:{flex:"1 1 0",minWidth:0},[`${r}-label[class$='-24'], ${r}-label[class*='-24 ']`]:{[`& + ${r}-control`]:{minWidth:"unset"}},[`${t}-col-24${r}-label, + ${t}-col-xl-24${r}-label`]:v(e)}}})(r),(e=>{let{componentCls:t,formItemCls:r,inlineItemMarginBottom:n}=e;return{[`${t}-inline`]:{display:"flex",flexWrap:"wrap",[`${r}-inline`]:{flex:"none",marginInlineEnd:e.margin,marginBottom:n,"&-row":{flexWrap:"nowrap"},[`> ${r}-label, + > ${r}-control`]:{display:"inline-block",verticalAlign:"top"},[`> ${r}-label`]:{flex:"none"},[`${t}-text`]:{display:"inline-block"},[`${r}-has-feedback`]:{display:"inline-block"}}}}})(r),(e=>{let{componentCls:t,formItemCls:r,antCls:n}=e;return{[`${r}-vertical`]:{[`${r}-row`]:{flexDirection:"column"},[`${r}-label > label`]:{height:"auto"},[`${r}-control`]:{width:"100%"},[`${r}-label, + ${n}-col-24${r}-label, + ${n}-col-xl-24${r}-label`]:v(e)},[`@media (max-width: ${(0,u.unit)(e.screenXSMax)})`]:[(e=>{let{componentCls:t,formItemCls:r,rootPrefixCls:n}=e;return{[`${r} ${r}-label`]:v(e),[`${t}:not(${t}-inline)`]:{[r]:{flexWrap:"wrap",[`${r}-label, ${r}-control`]:{[`&:not([class*=" ${n}-col-xs"])`]:{flex:"0 0 100%",maxWidth:"100%"}}}}}})(e),{[t]:{[`${r}:not(${r}-horizontal)`]:{[`${n}-col-xs-24${r}-label`]:v(e)}}}],[`@media (max-width: ${(0,u.unit)(e.screenSMMax)})`]:{[t]:{[`${r}:not(${r}-horizontal)`]:{[`${n}-col-sm-24${r}-label`]:v(e)}}},[`@media (max-width: ${(0,u.unit)(e.screenMDMax)})`]:{[t]:{[`${r}:not(${r}-horizontal)`]:{[`${n}-col-md-24${r}-label`]:v(e)}}},[`@media (max-width: ${(0,u.unit)(e.screenLGMax)})`]:{[t]:{[`${r}:not(${r}-horizontal)`]:{[`${n}-col-lg-24${r}-label`]:v(e)}}}}})(r),(0,f.genCollapseMotion)(r),p.zoomIn]},e=>({labelRequiredMarkColor:e.colorError,labelColor:e.colorTextHeading,labelFontSize:e.fontSize,labelHeight:e.controlHeight,labelColonMarginInlineStart:e.marginXXS/2,labelColonMarginInlineEnd:e.marginXS,itemMarginBottom:e.marginLG,verticalLabelPadding:`0 0 ${e.paddingXS}px`,verticalLabelMargin:0,inlineItemMarginBottom:0}),{order:-1e3});e.s(["default",0,b,"prepareToken",0,y],908709);let w=[];function C(e,t,r,n=0){return{key:"string"==typeof e?e:`${t}-${n}`,error:e,errorStatus:r}}e.s(["default",0,({help:e,helpStatus:u,errors:d=w,warnings:f=w,className:p,fieldId:m,onVisibleChanged:g})=>{let{prefixCls:h}=r.useContext(s.FormItemPrefixContext),v=`${h}-item-explain`,y=(0,l.default)(h),[x,S,$]=b(h,y),E=r.useMemo(()=>(0,i.default)(h),[h]),k=(0,c.default)(d),O=(0,c.default)(f),j=r.useMemo(()=>null!=e?[C(e,"help",u)]:[].concat((0,t.default)(k.map((e,t)=>C(e,"error","error",t))),(0,t.default)(O.map((e,t)=>C(e,"warning","warning",t)))),[e,u,k,O]),T=r.useMemo(()=>{let e={};return j.forEach(({key:t})=>{e[t]=(e[t]||0)+1}),j.map((t,r)=>Object.assign(Object.assign({},t),{key:e[t.key]>1?`${t.key}-fallback-${r}`:t.key}))},[j]),_={};return m&&(_.id=`${m}_help`),x(r.createElement(o.default,{motionDeadline:E.motionDeadline,motionName:`${h}-show-help`,visible:!!T.length,onVisibleChanged:g},e=>{let{className:t,style:o}=e;return r.createElement("div",Object.assign({},_,{className:(0,n.default)(v,t,$,y,p,S),style:o}),r.createElement(a.CSSMotionList,Object.assign({keys:T},(0,i.default)(h),{motionName:`${h}-show-help-item`,component:!1}),e=>{let{key:t,error:o,errorStatus:a,className:i,style:l}=e;return r.createElement("div",{key:t,className:(0,n.default)(i,{[`${v}-${a}`]:a}),style:l},o)}))}))}],782074);var x=e.i(197091);e.s(["List",()=>x.default],53058);var S=e.i(621796);e.s(["useWatch",()=>S.default],923624)},517455,e=>{"use strict";var t=e.i(271645),r=e.i(666365);e.s(["default",0,e=>{let n=t.default.useContext(r.default);return t.default.useMemo(()=>e?"string"==typeof e?null!=e?e:n:"function"==typeof e?e(n):n:n,[e,n])}])},286039,531880,e=>{"use strict";var t=e.i(271645);e.i(495347);var r=e.i(787894),r=r,n=e.i(279697);let o=e=>"object"==typeof e&&null!=e&&1===e.nodeType,a=(e,t)=>(!t||"hidden"!==e)&&"visible"!==e&&"clip"!==e,i=(e,t)=>{if(e.clientHeight{if(!e.ownerDocument||!e.ownerDocument.defaultView)return null;try{return e.ownerDocument.defaultView.frameElement}catch(e){return null}})(e))&&(r.clientHeightat||a>e&&i=t&&l>=r?a-e-n:i>t&&lr?i-t+o:0,s=e=>{let t=e.parentElement;return null==t?e.getRootNode().host||null:t},c=(e,t)=>{var r,n,a,c;let u;if("u"e!==m;if(!o(e))throw TypeError("Invalid target");let v=document.scrollingElement||document.documentElement,y=[],b=e;for(;o(b)&&h(b);){if((b=s(b))===v){y.push(b);break}null!=b&&b===document.body&&i(b)&&!i(document.documentElement)||null!=b&&i(b,g)&&y.push(b)}let w=null!=(n=null==(r=window.visualViewport)?void 0:r.width)?n:innerWidth,C=null!=(c=null==(a=window.visualViewport)?void 0:a.height)?c:innerHeight,{scrollX:x,scrollY:S}=window,{height:$,width:E,top:k,right:O,bottom:j,left:T}=e.getBoundingClientRect(),{top:_,right:P,bottom:I,left:F}={top:parseFloat((u=window.getComputedStyle(e)).scrollMarginTop)||0,right:parseFloat(u.scrollMarginRight)||0,bottom:parseFloat(u.scrollMarginBottom)||0,left:parseFloat(u.scrollMarginLeft)||0},N="start"===f||"nearest"===f?k-_:"end"===f?j+I:k+$/2-_+I,R="center"===p?T+E/2-F+P:"end"===p?O+P:T-F,M=[];for(let e=0;e=0&&T>=0&&j<=C&&O<=w&&(t===v&&!i(t)||k>=o&&j<=s&&T>=c&&O<=a))break;let u=getComputedStyle(t),m=parseInt(u.borderLeftWidth,10),g=parseInt(u.borderTopWidth,10),h=parseInt(u.borderRightWidth,10),b=parseInt(u.borderBottomWidth,10),_=0,P=0,I="offsetWidth"in t?t.offsetWidth-t.clientWidth-m-h:0,F="offsetHeight"in t?t.offsetHeight-t.clientHeight-g-b:0,A="offsetWidth"in t?0===t.offsetWidth?0:n/t.offsetWidth:0,B="offsetHeight"in t?0===t.offsetHeight?0:r/t.offsetHeight:0;if(v===t)_="start"===f?N:"end"===f?N-C:"nearest"===f?l(S,S+C,C,g,b,S+N,S+N+$,$):N-C/2,P="start"===p?R:"center"===p?R-w/2:"end"===p?R-w:l(x,x+w,w,m,h,x+R,x+R+E,E),_=Math.max(0,_+S),P=Math.max(0,P+x);else{_="start"===f?N-o-g:"end"===f?N-s+b+F:"nearest"===f?l(o,s,r,g,b+F,N,N+$,$):N-(o+r/2)+F/2,P="start"===p?R-c-m:"center"===p?R-(c+n/2)+I/2:"end"===p?R-a+h+I:l(c,a,n,m,h+I,R,R+E,E);let{scrollLeft:e,scrollTop:i}=t;_=0===B?0:Math.max(0,Math.min(i+_/B,t.scrollHeight-r/B+F)),P=0===A?0:Math.max(0,Math.min(e+P/A,t.scrollWidth-n/A+I)),N+=i-_,R+=e-P}M.push({el:t,top:_,left:P})}return M},u=["parentNode"];function d(e){return void 0===e||!1===e?[]:Array.isArray(e)?e:[e]}function f(e,t){if(!e.length)return;let r=e.join("_");return t?`${t}_${r}`:u.includes(r)?`form_item_${r}`:r}function p(e,t,r,n,o,a){let i=n;return void 0!==a?i=a:r.validating?i="validating":e.length?i="error":t.length?i="warning":(r.touched||o&&r.validated)&&(i="success"),i}e.s(["getFieldId",()=>f,"getStatus",()=>p,"toArray",()=>d],531880);var m=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};function g(e){return d(e).join("_")}function h(e,t){let r=t.getFieldInstance(e),o=(0,n.getDOM)(r);if(o)return o;let a=f(d(e),t.__INTERNAL__.name);if(a)return document.getElementById(a)}function v(e){let[n]=(0,r.default)(),o=t.useRef({}),a=t.useMemo(()=>null!=e?e:Object.assign(Object.assign({},n),{__INTERNAL__:{itemRef:e=>t=>{let r=g(e);t?o.current[r]=t:delete o.current[r]}},scrollToField:(e,t={})=>{let{focus:r}=t,n=m(t,["focus"]),o=h(e,a);o&&(!function(e,t){let r;if(!e.isConnected||!(e=>{let t=e;for(;t&&t.parentNode;){if(t.parentNode===document)return!0;t=t.parentNode instanceof ShadowRoot?t.parentNode.host:t.parentNode}return!1})(e))return;let n={top:parseFloat((r=window.getComputedStyle(e)).scrollMarginTop)||0,right:parseFloat(r.scrollMarginRight)||0,bottom:parseFloat(r.scrollMarginBottom)||0,left:parseFloat(r.scrollMarginLeft)||0};if("object"==typeof t&&"function"==typeof t.behavior)return t.behavior(c(e,t));let o="boolean"==typeof t||null==t?void 0:t.behavior;for(let{el:r,top:a,left:i}of c(e,!1===t?{block:"end",inline:"nearest"}:t===Object(t)&&0!==Object.keys(t).length?t:{block:"start",inline:"nearest"})){let e=a-n.top+n.bottom,t=i-n.left+n.right;r.scroll({top:e,left:t,behavior:o})}}(o,Object.assign({scrollMode:"if-needed",block:"nearest"},n)),r&&a.focusField(e))},focusField:e=>{var t,r;let n=a.getFieldInstance(e);"function"==typeof(null==n?void 0:n.focus)?n.focus():null==(r=null==(t=h(e,a))?void 0:t.focus)||r.call(t)},getFieldInstance:e=>{let t=g(e);return o.current[t]}}),[e,n]);return[a]}e.s(["default",()=>v,"toNamePathStr",()=>g],286039)},56117,411412,420422,355268,220489,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(495347);e.i(53058),e.i(923624);var o=e.i(242064),a=e.i(937328),i=e.i(321883),l=e.i(517455),s=e.i(666365),c=e.i(62139),u=e.i(286039),d=e.i(908709),f=e.i(819828),p=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=t.forwardRef((e,m)=>{let g=t.useContext(a.default),{getPrefixCls:h,direction:v,requiredMark:y,colon:b,scrollToFirstError:w,className:C,style:x}=(0,o.useComponentConfig)("form"),{prefixCls:S,className:$,rootClassName:E,size:k,disabled:O=g,form:j,colon:T,labelAlign:_,labelWrap:P,labelCol:I,wrapperCol:F,hideRequiredMark:N,layout:R="horizontal",scrollToFirstError:M,requiredMark:A,onFinishFailed:B,name:z,style:L,feedbackIcons:H,variant:D}=e,V=p(e,["prefixCls","className","rootClassName","size","disabled","form","colon","labelAlign","labelWrap","labelCol","wrapperCol","hideRequiredMark","layout","scrollToFirstError","requiredMark","onFinishFailed","name","style","feedbackIcons","variant"]),W=(0,l.default)(k),U=t.useContext(f.default),G=t.useMemo(()=>void 0!==A?A:!N&&(void 0===y||y),[N,A,y]),q=null!=T?T:b,K=h("form",S),X=(0,i.default)(K),[J,Y,Q]=(0,d.default)(K,X),Z=(0,r.default)(K,`${K}-${R}`,{[`${K}-hide-required-mark`]:!1===G,[`${K}-rtl`]:"rtl"===v,[`${K}-${W}`]:W},Q,X,Y,C,$,E),[ee]=(0,u.default)(j),{__INTERNAL__:et}=ee;et.name=z;let er=t.useMemo(()=>({name:z,labelAlign:_,labelCol:I,labelWrap:P,wrapperCol:F,layout:R,colon:q,requiredMark:G,itemRef:et.itemRef,form:ee,feedbackIcons:H}),[z,_,I,F,R,q,G,ee,H]),en=t.useRef(null);t.useImperativeHandle(m,()=>{var e;return Object.assign(Object.assign({},ee),{nativeElement:null==(e=en.current)?void 0:e.nativeElement})});let eo=(e,t)=>{if(e){let r={block:"nearest"};"object"==typeof e&&(r=Object.assign(Object.assign({},r),e)),ee.scrollToField(t,r)}};return J(t.createElement(c.VariantContext.Provider,{value:D},t.createElement(a.DisabledContextProvider,{disabled:O},t.createElement(s.default.Provider,{value:W},t.createElement(c.FormProvider,{validateMessages:U},t.createElement(c.FormContext.Provider,{value:er},t.createElement(c.NoFormStyle,{status:!0},t.createElement(n.default,Object.assign({id:z},V,{name:z,onFinishFailed:e=>{if(null==B||B(e),e.errorFields.length){let t=e.errorFields[0].name;if(void 0!==M)return void eo(M,t);void 0!==w&&eo(w,t)}},form:ee,ref:en,style:Object.assign(Object.assign({},x),L),className:Z})))))))))});e.s(["default",0,m],56117),e.s(["useForm",()=>u.default],411412);var g=e.i(162129);e.s(["Field",()=>g.default],420422);var h=e.i(177886);e.s(["FieldContext",()=>h.default],355268);var v=e.i(786944);e.s(["ListContext",()=>v.default],220489)},763731,e=>{"use strict";var t=e.i(271645);function r(e){return e&&t.default.isValidElement(e)&&e.type===t.default.Fragment}let n=(e,r,n)=>t.default.isValidElement(e)?t.default.cloneElement(e,"function"==typeof n?n(e.props||{}):n):r;function o(e,t){return n(e,e,t)}e.s(["cloneElement",()=>o,"isFragment",()=>r,"replaceElement",0,n])},522228,893872,857034,606836,e=>{"use strict";var t=e.i(876556);function r(e){if("function"==typeof e)return e;let r=(0,t.default)(e);return r.length<=1?r[0]:r}e.s(["default",()=>r],522228),e.i(247167);var n=e.i(271645),o=e.i(62139);let a=()=>{let{status:e,errors:t=[],warnings:r=[]}=n.useContext(o.FormItemInputContext);return{status:e,errors:t,warnings:r}};a.Context=o.FormItemInputContext,e.s(["default",0,a],893872);var i=e.i(963188);function l(e){let[t,r]=n.useState(e),o=n.useRef(null),a=n.useRef([]),l=n.useRef(!1);return n.useEffect(()=>(l.current=!1,()=>{l.current=!0,i.default.cancel(o.current),o.current=null}),[]),[t,function(e){l.current||(null===o.current&&(a.current=[],o.current=(0,i.default)(()=>{o.current=null,r(e=>{let t=e;return a.current.forEach(e=>{t=e(t)}),t})})),a.current.push(e))}]}e.s(["default",()=>l],857034);var s=e.i(611935);function c(){let{itemRef:e}=n.useContext(o.FormContext),t=n.useRef({});return function(r,n){let o=n&&"object"==typeof n&&(0,s.getNodeRef)(n),a=r.join("_");return(t.current.name!==a||t.current.originRef!==o)&&(t.current.name=a,t.current.originRef=o,t.current.ref=(0,s.composeRef)(e(r),o)),t.current.ref}}e.s(["default",()=>c],606836)},606262,e=>{"use strict";e.s(["default",0,function(e){if(!e)return!1;if(e instanceof Element){if(e.offsetParent)return!0;if(e.getBBox){var t=e.getBBox(),r=t.width,n=t.height;if(r||n)return!0}if(e.getBoundingClientRect){var o=e.getBoundingClientRect(),a=o.width,i=o.height;if(a||i)return!0}}return!1}])},958503,e=>{"use strict";e.s(["addMediaQueryListener",0,(e,t)=>{void 0!==(null==e?void 0:e.addEventListener)?e.addEventListener("change",t):void 0!==(null==e?void 0:e.addListener)&&e.addListener(t)},"removeMediaQueryListener",0,(e,t)=>{void 0!==(null==e?void 0:e.removeEventListener)?e.removeEventListener("change",t):void 0!==(null==e?void 0:e.removeListener)&&e.removeListener(t)}])},908206,e=>{"use strict";var t=e.i(271645),r=e.i(104458),n=e.i(958503);let o=["xxl","xl","lg","md","sm","xs"];e.s(["default",0,()=>{let e,[,a]=(0,r.useToken)(),i=((e=[].concat(o).reverse()).forEach((t,r)=>{let n=t.toUpperCase(),o=`screen${n}Min`,i=`screen${n}`;if(!(a[o]<=a[i]))throw Error(`${o}<=${i} fails : !(${a[o]}<=${a[i]})`);if(r{let e=new Map,t=-1,r={};return{responsiveMap:i,matchHandlers:{},dispatch:t=>(r=t,e.forEach(e=>e(r)),e.size>=1),subscribe(n){return e.size||this.register(),t+=1,e.set(t,n),n(r),t},unsubscribe(t){e.delete(t),e.size||this.unregister()},register(){Object.entries(i).forEach(([e,t])=>{let o=({matches:t})=>{this.dispatch(Object.assign(Object.assign({},r),{[e]:t}))},a=window.matchMedia(t);(0,n.addMediaQueryListener)(a,o),this.matchHandlers[t]={mql:a,listener:o},o(a)})},unregister(){Object.values(i).forEach(e=>{let t=this.matchHandlers[e];(0,n.removeMediaQueryListener)(null==t?void 0:t.mql,null==t?void 0:t.listener)}),e.clear()}}},[i])},"matchScreen",0,(e,t)=>{if(t){for(let r of o)if(e[r]&&(null==t?void 0:t[r])!==void 0)return t[r]}},"responsiveArray",0,o])},149809,e=>{"use strict";var t=e.i(271645);e.s(["useForceUpdate",0,()=>t.default.useReducer(e=>e+1,0)])},150073,e=>{"use strict";var t=e.i(271645),r=e.i(174428),n=e.i(149809),o=e.i(908206);e.s(["default",0,function(e=!0,a={}){let i=(0,t.useRef)(a),[,l]=(0,n.useForceUpdate)(),s=(0,o.default)();return(0,r.default)(()=>{let t=s.subscribe(t=>{i.current=t,e&&l()});return()=>s.unsubscribe(t)},[]),i.current}])},39874,559442,e=>{"use strict";var t=e.i(908206);function r(e,r){let n=[void 0,void 0],o=Array.isArray(e)?e:[e,void 0],a=r||{xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0};return o.forEach((e,r)=>{if("object"==typeof e&&null!==e)for(let o=0;or],39874);let n=(0,e.i(271645).createContext)({});e.s(["default",0,n],559442)},756570,e=>{"use strict";e.i(296059);var t=e.i(915654),r=e.i(246422),n=e.i(838378);let o=(e,t)=>((e,t)=>{let{prefixCls:r,componentCls:n,gridColumns:o}=e,a={};for(let e=o;e>=0;e--)0===e?(a[`${n}${t}-${e}`]={display:"none"},a[`${n}-push-${e}`]={insetInlineStart:"auto"},a[`${n}-pull-${e}`]={insetInlineEnd:"auto"},a[`${n}${t}-push-${e}`]={insetInlineStart:"auto"},a[`${n}${t}-pull-${e}`]={insetInlineEnd:"auto"},a[`${n}${t}-offset-${e}`]={marginInlineStart:0},a[`${n}${t}-order-${e}`]={order:0}):(a[`${n}${t}-${e}`]=[{"--ant-display":"block",display:"block"},{display:"var(--ant-display)",flex:`0 0 ${e/o*100}%`,maxWidth:`${e/o*100}%`}],a[`${n}${t}-push-${e}`]={insetInlineStart:`${e/o*100}%`},a[`${n}${t}-pull-${e}`]={insetInlineEnd:`${e/o*100}%`},a[`${n}${t}-offset-${e}`]={marginInlineStart:`${e/o*100}%`},a[`${n}${t}-order-${e}`]={order:e});return a[`${n}${t}-flex`]={flex:`var(--${r}${t}-flex)`},a})(e,t),a=(0,r.genStyleHooks)("Grid",e=>{let{componentCls:t}=e;return{[t]:{display:"flex",flexFlow:"row wrap",minWidth:0,"&::before, &::after":{display:"flex"},"&-no-wrap":{flexWrap:"nowrap"},"&-start":{justifyContent:"flex-start"},"&-center":{justifyContent:"center"},"&-end":{justifyContent:"flex-end"},"&-space-between":{justifyContent:"space-between"},"&-space-around":{justifyContent:"space-around"},"&-space-evenly":{justifyContent:"space-evenly"},"&-top":{alignItems:"flex-start"},"&-middle":{alignItems:"center"},"&-bottom":{alignItems:"flex-end"}}}},()=>({})),i=e=>({xs:e.screenXSMin,sm:e.screenSMMin,md:e.screenMDMin,lg:e.screenLGMin,xl:e.screenXLMin,xxl:e.screenXXLMin}),l=(0,r.genStyleHooks)("Grid",e=>{let r=(0,n.mergeToken)(e,{gridColumns:24}),a=i(r);return delete a.xs,[(e=>{let{componentCls:t}=e;return{[t]:{position:"relative",maxWidth:"100%",minHeight:1}}})(r),o(r,""),o(r,"-xs"),Object.keys(a).map(e=>{let n,i;return n=a[e],i=`-${e}`,{[`@media (min-width: ${(0,t.unit)(n)})`]:Object.assign({},o(r,i))}}).reduce((e,t)=>Object.assign(Object.assign({},e),t),{})]},()=>({}));e.s(["getMediaSize",0,i,"useColStyle",0,l,"useRowStyle",0,a])},264042,131757,292169,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(908206),o=e.i(242064),a=e.i(150073),i=e.i(39874),l=e.i(559442),s=e.i(756570),c=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};function u(e,r){let[o,a]=t.useState("string"==typeof e?e:"");return t.useEffect(()=>{(()=>{if("string"==typeof e&&a(e),"object"==typeof e)for(let t=0;t{let{prefixCls:d,justify:f,align:p,className:m,style:g,children:h,gutter:v=0,wrap:y}=e,b=c(e,["prefixCls","justify","align","className","style","children","gutter","wrap"]),{getPrefixCls:w,direction:C}=t.useContext(o.ConfigContext),x=(0,a.default)(!0,null),S=u(p,x),$=u(f,x),E=w("row",d),[k,O,j]=(0,s.useRowStyle)(E),T=(0,i.default)(v,x),_=(0,r.default)(E,{[`${E}-no-wrap`]:!1===y,[`${E}-${$}`]:$,[`${E}-${S}`]:S,[`${E}-rtl`]:"rtl"===C},m,O,j),P={};if(null==T?void 0:T[0]){let e="number"==typeof T[0]?`${-(T[0]/2)}px`:`calc(${T[0]} / -2)`;P.marginLeft=e,P.marginRight=e}let[I,F]=T;P.rowGap=F;let N=t.useMemo(()=>({gutter:[I,F],wrap:y}),[I,F,y]);return k(t.createElement(l.default.Provider,{value:N},t.createElement("div",Object.assign({},b,{className:_,style:Object.assign(Object.assign({},P),g),ref:n}),h)))});e.s(["Row",0,d],264042),e.i(62664);var f=e.i(657791),f=f,p=e.i(349057),p=p,m=e.i(174428),g=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};function h(e){return"auto"===e?"1 1 auto":"number"==typeof e?`${e} ${e} auto`:/^\d+(\.\d+)?(px|em|rem|%)$/.test(e)?`0 0 ${e}`:e}let v=["xs","sm","md","lg","xl","xxl"],y=t.forwardRef((e,n)=>{let{getPrefixCls:a,direction:i}=t.useContext(o.ConfigContext),{gutter:c,wrap:u}=t.useContext(l.default),{prefixCls:d,span:f,order:p,offset:m,push:y,pull:b,className:w,children:C,flex:x,style:S}=e,$=g(e,["prefixCls","span","order","offset","push","pull","className","children","flex","style"]),E=a("col",d),[k,O,j]=(0,s.useColStyle)(E),T={},_={};v.forEach(t=>{let r={},n=e[t];"number"==typeof n?r.span=n:"object"==typeof n&&(r=n||{}),delete $[t],_=Object.assign(Object.assign({},_),{[`${E}-${t}-${r.span}`]:void 0!==r.span,[`${E}-${t}-order-${r.order}`]:r.order||0===r.order,[`${E}-${t}-offset-${r.offset}`]:r.offset||0===r.offset,[`${E}-${t}-push-${r.push}`]:r.push||0===r.push,[`${E}-${t}-pull-${r.pull}`]:r.pull||0===r.pull,[`${E}-rtl`]:"rtl"===i}),r.flex&&(_[`${E}-${t}-flex`]=!0,T[`--${E}-${t}-flex`]=h(r.flex))});let P=(0,r.default)(E,{[`${E}-${f}`]:void 0!==f,[`${E}-order-${p}`]:p,[`${E}-offset-${m}`]:m,[`${E}-push-${y}`]:y,[`${E}-pull-${b}`]:b},w,_,O,j),I={};if(null==c?void 0:c[0]){let e="number"==typeof c[0]?`${c[0]/2}px`:`calc(${c[0]} / 2)`;I.paddingLeft=e,I.paddingRight=e}return x&&(I.flex=h(x),!1!==u||I.minWidth||(I.minWidth=0)),k(t.createElement("div",Object.assign({},$,{style:Object.assign(Object.assign(Object.assign({},I),S),T),className:P,ref:n}),C))});e.s(["default",0,y],131757);var b=e.i(62139),w=e.i(782074),C=e.i(908709);let x=(0,e.i(246422).genSubStyleComponent)(["Form","item-item"],(e,{rootPrefixCls:t})=>(e=>{let{formItemCls:t}=e;return{"@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none)":{[`${t}-control`]:{display:"flex"}}}})((0,C.prepareToken)(e,t)));var S=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};e.s(["default",0,e=>{let{prefixCls:n,status:o,labelCol:a,wrapperCol:i,children:l,errors:s,warnings:c,_internalItemRender:u,extra:d,help:g,fieldId:h,marginBottom:v,onErrorVisibleChanged:C,label:$}=e,E=`${n}-item`,k=t.useContext(b.FormContext),O=t.useMemo(()=>{let e=Object.assign({},i||k.wrapperCol||{});return null!==$||a||i||!k.labelCol||[void 0,"xs","sm","md","lg","xl","xxl"].forEach(t=>{let r=t?[t]:[],n=(0,f.default)(k.labelCol,r),o="object"==typeof n?n:{},a=(0,f.default)(e,r);"span"in o&&!("offset"in("object"==typeof a?a:{}))&&o.span<24&&(e=(0,p.default)(e,[].concat(r,["offset"]),o.span))}),e},[i,k.wrapperCol,k.labelCol,$,a]),j=(0,r.default)(`${E}-control`,O.className),T=t.useMemo(()=>{let{labelCol:e,wrapperCol:t}=k;return S(k,["labelCol","wrapperCol"])},[k]),_=t.useRef(null),[P,I]=t.useState(0);(0,m.default)(()=>{d&&_.current?I(_.current.clientHeight):I(0)},[d]);let F=t.createElement("div",{className:`${E}-control-input`},t.createElement("div",{className:`${E}-control-input-content`},l)),N=t.useMemo(()=>({prefixCls:n,status:o}),[n,o]),R=null!==v||s.length||c.length?t.createElement(b.FormItemPrefixContext.Provider,{value:N},t.createElement(w.default,{fieldId:h,errors:s,warnings:c,help:g,helpStatus:o,className:`${E}-explain-connected`,onVisibleChanged:C})):null,M={};h&&(M.id=`${h}_extra`);let A=d?t.createElement("div",Object.assign({},M,{className:`${E}-extra`,ref:_}),d):null,B=R||A?t.createElement("div",{className:`${E}-additional`,style:v?{minHeight:v+P}:{}},R,A):null,z=u&&"pro_table_render"===u.mark&&u.render?u.render(e,{input:F,errorList:R,extra:A}):t.createElement(t.Fragment,null,F,B);return t.createElement(b.FormContext.Provider,{value:T},t.createElement(y,Object.assign({},O,{className:j}),z),t.createElement(x,{prefixCls:n}))}],292169)},684024,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={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:"M623.6 316.7C593.6 290.4 554 276 512 276s-81.6 14.5-111.6 40.7C369.2 344 352 380.7 352 420v7.6c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V420c0-44.1 43.1-80 96-80s96 35.9 96 80c0 31.1-22 59.6-56.1 72.7-21.2 8.1-39.2 22.3-52.1 40.9-13.1 19-19.9 41.8-19.9 64.9V620c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-22.7a48.3 48.3 0 0130.9-44.8c59-22.7 97.1-74.7 97.1-132.5.1-39.3-17.1-76-48.3-103.3zM472 732a40 40 0 1080 0 40 40 0 10-80 0z"}}]},name:"question-circle",theme:"outlined"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],684024)},995144,e=>{"use strict";var t=e.i(271645);e.s(["default",0,function(e){return null==e?null:"object"!=typeof e||(0,t.isValidElement)(e)?{title:e}:e}])},408850,929447,e=>{"use strict";var t=e.i(271645),r=e.i(595575),n=e.i(87414);let o=(e,o)=>{let a=t.useContext(r.default);return[t.useMemo(()=>{var t;let r=o||n.default[e],i=null!=(t=null==a?void 0:a[e])?t:{};return Object.assign(Object.assign({},"function"==typeof r?r():r),i||{})},[e,o,a]),t.useMemo(()=>{let e=null==a?void 0:a.locale;return(null==a?void 0:a.exist)&&!e?n.default.locale:e},[a])]};e.s(["default",0,o],929447),e.s(["useLocale",0,o],408850)},552821,e=>{"use strict";var t=e.i(343794),r=e.i(271645);function n(e){var n=e.children,o=e.prefixCls,a=e.id,i=e.overlayInnerStyle,l=e.bodyClassName,s=e.className,c=e.style;return r.createElement("div",{className:(0,t.default)("".concat(o,"-content"),s),style:c},r.createElement("div",{className:(0,t.default)("".concat(o,"-inner"),l),id:a,role:"tooltip",style:i},"function"==typeof n?n():n))}e.s(["default",()=>n])},951160,815289,e=>{"use strict";e.i(247167);var t,r=e.i(392221),n=e.i(271645),o=e.i(174080),a=e.i(654310);e.i(883110);var i=e.i(611935),l=n.createContext(null),s=e.i(8211),c=e.i(174428),u=[],d=e.i(575943);function f(e){var t,r,n="rc-scrollbar-measure-".concat(Math.random().toString(36).substring(7)),o=document.createElement("div");o.id=n;var a=o.style;if(a.position="absolute",a.left="0",a.top="0",a.width="100px",a.height="100px",a.overflow="scroll",e){var i=getComputedStyle(e);a.scrollbarColor=i.scrollbarColor,a.scrollbarWidth=i.scrollbarWidth;var l=getComputedStyle(e,"::-webkit-scrollbar"),s=parseInt(l.width,10),c=parseInt(l.height,10);try{var u=s?"width: ".concat(l.width,";"):"",f=c?"height: ".concat(l.height,";"):"";(0,d.updateCSS)("\n#".concat(n,"::-webkit-scrollbar {\n").concat(u,"\n").concat(f,"\n}"),n)}catch(e){console.error(e),t=s,r=c}}document.body.appendChild(o);var p=e&&t&&!isNaN(t)?t:o.offsetWidth-o.clientWidth,m=e&&r&&!isNaN(r)?r:o.offsetHeight-o.clientHeight;return document.body.removeChild(o),(0,d.removeCSS)(n),{width:p,height:m}}function p(e){return"u"p,"getTargetScrollBarSize",()=>m],815289);var g="rc-util-locker-".concat(Date.now()),h=0,v=function(e){return!1!==e&&((0,a.default)()&&e?"string"==typeof e?document.querySelector(e):"function"==typeof e?e():e:null)},y=n.forwardRef(function(e,t){var f,p,y,b=e.open,w=e.autoLock,C=e.getContainer,x=(e.debug,e.autoDestroy),S=void 0===x||x,$=e.children,E=n.useState(b),k=(0,r.default)(E,2),O=k[0],j=k[1],T=O||b;n.useEffect(function(){(S||b)&&j(b)},[b,S]);var _=n.useState(function(){return v(C)}),P=(0,r.default)(_,2),I=P[0],F=P[1];n.useEffect(function(){var e=v(C);F(null!=e?e:null)});var N=function(e,t){var o=n.useState(function(){return(0,a.default)()?document.createElement("div"):null}),i=(0,r.default)(o,1)[0],d=n.useRef(!1),f=n.useContext(l),p=n.useState(u),m=(0,r.default)(p,2),g=m[0],h=m[1],v=f||(d.current?void 0:function(e){h(function(t){return[e].concat((0,s.default)(t))})});function y(){i.parentElement||document.body.appendChild(i),d.current=!0}function b(){var e;null==(e=i.parentElement)||e.removeChild(i),d.current=!1}return(0,c.default)(function(){return e?f?f(y):y():b(),b},[e]),(0,c.default)(function(){g.length&&(g.forEach(function(e){return e()}),h(u))},[g]),[i,v]}(T&&!I,0),R=(0,r.default)(N,2),M=R[0],A=R[1],B=null!=I?I:M;f=!!(w&&b&&(0,a.default)()&&(B===M||B===document.body)),p=n.useState(function(){return h+=1,"".concat(g,"_").concat(h)}),y=(0,r.default)(p,1)[0],(0,c.default)(function(){if(f){var e=m(document.body).width,t=document.body.scrollHeight>(window.innerHeight||document.documentElement.clientHeight)&&window.innerWidth>document.body.offsetWidth;(0,d.updateCSS)("\nhtml body {\n overflow-y: hidden;\n ".concat(t?"width: calc(100% - ".concat(e,"px);"):"","\n}"),y)}else(0,d.removeCSS)(y);return function(){(0,d.removeCSS)(y)}},[f,y]);var z=null;$&&(0,i.supportRef)($)&&t&&(z=$.ref);var L=(0,i.useComposeRef)(z,t);if(!T||!(0,a.default)()||void 0===I)return null;var H=!1===B,D=$;return t&&(D=n.cloneElement($,{ref:L})),n.createElement(l.Provider,{value:A},H?D:(0,o.createPortal)(D,B))});e.s(["default",0,y],951160)},430073,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645),n=e.i(876556);e.i(883110);var o=e.i(209428),a=e.i(410160),i=e.i(279697),l=e.i(611935),s=r.createContext(null),c=function(){if("u">typeof Map)return Map;function e(e,t){var r=-1;return e.some(function(e,n){return e[0]===t&&(r=n,!0)}),r}function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var r=e(this.__entries__,t),n=this.__entries__[r];return n&&n[1]},t.prototype.set=function(t,r){var n=e(this.__entries__,t);~n?this.__entries__[n][1]=r:this.__entries__.push([t,r])},t.prototype.delete=function(t){var r=this.__entries__,n=e(r,t);~n&&r.splice(n,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var r=0,n=this.__entries__;rtypeof window&&"u">typeof document&&window.document===document,d=e.g.Math===Math?e.g:"u">typeof self&&self.Math===Math?self:"u">typeof window&&window.Math===Math?window:Function("return this")(),f="function"==typeof requestAnimationFrame?requestAnimationFrame.bind(d):function(e){return setTimeout(function(){return e(Date.now())},1e3/60)},p=["top","right","bottom","left","width","height","size","weight"],m="u">typeof MutationObserver,g=function(){function e(){this.connected_=!1,this.mutationEventsAdded_=!1,this.mutationsObserver_=null,this.observers_=[],this.onTransitionEnd_=this.onTransitionEnd_.bind(this),this.refresh=function(e,t){var r=!1,n=!1,o=0;function a(){r&&(r=!1,e()),n&&l()}function i(){f(a)}function l(){var e=Date.now();if(r){if(e-o<2)return;n=!0}else r=!0,n=!1,setTimeout(i,20);o=e}return l}(this.refresh.bind(this),0)}return e.prototype.addObserver=function(e){~this.observers_.indexOf(e)||this.observers_.push(e),this.connected_||this.connect_()},e.prototype.removeObserver=function(e){var t=this.observers_,r=t.indexOf(e);~r&&t.splice(r,1),!t.length&&this.connected_&&this.disconnect_()},e.prototype.refresh=function(){this.updateObservers_()&&this.refresh()},e.prototype.updateObservers_=function(){var e=this.observers_.filter(function(e){return e.gatherActive(),e.hasActive()});return e.forEach(function(e){return e.broadcastActive()}),e.length>0},e.prototype.connect_=function(){u&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),m?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){u&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,r=void 0===t?"":t;p.some(function(e){return!!~r.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),h=function(e,t){for(var r=0,n=Object.keys(t);rtypeof SVGGraphicsElement?function(e){return e instanceof v(e).SVGGraphicsElement}:function(e){return e instanceof v(e).SVGElement&&"function"==typeof e.getBBox};function x(e,t,r,n){return{x:e,y:t,width:r,height:n}}var S=function(){function e(e){this.broadcastWidth=0,this.broadcastHeight=0,this.contentRect_=x(0,0,0,0),this.target=e}return e.prototype.isActive=function(){var e=function(e){if(!u)return y;if(C(e)){var t;return x(0,0,(t=e.getBBox()).width,t.height)}return function(e){var t,r=e.clientWidth,n=e.clientHeight;if(!r&&!n)return y;var o=v(e).getComputedStyle(e),a=function(e){for(var t={},r=0,n=["top","right","bottom","left"];rtypeof DOMRectReadOnly?DOMRectReadOnly:Object).prototype),{x:r,y:n,width:o,height:a,top:n,right:r+o,bottom:a+n,left:r}),i);h(this,{target:e,contentRect:l})},E=function(){function e(e,t,r){if(this.activeObservations_=[],this.observations_=new c,"function"!=typeof e)throw TypeError("The callback provided as parameter 1 is not a function.");this.callback_=e,this.controller_=t,this.callbackCtx_=r}return e.prototype.observe=function(e){if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");if(!("u"0},e}(),k="u">typeof WeakMap?new WeakMap:new c,O=function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var r=new E(t,g.getInstance(),this);k.set(this,r)};["observe","unobserve","disconnect"].forEach(function(e){O.prototype[e]=function(){var t;return(t=k.get(this))[e].apply(t,arguments)}});var j=void 0!==d.ResizeObserver?d.ResizeObserver:O,T=new Map,_=new j(function(e){e.forEach(function(e){var t,r=e.target;null==(t=T.get(r))||t.forEach(function(e){return e(r)})})}),P=e.i(278409),I=e.i(233848),F=e.i(868917),N=e.i(674813),R=function(e){(0,F.default)(r,e);var t=(0,N.default)(r);function r(){return(0,P.default)(this,r),t.apply(this,arguments)}return(0,I.default)(r,[{key:"render",value:function(){return this.props.children}}]),r}(r.Component),M=r.forwardRef(function(e,t){var n=e.children,c=e.disabled,u=r.useRef(null),d=r.useRef(null),f=r.useContext(s),p="function"==typeof n,m=p?n(u):n,g=r.useRef({width:-1,height:-1,offsetWidth:-1,offsetHeight:-1}),h=!p&&r.isValidElement(m)&&(0,l.supportRef)(m),v=h?(0,l.getNodeRef)(m):null,y=(0,l.useComposeRef)(v,u),b=function(){var e;return(0,i.default)(u.current)||(u.current&&"object"===(0,a.default)(u.current)?(0,i.default)(null==(e=u.current)?void 0:e.nativeElement):null)||(0,i.default)(d.current)};r.useImperativeHandle(t,function(){return b()});var w=r.useRef(e);w.current=e;var C=r.useCallback(function(e){var t=w.current,r=t.onResize,n=t.data,a=e.getBoundingClientRect(),i=a.width,l=a.height,s=e.offsetWidth,c=e.offsetHeight,u=Math.floor(i),d=Math.floor(l);if(g.current.width!==u||g.current.height!==d||g.current.offsetWidth!==s||g.current.offsetHeight!==c){var p={width:u,height:d,offsetWidth:s,offsetHeight:c};g.current=p;var m=s===Math.round(i)?i:s,h=c===Math.round(l)?l:c,v=(0,o.default)((0,o.default)({},p),{},{offsetWidth:m,offsetHeight:h});null==f||f(v,e,n),r&&Promise.resolve().then(function(){r(v,e)})}},[]);return r.useEffect(function(){var e=b();return e&&!c&&(T.has(e)||(T.set(e,new Set),_.observe(e)),T.get(e).add(C)),function(){T.has(e)&&(T.get(e).delete(C),!T.get(e).size&&(_.unobserve(e),T.delete(e)))}},[u.current,c]),r.createElement(R,{ref:d},h?r.cloneElement(m,{ref:y}):m)}),A=r.forwardRef(function(e,o){var a=e.children;return("function"==typeof a?[a]:(0,n.default)(a)).map(function(n,a){var i=(null==n?void 0:n.key)||"".concat("rc-observer-key","-").concat(a);return r.createElement(M,(0,t.default)({},e,{key:i,ref:0===a?o:void 0}),n)})});A.Collection=function(e){var t=e.children,n=e.onBatchResize,o=r.useRef(0),a=r.useRef([]),i=r.useContext(s),l=r.useCallback(function(e,t,r){o.current+=1;var l=o.current;a.current.push({size:e,element:t,data:r}),Promise.resolve().then(function(){l===o.current&&(null==n||n(a.current),a.current=[])}),null==i||i(e,t,r)},[n,i]);return r.createElement(s.Provider,{value:l},t)},e.s(["default",0,A],430073)},981444,e=>{"use strict";var t=e.i(392221),r=e.i(209428),n=e.i(271645),o=0,a=(0,r.default)({},n).useId;let i=a?function(e){var t=a();return e||t}:function(e){var r=n.useState("ssr-id"),a=(0,t.default)(r,2),i=a[0],l=a[1];return(n.useEffect(function(){var e=o;o+=1,l("rc_unique_".concat(e))},[]),e)?e:i};e.s(["default",0,i])},614761,e=>{"use strict";e.s(["default",0,function(){if("u"{"use strict";e.i(247167);var t=e.i(931067),r=e.i(209428),n=e.i(392221),o=e.i(343794),a=e.i(361275),i=e.i(430073),l=e.i(174428),s=e.i(611935),c=e.i(271645);function u(e){var t=e.prefixCls,r=e.align,n=e.arrow,a=e.arrowPos,i=n||{},l=i.className,s=i.content,u=a.x,d=a.y,f=c.useRef();if(!r||!r.points)return null;var p={position:"absolute"};if(!1!==r.autoArrow){var m=r.points[0],g=r.points[1],h=m[0],v=m[1],y=g[0],b=g[1];h!==y&&["t","b"].includes(h)?"t"===h?p.top=0:p.bottom=0:p.top=void 0===d?0:d,v!==b&&["l","r"].includes(v)?"l"===v?p.left=0:p.right=0:p.left=void 0===u?0:u}return c.createElement("div",{ref:f,className:(0,o.default)("".concat(t,"-arrow"),l),style:p},s)}function d(e){var r=e.prefixCls,n=e.open,i=e.zIndex,l=e.mask,s=e.motion;return l?c.createElement(a.default,(0,t.default)({},s,{motionAppear:!0,visible:n,removeOnLeave:!0}),function(e){var t=e.className;return c.createElement("div",{style:{zIndex:i},className:(0,o.default)("".concat(r,"-mask"),t)})}):null}var f=c.memo(function(e){return e.children},function(e,t){return t.cache}),p=c.forwardRef(function(e,p){var m=e.popup,g=e.className,h=e.prefixCls,v=e.style,y=e.target,b=e.onVisibleChanged,w=e.open,C=e.keepDom,x=e.fresh,S=e.onClick,$=e.mask,E=e.arrow,k=e.arrowPos,O=e.align,j=e.motion,T=e.maskMotion,_=e.forceRender,P=e.getPopupContainer,I=e.autoDestroy,F=e.portal,N=e.zIndex,R=e.onMouseEnter,M=e.onMouseLeave,A=e.onPointerEnter,B=e.onPointerDownCapture,z=e.ready,L=e.offsetX,H=e.offsetY,D=e.offsetR,V=e.offsetB,W=e.onAlign,U=e.onPrepare,G=e.stretch,q=e.targetWidth,K=e.targetHeight,X="function"==typeof m?m():m,J=w||C,Y=(null==P?void 0:P.length)>0,Q=c.useState(!P||!Y),Z=(0,n.default)(Q,2),ee=Z[0],et=Z[1];if((0,l.default)(function(){!ee&&Y&&y&&et(!0)},[ee,Y,y]),!ee)return null;var er="auto",en={left:"-1000vw",top:"-1000vh",right:er,bottom:er};if(z||!w){var eo,ea=O.points,ei=O.dynamicInset||(null==(eo=O._experimental)?void 0:eo.dynamicInset),el=ei&&"r"===ea[0][1],es=ei&&"b"===ea[0][0];el?(en.right=D,en.left=er):(en.left=L,en.right=er),es?(en.bottom=V,en.top=er):(en.top=H,en.bottom=er)}var ec={};return G&&(G.includes("height")&&K?ec.height=K:G.includes("minHeight")&&K&&(ec.minHeight=K),G.includes("width")&&q?ec.width=q:G.includes("minWidth")&&q&&(ec.minWidth=q)),w||(ec.pointerEvents="none"),c.createElement(F,{open:_||J,getContainer:P&&function(){return P(y)},autoDestroy:I},c.createElement(d,{prefixCls:h,open:w,zIndex:N,mask:$,motion:T}),c.createElement(i.default,{onResize:W,disabled:!w},function(e){return c.createElement(a.default,(0,t.default)({motionAppear:!0,motionEnter:!0,motionLeave:!0,removeOnLeave:!1,forceRender:_,leavedClassName:"".concat(h,"-hidden")},j,{onAppearPrepare:U,onEnterPrepare:U,visible:w,onVisibleChanged:function(e){var t;null==j||null==(t=j.onVisibleChanged)||t.call(j,e),b(e)}}),function(t,n){var a=t.className,i=t.style,l=(0,o.default)(h,a,g);return c.createElement("div",{ref:(0,s.composeRef)(e,p,n),className:l,style:(0,r.default)((0,r.default)((0,r.default)((0,r.default)({"--arrow-x":"".concat(k.x||0,"px"),"--arrow-y":"".concat(k.y||0,"px")},en),ec),i),{},{boxSizing:"border-box",zIndex:N},v),onMouseEnter:R,onMouseLeave:M,onPointerEnter:A,onClick:S,onPointerDownCapture:B},E&&c.createElement(u,{prefixCls:h,arrow:E,arrowPos:k,align:O}),c.createElement(f,{cache:!w&&!x},X))})}))});e.s(["default",0,p],546004);var m=c.forwardRef(function(e,t){var r=e.children,n=e.getTriggerDOMNode,o=(0,s.supportRef)(r),a=c.useCallback(function(e){(0,s.fillRef)(t,n?n(e):e)},[n]),i=(0,s.useComposeRef)(a,(0,s.getNodeRef)(r));return o?c.cloneElement(r,{ref:i}):r});e.s(["default",0,m],508811);var g=c.createContext(null);function h(e){return e?Array.isArray(e)?e:[e]:[]}function v(e,t,r,n){return c.useMemo(function(){var o=h(null!=r?r:t),a=h(null!=n?n:t),i=new Set(o),l=new Set(a);return e&&(i.has("hover")&&(i.delete("hover"),i.add("click")),l.has("hover")&&(l.delete("hover"),l.add("click"))),[i,l]},[e,t,r,n])}e.s(["default",0,g],976637),e.s(["default",()=>v],920)},707067,e=>{"use strict";e.i(247167);var t=e.i(209428),r=e.i(392221),n=e.i(703923),o=e.i(951160),a=e.i(343794),i=e.i(430073),l=e.i(279697),s=e.i(909887),c=e.i(175066),u=e.i(981444),d=e.i(174428),f=e.i(614761),p=e.i(271645),m=e.i(546004),g=e.i(508811),h=e.i(976637),v=e.i(920),y=e.i(606262);function b(e,t,r,n){return t||(r?{motionName:"".concat(e,"-").concat(r)}:n?{motionName:n}:null)}function w(e){return e.ownerDocument.defaultView}function C(e){for(var t=[],r=null==e?void 0:e.parentElement,n=["hidden","scroll","clip","auto"];r;){var o=w(r).getComputedStyle(r);[o.overflowX,o.overflowY,o.overflow].some(function(e){return n.includes(e)})&&t.push(r),r=r.parentElement}return t}function x(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return Number.isNaN(e)?t:e}function S(e){return x(parseFloat(e),0)}function $(e,r){var n=(0,t.default)({},e);return(r||[]).forEach(function(e){if(!(e instanceof HTMLBodyElement||e instanceof HTMLHtmlElement)){var t=w(e).getComputedStyle(e),r=t.overflow,o=t.overflowClipMargin,a=t.borderTopWidth,i=t.borderBottomWidth,l=t.borderLeftWidth,s=t.borderRightWidth,c=e.getBoundingClientRect(),u=e.offsetHeight,d=e.clientHeight,f=e.offsetWidth,p=e.clientWidth,m=S(a),g=S(i),h=S(l),v=S(s),y=x(Math.round(c.width/f*1e3)/1e3),b=x(Math.round(c.height/u*1e3)/1e3),C=m*b,$=h*y,E=0,k=0;if("clip"===r){var O=S(o);E=O*y,k=O*b}var j=c.x+$-E,T=c.y+C-k,_=j+c.width+2*E-$-v*y-(f-p-h-v)*y,P=T+c.height+2*k-C-g*b-(u-d-m-g)*b;n.left=Math.max(n.left,j),n.top=Math.max(n.top,T),n.right=Math.min(n.right,_),n.bottom=Math.min(n.bottom,P)}}),n}function E(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r="".concat(t),n=r.match(/^(.*)\%$/);return n?e*(parseFloat(n[1])/100):parseFloat(r)}function k(e,t){var n=(0,r.default)(t||[],2),o=n[0],a=n[1];return[E(e.width,o),E(e.height,a)]}function O(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return[e[0],e[1]]}function j(e,t){var r,n=t[0],o=t[1];return r="t"===n?e.y:"b"===n?e.y+e.height:e.y+e.height/2,{x:"l"===o?e.x:"r"===o?e.x+e.width:e.x+e.width/2,y:r}}function T(e,t){var r={t:"b",b:"t",l:"r",r:"l"};return e.map(function(e,n){return n===t?r[e]||"c":e}).join("")}var _=e.i(8211);e.i(883110);var P=["prefixCls","children","action","showAction","hideAction","popupVisible","defaultPopupVisible","onPopupVisibleChange","afterPopupVisibleChange","mouseEnterDelay","mouseLeaveDelay","focusDelay","blurDelay","mask","maskClosable","getPopupContainer","forceRender","autoDestroy","destroyPopupOnHide","popup","popupClassName","popupStyle","popupPlacement","builtinPlacements","popupAlign","zIndex","stretch","getPopupClassNameFromAlign","fresh","alignPoint","onPopupClick","onPopupAlign","arrow","popupMotion","maskMotion","popupTransitionName","popupAnimation","maskTransitionName","maskAnimation","className","getTriggerDOMNode"];let I=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o.default;return p.forwardRef(function(o,S){var E,I,F,N,R,M,A,B,z,L,H,D,V,W,U,G,q=o.prefixCls,K=void 0===q?"rc-trigger-popup":q,X=o.children,J=o.action,Y=o.showAction,Q=o.hideAction,Z=o.popupVisible,ee=o.defaultPopupVisible,et=o.onPopupVisibleChange,er=o.afterPopupVisibleChange,en=o.mouseEnterDelay,eo=o.mouseLeaveDelay,ea=void 0===eo?.1:eo,ei=o.focusDelay,el=o.blurDelay,es=o.mask,ec=o.maskClosable,eu=o.getPopupContainer,ed=o.forceRender,ef=o.autoDestroy,ep=o.destroyPopupOnHide,em=o.popup,eg=o.popupClassName,eh=o.popupStyle,ev=o.popupPlacement,ey=o.builtinPlacements,eb=void 0===ey?{}:ey,ew=o.popupAlign,eC=o.zIndex,ex=o.stretch,eS=o.getPopupClassNameFromAlign,e$=o.fresh,eE=o.alignPoint,ek=o.onPopupClick,eO=o.onPopupAlign,ej=o.arrow,eT=o.popupMotion,e_=o.maskMotion,eP=o.popupTransitionName,eI=o.popupAnimation,eF=o.maskTransitionName,eN=o.maskAnimation,eR=o.className,eM=o.getTriggerDOMNode,eA=(0,n.default)(o,P),eB=p.useState(!1),ez=(0,r.default)(eB,2),eL=ez[0],eH=ez[1];(0,d.default)(function(){eH((0,f.default)())},[]);var eD=p.useRef({}),eV=p.useContext(h.default),eW=p.useMemo(function(){return{registerSubPopup:function(e,t){eD.current[e]=t,null==eV||eV.registerSubPopup(e,t)}}},[eV]),eU=(0,u.default)(),eG=p.useState(null),eq=(0,r.default)(eG,2),eK=eq[0],eX=eq[1],eJ=p.useRef(null),eY=(0,c.default)(function(e){eJ.current=e,(0,l.isDOM)(e)&&eK!==e&&eX(e),null==eV||eV.registerSubPopup(eU,e)}),eQ=p.useState(null),eZ=(0,r.default)(eQ,2),e0=eZ[0],e1=eZ[1],e2=p.useRef(null),e4=(0,c.default)(function(e){(0,l.isDOM)(e)&&e0!==e&&(e1(e),e2.current=e)}),e6=p.Children.only(X),e5=(null==e6?void 0:e6.props)||{},e3={},e7=(0,c.default)(function(e){var t,r;return(null==e0?void 0:e0.contains(e))||(null==(t=(0,s.getShadowRoot)(e0))?void 0:t.host)===e||e===e0||(null==eK?void 0:eK.contains(e))||(null==(r=(0,s.getShadowRoot)(eK))?void 0:r.host)===e||e===eK||Object.values(eD.current).some(function(t){return(null==t?void 0:t.contains(e))||e===t})}),e8=b(K,eT,eI,eP),e9=b(K,e_,eN,eF),te=p.useState(ee||!1),tt=(0,r.default)(te,2),tr=tt[0],tn=tt[1],to=null!=Z?Z:tr,ta=(0,c.default)(function(e){void 0===Z&&tn(e)});(0,d.default)(function(){tn(Z||!1)},[Z]);var ti=p.useRef(to);ti.current=to;var tl=p.useRef([]);tl.current=[];var ts=(0,c.default)(function(e){var t;ta(e),(null!=(t=tl.current[tl.current.length-1])?t:to)!==e&&(tl.current.push(e),null==et||et(e))}),tc=p.useRef(),tu=function(){clearTimeout(tc.current)},td=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;tu(),0===t?ts(e):tc.current=setTimeout(function(){ts(e)},1e3*t)};p.useEffect(function(){return tu},[]);var tf=p.useState(!1),tp=(0,r.default)(tf,2),tm=tp[0],tg=tp[1];(0,d.default)(function(e){(!e||to)&&tg(!0)},[to]);var th=p.useState(null),tv=(0,r.default)(th,2),ty=tv[0],tb=tv[1],tw=p.useState(null),tC=(0,r.default)(tw,2),tx=tC[0],tS=tC[1],t$=function(e){tS([e.clientX,e.clientY])},tE=(E=eE&&null!==tx?tx:e0,I=p.useState({ready:!1,offsetX:0,offsetY:0,offsetR:0,offsetB:0,arrowX:0,arrowY:0,scaleX:1,scaleY:1,align:eb[ev]||{}}),N=(F=(0,r.default)(I,2))[0],R=F[1],M=p.useRef(0),A=p.useMemo(function(){return eK?C(eK):[]},[eK]),B=p.useRef({}),to||(B.current={}),z=(0,c.default)(function(){if(eK&&E&&to){var e=eK.ownerDocument,n=w(eK),o=n.getComputedStyle(eK).position,a=eK.style.left,i=eK.style.top,s=eK.style.right,c=eK.style.bottom,u=eK.style.overflow,d=(0,t.default)((0,t.default)({},eb[ev]),ew),f=e.createElement("div");if(null==(v=eK.parentElement)||v.appendChild(f),f.style.left="".concat(eK.offsetLeft,"px"),f.style.top="".concat(eK.offsetTop,"px"),f.style.position=o,f.style.height="".concat(eK.offsetHeight,"px"),f.style.width="".concat(eK.offsetWidth,"px"),eK.style.left="0",eK.style.top="0",eK.style.right="auto",eK.style.bottom="auto",eK.style.overflow="hidden",Array.isArray(E))_={x:E[0],y:E[1],width:0,height:0};else{var p,m,g,h,v,b,C,S,_,P,I,F=E.getBoundingClientRect();F.x=null!=(P=F.x)?P:F.left,F.y=null!=(I=F.y)?I:F.top,_={x:F.x,y:F.y,width:F.width,height:F.height}}var N=eK.getBoundingClientRect(),M=n.getComputedStyle(eK),z=M.height,L=M.width;N.x=null!=(b=N.x)?b:N.left,N.y=null!=(C=N.y)?C:N.top;var H=e.documentElement,D=H.clientWidth,V=H.clientHeight,W=H.scrollWidth,U=H.scrollHeight,G=H.scrollTop,q=H.scrollLeft,K=N.height,X=N.width,J=_.height,Y=_.width,Q=d.htmlRegion,Z="visible",ee="visibleFirst";"scroll"!==Q&&Q!==ee&&(Q=Z);var et=Q===ee,er=$({left:-q,top:-G,right:W-q,bottom:U-G},A),en=$({left:0,top:0,right:D,bottom:V},A),eo=Q===Z?en:er,ea=et?en:eo;eK.style.left="auto",eK.style.top="auto",eK.style.right="0",eK.style.bottom="0";var ei=eK.getBoundingClientRect();eK.style.left=a,eK.style.top=i,eK.style.right=s,eK.style.bottom=c,eK.style.overflow=u,null==(S=eK.parentElement)||S.removeChild(f);var el=x(Math.round(X/parseFloat(L)*1e3)/1e3),es=x(Math.round(K/parseFloat(z)*1e3)/1e3);if(!(0===el||0===es||(0,l.isDOM)(E)&&!(0,y.default)(E))){var ec=d.offset,eu=d.targetOffset,ed=k(N,ec),ef=(0,r.default)(ed,2),ep=ef[0],em=ef[1],eg=k(_,eu),eh=(0,r.default)(eg,2),ey=eh[0],eC=eh[1];_.x-=ey,_.y-=eC;var ex=d.points||[],eS=(0,r.default)(ex,2),e$=eS[0],eE=O(eS[1]),ek=O(e$),ej=j(_,eE),eT=j(N,ek),e_=(0,t.default)({},d),eP=ej.x-eT.x+ep,eI=ej.y-eT.y+em,eF=td(eP,eI),eN=td(eP,eI,en),eR=j(_,["t","l"]),eM=j(N,["t","l"]),eA=j(_,["b","r"]),eB=j(N,["b","r"]),ez=d.overflow||{},eL=ez.adjustX,eH=ez.adjustY,eD=ez.shiftX,eV=ez.shiftY,eW=function(e){return"boolean"==typeof e?e:e>=0};tf();var eU=eW(eH),eG=ek[0]===eE[0];if(eU&&"t"===ek[0]&&(m>ea.bottom||B.current.bt)){var eq=eI;eG?eq-=K-J:eq=eR.y-eB.y-em;var eX=td(eP,eq),eJ=td(eP,eq,en);eX>eF||eX===eF&&(!et||eJ>=eN)?(B.current.bt=!0,eI=eq,em=-em,e_.points=[T(ek,0),T(eE,0)]):B.current.bt=!1}if(eU&&"b"===ek[0]&&(peF||eQ===eF&&(!et||eZ>=eN)?(B.current.tb=!0,eI=eY,em=-em,e_.points=[T(ek,0),T(eE,0)]):B.current.tb=!1}var e0=eW(eL),e1=ek[1]===eE[1];if(e0&&"l"===ek[1]&&(h>ea.right||B.current.rl)){var e2=eP;e1?e2-=X-Y:e2=eR.x-eB.x-ep;var e4=td(e2,eI),e6=td(e2,eI,en);e4>eF||e4===eF&&(!et||e6>=eN)?(B.current.rl=!0,eP=e2,ep=-ep,e_.points=[T(ek,1),T(eE,1)]):B.current.rl=!1}if(e0&&"r"===ek[1]&&(geF||e3===eF&&(!et||e7>=eN)?(B.current.lr=!0,eP=e5,ep=-ep,e_.points=[T(ek,1),T(eE,1)]):B.current.lr=!1}tf();var e8=!0===eD?0:eD;"number"==typeof e8&&(gen.right&&(eP-=h-en.right-ep,_.x>en.right-e8&&(eP+=_.x-en.right+e8)));var e9=!0===eV?0:eV;"number"==typeof e9&&(pen.bottom&&(eI-=m-en.bottom-em,_.y>en.bottom-e9&&(eI+=_.y-en.bottom+e9)));var te=N.x+eP,tt=N.y+eI,tr=_.x,tn=_.y,ta=Math.max(te,tr),ti=Math.min(te+X,tr+Y),tl=Math.max(tt,tn),ts=Math.min(tt+K,tn+J);null==eO||eO(eK,e_);var tc=ei.right-N.x-(eP+N.width),tu=ei.bottom-N.y-(eI+N.height);1===el&&(eP=Math.floor(eP),tc=Math.floor(tc)),1===es&&(eI=Math.floor(eI),tu=Math.floor(tu)),R({ready:!0,offsetX:eP/el,offsetY:eI/es,offsetR:tc/el,offsetB:tu/es,arrowX:((ta+ti)/2-te)/el,arrowY:((tl+ts)/2-tt)/es,scaleX:el,scaleY:es,align:e_})}function td(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:eo,n=N.x+e,o=N.y+t,a=Math.max(n,r.left),i=Math.max(o,r.top);return Math.max(0,(Math.min(n+X,r.right)-a)*(Math.min(o+K,r.bottom)-i))}function tf(){m=(p=N.y+eI)+K,h=(g=N.x+eP)+X}}}),L=function(){R(function(e){return(0,t.default)((0,t.default)({},e),{},{ready:!1})})},(0,d.default)(L,[ev]),(0,d.default)(function(){to||L()},[to]),[N.ready,N.offsetX,N.offsetY,N.offsetR,N.offsetB,N.arrowX,N.arrowY,N.scaleX,N.scaleY,N.align,function(){M.current+=1;var e=M.current;Promise.resolve().then(function(){M.current===e&&z()})}]),tk=(0,r.default)(tE,11),tO=tk[0],tj=tk[1],tT=tk[2],t_=tk[3],tP=tk[4],tI=tk[5],tF=tk[6],tN=tk[7],tR=tk[8],tM=tk[9],tA=tk[10],tB=(0,v.default)(eL,void 0===J?"hover":J,Y,Q),tz=(0,r.default)(tB,2),tL=tz[0],tH=tz[1],tD=tL.has("click"),tV=tH.has("click")||tH.has("contextMenu"),tW=(0,c.default)(function(){tm||tA()});H=function(){ti.current&&eE&&tV&&td(!1)},(0,d.default)(function(){if(to&&e0&&eK){var e=C(e0),t=C(eK),r=w(eK),n=new Set([r].concat((0,_.default)(e),(0,_.default)(t)));function o(){tW(),H()}return n.forEach(function(e){e.addEventListener("scroll",o,{passive:!0})}),r.addEventListener("resize",o,{passive:!0}),tW(),function(){n.forEach(function(e){e.removeEventListener("scroll",o),r.removeEventListener("resize",o)})}}},[to,e0,eK]),(0,d.default)(function(){tW()},[tx,ev]),(0,d.default)(function(){to&&!(null!=eb&&eb[ev])&&tW()},[JSON.stringify(ew)]);var tU=p.useMemo(function(){var e=function(e,t,r,n){for(var o=r.points,a=Object.keys(e),i=0;i0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],r=arguments.length>2?arguments[2]:void 0;return r?e[0]===t[0]:e[0]===t[0]&&e[1]===t[1]}(null==(l=e[s])?void 0:l.points,o,n))return"".concat(t,"-placement-").concat(s)}return""}(eb,K,tM,eE);return(0,a.default)(e,null==eS?void 0:eS(tM))},[tM,eS,eb,K,eE]);p.useImperativeHandle(S,function(){return{nativeElement:e2.current,popupElement:eJ.current,forceAlign:tW}});var tG=p.useState(0),tq=(0,r.default)(tG,2),tK=tq[0],tX=tq[1],tJ=p.useState(0),tY=(0,r.default)(tJ,2),tQ=tY[0],tZ=tY[1],t0=function(){if(ex&&e0){var e=e0.getBoundingClientRect();tX(e.width),tZ(e.height)}};function t1(e,t,r,n){e3[e]=function(o){var a;null==n||n(o),td(t,r);for(var i=arguments.length,l=Array(i>1?i-1:0),s=1;s1?r-1:0),o=1;o1?r-1:0),o=1;o{"use strict";var t=e.i(552821),r=e.i(931067),n=e.i(209428),o=e.i(703923),a=e.i(707067),i=e.i(343794),l=e.i(271645),s={shiftX:64,adjustY:1},c={adjustX:1,shiftY:!0},u=[0,0],d={left:{points:["cr","cl"],overflow:c,offset:[-4,0],targetOffset:u},right:{points:["cl","cr"],overflow:c,offset:[4,0],targetOffset:u},top:{points:["bc","tc"],overflow:s,offset:[0,-4],targetOffset:u},bottom:{points:["tc","bc"],overflow:s,offset:[0,4],targetOffset:u},topLeft:{points:["bl","tl"],overflow:s,offset:[0,-4],targetOffset:u},leftTop:{points:["tr","tl"],overflow:c,offset:[-4,0],targetOffset:u},topRight:{points:["br","tr"],overflow:s,offset:[0,-4],targetOffset:u},rightTop:{points:["tl","tr"],overflow:c,offset:[4,0],targetOffset:u},bottomRight:{points:["tr","br"],overflow:s,offset:[0,4],targetOffset:u},rightBottom:{points:["bl","br"],overflow:c,offset:[4,0],targetOffset:u},bottomLeft:{points:["tl","bl"],overflow:s,offset:[0,4],targetOffset:u},leftBottom:{points:["br","bl"],overflow:c,offset:[-4,0],targetOffset:u}},f=e.i(981444),p=["overlayClassName","trigger","mouseEnterDelay","mouseLeaveDelay","overlayStyle","prefixCls","children","onVisibleChange","afterVisibleChange","transitionName","animation","motion","placement","align","destroyTooltipOnHide","defaultVisible","getTooltipContainer","overlayInnerStyle","arrowContent","overlay","id","showArrow","classNames","styles"];let m=(0,l.forwardRef)(function(e,s){var c,u,m,g=e.overlayClassName,h=e.trigger,v=e.mouseEnterDelay,y=e.mouseLeaveDelay,b=e.overlayStyle,w=e.prefixCls,C=void 0===w?"rc-tooltip":w,x=e.children,S=e.onVisibleChange,$=e.afterVisibleChange,E=e.transitionName,k=e.animation,O=e.motion,j=e.placement,T=e.align,_=e.destroyTooltipOnHide,P=e.defaultVisible,I=e.getTooltipContainer,F=e.overlayInnerStyle,N=(e.arrowContent,e.overlay),R=e.id,M=e.showArrow,A=e.classNames,B=e.styles,z=(0,o.default)(e,p),L=(0,f.default)(R),H=(0,l.useRef)(null);(0,l.useImperativeHandle)(s,function(){return H.current});var D=(0,n.default)({},z);return"visible"in e&&(D.popupVisible=e.visible),l.createElement(a.default,(0,r.default)({popupClassName:(0,i.default)(g,null==A?void 0:A.root),prefixCls:C,popup:function(){return l.createElement(t.default,{key:"content",prefixCls:C,id:L,bodyClassName:null==A?void 0:A.body,overlayInnerStyle:(0,n.default)((0,n.default)({},F),null==B?void 0:B.body)},N)},action:void 0===h?["hover"]:h,builtinPlacements:d,popupPlacement:void 0===j?"right":j,ref:H,popupAlign:void 0===T?{}:T,getPopupContainer:I,onPopupVisibleChange:S,afterPopupVisibleChange:$,popupTransitionName:E,popupAnimation:k,popupMotion:O,defaultPopupVisible:P,autoDestroy:void 0!==_&&_,mouseLeaveDelay:void 0===y?.1:y,popupStyle:(0,n.default)((0,n.default)({},b),null==B?void 0:B.root),mouseEnterDelay:void 0===v?0:v,arrow:void 0===M||M},D),(u=(null==(c=l.Children.only(x))?void 0:c.props)||{},m=(0,n.default)((0,n.default)({},u),{},{"aria-describedby":N?L:null}),l.cloneElement(x,m)))});e.s(["default",0,m],793154)},249616,e=>{"use strict";var t=e.i(271645),r=e.i(343794),n=e.i(876556),o=e.i(242064),a=e.i(517455);let i=(0,e.i(246422).genStyleHooks)(["Space","Compact"],e=>[(e=>{let{componentCls:t}=e;return{[t]:{display:"inline-flex","&-block":{display:"flex",width:"100%"},"&-vertical":{flexDirection:"column"},"&-rtl":{direction:"rtl"}}}})(e)],()=>({}),{resetStyle:!1});var l=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 s=t.createContext(null),c=e=>{let{children:r}=e,n=l(e,["children"]);return t.createElement(s.Provider,{value:t.useMemo(()=>n,[n])},r)};e.s(["NoCompactStyle",0,e=>{let{children:r}=e;return t.createElement(s.Provider,{value:null},r)},"default",0,e=>{let{getPrefixCls:u,direction:d}=t.useContext(o.ConfigContext),{size:f,direction:p,block:m,prefixCls:g,className:h,rootClassName:v,children:y}=e,b=l(e,["size","direction","block","prefixCls","className","rootClassName","children"]),w=(0,a.default)(e=>null!=f?f:e),C=u("space-compact",g),[x,S]=i(C),$=(0,r.default)(C,S,{[`${C}-rtl`]:"rtl"===d,[`${C}-block`]:m,[`${C}-vertical`]:"vertical"===p},h,v),E=t.useContext(s),k=(0,n.default)(y),O=t.useMemo(()=>k.map((e,r)=>{let n=(null==e?void 0:e.key)||`${C}-item-${r}`;return t.createElement(c,{key:n,compactSize:w,compactDirection:p,isFirstItem:0===r&&(!E||(null==E?void 0:E.isFirstItem)),isLastItem:r===k.length-1&&(!E||(null==E?void 0:E.isLastItem))},e)}),[k,E,p,w,C]);return 0===k.length?null:x(t.createElement("div",Object.assign({className:$},b),O))},"useCompactItemContext",0,(e,n)=>{let o=t.useContext(s),a=t.useMemo(()=>{if(!o)return"";let{compactDirection:t,isFirstItem:a,isLastItem:i}=o,l="vertical"===t?"-vertical-":"-";return(0,r.default)(`${e}-compact${l}item`,{[`${e}-compact${l}first-item`]:a,[`${e}-compact${l}last-item`]:i,[`${e}-compact${l}item-rtl`]:"rtl"===n})},[e,n,o]);return{compactSize:null==o?void 0:o.compactSize,compactDirection:null==o?void 0:o.compactDirection,compactItemClassnames:a}}],249616)},617206,e=>{"use strict";var t=e.i(271645),r=e.i(62139),n=e.i(249616);e.s(["default",0,e=>{let{space:o,form:a,children:i}=e;if(null==i)return null;let l=i;return a&&(l=t.default.createElement(r.NoFormStyle,{override:!0,status:!0},l)),o&&(l=t.default.createElement(n.NoCompactStyle,null,l)),l}])},805984,307358,320560,e=>{"use strict";e.i(296059);var t=e.i(915654);function r(e){let{sizePopupArrow:t,borderRadiusXS:r,borderRadiusOuter:n}=e,o=t/2,a=n/Math.sqrt(2),i=o-n*(1-1/Math.sqrt(2)),l=o-1/Math.sqrt(2)*r,s=n*(Math.sqrt(2)-1)+1/Math.sqrt(2)*r,c=o*Math.sqrt(2)+n*(Math.sqrt(2)-2),u=n*(Math.sqrt(2)-1),d=`polygon(${u}px 100%, 50% ${u}px, ${2*o-u}px 100%, ${u}px 100%)`;return{arrowShadowWidth:c,arrowPath:`path('M 0 ${o} A ${n} ${n} 0 0 0 ${a} ${i} L ${l} ${s} A ${r} ${r} 0 0 1 ${2*o-l} ${s} L ${2*o-a} ${i} A ${n} ${n} 0 0 0 ${2*o-0} ${o} Z')`,arrowPolygon:d}}let n=(e,r,n)=>{let{sizePopupArrow:o,arrowPolygon:a,arrowPath:i,arrowShadowWidth:l,borderRadiusXS:s,calc:c}=e;return{pointerEvents:"none",width:o,height:o,overflow:"hidden","&::before":{position:"absolute",bottom:0,insetInlineStart:0,width:o,height:c(o).div(2).equal(),background:r,clipPath:{_multi_value_:!0,value:[a,i]},content:'""'},"&::after":{content:'""',position:"absolute",width:l,height:l,bottom:0,insetInline:0,margin:"auto",borderRadius:{_skip_check_:!0,value:`0 0 ${(0,t.unit)(s)} 0`},transform:"translateY(50%) rotate(-135deg)",boxShadow:n,zIndex:0,background:"transparent"}}};function o(e){let{contentRadius:t,limitVerticalRadius:r}=e,n=t>12?t+2:12;return{arrowOffsetHorizontal:n,arrowOffsetVertical:r?8:n}}function a(e,r,o){var a,i,l,s,c,u,d,f;let{componentCls:p,boxShadowPopoverArrow:m,arrowOffsetVertical:g,arrowOffsetHorizontal:h}=e,{arrowDistance:v=0,arrowPlacement:y={left:!0,right:!0,top:!0,bottom:!0}}=o||{};return{[p]:Object.assign(Object.assign(Object.assign(Object.assign({[`${p}-arrow`]:[Object.assign(Object.assign({position:"absolute",zIndex:1,display:"block"},n(e,r,m)),{"&:before":{background:r}})]},(a=!!y.top,i={[`&-placement-top > ${p}-arrow,&-placement-topLeft > ${p}-arrow,&-placement-topRight > ${p}-arrow`]:{bottom:v,transform:"translateY(100%) rotate(180deg)"},[`&-placement-top > ${p}-arrow`]:{left:{_skip_check_:!0,value:"50%"},transform:"translateX(-50%) translateY(100%) rotate(180deg)"},"&-placement-topLeft":{"--arrow-offset-horizontal":h,[`> ${p}-arrow`]:{left:{_skip_check_:!0,value:h}}},"&-placement-topRight":{"--arrow-offset-horizontal":`calc(100% - ${(0,t.unit)(h)})`,[`> ${p}-arrow`]:{right:{_skip_check_:!0,value:h}}}},a?i:{})),(l=!!y.bottom,s={[`&-placement-bottom > ${p}-arrow,&-placement-bottomLeft > ${p}-arrow,&-placement-bottomRight > ${p}-arrow`]:{top:v,transform:"translateY(-100%)"},[`&-placement-bottom > ${p}-arrow`]:{left:{_skip_check_:!0,value:"50%"},transform:"translateX(-50%) translateY(-100%)"},"&-placement-bottomLeft":{"--arrow-offset-horizontal":h,[`> ${p}-arrow`]:{left:{_skip_check_:!0,value:h}}},"&-placement-bottomRight":{"--arrow-offset-horizontal":`calc(100% - ${(0,t.unit)(h)})`,[`> ${p}-arrow`]:{right:{_skip_check_:!0,value:h}}}},l?s:{})),(c=!!y.left,u={[`&-placement-left > ${p}-arrow,&-placement-leftTop > ${p}-arrow,&-placement-leftBottom > ${p}-arrow`]:{right:{_skip_check_:!0,value:v},transform:"translateX(100%) rotate(90deg)"},[`&-placement-left > ${p}-arrow`]:{top:{_skip_check_:!0,value:"50%"},transform:"translateY(-50%) translateX(100%) rotate(90deg)"},[`&-placement-leftTop > ${p}-arrow`]:{top:g},[`&-placement-leftBottom > ${p}-arrow`]:{bottom:g}},c?u:{})),(d=!!y.right,f={[`&-placement-right > ${p}-arrow,&-placement-rightTop > ${p}-arrow,&-placement-rightBottom > ${p}-arrow`]:{left:{_skip_check_:!0,value:v},transform:"translateX(-100%) rotate(-90deg)"},[`&-placement-right > ${p}-arrow`]:{top:{_skip_check_:!0,value:"50%"},transform:"translateY(-50%) translateX(-100%) rotate(-90deg)"},[`&-placement-rightTop > ${p}-arrow`]:{top:g},[`&-placement-rightBottom > ${p}-arrow`]:{bottom:g}},d?f:{}))}}e.s(["genRoundedArrow",0,n,"getArrowToken",()=>r],307358),e.s(["MAX_VERTICAL_CONTENT_RADIUS",0,8,"default",()=>a,"getArrowOffsetToken",()=>o],320560);let i={left:{points:["cr","cl"]},right:{points:["cl","cr"]},top:{points:["bc","tc"]},bottom:{points:["tc","bc"]},topLeft:{points:["bl","tl"]},leftTop:{points:["tr","tl"]},topRight:{points:["br","tr"]},rightTop:{points:["tl","tr"]},bottomRight:{points:["tr","br"]},rightBottom:{points:["bl","br"]},bottomLeft:{points:["tl","bl"]},leftBottom:{points:["br","bl"]}},l={topLeft:{points:["bl","tc"]},leftTop:{points:["tr","cl"]},topRight:{points:["br","tc"]},rightTop:{points:["tl","cr"]},bottomRight:{points:["tr","bc"]},rightBottom:{points:["bl","cr"]},bottomLeft:{points:["tl","bc"]},leftBottom:{points:["br","cl"]}},s=new Set(["topLeft","topRight","bottomLeft","bottomRight","leftTop","leftBottom","rightTop","rightBottom"]);function c(e){let{arrowWidth:t,autoAdjustOverflow:r,arrowPointAtCenter:n,offset:a,borderRadius:c,visibleFirst:u}=e,d=t/2,f={},p=o({contentRadius:c,limitVerticalRadius:!0});return Object.keys(i).forEach(e=>{let o=Object.assign(Object.assign({},n&&l[e]||i[e]),{offset:[0,0],dynamicInset:!0});switch(f[e]=o,s.has(e)&&(o.autoArrow=!1),e){case"top":case"topLeft":case"topRight":o.offset[1]=-d-a;break;case"bottom":case"bottomLeft":case"bottomRight":o.offset[1]=d+a;break;case"left":case"leftTop":case"leftBottom":o.offset[0]=-d-a;break;case"right":case"rightTop":case"rightBottom":o.offset[0]=d+a}if(n)switch(e){case"topLeft":case"bottomLeft":o.offset[0]=-p.arrowOffsetHorizontal-d;break;case"topRight":case"bottomRight":o.offset[0]=p.arrowOffsetHorizontal+d;break;case"leftTop":case"rightTop":o.offset[1]=-(2*p.arrowOffsetHorizontal)+d;break;case"leftBottom":case"rightBottom":o.offset[1]=2*p.arrowOffsetHorizontal-d}o.overflow=function(e,t,r,n){if(!1===n)return{adjustX:!1,adjustY:!1};let o={};switch(e){case"top":case"bottom":o.shiftX=2*t.arrowOffsetHorizontal+r,o.shiftY=!0,o.adjustY=!0;break;case"left":case"right":o.shiftY=2*t.arrowOffsetVertical+r,o.shiftX=!0,o.adjustX=!0}let a=Object.assign(Object.assign({},o),n&&"object"==typeof n?n:{});return a.shiftX||(a.adjustX=!0),a.shiftY||(a.adjustY=!0),a}(e,p,t,r),u&&(o.htmlRegion="visibleFirst")}),f}e.s(["default",()=>c],805984)},880476,e=>{"use strict";var t=e.i(552821);e.s(["Popup",()=>t.default])},617933,e=>{"use strict";e.s(["PresetColors",0,["blue","purple","cyan","green","magenta","pink","red","orange","yellow","volcano","geekblue","lime","gold"]])},403541,e=>{"use strict";var t=e.i(617933);function r(e,r){return t.PresetColors.reduce((t,n)=>{let o=e[`${n}1`],a=e[`${n}3`],i=e[`${n}6`],l=e[`${n}7`];return Object.assign(Object.assign({},t),r(n,{lightColor:o,lightBorderColor:a,darkColor:i,textColor:l}))},{})}e.s(["genPresetColor",()=>r],403541)},57667,e=>{"use strict";e.i(296059);var t=e.i(915654),r=e.i(183293),n=e.i(717356),o=e.i(320560),a=e.i(307358),i=e.i(403541),l=e.i(246422),s=e.i(838378);let c=e=>Object.assign(Object.assign({zIndexPopup:e.zIndexPopupBase+70},(0,o.getArrowOffsetToken)({contentRadius:e.borderRadius,limitVerticalRadius:!0})),(0,a.getArrowToken)((0,s.mergeToken)(e,{borderRadiusOuter:Math.min(e.borderRadiusOuter,4)})));e.s(["default",0,(e,a=!0)=>(0,l.genStyleHooks)("Tooltip",e=>{let{borderRadius:a,colorTextLightSolid:l,colorBgSpotlight:c}=e;return[(e=>{let{calc:n,componentCls:a,tooltipMaxWidth:l,tooltipColor:s,tooltipBg:c,tooltipBorderRadius:u,zIndexPopup:d,controlHeight:f,boxShadowSecondary:p,paddingSM:m,paddingXS:g,arrowOffsetHorizontal:h,sizePopupArrow:v}=e,y=n(u).add(v).add(h).equal(),b=n(u).mul(2).add(v).equal();return[{[a]:Object.assign(Object.assign(Object.assign(Object.assign({},(0,r.resetComponent)(e)),{position:"absolute",zIndex:d,display:"block",width:"max-content",maxWidth:l,visibility:"visible","--valid-offset-x":"var(--arrow-offset-horizontal, var(--arrow-x))",transformOrigin:"var(--valid-offset-x, 50%) var(--arrow-y, 50%)","&-hidden":{display:"none"},"--antd-arrow-background-color":c,[`${a}-inner`]:{minWidth:b,minHeight:f,padding:`${(0,t.unit)(e.calc(m).div(2).equal())} ${(0,t.unit)(g)}`,color:`var(--ant-tooltip-color, ${s})`,textAlign:"start",textDecoration:"none",wordWrap:"break-word",backgroundColor:c,borderRadius:u,boxShadow:p,boxSizing:"border-box"},"&-placement-topLeft,&-placement-topRight,&-placement-bottomLeft,&-placement-bottomRight":{minWidth:y},"&-placement-left,&-placement-leftTop,&-placement-leftBottom,&-placement-right,&-placement-rightTop,&-placement-rightBottom":{[`${a}-inner`]:{borderRadius:e.min(u,o.MAX_VERTICAL_CONTENT_RADIUS)}},[`${a}-content`]:{position:"relative"}}),(0,i.genPresetColor)(e,(e,{darkColor:t})=>({[`&${a}-${e}`]:{[`${a}-inner`]:{backgroundColor:t},[`${a}-arrow`]:{"--antd-arrow-background-color":t}}}))),{"&-rtl":{direction:"rtl"}})},(0,o.default)(e,"var(--antd-arrow-background-color)"),{[`${a}-pure`]:{position:"relative",maxWidth:"none",margin:e.sizePopupArrow}}]})((0,s.mergeToken)(e,{tooltipMaxWidth:250,tooltipColor:l,tooltipBorderRadius:a,tooltipBg:c})),(0,n.initZoomMotion)(e,"zoom-big-fast")]},c,{resetStyle:!1,injectStyle:a})(e)])},702779,e=>{"use strict";var t=e.i(8211),r=e.i(617933);let n=r.PresetColors.map(e=>`${e}-inverse`),o=["success","processing","error","default","warning"];function a(e,o=!0){return o?[].concat((0,t.default)(n),(0,t.default)(r.PresetColors)).includes(e):r.PresetColors.includes(e)}function i(e){return o.includes(e)}e.s(["isPresetColor",()=>a,"isPresetStatusColor",()=>i])},571070,814690,162464,509808,e=>{"use strict";var t=e.i(278409),r=e.i(233848);e.i(247167),e.i(931067);var n=e.i(211577),o=e.i(392221),a=e.i(271645),i=e.i(209428),l=e.i(868917),s=e.i(674813),c=e.i(703923),u=e.i(410160);e.i(262370);var d=e.i(135551),f=["b"],p=["v"],m=function(e){return Math.round(Number(e||0))},g=function(e){if(e instanceof d.FastColor)return e;if(e&&"object"===(0,u.default)(e)&&"h"in e&&"b"in e){var t=e.b,r=(0,c.default)(e,f);return(0,i.default)((0,i.default)({},r),{},{v:t})}return"string"==typeof e&&/hsb/.test(e)?e.replace(/hsb/,"hsv"):e},h=function(e){(0,l.default)(o,e);var n=(0,s.default)(o);function o(e){return(0,t.default)(this,o),n.call(this,g(e))}return(0,r.default)(o,[{key:"toHsbString",value:function(){var e=this.toHsb(),t=m(100*e.s),r=m(100*e.b),n=m(e.h),o=e.a,a="hsb(".concat(n,", ").concat(t,"%, ").concat(r,"%)"),i="hsba(".concat(n,", ").concat(t,"%, ").concat(r,"%, ").concat(o.toFixed(2*(0!==o)),")");return 1===o?a:i}},{key:"toHsb",value:function(){var e=this.toHsv(),t=e.v,r=(0,c.default)(e,p);return(0,i.default)((0,i.default)({},r),{},{b:t,a:this.a})}}]),o}(d.FastColor);e.s(["Color",()=>h],814690);var v=function(e){return e instanceof h?e:new h(e)};v("#1677ff");var y=e.i(343794);e.s(["default",0,function(e){var t=e.color,r=e.prefixCls,n=e.className,o=e.style,i=e.onClick,l="".concat(r,"-color-block");return a.default.createElement("div",{className:(0,y.default)(l,n),style:o,onClick:i},a.default.createElement("div",{className:"".concat(l,"-inner"),style:{background:t}}))}],162464);e.i(62664);e.i(697539);e.i(914949);e.s([],509808);let b=(0,r.default)(function e(r){var n;if((0,t.default)(this,e),this.cleared=!1,r instanceof e){this.metaColor=r.metaColor.clone(),this.colors=null==(n=r.colors)?void 0:n.map(t=>({color:new e(t.color),percent:t.percent})),this.cleared=r.cleared;return}let o=Array.isArray(r);o&&r.length?(this.colors=r.map(({color:t,percent:r})=>({color:new e(t),percent:r})),this.metaColor=new h(this.colors[0].color.metaColor)):this.metaColor=new h(o?"":r),r&&(!o||this.colors)||(this.metaColor=this.metaColor.setA(0),this.cleared=!0)},[{key:"toHsb",value:function(){return this.metaColor.toHsb()}},{key:"toHsbString",value:function(){return this.metaColor.toHsbString()}},{key:"toHex",value:function(){var e,t;return e=this.toHexString(),t=this.metaColor.a<1,e&&(null==e?void 0:e.replace(/[^\w/]/g,"").slice(0,t?8:6))||""}},{key:"toHexString",value:function(){return this.metaColor.toHexString()}},{key:"toRgb",value:function(){return this.metaColor.toRgb()}},{key:"toRgbString",value:function(){return this.metaColor.toRgbString()}},{key:"isGradient",value:function(){return!!this.colors&&!this.cleared}},{key:"getColors",value:function(){return this.colors||[{color:this,percent:0}]}},{key:"toCssString",value:function(){let{colors:e}=this;if(e){let t=e.map(e=>`${e.color.toRgbString()} ${e.percent}%`).join(", ");return`linear-gradient(90deg, ${t})`}return this.metaColor.toRgbString()}},{key:"equals",value:function(e){return!!e&&this.isGradient()===e.isGradient()&&(this.isGradient()?this.colors.length===e.colors.length&&this.colors.every((t,r)=>{let n=e.colors[r];return t.percent===n.percent&&t.color.equals(n.color)}):this.toHexString()===e.toHexString())}}]);e.s(["AggregationColor",()=>b],571070)},656449,e=>{"use strict";e.i(8211),e.i(509808),e.i(814690);var t=e.i(571070);e.s(["generateColor",0,e=>e instanceof t.AggregationColor?e:new t.AggregationColor(e)])},491816,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(793154),o=e.i(914949),a=e.i(617206),i=e.i(122767),l=e.i(613541),s=e.i(805984),c=e.i(763731),u=e.i(747656),d=e.i(340010),f=e.i(242064),p=e.i(104458),m=e.i(880476),g=e.i(57667),h=e.i(702779),v=e.i(656449);function y(e,t){let n=(0,h.isPresetColor)(t),o=(0,r.default)({[`${e}-${t}`]:t&&n}),a={},i={},l=(0,v.generateColor)(t).toRgb(),s=(.299*l.r+.587*l.g+.114*l.b)/255;return t&&!n&&(a.background=t,a["--ant-tooltip-color"]=s<.5?"#FFF":"#000",i["--antd-arrow-background-color"]=t),{className:o,overlayStyle:a,arrowStyle:i}}var b=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 w=t.forwardRef((e,m)=>{var h,v;let{prefixCls:w,openClassName:C,getTooltipContainer:x,color:S,overlayInnerStyle:$,children:E,afterOpenChange:k,afterVisibleChange:O,destroyTooltipOnHide:j,destroyOnHidden:T,arrow:_=!0,title:P,overlay:I,builtinPlacements:F,arrowPointAtCenter:N=!1,autoAdjustOverflow:R=!0,motion:M,getPopupContainer:A,placement:B="top",mouseEnterDelay:z=.1,mouseLeaveDelay:L=.1,overlayStyle:H,rootClassName:D,overlayClassName:V,styles:W,classNames:U}=e,G=b(e,["prefixCls","openClassName","getTooltipContainer","color","overlayInnerStyle","children","afterOpenChange","afterVisibleChange","destroyTooltipOnHide","destroyOnHidden","arrow","title","overlay","builtinPlacements","arrowPointAtCenter","autoAdjustOverflow","motion","getPopupContainer","placement","mouseEnterDelay","mouseLeaveDelay","overlayStyle","rootClassName","overlayClassName","styles","classNames"]),q=!!_,[,K]=(0,p.useToken)(),{getPopupContainer:X,getPrefixCls:J,direction:Y,className:Q,style:Z,classNames:ee,styles:et}=(0,f.useComponentConfig)("tooltip"),er=(0,u.devUseWarning)("Tooltip"),en=t.useRef(null),eo=()=>{var e;null==(e=en.current)||e.forceAlign()};t.useImperativeHandle(m,()=>{var e,t;return{forceAlign:eo,forcePopupAlign:()=>{er.deprecated(!1,"forcePopupAlign","forceAlign"),eo()},nativeElement:null==(e=en.current)?void 0:e.nativeElement,popupElement:null==(t=en.current)?void 0:t.popupElement}});let[ea,ei]=(0,o.default)(!1,{value:null!=(h=e.open)?h:e.visible,defaultValue:null!=(v=e.defaultOpen)?v:e.defaultVisible}),el=!P&&!I&&0!==P,es=t.useMemo(()=>{var e,t;let r=N;return"object"==typeof _&&(r=null!=(t=null!=(e=_.pointAtCenter)?e:_.arrowPointAtCenter)?t:N),F||(0,s.default)({arrowPointAtCenter:r,autoAdjustOverflow:R,arrowWidth:q?K.sizePopupArrow:0,borderRadius:K.borderRadius,offset:K.marginXXS,visibleFirst:!0})},[N,_,F,K]),ec=t.useMemo(()=>0===P?P:I||P||"",[I,P]),eu=t.createElement(a.default,{space:!0},"function"==typeof ec?ec():ec),ed=J("tooltip",w),ef=J(),ep=e["data-popover-inject"],em=ea;"open"in e||"visible"in e||!el||(em=!1);let eg=t.isValidElement(E)&&!(0,c.isFragment)(E)?E:t.createElement("span",null,E),eh=eg.props,ev=eh.className&&"string"!=typeof eh.className?eh.className:(0,r.default)(eh.className,C||`${ed}-open`),[ey,eb,ew]=(0,g.default)(ed,!ep),eC=y(ed,S),ex=eC.arrowStyle,eS=(0,r.default)(V,{[`${ed}-rtl`]:"rtl"===Y},eC.className,D,eb,ew,Q,ee.root,null==U?void 0:U.root),e$=(0,r.default)(ee.body,null==U?void 0:U.body),[eE,ek]=(0,i.useZIndex)("Tooltip",G.zIndex),eO=t.createElement(n.default,Object.assign({},G,{zIndex:eE,showArrow:q,placement:B,mouseEnterDelay:z,mouseLeaveDelay:L,prefixCls:ed,classNames:{root:eS,body:e$},styles:{root:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},ex),et.root),Z),H),null==W?void 0:W.root),body:Object.assign(Object.assign(Object.assign(Object.assign({},et.body),$),null==W?void 0:W.body),eC.overlayStyle)},getTooltipContainer:A||x||X,ref:en,builtinPlacements:es,overlay:eu,visible:em,onVisibleChange:t=>{var r,n;ei(!el&&t),el||(null==(r=e.onOpenChange)||r.call(e,t),null==(n=e.onVisibleChange)||n.call(e,t))},afterVisibleChange:null!=k?k:O,arrowContent:t.createElement("span",{className:`${ed}-arrow-content`}),motion:{motionName:(0,l.getTransitionName)(ef,"zoom-big-fast",e.transitionName),motionDeadline:1e3},destroyTooltipOnHide:null!=T?T:!!j}),em?(0,c.cloneElement)(eg,{className:ev}):eg);return ey(t.createElement(d.default.Provider,{value:ek},eO))});w._InternalPanelDoNotUseOrYouWillBeFired=e=>{let{prefixCls:n,className:o,placement:a="top",title:i,color:l,overlayInnerStyle:s}=e,{getPrefixCls:c}=t.useContext(f.ConfigContext),u=c("tooltip",n),[d,p,h]=(0,g.default)(u),v=y(u,l),b=v.arrowStyle,w=Object.assign(Object.assign({},s),v.overlayStyle),C=(0,r.default)(p,h,u,`${u}-pure`,`${u}-placement-${a}`,o,v.className);return d(t.createElement("div",{className:C,style:b},t.createElement("div",{className:`${u}-arrow`}),t.createElement(m.Popup,Object.assign({},e,{className:p,prefixCls:u,overlayInnerStyle:w}),i)))},e.s(["default",0,w],491816)},808613,905536,e=>{"use strict";e.i(247167);var t=e.i(62139),r=e.i(782074),n=e.i(56117),o=e.i(411412),a=e.i(923624),i=e.i(8211),l=e.i(271645),s=e.i(343794);e.i(495347);var c=e.i(420422),u=e.i(355268),d=e.i(220489),f=e.i(290967),p=e.i(611935),m=e.i(763731),g=e.i(747656),h=e.i(242064),v=e.i(321883),y=e.i(522228),b=e.i(893872),w=e.i(857034),C=e.i(606836),x=e.i(908709),S=e.i(531880),$=e.i(606262),E=e.i(174428),k=e.i(529681),O=e.i(264042),j=e.i(292169),T=e.i(684024),_=e.i(995144),P=e.i(131757),I=e.i(408850),F=e.i(87414),N=e.i(491816),R=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=({prefixCls:e,label:r,htmlFor:n,labelCol:o,labelAlign:a,colon:i,required:c,requiredMark:u,tooltip:d,vertical:f})=>{var p;let m,[g]=(0,I.useLocale)("Form"),{labelAlign:h,labelCol:v,labelWrap:y,colon:b}=l.useContext(t.FormContext);if(!r)return null;let w=o||v||{},C=`${e}-item-label`,x=(0,s.default)(C,"left"===(a||h)&&`${C}-left`,w.className,{[`${C}-wrap`]:!!y}),S=r,$=!0===i||!1!==b&&!1!==i;$&&!f&&"string"==typeof r&&r.trim()&&(S=r.replace(/[:|:]\s*$/,""));let E=(0,_.default)(d);if(E){let{icon:t=l.createElement(T.default,null)}=E,r=R(E,["icon"]),n=l.createElement(N.default,Object.assign({},r),l.cloneElement(t,{className:`${e}-item-tooltip`,title:"",onClick:e=>{e.preventDefault()},tabIndex:null}));S=l.createElement(l.Fragment,null,S,n)}let k="optional"===u,O="function"==typeof u;O?S=u(S,{required:!!c}):k&&!c&&(S=l.createElement(l.Fragment,null,S,l.createElement("span",{className:`${e}-item-optional`,title:""},(null==g?void 0:g.optional)||(null==(p=F.default.Form)?void 0:p.optional)))),!1===u?m="hidden":(k||O)&&(m="optional");let j=(0,s.default)({[`${e}-item-required`]:c,[`${e}-item-required-mark-${m}`]:m,[`${e}-item-no-colon`]:!$});return l.createElement(P.default,Object.assign({},w,{className:x}),l.createElement("label",{htmlFor:n,className:j,title:"string"==typeof r?r:""},S))};var A=e.i(830919),B=e.i(201072),z=e.i(726289),L=e.i(562901),H=e.i(739295);let D={success:B.default,warning:L.default,error:z.default,validating:H.default};function V({children:e,errors:r,warnings:n,hasFeedback:o,validateStatus:a,prefixCls:i,meta:c,noStyle:u,name:d}){let f=`${i}-item`,{feedbackIcons:p}=l.useContext(t.FormContext),m=(0,S.getStatus)(r,n,c,null,!!o,a),{isFormItemInput:g,status:h,hasFeedback:v,feedbackIcon:y,name:b}=l.useContext(t.FormItemInputContext),w=l.useMemo(()=>{var e;let t;if(o){let a=!0!==o&&o.icons||p,i=m&&(null==(e=null==a?void 0:a({status:m,errors:r,warnings:n}))?void 0:e[m]),c=m?D[m]:null;t=!1!==i&&c?l.createElement("span",{className:(0,s.default)(`${f}-feedback-icon`,`${f}-feedback-icon-${m}`)},i||l.createElement(c,null)):null}let a={status:m||"",errors:r,warnings:n,hasFeedback:!!o,feedbackIcon:t,isFormItemInput:!0,name:d};return u&&(a.status=(null!=m?m:h)||"",a.isFormItemInput=g,a.hasFeedback=!!(null!=o?o:v),a.feedbackIcon=void 0!==o?a.feedbackIcon:y,a.name=null!=d?d:b),a},[m,o,u,g,h]);return l.createElement(t.FormItemInputContext.Provider,{value:w},e)}var W=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};function U(e){let{prefixCls:r,className:n,rootClassName:o,style:a,help:i,errors:c,warnings:u,validateStatus:d,meta:f,hasFeedback:p,hidden:m,children:g,fieldId:h,required:v,isRequired:y,onSubItemMetaChange:b,layout:w,name:C}=e,x=W(e,["prefixCls","className","rootClassName","style","help","errors","warnings","validateStatus","meta","hasFeedback","hidden","children","fieldId","required","isRequired","onSubItemMetaChange","layout","name"]),T=`${r}-item`,{requiredMark:_,layout:P}=l.useContext(t.FormContext),I=w||P,F="vertical"===I,N=l.useRef(null),R=(0,A.default)(c),B=(0,A.default)(u),z=null!=i,L=!!(z||c.length||u.length),H=!!N.current&&(0,$.default)(N.current),[D,U]=l.useState(null);(0,E.default)(()=>{L&&N.current&&U(Number.parseInt(getComputedStyle(N.current).marginBottom,10))},[L,H]);let G=((e=!1)=>{let t=e?R:f.errors,r=e?B:f.warnings;return(0,S.getStatus)(t,r,f,"",!!p,d)})(),q=(0,s.default)(T,n,o,{[`${T}-with-help`]:z||R.length||B.length,[`${T}-has-feedback`]:G&&p,[`${T}-has-success`]:"success"===G,[`${T}-has-warning`]:"warning"===G,[`${T}-has-error`]:"error"===G,[`${T}-is-validating`]:"validating"===G,[`${T}-hidden`]:m,[`${T}-${I}`]:I});return l.createElement("div",{className:q,style:a,ref:N},l.createElement(O.Row,Object.assign({className:`${T}-row`},(0,k.default)(x,["_internalItemRender","colon","dependencies","extra","fieldKey","getValueFromEvent","getValueProps","htmlFor","id","initialValue","isListField","label","labelAlign","labelCol","labelWrap","messageVariables","name","normalize","noStyle","preserve","requiredMark","rules","shouldUpdate","trigger","tooltip","validateFirst","validateTrigger","valuePropName","wrapperCol","validateDebounce"])),l.createElement(M,Object.assign({htmlFor:h},e,{requiredMark:_,required:null!=v?v:y,prefixCls:r,vertical:F})),l.createElement(j.default,Object.assign({},e,f,{errors:R,warnings:B,prefixCls:r,status:G,help:i,marginBottom:D,onErrorVisibleChanged:e=>{e||U(null)}}),l.createElement(t.NoStyleItemContext.Provider,{value:b},l.createElement(V,{prefixCls:r,meta:f,errors:f.errors,warnings:f.warnings,hasFeedback:p,validateStatus:G,name:C},g)))),!!D&&l.createElement("div",{className:`${T}-margin-offset`,style:{marginBottom:-D}}))}let G=l.memo(({children:e})=>e,(e,t)=>{var r,n;let o,a;return r=e.control,n=t.control,o=Object.keys(r),a=Object.keys(n),o.length===a.length&&o.every(e=>{let t=r[e],o=n[e];return t===o||"function"==typeof t||"function"==typeof o})&&e.update===t.update&&e.childProps.length===t.childProps.length&&e.childProps.every((e,r)=>e===t.childProps[r])});function q(){return{errors:[],warnings:[],touched:!1,validating:!1,name:[],validated:!1}}let K=function(e){let{name:r,noStyle:n,className:o,dependencies:a,prefixCls:b,shouldUpdate:$,rules:E,children:k,required:O,label:j,messageVariables:T,trigger:_="onChange",validateTrigger:P,hidden:I,help:F,layout:N}=e,{getPrefixCls:R}=l.useContext(h.ConfigContext),{name:M}=l.useContext(t.FormContext),A=(0,y.default)(k),B="function"==typeof A,z=l.useContext(t.NoStyleItemContext),{validateTrigger:L}=l.useContext(u.FieldContext),H=void 0!==P?P:L,D=null!=r,W=R("form",b),K=(0,v.default)(W),[X,J,Y]=(0,x.default)(W,K);(0,g.devUseWarning)("Form.Item");let Q=l.useContext(d.ListContext),Z=l.useRef(null),[ee,et]=(0,w.default)({}),[er,en]=(0,f.default)(()=>q()),eo=(e,t)=>{et(r=>{let n=Object.assign({},r),o=[].concat((0,i.default)(e.name.slice(0,-1)),(0,i.default)(t)).join("__SPLIT__");return e.destroy?delete n[o]:n[o]=e,n})},[ea,ei]=l.useMemo(()=>{let e=(0,i.default)(er.errors),t=(0,i.default)(er.warnings);return Object.values(ee).forEach(r=>{e.push.apply(e,(0,i.default)(r.errors||[])),t.push.apply(t,(0,i.default)(r.warnings||[]))}),[e,t]},[ee,er.errors,er.warnings]),el=(0,C.default)();function es(t,a,i){return n&&!I?l.createElement(V,{prefixCls:W,hasFeedback:e.hasFeedback,validateStatus:e.validateStatus,meta:er,errors:ea,warnings:ei,noStyle:!0,name:r},t):l.createElement(U,Object.assign({key:"row"},e,{className:(0,s.default)(o,Y,K,J),prefixCls:W,fieldId:a,isRequired:i,errors:ea,warnings:ei,meta:er,onSubItemMetaChange:eo,layout:N,name:r}),t)}if(!D&&!B&&!a)return X(es(A));let ec={};return"string"==typeof j?ec.label=j:r&&(ec.label=String(r)),T&&(ec=Object.assign(Object.assign({},ec),T)),X(l.createElement(c.Field,Object.assign({},e,{messageVariables:ec,trigger:_,validateTrigger:H,onMetaChange:e=>{let t=null==Q?void 0:Q.getKey(e.name);if(en(e.destroy?q():e,!0),n&&!1!==F&&z){let r=e.name;if(e.destroy)r=Z.current||r;else if(void 0!==t){let[e,n]=t;Z.current=r=[e].concat((0,i.default)(n))}z(e,r)}}}),(t,n,o)=>{let s=(0,S.toArray)(r).length&&n?n.name:[],c=(0,S.getFieldId)(s,M),u=void 0!==O?O:!!(null==E?void 0:E.some(e=>{if(e&&"object"==typeof e&&e.required&&!e.warningOnly)return!0;if("function"==typeof e){let t=e(o);return(null==t?void 0:t.required)&&!(null==t?void 0:t.warningOnly)}return!1})),d=Object.assign({},t),f=null;if(Array.isArray(A)&&D)f=A;else if(B&&(!($||a)||D));else if(!a||B||D)if(l.isValidElement(A)){let t=Object.assign(Object.assign({},A.props),d);if(t.id||(t.id=c),F||ea.length>0||ei.length>0||e.extra){let r=[];(F||ea.length>0)&&r.push(`${c}_help`),e.extra&&r.push(`${c}_extra`),t["aria-describedby"]=r.join(" ")}ea.length>0&&(t["aria-invalid"]="true"),u&&(t["aria-required"]="true"),(0,p.supportRef)(A)&&(t.ref=el(s,A)),new Set([].concat((0,i.default)((0,S.toArray)(_)),(0,i.default)((0,S.toArray)(H)))).forEach(e=>{t[e]=(...t)=>{var r,n,o;null==(r=d[e])||r.call.apply(r,[d].concat(t)),null==(o=(n=A.props)[e])||o.call.apply(o,[n].concat(t))}});let r=[t["aria-required"],t["aria-invalid"],t["aria-describedby"]];f=l.createElement(G,{control:d,update:A,childProps:r},(0,m.cloneElement)(A,t))}else f=B&&($||a)&&!D?A(o):A;return es(f,c,u)}))};K.useStatus=b.default,e.s(["default",0,K],905536);var X=e.i(53058),J=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 Y=n.default;Y.Item=K,Y.List=e=>{var{prefixCls:r,children:n}=e,o=J(e,["prefixCls","children"]);let{getPrefixCls:a}=l.useContext(h.ConfigContext),i=a("form",r),s=l.useMemo(()=>({prefixCls:i,status:"error"}),[i]);return l.createElement(X.List,Object.assign({},o),(e,r,o)=>l.createElement(t.FormItemPrefixContext.Provider,{value:s},n(e.map(e=>Object.assign(Object.assign({},e),{fieldKey:e.key})),r,{errors:o.errors,warnings:o.warnings})))},Y.ErrorList=r.default,Y.useForm=o.useForm,Y.useFormInstance=function(){let{form:e}=l.useContext(t.FormContext);return e},Y.useWatch=a.useWatch,Y.Provider=t.FormProvider,Y.create=()=>{},e.s(["Form",0,Y],808613)},372409,e=>{"use strict";function t(e,r={focus:!0}){let{componentCls:n}=e,{componentCls:o}=r,a=o||n,i=`${a}-compact`;return{[i]:Object.assign(Object.assign({},function(e,t,r,n){let{focusElCls:o,focus:a,borderElCls:i}=r,l=i?"> *":"",s=["hover",a?"focus":null,"active"].filter(Boolean).map(e=>`&:${e} ${l}`).join(",");return{[`&-item:not(${t}-last-item)`]:{marginInlineEnd:e.calc(e.lineWidth).mul(-1).equal()},[`&-item:not(${n}-status-success)`]:{zIndex:2},"&-item":Object.assign(Object.assign({[s]:{zIndex:3}},o?{[`&${o}`]:{zIndex:3}}:{}),{[`&[disabled] ${l}`]:{zIndex:0}})}}(e,i,r,a)),function(e,t,r){let{borderElCls:n}=r,o=n?`> ${n}`:"";return{[`&-item:not(${t}-first-item):not(${t}-last-item) ${o}`]:{borderRadius:0},[`&-item:not(${t}-last-item)${t}-first-item`]:{[`& ${o}, &${e}-sm ${o}, &${e}-lg ${o}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&-item:not(${t}-first-item)${t}-last-item`]:{[`& ${o}, &${e}-sm ${o}, &${e}-lg ${o}`]:{borderStartStartRadius:0,borderEndStartRadius:0}}}}(a,i,r))}}e.s(["genCompactItemStyle",()=>t])},349942,517458,889943,e=>{"use strict";e.i(296059);var t=e.i(915654),r=e.i(183293),n=e.i(372409),o=e.i(246422),a=e.i(838378);function i(e){return(0,a.mergeToken)(e,{inputAffixPadding:e.paddingXXS})}let l=e=>{let{controlHeight:t,fontSize:r,lineHeight:n,lineWidth:o,controlHeightSM:a,controlHeightLG:i,fontSizeLG:l,lineHeightLG:s,paddingSM:c,controlPaddingHorizontalSM:u,controlPaddingHorizontal:d,colorFillAlter:f,colorPrimaryHover:p,colorPrimary:m,controlOutlineWidth:g,controlOutline:h,colorErrorOutline:v,colorWarningOutline:y,colorBgContainer:b,inputFontSize:w,inputFontSizeLG:C,inputFontSizeSM:x}=e,S=w||r,$=x||S,E=C||l;return{paddingBlock:Math.max(Math.round((t-S*n)/2*10)/10-o,0),paddingBlockSM:Math.max(Math.round((a-$*n)/2*10)/10-o,0),paddingBlockLG:Math.max(Math.ceil((i-E*s)/2*10)/10-o,0),paddingInline:c-o,paddingInlineSM:u-o,paddingInlineLG:d-o,addonBg:f,activeBorderColor:m,hoverBorderColor:p,activeShadow:`0 0 0 ${g}px ${h}`,errorActiveShadow:`0 0 0 ${g}px ${v}`,warningActiveShadow:`0 0 0 ${g}px ${y}`,hoverBg:b,activeBg:b,inputFontSize:S,inputFontSizeLG:E,inputFontSizeSM:$}};e.s(["initComponentToken",0,l,"initInputToken",()=>i],517458);let s=e=>{let t;return{color:e.colorTextDisabled,backgroundColor:e.colorBgContainerDisabled,borderColor:e.colorBorder,boxShadow:"none",cursor:"not-allowed",opacity:1,"input[disabled], textarea[disabled]":{cursor:"not-allowed"},"&:hover:not([disabled])":Object.assign({},{borderColor:(t=(0,a.mergeToken)(e,{hoverBorderColor:e.colorBorder,hoverBg:e.colorBgContainerDisabled})).hoverBorderColor,backgroundColor:t.hoverBg})}},c=(e,t)=>({background:e.colorBgContainer,borderWidth:e.lineWidth,borderStyle:e.lineType,borderColor:t.borderColor,"&:hover":{borderColor:t.hoverBorderColor,backgroundColor:e.hoverBg},"&:focus, &:focus-within":{borderColor:t.activeBorderColor,boxShadow:t.activeShadow,outline:0,backgroundColor:e.activeBg}}),u=(e,t)=>({[`&${e.componentCls}-status-${t.status}:not(${e.componentCls}-disabled)`]:Object.assign(Object.assign({},c(e,t)),{[`${e.componentCls}-prefix, ${e.componentCls}-suffix`]:{color:t.affixColor}}),[`&${e.componentCls}-status-${t.status}${e.componentCls}-disabled`]:{borderColor:t.borderColor}}),d=(e,t)=>({"&-outlined":Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},c(e,{borderColor:e.colorBorder,hoverBorderColor:e.hoverBorderColor,activeBorderColor:e.activeBorderColor,activeShadow:e.activeShadow})),{[`&${e.componentCls}-disabled, &[disabled]`]:Object.assign({},s(e))}),u(e,{status:"error",borderColor:e.colorError,hoverBorderColor:e.colorErrorBorderHover,activeBorderColor:e.colorError,activeShadow:e.errorActiveShadow,affixColor:e.colorError})),u(e,{status:"warning",borderColor:e.colorWarning,hoverBorderColor:e.colorWarningBorderHover,activeBorderColor:e.colorWarning,activeShadow:e.warningActiveShadow,affixColor:e.colorWarning})),t)}),f=(e,t)=>({[`&${e.componentCls}-group-wrapper-status-${t.status}`]:{[`${e.componentCls}-group-addon`]:{borderColor:t.addonBorderColor,color:t.addonColor}}}),p=e=>({"&-outlined":Object.assign(Object.assign(Object.assign({[`${e.componentCls}-group`]:{"&-addon":{background:e.addonBg,border:`${(0,t.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`},"&-addon:first-child":{borderInlineEnd:0},"&-addon:last-child":{borderInlineStart:0}}},f(e,{status:"error",addonBorderColor:e.colorError,addonColor:e.colorErrorText})),f(e,{status:"warning",addonBorderColor:e.colorWarning,addonColor:e.colorWarningText})),{[`&${e.componentCls}-group-wrapper-disabled`]:{[`${e.componentCls}-group-addon`]:Object.assign({},s(e))}})}),m=(e,t)=>{let{componentCls:r}=e;return{"&-borderless":Object.assign({background:"transparent",border:"none","&:focus, &:focus-within":{outline:"none"},[`&${r}-disabled, &[disabled]`]:{color:e.colorTextDisabled,cursor:"not-allowed"},[`&${r}-status-error`]:{"&, & input, & textarea":{color:e.colorError}},[`&${r}-status-warning`]:{"&, & input, & textarea":{color:e.colorWarning}}},t)}},g=(e,t)=>{var r;return{background:t.bg,borderWidth:e.lineWidth,borderStyle:e.lineType,borderColor:"transparent","input&, & input, textarea&, & textarea":{color:null!=(r=null==t?void 0:t.inputColor)?r:"unset"},"&:hover":{background:t.hoverBg},"&:focus, &:focus-within":{outline:0,borderColor:t.activeBorderColor,backgroundColor:e.activeBg}}},h=(e,t)=>({[`&${e.componentCls}-status-${t.status}:not(${e.componentCls}-disabled)`]:Object.assign(Object.assign({},g(e,t)),{[`${e.componentCls}-prefix, ${e.componentCls}-suffix`]:{color:t.affixColor}})}),v=(e,t)=>({"&-filled":Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},g(e,{bg:e.colorFillTertiary,hoverBg:e.colorFillSecondary,activeBorderColor:e.activeBorderColor})),{[`&${e.componentCls}-disabled, &[disabled]`]:Object.assign({},s(e))}),h(e,{status:"error",bg:e.colorErrorBg,hoverBg:e.colorErrorBgHover,activeBorderColor:e.colorError,inputColor:e.colorErrorText,affixColor:e.colorError})),h(e,{status:"warning",bg:e.colorWarningBg,hoverBg:e.colorWarningBgHover,activeBorderColor:e.colorWarning,inputColor:e.colorWarningText,affixColor:e.colorWarning})),t)}),y=(e,t)=>({[`&${e.componentCls}-group-wrapper-status-${t.status}`]:{[`${e.componentCls}-group-addon`]:{background:t.addonBg,color:t.addonColor}}}),b=e=>({"&-filled":Object.assign(Object.assign(Object.assign({[`${e.componentCls}-group-addon`]:{background:e.colorFillTertiary,"&:last-child":{position:"static"}}},y(e,{status:"error",addonBg:e.colorErrorBg,addonColor:e.colorErrorText})),y(e,{status:"warning",addonBg:e.colorWarningBg,addonColor:e.colorWarningText})),{[`&${e.componentCls}-group-wrapper-disabled`]:{[`${e.componentCls}-group`]:{"&-addon":{background:e.colorFillTertiary,color:e.colorTextDisabled},"&-addon:first-child":{borderInlineStart:`${(0,t.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderTop:`${(0,t.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderBottom:`${(0,t.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`},"&-addon:last-child":{borderInlineEnd:`${(0,t.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderTop:`${(0,t.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderBottom:`${(0,t.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`}}}})}),w=(e,r)=>({background:e.colorBgContainer,borderWidth:`${(0,t.unit)(e.lineWidth)} 0`,borderStyle:`${e.lineType} none`,borderColor:`transparent transparent ${r.borderColor} transparent`,borderRadius:0,"&:hover":{borderColor:`transparent transparent ${r.hoverBorderColor} transparent`,backgroundColor:e.hoverBg},"&:focus, &:focus-within":{borderColor:`transparent transparent ${r.activeBorderColor} transparent`,outline:0,backgroundColor:e.activeBg}}),C=(e,t)=>({[`&${e.componentCls}-status-${t.status}:not(${e.componentCls}-disabled)`]:Object.assign(Object.assign({},w(e,t)),{[`${e.componentCls}-prefix, ${e.componentCls}-suffix`]:{color:t.affixColor}}),[`&${e.componentCls}-status-${t.status}${e.componentCls}-disabled`]:{borderColor:`transparent transparent ${t.borderColor} transparent`}}),x=(e,t)=>({"&-underlined":Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},w(e,{borderColor:e.colorBorder,hoverBorderColor:e.hoverBorderColor,activeBorderColor:e.activeBorderColor,activeShadow:e.activeShadow})),{[`&${e.componentCls}-disabled, &[disabled]`]:{color:e.colorTextDisabled,boxShadow:"none",cursor:"not-allowed","&:hover":{borderColor:`transparent transparent ${e.colorBorder} transparent`}},"input[disabled], textarea[disabled]":{cursor:"not-allowed"}}),C(e,{status:"error",borderColor:e.colorError,hoverBorderColor:e.colorErrorBorderHover,activeBorderColor:e.colorError,activeShadow:e.errorActiveShadow,affixColor:e.colorError})),C(e,{status:"warning",borderColor:e.colorWarning,hoverBorderColor:e.colorWarningBorderHover,activeBorderColor:e.colorWarning,activeShadow:e.warningActiveShadow,affixColor:e.colorWarning})),t)});e.s(["genBaseOutlinedStyle",0,c,"genBorderlessStyle",0,m,"genDisabledStyle",0,s,"genFilledGroupStyle",0,b,"genFilledStyle",0,v,"genOutlinedGroupStyle",0,p,"genOutlinedStyle",0,d,"genUnderlinedStyle",0,x],889943);let S=e=>({"&::-moz-placeholder":{opacity:1},"&::placeholder":{color:e,userSelect:"none"},"&:placeholder-shown":{textOverflow:"ellipsis"}}),$=e=>{let{paddingBlockLG:r,lineHeightLG:n,borderRadiusLG:o,paddingInlineLG:a}=e;return{padding:`${(0,t.unit)(r)} ${(0,t.unit)(a)}`,fontSize:e.inputFontSizeLG,lineHeight:n,borderRadius:o}},E=e=>({padding:`${(0,t.unit)(e.paddingBlockSM)} ${(0,t.unit)(e.paddingInlineSM)}`,fontSize:e.inputFontSizeSM,borderRadius:e.borderRadiusSM}),k=e=>Object.assign(Object.assign({position:"relative",display:"inline-block",width:"100%",minWidth:0,padding:`${(0,t.unit)(e.paddingBlock)} ${(0,t.unit)(e.paddingInline)}`,color:e.colorText,fontSize:e.inputFontSize,lineHeight:e.lineHeight,borderRadius:e.borderRadius,transition:`all ${e.motionDurationMid}`},S(e.colorTextPlaceholder)),{"&-lg":Object.assign({},$(e)),"&-sm":Object.assign({},E(e)),"&-rtl, &-textarea-rtl":{direction:"rtl"}}),O=e=>{let{componentCls:n,antCls:o}=e;return{position:"relative",display:"table",width:"100%",borderCollapse:"separate",borderSpacing:0,"&[class*='col-']":{paddingInlineEnd:e.paddingXS,"&:last-child":{paddingInlineEnd:0}},[`&-lg ${n}, &-lg > ${n}-group-addon`]:Object.assign({},$(e)),[`&-sm ${n}, &-sm > ${n}-group-addon`]:Object.assign({},E(e)),[`&-lg ${o}-select-single ${o}-select-selector`]:{height:e.controlHeightLG},[`&-sm ${o}-select-single ${o}-select-selector`]:{height:e.controlHeightSM},[`> ${n}`]:{display:"table-cell","&:not(:first-child):not(:last-child)":{borderRadius:0}},[`${n}-group`]:{"&-addon, &-wrap":{display:"table-cell",width:1,whiteSpace:"nowrap",verticalAlign:"middle","&:not(:first-child):not(:last-child)":{borderRadius:0}},"&-wrap > *":{display:"block !important"},"&-addon":{position:"relative",padding:`0 ${(0,t.unit)(e.paddingInline)}`,color:e.colorText,fontWeight:"normal",fontSize:e.inputFontSize,textAlign:"center",borderRadius:e.borderRadius,transition:`all ${e.motionDurationSlow}`,lineHeight:1,[`${o}-select`]:{margin:`${(0,t.unit)(e.calc(e.paddingBlock).add(1).mul(-1).equal())} ${(0,t.unit)(e.calc(e.paddingInline).mul(-1).equal())}`,[`&${o}-select-single:not(${o}-select-customize-input):not(${o}-pagination-size-changer)`]:{[`${o}-select-selector`]:{backgroundColor:"inherit",border:`${(0,t.unit)(e.lineWidth)} ${e.lineType} transparent`,boxShadow:"none"}}},[`${o}-cascader-picker`]:{margin:`-9px ${(0,t.unit)(e.calc(e.paddingInline).mul(-1).equal())}`,backgroundColor:"transparent",[`${o}-cascader-input`]:{textAlign:"start",border:0,boxShadow:"none"}}}},[n]:{width:"100%",marginBottom:0,textAlign:"inherit","&:focus":{zIndex:1,borderInlineEndWidth:1},"&:hover":{zIndex:1,borderInlineEndWidth:1,[`${n}-search-with-button &`]:{zIndex:0}}},[`> ${n}:first-child, ${n}-group-addon:first-child`]:{borderStartEndRadius:0,borderEndEndRadius:0,[`${o}-select ${o}-select-selector`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`> ${n}-affix-wrapper`]:{[`&:not(:first-child) ${n}`]:{borderStartStartRadius:0,borderEndStartRadius:0},[`&:not(:last-child) ${n}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`> ${n}:last-child, ${n}-group-addon:last-child`]:{borderStartStartRadius:0,borderEndStartRadius:0,[`${o}-select ${o}-select-selector`]:{borderStartStartRadius:0,borderEndStartRadius:0}},[`${n}-affix-wrapper`]:{"&:not(:last-child)":{borderStartEndRadius:0,borderEndEndRadius:0,[`${n}-search &`]:{borderStartStartRadius:e.borderRadius,borderEndStartRadius:e.borderRadius}},[`&:not(:first-child), ${n}-search &:not(:first-child)`]:{borderStartStartRadius:0,borderEndStartRadius:0}},[`&${n}-group-compact`]:Object.assign(Object.assign({display:"block"},(0,r.clearFix)()),{[`${n}-group-addon, ${n}-group-wrap, > ${n}`]:{"&:not(:first-child):not(:last-child)":{borderInlineEndWidth:e.lineWidth,"&:hover, &:focus":{zIndex:1}}},"& > *":{display:"inline-flex",float:"none",verticalAlign:"top",borderRadius:0},[` + & > ${n}-affix-wrapper, + & > ${n}-number-affix-wrapper, + & > ${o}-picker-range + `]:{display:"inline-flex"},"& > *:not(:last-child)":{marginInlineEnd:e.calc(e.lineWidth).mul(-1).equal(),borderInlineEndWidth:e.lineWidth},[n]:{float:"none"},[`& > ${o}-select > ${o}-select-selector, + & > ${o}-select-auto-complete ${n}, + & > ${o}-cascader-picker ${n}, + & > ${n}-group-wrapper ${n}`]:{borderInlineEndWidth:e.lineWidth,borderRadius:0,"&:hover, &:focus":{zIndex:1}},[`& > ${o}-select-focused`]:{zIndex:1},[`& > ${o}-select > ${o}-select-arrow`]:{zIndex:1},[`& > *:first-child, + & > ${o}-select:first-child > ${o}-select-selector, + & > ${o}-select-auto-complete:first-child ${n}, + & > ${o}-cascader-picker:first-child ${n}`]:{borderStartStartRadius:e.borderRadius,borderEndStartRadius:e.borderRadius},[`& > *:last-child, + & > ${o}-select:last-child > ${o}-select-selector, + & > ${o}-cascader-picker:last-child ${n}, + & > ${o}-cascader-picker-focused:last-child ${n}`]:{borderInlineEndWidth:e.lineWidth,borderStartEndRadius:e.borderRadius,borderEndEndRadius:e.borderRadius},[`& > ${o}-select-auto-complete ${n}`]:{verticalAlign:"top"},[`${n}-group-wrapper + ${n}-group-wrapper`]:{marginInlineStart:e.calc(e.lineWidth).mul(-1).equal(),[`${n}-affix-wrapper`]:{borderRadius:0}},[`${n}-group-wrapper:not(:last-child)`]:{[`&${n}-search > ${n}-group`]:{[`& > ${n}-group-addon > ${n}-search-button`]:{borderRadius:0},[`& > ${n}`]:{borderStartStartRadius:e.borderRadius,borderStartEndRadius:0,borderEndEndRadius:0,borderEndStartRadius:e.borderRadius}}}})}},j=(0,o.genStyleHooks)(["Input","Shared"],e=>{let n=(0,a.mergeToken)(e,i(e));return[(e=>{let{componentCls:t,controlHeightSM:n,lineWidth:o,calc:a}=e,i=a(n).sub(a(o).mul(2)).sub(16).div(2).equal();return{[t]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},(0,r.resetComponent)(e)),k(e)),d(e)),v(e)),m(e)),x(e)),{'&[type="color"]':{height:e.controlHeight,[`&${t}-lg`]:{height:e.controlHeightLG},[`&${t}-sm`]:{height:n,paddingTop:i,paddingBottom:i}},'&[type="search"]::-webkit-search-cancel-button, &[type="search"]::-webkit-search-decoration':{appearance:"none"}})}})(n),(e=>{let{componentCls:r,inputAffixPadding:n,colorTextDescription:o,motionDurationSlow:a,colorIcon:i,colorIconHover:l,iconCls:s}=e,c=`${r}-affix-wrapper`,u=`${r}-affix-wrapper-disabled`;return{[c]:Object.assign(Object.assign(Object.assign(Object.assign({},k(e)),{display:"inline-flex",[`&:not(${r}-disabled):hover`]:{zIndex:1,[`${r}-search-with-button &`]:{zIndex:0}},"&-focused, &:focus":{zIndex:1},[`> input${r}`]:{padding:0},[`> input${r}, > textarea${r}`]:{fontSize:"inherit",border:"none",borderRadius:0,outline:"none",background:"transparent",color:"inherit","&::-ms-reveal":{display:"none"},"&:focus":{boxShadow:"none !important"}},"&::before":{display:"inline-block",width:0,visibility:"hidden",content:'"\\a0"'},[r]:{"&-prefix, &-suffix":{display:"flex",flex:"none",alignItems:"center","> *:not(:last-child)":{marginInlineEnd:e.paddingXS}},"&-show-count-suffix":{color:o,direction:"ltr"},"&-show-count-has-suffix":{marginInlineEnd:e.paddingXXS},"&-prefix":{marginInlineEnd:n},"&-suffix":{marginInlineStart:n}}}),(e=>{let{componentCls:r}=e;return{[`${r}-clear-icon`]:{margin:0,padding:0,lineHeight:0,color:e.colorTextQuaternary,fontSize:e.fontSizeIcon,verticalAlign:-1,cursor:"pointer",transition:`color ${e.motionDurationSlow}`,border:"none",outline:"none",backgroundColor:"transparent","&:hover":{color:e.colorIcon},"&:active":{color:e.colorText},"&-hidden":{visibility:"hidden"},"&-has-suffix":{margin:`0 ${(0,t.unit)(e.inputAffixPadding)}`}}}})(e)),{[`${s}${r}-password-icon`]:{color:i,cursor:"pointer",transition:`all ${a}`,"&:hover":{color:l}}}),[`${r}-underlined`]:{borderRadius:0},[u]:{[`${s}${r}-password-icon`]:{color:i,cursor:"not-allowed","&:hover":{color:i}}}}})(n)]},l,{resetFont:!1}),T=(0,o.genStyleHooks)(["Input","Component"],e=>{let t=(0,a.mergeToken)(e,i(e));return[(e=>{let{componentCls:t,borderRadiusLG:n,borderRadiusSM:o}=e;return{[`${t}-group`]:Object.assign(Object.assign(Object.assign({},(0,r.resetComponent)(e)),O(e)),{"&-rtl":{direction:"rtl"},"&-wrapper":Object.assign(Object.assign(Object.assign({display:"inline-block",width:"100%",textAlign:"start",verticalAlign:"top","&-rtl":{direction:"rtl"},"&-lg":{[`${t}-group-addon`]:{borderRadius:n,fontSize:e.inputFontSizeLG}},"&-sm":{[`${t}-group-addon`]:{borderRadius:o}}},p(e)),b(e)),{[`&:not(${t}-compact-first-item):not(${t}-compact-last-item)${t}-compact-item`]:{[`${t}, ${t}-group-addon`]:{borderRadius:0}},[`&:not(${t}-compact-last-item)${t}-compact-first-item`]:{[`${t}, ${t}-group-addon`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&:not(${t}-compact-first-item)${t}-compact-last-item`]:{[`${t}, ${t}-group-addon`]:{borderStartStartRadius:0,borderEndStartRadius:0}},[`&:not(${t}-compact-last-item)${t}-compact-item`]:{[`${t}-affix-wrapper`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&:not(${t}-compact-first-item)${t}-compact-item`]:{[`${t}-affix-wrapper`]:{borderStartStartRadius:0,borderEndStartRadius:0}}})})}})(t),(e=>{let{componentCls:t,antCls:r}=e,n=`${t}-search`;return{[n]:{[t]:{"&:not([disabled]):hover, &:not([disabled]):focus":{[`+ ${t}-group-addon ${n}-button:not(${r}-btn-color-primary):not(${r}-btn-variant-text)`]:{borderInlineStartColor:e.colorPrimaryHover}}},[`${t}-affix-wrapper`]:{height:e.controlHeight,borderRadius:0},[`${t}-lg`]:{lineHeight:e.calc(e.lineHeightLG).sub(2e-4).equal()},[`> ${t}-group`]:{[`> ${t}-group-addon:last-child`]:{insetInlineStart:-1,padding:0,border:0,[`${n}-button`]:{marginInlineEnd:-1,borderStartStartRadius:0,borderEndStartRadius:0,boxShadow:"none"},[`${n}-button:not(${r}-btn-color-primary)`]:{color:e.colorTextDescription,"&:not([disabled]):hover":{color:e.colorPrimaryHover},"&:active":{color:e.colorPrimaryActive},[`&${r}-btn-loading::before`]:{inset:0}}}},[`${n}-button`]:{height:e.controlHeight,"&:hover, &:focus":{zIndex:1}},"&-large":{[`${t}-affix-wrapper, ${n}-button`]:{height:e.controlHeightLG}},"&-small":{[`${t}-affix-wrapper, ${n}-button`]:{height:e.controlHeightSM}},"&-rtl":{direction:"rtl"},[`&${t}-compact-item`]:{[`&:not(${t}-compact-last-item)`]:{[`${t}-group-addon`]:{[`${t}-search-button`]:{marginInlineEnd:e.calc(e.lineWidth).mul(-1).equal(),borderRadius:0}}},[`&:not(${t}-compact-first-item)`]:{[`${t},${t}-affix-wrapper`]:{borderRadius:0}},[`> ${t}-group-addon ${t}-search-button, + > ${t}, + ${t}-affix-wrapper`]:{"&:hover, &:focus, &:active":{zIndex:2}},[`> ${t}-affix-wrapper-focused`]:{zIndex:2}}}}})(t),(e=>{let{componentCls:t}=e;return{[`${t}-out-of-range`]:{[`&, & input, & textarea, ${t}-show-count-suffix, ${t}-data-count`]:{color:e.colorError}}}})(t),(0,n.genCompactItemStyle)(t)]},l,{resetFont:!1});e.s(["default",0,T,"genBasicInputStyle",0,k,"genInputGroupStyle",0,O,"genInputSmallStyle",0,E,"genPlaceholderStyle",0,S,"useSharedStyle",0,j],349942)},831357,e=>{"use strict";var t=e.i(271645),r=e.i(343794),n=e.i(242064),o=e.i(62139),a=e.i(349942);e.s(["default",0,e=>{let{getPrefixCls:i,direction:l}=(0,t.useContext)(n.ConfigContext),{prefixCls:s,className:c}=e,u=i("input-group",s),d=i("input"),[f,p,m]=(0,a.default)(d),g=(0,r.default)(u,m,{[`${u}-lg`]:"large"===e.size,[`${u}-sm`]:"small"===e.size,[`${u}-compact`]:e.compact,[`${u}-rtl`]:"rtl"===l},p,c),h=(0,t.useContext)(o.FormItemInputContext),v=(0,t.useMemo)(()=>Object.assign(Object.assign({},h),{isFormItemInput:!1}),[h]);return f(t.createElement("span",{className:g,style:e.style,onMouseEnter:e.onMouseEnter,onMouseLeave:e.onMouseLeave,onFocus:e.onFocus,onBlur:e.onBlur},t.createElement(o.FormItemInputContext.Provider,{value:v},e.children)))}])},175636,131299,367397,874460,e=>{"use strict";var t=e.i(209428),r=e.i(931067),n=e.i(211577),o=e.i(410160),a=e.i(343794),i=e.i(271645);function l(e){return!!(e.addonBefore||e.addonAfter)}function s(e){return!!(e.prefix||e.suffix||e.allowClear)}function c(e,t,r){var n=t.cloneNode(!0),o=Object.create(e,{target:{value:n},currentTarget:{value:n}});return n.value=r,"number"==typeof t.selectionStart&&"number"==typeof t.selectionEnd&&(n.selectionStart=t.selectionStart,n.selectionEnd=t.selectionEnd),n.setSelectionRange=function(){t.setSelectionRange.apply(t,arguments)},o}function u(e,t,r,n){if(r){var o=t;if("click"===t.type)return void r(o=c(t,e,""));if("file"!==e.type&&void 0!==n)return void r(o=c(t,e,n));r(o)}}function d(e,t){if(e){e.focus(t);var r=(t||{}).cursor;if(r){var n=e.value.length;switch(r){case"start":e.setSelectionRange(0,0);break;case"end":e.setSelectionRange(n,n);break;default:e.setSelectionRange(0,n)}}}}e.s(["hasAddon",()=>l,"hasPrefixSuffix",()=>s,"resolveOnChange",()=>u,"triggerFocus",()=>d],131299);var f=i.default.forwardRef(function(e,c){var u,d,f,p=e.inputElement,m=e.children,g=e.prefixCls,h=e.prefix,v=e.suffix,y=e.addonBefore,b=e.addonAfter,w=e.className,C=e.style,x=e.disabled,S=e.readOnly,$=e.focused,E=e.triggerFocus,k=e.allowClear,O=e.value,j=e.handleReset,T=e.hidden,_=e.classes,P=e.classNames,I=e.dataAttrs,F=e.styles,N=e.components,R=e.onClear,M=null!=m?m:p,A=(null==N?void 0:N.affixWrapper)||"span",B=(null==N?void 0:N.groupWrapper)||"span",z=(null==N?void 0:N.wrapper)||"span",L=(null==N?void 0:N.groupAddon)||"span",H=(0,i.useRef)(null),D=s(e),V=(0,i.cloneElement)(M,{value:O,className:(0,a.default)(null==(u=M.props)?void 0:u.className,!D&&(null==P?void 0:P.variant))||null}),W=(0,i.useRef)(null);if(i.default.useImperativeHandle(c,function(){return{nativeElement:W.current||H.current}}),D){var U=null;if(k){var G=!x&&!S&&O,q="".concat(g,"-clear-icon"),K="object"===(0,o.default)(k)&&null!=k&&k.clearIcon?k.clearIcon:"✖";U=i.default.createElement("button",{type:"button",tabIndex:-1,onClick:function(e){null==j||j(e),null==R||R()},onMouseDown:function(e){return e.preventDefault()},className:(0,a.default)(q,(0,n.default)((0,n.default)({},"".concat(q,"-hidden"),!G),"".concat(q,"-has-suffix"),!!v))},K)}var X="".concat(g,"-affix-wrapper"),J=(0,a.default)(X,(0,n.default)((0,n.default)((0,n.default)((0,n.default)((0,n.default)({},"".concat(g,"-disabled"),x),"".concat(X,"-disabled"),x),"".concat(X,"-focused"),$),"".concat(X,"-readonly"),S),"".concat(X,"-input-with-clear-btn"),v&&k&&O),null==_?void 0:_.affixWrapper,null==P?void 0:P.affixWrapper,null==P?void 0:P.variant),Y=(v||k)&&i.default.createElement("span",{className:(0,a.default)("".concat(g,"-suffix"),null==P?void 0:P.suffix),style:null==F?void 0:F.suffix},U,v);V=i.default.createElement(A,(0,r.default)({className:J,style:null==F?void 0:F.affixWrapper,onClick:function(e){var t;null!=(t=H.current)&&t.contains(e.target)&&(null==E||E())}},null==I?void 0:I.affixWrapper,{ref:H}),h&&i.default.createElement("span",{className:(0,a.default)("".concat(g,"-prefix"),null==P?void 0:P.prefix),style:null==F?void 0:F.prefix},h),V,Y)}if(l(e)){var Q="".concat(g,"-group"),Z="".concat(Q,"-addon"),ee="".concat(Q,"-wrapper"),et=(0,a.default)("".concat(g,"-wrapper"),Q,null==_?void 0:_.wrapper,null==P?void 0:P.wrapper),er=(0,a.default)(ee,(0,n.default)({},"".concat(ee,"-disabled"),x),null==_?void 0:_.group,null==P?void 0:P.groupWrapper);V=i.default.createElement(B,{className:er,ref:W},i.default.createElement(z,{className:et},y&&i.default.createElement(L,{className:Z},y),V,b&&i.default.createElement(L,{className:Z},b)))}return i.default.cloneElement(V,{className:(0,a.default)(null==(d=V.props)?void 0:d.className,w)||null,style:(0,t.default)((0,t.default)({},null==(f=V.props)?void 0:f.style),C),hidden:T})});e.s(["default",0,f],367397);var p=e.i(8211),m=e.i(392221),g=e.i(703923),h=e.i(914949),v=e.i(529681),y=["show"];function b(e,r){return i.useMemo(function(){var n={};r&&(n.show="object"===(0,o.default)(r)&&r.formatter?r.formatter:!!r);var a=n=(0,t.default)((0,t.default)({},n),e),i=a.show,l=(0,g.default)(a,y);return(0,t.default)((0,t.default)({},l),{},{show:!!i,showFormatter:"function"==typeof i?i:void 0,strategy:l.strategy||function(e){return e.length}})},[e,r])}e.s(["default",()=>b],874460);var w=["autoComplete","onChange","onFocus","onBlur","onPressEnter","onKeyDown","onKeyUp","prefixCls","disabled","htmlSize","className","maxLength","suffix","showCount","count","type","classes","classNames","styles","onCompositionStart","onCompositionEnd"],C=(0,i.forwardRef)(function(e,o){var l,s=e.autoComplete,c=e.onChange,y=e.onFocus,C=e.onBlur,x=e.onPressEnter,S=e.onKeyDown,$=e.onKeyUp,E=e.prefixCls,k=void 0===E?"rc-input":E,O=e.disabled,j=e.htmlSize,T=e.className,_=e.maxLength,P=e.suffix,I=e.showCount,F=e.count,N=e.type,R=e.classes,M=e.classNames,A=e.styles,B=e.onCompositionStart,z=e.onCompositionEnd,L=(0,g.default)(e,w),H=(0,i.useState)(!1),D=(0,m.default)(H,2),V=D[0],W=D[1],U=(0,i.useRef)(!1),G=(0,i.useRef)(!1),q=(0,i.useRef)(null),K=(0,i.useRef)(null),X=function(e){q.current&&d(q.current,e)},J=(0,h.default)(e.defaultValue,{value:e.value}),Y=(0,m.default)(J,2),Q=Y[0],Z=Y[1],ee=null==Q?"":String(Q),et=(0,i.useState)(null),er=(0,m.default)(et,2),en=er[0],eo=er[1],ea=b(F,I),ei=ea.max||_,el=ea.strategy(ee),es=!!ei&&el>ei;(0,i.useImperativeHandle)(o,function(){var e;return{focus:X,blur:function(){var e;null==(e=q.current)||e.blur()},setSelectionRange:function(e,t,r){var n;null==(n=q.current)||n.setSelectionRange(e,t,r)},select:function(){var e;null==(e=q.current)||e.select()},input:q.current,nativeElement:(null==(e=K.current)?void 0:e.nativeElement)||q.current}}),(0,i.useEffect)(function(){G.current&&(G.current=!1),W(function(e){return(!e||!O)&&e})},[O]);var ec=function(e,t,r){var n,o,a=t;if(!U.current&&ea.exceedFormatter&&ea.max&&ea.strategy(t)>ea.max)a=ea.exceedFormatter(t,{max:ea.max}),t!==a&&eo([(null==(n=q.current)?void 0:n.selectionStart)||0,(null==(o=q.current)?void 0:o.selectionEnd)||0]);else if("compositionEnd"===r.source)return;Z(a),q.current&&u(q.current,e,c,a)};(0,i.useEffect)(function(){if(en){var e;null==(e=q.current)||e.setSelectionRange.apply(e,(0,p.default)(en))}},[en]);var eu=es&&"".concat(k,"-out-of-range");return i.default.createElement(f,(0,r.default)({},L,{prefixCls:k,className:(0,a.default)(T,eu),handleReset:function(e){Z(""),X(),q.current&&u(q.current,e,c)},value:ee,focused:V,triggerFocus:X,suffix:function(){var e=Number(ei)>0;if(P||ea.show){var r=ea.showFormatter?ea.showFormatter({value:ee,count:el,maxLength:ei}):"".concat(el).concat(e?" / ".concat(ei):"");return i.default.createElement(i.default.Fragment,null,ea.show&&i.default.createElement("span",{className:(0,a.default)("".concat(k,"-show-count-suffix"),(0,n.default)({},"".concat(k,"-show-count-has-suffix"),!!P),null==M?void 0:M.count),style:(0,t.default)({},null==A?void 0:A.count)},r),P)}return null}(),disabled:O,classes:R,classNames:M,styles:A,ref:K}),(l=(0,v.default)(e,["prefixCls","onPressEnter","addonBefore","addonAfter","prefix","suffix","allowClear","defaultValue","showCount","count","classes","htmlSize","styles","classNames","onClear"]),i.default.createElement("input",(0,r.default)({autoComplete:s},l,{onChange:function(e){ec(e,e.target.value,{source:"change"})},onFocus:function(e){W(!0),null==y||y(e)},onBlur:function(e){G.current&&(G.current=!1),W(!1),null==C||C(e)},onKeyDown:function(e){x&&"Enter"===e.key&&!G.current&&(G.current=!0,x(e)),null==S||S(e)},onKeyUp:function(e){"Enter"===e.key&&(G.current=!1),null==$||$(e)},className:(0,a.default)(k,(0,n.default)({},"".concat(k,"-disabled"),O),null==M?void 0:M.input),style:null==A?void 0:A.input,ref:q,size:j,type:void 0===N?"text":N,onCompositionStart:function(e){U.current=!0,null==B||B(e)},onCompositionEnd:function(e){U.current=!1,ec(e,e.currentTarget.value,{source:"compositionEnd"}),null==z||z(e)}}))))});e.s(["default",0,C],175636)},330683,e=>{"use strict";var t=e.i(271645),r=e.i(726289);e.s(["default",0,e=>{let n;return"object"==typeof e&&(null==e?void 0:e.clearIcon)?n=e:e&&(n={clearIcon:t.default.createElement(r.default,null)}),n}])},52956,e=>{"use strict";var t=e.i(343794);function r(e,r,n){return(0,t.default)({[`${e}-status-success`]:"success"===r,[`${e}-status-warning`]:"warning"===r,[`${e}-status-error`]:"error"===r,[`${e}-status-validating`]:"validating"===r,[`${e}-has-feedback`]:n})}e.s(["getMergedStatus",0,(e,t)=>t||e,"getStatusClassNames",()=>r])},792812,e=>{"use strict";var t=e.i(271645),r=e.i(242064),n=e.i(62139);e.s(["default",0,(e,o,a)=>{var i,l;let s,{variant:c,[e]:u}=t.useContext(r.ConfigContext),d=t.useContext(n.VariantContext),f=null==u?void 0:u.variant;s=void 0!==o?o:!1===a?"borderless":null!=(l=null!=(i=null!=d?d:f)?i:c)?l:"outlined";let p=r.Variants.includes(s);return[s,p]}])},90635,545719,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(175636);e.i(131299);var o=e.i(611935),a=e.i(617206),i=e.i(330683),l=e.i(52956),s=e.i(242064),c=e.i(937328),u=e.i(321883),d=e.i(517455),f=e.i(62139),p=e.i(792812),m=e.i(249616);function g(e,r){let n=(0,t.useRef)([]),o=()=>{n.current.push(setTimeout(()=>{var t,r,n,o;(null==(t=e.current)?void 0:t.input)&&(null==(r=e.current)?void 0:r.input.getAttribute("type"))==="password"&&(null==(n=e.current)?void 0:n.input.hasAttribute("value"))&&(null==(o=e.current)||o.input.removeAttribute("value"))}))};return(0,t.useEffect)(()=>(r&&o(),()=>n.current.forEach(e=>{e&&clearTimeout(e)})),[]),o}e.s(["default",()=>g],545719);var h=e.i(349942),v=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 y=(0,t.forwardRef)((e,y)=>{let{prefixCls:b,bordered:w=!0,status:C,size:x,disabled:S,onBlur:$,onFocus:E,suffix:k,allowClear:O,addonAfter:j,addonBefore:T,className:_,style:P,styles:I,rootClassName:F,onChange:N,classNames:R,variant:M,_skipAddonWarning:A}=e,B=v(e,["prefixCls","bordered","status","size","disabled","onBlur","onFocus","suffix","allowClear","addonAfter","addonBefore","className","style","styles","rootClassName","onChange","classNames","variant","_skipAddonWarning"]),{getPrefixCls:z,direction:L,allowClear:H,autoComplete:D,className:V,style:W,classNames:U,styles:G}=(0,s.useComponentConfig)("input"),q=z("input",b),K=(0,t.useRef)(null),X=(0,u.default)(q),[J,Y,Q]=(0,h.useSharedStyle)(q,F),[Z]=(0,h.default)(q,X),{compactSize:ee,compactItemClassnames:et}=(0,m.useCompactItemContext)(q,L),er=(0,d.default)(e=>{var t;return null!=(t=null!=x?x:ee)?t:e}),en=t.default.useContext(c.default),{status:eo,hasFeedback:ea,feedbackIcon:ei}=(0,t.useContext)(f.FormItemInputContext),el=(0,l.getMergedStatus)(eo,C),es=!!(e.prefix||e.suffix||e.allowClear||e.showCount)||!!ea;(0,t.useRef)(es);let ec=g(K,!0),eu=(ea||k)&&t.default.createElement(t.default.Fragment,null,k,ea&&ei),ed=(0,i.default)(null!=O?O:H),[ef,ep]=(0,p.default)("input",M,w);return J(Z(t.default.createElement(n.default,Object.assign({ref:(0,o.composeRef)(y,K),prefixCls:q,autoComplete:D},B,{disabled:null!=S?S:en,onBlur:e=>{ec(),null==$||$(e)},onFocus:e=>{ec(),null==E||E(e)},style:Object.assign(Object.assign({},W),P),styles:Object.assign(Object.assign({},G),I),suffix:eu,allowClear:ed,className:(0,r.default)(_,F,Q,X,et,V),onChange:e=>{ec(),null==N||N(e)},addonBefore:T&&t.default.createElement(a.default,{form:!0,space:!0},T),addonAfter:j&&t.default.createElement(a.default,{form:!0,space:!0},j),classNames:Object.assign(Object.assign(Object.assign({},R),U),{input:(0,r.default)({[`${q}-sm`]:"small"===er,[`${q}-lg`]:"large"===er,[`${q}-rtl`]:"rtl"===L},null==R?void 0:R.input,U.input,Y),variant:(0,r.default)({[`${q}-${ef}`]:ep},(0,l.getStatusClassNames)(q,el)),affixWrapper:(0,r.default)({[`${q}-affix-wrapper-sm`]:"small"===er,[`${q}-affix-wrapper-lg`]:"large"===er,[`${q}-affix-wrapper-rtl`]:"rtl"===L},Y),wrapper:(0,r.default)({[`${q}-group-rtl`]:"rtl"===L},Y),groupWrapper:(0,r.default)({[`${q}-group-wrapper-sm`]:"small"===er,[`${q}-group-wrapper-lg`]:"large"===er,[`${q}-group-wrapper-rtl`]:"rtl"===L,[`${q}-group-wrapper-${ef}`]:ep},(0,l.getStatusClassNames)(`${q}-group-wrapper`,el,ea),Y)})}))))});e.s(["default",0,y],90635)},932399,741585,984125,236798,e=>{"use strict";e.i(247167);var t=e.i(8211),r=e.i(271645),n=e.i(343794),o=e.i(175066),a=e.i(244009),i=e.i(52956),l=e.i(242064),s=e.i(517455),c=e.i(62139),u=e.i(246422),d=e.i(838378),f=e.i(517458);let p=(0,u.genStyleHooks)(["Input","OTP"],e=>(e=>{let{componentCls:t,paddingXS:r}=e;return{[t]:{display:"inline-flex",alignItems:"center",flexWrap:"nowrap",columnGap:r,[`${t}-input-wrapper`]:{position:"relative",[`${t}-mask-icon`]:{position:"absolute",zIndex:"1",top:"50%",right:"50%",transform:"translate(50%, -50%)",pointerEvents:"none"},[`${t}-mask-input`]:{color:"transparent",caretColor:e.colorText},[`${t}-mask-input[type=number]::-webkit-inner-spin-button`]:{"-webkit-appearance":"none",margin:0},[`${t}-mask-input[type=number]`]:{"-moz-appearance":"textfield"}},"&-rtl":{direction:"rtl"},[`${t}-input`]:{textAlign:"center",paddingInline:e.paddingXXS},[`&${t}-sm ${t}-input`]:{paddingInline:e.calc(e.paddingXXS).div(2).equal()},[`&${t}-lg ${t}-input`]:{paddingInline:e.paddingXS}}}})((0,d.mergeToken)(e,(0,f.initInputToken)(e))),f.initComponentToken);var m=e.i(963188),g=e.i(90635),h=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 v=r.forwardRef((e,t)=>{let{className:o,value:a,onChange:i,onActiveChange:s,index:c,mask:u}=e,d=h(e,["className","value","onChange","onActiveChange","index","mask"]),{getPrefixCls:f}=r.useContext(l.ConfigContext),p=f("otp"),v="string"==typeof u?u:a,y=r.useRef(null);r.useImperativeHandle(t,()=>y.current);let b=()=>{(0,m.default)(()=>{var e;let t=null==(e=y.current)?void 0:e.input;document.activeElement===t&&t&&t.select()})};return r.createElement("span",{className:`${p}-input-wrapper`,role:"presentation"},u&&""!==a&&void 0!==a&&r.createElement("span",{className:`${p}-mask-icon`,"aria-hidden":"true"},v),r.createElement(g.default,Object.assign({"aria-label":`OTP Input ${c+1}`,type:!0===u?"password":"text"},d,{ref:y,value:a,onInput:e=>{i(c,e.target.value)},onFocus:b,onKeyDown:e=>{let{key:t,ctrlKey:r,metaKey:n}=e;"ArrowLeft"===t?s(c-1):"ArrowRight"===t?s(c+1):"z"===t&&(r||n)?e.preventDefault():"Backspace"!==t||a||s(c-1),b()},onMouseDown:b,onMouseUp:b,className:(0,n.default)(o,{[`${p}-mask-input`]:u})})))});var y=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};function b(e){return(e||"").split("")}let w=e=>{let{index:t,prefixCls:n,separator:o}=e,a="function"==typeof o?o(t):o;return a?r.createElement("span",{className:`${n}-separator`},a):null},C=r.forwardRef((e,u)=>{let{prefixCls:d,length:f=6,size:m,defaultValue:g,value:h,onChange:C,formatter:x,separator:S,variant:$,disabled:E,status:k,autoFocus:O,mask:j,type:T,onInput:_,inputMode:P}=e,I=y(e,["prefixCls","length","size","defaultValue","value","onChange","formatter","separator","variant","disabled","status","autoFocus","mask","type","onInput","inputMode"]),{getPrefixCls:F,direction:N}=r.useContext(l.ConfigContext),R=F("otp",d),M=(0,a.default)(I,{aria:!0,data:!0,attr:!0}),[A,B,z]=p(R),L=(0,s.default)(e=>null!=m?m:e),H=r.useContext(c.FormItemInputContext),D=(0,i.getMergedStatus)(H.status,k),V=r.useMemo(()=>Object.assign(Object.assign({},H),{status:D,hasFeedback:!1,feedbackIcon:null}),[H,D]),W=r.useRef(null),U=r.useRef({});r.useImperativeHandle(u,()=>({focus:()=>{var e;null==(e=U.current[0])||e.focus()},blur:()=>{var e;for(let t=0;tx?x(e):e,[q,K]=r.useState(()=>b(G(g||"")));r.useEffect(()=>{void 0!==h&&K(b(h))},[h]);let X=(0,o.default)(e=>{K(e),_&&_(e),C&&e.length===f&&e.every(e=>e)&&e.some((e,t)=>q[t]!==e)&&C(e.join(""))}),J=(0,o.default)((e,r)=>{let n=(0,t.default)(q);for(let t=0;t=0&&!n[e];e-=1)n.pop();return n=b(G(n.map(e=>e||" ").join(""))).map((e,t)=>" "!==e||n[t]?e:n[t])}),Y=(e,t)=>{var r;let n=J(e,t),o=Math.min(e+t.length,f-1);o!==e&&void 0!==n[e]&&(null==(r=U.current[o])||r.focus()),X(n)},Q=e=>{var t;null==(t=U.current[e])||t.focus()},Z={variant:$,disabled:E,status:D,mask:j,type:T,inputMode:P};return A(r.createElement("div",Object.assign({},M,{ref:W,className:(0,n.default)(R,{[`${R}-sm`]:"small"===L,[`${R}-lg`]:"large"===L,[`${R}-rtl`]:"rtl"===N},z,B),role:"group"}),r.createElement(c.FormItemInputContext.Provider,{value:V},Array.from({length:f}).map((e,t)=>{let n=`otp-${t}`,o=q[t]||"";return r.createElement(r.Fragment,{key:n},r.createElement(v,Object.assign({ref:e=>{U.current[t]=e},index:t,size:L,htmlSize:1,className:`${R}-input`,onChange:Y,value:o,onActiveChange:Q,autoFocus:0===t&&O},Z)),tt.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 F=e=>e?r.createElement(O,null):r.createElement(E,null),N={click:"onClick",hover:"onMouseOver"},R=r.forwardRef((e,t)=>{let o,a,i,{disabled:s,action:c="click",visibilityToggle:u=!0,iconRender:d=F,suffix:f}=e,p=r.useContext(_.default),m=null!=s?s:p,h="object"==typeof u&&void 0!==u.visible,[v,y]=(0,r.useState)(()=>!!h&&u.visible),b=(0,r.useRef)(null);r.useEffect(()=>{h&&y(u.visible)},[h,u]);let w=(0,P.default)(b),{className:C,prefixCls:x,inputPrefixCls:S,size:$}=e,E=I(e,["className","prefixCls","inputPrefixCls","size"]),{getPrefixCls:k}=r.useContext(l.ConfigContext),O=k("input",S),R=k("input-password",x),M=u&&(o=N[c]||"",a=d(v),i={[o]:()=>{var e;if(m)return;v&&w();let t=!v;y(t),"object"==typeof u&&(null==(e=u.onVisibleChange)||e.call(u,t))},className:`${R}-icon`,key:"passwordIcon",onMouseDown:e=>{e.preventDefault()},onMouseUp:e=>{e.preventDefault()}},r.cloneElement(r.isValidElement(a)?a:r.createElement("span",null,a),i)),A=(0,n.default)(R,C,{[`${R}-${$}`]:!!$}),B=Object.assign(Object.assign({},(0,j.default)(E,["suffix","iconRender","visibilityToggle"])),{type:v?"text":"password",className:A,prefixCls:O,suffix:r.createElement(r.Fragment,null,M,f)});return $&&(B.size=$),r.createElement(g.default,Object.assign({ref:(0,T.composeRef)(t,b)},B))});e.s(["default",0,R],236798)},38953,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"}}]},name:"search",theme:"outlined"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],38953)},121872,26905,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(606262),o=e.i(611935),a=e.i(242064),i=e.i(763731);let l=(0,e.i(246422).genComponentStyleHook)("Wave",e=>{let{componentCls:t,colorPrimary:r}=e;return{[t]:{position:"absolute",background:"transparent",pointerEvents:"none",boxSizing:"border-box",color:`var(--wave-color, ${r})`,boxShadow:"0 0 0 0 currentcolor",opacity:.2,"&.wave-motion-appear":{transition:`box-shadow 0.4s ${e.motionEaseOutCirc},opacity 2s ${e.motionEaseOutCirc}`,"&-active":{boxShadow:"0 0 0 6px currentcolor",opacity:0},"&.wave-quick":{transition:`box-shadow ${e.motionDurationSlow} ${e.motionEaseInOut},opacity ${e.motionDurationSlow} ${e.motionEaseInOut}`}}}}});var s=e.i(175066),c=e.i(963188),u=e.i(719581);let d=`${a.defaultPrefixCls}-wave-target`;e.s(["TARGET_CLS",0,d],26905);var f=e.i(361275),p=e.i(783164);function m(e){return e&&"#fff"!==e&&"#ffffff"!==e&&"rgb(255, 255, 255)"!==e&&"rgba(255, 255, 255, 1)"!==e&&!/rgba\((?:\d*, ){3}0\)/.test(e)&&"transparent"!==e&&"canvastext"!==e}function g(e){return Number.isNaN(e)?0:e}let h=e=>{let{className:n,target:a,component:i,registerUnmount:l}=e,s=t.useRef(null),u=t.useRef(null);t.useEffect(()=>{u.current=l()},[]);let[p,h]=t.useState(null),[v,y]=t.useState([]),[b,w]=t.useState(0),[C,x]=t.useState(0),[S,$]=t.useState(0),[E,k]=t.useState(0),[O,j]=t.useState(!1),T={left:b,top:C,width:S,height:E,borderRadius:v.map(e=>`${e}px`).join(" ")};function _(){let e=getComputedStyle(a);h(function(e){var t;let{borderTopColor:r,borderColor:n,backgroundColor:o}=getComputedStyle(e);return null!=(t=[r,n,o].find(m))?t:null}(a));let t="static"===e.position,{borderLeftWidth:r,borderTopWidth:n}=e;w(t?a.offsetLeft:g(-Number.parseFloat(r))),x(t?a.offsetTop:g(-Number.parseFloat(n))),$(a.offsetWidth),k(a.offsetHeight);let{borderTopLeftRadius:o,borderTopRightRadius:i,borderBottomLeftRadius:l,borderBottomRightRadius:s}=e;y([o,i,s,l].map(e=>g(Number.parseFloat(e))))}if(p&&(T["--wave-color"]=p),t.useEffect(()=>{if(a){let e,t=(0,c.default)(()=>{_(),j(!0)});return"u">typeof ResizeObserver&&(e=new ResizeObserver(_)).observe(a),()=>{c.default.cancel(t),null==e||e.disconnect()}}},[a]),!O)return null;let P=("Checkbox"===i||"Radio"===i)&&(null==a?void 0:a.classList.contains(d));return t.createElement(f.default,{visible:!0,motionAppear:!0,motionName:"wave-motion",motionDeadline:5e3,onAppearEnd:(e,t)=>{var r,n;if(t.deadline||"opacity"===t.propertyName){let e=null==(r=s.current)?void 0:r.parentElement;null==(n=u.current)||n.call(u).then(()=>{null==e||e.remove()})}return!1}},({className:e},a)=>t.createElement("div",{ref:(0,o.composeRef)(s,a),className:(0,r.default)(n,e,{"wave-quick":P}),style:T}))};e.s(["default",0,e=>{let{children:f,disabled:m,component:g}=e,{getPrefixCls:v}=(0,t.useContext)(a.ConfigContext),y=(0,t.useRef)(null),b=v("wave"),[,w]=l(b),C=((e,r,n)=>{let{wave:o}=t.useContext(a.ConfigContext),[,i,l]=(0,u.default)(),f=(0,s.default)(a=>{let s=e.current;if((null==o?void 0:o.disabled)||!s)return;let c=s.querySelector(`.${d}`)||s,{showEffect:u}=o||{};(u||((e,r)=>{var n;let{component:o}=r;if("Checkbox"===o&&!(null==(n=e.querySelector("input"))?void 0:n.checked))return;let a=document.createElement("div");a.style.position="absolute",a.style.left="0px",a.style.top="0px",null==e||e.insertBefore(a,null==e?void 0:e.firstChild);let i=(0,p.unstableSetRender)(),l=null;l=i(t.createElement(h,Object.assign({},r,{target:e,registerUnmount:function(){return l}})),a)}))(c,{className:r,token:i,component:n,event:a,hashId:l})}),m=t.useRef(null);return e=>{c.default.cancel(m.current),m.current=(0,c.default)(()=>{f(e)})}})(y,(0,r.default)(b,w),g);if(t.default.useEffect(()=>{let e=y.current;if(!e||e.nodeType!==window.Node.ELEMENT_NODE||m)return;let t=t=>{!(0,n.default)(t.target)||!e.getAttribute||e.getAttribute("disabled")||e.disabled||e.className.includes("disabled")&&!e.className.includes("disabled:")||"true"===e.getAttribute("aria-disabled")||e.className.includes("-leave")||C(t)};return e.addEventListener("click",t,!0),()=>{e.removeEventListener("click",t,!0)}},[m]),!t.default.isValidElement(f))return null!=f?f:null;let x=(0,o.supportRef)(f)?(0,o.composeRef)((0,o.getNodeRef)(f),y):y;return(0,i.cloneElement)(f,{ref:x})}],121872)},735996,e=>{"use strict";var t=e.i(271645),r=e.i(343794),n=e.i(242064),o=e.i(104458),a=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 i=t.createContext(void 0);e.s(["GroupSizeContext",0,i,"default",0,e=>{let{getPrefixCls:l,direction:s}=t.useContext(n.ConfigContext),{prefixCls:c,size:u,className:d}=e,f=a(e,["prefixCls","size","className"]),p=l("btn-group",c),[,,m]=(0,o.useToken)(),g=t.useMemo(()=>{switch(u){case"large":return"lg";case"small":return"sm";default:return""}},[u]),h=(0,r.default)(p,{[`${p}-${g}`]:g,[`${p}-rtl`]:"rtl"===s},d,m);return t.createElement(i.Provider,{value:u},t.createElement("div",Object.assign({},f,{className:h})))}])},62405,869693,868004,470977,e=>{"use strict";var t=e.i(8211),r=e.i(271645),n=e.i(763731),o=e.i(617933);let a=/^[\u4E00-\u9FA5]{2}$/,i=a.test.bind(a);function l(e){return"danger"===e?{danger:!0}:{type:e}}function s(e){return"string"==typeof e}function c(e){return"text"===e||"link"===e}function u(e,t){let o=!1,a=[];return r.default.Children.forEach(e,e=>{let t=typeof e,r="string"===t||"number"===t;if(o&&r){let t=a.length-1,r=a[t];a[t]=`${r}${e}`}else a.push(e);o=r}),r.default.Children.map(a,e=>(function(e,t){if(null==e)return;let o=t?" ":"";return"string"!=typeof e&&"number"!=typeof e&&s(e.type)&&i(e.props.children)?(0,n.cloneElement)(e,{children:e.props.children.split("").join(o)}):s(e)?i(e)?r.default.createElement("span",null,e.split("").join(o)):r.default.createElement("span",null,e):(0,n.isFragment)(e)?r.default.createElement("span",null,e):e})(e,t))}["default","primary","danger"].concat((0,t.default)(o.PresetColors)),e.s(["convertLegacyProps",()=>l,"isTwoCNChar",0,i,"isUnBorderedButtonVariant",()=>c,"spaceChildren",()=>u],62405);var d=e.i(739295),f=e.i(343794),p=e.i(361275);let m=(0,r.forwardRef)((e,t)=>{let{className:n,style:o,children:a,prefixCls:i}=e,l=(0,f.default)(`${i}-icon`,n);return r.default.createElement("span",{ref:t,className:l,style:o},a)});e.s(["default",0,m],869693);let g=(0,r.forwardRef)((e,t)=>{let{prefixCls:n,className:o,style:a,iconClassName:i}=e,l=(0,f.default)(`${n}-loading-icon`,o);return r.default.createElement(m,{prefixCls:n,className:l,style:a,ref:t},r.default.createElement(d.default,{className:i}))}),h=()=>({width:0,opacity:0,transform:"scale(0)"}),v=e=>({width:e.scrollWidth,opacity:1,transform:"scale(1)"});e.s(["default",0,e=>{let{prefixCls:t,loading:n,existIcon:o,className:a,style:i,mount:l}=e;return o?r.default.createElement(g,{prefixCls:t,className:a,style:i}):r.default.createElement(p.default,{visible:!!n,motionName:`${t}-loading-icon-motion`,motionAppear:!l,motionEnter:!l,motionLeave:!l,removeOnLeave:!0,onAppearStart:h,onAppearActive:v,onEnterStart:h,onEnterActive:v,onLeaveStart:v,onLeaveActive:h},({className:e,style:n},o)=>{let l=Object.assign(Object.assign({},i),n);return r.default.createElement(g,{prefixCls:t,className:(0,f.default)(a,e),style:l,ref:o})})}],868004);let y=(e,t)=>({[`> span, > ${e}`]:{"&:not(:last-child)":{[`&, & > ${e}`]:{"&:not(:disabled)":{borderInlineEndColor:t}}},"&:not(:first-child)":{[`&, & > ${e}`]:{"&:not(:disabled)":{borderInlineStartColor:t}}}}});e.s(["default",0,e=>{let{componentCls:t,fontSize:r,lineWidth:n,groupBorderColor:o,colorErrorHover:a}=e;return{[`${t}-group`]:[{position:"relative",display:"inline-flex",[`> span, > ${t}`]:{"&:not(:last-child)":{[`&, & > ${t}`]:{borderStartEndRadius:0,borderEndEndRadius:0}},"&:not(:first-child)":{marginInlineStart:e.calc(n).mul(-1).equal(),[`&, & > ${t}`]:{borderStartStartRadius:0,borderEndStartRadius:0}}},[t]:{position:"relative",zIndex:1,"&:hover, &:focus, &:active":{zIndex:2},"&[disabled]":{zIndex:0}},[`${t}-icon-only`]:{fontSize:r}},y(`${t}-primary`,o),y(`${t}-danger`,a)]}}],470977)},202599,e=>{"use strict";var t=e.i(162464);e.s(["ColorBlock",()=>t.default])},286612,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={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"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],286612)},301092,e=>{"use strict";var t=e.i(931067),r=e.i(8211),n=e.i(392221),o=e.i(410160),a=e.i(343794),i=e.i(914949),l=e.i(883110),s=e.i(271645),c=e.i(703923),u=e.i(876556),d=e.i(209428),f=e.i(211577),p=e.i(361275),m=e.i(404948),g=s.default.forwardRef(function(e,t){var r=e.prefixCls,o=e.forceRender,i=e.className,l=e.style,c=e.children,u=e.isActive,d=e.role,p=e.classNames,m=e.styles,g=s.default.useState(u||o),h=(0,n.default)(g,2),v=h[0],y=h[1];return(s.default.useEffect(function(){(o||u)&&y(!0)},[o,u]),v)?s.default.createElement("div",{ref:t,className:(0,a.default)("".concat(r,"-content"),(0,f.default)((0,f.default)({},"".concat(r,"-content-active"),u),"".concat(r,"-content-inactive"),!u),i),style:l,role:d},s.default.createElement("div",{className:(0,a.default)("".concat(r,"-content-box"),null==p?void 0:p.body),style:null==m?void 0:m.body},c)):null});g.displayName="PanelContent";var h=["showArrow","headerClass","isActive","onItemClick","forceRender","className","classNames","styles","prefixCls","collapsible","accordion","panelKey","extra","header","expandIcon","openMotion","destroyInactivePanel","children"],v=s.default.forwardRef(function(e,r){var n=e.showArrow,o=e.headerClass,i=e.isActive,l=e.onItemClick,u=e.forceRender,v=e.className,y=e.classNames,b=void 0===y?{}:y,w=e.styles,C=void 0===w?{}:w,x=e.prefixCls,S=e.collapsible,$=e.accordion,E=e.panelKey,k=e.extra,O=e.header,j=e.expandIcon,T=e.openMotion,_=e.destroyInactivePanel,P=e.children,I=(0,c.default)(e,h),F="disabled"===S,N=(0,f.default)((0,f.default)((0,f.default)({onClick:function(){null==l||l(E)},onKeyDown:function(e){("Enter"===e.key||e.keyCode===m.default.ENTER||e.which===m.default.ENTER)&&(null==l||l(E))},role:$?"tab":"button"},"aria-expanded",i),"aria-disabled",F),"tabIndex",F?-1:0),R="function"==typeof j?j(e):s.default.createElement("i",{className:"arrow"}),M=R&&s.default.createElement("div",(0,t.default)({className:"".concat(x,"-expand-icon")},["header","icon"].includes(S)?N:{}),R),A=(0,a.default)("".concat(x,"-item"),(0,f.default)((0,f.default)({},"".concat(x,"-item-active"),i),"".concat(x,"-item-disabled"),F),v),B=(0,a.default)(o,"".concat(x,"-header"),(0,f.default)({},"".concat(x,"-collapsible-").concat(S),!!S),b.header),z=(0,d.default)({className:B,style:C.header},["header","icon"].includes(S)?{}:N);return s.default.createElement("div",(0,t.default)({},I,{ref:r,className:A}),s.default.createElement("div",z,(void 0===n||n)&&M,s.default.createElement("span",(0,t.default)({className:"".concat(x,"-header-text")},"header"===S?N:{}),O),null!=k&&"boolean"!=typeof k&&s.default.createElement("div",{className:"".concat(x,"-extra")},k)),s.default.createElement(p.default,(0,t.default)({visible:i,leavedClassName:"".concat(x,"-content-hidden")},T,{forceRender:u,removeOnLeave:_}),function(e,t){var r=e.className,n=e.style;return s.default.createElement(g,{ref:t,prefixCls:x,className:r,classNames:b,style:n,styles:C,isActive:i,forceRender:u,role:$?"tabpanel":void 0},P)}))}),y=["children","label","key","collapsible","onItemClick","destroyInactivePanel"],b=function(e,r){var n=r.prefixCls,o=r.accordion,a=r.collapsible,i=r.destroyInactivePanel,l=r.onItemClick,u=r.activeKey,d=r.openMotion,f=r.expandIcon;return e.map(function(e,r){var p=e.children,m=e.label,g=e.key,h=e.collapsible,b=e.onItemClick,w=e.destroyInactivePanel,C=(0,c.default)(e,y),x=String(null!=g?g:r),S=null!=h?h:a,$=!1;return $=o?u[0]===x:u.indexOf(x)>-1,s.default.createElement(v,(0,t.default)({},C,{prefixCls:n,key:x,panelKey:x,isActive:$,accordion:o,openMotion:d,expandIcon:f,header:m,collapsible:S,onItemClick:function(e){"disabled"!==S&&(l(e),null==b||b(e))},destroyInactivePanel:null!=w?w:i}),p)})},w=function(e,t,r){if(!e)return null;var n=r.prefixCls,o=r.accordion,a=r.collapsible,i=r.destroyInactivePanel,l=r.onItemClick,c=r.activeKey,u=r.openMotion,d=r.expandIcon,f=e.key||String(t),p=e.props,m=p.header,g=p.headerClass,h=p.destroyInactivePanel,v=p.collapsible,y=p.onItemClick,b=!1;b=o?c[0]===f:c.indexOf(f)>-1;var w=null!=v?v:a,C={key:f,panelKey:f,header:m,headerClass:g,isActive:b,prefixCls:n,destroyInactivePanel:null!=h?h:i,openMotion:u,accordion:o,children:e.props.children,onItemClick:function(e){"disabled"!==w&&(l(e),null==y||y(e))},expandIcon:d,collapsible:w};return"string"==typeof e.type?e:(Object.keys(C).forEach(function(e){void 0===C[e]&&delete C[e]}),s.default.cloneElement(e,C))},C=e.i(244009);function x(e){var t=e;if(!Array.isArray(t)){var r=(0,o.default)(t);t="number"===r||"string"===r?[t]:[]}return t.map(function(e){return String(e)})}let S=Object.assign(s.default.forwardRef(function(e,o){var c,d=e.prefixCls,f=void 0===d?"rc-collapse":d,p=e.destroyInactivePanel,m=e.style,g=e.accordion,h=e.className,v=e.children,y=e.collapsible,S=e.openMotion,$=e.expandIcon,E=e.activeKey,k=e.defaultActiveKey,O=e.onChange,j=e.items,T=(0,a.default)(f,h),_=(0,i.default)([],{value:E,onChange:function(e){return null==O?void 0:O(e)},defaultValue:k,postState:x}),P=(0,n.default)(_,2),I=P[0],F=P[1];(0,l.default)(!v,"[rc-collapse] `children` will be removed in next major version. Please use `items` instead.");var N=(c={prefixCls:f,accordion:g,openMotion:S,expandIcon:$,collapsible:y,destroyInactivePanel:void 0!==p&&p,onItemClick:function(e){return F(function(){return g?I[0]===e?[]:[e]:I.indexOf(e)>-1?I.filter(function(t){return t!==e}):[].concat((0,r.default)(I),[e])})},activeKey:I},Array.isArray(j)?b(j,c):(0,u.default)(v).map(function(e,t){return w(e,t,c)}));return s.default.createElement("div",(0,t.default)({ref:o,className:T,style:m,role:g?"tablist":void 0},(0,C.default)(e,{aria:!0,data:!0})),N)}),{Panel:v});S.Panel,e.s(["default",0,S],301092)},125234,e=>{"use strict";var t=e.i(271645),r=e.i(343794),n=e.i(301092),o=e.i(242064);let a=t.forwardRef((e,a)=>{let{getPrefixCls:i}=t.useContext(o.ConfigContext),{prefixCls:l,className:s,showArrow:c=!0}=e,u=i("collapse",l),d=(0,r.default)({[`${u}-no-arrow`]:!c},s);return t.createElement(n.default.Panel,Object.assign({ref:a},e,{prefixCls:u,className:d}))});e.s(["default",0,a])},988122,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(286612),n=e.i(343794),o=e.i(301092),a=e.i(876556),i=e.i(529681),l=e.i(613541),s=e.i(763731),c=e.i(242064),u=e.i(517455),d=e.i(125234);e.i(296059);var f=e.i(915654),p=e.i(183293),m=e.i(447580),g=e.i(246422),h=e.i(838378);let v=(0,g.genStyleHooks)("Collapse",e=>{let t=(0,h.mergeToken)(e,{collapseHeaderPaddingSM:`${(0,f.unit)(e.paddingXS)} ${(0,f.unit)(e.paddingSM)}`,collapseHeaderPaddingLG:`${(0,f.unit)(e.padding)} ${(0,f.unit)(e.paddingLG)}`,collapsePanelBorderRadius:e.borderRadiusLG});return[(e=>{let{componentCls:t,contentBg:r,padding:n,headerBg:o,headerPadding:a,collapseHeaderPaddingSM:i,collapseHeaderPaddingLG:l,collapsePanelBorderRadius:s,lineWidth:c,lineType:u,colorBorder:d,colorText:m,colorTextHeading:g,colorTextDisabled:h,fontSizeLG:v,lineHeight:y,lineHeightLG:b,marginSM:w,paddingSM:C,paddingLG:x,paddingXS:S,motionDurationSlow:$,fontSizeIcon:E,contentPadding:k,fontHeight:O,fontHeightLG:j}=e,T=`${(0,f.unit)(c)} ${u} ${d}`;return{[t]:Object.assign(Object.assign({},(0,p.resetComponent)(e)),{backgroundColor:o,border:T,borderRadius:s,"&-rtl":{direction:"rtl"},[`& > ${t}-item`]:{borderBottom:T,"&:first-child":{[` + &, + & > ${t}-header`]:{borderRadius:`${(0,f.unit)(s)} ${(0,f.unit)(s)} 0 0`}},"&:last-child":{[` + &, + & > ${t}-header`]:{borderRadius:`0 0 ${(0,f.unit)(s)} ${(0,f.unit)(s)}`}},[`> ${t}-header`]:Object.assign(Object.assign({position:"relative",display:"flex",flexWrap:"nowrap",alignItems:"flex-start",padding:a,color:g,lineHeight:y,cursor:"pointer",transition:`all ${$}, visibility 0s`},(0,p.genFocusStyle)(e)),{[`> ${t}-header-text`]:{flex:"auto"},[`${t}-expand-icon`]:{height:O,display:"flex",alignItems:"center",paddingInlineEnd:w},[`${t}-arrow`]:Object.assign(Object.assign({},(0,p.resetIcon)()),{fontSize:E,transition:`transform ${$}`,svg:{transition:`transform ${$}`}}),[`${t}-header-text`]:{marginInlineEnd:"auto"}}),[`${t}-collapsible-header`]:{cursor:"default",[`${t}-header-text`]:{flex:"none",cursor:"pointer"},[`${t}-expand-icon`]:{cursor:"pointer"}},[`${t}-collapsible-icon`]:{cursor:"unset",[`${t}-expand-icon`]:{cursor:"pointer"}}},[`${t}-content`]:{color:m,backgroundColor:r,borderTop:T,[`& > ${t}-content-box`]:{padding:k},"&-hidden":{display:"none"}},"&-small":{[`> ${t}-item`]:{[`> ${t}-header`]:{padding:i,paddingInlineStart:S,[`> ${t}-expand-icon`]:{marginInlineStart:e.calc(C).sub(S).equal()}},[`> ${t}-content > ${t}-content-box`]:{padding:C}}},"&-large":{[`> ${t}-item`]:{fontSize:v,lineHeight:b,[`> ${t}-header`]:{padding:l,paddingInlineStart:n,[`> ${t}-expand-icon`]:{height:j,marginInlineStart:e.calc(x).sub(n).equal()}},[`> ${t}-content > ${t}-content-box`]:{padding:x}}},[`${t}-item:last-child`]:{borderBottom:0,[`> ${t}-content`]:{borderRadius:`0 0 ${(0,f.unit)(s)} ${(0,f.unit)(s)}`}},[`& ${t}-item-disabled > ${t}-header`]:{[` + &, + & > .arrow + `]:{color:h,cursor:"not-allowed"}},[`&${t}-icon-position-end`]:{[`& > ${t}-item`]:{[`> ${t}-header`]:{[`${t}-expand-icon`]:{order:1,paddingInlineEnd:0,paddingInlineStart:w}}}}})}})(t),(e=>{let{componentCls:t,headerBg:r,borderlessContentPadding:n,borderlessContentBg:o,colorBorder:a}=e;return{[`${t}-borderless`]:{backgroundColor:r,border:0,[`> ${t}-item`]:{borderBottom:`1px solid ${a}`},[` + > ${t}-item:last-child, + > ${t}-item:last-child ${t}-header + `]:{borderRadius:0},[`> ${t}-item:last-child`]:{borderBottom:0},[`> ${t}-item > ${t}-content`]:{backgroundColor:o,borderTop:0},[`> ${t}-item > ${t}-content > ${t}-content-box`]:{padding:n}}}})(t),(e=>{let{componentCls:t,paddingSM:r}=e;return{[`${t}-ghost`]:{backgroundColor:"transparent",border:0,[`> ${t}-item`]:{borderBottom:0,[`> ${t}-content`]:{backgroundColor:"transparent",border:0,[`> ${t}-content-box`]:{paddingBlock:r}}}}}})(t),(e=>{let{componentCls:t}=e,r=`> ${t}-item > ${t}-header ${t}-arrow`;return{[`${t}-rtl`]:{[r]:{transform:"rotate(180deg)"}}}})(t),(0,m.genCollapseMotion)(t)]},e=>({headerPadding:`${e.paddingSM}px ${e.padding}px`,headerBg:e.colorFillAlter,contentPadding:`${e.padding}px 16px`,contentBg:e.colorBgContainer,borderlessContentPadding:`${e.paddingXXS}px 16px ${e.padding}px`,borderlessContentBg:"transparent"})),y=Object.assign(t.forwardRef((e,d)=>{let{getPrefixCls:f,direction:p,expandIcon:m,className:g,style:h}=(0,c.useComponentConfig)("collapse"),{prefixCls:y,className:b,rootClassName:w,style:C,bordered:x=!0,ghost:S,size:$,expandIconPosition:E="start",children:k,destroyInactivePanel:O,destroyOnHidden:j,expandIcon:T}=e,_=(0,u.default)(e=>{var t;return null!=(t=null!=$?$:e)?t:"middle"}),P=f("collapse",y),I=f(),[F,N,R]=v(P),M=t.useMemo(()=>"left"===E?"start":"right"===E?"end":E,[E]),A=null!=T?T:m,B=t.useCallback((e={})=>{let o="function"==typeof A?A(e):t.createElement(r.default,{rotate:e.isActive?"rtl"===p?-90:90:void 0,"aria-label":e.isActive?"expanded":"collapsed"});return(0,s.cloneElement)(o,()=>{var e;return{className:(0,n.default)(null==(e=o.props)?void 0:e.className,`${P}-arrow`)}})},[A,P,p]),z=(0,n.default)(`${P}-icon-position-${M}`,{[`${P}-borderless`]:!x,[`${P}-rtl`]:"rtl"===p,[`${P}-ghost`]:!!S,[`${P}-${_}`]:"middle"!==_},g,b,w,N,R),L=t.useMemo(()=>Object.assign(Object.assign({},(0,l.default)(I)),{motionAppear:!1,leavedClassName:`${P}-content-hidden`}),[I,P]),H=t.useMemo(()=>k?(0,a.default)(k).map((e,t)=>{var r,n;let o=e.props;if(null==o?void 0:o.disabled){let a=null!=(r=e.key)?r:String(t),l=Object.assign(Object.assign({},(0,i.default)(e.props,["disabled"])),{key:a,collapsible:null!=(n=o.collapsible)?n:"disabled"});return(0,s.cloneElement)(e,l)}return e}):null,[k]);return F(t.createElement(o.default,Object.assign({ref:d,openMotion:L},(0,i.default)(e,["rootClassName"]),{expandIcon:B,prefixCls:P,className:z,style:Object.assign(Object.assign({},h),C),destroyInactivePanel:null!=j?j:O}),H))}),{Panel:d.default});e.s(["default",0,y],988122)},432231,327174,e=>{"use strict";e.i(296059);var t=e.i(915654),r=e.i(183293),n=e.i(617933),o=e.i(246422),a=e.i(838378),i=e.i(470977),l=e.i(571070);e.i(271645),e.i(509808),e.i(202599);var s=e.i(814690);e.i(343794),e.i(914949),e.i(988122),e.i(408850),e.i(104458),e.i(656449);var c=e.i(988317),u=e.i(745978);let d=e=>{let{paddingInline:t,onlyIconSize:r}=e;return(0,a.mergeToken)(e,{buttonPaddingHorizontal:t,buttonPaddingVertical:0,buttonIconOnlyFontSize:r})},f=e=>{var r,o,a,i,d,f;let p=null!=(r=e.contentFontSize)?r:e.fontSize,m=null!=(o=e.contentFontSizeSM)?o:e.fontSize,g=null!=(a=e.contentFontSizeLG)?a:e.fontSizeLG,h=null!=(i=e.contentLineHeight)?i:(0,c.getLineHeight)(p),v=null!=(d=e.contentLineHeightSM)?d:(0,c.getLineHeight)(m),y=null!=(f=e.contentLineHeightLG)?f:(0,c.getLineHeight)(g),b=((e,t)=>{let{r,g:n,b:o,a}=e.toRgb(),i=new s.Color(e.toRgbString()).onBackground(t).toHsv();return a<=.5?i.v>.5:.299*r+.587*n+.114*o>192})(new l.AggregationColor(e.colorBgSolid),"#fff")?"#000":"#fff";return Object.assign(Object.assign({},n.PresetColors.reduce((r,n)=>Object.assign(Object.assign({},r),{[`${n}ShadowColor`]:`0 ${(0,t.unit)(e.controlOutlineWidth)} 0 ${(0,u.default)(e[`${n}1`],e.colorBgContainer)}`}),{})),{fontWeight:400,iconGap:e.marginXS,defaultShadow:`0 ${e.controlOutlineWidth}px 0 ${e.controlTmpOutline}`,primaryShadow:`0 ${e.controlOutlineWidth}px 0 ${e.controlOutline}`,dangerShadow:`0 ${e.controlOutlineWidth}px 0 ${e.colorErrorOutline}`,primaryColor:e.colorTextLightSolid,dangerColor:e.colorTextLightSolid,borderColorDisabled:e.colorBorder,defaultGhostColor:e.colorBgContainer,ghostBg:"transparent",defaultGhostBorderColor:e.colorBgContainer,paddingInline:e.paddingContentHorizontal-e.lineWidth,paddingInlineLG:e.paddingContentHorizontal-e.lineWidth,paddingInlineSM:8-e.lineWidth,onlyIconSize:"inherit",onlyIconSizeSM:"inherit",onlyIconSizeLG:"inherit",groupBorderColor:e.colorPrimaryHover,linkHoverBg:"transparent",textTextColor:e.colorText,textTextHoverColor:e.colorText,textTextActiveColor:e.colorText,textHoverBg:e.colorFillTertiary,defaultColor:e.colorText,defaultBg:e.colorBgContainer,defaultBorderColor:e.colorBorder,defaultBorderColorDisabled:e.colorBorder,defaultHoverBg:e.colorBgContainer,defaultHoverColor:e.colorPrimaryHover,defaultHoverBorderColor:e.colorPrimaryHover,defaultActiveBg:e.colorBgContainer,defaultActiveColor:e.colorPrimaryActive,defaultActiveBorderColor:e.colorPrimaryActive,solidTextColor:b,contentFontSize:p,contentFontSizeSM:m,contentFontSizeLG:g,contentLineHeight:h,contentLineHeightSM:v,contentLineHeightLG:y,paddingBlock:Math.max((e.controlHeight-p*h)/2-e.lineWidth,0),paddingBlockSM:Math.max((e.controlHeightSM-m*v)/2-e.lineWidth,0),paddingBlockLG:Math.max((e.controlHeightLG-g*y)/2-e.lineWidth,0)})};e.s(["prepareComponentToken",0,f,"prepareToken",0,d],327174);let p=(e,t,r)=>({[`&:not(:disabled):not(${e}-disabled)`]:{"&:hover":t,"&:active":r}}),m=(e,t,r,n,o,a,i,l)=>({[`&${e}-background-ghost`]:Object.assign(Object.assign({color:r||void 0,background:t,borderColor:n||void 0,boxShadow:"none"},p(e,Object.assign({background:t},i),Object.assign({background:t},l))),{"&:disabled":{cursor:"not-allowed",color:o||void 0,borderColor:a||void 0}})}),g=(e,t,r,n)=>Object.assign(Object.assign({},(n&&["link","text"].includes(n)?e=>({[`&:disabled, &${e.componentCls}-disabled`]:{cursor:"not-allowed",color:e.colorTextDisabled}}):e=>({[`&:disabled, &${e.componentCls}-disabled`]:Object.assign({},{cursor:"not-allowed",borderColor:e.borderColorDisabled,color:e.colorTextDisabled,background:e.colorBgContainerDisabled,boxShadow:"none"})}))(e)),p(e.componentCls,t,r)),h=(e,t,r,n,o)=>({[`&${e.componentCls}-variant-solid`]:Object.assign({color:t,background:r},g(e,n,o))}),v=(e,t,r,n,o)=>({[`&${e.componentCls}-variant-outlined, &${e.componentCls}-variant-dashed`]:Object.assign({borderColor:t,background:r},g(e,n,o))}),y=e=>({[`&${e.componentCls}-variant-dashed`]:{borderStyle:"dashed"}}),b=(e,t,r,n)=>({[`&${e.componentCls}-variant-filled`]:Object.assign({boxShadow:"none",background:t},g(e,r,n))}),w=(e,t,r,n,o)=>({[`&${e.componentCls}-variant-${r}`]:Object.assign({color:t,boxShadow:"none"},g(e,n,o,r))}),C=(e,r="")=>{let{componentCls:n,controlHeight:o,fontSize:a,borderRadius:i,buttonPaddingHorizontal:l,iconCls:s,buttonPaddingVertical:c,buttonIconOnlyFontSize:u}=e;return[{[r]:{fontSize:a,height:o,padding:`${(0,t.unit)(c)} ${(0,t.unit)(l)}`,borderRadius:i,[`&${n}-icon-only`]:{width:o,[s]:{fontSize:u}}}},{[`${n}${n}-circle${r}`]:{minWidth:e.controlHeight,paddingInline:0,borderRadius:"50%"}},{[`${n}${n}-round${r}`]:{borderRadius:e.controlHeight,[`&:not(${n}-icon-only)`]:{paddingInline:e.buttonPaddingHorizontal}}}]},x=(0,o.genStyleHooks)("Button",e=>{let o=d(e);return[(e=>{let{componentCls:n,iconCls:o,fontWeight:a,opacityLoading:i,motionDurationSlow:l,motionEaseInOut:s,iconGap:c,calc:u}=e;return{[n]:{outline:"none",position:"relative",display:"inline-flex",gap:c,alignItems:"center",justifyContent:"center",fontWeight:a,whiteSpace:"nowrap",textAlign:"center",backgroundImage:"none",background:"transparent",border:`${(0,t.unit)(e.lineWidth)} ${e.lineType} transparent`,cursor:"pointer",transition:`all ${e.motionDurationMid} ${e.motionEaseInOut}`,userSelect:"none",touchAction:"manipulation",color:e.colorText,"&:disabled > *":{pointerEvents:"none"},[`${n}-icon > svg`]:(0,r.resetIcon)(),"> a":{color:"currentColor"},"&:not(:disabled)":(0,r.genFocusStyle)(e),[`&${n}-two-chinese-chars::first-letter`]:{letterSpacing:"0.34em"},[`&${n}-two-chinese-chars > *:not(${o})`]:{marginInlineEnd:"-0.34em",letterSpacing:"0.34em"},[`&${n}-icon-only`]:{paddingInline:0,[`&${n}-compact-item`]:{flex:"none"}},[`&${n}-loading`]:{opacity:i,cursor:"default"},[`${n}-loading-icon`]:{transition:["width","opacity","margin"].map(e=>`${e} ${l} ${s}`).join(",")},[`&:not(${n}-icon-end)`]:{[`${n}-loading-icon-motion`]:{"&-appear-start, &-enter-start":{marginInlineEnd:u(c).mul(-1).equal()},"&-appear-active, &-enter-active":{marginInlineEnd:0},"&-leave-start":{marginInlineEnd:0},"&-leave-active":{marginInlineEnd:u(c).mul(-1).equal()}}},"&-icon-end":{flexDirection:"row-reverse",[`${n}-loading-icon-motion`]:{"&-appear-start, &-enter-start":{marginInlineStart:u(c).mul(-1).equal()},"&-appear-active, &-enter-active":{marginInlineStart:0},"&-leave-start":{marginInlineStart:0},"&-leave-active":{marginInlineStart:u(c).mul(-1).equal()}}}}}})(o),C((0,a.mergeToken)(o,{fontSize:o.contentFontSize}),o.componentCls),C((0,a.mergeToken)(o,{controlHeight:o.controlHeightSM,fontSize:o.contentFontSizeSM,padding:o.paddingXS,buttonPaddingHorizontal:o.paddingInlineSM,buttonPaddingVertical:0,borderRadius:o.borderRadiusSM,buttonIconOnlyFontSize:o.onlyIconSizeSM}),`${o.componentCls}-sm`),C((0,a.mergeToken)(o,{controlHeight:o.controlHeightLG,fontSize:o.contentFontSizeLG,buttonPaddingHorizontal:o.paddingInlineLG,buttonPaddingVertical:0,borderRadius:o.borderRadiusLG,buttonIconOnlyFontSize:o.onlyIconSizeLG}),`${o.componentCls}-lg`),(e=>{let{componentCls:t}=e;return{[t]:{[`&${t}-block`]:{width:"100%"}}}})(o),(e=>{let{componentCls:t}=e;return Object.assign({[`${t}-color-default`]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({color:e.defaultColor,boxShadow:e.defaultShadow},h(e,e.solidTextColor,e.colorBgSolid,{color:e.solidTextColor,background:e.colorBgSolidHover},{color:e.solidTextColor,background:e.colorBgSolidActive})),y(e)),b(e,e.colorFillTertiary,{color:e.defaultColor,background:e.colorFillSecondary},{color:e.defaultColor,background:e.colorFill})),m(e.componentCls,e.ghostBg,e.defaultGhostColor,e.defaultGhostBorderColor,e.colorTextDisabled,e.colorBorder)),w(e,e.textTextColor,"link",{color:e.colorLinkHover,background:e.linkHoverBg},{color:e.colorLinkActive})),[`${t}-color-primary`]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({color:e.colorPrimary,boxShadow:e.primaryShadow},v(e,e.colorPrimary,e.colorBgContainer,{color:e.colorPrimaryTextHover,borderColor:e.colorPrimaryHover,background:e.colorBgContainer},{color:e.colorPrimaryTextActive,borderColor:e.colorPrimaryActive,background:e.colorBgContainer})),y(e)),b(e,e.colorPrimaryBg,{color:e.colorPrimary,background:e.colorPrimaryBgHover},{color:e.colorPrimary,background:e.colorPrimaryBorder})),w(e,e.colorPrimaryText,"text",{color:e.colorPrimaryTextHover,background:e.colorPrimaryBg},{color:e.colorPrimaryTextActive,background:e.colorPrimaryBorder})),w(e,e.colorPrimaryText,"link",{color:e.colorPrimaryTextHover,background:e.linkHoverBg},{color:e.colorPrimaryTextActive})),m(e.componentCls,e.ghostBg,e.colorPrimary,e.colorPrimary,e.colorTextDisabled,e.colorBorder,{color:e.colorPrimaryHover,borderColor:e.colorPrimaryHover},{color:e.colorPrimaryActive,borderColor:e.colorPrimaryActive})),[`${t}-color-dangerous`]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({color:e.colorError,boxShadow:e.dangerShadow},h(e,e.dangerColor,e.colorError,{background:e.colorErrorHover},{background:e.colorErrorActive})),v(e,e.colorError,e.colorBgContainer,{color:e.colorErrorHover,borderColor:e.colorErrorBorderHover},{color:e.colorErrorActive,borderColor:e.colorErrorActive})),y(e)),b(e,e.colorErrorBg,{color:e.colorError,background:e.colorErrorBgFilledHover},{color:e.colorError,background:e.colorErrorBgActive})),w(e,e.colorError,"text",{color:e.colorErrorHover,background:e.colorErrorBg},{color:e.colorErrorHover,background:e.colorErrorBgActive})),w(e,e.colorError,"link",{color:e.colorErrorHover},{color:e.colorErrorActive})),m(e.componentCls,e.ghostBg,e.colorError,e.colorError,e.colorTextDisabled,e.colorBorder,{color:e.colorErrorHover,borderColor:e.colorErrorHover},{color:e.colorErrorActive,borderColor:e.colorErrorActive})),[`${t}-color-link`]:Object.assign(Object.assign({},w(e,e.colorLink,"link",{color:e.colorLinkHover},{color:e.colorLinkActive})),m(e.componentCls,e.ghostBg,e.colorInfo,e.colorInfo,e.colorTextDisabled,e.colorBorder,{color:e.colorInfoHover,borderColor:e.colorInfoHover},{color:e.colorInfoActive,borderColor:e.colorInfoActive}))},(e=>{let{componentCls:t}=e;return n.PresetColors.reduce((r,n)=>{let o=e[`${n}6`],a=e[`${n}1`],i=e[`${n}5`],l=e[`${n}2`],s=e[`${n}3`],c=e[`${n}7`];return Object.assign(Object.assign({},r),{[`&${t}-color-${n}`]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({color:o,boxShadow:e[`${n}ShadowColor`]},h(e,e.colorTextLightSolid,o,{background:i},{background:c})),v(e,o,e.colorBgContainer,{color:i,borderColor:i,background:e.colorBgContainer},{color:c,borderColor:c,background:e.colorBgContainer})),y(e)),b(e,a,{color:o,background:l},{color:o,background:s})),w(e,o,"link",{color:i},{color:c})),w(e,o,"text",{color:i,background:a},{color:c,background:s}))})},{})})(e))})(o),Object.assign(Object.assign(Object.assign(Object.assign({},v(o,o.defaultBorderColor,o.defaultBg,{color:o.defaultHoverColor,borderColor:o.defaultHoverBorderColor,background:o.defaultHoverBg},{color:o.defaultActiveColor,borderColor:o.defaultActiveBorderColor,background:o.defaultActiveBg})),w(o,o.textTextColor,"text",{color:o.textTextHoverColor,background:o.textHoverBg},{color:o.textTextActiveColor,background:o.colorBgTextActive})),h(o,o.primaryColor,o.colorPrimary,{background:o.colorPrimaryHover,color:o.primaryColor},{background:o.colorPrimaryActive,color:o.primaryColor})),w(o,o.colorLink,"link",{color:o.colorLinkHover,background:o.linkHoverBg},{color:o.colorLinkActive})),(0,i.default)(o)]},f,{unitless:{fontWeight:!0,contentLineHeight:!0,contentLineHeightSM:!0,contentLineHeightLG:!0}});e.s(["default",0,x],432231)},920228,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(174428),o=e.i(529681),a=e.i(611935),i=e.i(121872),l=e.i(242064),s=e.i(937328),c=e.i(517455),u=e.i(249616),d=e.i(735996),f=e.i(62405),p=e.i(868004),m=e.i(869693),g=e.i(432231),h=e.i(372409),v=e.i(246422),y=e.i(327174);let b=(0,v.genSubStyleComponent)(["Button","compact"],e=>{var t,r;let n,o=(0,y.prepareToken)(e);return[(0,h.genCompactItemStyle)(o),{[n=`${o.componentCls}-compact-vertical`]:Object.assign(Object.assign({},(t=o.componentCls,{[`&-item:not(${n}-last-item)`]:{marginBottom:o.calc(o.lineWidth).mul(-1).equal()},[`&-item:not(${t}-status-success)`]:{zIndex:2},"&-item":{"&:hover,&:focus,&:active":{zIndex:3},"&[disabled]":{zIndex:0}}})),(r=o.componentCls,{[`&-item:not(${n}-first-item):not(${n}-last-item)`]:{borderRadius:0},[`&-item${n}-first-item:not(${n}-last-item)`]:{[`&, &${r}-sm, &${r}-lg`]:{borderEndEndRadius:0,borderEndStartRadius:0}},[`&-item${n}-last-item:not(${n}-first-item)`]:{[`&, &${r}-sm, &${r}-lg`]:{borderStartStartRadius:0,borderStartEndRadius:0}}}))},(e=>{let{componentCls:t,colorPrimaryHover:r,lineWidth:n,calc:o}=e,a=o(n).mul(-1).equal(),i=e=>{let o=`${t}-compact${e?"-vertical":""}-item${t}-primary:not([disabled])`;return{[`${o} + ${o}::before`]:{position:"absolute",top:e?a:0,insetInlineStart:e?0:a,backgroundColor:r,content:'""',width:e?"100%":n,height:e?n:"100%"}}};return Object.assign(Object.assign({},i()),i(!0))})(o)]},y.prepareComponentToken);var w=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 C={default:["default","outlined"],primary:["primary","solid"],dashed:["default","dashed"],link:["link","link"],text:["default","text"]},x=t.default.forwardRef((e,h)=>{var v,y;let x,{loading:S=!1,prefixCls:$,color:E,variant:k,type:O,danger:j=!1,shape:T,size:_,styles:P,disabled:I,className:F,rootClassName:N,children:R,icon:M,iconPosition:A="start",ghost:B=!1,block:z=!1,htmlType:L="button",classNames:H,style:D={},autoInsertSpace:V,autoFocus:W}=e,U=w(e,["loading","prefixCls","color","variant","type","danger","shape","size","styles","disabled","className","rootClassName","children","icon","iconPosition","ghost","block","htmlType","classNames","style","autoInsertSpace","autoFocus"]),G=O||"default",{button:q}=t.default.useContext(l.ConfigContext),K=T||(null==q?void 0:q.shape)||"default",[X,J]=(0,t.useMemo)(()=>{if(E&&k)return[E,k];if(O||j){let e=C[G]||[];return j?["danger",e[1]]:e}return(null==q?void 0:q.color)&&(null==q?void 0:q.variant)?[q.color,q.variant]:["default","outlined"]},[E,k,O,j,null==q?void 0:q.color,null==q?void 0:q.variant,G]),Y="danger"===X?"dangerous":X,{getPrefixCls:Q,direction:Z,autoInsertSpace:ee,className:et,style:er,classNames:en,styles:eo}=(0,l.useComponentConfig)("button"),ea=null==(v=null!=V?V:ee)||v,ei=Q("btn",$),[el,es,ec]=(0,g.default)(ei),eu=(0,t.useContext)(s.default),ed=null!=I?I:eu,ef=(0,t.useContext)(d.GroupSizeContext),ep=(0,t.useMemo)(()=>(function(e){if("object"==typeof e&&e){let t=null==e?void 0:e.delay;return{loading:(t=Number.isNaN(t)||"number"!=typeof t?0:t)<=0,delay:t}}return{loading:!!e,delay:0}})(S),[S]),[em,eg]=(0,t.useState)(ep.loading),[eh,ev]=(0,t.useState)(!1),ey=(0,t.useRef)(null),eb=(0,a.useComposeRef)(h,ey),ew=1===t.Children.count(R)&&!M&&!(0,f.isUnBorderedButtonVariant)(J),eC=(0,t.useRef)(!0);t.default.useEffect(()=>(eC.current=!1,()=>{eC.current=!0}),[]),(0,n.default)(()=>{let e=null;return ep.delay>0?e=setTimeout(()=>{e=null,eg(!0)},ep.delay):eg(ep.loading),function(){e&&(clearTimeout(e),e=null)}},[ep.delay,ep.loading]),(0,t.useEffect)(()=>{if(!ey.current||!ea)return;let e=ey.current.textContent||"";ew&&(0,f.isTwoCNChar)(e)?eh||ev(!0):eh&&ev(!1)}),(0,t.useEffect)(()=>{W&&ey.current&&ey.current.focus()},[]);let ex=t.default.useCallback(t=>{var r;em||ed?t.preventDefault():null==(r=e.onClick)||r.call(e,("href"in e,t))},[e.onClick,em,ed]),{compactSize:eS,compactItemClassnames:e$}=(0,u.useCompactItemContext)(ei,Z),eE=(0,c.default)(e=>{var t,r;return null!=(r=null!=(t=null!=_?_:eS)?t:ef)?r:e}),ek=eE&&null!=(y=({large:"lg",small:"sm",middle:void 0})[eE])?y:"",eO=em?"loading":M,ej=(0,o.default)(U,["navigate"]),eT=(0,r.default)(ei,es,ec,{[`${ei}-${K}`]:"default"!==K&&K,[`${ei}-${G}`]:G,[`${ei}-dangerous`]:j,[`${ei}-color-${Y}`]:Y,[`${ei}-variant-${J}`]:J,[`${ei}-${ek}`]:ek,[`${ei}-icon-only`]:!R&&0!==R&&!!eO,[`${ei}-background-ghost`]:B&&!(0,f.isUnBorderedButtonVariant)(J),[`${ei}-loading`]:em,[`${ei}-two-chinese-chars`]:eh&&ea&&!em,[`${ei}-block`]:z,[`${ei}-rtl`]:"rtl"===Z,[`${ei}-icon-end`]:"end"===A},e$,F,N,et),e_=Object.assign(Object.assign({},er),D),eP=(0,r.default)(null==H?void 0:H.icon,en.icon),eI=Object.assign(Object.assign({},(null==P?void 0:P.icon)||{}),eo.icon||{}),eF=e=>t.default.createElement(m.default,{prefixCls:ei,className:eP,style:eI},e);x=M&&!em?eF(M):S&&"object"==typeof S&&S.icon?eF(S.icon):t.default.createElement(p.default,{existIcon:!!M,prefixCls:ei,loading:em,mount:eC.current});let eN=R||0===R?(0,f.spaceChildren)(R,ew&&ea):null;if(void 0!==ej.href)return el(t.default.createElement("a",Object.assign({},ej,{className:(0,r.default)(eT,{[`${ei}-disabled`]:ed}),href:ed?void 0:ej.href,style:e_,onClick:ex,ref:eb,tabIndex:ed?-1:0,"aria-disabled":ed}),x,eN));let eR=t.default.createElement("button",Object.assign({},U,{type:L,className:eT,style:e_,onClick:ex,disabled:ed,ref:eb}),x,eN,e$&&t.default.createElement(b,{prefixCls:ei}));return(0,f.isUnBorderedButtonVariant)(J)||(eR=t.default.createElement(i.default,{component:"Button",disabled:em},eR)),el(eR)});x.Group=d.default,x.__ANT_BUTTON=!0,e.s(["default",0,x],920228)},995387,e=>{"use strict";var t=e.i(271645),r=e.i(38953),n=e.i(343794),o=e.i(611935),a=e.i(763731),i=e.i(920228),l=e.i(242064),s=e.i(517455),c=e.i(249616),u=e.i(90635),d=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 f=t.forwardRef((e,f)=>{let p,{prefixCls:m,inputPrefixCls:g,className:h,size:v,suffix:y,enterButton:b=!1,addonAfter:w,loading:C,disabled:x,onSearch:S,onChange:$,onCompositionStart:E,onCompositionEnd:k,variant:O,onPressEnter:j}=e,T=d(e,["prefixCls","inputPrefixCls","className","size","suffix","enterButton","addonAfter","loading","disabled","onSearch","onChange","onCompositionStart","onCompositionEnd","variant","onPressEnter"]),{getPrefixCls:_,direction:P}=t.useContext(l.ConfigContext),I=t.useRef(!1),F=_("input-search",m),N=_("input",g),{compactSize:R}=(0,c.useCompactItemContext)(F,P),M=(0,s.default)(e=>{var t;return null!=(t=null!=v?v:R)?t:e}),A=t.useRef(null),B=e=>{var t;document.activeElement===(null==(t=A.current)?void 0:t.input)&&e.preventDefault()},z=e=>{var t,r;S&&S(null==(r=null==(t=A.current)?void 0:t.input)?void 0:r.value,e,{source:"input"})},L="boolean"==typeof b?t.createElement(r.default,null):null,H=`${F}-button`,D=b||{},V=D.type&&!0===D.type.__ANT_BUTTON;p=V||"button"===D.type?(0,a.cloneElement)(D,Object.assign({onMouseDown:B,onClick:e=>{var t,r;null==(r=null==(t=null==D?void 0:D.props)?void 0:t.onClick)||r.call(t,e),z(e)},key:"enterButton"},V?{className:H,size:M}:{})):t.createElement(i.default,{className:H,color:b?"primary":"default",size:M,disabled:x,key:"enterButton",onMouseDown:B,onClick:z,loading:C,icon:L,variant:"borderless"===O||"filled"===O||"underlined"===O?"text":b?"solid":void 0},b),w&&(p=[p,(0,a.cloneElement)(w,{key:"addonAfter"})]);let W=(0,n.default)(F,{[`${F}-rtl`]:"rtl"===P,[`${F}-${M}`]:!!M,[`${F}-with-button`]:!!b},h),U=Object.assign(Object.assign({},T),{className:W,prefixCls:N,type:"search",size:M,variant:O,onPressEnter:e=>{I.current||C||(null==j||j(e),z(e))},onCompositionStart:e=>{I.current=!0,null==E||E(e)},onCompositionEnd:e=>{I.current=!1,null==k||k(e)},addonAfter:p,suffix:y,onChange:e=>{(null==e?void 0:e.target)&&"click"===e.type&&S&&S(e.target.value,e,{source:"clear"}),null==$||$(e)},disabled:x,_skipAddonWarning:!0});return t.createElement(u.default,Object.assign({ref:(0,o.composeRef)(A,f)},U))});e.s(["default",0,f])},302384,e=>{"use strict";var t=e.i(367397);e.s(["BaseInput",()=>t.default])},598030,e=>{"use strict";var t,r=e.i(931067),n=e.i(211577),o=e.i(209428),a=e.i(8211),i=e.i(392221),l=e.i(703923),s=e.i(343794);e.i(175636);var c=e.i(302384),u=e.i(874460),d=e.i(131299),f=e.i(914949),p=e.i(271645);e.i(247167);var m=e.i(410160),g=e.i(430073),h=e.i(174428),v=e.i(963188),y=["letter-spacing","line-height","padding-top","padding-bottom","font-family","font-weight","font-size","font-variant","text-rendering","text-transform","width","text-indent","padding-left","padding-right","border-width","box-sizing","word-break","white-space"],b={},w=["prefixCls","defaultValue","value","autoSize","onResize","className","style","disabled","onChange","onInternalAutoSize"],C=p.forwardRef(function(e,a){var c=e.prefixCls,u=e.defaultValue,d=e.value,C=e.autoSize,x=e.onResize,S=e.className,$=e.style,E=e.disabled,k=e.onChange,O=(e.onInternalAutoSize,(0,l.default)(e,w)),j=(0,f.default)(u,{value:d,postState:function(e){return null!=e?e:""}}),T=(0,i.default)(j,2),_=T[0],P=T[1],I=p.useRef();p.useImperativeHandle(a,function(){return{textArea:I.current}});var F=p.useMemo(function(){return C&&"object"===(0,m.default)(C)?[C.minRows,C.maxRows]:[]},[C]),N=(0,i.default)(F,2),R=N[0],M=N[1],A=!!C,B=p.useState(2),z=(0,i.default)(B,2),L=z[0],H=z[1],D=p.useState(),V=(0,i.default)(D,2),W=V[0],U=V[1],G=function(){H(0)};(0,h.default)(function(){A&&G()},[d,R,M,A]),(0,h.default)(function(){if(0===L)H(1);else if(1===L){var e=function(e){var r,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;t||((t=document.createElement("textarea")).setAttribute("tab-index","-1"),t.setAttribute("aria-hidden","true"),t.setAttribute("name","hiddenTextarea"),document.body.appendChild(t)),e.getAttribute("wrap")?t.setAttribute("wrap",e.getAttribute("wrap")):t.removeAttribute("wrap");var i=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=e.getAttribute("id")||e.getAttribute("data-reactid")||e.getAttribute("name");if(t&&b[r])return b[r];var n=window.getComputedStyle(e),o=n.getPropertyValue("box-sizing")||n.getPropertyValue("-moz-box-sizing")||n.getPropertyValue("-webkit-box-sizing"),a=parseFloat(n.getPropertyValue("padding-bottom"))+parseFloat(n.getPropertyValue("padding-top")),i=parseFloat(n.getPropertyValue("border-bottom-width"))+parseFloat(n.getPropertyValue("border-top-width")),l={sizingStyle:y.map(function(e){return"".concat(e,":").concat(n.getPropertyValue(e))}).join(";"),paddingSize:a,borderSize:i,boxSizing:o};return t&&r&&(b[r]=l),l}(e,n),l=i.paddingSize,s=i.borderSize,c=i.boxSizing,u=i.sizingStyle;t.setAttribute("style","".concat(u,";").concat("\n min-height:0 !important;\n max-height:none !important;\n height:0 !important;\n visibility:hidden !important;\n overflow:hidden !important;\n position:absolute !important;\n z-index:-1000 !important;\n top:0 !important;\n right:0 !important;\n pointer-events: none !important;\n")),t.value=e.value||e.placeholder||"";var d=void 0,f=void 0,p=t.scrollHeight;if("border-box"===c?p+=s:"content-box"===c&&(p-=l),null!==o||null!==a){t.value=" ";var m=t.scrollHeight-l;null!==o&&(d=m*o,"border-box"===c&&(d=d+l+s),p=Math.max(d,p)),null!==a&&(f=m*a,"border-box"===c&&(f=f+l+s),r=p>f?"":"hidden",p=Math.min(f,p))}var g={height:p,overflowY:r,resize:"none"};return d&&(g.minHeight=d),f&&(g.maxHeight=f),g}(I.current,!1,R,M);H(2),U(e)}},[L]);var q=p.useRef(),K=function(){v.default.cancel(q.current)};p.useEffect(function(){return K},[]);var X=(0,o.default)((0,o.default)({},$),A?W:null);return(0===L||1===L)&&(X.overflowY="hidden",X.overflowX="hidden"),p.createElement(g.default,{onResize:function(e){2===L&&(null==x||x(e),C&&(K(),q.current=(0,v.default)(function(){G()})))},disabled:!(C||x)},p.createElement("textarea",(0,r.default)({},O,{ref:I,style:X,className:(0,s.default)(c,S,(0,n.default)({},"".concat(c,"-disabled"),E)),disabled:E,value:_,onChange:function(e){P(e.target.value),null==k||k(e)}})))}),x=["defaultValue","value","onFocus","onBlur","onChange","allowClear","maxLength","onCompositionStart","onCompositionEnd","suffix","prefixCls","showCount","count","className","style","disabled","hidden","classNames","styles","onResize","onClear","onPressEnter","readOnly","autoSize","onKeyDown"],S=p.default.forwardRef(function(e,t){var m,g,h=e.defaultValue,v=e.value,y=e.onFocus,b=e.onBlur,w=e.onChange,S=e.allowClear,$=e.maxLength,E=e.onCompositionStart,k=e.onCompositionEnd,O=e.suffix,j=e.prefixCls,T=void 0===j?"rc-textarea":j,_=e.showCount,P=e.count,I=e.className,F=e.style,N=e.disabled,R=e.hidden,M=e.classNames,A=e.styles,B=e.onResize,z=e.onClear,L=e.onPressEnter,H=e.readOnly,D=e.autoSize,V=e.onKeyDown,W=(0,l.default)(e,x),U=(0,f.default)(h,{value:v,defaultValue:h}),G=(0,i.default)(U,2),q=G[0],K=G[1],X=null==q?"":String(q),J=p.default.useState(!1),Y=(0,i.default)(J,2),Q=Y[0],Z=Y[1],ee=p.default.useRef(!1),et=p.default.useState(null),er=(0,i.default)(et,2),en=er[0],eo=er[1],ea=(0,p.useRef)(null),ei=(0,p.useRef)(null),el=function(){var e;return null==(e=ei.current)?void 0:e.textArea},es=function(){el().focus()};(0,p.useImperativeHandle)(t,function(){var e;return{resizableTextArea:ei.current,focus:es,blur:function(){el().blur()},nativeElement:(null==(e=ea.current)?void 0:e.nativeElement)||el()}}),(0,p.useEffect)(function(){Z(function(e){return!N&&e})},[N]);var ec=p.default.useState(null),eu=(0,i.default)(ec,2),ed=eu[0],ef=eu[1];p.default.useEffect(function(){if(ed){var e;(e=el()).setSelectionRange.apply(e,(0,a.default)(ed))}},[ed]);var ep=(0,u.default)(P,_),em=null!=(m=ep.max)?m:$,eg=Number(em)>0,eh=ep.strategy(X),ev=!!em&&eh>em,ey=function(e,t){var r=t;!ee.current&&ep.exceedFormatter&&ep.max&&ep.strategy(t)>ep.max&&(r=ep.exceedFormatter(t,{max:ep.max}),t!==r&&ef([el().selectionStart||0,el().selectionEnd||0])),K(r),(0,d.resolveOnChange)(e.currentTarget,e,w,r)},eb=O;ep.show&&(g=ep.showFormatter?ep.showFormatter({value:X,count:eh,maxLength:em}):"".concat(eh).concat(eg?" / ".concat(em):""),eb=p.default.createElement(p.default.Fragment,null,eb,p.default.createElement("span",{className:(0,s.default)("".concat(T,"-data-count"),null==M?void 0:M.count),style:null==A?void 0:A.count},g)));var ew=!D&&!_&&!S;return p.default.createElement(c.BaseInput,{ref:ea,value:X,allowClear:S,handleReset:function(e){K(""),es(),(0,d.resolveOnChange)(el(),e,w)},suffix:eb,prefixCls:T,classNames:(0,o.default)((0,o.default)({},M),{},{affixWrapper:(0,s.default)(null==M?void 0:M.affixWrapper,(0,n.default)((0,n.default)({},"".concat(T,"-show-count"),_),"".concat(T,"-textarea-allow-clear"),S))}),disabled:N,focused:Q,className:(0,s.default)(I,ev&&"".concat(T,"-out-of-range")),style:(0,o.default)((0,o.default)({},F),en&&!ew?{height:"auto"}:{}),dataAttrs:{affixWrapper:{"data-count":"string"==typeof g?g:void 0}},hidden:R,readOnly:H,onClear:z},p.default.createElement(C,(0,r.default)({},W,{autoSize:D,maxLength:$,onKeyDown:function(e){"Enter"===e.key&&L&&L(e),null==V||V(e)},onChange:function(e){ey(e,e.target.value)},onFocus:function(e){Z(!0),null==y||y(e)},onBlur:function(e){Z(!1),null==b||b(e)},onCompositionStart:function(e){ee.current=!0,null==E||E(e)},onCompositionEnd:function(e){ee.current=!1,ey(e,e.currentTarget.value),null==k||k(e)},className:(0,s.default)(null==M?void 0:M.textarea),style:(0,o.default)((0,o.default)({},null==A?void 0:A.textarea),{},{resize:null==F?void 0:F.resize}),disabled:N,prefixCls:T,onResize:function(e){var t;null==B||B(e),null!=(t=el())&&t.style.height&&eo(!0)},ref:ei,readOnly:H})))});e.s(["default",0,S],598030)},635432,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(598030),o=e.i(330683),a=e.i(52956),i=e.i(242064),l=e.i(937328),s=e.i(321883),c=e.i(517455),u=e.i(62139),d=e.i(792812),f=e.i(249616),p=e.i(131299),m=e.i(349942),g=e.i(246422),h=e.i(838378),v=e.i(517458);let y=(0,g.genStyleHooks)(["Input","TextArea"],e=>(e=>{let{componentCls:t,paddingLG:r}=e,n=`${t}-textarea`;return{[`textarea${t}`]:{maxWidth:"100%",height:"auto",minHeight:e.controlHeight,lineHeight:e.lineHeight,verticalAlign:"bottom",transition:`all ${e.motionDurationSlow}`,resize:"vertical",[`&${t}-mouse-active`]:{transition:`all ${e.motionDurationSlow}, height 0s, width 0s`}},[`${t}-textarea-affix-wrapper-resize-dirty`]:{width:"auto"},[n]:{position:"relative","&-show-count":{[`${t}-data-count`]:{position:"absolute",bottom:e.calc(e.fontSize).mul(e.lineHeight).mul(-1).equal(),insetInlineEnd:0,color:e.colorTextDescription,whiteSpace:"nowrap",pointerEvents:"none"}},[` + &-allow-clear > ${t}, + &-affix-wrapper${n}-has-feedback ${t} + `]:{paddingInlineEnd:r},[`&-affix-wrapper${t}-affix-wrapper`]:{padding:0,[`> textarea${t}`]:{fontSize:"inherit",border:"none",outline:"none",background:"transparent",minHeight:e.calc(e.controlHeight).sub(e.calc(e.lineWidth).mul(2)).equal(),"&:focus":{boxShadow:"none !important"}},[`${t}-suffix`]:{margin:0,"> *:not(:last-child)":{marginInline:0},[`${t}-clear-icon`]:{position:"absolute",insetInlineEnd:e.paddingInline,insetBlockStart:e.paddingXS},[`${n}-suffix`]:{position:"absolute",top:0,insetInlineEnd:e.paddingInline,bottom:0,zIndex:1,display:"inline-flex",alignItems:"center",margin:"auto",pointerEvents:"none"}}},[`&-affix-wrapper${t}-affix-wrapper-rtl`]:{[`${t}-suffix`]:{[`${t}-data-count`]:{direction:"ltr",insetInlineStart:0}}},[`&-affix-wrapper${t}-affix-wrapper-sm`]:{[`${t}-suffix`]:{[`${t}-clear-icon`]:{insetInlineEnd:e.paddingInlineSM}}}}}})((0,h.mergeToken)(e,(0,v.initInputToken)(e))),v.initComponentToken,{resetFont:!1});var b=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 w=(0,t.forwardRef)((e,g)=>{var h;let{prefixCls:v,bordered:w=!0,size:C,disabled:x,status:S,allowClear:$,classNames:E,rootClassName:k,className:O,style:j,styles:T,variant:_,showCount:P,onMouseDown:I,onResize:F}=e,N=b(e,["prefixCls","bordered","size","disabled","status","allowClear","classNames","rootClassName","className","style","styles","variant","showCount","onMouseDown","onResize"]),{getPrefixCls:R,direction:M,allowClear:A,autoComplete:B,className:z,style:L,classNames:H,styles:D}=(0,i.useComponentConfig)("textArea"),V=t.useContext(l.default),{status:W,hasFeedback:U,feedbackIcon:G}=t.useContext(u.FormItemInputContext),q=(0,a.getMergedStatus)(W,S),K=t.useRef(null);t.useImperativeHandle(g,()=>{var e;return{resizableTextArea:null==(e=K.current)?void 0:e.resizableTextArea,focus:e=>{var t,r;(0,p.triggerFocus)(null==(r=null==(t=K.current)?void 0:t.resizableTextArea)?void 0:r.textArea,e)},blur:()=>{var e;return null==(e=K.current)?void 0:e.blur()}}});let X=R("input",v),J=(0,s.default)(X),[Y,Q,Z]=(0,m.useSharedStyle)(X,k),[ee]=y(X,J),{compactSize:et,compactItemClassnames:er}=(0,f.useCompactItemContext)(X,M),en=(0,c.default)(e=>{var t;return null!=(t=null!=C?C:et)?t:e}),[eo,ea]=(0,d.default)("textArea",_,w),ei=(0,o.default)(null!=$?$:A),[el,es]=t.useState(!1),[ec,eu]=t.useState(!1);return Y(ee(t.createElement(n.default,Object.assign({autoComplete:B},N,{style:Object.assign(Object.assign({},L),j),styles:Object.assign(Object.assign({},D),T),disabled:null!=x?x:V,allowClear:ei,className:(0,r.default)(Z,J,O,k,er,z,ec&&`${X}-textarea-affix-wrapper-resize-dirty`),classNames:Object.assign(Object.assign(Object.assign({},E),H),{textarea:(0,r.default)({[`${X}-sm`]:"small"===en,[`${X}-lg`]:"large"===en},Q,null==E?void 0:E.textarea,H.textarea,el&&`${X}-mouse-active`),variant:(0,r.default)({[`${X}-${eo}`]:ea},(0,a.getStatusClassNames)(X,q)),affixWrapper:(0,r.default)(`${X}-textarea-affix-wrapper`,{[`${X}-affix-wrapper-rtl`]:"rtl"===M,[`${X}-affix-wrapper-sm`]:"small"===en,[`${X}-affix-wrapper-lg`]:"large"===en,[`${X}-textarea-show-count`]:P||(null==(h=e.count)?void 0:h.show)},Q)}),prefixCls:X,suffix:U&&t.createElement("span",{className:`${X}-textarea-suffix`},G),showCount:P,ref:K,onResize:e=>{var t,r;if(null==F||F(e),el&&"function"==typeof getComputedStyle){let e=null==(r=null==(t=K.current)?void 0:t.nativeElement)?void 0:r.querySelector("textarea");e&&"both"===getComputedStyle(e).resize&&eu(!0)}},onMouseDown:e=>{es(!0),null==I||I(e);let t=()=>{es(!1),document.removeEventListener("mouseup",t)};document.addEventListener("mouseup",t)}}))))});e.s(["default",0,w],635432)},311451,e=>{"use strict";var t=e.i(831357),r=e.i(90635),n=e.i(932399),o=e.i(236798),a=e.i(995387),i=e.i(635432);let l=r.default;l.Group=t.default,l.Search=a.default,l.TextArea=i.default,l.Password=o.default,l.OTP=n.default,e.s(["Input",0,l],311451)},247153,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"}}]},name:"down",theme:"outlined"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],247153)},536591,567075,407417,35862,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"}}]},name:"up",theme:"outlined"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],536591);var i=e.i(278409),l=e.i(233848),s=e.i(211577);function c(){return"function"==typeof BigInt}function u(e){return!e&&0!==e&&!Number.isNaN(e)||!String(e).trim()}function d(e){var t=e.trim(),r=t.startsWith("-");r&&(t=t.slice(1)),(t=t.replace(/(\.\d*[^0])0*$/,"$1").replace(/\.0*$/,"").replace(/^0+/,"")).startsWith(".")&&(t="0".concat(t));var n=t||"0",o=n.split("."),a=o[0]||"0",i=o[1]||"0";"0"===a&&"0"===i&&(r=!1);var l=r?"-":"";return{negative:r,negativeStr:l,trimStr:n,integerStr:a,decimalStr:i,fullStr:"".concat(l).concat(n)}}function f(e){var t=String(e);return!Number.isNaN(Number(t))&&t.includes("e")}function p(e){var t=String(e);if(f(e)){var r=Number(t.slice(t.indexOf("e-")+2)),n=t.match(/\.(\d+)/);return null!=n&&n[1]&&(r+=n[1].length),r}return t.includes(".")&&g(t)?t.length-t.indexOf(".")-1:0}function m(e){var t=String(e);if(f(e)){if(e>Number.MAX_SAFE_INTEGER)return String(c()?BigInt(e).toString():Number.MAX_SAFE_INTEGER);if(ep,"isE",()=>f,"isEmpty",()=>u,"num2str",()=>m,"trimNumber",()=>d,"validateNumber",()=>g],567075);var h=function(){function e(t){if((0,i.default)(this,e),(0,s.default)(this,"origin",""),(0,s.default)(this,"negative",void 0),(0,s.default)(this,"integer",void 0),(0,s.default)(this,"decimal",void 0),(0,s.default)(this,"decimalLen",void 0),(0,s.default)(this,"empty",void 0),(0,s.default)(this,"nan",void 0),u(t)){this.empty=!0;return}if(this.origin=String(t),"-"===t||Number.isNaN(t)){this.nan=!0;return}var r=t;if(f(r)&&(r=Number(r)),g(r="string"==typeof r?r:m(r))){var n=d(r);this.negative=n.negative;var o=n.trimStr.split(".");this.integer=BigInt(o[0]);var a=o[1]||"0";this.decimal=BigInt(a),this.decimalLen=a.length}else this.nan=!0}return(0,l.default)(e,[{key:"getMark",value:function(){return this.negative?"-":""}},{key:"getIntegerStr",value:function(){return this.integer.toString()}},{key:"getDecimalStr",value:function(){return this.decimal.toString().padStart(this.decimalLen,"0")}},{key:"alignDecimal",value:function(e){return BigInt("".concat(this.getMark()).concat(this.getIntegerStr()).concat(this.getDecimalStr().padEnd(e,"0")))}},{key:"negate",value:function(){var t=new e(this.toString());return t.negative=!t.negative,t}},{key:"cal",value:function(t,r,n){var o=Math.max(this.getDecimalStr().length,t.getDecimalStr().length),a=r(this.alignDecimal(o),t.alignDecimal(o)).toString(),i=n(o),l=d(a),s=l.negativeStr,c=l.trimStr,u="".concat(s).concat(c.padStart(i+1,"0"));return new e("".concat(u.slice(0,-i),".").concat(u.slice(-i)))}},{key:"add",value:function(t){if(this.isInvalidate())return new e(t);var r=new e(t);return r.isInvalidate()?this:this.cal(r,function(e,t){return e+t},function(e){return e})}},{key:"multi",value:function(t){var r=new e(t);return this.isInvalidate()||r.isInvalidate()?new e(NaN):this.cal(r,function(e,t){return e*t},function(e){return 2*e})}},{key:"isEmpty",value:function(){return this.empty}},{key:"isNaN",value:function(){return this.nan}},{key:"isInvalidate",value:function(){return this.isEmpty()||this.isNaN()}},{key:"equals",value:function(e){return this.toString()===(null==e?void 0:e.toString())}},{key:"lessEquals",value:function(e){return 0>=this.add(e.negate().toString()).toNumber()}},{key:"toNumber",value:function(){return this.isNaN()?NaN:Number(this.toString())}},{key:"toString",value:function(){var e=!(arguments.length>0)||void 0===arguments[0]||arguments[0];return e?this.isInvalidate()?"":d("".concat(this.getMark()).concat(this.getIntegerStr(),".").concat(this.getDecimalStr())).fullStr:this.origin}}]),e}(),v=function(){function e(t){if((0,i.default)(this,e),(0,s.default)(this,"origin",""),(0,s.default)(this,"number",void 0),(0,s.default)(this,"empty",void 0),u(t)){this.empty=!0;return}this.origin=String(t),this.number=Number(t)}return(0,l.default)(e,[{key:"negate",value:function(){return new e(-this.toNumber())}},{key:"add",value:function(t){if(this.isInvalidate())return new e(t);var r=Number(t);if(Number.isNaN(r))return this;var n=this.number+r;if(n>Number.MAX_SAFE_INTEGER)return new e(Number.MAX_SAFE_INTEGER);if(nNumber.MAX_SAFE_INTEGER)return new e(Number.MAX_SAFE_INTEGER);if(n=this.add(e.negate().toString()).toNumber()}},{key:"toNumber",value:function(){return this.number}},{key:"toString",value:function(){var e=!(arguments.length>0)||void 0===arguments[0]||arguments[0];return e?this.isInvalidate()?"":m(this.number):this.origin}}]),e}();function y(e){return c()?new h(e):new v(e)}function b(e,t,r){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(""===e)return"";var o=d(e),a=o.negativeStr,i=o.integerStr,l=o.decimalStr,s="".concat(t).concat(l),c="".concat(a).concat(i);if(r>=0){var u=Number(l[r]);return u>=5&&!n?b(y(e).add("".concat(a,"0.").concat("0".repeat(r)).concat(10-u)).toString(),t,r,n):0===r?c:"".concat(c).concat(t).concat(l.padEnd(r,"0").slice(0,r))}return".0"===s?c:"".concat(c).concat(s)}e.s(["default",()=>y,"toFixed",()=>b],522181),e.s(["default",0,y],407417),e.i(522181),e.s(["toFixed",()=>b],35862)},28651,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(247153),n=e.i(536591),o=e.i(343794),a=e.i(931067),i=e.i(211577),l=e.i(410160),s=e.i(392221),c=e.i(703923),u=e.i(407417),d=e.i(567075),f=e.i(35862);e.i(175636);var p=e.i(302384),m=e.i(174428),g=e.i(611935),h=e.i(883110),v=e.i(614761);let y=function(){var e=(0,t.useState)(!1),r=(0,s.default)(e,2),n=r[0],o=r[1];return(0,m.default)(function(){o((0,v.default)())},[]),n};var b=e.i(963188);function w(e){var r=e.prefixCls,n=e.upNode,l=e.downNode,s=e.upDisabled,c=e.downDisabled,u=e.onStep,d=t.useRef(),f=t.useRef([]),p=t.useRef();p.current=u;var m=function(){clearTimeout(d.current)},g=function(e,t){e.preventDefault(),m(),p.current(t),d.current=setTimeout(function e(){p.current(t),d.current=setTimeout(e,200)},600)};if(t.useEffect(function(){return function(){m(),f.current.forEach(function(e){return b.default.cancel(e)})}},[]),y())return null;var h="".concat(r,"-handler"),v=(0,o.default)(h,"".concat(h,"-up"),(0,i.default)({},"".concat(h,"-up-disabled"),s)),w=(0,o.default)(h,"".concat(h,"-down"),(0,i.default)({},"".concat(h,"-down-disabled"),c)),C=function(){return f.current.push((0,b.default)(m))},x={unselectable:"on",role:"button",onMouseUp:C,onMouseLeave:C};return t.createElement("div",{className:"".concat(h,"-wrap")},t.createElement("span",(0,a.default)({},x,{onMouseDown:function(e){g(e,!0)},"aria-label":"Increase Value","aria-disabled":s,className:v}),n||t.createElement("span",{unselectable:"on",className:"".concat(r,"-handler-up-inner")})),t.createElement("span",(0,a.default)({},x,{onMouseDown:function(e){g(e,!1)},"aria-label":"Decrease Value","aria-disabled":c,className:w}),l||t.createElement("span",{unselectable:"on",className:"".concat(r,"-handler-down-inner")})))}function C(e){var t="number"==typeof e?(0,d.num2str)(e):(0,d.trimNumber)(e).fullStr;return t.includes(".")?(0,d.trimNumber)(t.replace(/(\d)\.(\d)/g,"$1$2.")).fullStr:e+"0"}var x=e.i(131299);let S=function(){var e=(0,t.useRef)(0),r=function(){b.default.cancel(e.current)};return(0,t.useEffect)(function(){return r},[]),function(t){r(),e.current=(0,b.default)(function(){t()})}};var $=["prefixCls","className","style","min","max","step","defaultValue","value","disabled","readOnly","upHandler","downHandler","keyboard","changeOnWheel","controls","classNames","stringMode","parser","formatter","precision","decimalSeparator","onChange","onInput","onPressEnter","onStep","changeOnBlur","domRef"],E=["disabled","style","prefixCls","value","prefix","suffix","addonBefore","addonAfter","className","classNames"],k=function(e,t){return e||t.isEmpty()?t.toString():t.toNumber()},O=function(e){var t=(0,u.default)(e);return t.isInvalidate()?null:t},j=t.forwardRef(function(e,r){var n,p,v=e.prefixCls,y=e.className,b=e.style,x=e.min,E=e.max,j=e.step,T=void 0===j?1:j,_=e.defaultValue,P=e.value,I=e.disabled,F=e.readOnly,N=e.upHandler,R=e.downHandler,M=e.keyboard,A=e.changeOnWheel,B=void 0!==A&&A,z=e.controls,L=(e.classNames,e.stringMode),H=e.parser,D=e.formatter,V=e.precision,W=e.decimalSeparator,U=e.onChange,G=e.onInput,q=e.onPressEnter,K=e.onStep,X=e.changeOnBlur,J=void 0===X||X,Y=e.domRef,Q=(0,c.default)(e,$),Z="".concat(v,"-input"),ee=t.useRef(null),et=t.useState(!1),er=(0,s.default)(et,2),en=er[0],eo=er[1],ea=t.useRef(!1),ei=t.useRef(!1),el=t.useRef(!1),es=t.useState(function(){return(0,u.default)(null!=P?P:_)}),ec=(0,s.default)(es,2),eu=ec[0],ed=ec[1],ef=t.useCallback(function(e,t){if(!t)return V>=0?V:Math.max((0,d.getNumberPrecision)(e),(0,d.getNumberPrecision)(T))},[V,T]),ep=t.useCallback(function(e){var t=String(e);if(H)return H(t);var r=t;return W&&(r=r.replace(W,".")),r.replace(/[^\w.-]+/g,"")},[H,W]),em=t.useRef(""),eg=t.useCallback(function(e,t){if(D)return D(e,{userTyping:t,input:String(em.current)});var r="number"==typeof e?(0,d.num2str)(e):e;if(!t){var n=ef(r,t);if((0,d.validateNumber)(r)&&(W||n>=0)){var o=W||".";r=(0,f.toFixed)(r,o,n)}}return r},[D,ef,W]),eh=t.useState(function(){var e=null!=_?_:P;return eu.isInvalidate()&&["string","number"].includes((0,l.default)(e))?Number.isNaN(e)?"":e:eg(eu.toString(),!1)}),ev=(0,s.default)(eh,2),ey=ev[0],eb=ev[1];function ew(e,t){eb(eg(e.isInvalidate()?e.toString(!1):e.toString(!t),t))}em.current=ey;var eC=t.useMemo(function(){return O(E)},[E,V]),ex=t.useMemo(function(){return O(x)},[x,V]),eS=t.useMemo(function(){return!(!eC||!eu||eu.isInvalidate())&&eC.lessEquals(eu)},[eC,eu]),e$=t.useMemo(function(){return!(!ex||!eu||eu.isInvalidate())&&eu.lessEquals(ex)},[ex,eu]),eE=(n=ee.current,p=(0,t.useRef)(null),[function(){try{var e=n.selectionStart,t=n.selectionEnd,r=n.value,o=r.substring(0,e),a=r.substring(t);p.current={start:e,end:t,value:r,beforeTxt:o,afterTxt:a}}catch(e){}},function(){if(n&&p.current&&en)try{var e=n.value,t=p.current,r=t.beforeTxt,o=t.afterTxt,a=t.start,i=e.length;if(e.startsWith(r))i=r.length;else if(e.endsWith(o))i=e.length-p.current.afterTxt.length;else{var l=r[a-1],s=e.indexOf(l,a-1);-1!==s&&(i=s+1)}n.setSelectionRange(i,i)}catch(e){(0,h.default)(!1,"Something warning of cursor restore. Please fire issue about this: ".concat(e.message))}}]),ek=(0,s.default)(eE,2),eO=ek[0],ej=ek[1],eT=function(e){return eC&&!e.lessEquals(eC)?eC:ex&&!ex.lessEquals(e)?ex:null},e_=function(e){return!eT(e)},eP=function(e,t){var r=e,n=e_(r)||r.isEmpty();if(r.isEmpty()||t||(r=eT(r)||r,n=!0),!F&&!I&&n){var o,a=r.toString(),i=ef(a,t);return i>=0&&(e_(r=(0,u.default)((0,f.toFixed)(a,".",i)))||(r=(0,u.default)((0,f.toFixed)(a,".",i,!0)))),r.equals(eu)||(o=r,void 0===P&&ed(o),null==U||U(r.isEmpty()?null:k(L,r)),void 0===P&&ew(r,t)),r}return eu},eI=S(),eF=function e(t){if(eO(),em.current=t,eb(t),!ei.current){var r=ep(t),n=(0,u.default)(r);n.isNaN()||eP(n,!0)}null==G||G(t),eI(function(){var r=t;H||(r=t.replace(/。/g,".")),r!==t&&e(r)})},eN=function(e){if((!e||!eS)&&(e||!e$)){ea.current=!1;var t,r=(0,u.default)(el.current?C(T):T);e||(r=r.negate());var n=eP((eu||(0,u.default)(0)).add(r.toString()),!1);null==K||K(k(L,n),{offset:el.current?C(T):T,type:e?"up":"down"}),null==(t=ee.current)||t.focus()}},eR=function(e){var t,r=(0,u.default)(ep(ey));t=r.isNaN()?eP(eu,e):eP(r,e),void 0!==P?ew(eu,!1):t.isNaN()||ew(t,!1)};return t.useEffect(function(){if(B&&en){var e=function(e){eN(e.deltaY<0),e.preventDefault()},t=ee.current;if(t)return t.addEventListener("wheel",e,{passive:!1}),function(){return t.removeEventListener("wheel",e)}}}),(0,m.useLayoutUpdateEffect)(function(){eu.isInvalidate()||ew(eu,!1)},[V,D]),(0,m.useLayoutUpdateEffect)(function(){var e=(0,u.default)(P);ed(e);var t=(0,u.default)(ep(ey));e.equals(t)&&ea.current&&!D||ew(e,ea.current)},[P]),(0,m.useLayoutUpdateEffect)(function(){D&&ej()},[ey]),t.createElement("div",{ref:Y,className:(0,o.default)(v,y,(0,i.default)((0,i.default)((0,i.default)((0,i.default)((0,i.default)({},"".concat(v,"-focused"),en),"".concat(v,"-disabled"),I),"".concat(v,"-readonly"),F),"".concat(v,"-not-a-number"),eu.isNaN()),"".concat(v,"-out-of-range"),!eu.isInvalidate()&&!e_(eu))),style:b,onFocus:function(){eo(!0)},onBlur:function(){J&&eR(!1),eo(!1),ea.current=!1},onKeyDown:function(e){var t=e.key,r=e.shiftKey;ea.current=!0,el.current=r,"Enter"===t&&(ei.current||(ea.current=!1),eR(!1),null==q||q(e)),!1!==M&&!ei.current&&["Up","ArrowUp","Down","ArrowDown"].includes(t)&&(eN("Up"===t||"ArrowUp"===t),e.preventDefault())},onKeyUp:function(){ea.current=!1,el.current=!1},onCompositionStart:function(){ei.current=!0},onCompositionEnd:function(){ei.current=!1,eF(ee.current.value)},onBeforeInput:function(){ea.current=!0}},(void 0===z||z)&&t.createElement(w,{prefixCls:v,upNode:N,downNode:R,upDisabled:eS,downDisabled:e$,onStep:eN}),t.createElement("div",{className:"".concat(Z,"-wrap")},t.createElement("input",(0,a.default)({autoComplete:"off",role:"spinbutton","aria-valuemin":x,"aria-valuemax":E,"aria-valuenow":eu.isInvalidate()?null:eu.toString(),step:T},Q,{ref:(0,g.composeRef)(ee,r),className:Z,value:ey,onChange:function(e){eF(e.target.value)},disabled:I,readOnly:F}))))}),T=t.forwardRef(function(e,r){var n=e.disabled,o=e.style,i=e.prefixCls,l=void 0===i?"rc-input-number":i,s=e.value,u=e.prefix,d=e.suffix,f=e.addonBefore,m=e.addonAfter,g=e.className,h=e.classNames,v=(0,c.default)(e,E),y=t.useRef(null),b=t.useRef(null),w=t.useRef(null),C=function(e){w.current&&(0,x.triggerFocus)(w.current,e)};return t.useImperativeHandle(r,function(){var e,t;return e=w.current,t={focus:C,nativeElement:y.current.nativeElement||b.current},"u">typeof Proxy&&e?new Proxy(e,{get:function(e,r){if(t[r])return t[r];var n=e[r];return"function"==typeof n?n.bind(e):n}}):e}),t.createElement(p.BaseInput,{className:g,triggerFocus:C,prefixCls:l,value:s,disabled:n,style:o,prefix:u,suffix:d,addonAfter:m,addonBefore:f,classNames:h,components:{affixWrapper:"div",groupWrapper:"div",wrapper:"div",groupAddon:"div"},ref:y},t.createElement(j,(0,a.default)({prefixCls:l,disabled:n,ref:w,domRef:b,className:null==h?void 0:h.input},v)))}),_=e.i(617206),P=e.i(52956),I=e.i(609587),F=e.i(242064),N=e.i(937328),R=e.i(321883),M=e.i(517455),A=e.i(62139),B=e.i(792812),z=e.i(249616);e.i(296059);var L=e.i(915654),H=e.i(349942),D=e.i(517458),V=e.i(889943),W=e.i(183293),U=e.i(372409),G=e.i(246422),q=e.i(838378);e.i(262370);var K=e.i(135551);let X=({componentCls:e,borderRadiusSM:t,borderRadiusLG:r},n)=>{let o="lg"===n?r:t;return{[`&-${n}`]:{[`${e}-handler-wrap`]:{borderStartEndRadius:o,borderEndEndRadius:o},[`${e}-handler-up`]:{borderStartEndRadius:o},[`${e}-handler-down`]:{borderEndEndRadius:o}}}},J=(0,G.genStyleHooks)("InputNumber",e=>{let t=(0,q.mergeToken)(e,(0,D.initInputToken)(e));return[(e=>{let{componentCls:t,lineWidth:r,lineType:n,borderRadius:o,inputFontSizeSM:a,inputFontSizeLG:i,controlHeightLG:l,controlHeightSM:s,colorError:c,paddingInlineSM:u,paddingBlockSM:d,paddingBlockLG:f,paddingInlineLG:p,colorIcon:m,motionDurationMid:g,handleHoverColor:h,handleOpacity:v,paddingInline:y,paddingBlock:b,handleBg:w,handleActiveBg:C,colorTextDisabled:x,borderRadiusSM:S,borderRadiusLG:$,controlWidth:E,handleBorderColor:k,filledHandleBg:O,lineHeightLG:j,calc:T}=e;return[{[t]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},(0,W.resetComponent)(e)),(0,H.genBasicInputStyle)(e)),{display:"inline-block",width:E,margin:0,padding:0,borderRadius:o}),(0,V.genOutlinedStyle)(e,{[`${t}-handler-wrap`]:{background:w,[`${t}-handler-down`]:{borderBlockStart:`${(0,L.unit)(r)} ${n} ${k}`}}})),(0,V.genFilledStyle)(e,{[`${t}-handler-wrap`]:{background:O,[`${t}-handler-down`]:{borderBlockStart:`${(0,L.unit)(r)} ${n} ${k}`}},"&:focus-within":{[`${t}-handler-wrap`]:{background:w}}})),(0,V.genUnderlinedStyle)(e,{[`${t}-handler-wrap`]:{background:w,[`${t}-handler-down`]:{borderBlockStart:`${(0,L.unit)(r)} ${n} ${k}`}}})),(0,V.genBorderlessStyle)(e)),{"&-rtl":{direction:"rtl",[`${t}-input`]:{direction:"rtl"}},"&-lg":{padding:0,fontSize:i,lineHeight:j,borderRadius:$,[`input${t}-input`]:{height:T(l).sub(T(r).mul(2)).equal(),padding:`${(0,L.unit)(f)} ${(0,L.unit)(p)}`}},"&-sm":{padding:0,fontSize:a,borderRadius:S,[`input${t}-input`]:{height:T(s).sub(T(r).mul(2)).equal(),padding:`${(0,L.unit)(d)} ${(0,L.unit)(u)}`}},"&-out-of-range":{[`${t}-input-wrap`]:{input:{color:c}}},"&-group":Object.assign(Object.assign(Object.assign({},(0,W.resetComponent)(e)),(0,H.genInputGroupStyle)(e)),{"&-wrapper":Object.assign(Object.assign(Object.assign({display:"inline-block",textAlign:"start",verticalAlign:"top",[`${t}-affix-wrapper`]:{width:"100%"},"&-lg":{[`${t}-group-addon`]:{borderRadius:$,fontSize:e.fontSizeLG}},"&-sm":{[`${t}-group-addon`]:{borderRadius:S}}},(0,V.genOutlinedGroupStyle)(e)),(0,V.genFilledGroupStyle)(e)),{[`&:not(${t}-compact-first-item):not(${t}-compact-last-item)${t}-compact-item`]:{[`${t}, ${t}-group-addon`]:{borderRadius:0}},[`&:not(${t}-compact-last-item)${t}-compact-first-item`]:{[`${t}, ${t}-group-addon`]:{borderStartEndRadius:0,borderEndEndRadius:0}},[`&:not(${t}-compact-first-item)${t}-compact-last-item`]:{[`${t}, ${t}-group-addon`]:{borderStartStartRadius:0,borderEndStartRadius:0}}})}),[`&-disabled ${t}-input`]:{cursor:"not-allowed"},[t]:{"&-input":Object.assign(Object.assign(Object.assign(Object.assign({},(0,W.resetComponent)(e)),{width:"100%",padding:`${(0,L.unit)(b)} ${(0,L.unit)(y)}`,textAlign:"start",backgroundColor:"transparent",border:0,borderRadius:o,outline:0,transition:`all ${g} linear`,appearance:"textfield",fontSize:"inherit"}),(0,H.genPlaceholderStyle)(e.colorTextPlaceholder)),{'&[type="number"]::-webkit-inner-spin-button, &[type="number"]::-webkit-outer-spin-button':{margin:0,appearance:"none"}})},[`&:hover ${t}-handler-wrap, &-focused ${t}-handler-wrap`]:{width:e.handleWidth,opacity:1}})},{[t]:Object.assign(Object.assign(Object.assign({[`${t}-handler-wrap`]:{position:"absolute",insetBlockStart:0,insetInlineEnd:0,width:e.handleVisibleWidth,opacity:v,height:"100%",borderStartStartRadius:0,borderStartEndRadius:o,borderEndEndRadius:o,borderEndStartRadius:0,display:"flex",flexDirection:"column",alignItems:"stretch",transition:`all ${g}`,overflow:"hidden",[`${t}-handler`]:{display:"flex",alignItems:"center",justifyContent:"center",flex:"auto",height:"40%",[` + ${t}-handler-up-inner, + ${t}-handler-down-inner + `]:{marginInlineEnd:0,fontSize:e.handleFontSize}}},[`${t}-handler`]:{height:"50%",overflow:"hidden",color:m,fontWeight:"bold",lineHeight:0,textAlign:"center",cursor:"pointer",borderInlineStart:`${(0,L.unit)(r)} ${n} ${k}`,transition:`all ${g} linear`,"&:active":{background:C},"&:hover":{height:"60%",[` + ${t}-handler-up-inner, + ${t}-handler-down-inner + `]:{color:h}},"&-up-inner, &-down-inner":Object.assign(Object.assign({},(0,W.resetIcon)()),{color:m,transition:`all ${g} linear`,userSelect:"none"})},[`${t}-handler-up`]:{borderStartEndRadius:o},[`${t}-handler-down`]:{borderEndEndRadius:o}},X(e,"lg")),X(e,"sm")),{"&-disabled, &-readonly":{[`${t}-handler-wrap`]:{display:"none"},[`${t}-input`]:{color:"inherit"}},[` + ${t}-handler-up-disabled, + ${t}-handler-down-disabled + `]:{cursor:"not-allowed"},[` + ${t}-handler-up-disabled:hover &-handler-up-inner, + ${t}-handler-down-disabled:hover &-handler-down-inner + `]:{color:x}})}]})(t),(e=>{let{componentCls:t,paddingBlock:r,paddingInline:n,inputAffixPadding:o,controlWidth:a,borderRadiusLG:i,borderRadiusSM:l,paddingInlineLG:s,paddingInlineSM:c,paddingBlockLG:u,paddingBlockSM:d,motionDurationMid:f}=e;return{[`${t}-affix-wrapper`]:Object.assign(Object.assign({[`input${t}-input`]:{padding:`${(0,L.unit)(r)} 0`}},(0,H.genBasicInputStyle)(e)),{position:"relative",display:"inline-flex",alignItems:"center",width:a,padding:0,paddingInlineStart:n,"&-lg":{borderRadius:i,paddingInlineStart:s,[`input${t}-input`]:{padding:`${(0,L.unit)(u)} 0`}},"&-sm":{borderRadius:l,paddingInlineStart:c,[`input${t}-input`]:{padding:`${(0,L.unit)(d)} 0`}},[`&:not(${t}-disabled):hover`]:{zIndex:1},"&-focused, &:focus":{zIndex:1},[`&-disabled > ${t}-disabled`]:{background:"transparent"},[`> div${t}`]:{width:"100%",border:"none",outline:"none",[`&${t}-focused`]:{boxShadow:"none !important"}},"&::before":{display:"inline-block",width:0,visibility:"hidden",content:'"\\a0"'},[`${t}-handler-wrap`]:{zIndex:2},[t]:{position:"static",color:"inherit","&-prefix, &-suffix":{display:"flex",flex:"none",alignItems:"center",pointerEvents:"none"},"&-prefix":{marginInlineEnd:o},"&-suffix":{insetBlockStart:0,insetInlineEnd:0,height:"100%",marginInlineEnd:n,marginInlineStart:o,transition:`margin ${f}`}},[`&:hover ${t}-handler-wrap, &-focused ${t}-handler-wrap`]:{width:e.handleWidth,opacity:1},[`&:not(${t}-affix-wrapper-without-controls):hover ${t}-suffix`]:{marginInlineEnd:e.calc(e.handleWidth).add(n).equal()}}),[`${t}-underlined`]:{borderRadius:0}}})(t),(0,U.genCompactItemStyle)(t)]},e=>{var t;let r=null!=(t=e.handleVisible)?t:"auto",n=e.controlHeightSM-2*e.lineWidth;return Object.assign(Object.assign({},(0,D.initComponentToken)(e)),{controlWidth:90,handleWidth:n,handleFontSize:e.fontSize/2,handleVisible:r,handleActiveBg:e.colorFillAlter,handleBg:e.colorBgContainer,filledHandleBg:new K.FastColor(e.colorFillSecondary).onBackground(e.colorBgContainer).toHexString(),handleHoverColor:e.colorPrimary,handleBorderColor:e.colorBorder,handleOpacity:+(!0===r),handleVisibleWidth:!0===r?n:0})},{unitless:{handleOpacity:!0},resetFont:!1});var Y=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 Q=t.forwardRef((e,a)=>{let{getPrefixCls:i,direction:l}=t.useContext(F.ConfigContext),s=t.useRef(null);t.useImperativeHandle(a,()=>s.current);let{className:c,rootClassName:u,size:d,disabled:f,prefixCls:p,addonBefore:m,addonAfter:g,prefix:h,suffix:v,bordered:y,readOnly:b,status:w,controls:C,variant:x}=e,S=Y(e,["className","rootClassName","size","disabled","prefixCls","addonBefore","addonAfter","prefix","suffix","bordered","readOnly","status","controls","variant"]),$=i("input-number",p),E=(0,R.default)($),[k,O,j]=J($,E),{compactSize:I,compactItemClassnames:L}=(0,z.useCompactItemContext)($,l),H=t.createElement(n.default,{className:`${$}-handler-up-inner`}),D=t.createElement(r.default,{className:`${$}-handler-down-inner`}),V="boolean"==typeof C?C:void 0;"object"==typeof C&&(H=void 0===C.upIcon?H:t.createElement("span",{className:`${$}-handler-up-inner`},C.upIcon),D=void 0===C.downIcon?D:t.createElement("span",{className:`${$}-handler-down-inner`},C.downIcon));let{hasFeedback:W,status:U,isFormItemInput:G,feedbackIcon:q}=t.useContext(A.FormItemInputContext),K=(0,P.getMergedStatus)(U,w),X=(0,M.default)(e=>{var t;return null!=(t=null!=d?d:I)?t:e}),Q=t.useContext(N.default),Z=null!=f?f:Q,[ee,et]=(0,B.default)("inputNumber",x,y),er=W&&t.createElement(t.Fragment,null,q),en=(0,o.default)({[`${$}-lg`]:"large"===X,[`${$}-sm`]:"small"===X,[`${$}-rtl`]:"rtl"===l,[`${$}-in-form-item`]:G},O),eo=`${$}-group`;return k(t.createElement(T,Object.assign({ref:s,disabled:Z,className:(0,o.default)(j,E,c,u,L),upHandler:H,downHandler:D,prefixCls:$,readOnly:b,controls:V,prefix:h,suffix:er||v,addonBefore:m&&t.createElement(_.default,{form:!0,space:!0},m),addonAfter:g&&t.createElement(_.default,{form:!0,space:!0},g),classNames:{input:en,variant:(0,o.default)({[`${$}-${ee}`]:et},(0,P.getStatusClassNames)($,K,W)),affixWrapper:(0,o.default)({[`${$}-affix-wrapper-sm`]:"small"===X,[`${$}-affix-wrapper-lg`]:"large"===X,[`${$}-affix-wrapper-rtl`]:"rtl"===l,[`${$}-affix-wrapper-without-controls`]:!1===C||Z||b},O),wrapper:(0,o.default)({[`${eo}-rtl`]:"rtl"===l},O),groupWrapper:(0,o.default)({[`${$}-group-wrapper-sm`]:"small"===X,[`${$}-group-wrapper-lg`]:"large"===X,[`${$}-group-wrapper-rtl`]:"rtl"===l,[`${$}-group-wrapper-${ee}`]:et},(0,P.getStatusClassNames)(`${$}-group-wrapper`,K,W),O)}},S)))});Q._InternalPanelDoNotUseOrYouWillBeFired=e=>t.createElement(I.default,{theme:{components:{InputNumber:{handleVisible:!0}}}},t.createElement(Q,Object.assign({},e))),e.s(["InputNumber",0,Q],28651)},147138,210803,266623,794721,232176,843375,229548,e=>{"use strict";var t=e.i(410160),r=e.i(271645),n=e.i(343794);let o=function(e){var t=e.className,o=e.customizeIcon,a=e.customizeIconProps,i=e.children,l=e.onMouseDown,s=e.onClick,c="function"==typeof o?o(a):o;return r.createElement("span",{className:t,onMouseDown:function(e){e.preventDefault(),null==l||l(e)},style:{userSelect:"none",WebkitUserSelect:"none"},unselectable:"on",onClick:s,"aria-hidden":!0},void 0!==c?c:r.createElement("span",{className:(0,n.default)(t.split(/\s+/).map(function(e){return"".concat(e,"-icon")}))},i))};e.s(["default",0,o],210803);var a=function(e,n,a,i,l){var s=arguments.length>5&&void 0!==arguments[5]&&arguments[5],c=arguments.length>6?arguments[6]:void 0,u=arguments.length>7?arguments[7]:void 0,d=r.default.useMemo(function(){return"object"===(0,t.default)(i)?i.clearIcon:l||void 0},[i,l]);return{allowClear:r.default.useMemo(function(){return!s&&!!i&&(!!a.length||!!c)&&("combobox"!==u||""!==c)},[i,s,a.length,c,u]),clearIcon:r.default.createElement(o,{className:"".concat(e,"-clear"),onMouseDown:n,customizeIcon:d},"×")}};e.s(["useAllowClear",()=>a],147138);var i=r.createContext(null);function l(){return r.useContext(i)}e.s(["BaseSelectContext",()=>i,"default",()=>l],266623);var s=e.i(392221);function c(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,t=r.useState(!1),n=(0,s.default)(t,2),o=n[0],a=n[1],i=r.useRef(null),l=function(){window.clearTimeout(i.current)};return r.useEffect(function(){return l},[]),[o,function(t,r){l(),i.current=window.setTimeout(function(){a(t),r&&r()},e)},l]}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:250,t=r.useRef(null),n=r.useRef(null);return r.useEffect(function(){return function(){window.clearTimeout(n.current)}},[]),[function(){return t.current},function(r){(r||null===t.current)&&(t.current=r),window.clearTimeout(n.current),n.current=window.setTimeout(function(){t.current=null},e)}]}function d(e,t,n,o){var a=r.useRef(null);a.current={open:t,triggerOpen:n,customizedTrigger:o},r.useEffect(function(){function t(t){if(null==(r=a.current)||!r.customizedTrigger){var r,n=t.target;n.shadowRoot&&t.composed&&(n=t.composedPath()[0]||n),a.current.open&&e().filter(function(e){return e}).every(function(e){return!e.contains(n)&&e!==n})&&a.current.triggerOpen(!1)}}return window.addEventListener("mousedown",t),function(){return window.removeEventListener("mousedown",t)}},[])}e.s(["default",()=>c],794721),e.s(["default",()=>u],232176),e.s(["default",()=>d],843375);var f=e.i(404948);function p(e){return e&&![f.default.ESC,f.default.SHIFT,f.default.BACKSPACE,f.default.TAB,f.default.WIN_KEY,f.default.ALT,f.default.META,f.default.WIN_KEY_RIGHT,f.default.CTRL,f.default.SEMICOLON,f.default.EQUALS,f.default.CAPS_LOCK,f.default.CONTEXT_MENU,f.default.F1,f.default.F2,f.default.F3,f.default.F4,f.default.F5,f.default.F6,f.default.F7,f.default.F8,f.default.F9,f.default.F10,f.default.F11,f.default.F12].includes(e)}e.s(["isValidateOpenKey",()=>p],229548)},658315,e=>{"use strict";var t=e.i(931067),r=e.i(209428),n=e.i(392221),o=e.i(703923),a=e.i(271645),i=e.i(343794),l=e.i(430073),s=e.i(174428),c=["prefixCls","invalidate","item","renderItem","responsive","responsiveDisabled","registerSize","itemKey","className","style","children","display","order","component"],u=void 0,d=a.forwardRef(function(e,n){var s,d=e.prefixCls,f=e.invalidate,p=e.item,m=e.renderItem,g=e.responsive,h=e.responsiveDisabled,v=e.registerSize,y=e.itemKey,b=e.className,w=e.style,C=e.children,x=e.display,S=e.order,$=e.component,E=(0,o.default)(e,c),k=g&&!x;a.useEffect(function(){return function(){v(y,null)}},[]);var O=m&&p!==u?m(p,{index:S}):C;f||(s={opacity:+!k,height:k?0:u,overflowY:k?"hidden":u,order:g?S:u,pointerEvents:k?"none":u,position:k?"absolute":u});var j={};k&&(j["aria-hidden"]=!0);var T=a.createElement(void 0===$?"div":$,(0,t.default)({className:(0,i.default)(!f&&d,b),style:(0,r.default)((0,r.default)({},s),w)},j,E,{ref:n}),O);return g&&(T=a.createElement(l.default,{onResize:function(e){v(y,e.offsetWidth)},disabled:h},T)),T});d.displayName="Item";var f=e.i(175066),p=e.i(174080),m=e.i(963188);function g(e,t){var r=a.useState(t),o=(0,n.default)(r,2),i=o[0],l=o[1];return[i,(0,f.default)(function(t){e(function(){l(t)})})]}var h=a.default.createContext(null),v=["component"],y=["className"],b=["className"],w=a.forwardRef(function(e,r){var n=a.useContext(h);if(!n){var l=e.component,s=(0,o.default)(e,v);return a.createElement(void 0===l?"div":l,(0,t.default)({},s,{ref:r}))}var c=n.className,u=(0,o.default)(n,y),f=e.className,p=(0,o.default)(e,b);return a.createElement(h.Provider,{value:null},a.createElement(d,(0,t.default)({ref:r,className:(0,i.default)(c,f)},u,p)))});w.displayName="RawItem";var C=["prefixCls","data","renderItem","renderRawItem","itemKey","itemWidth","ssr","style","className","maxCount","renderRest","renderRawRest","prefix","suffix","component","itemComponent","onVisibleChange"],x="responsive",S="invalidate";function $(e){return"+ ".concat(e.length," ...")}var E=a.forwardRef(function(e,c){var u,f=e.prefixCls,v=void 0===f?"rc-overflow":f,y=e.data,b=void 0===y?[]:y,w=e.renderItem,E=e.renderRawItem,k=e.itemKey,O=e.itemWidth,j=void 0===O?10:O,T=e.ssr,_=e.style,P=e.className,I=e.maxCount,F=e.renderRest,N=e.renderRawRest,R=e.prefix,M=e.suffix,A=e.component,B=e.itemComponent,z=e.onVisibleChange,L=(0,o.default)(e,C),H="full"===T,D=(u=a.useRef(null),function(e){if(!u.current){u.current=[];var t=function(){(0,p.unstable_batchedUpdates)(function(){u.current.forEach(function(e){e()}),u.current=null})};if("u"I,eF=(0,a.useMemo)(function(){var e=b;return e_?e=null===U&&H?b:b.slice(0,Math.min(b.length,q/j)):"number"==typeof I&&(e=b.slice(0,I)),e},[b,j,U,I,e_]),eN=(0,a.useMemo)(function(){return e_?b.slice(ex+1):b.slice(eF.length)},[b,eF,e_,ex]),eR=(0,a.useCallback)(function(e,t){var r;return"function"==typeof k?k(e):null!=(r=k&&(null==e?void 0:e[k]))?r:t},[k]),eM=(0,a.useCallback)(w||function(e){return e},[w]);function eA(e,t,r){(ew!==e||void 0!==t&&t!==eh)&&(eC(e),r||(ek(eq){eA(n-1,e-o-ef+eo);break}}M&&ez(0)+ef>q&&ev(null)}},[q,J,eo,es,ef,eR,eF]);var eL=eE&&!!eN.length,eH={};null!==eh&&e_&&(eH={position:"absolute",left:eh,top:0});var eD={prefixCls:eO,responsive:e_,component:B,invalidate:eP},eV=E?function(e,t){var n=eR(e,t);return a.createElement(h.Provider,{key:n,value:(0,r.default)((0,r.default)({},eD),{},{order:t,item:e,itemKey:n,registerSize:eB,display:t<=ex})},E(e,t))}:function(e,r){var n=eR(e,r);return a.createElement(d,(0,t.default)({},eD,{order:r,key:n,item:e,renderItem:eM,itemKey:n,registerSize:eB,display:r<=ex}))},eW={order:eL?ex:Number.MAX_SAFE_INTEGER,className:"".concat(eO,"-rest"),registerSize:function(e,t){ea(t),et(eo)},display:eL},eU=F||$,eG=N?a.createElement(h.Provider,{value:(0,r.default)((0,r.default)({},eD),eW)},N(eN)):a.createElement(d,(0,t.default)({},eD,eW),"function"==typeof eU?eU(eN):eU),eq=a.createElement(void 0===A?"div":A,(0,t.default)({className:(0,i.default)(!eP&&v,P),style:_,ref:c},L),R&&a.createElement(d,(0,t.default)({},eD,{responsive:eT,responsiveDisabled:!e_,order:-1,className:"".concat(eO,"-prefix"),registerSize:function(e,t){ec(t)},display:!0}),R),eF.map(eV),eI?eG:null,M&&a.createElement(d,(0,t.default)({},eD,{responsive:eT,responsiveDisabled:!e_,order:ex,className:"".concat(eO,"-suffix"),registerSize:function(e,t){ep(t)},display:!0,style:eH}),M));return eT?a.createElement(l.default,{onResize:function(e,t){G(t.clientWidth)},disabled:!e_},eq):eq});E.displayName="Overflow",E.Item=w,E.RESPONSIVE=x,E.INVALIDATE=S,e.s(["default",0,E],658315)},823744,207427,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(392221),n=e.i(404948),o=e.i(271645),a=e.i(232176),i=e.i(229548),l=e.i(211577),s=e.i(343794),c=e.i(244009),u=e.i(658315),d=e.i(210803),f=e.i(209428),p=e.i(703923),m=e.i(611935),g=e.i(883110);let h=function(e,t,r){var n=(0,f.default)((0,f.default)({},e),r?t:{});return Object.keys(t).forEach(function(r){var o=t[r];"function"==typeof o&&(n[r]=function(){for(var t,n=arguments.length,a=Array(n),i=0;itypeof window&&window.document&&window.document.documentElement;function x(e){return null!=e}function S(e){return!e&&0!==e}function $(e){return["string","number"].includes((0,b.default)(e))}function E(e){var t=void 0;return e&&($(e.title)?t=e.title.toString():$(e.label)&&(t=e.label.toString())),t}function k(e){var t;return null!=(t=e.key)?t:e.value}e.s(["getTitle",()=>E,"hasValue",()=>x,"isBrowserClient",()=>C,"isComboNoValue",()=>S,"toArray",()=>w],207427);var O=function(e){e.preventDefault(),e.stopPropagation()};let j=function(e){var t,n,a=e.id,i=e.prefixCls,f=e.values,p=e.open,m=e.searchValue,g=e.autoClearSearchValue,h=e.inputRef,v=e.placeholder,b=e.disabled,w=e.mode,x=e.showSearch,S=e.autoFocus,$=e.autoComplete,j=e.activeDescendantId,T=e.tabIndex,_=e.removeIcon,P=e.maxTagCount,I=e.maxTagTextLength,F=e.maxTagPlaceholder,N=void 0===F?function(e){return"+ ".concat(e.length," ...")}:F,R=e.tagRender,M=e.onToggleOpen,A=e.onRemove,B=e.onInputChange,z=e.onInputPaste,L=e.onInputKeyDown,H=e.onInputMouseDown,D=e.onInputCompositionStart,V=e.onInputCompositionEnd,W=e.onInputBlur,U=o.useRef(null),G=(0,o.useState)(0),q=(0,r.default)(G,2),K=q[0],X=q[1],J=(0,o.useState)(!1),Y=(0,r.default)(J,2),Q=Y[0],Z=Y[1],ee="".concat(i,"-selection"),et=p||"multiple"===w&&!1===g||"tags"===w?m:"",er="tags"===w||"multiple"===w&&!1===g||x&&(p||Q);t=function(){X(U.current.scrollWidth)},n=[et],C?o.useLayoutEffect(t,n):o.useEffect(t,n);var en=function(e,t,r,n,a){return o.createElement("span",{title:E(e),className:(0,s.default)("".concat(ee,"-item"),(0,l.default)({},"".concat(ee,"-item-disabled"),r))},o.createElement("span",{className:"".concat(ee,"-item-content")},t),n&&o.createElement(d.default,{className:"".concat(ee,"-item-remove"),onMouseDown:O,onClick:a,customizeIcon:_},"×"))},eo=function(e,t,r,n,a,i){return o.createElement("span",{onMouseDown:function(e){O(e),M(!p)}},R({label:t,value:e,disabled:r,closable:n,onClose:a,isMaxTag:!!i}))},ea=o.createElement("div",{className:"".concat(ee,"-search"),style:{width:K},onFocus:function(){Z(!0)},onBlur:function(){Z(!1)}},o.createElement(y,{ref:h,open:p,prefixCls:i,id:a,inputElement:null,disabled:b,autoFocus:S,autoComplete:$,editable:er,activeDescendantId:j,value:et,onKeyDown:L,onMouseDown:H,onChange:B,onPaste:z,onCompositionStart:D,onCompositionEnd:V,onBlur:W,tabIndex:T,attrs:(0,c.default)(e,!0)}),o.createElement("span",{ref:U,className:"".concat(ee,"-search-mirror"),"aria-hidden":!0},et," ")),ei=o.createElement(u.default,{prefixCls:"".concat(ee,"-overflow"),data:f,renderItem:function(e){var t=e.disabled,r=e.label,n=e.value,o=!b&&!t,a=r;if("number"==typeof I&&("string"==typeof r||"number"==typeof r)){var i=String(a);i.length>I&&(a="".concat(i.slice(0,I),"..."))}var l=function(t){t&&t.stopPropagation(),A(e)};return"function"==typeof R?eo(n,a,t,o,l):en(e,a,t,o,l)},renderRest:function(e){if(!f.length)return null;var t="function"==typeof N?N(e):N;return"function"==typeof R?eo(void 0,t,!1,!1,void 0,!0):en({title:t},t,!1)},suffix:ea,itemKey:k,maxCount:P});return o.createElement("span",{className:"".concat(ee,"-wrap")},ei,!f.length&&!et&&o.createElement("span",{className:"".concat(ee,"-placeholder")},v))},T=function(e){var t=e.inputElement,n=e.prefixCls,a=e.id,i=e.inputRef,l=e.disabled,s=e.autoFocus,u=e.autoComplete,d=e.activeDescendantId,f=e.mode,p=e.open,m=e.values,g=e.placeholder,h=e.tabIndex,v=e.showSearch,b=e.searchValue,w=e.activeValue,C=e.maxLength,x=e.onInputKeyDown,S=e.onInputMouseDown,$=e.onInputChange,k=e.onInputPaste,O=e.onInputCompositionStart,j=e.onInputCompositionEnd,T=e.onInputBlur,_=e.title,P=o.useState(!1),I=(0,r.default)(P,2),F=I[0],N=I[1],R="combobox"===f,M=R||v,A=m[0],B=b||"";R&&w&&!F&&(B=w),o.useEffect(function(){R&&N(!1)},[R,w]);var z=("combobox"===f||!!p||!!v)&&!!B,L=void 0===_?E(A):_,H=o.useMemo(function(){return A?null:o.createElement("span",{className:"".concat(n,"-selection-placeholder"),style:z?{visibility:"hidden"}:void 0},g)},[A,z,g,n]);return o.createElement("span",{className:"".concat(n,"-selection-wrap")},o.createElement("span",{className:"".concat(n,"-selection-search")},o.createElement(y,{ref:i,prefixCls:n,id:a,open:p,inputElement:t,disabled:l,autoFocus:s,autoComplete:u,editable:M,activeDescendantId:d,value:B,onKeyDown:x,onMouseDown:S,onChange:function(e){N(!0),$(e)},onPaste:k,onCompositionStart:O,onCompositionEnd:j,onBlur:T,tabIndex:h,attrs:(0,c.default)(e,!0),maxLength:R?C:void 0})),!R&&A?o.createElement("span",{className:"".concat(n,"-selection-item"),title:L,style:z?{visibility:"hidden"}:void 0},A.label):null,H)};var _=o.forwardRef(function(e,l){var s=(0,o.useRef)(null),c=(0,o.useRef)(!1),u=e.prefixCls,d=e.open,f=e.mode,p=e.showSearch,m=e.tokenWithEnter,g=e.disabled,h=e.prefix,v=e.autoClearSearchValue,y=e.onSearch,b=e.onSearchSubmit,w=e.onToggleOpen,C=e.onInputKeyDown,x=e.onInputBlur,S=e.domRef;o.useImperativeHandle(l,function(){return{focus:function(e){s.current.focus(e)},blur:function(){s.current.blur()}}});var $=(0,a.default)(0),E=(0,r.default)($,2),k=E[0],O=E[1],_=(0,o.useRef)(null),P=function(e){!1!==y(e,!0,c.current)&&w(!0)},I={inputRef:s,onInputKeyDown:function(e){var t=e.which,r=s.current instanceof HTMLTextAreaElement;!r&&d&&(t===n.default.UP||t===n.default.DOWN)&&e.preventDefault(),C&&C(e),t!==n.default.ENTER||"tags"!==f||c.current||d||null==b||b(e.target.value),!(r&&!d&&~[n.default.UP,n.default.DOWN,n.default.LEFT,n.default.RIGHT].indexOf(t))&&(0,i.isValidateOpenKey)(t)&&w(!0)},onInputMouseDown:function(){O(!0)},onInputChange:function(e){var t=e.target.value;if(m&&_.current&&/[\r\n]/.test(_.current)){var r=_.current.replace(/[\r\n]+$/,"").replace(/\r\n/g," ").replace(/[\r\n]/g," ");t=t.replace(r,_.current)}_.current=null,P(t)},onInputPaste:function(e){var t=e.clipboardData;_.current=(null==t?void 0:t.getData("text"))||""},onInputCompositionStart:function(){c.current=!0},onInputCompositionEnd:function(e){c.current=!1,"combobox"!==f&&P(e.target.value)},onInputBlur:x},F="multiple"===f||"tags"===f?o.createElement(j,(0,t.default)({},e,I)):o.createElement(T,(0,t.default)({},e,I));return o.createElement("div",{ref:S,className:"".concat(u,"-selector"),onClick:function(e){e.target!==s.current&&(void 0!==document.body.style.msTouchAction?setTimeout(function(){s.current.focus()}):s.current.focus())},onMouseDown:function(e){var t=k();e.target===s.current||t||"combobox"===f&&g||e.preventDefault(),("combobox"===f||p&&t)&&d||(d&&!1!==v&&y("",!0,!1),w())}},h&&o.createElement("div",{className:"".concat(u,"-prefix")},h),F)});e.s(["default",0,_],823744)},331290,670532,300877,567770,750756,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(211577),n=e.i(8211),o=e.i(392221),a=e.i(209428),i=e.i(703923),l=e.i(343794),s=e.i(174428),c=e.i(914949),u=e.i(614761),d=e.i(611935),f=e.i(271645),p=e.i(147138),m=e.i(266623),g=e.i(794721),h=e.i(232176),v=e.i(843375),y=e.i(823744),b=e.i(707067),w=["prefixCls","disabled","visible","children","popupElement","animation","transitionName","dropdownStyle","dropdownClassName","direction","placement","builtinPlacements","dropdownMatchSelectWidth","dropdownRender","dropdownAlign","getPopupContainer","empty","getTriggerDOMNode","onPopupVisibleChange","onPopupMouseEnter"],C=function(e){var t=+(!0!==e);return{bottomLeft:{points:["tl","bl"],offset:[0,4],overflow:{adjustX:t,adjustY:1},htmlRegion:"scroll"},bottomRight:{points:["tr","br"],offset:[0,4],overflow:{adjustX:t,adjustY:1},htmlRegion:"scroll"},topLeft:{points:["bl","tl"],offset:[0,-4],overflow:{adjustX:t,adjustY:1},htmlRegion:"scroll"},topRight:{points:["br","tr"],offset:[0,-4],overflow:{adjustX:t,adjustY:1},htmlRegion:"scroll"}}},x=f.forwardRef(function(e,n){var o=e.prefixCls,s=(e.disabled,e.visible),c=e.children,u=e.popupElement,d=e.animation,p=e.transitionName,m=e.dropdownStyle,g=e.dropdownClassName,h=e.direction,v=e.placement,y=e.builtinPlacements,x=e.dropdownMatchSelectWidth,S=e.dropdownRender,$=e.dropdownAlign,E=e.getPopupContainer,k=e.empty,O=e.getTriggerDOMNode,j=e.onPopupVisibleChange,T=e.onPopupMouseEnter,_=(0,i.default)(e,w),P="".concat(o,"-dropdown"),I=u;S&&(I=S(u));var F=f.useMemo(function(){return y||C(x)},[y,x]),N=d?"".concat(P,"-").concat(d):p,R="number"==typeof x,M=f.useMemo(function(){return R?null:!1===x?"minWidth":"width"},[x,R]),A=m;R&&(A=(0,a.default)((0,a.default)({},A),{},{width:x}));var B=f.useRef(null);return f.useImperativeHandle(n,function(){return{getPopupElement:function(){var e;return null==(e=B.current)?void 0:e.popupElement}}}),f.createElement(b.default,(0,t.default)({},_,{showAction:j?["click"]:[],hideAction:j?["click"]:[],popupPlacement:v||("rtl"===(void 0===h?"ltr":h)?"bottomRight":"bottomLeft"),builtinPlacements:F,prefixCls:P,popupTransitionName:N,popup:f.createElement("div",{onMouseEnter:T},I),ref:B,stretch:M,popupAlign:$,popupVisible:s,getPopupContainer:E,popupClassName:(0,l.default)(g,(0,r.default)({},"".concat(P,"-empty"),k)),popupStyle:A,getTriggerDOMNode:O,onPopupVisibleChange:j}),c)}),S=e.i(210803),$=e.i(865610),E=e.i(883110);function k(e,t){var r,n=e.key;return("value"in e&&(r=e.value),null!=n)?n:void 0!==r?r:"rc-index-key-".concat(t)}function O(e){return void 0!==e&&!Number.isNaN(e)}function j(e,t){var r=e||{},n=r.label,o=r.value,a=r.options,i=r.groupLabel,l=n||(t?"children":"label");return{label:l,value:o||"value",options:a||"options",groupLabel:i||l}}function T(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.fieldNames,n=t.childrenAsData,o=[],a=j(r,!1),i=a.label,l=a.value,s=a.options,c=a.groupLabel;return!function e(t,r){Array.isArray(t)&&t.forEach(function(t){if(!r&&s in t){var a=t[c];void 0===a&&n&&(a=t.label),o.push({key:k(t,o.length),group:!0,data:t,label:a}),e(t[s],!0)}else{var u=t[l];o.push({key:k(t,o.length),groupOption:r,data:t,label:t[i],value:u})}})}(e,!1),o}function _(e){var t=(0,a.default)({},e);return"props"in t||Object.defineProperty(t,"props",{get:function(){return(0,E.default)(!1,"Return type is option instead of Option instance. Please read value directly instead of reading from `props`."),t}}),t}var P=function(e,t,r){if(!t||!t.length)return null;var o=!1,a=function e(t,r){var a=(0,$.default)(r),i=a[0],l=a.slice(1);if(!i)return[t];var s=t.split(i);return o=o||s.length>1,s.reduce(function(t,r){return[].concat((0,n.default)(t),(0,n.default)(e(r,l)))},[]).filter(Boolean)}(e,t);return o?void 0!==r?a.slice(0,r):a:null};e.s(["fillFieldNames",()=>j,"flattenOptions",()=>T,"getSeparatedContent",()=>P,"injectPropsWithOption",()=>_,"isValidCount",()=>O],670532);var I=f.createContext(null);e.s(["default",0,I],300877);var F=e.i(410160);function N(e){var t=e.visible,r=e.values;return t?f.createElement("span",{"aria-live":"polite",style:{width:0,height:0,position:"absolute",overflow:"hidden",opacity:0}},"".concat(r.slice(0,50).map(function(e){var t=e.label,r=e.value;return["number","string"].includes((0,F.default)(t))?t:r}).join(", ")),r.length>50?", ...":null):null}var R=["id","prefixCls","className","showSearch","tagRender","direction","omitDomProps","displayValues","onDisplayValuesChange","emptyOptions","notFoundContent","onClear","mode","disabled","loading","getInputElement","getRawInputElement","open","defaultOpen","onDropdownVisibleChange","activeValue","onActiveValueChange","activeDescendantId","searchValue","autoClearSearchValue","onSearch","onSearchSplit","tokenSeparators","allowClear","prefix","suffixIcon","clearIcon","OptionList","animation","transitionName","dropdownStyle","dropdownClassName","dropdownMatchSelectWidth","dropdownRender","dropdownAlign","placement","builtinPlacements","getPopupContainer","showAction","onFocus","onBlur","onKeyUp","onKeyDown","onMouseDown"],M=["value","onChange","removeIcon","placeholder","autoFocus","maxTagCount","maxTagTextLength","maxTagPlaceholder","choiceTransitionName","onInputKeyDown","onPopupScroll","tabIndex"],A=function(e){return"tags"===e||"multiple"===e},B=f.forwardRef(function(e,b){var w,C,$,E,k=e.id,j=e.prefixCls,T=e.className,_=e.showSearch,F=e.tagRender,B=e.direction,z=e.omitDomProps,L=e.displayValues,H=e.onDisplayValuesChange,D=e.emptyOptions,V=e.notFoundContent,W=void 0===V?"Not Found":V,U=e.onClear,G=e.mode,q=e.disabled,K=e.loading,X=e.getInputElement,J=e.getRawInputElement,Y=e.open,Q=e.defaultOpen,Z=e.onDropdownVisibleChange,ee=e.activeValue,et=e.onActiveValueChange,er=e.activeDescendantId,en=e.searchValue,eo=e.autoClearSearchValue,ea=e.onSearch,ei=e.onSearchSplit,el=e.tokenSeparators,es=e.allowClear,ec=e.prefix,eu=e.suffixIcon,ed=e.clearIcon,ef=e.OptionList,ep=e.animation,em=e.transitionName,eg=e.dropdownStyle,eh=e.dropdownClassName,ev=e.dropdownMatchSelectWidth,ey=e.dropdownRender,eb=e.dropdownAlign,ew=e.placement,eC=e.builtinPlacements,ex=e.getPopupContainer,eS=e.showAction,e$=void 0===eS?[]:eS,eE=e.onFocus,ek=e.onBlur,eO=e.onKeyUp,ej=e.onKeyDown,eT=e.onMouseDown,e_=(0,i.default)(e,R),eP=A(G),eI=(void 0!==_?_:eP)||"combobox"===G,eF=(0,a.default)({},e_);M.forEach(function(e){delete eF[e]}),null==z||z.forEach(function(e){delete eF[e]});var eN=f.useState(!1),eR=(0,o.default)(eN,2),eM=eR[0],eA=eR[1];f.useEffect(function(){eA((0,u.default)())},[]);var eB=f.useRef(null),ez=f.useRef(null),eL=f.useRef(null),eH=f.useRef(null),eD=f.useRef(null),eV=f.useRef(!1),eW=(0,g.default)(),eU=(0,o.default)(eW,3),eG=eU[0],eq=eU[1],eK=eU[2];f.useImperativeHandle(b,function(){var e,t;return{focus:null==(e=eH.current)?void 0:e.focus,blur:null==(t=eH.current)?void 0:t.blur,scrollTo:function(e){var t;return null==(t=eD.current)?void 0:t.scrollTo(e)},nativeElement:eB.current||ez.current}});var eX=f.useMemo(function(){if("combobox"!==G)return en;var e,t=null==(e=L[0])?void 0:e.value;return"string"==typeof t||"number"==typeof t?String(t):""},[en,G,L]),eJ="combobox"===G&&"function"==typeof X&&X()||null,eY="function"==typeof J&&J(),eQ=(0,d.useComposeRef)(ez,null==eY||null==(w=eY.props)?void 0:w.ref),eZ=f.useState(!1),e0=(0,o.default)(eZ,2),e1=e0[0],e2=e0[1];(0,s.default)(function(){e2(!0)},[]);var e4=(0,c.default)(!1,{defaultValue:Q,value:Y}),e6=(0,o.default)(e4,2),e5=e6[0],e3=e6[1],e7=!!e1&&e5,e8=!W&&D;(q||e8&&e7&&"combobox"===G)&&(e7=!1);var e9=!e8&&e7,te=f.useCallback(function(e){var t=void 0!==e?e:!e7;q||(e3(t),e7!==t&&(null==Z||Z(t)))},[q,e7,e3,Z]),tt=f.useMemo(function(){return(el||[]).some(function(e){return["\n","\r\n"].includes(e)})},[el]),tr=f.useContext(I)||{},tn=tr.maxCount,to=tr.rawValues,ta=function(e,t,r){if(!(eP&&O(tn))||!((null==to?void 0:to.size)>=tn)){var n=!0,o=e;null==et||et(null);var a=P(e,el,O(tn)?tn-to.size:void 0),i=r?null:a;return"combobox"!==G&&i&&(o="",null==ei||ei(i),te(!1),n=!1),ea&&eX!==o&&ea(o,{source:t?"typing":"effect"}),n}};f.useEffect(function(){e7||eP||"combobox"===G||ta("",!1,!1)},[e7]),f.useEffect(function(){e5&&q&&e3(!1),q&&!eV.current&&eq(!1)},[q]);var ti=(0,h.default)(),tl=(0,o.default)(ti,2),ts=tl[0],tc=tl[1],tu=f.useRef(!1),td=f.useRef(!1),tf=[];f.useEffect(function(){return function(){tf.forEach(function(e){return clearTimeout(e)}),tf.splice(0,tf.length)}},[]);var tp=f.useState({}),tm=(0,o.default)(tp,2)[1];eY&&(C=function(e){te(e)}),(0,v.default)(function(){var e;return[eB.current,null==(e=eL.current)?void 0:e.getPopupElement()]},e9,te,!!eY);var tg=f.useMemo(function(){return(0,a.default)((0,a.default)({},e),{},{notFoundContent:W,open:e7,triggerOpen:e9,id:k,showSearch:eI,multiple:eP,toggleOpen:te})},[e,W,e9,e7,k,eI,eP,te]),th=!!eu||K;th&&($=f.createElement(S.default,{className:(0,l.default)("".concat(j,"-arrow"),(0,r.default)({},"".concat(j,"-arrow-loading"),K)),customizeIcon:eu,customizeIconProps:{loading:K,searchValue:eX,open:e7,focused:eG,showSearch:eI}}));var tv=(0,p.useAllowClear)(j,function(){var e;null==U||U(),null==(e=eH.current)||e.focus(),H([],{type:"clear",values:L}),ta("",!1,!1)},L,es,ed,q,eX,G),ty=tv.allowClear,tb=tv.clearIcon,tw=f.createElement(ef,{ref:eD}),tC=(0,l.default)(j,T,(0,r.default)((0,r.default)((0,r.default)((0,r.default)((0,r.default)((0,r.default)((0,r.default)((0,r.default)((0,r.default)((0,r.default)({},"".concat(j,"-focused"),eG),"".concat(j,"-multiple"),eP),"".concat(j,"-single"),!eP),"".concat(j,"-allow-clear"),es),"".concat(j,"-show-arrow"),th),"".concat(j,"-disabled"),q),"".concat(j,"-loading"),K),"".concat(j,"-open"),e7),"".concat(j,"-customize-input"),eJ),"".concat(j,"-show-search"),eI)),tx=f.createElement(x,{ref:eL,disabled:q,prefixCls:j,visible:e9,popupElement:tw,animation:ep,transitionName:em,dropdownStyle:eg,dropdownClassName:eh,direction:B,dropdownMatchSelectWidth:ev,dropdownRender:ey,dropdownAlign:eb,placement:ew,builtinPlacements:eC,getPopupContainer:ex,empty:D,getTriggerDOMNode:function(e){return ez.current||e},onPopupVisibleChange:C,onPopupMouseEnter:function(){tm({})}},eY?f.cloneElement(eY,{ref:eQ}):f.createElement(y.default,(0,t.default)({},e,{domRef:ez,prefixCls:j,inputElement:eJ,ref:eH,id:k,prefix:ec,showSearch:eI,autoClearSearchValue:eo,mode:G,activeDescendantId:er,tagRender:F,values:L,open:e7,onToggleOpen:te,activeValue:ee,searchValue:eX,onSearch:ta,onSearchSubmit:function(e){e&&e.trim()&&ea(e,{source:"submit"})},onRemove:function(e){H(L.filter(function(t){return t!==e}),{type:"remove",values:[e]})},tokenWithEnter:tt,onInputBlur:function(){tu.current=!1}})));return E=eY?tx:f.createElement("div",(0,t.default)({className:tC},eF,{ref:eB,onMouseDown:function(e){var t,r=e.target,n=null==(t=eL.current)?void 0:t.getPopupElement();if(n&&n.contains(r)){var o=setTimeout(function(){var e,t=tf.indexOf(o);-1!==t&&tf.splice(t,1),eK(),eM||n.contains(document.activeElement)||null==(e=eH.current)||e.focus()});tf.push(o)}for(var a=arguments.length,i=Array(a>1?a-1:0),l=1;l=0;s-=1){var c=i[s];if(!c.disabled){i.splice(s,1),l=c;break}}l&&H(i,{type:"remove",values:[l]})}for(var u=arguments.length,d=Array(u>1?u-1:0),f=1;f1?r-1:0),o=1;oA],331290);var z=function(){return null};z.isSelectOptGroup=!0,e.s(["default",0,z],567770);var L=function(){return null};L.isSelectOption=!0,e.s(["default",0,L],750756)},323002,e=>{"use strict";var t=e.i(931067),r=e.i(410160),n=e.i(209428),o=e.i(211577),a=e.i(392221),i=e.i(703923),l=e.i(343794),s=e.i(430073);e.i(62664);var c=e.i(697539),u=e.i(174428),d=e.i(271645),f=e.i(174080),p=d.forwardRef(function(e,r){var a=e.height,i=e.offsetY,c=e.offsetX,u=e.children,f=e.prefixCls,p=e.onInnerResize,m=e.innerProps,g=e.rtl,h=e.extra,v={},y={display:"flex",flexDirection:"column"};return void 0!==i&&(v={height:a,position:"relative",overflow:"hidden"},y=(0,n.default)((0,n.default)({},y),{},(0,o.default)((0,o.default)((0,o.default)((0,o.default)((0,o.default)({transform:"translateY(".concat(i,"px)")},g?"marginRight":"marginLeft",-c),"position","absolute"),"left",0),"right",0),"top",0))),d.createElement("div",{style:v},d.createElement(s.default,{onResize:function(e){e.offsetHeight&&p&&p()}},d.createElement("div",(0,t.default)({style:y,className:(0,l.default)((0,o.default)({},"".concat(f,"-holder-inner"),f)),ref:r},m),u,h)))});function m(e){var t=e.children,r=e.setRef,n=d.useCallback(function(e){r(e)},[]);return d.cloneElement(t,{ref:n})}p.displayName="Filler";var g=e.i(963188),h=("u"2&&void 0!==arguments[2]&&arguments[2],n=e?t<0&&i.current.left||t>0&&i.current.right:t<0&&i.current.top||t>0&&i.current.bottom;return r&&n?(clearTimeout(a.current),o.current=!1):(!n||o.current)&&(clearTimeout(a.current),o.current=!0,a.current=setTimeout(function(){o.current=!1},50)),!o.current&&n}};var y=e.i(278409),b=e.i(233848),w=function(){function e(){(0,y.default)(this,e),(0,o.default)(this,"maps",void 0),(0,o.default)(this,"id",0),(0,o.default)(this,"diffRecords",new Map),this.maps=Object.create(null)}return(0,b.default)(e,[{key:"set",value:function(e,t){this.diffRecords.set(e,this.maps[e]),this.maps[e]=t,this.id+=1}},{key:"get",value:function(e){return this.maps[e]}},{key:"resetRecord",value:function(){this.diffRecords.clear()}},{key:"getRecord",value:function(){return this.diffRecords}}]),e}();function C(e){var t=parseFloat(e);return isNaN(t)?0:t}var x=14/15;function S(e){return Math.floor(Math.pow(e,.5))}function $(e,t){return("touches"in e?e.touches[0]:e)[t?"pageX":"pageY"]-window[t?"scrollX":"scrollY"]}e.i(247167);var E=d.forwardRef(function(e,t){var r=e.prefixCls,i=e.rtl,s=e.scrollOffset,c=e.scrollRange,u=e.onStartMove,f=e.onStopMove,p=e.onScroll,m=e.horizontal,h=e.spinSize,v=e.containerSize,y=e.style,b=e.thumbStyle,w=e.showScrollBar,C=d.useState(!1),x=(0,a.default)(C,2),S=x[0],E=x[1],k=d.useState(null),O=(0,a.default)(k,2),j=O[0],T=O[1],_=d.useState(null),P=(0,a.default)(_,2),I=P[0],F=P[1],N=!i,R=d.useRef(),M=d.useRef(),A=d.useState(w),B=(0,a.default)(A,2),z=B[0],L=B[1],H=d.useRef(),D=function(){!0!==w&&!1!==w&&(clearTimeout(H.current),L(!0),H.current=setTimeout(function(){L(!1)},3e3))},V=c-v||0,W=v-h||0,U=d.useMemo(function(){return 0===s||0===V?0:s/V*W},[s,V,W]),G=d.useRef({top:U,dragging:S,pageY:j,startTop:I});G.current={top:U,dragging:S,pageY:j,startTop:I};var q=function(e){E(!0),T($(e,m)),F(G.current.top),u(),e.stopPropagation(),e.preventDefault()};d.useEffect(function(){var e=function(e){e.preventDefault()},t=R.current,r=M.current;return t.addEventListener("touchstart",e,{passive:!1}),r.addEventListener("touchstart",q,{passive:!1}),function(){t.removeEventListener("touchstart",e),r.removeEventListener("touchstart",q)}},[]);var K=d.useRef();K.current=V;var X=d.useRef();X.current=W,d.useEffect(function(){if(S){var e,t=function(t){var r=G.current,n=r.dragging,o=r.pageY,a=r.startTop;g.default.cancel(e);var i=R.current.getBoundingClientRect(),l=v/(m?i.width:i.height);if(n){var s=($(t,m)-o)*l,c=a;!N&&m?c-=s:c+=s;var u=K.current,d=X.current,f=Math.ceil((d?c/d:0)*u);f=Math.min(f=Math.max(f,0),u),e=(0,g.default)(function(){p(f,m)})}},r=function(){E(!1),f()};return window.addEventListener("mousemove",t,{passive:!0}),window.addEventListener("touchmove",t,{passive:!0}),window.addEventListener("mouseup",r,{passive:!0}),window.addEventListener("touchend",r,{passive:!0}),function(){window.removeEventListener("mousemove",t),window.removeEventListener("touchmove",t),window.removeEventListener("mouseup",r),window.removeEventListener("touchend",r),g.default.cancel(e)}}},[S]),d.useEffect(function(){return D(),function(){clearTimeout(H.current)}},[s]),d.useImperativeHandle(t,function(){return{delayHidden:D}});var J="".concat(r,"-scrollbar"),Y={position:"absolute",visibility:z?null:"hidden"},Q={position:"absolute",borderRadius:99,background:"var(--rc-virtual-list-scrollbar-bg, rgba(0, 0, 0, 0.5))",cursor:"pointer",userSelect:"none"};return m?(Object.assign(Y,{height:8,left:0,right:0,bottom:0}),Object.assign(Q,(0,o.default)({height:"100%",width:h},N?"left":"right",U))):(Object.assign(Y,(0,o.default)({width:8,top:0,bottom:0},N?"right":"left",0)),Object.assign(Q,{width:"100%",height:h,top:U})),d.createElement("div",{ref:R,className:(0,l.default)(J,(0,o.default)((0,o.default)((0,o.default)({},"".concat(J,"-horizontal"),m),"".concat(J,"-vertical"),!m),"".concat(J,"-visible"),z)),style:(0,n.default)((0,n.default)({},Y),y),onMouseDown:function(e){e.stopPropagation(),e.preventDefault()},onMouseMove:D},d.createElement("div",{ref:M,className:(0,l.default)("".concat(J,"-thumb"),(0,o.default)({},"".concat(J,"-thumb-moving"),S)),style:(0,n.default)((0,n.default)({},Q),b),onMouseDown:q}))});function k(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=e/t*e;return isNaN(r)&&(r=0),Math.floor(r=Math.max(r,20))}var O=["prefixCls","className","height","itemHeight","fullHeight","style","data","children","itemKey","virtual","direction","scrollWidth","component","onScroll","onVirtualScroll","onVisibleChange","innerProps","extraRender","styles","showScrollBar"],j=[],T={overflowY:"auto",overflowAnchor:"none"},_=d.forwardRef(function(e,y){var b,_,P,I,F,N,R,M,A,B,z,L,H,D,V,W,U,G,q,K,X,J,Y,Q,Z,ee,et,er,en,eo,ea,ei,el,es,ec,eu,ed,ef=e.prefixCls,ep=void 0===ef?"rc-virtual-list":ef,em=e.className,eg=e.height,eh=e.itemHeight,ev=e.fullHeight,ey=e.style,eb=e.data,ew=e.children,eC=e.itemKey,ex=e.virtual,eS=e.direction,e$=e.scrollWidth,eE=e.component,ek=e.onScroll,eO=e.onVirtualScroll,ej=e.onVisibleChange,eT=e.innerProps,e_=e.extraRender,eP=e.styles,eI=e.showScrollBar,eF=void 0===eI?"optional":eI,eN=(0,i.default)(e,O),eR=d.useCallback(function(e){return"function"==typeof eC?eC(e):null==e?void 0:e[eC]},[eC]),eM=function(e,t,r){var n=d.useState(0),o=(0,a.default)(n,2),i=o[0],l=o[1],s=(0,d.useRef)(new Map),c=(0,d.useRef)(new w),u=(0,d.useRef)(0);function f(){u.current+=1}function p(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];f();var t=function(){var e=!1;s.current.forEach(function(t,r){if(t&&t.offsetParent){var n=t.offsetHeight,o=getComputedStyle(t),a=o.marginTop,i=o.marginBottom,l=n+C(a)+C(i);c.current.get(r)!==l&&(c.current.set(r,l),e=!0)}}),e&&l(function(e){return e+1})};if(e)t();else{u.current+=1;var r=u.current;Promise.resolve().then(function(){r===u.current&&t()})}}return(0,d.useEffect)(function(){return f},[]),[function(n,o){var a=e(n),i=s.current.get(a);o?(s.current.set(a,o),p()):s.current.delete(a),!i!=!o&&(o?null==t||t(n):null==r||r(n))},p,c.current,i]}(eR,null,null),eA=(0,a.default)(eM,4),eB=eA[0],ez=eA[1],eL=eA[2],eH=eA[3],eD=!!(!1!==ex&&eg&&eh),eV=d.useMemo(function(){return Object.values(eL.maps).reduce(function(e,t){return e+t},0)},[eL.id,eL.maps]),eW=eD&&eb&&(Math.max(eh*eb.length,eV)>eg||!!e$),eU="rtl"===eS,eG=(0,l.default)(ep,(0,o.default)({},"".concat(ep,"-rtl"),eU),em),eq=eb||j,eK=(0,d.useRef)(),eX=(0,d.useRef)(),eJ=(0,d.useRef)(),eY=(0,d.useState)(0),eQ=(0,a.default)(eY,2),eZ=eQ[0],e0=eQ[1],e1=(0,d.useState)(0),e2=(0,a.default)(e1,2),e4=e2[0],e6=e2[1],e5=(0,d.useState)(!1),e3=(0,a.default)(e5,2),e7=e3[0],e8=e3[1],e9=function(){e8(!0)},te=function(){e8(!1)};function tt(e){e0(function(t){var r,n=(r="function"==typeof e?e(t):e,Number.isNaN(tb.current)||(r=Math.min(r,tb.current)),r=Math.max(r,0));return eK.current.scrollTop=n,n})}var tr=(0,d.useRef)({start:0,end:eq.length}),tn=(0,d.useRef)(),to=(b=d.useState(eq),P=(_=(0,a.default)(b,2))[0],I=_[1],F=d.useState(null),R=(N=(0,a.default)(F,2))[0],M=N[1],d.useEffect(function(){var e=function(e,t,r){var n,o,a=e.length,i=t.length;if(0===a&&0===i)return null;a=eZ&&void 0===t&&(t=i,r=o),c>eZ+eg&&void 0===n&&(n=i),o=c}return void 0===t&&(t=0,r=0,n=Math.ceil(eg/eh)),void 0===n&&(n=eq.length-1),{scrollHeight:o,start:t,end:n=Math.min(n+1,eq.length-1),offset:r}},[eW,eD,eZ,eq,eH,eg]),ti=ta.scrollHeight,tl=ta.start,ts=ta.end,tc=ta.offset;tr.current.start=tl,tr.current.end=ts,d.useLayoutEffect(function(){var e=eL.getRecord();if(1===e.size){var t=Array.from(e.keys())[0],r=e.get(t),n=eq[tl];if(n&&void 0===r&&eR(n)===t){var o=eL.get(t)-eh;tt(function(e){return e+o})}}eL.resetRecord()},[ti]);var tu=d.useState({width:0,height:eg}),td=(0,a.default)(tu,2),tf=td[0],tp=td[1],tm=(0,d.useRef)(),tg=(0,d.useRef)(),th=d.useMemo(function(){return k(tf.width,e$)},[tf.width,e$]),tv=d.useMemo(function(){return k(tf.height,ti)},[tf.height,ti]),ty=ti-eg,tb=(0,d.useRef)(ty);tb.current=ty;var tw=eZ<=0,tC=eZ>=ty,tx=e4<=0,tS=e4>=e$,t$=v(tw,tC,tx,tS),tE=function(){return{x:eU?-e4:e4,y:eZ}},tk=(0,d.useRef)(tE()),tO=(0,c.useEvent)(function(e){if(eO){var t=(0,n.default)((0,n.default)({},tE()),e);(tk.current.x!==t.x||tk.current.y!==t.y)&&(eO(t),tk.current=t)}});function tj(e,t){t?((0,f.flushSync)(function(){e6(e)}),tO()):tt(e)}var tT=function(e){var t=e,r=e$?e$-tf.width:0;return Math.min(t=Math.max(t,0),r)},t_=(0,c.useEvent)(function(e,t){t?((0,f.flushSync)(function(){e6(function(t){return tT(t+(eU?-e:e))})}),tO()):tt(function(t){return t+e})}),tP=(A=!!e$,B=(0,d.useRef)(0),z=(0,d.useRef)(null),L=(0,d.useRef)(null),H=(0,d.useRef)(!1),D=v(tw,tC,tx,tS),V=(0,d.useRef)(null),W=(0,d.useRef)(null),[function(e){if(eD){g.default.cancel(W.current),W.current=(0,g.default)(function(){V.current=null},2);var t,r,n=e.deltaX,o=e.deltaY,a=e.shiftKey,i=n,l=o;("sx"===V.current||!V.current&&a&&o&&!n)&&(i=o,l=0,V.current="sx");var s=Math.abs(i),c=Math.abs(l);if(null===V.current&&(V.current=A&&s>c?"x":"y"),"y"===V.current){t=e,r=l,g.default.cancel(z.current),!D(!1,r)&&(t._virtualHandled||(t._virtualHandled=!0,B.current+=r,L.current=r,h||t.preventDefault(),z.current=(0,g.default)(function(){var e=H.current?10:1;t_(B.current*e,!1),B.current=0})))}else t_(i,!0),h||e.preventDefault()}},function(e){eD&&(H.current=e.detail===L.current)}]),tI=(0,a.default)(tP,2),tF=tI[0],tN=tI[1];U=function(e,t,r,n){return!t$(e,t,r)&&(!n||!n._virtualHandled)&&(n&&(n._virtualHandled=!0),tF({preventDefault:function(){},deltaX:e?t:0,deltaY:e?0:t}),!0)},q=(0,d.useRef)(!1),K=(0,d.useRef)(0),X=(0,d.useRef)(0),J=(0,d.useRef)(null),Y=(0,d.useRef)(null),Q=function(e){if(q.current){var t=Math.ceil(e.touches[0].pageX),r=Math.ceil(e.touches[0].pageY),n=K.current-t,o=X.current-r,a=Math.abs(n)>Math.abs(o);a?K.current=t:X.current=r;var i=U(a,a?n:o,!1,e);i&&e.preventDefault(),clearInterval(Y.current),i&&(Y.current=setInterval(function(){a?n*=x:o*=x;var e=Math.floor(a?n:o);(!U(a,e,!0)||.1>=Math.abs(e))&&clearInterval(Y.current)},16))}},Z=function(){q.current=!1,G()},ee=function(e){G(),1!==e.touches.length||q.current||(q.current=!0,K.current=Math.ceil(e.touches[0].pageX),X.current=Math.ceil(e.touches[0].pageY),J.current=e.target,J.current.addEventListener("touchmove",Q,{passive:!1}),J.current.addEventListener("touchend",Z,{passive:!0}))},G=function(){J.current&&(J.current.removeEventListener("touchmove",Q),J.current.removeEventListener("touchend",Z))},(0,u.default)(function(){return eD&&eK.current.addEventListener("touchstart",ee,{passive:!0}),function(){var e;null==(e=eK.current)||e.removeEventListener("touchstart",ee),G(),clearInterval(Y.current)}},[eD]),et=function(e){tt(function(t){return t+e})},d.useEffect(function(){var e=eK.current;if(eW&&e){var t,r,n=!1,o=function(){g.default.cancel(t)},a=function e(){o(),t=(0,g.default)(function(){et(r),e()})},i=function(){n=!1,o()},l=function(e){!e.target.draggable&&0===e.button&&(e._virtualHandled||(e._virtualHandled=!0,n=!0))},s=function(t){if(n){var i=$(t,!1),l=e.getBoundingClientRect(),s=l.top,c=l.bottom;i<=s?(r=-S(s-i),a()):i>=c?(r=S(i-c),a()):o()}};return e.addEventListener("mousedown",l),e.ownerDocument.addEventListener("mouseup",i),e.ownerDocument.addEventListener("mousemove",s),e.ownerDocument.addEventListener("dragend",i),function(){e.removeEventListener("mousedown",l),e.ownerDocument.removeEventListener("mouseup",i),e.ownerDocument.removeEventListener("mousemove",s),e.ownerDocument.removeEventListener("dragend",i),o()}}},[eW]),(0,u.default)(function(){function e(e){var t=tw&&e.detail<0,r=tC&&e.detail>0;!eD||t||r||e.preventDefault()}var t=eK.current;return t.addEventListener("wheel",tF,{passive:!1}),t.addEventListener("DOMMouseScroll",tN,{passive:!0}),t.addEventListener("MozMousePixelScroll",e,{passive:!1}),function(){t.removeEventListener("wheel",tF),t.removeEventListener("DOMMouseScroll",tN),t.removeEventListener("MozMousePixelScroll",e)}},[eD,tw,tC]),(0,u.default)(function(){if(e$){var e=tT(e4);e6(e),tO({x:e})}},[tf.width,e$]);var tR=function(){var e,t;null==(e=tm.current)||e.delayHidden(),null==(t=tg.current)||t.delayHidden()},tM=(er=function(){return ez(!0)},en=d.useRef(),eo=d.useState(null),ei=(ea=(0,a.default)(eo,2))[0],el=ea[1],(0,u.default)(function(){if(ei&&ei.times<10){if(!eK.current)return void el(function(e){return(0,n.default)({},e)});er();var e=ei.targetAlign,t=ei.originAlign,r=ei.index,o=ei.offset,a=eK.current.clientHeight,i=!1,l=e,s=null;if(a){for(var c=e||t,u=0,d=0,f=0,p=Math.min(eq.length-1,r),m=0;m<=p;m+=1){var g=eR(eq[m]);d=u;var h=eL.get(g);u=f=d+(void 0===h?eh:h)}for(var v="top"===c?o:a-o,y=p;y>=0;y-=1){var b=eR(eq[y]),w=eL.get(b);if(void 0===w){i=!0;break}if((v-=w)<=0)break}switch(c){case"top":s=d-o;break;case"bottom":s=f-a+o;break;default:var C=eK.current.scrollTop;dC+a&&(l="bottom")}null!==s&&tt(s),s!==ei.lastTop&&(i=!0)}i&&el((0,n.default)((0,n.default)({},ei),{},{times:ei.times+1,targetAlign:l,lastTop:s}))}},[ei,eK.current]),function(e){if(null==e)return void tR();if(g.default.cancel(en.current),"number"==typeof e)tt(e);else if(e&&"object"===(0,r.default)(e)){var t,n=e.align;t="index"in e?e.index:eq.findIndex(function(t){return eR(t)===e.key});var o=e.offset;el({times:0,index:t,offset:void 0===o?0:o,originAlign:n})}});d.useImperativeHandle(y,function(){return{nativeElement:eJ.current,getScrollInfo:tE,scrollTo:function(e){e&&"object"===(0,r.default)(e)&&("left"in e||"top"in e)?(void 0!==e.left&&e6(tT(e.left)),tM(e.top)):tM(e)}}}),(0,u.default)(function(){ej&&ej(eq.slice(tl,ts+1),eq)},[tl,ts,eq]);var tA=(es=d.useMemo(function(){return[new Map,[]]},[eq,eL.id,eh]),eu=(ec=(0,a.default)(es,2))[0],ed=ec[1],function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e,r=eu.get(e),n=eu.get(t);if(void 0===r||void 0===n)for(var o=eq.length,a=ed.length;aeg&&d.createElement(E,{ref:tm,prefixCls:ep,scrollOffset:eZ,scrollRange:ti,rtl:eU,onScroll:tj,onStartMove:e9,onStopMove:te,spinSize:tv,containerSize:tf.height,style:null==eP?void 0:eP.verticalScrollBar,thumbStyle:null==eP?void 0:eP.verticalScrollBarThumb,showScrollBar:eF}),eW&&e$>tf.width&&d.createElement(E,{ref:tg,prefixCls:ep,scrollOffset:e4,scrollRange:e$,rtl:eU,onScroll:tj,onStartMove:e9,onStopMove:te,spinSize:th,containerSize:tf.width,horizontal:!0,style:null==eP?void 0:eP.horizontalScrollBar,thumbStyle:null==eP?void 0:eP.horizontalScrollBarThumb,showScrollBar:eF}))});_.displayName="List",e.s(["default",0,_],323002)},123829,955492,869301,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(8211),n=e.i(211577),o=e.i(209428),a=e.i(392221),i=e.i(703923),l=e.i(410160),s=e.i(914949);e.i(883110);var c=e.i(271645),u=e.i(331290),d=e.i(567770),f=e.i(750756),p=e.i(343794),m=e.i(404948),g=e.i(182585),h=e.i(529681),v=e.i(244009),y=e.i(323002),b=e.i(300877),w=e.i(210803),C=e.i(266623),x=e.i(670532),S=["disabled","title","children","style","className"];function $(e){return"string"==typeof e||"number"==typeof e}var E=c.forwardRef(function(e,o){var l=(0,C.default)(),s=l.prefixCls,u=l.id,d=l.open,f=l.multiple,E=l.mode,k=l.searchValue,O=l.toggleOpen,j=l.notFoundContent,T=l.onPopupScroll,_=c.useContext(b.default),P=_.maxCount,I=_.flattenOptions,F=_.onActiveValue,N=_.defaultActiveFirstOption,R=_.onSelect,M=_.menuItemSelectedIcon,A=_.rawValues,B=_.fieldNames,z=_.virtual,L=_.direction,H=_.listHeight,D=_.listItemHeight,V=_.optionRender,W="".concat(s,"-item"),U=(0,g.default)(function(){return I},[d,I],function(e,t){return t[0]&&e[1]!==t[1]}),G=c.useRef(null),q=c.useMemo(function(){return f&&(0,x.isValidCount)(P)&&(null==A?void 0:A.size)>=P},[f,P,null==A?void 0:A.size]),K=function(e){e.preventDefault()},X=function(e){var t;null==(t=G.current)||t.scrollTo("number"==typeof e?{index:e}:e)},J=c.useCallback(function(e){return"combobox"!==E&&A.has(e)},[E,(0,r.default)(A).toString(),A.size]),Y=function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,r=U.length,n=0;n1&&void 0!==arguments[1]&&arguments[1];et(e);var r={source:t?"keyboard":"mouse"},n=U[e];n?F(n.value,e,r):F(null,-1,r)};(0,c.useEffect)(function(){er(!1!==N?Y(0):-1)},[U.length,k]);var en=c.useCallback(function(e){return"combobox"===E?String(e).toLowerCase()===k.toLowerCase():A.has(e)},[E,k,(0,r.default)(A).toString(),A.size]);(0,c.useEffect)(function(){var e,t=setTimeout(function(){if(!f&&d&&1===A.size){var e=Array.from(A)[0],t=U.findIndex(function(t){var r=t.data;return k?String(r.value).startsWith(k):r.value===e});-1!==t&&(er(t),X(t))}});return d&&(null==(e=G.current)||e.scrollTo(void 0)),function(){return clearTimeout(t)}},[d,k]);var eo=function(e){void 0!==e&&R(e,{selected:!A.has(e)}),f||O(!1)};if(c.useImperativeHandle(o,function(){return{onKeyDown:function(e){var t=e.which,r=e.ctrlKey;switch(t){case m.default.N:case m.default.P:case m.default.UP:case m.default.DOWN:var n=0;if(t===m.default.UP?n=-1:t===m.default.DOWN?n=1:/(mac\sos|macintosh)/i.test(navigator.appVersion)&&r&&(t===m.default.N?n=1:t===m.default.P&&(n=-1)),0!==n){var o=Y(ee+n,n);X(o),er(o,!0)}break;case m.default.TAB:case m.default.ENTER:var a,i=U[ee];!i||null!=i&&null!=(a=i.data)&&a.disabled||q?eo(void 0):eo(i.value),d&&e.preventDefault();break;case m.default.ESC:O(!1),d&&e.stopPropagation()}},onKeyUp:function(){},scrollTo:function(e){X(e)}}}),0===U.length)return c.createElement("div",{role:"listbox",id:"".concat(u,"_list"),className:"".concat(W,"-empty"),onMouseDown:K},j);var ea=Object.keys(B).map(function(e){return B[e]}),ei=function(e){return e.label};function el(e,t){return{role:e.group?"presentation":"option",id:"".concat(u,"_list_").concat(t)}}var es=function(e){var r=U[e];if(!r)return null;var n=r.data||{},o=n.value,a=r.group,i=(0,v.default)(n,!0),l=ei(r);return r?c.createElement("div",(0,t.default)({"aria-label":"string"!=typeof l||a?null:l},i,{key:e},el(r,e),{"aria-selected":en(o)}),o):null},ec={role:"listbox",id:"".concat(u,"_list")};return c.createElement(c.Fragment,null,z&&c.createElement("div",(0,t.default)({},ec,{style:{height:0,width:0,overflow:"hidden"}}),es(ee-1),es(ee),es(ee+1)),c.createElement(y.default,{itemKey:"key",ref:G,data:U,height:H,itemHeight:D,fullHeight:!1,onMouseDown:K,onScroll:T,virtual:z,direction:L,innerProps:z?null:ec},function(e,r){var o=e.group,a=e.groupOption,l=e.data,s=e.label,u=e.value,d=l.key;if(o){var f,m=null!=(f=l.title)?f:$(s)?s.toString():void 0;return c.createElement("div",{className:(0,p.default)(W,"".concat(W,"-group"),l.className),title:m},void 0!==s?s:d)}var g=l.disabled,y=l.title,b=(l.children,l.style),C=l.className,x=(0,i.default)(l,S),E=(0,h.default)(x,ea),k=J(u),O=g||!k&&q,j="".concat(W,"-option"),T=(0,p.default)(W,j,C,(0,n.default)((0,n.default)((0,n.default)((0,n.default)({},"".concat(j,"-grouped"),a),"".concat(j,"-active"),ee===r&&!O),"".concat(j,"-disabled"),O),"".concat(j,"-selected"),k)),_=ei(e),P=!M||"function"==typeof M||k,I="number"==typeof _?_:_||u,F=$(I)?I.toString():void 0;return void 0!==y&&(F=y),c.createElement("div",(0,t.default)({},(0,v.default)(E),z?{}:el(e,r),{"aria-selected":en(u),className:T,title:F,onMouseMove:function(){ee===r||O||er(r)},onClick:function(){O||eo(u)},style:b}),c.createElement("div",{className:"".concat(j,"-content")},"function"==typeof V?V(e,{index:r}):I),c.isValidElement(M)||k,P&&c.createElement(w.default,{className:"".concat(W,"-option-state"),customizeIcon:M,customizeIconProps:{value:u,disabled:O,isSelected:k}},k?"✓":null))}))});let k=function(e,t){var r=c.useRef({values:new Map,options:new Map});return[c.useMemo(function(){var n=r.current,a=n.values,i=n.options,l=e.map(function(e){if(void 0===e.label){var t;return(0,o.default)((0,o.default)({},e),{},{label:null==(t=a.get(e.value))?void 0:t.label})}return e}),s=new Map,c=new Map;return l.forEach(function(e){s.set(e.value,e),c.set(e.value,t.get(e.value)||i.get(e.value))}),r.current.values=s,r.current.options=c,l},[e,t]),c.useCallback(function(e){return t.get(e)||r.current.options.get(e)},[t])]};var O=e.i(207427);function j(e,t){return(0,O.toArray)(e).join("").toUpperCase().includes(t)}var T=e.i(654310),_=0,P=(0,T.default)(),I=e.i(876556),F=["children","value"],N=["children"];function R(e){var t=c.useRef();return t.current=e,c.useCallback(function(){return t.current.apply(t,arguments)},[])}var M=["id","mode","prefixCls","backfill","fieldNames","inputValue","searchValue","onSearch","autoClearSearchValue","onSelect","onDeselect","dropdownMatchSelectWidth","filterOption","filterSort","optionFilterProp","optionLabelProp","options","optionRender","children","defaultActiveFirstOption","menuItemSelectedIcon","virtual","direction","listHeight","listItemHeight","labelRender","value","defaultValue","labelInValue","onChange","maxCount"],A=["inputValue"],B=c.forwardRef(function(e,d){var f,p,m,g,h,v=e.id,y=e.mode,w=e.prefixCls,C=e.backfill,S=e.fieldNames,$=e.inputValue,T=e.searchValue,B=e.onSearch,z=e.autoClearSearchValue,L=void 0===z||z,H=e.onSelect,D=e.onDeselect,V=e.dropdownMatchSelectWidth,W=void 0===V||V,U=e.filterOption,G=e.filterSort,q=e.optionFilterProp,K=e.optionLabelProp,X=e.options,J=e.optionRender,Y=e.children,Q=e.defaultActiveFirstOption,Z=e.menuItemSelectedIcon,ee=e.virtual,et=e.direction,er=e.listHeight,en=void 0===er?200:er,eo=e.listItemHeight,ea=void 0===eo?20:eo,ei=e.labelRender,el=e.value,es=e.defaultValue,ec=e.labelInValue,eu=e.onChange,ed=e.maxCount,ef=(0,i.default)(e,M),ep=(f=c.useState(),m=(p=(0,a.default)(f,2))[0],g=p[1],c.useEffect(function(){var e;g("rc_select_".concat((P?(e=_,_+=1):e="TEST_OR_SSR",e)))},[]),v||m),em=(0,u.isMultiple)(y),eg=!!(!X&&Y),eh=c.useMemo(function(){return(void 0!==U||"combobox"!==y)&&U},[U,y]),ev=c.useMemo(function(){return(0,x.fillFieldNames)(S,eg)},[JSON.stringify(S),eg]),ey=(0,s.default)("",{value:void 0!==T?T:$,postState:function(e){return e||""}}),eb=(0,a.default)(ey,2),ew=eb[0],eC=eb[1],ex=c.useMemo(function(){var e=X;X||(e=function e(t){var r=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return(0,I.default)(t).map(function(t,n){if(!c.isValidElement(t)||!t.type)return null;var a,l,s,u,d,f=t.type.isSelectOptGroup,p=t.key,m=t.props,g=m.children,h=(0,i.default)(m,N);return r||!f?(a=t.key,s=(l=t.props).children,u=l.value,d=(0,i.default)(l,F),(0,o.default)({key:a,value:void 0!==u?u:a,children:s},d)):(0,o.default)((0,o.default)({key:"__RC_SELECT_GRP__".concat(null===p?n:p,"__"),label:p},h),{},{options:e(g)})}).filter(function(e){return e})}(Y));var t=new Map,r=new Map,n=function(e,t,r){r&&"string"==typeof r&&e.set(t[r],t)};return!function e(o){for(var a=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=0;i0?e(t.options):t.options}):t})}(ez):ez},[ez,G,ew]),eH=c.useMemo(function(){return(0,x.flattenOptions)(eL,{fieldNames:ev,childrenAsData:eg})},[eL,ev,eg]),eD=function(e){var t=ek(e);if(e_(t),eu&&(t.length!==eF.length||t.some(function(e,t){var r;return(null==(r=eF[t])?void 0:r.value)!==(null==e?void 0:e.value)}))){var r=ec?t:t.map(function(e){return e.value}),n=t.map(function(e){return(0,x.injectPropsWithOption)(eN(e.value))});eu(em?r:r[0],em?n:n[0])}},eV=c.useState(null),eW=(0,a.default)(eV,2),eU=eW[0],eG=eW[1],eq=c.useState(0),eK=(0,a.default)(eq,2),eX=eK[0],eJ=eK[1],eY=void 0!==Q?Q:"combobox"!==y,eQ=c.useCallback(function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=r.source;eJ(t),C&&"combobox"===y&&null!==e&&"keyboard"===(void 0===n?"keyboard":n)&&eG(String(e))},[C,y]),eZ=function(e,t,r){var n=function(){var t,r=eN(e);return[ec?{label:null==r?void 0:r[ev.label],value:e,key:null!=(t=null==r?void 0:r.key)?t:e}:e,(0,x.injectPropsWithOption)(r)]};if(t&&H){var o=n(),i=(0,a.default)(o,2);H(i[0],i[1])}else if(!t&&D&&"clear"!==r){var l=n(),s=(0,a.default)(l,2);D(s[0],s[1])}},e0=R(function(e,t){var n=!em||t.selected;eD(n?em?[].concat((0,r.default)(eF),[e]):[e]:eF.filter(function(t){return t.value!==e})),eZ(e,n),"combobox"===y?eG(""):(!u.isMultiple||L)&&(eC(""),eG(""))}),e1=c.useMemo(function(){var e=!1!==ee&&!1!==W;return(0,o.default)((0,o.default)({},ex),{},{flattenOptions:eH,onActiveValue:eQ,defaultActiveFirstOption:eY,onSelect:e0,menuItemSelectedIcon:Z,rawValues:eM,fieldNames:ev,virtual:e,direction:et,listHeight:en,listItemHeight:ea,childrenAsData:eg,maxCount:ed,optionRender:J})},[ed,ex,eH,eQ,eY,e0,Z,eM,ev,ee,W,et,en,ea,eg,J]);return c.createElement(b.default.Provider,{value:e1},c.createElement(u.default,(0,t.default)({},ef,{id:ep,prefixCls:void 0===w?"rc-select":w,ref:d,omitDomProps:A,mode:y,displayValues:eR,onDisplayValuesChange:function(e,t){eD(e);var r=t.type,n=t.values;("remove"===r||"clear"===r)&&n.forEach(function(e){eZ(e.value,!1,r)})},direction:et,searchValue:ew,onSearch:function(e,t){if(eC(e),eG(null),"submit"===t.source){var n=(e||"").trim();n&&(eD(Array.from(new Set([].concat((0,r.default)(eM),[n])))),eZ(n,!0),eC(""));return}"blur"!==t.source&&("combobox"===y&&eD(e),null==B||B(e))},autoClearSearchValue:L,onSearchSplit:function(e){var t=e;"tags"!==y&&(t=e.map(function(e){var t=e$.get(e);return null==t?void 0:t.value}).filter(function(e){return void 0!==e}));var n=Array.from(new Set([].concat((0,r.default)(eM),(0,r.default)(t))));eD(n),n.forEach(function(e){eZ(e,!0)})},dropdownMatchSelectWidth:W,OptionList:E,emptyOptions:!eH.length,activeValue:eU,activeDescendantId:"".concat(ep,"_list_").concat(eX)})))});B.Option=f.default,B.OptGroup=d.default,e.s(["default",0,B],123829),e.s(["OptGroup",()=>d.default],955492),e.s(["Option",()=>f.default],869301)},805484,e=>{"use strict";var t=e.i(271645),r=e.i(914949),n=e.i(609587),o=e.i(242064);function a(e){return r=>t.createElement(n.default,{theme:{token:{motion:!1,zIndexPopupBase:0}}},t.createElement(e,Object.assign({},r)))}e.s(["default",0,(e,n,i,l,s)=>a(a=>{let{prefixCls:c,style:u}=a,d=t.useRef(null),[f,p]=t.useState(0),[m,g]=t.useState(0),[h,v]=(0,r.default)(!1,{value:a.open}),{getPrefixCls:y}=t.useContext(o.ConfigContext),b=y(l||"select",c);t.useEffect(()=>{if(v(!0),"u">typeof ResizeObserver){let e=new ResizeObserver(e=>{let t=e[0].target;p(t.offsetHeight+8),g(t.offsetWidth)}),t=setInterval(()=>{var r;let n=s?`.${s(b)}`:`.${b}-dropdown`,o=null==(r=d.current)?void 0:r.querySelector(n);o&&(clearInterval(t),e.observe(o))},10);return()=>{clearInterval(t),e.disconnect()}}},[b]);let w=Object.assign(Object.assign({},a),{style:Object.assign(Object.assign({},u),{margin:0}),open:h,visible:h,getPopupContainer:()=>d.current});return i&&(w=i(w)),n&&Object.assign(w,{[n]:{overflow:{adjustX:!1,adjustY:!1}}}),t.createElement("div",{ref:d,style:{paddingBottom:f,position:"relative",minWidth:m}},t.createElement(e,Object.assign({},w)))}),"withPureRenderTheme",()=>a])},616303,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(242064),o=e.i(408850);e.i(262370);var a=e.i(135551),i=e.i(104458),l=e.i(246422),s=e.i(838378);let c=(0,l.genStyleHooks)("Empty",e=>{let{componentCls:t,controlHeightLG:r,calc:n}=e;return(e=>{let{componentCls:t,margin:r,marginXS:n,marginXL:o,fontSize:a,lineHeight:i}=e;return{[t]:{marginInline:n,fontSize:a,lineHeight:i,textAlign:"center",[`${t}-image`]:{height:e.emptyImgHeight,marginBottom:n,opacity:e.opacityImage,img:{height:"100%"},svg:{maxWidth:"100%",height:"100%",margin:"auto"}},[`${t}-description`]:{color:e.colorTextDescription},[`${t}-footer`]:{marginTop:r},"&-normal":{marginBlock:o,color:e.colorTextDescription,[`${t}-description`]:{color:e.colorTextDescription},[`${t}-image`]:{height:e.emptyImgHeightMD}},"&-small":{marginBlock:n,color:e.colorTextDescription,[`${t}-image`]:{height:e.emptyImgHeightSM}}}}})((0,s.mergeToken)(e,{emptyImgCls:`${t}-img`,emptyImgHeight:n(r).mul(2.5).equal(),emptyImgHeightMD:r,emptyImgHeightSM:n(r).mul(.875).equal()}))});var u=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 d=t.createElement(()=>{let[,e]=(0,i.useToken)(),[r]=(0,o.useLocale)("Empty"),n=new a.FastColor(e.colorBgBase).toHsl().l<.5?{opacity:.65}:{};return t.createElement("svg",{style:n,width:"184",height:"152",viewBox:"0 0 184 152",xmlns:"http://www.w3.org/2000/svg"},t.createElement("title",null,(null==r?void 0:r.description)||"Empty"),t.createElement("g",{fill:"none",fillRule:"evenodd"},t.createElement("g",{transform:"translate(24 31.67)"},t.createElement("ellipse",{fillOpacity:".8",fill:"#F5F5F7",cx:"67.797",cy:"106.89",rx:"67.797",ry:"12.668"}),t.createElement("path",{d:"M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z",fill:"#AEB8C2"}),t.createElement("path",{d:"M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z",fill:"url(#linearGradient-1)",transform:"translate(13.56)"}),t.createElement("path",{d:"M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z",fill:"#F5F5F7"}),t.createElement("path",{d:"M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z",fill:"#DCE0E6"})),t.createElement("path",{d:"M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z",fill:"#DCE0E6"}),t.createElement("g",{transform:"translate(149.65 15.383)",fill:"#FFF"},t.createElement("ellipse",{cx:"20.654",cy:"3.167",rx:"2.849",ry:"2.815"}),t.createElement("path",{d:"M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"}))))},null),f=t.createElement(()=>{let[,e]=(0,i.useToken)(),[r]=(0,o.useLocale)("Empty"),{colorFill:n,colorFillTertiary:l,colorFillQuaternary:s,colorBgContainer:c}=e,{borderColor:u,shadowColor:d,contentColor:f}=(0,t.useMemo)(()=>({borderColor:new a.FastColor(n).onBackground(c).toHexString(),shadowColor:new a.FastColor(l).onBackground(c).toHexString(),contentColor:new a.FastColor(s).onBackground(c).toHexString()}),[n,l,s,c]);return t.createElement("svg",{width:"64",height:"41",viewBox:"0 0 64 41",xmlns:"http://www.w3.org/2000/svg"},t.createElement("title",null,(null==r?void 0:r.description)||"Empty"),t.createElement("g",{transform:"translate(0 1)",fill:"none",fillRule:"evenodd"},t.createElement("ellipse",{fill:d,cx:"32",cy:"33",rx:"32",ry:"7"}),t.createElement("g",{fillRule:"nonzero",stroke:u},t.createElement("path",{d:"M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"}),t.createElement("path",{d:"M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z",fill:f}))))},null),p=e=>{var a;let{className:i,rootClassName:l,prefixCls:s,image:p,description:m,children:g,imageStyle:h,style:v,classNames:y,styles:b}=e,w=u(e,["className","rootClassName","prefixCls","image","description","children","imageStyle","style","classNames","styles"]),{getPrefixCls:C,direction:x,className:S,style:$,classNames:E,styles:k,image:O}=(0,n.useComponentConfig)("empty"),j=C("empty",s),[T,_,P]=c(j),[I]=(0,o.useLocale)("Empty"),F=void 0!==m?m:null==I?void 0:I.description,N="string"==typeof F?F:"empty",R=null!=(a=null!=p?p:O)?a:d,M=null;return M="string"==typeof R?t.createElement("img",{draggable:!1,alt:N,src:R}):R,T(t.createElement("div",Object.assign({className:(0,r.default)(_,P,j,S,{[`${j}-normal`]:R===f,[`${j}-rtl`]:"rtl"===x},i,l,E.root,null==y?void 0:y.root),style:Object.assign(Object.assign(Object.assign(Object.assign({},k.root),$),null==b?void 0:b.root),v)},w),t.createElement("div",{className:(0,r.default)(`${j}-image`,E.image,null==y?void 0:y.image),style:Object.assign(Object.assign(Object.assign({},h),k.image),null==b?void 0:b.image)},M),F&&t.createElement("div",{className:(0,r.default)(`${j}-description`,E.description,null==y?void 0:y.description),style:Object.assign(Object.assign({},k.description),null==b?void 0:b.description)},F),g&&t.createElement("div",{className:(0,r.default)(`${j}-footer`,E.footer,null==y?void 0:y.footer),style:Object.assign(Object.assign({},k.footer),null==b?void 0:b.footer)},g)))};p.PRESENTED_IMAGE_DEFAULT=d,p.PRESENTED_IMAGE_SIMPLE=f,e.s(["default",0,p],616303)},721132,e=>{"use strict";var t=e.i(271645),r=e.i(242064),n=e.i(616303);e.s(["default",0,e=>{let{componentName:o}=e,{getPrefixCls:a}=(0,t.useContext)(r.ConfigContext),i=a("empty");switch(o){case"Table":case"List":return t.default.createElement(n.default,{image:n.default.PRESENTED_IMAGE_SIMPLE});case"Select":case"TreeSelect":case"Cascader":case"Transfer":case"Mentions":return t.default.createElement(n.default,{image:n.default.PRESENTED_IMAGE_SIMPLE,className:`${i}-small`});case"Table.filter":return null;default:return t.default.createElement(n.default,null)}}])},85566,e=>{"use strict";e.s(["default",0,function(e,t){let r;return e||{bottomLeft:Object.assign(Object.assign({},r={overflow:{adjustX:!0,adjustY:!0,shiftY:!0},htmlRegion:"scroll"===t?"scroll":"visible",dynamicInset:!0}),{points:["tl","bl"],offset:[0,4]}),bottomRight:Object.assign(Object.assign({},r),{points:["tr","br"],offset:[0,4]}),topLeft:Object.assign(Object.assign({},r),{points:["bl","tl"],offset:[0,-4]}),topRight:Object.assign(Object.assign({},r),{points:["br","tr"],offset:[0,-4]})}}])},777489,e=>{"use strict";e.i(296059);var t=e.i(694758),r=e.i(402366);let n=new t.Keyframes("antMoveDownIn",{"0%":{transform:"translate3d(0, 100%, 0)",transformOrigin:"0 0",opacity:0},"100%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1}}),o=new t.Keyframes("antMoveDownOut",{"0%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1},"100%":{transform:"translate3d(0, 100%, 0)",transformOrigin:"0 0",opacity:0}}),a=new t.Keyframes("antMoveLeftIn",{"0%":{transform:"translate3d(-100%, 0, 0)",transformOrigin:"0 0",opacity:0},"100%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1}}),i=new t.Keyframes("antMoveLeftOut",{"0%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1},"100%":{transform:"translate3d(-100%, 0, 0)",transformOrigin:"0 0",opacity:0}}),l=new t.Keyframes("antMoveRightIn",{"0%":{transform:"translate3d(100%, 0, 0)",transformOrigin:"0 0",opacity:0},"100%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1}}),s=new t.Keyframes("antMoveRightOut",{"0%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1},"100%":{transform:"translate3d(100%, 0, 0)",transformOrigin:"0 0",opacity:0}}),c={"move-up":{inKeyframes:new t.Keyframes("antMoveUpIn",{"0%":{transform:"translate3d(0, -100%, 0)",transformOrigin:"0 0",opacity:0},"100%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1}}),outKeyframes:new t.Keyframes("antMoveUpOut",{"0%":{transform:"translate3d(0, 0, 0)",transformOrigin:"0 0",opacity:1},"100%":{transform:"translate3d(0, -100%, 0)",transformOrigin:"0 0",opacity:0}})},"move-down":{inKeyframes:n,outKeyframes:o},"move-left":{inKeyframes:a,outKeyframes:i},"move-right":{inKeyframes:l,outKeyframes:s}};e.s(["initMoveMotion",0,(e,t)=>{let{antCls:n}=e,o=`${n}-${t}`,{inKeyframes:a,outKeyframes:i}=c[t];return[(0,r.initMotion)(o,a,i,e.motionDurationMid),{[` + ${o}-enter, + ${o}-appear + `]:{opacity:0,animationTimingFunction:e.motionEaseOutCirc},[`${o}-leave`]:{animationTimingFunction:e.motionEaseInOutCirc}}]}])},664142,e=>{"use strict";e.i(296059);var t=e.i(694758),r=e.i(402366);let n=new t.Keyframes("antSlideUpIn",{"0%":{transform:"scaleY(0.8)",transformOrigin:"0% 0%",opacity:0},"100%":{transform:"scaleY(1)",transformOrigin:"0% 0%",opacity:1}}),o=new t.Keyframes("antSlideUpOut",{"0%":{transform:"scaleY(1)",transformOrigin:"0% 0%",opacity:1},"100%":{transform:"scaleY(0.8)",transformOrigin:"0% 0%",opacity:0}}),a=new t.Keyframes("antSlideDownIn",{"0%":{transform:"scaleY(0.8)",transformOrigin:"100% 100%",opacity:0},"100%":{transform:"scaleY(1)",transformOrigin:"100% 100%",opacity:1}}),i=new t.Keyframes("antSlideDownOut",{"0%":{transform:"scaleY(1)",transformOrigin:"100% 100%",opacity:1},"100%":{transform:"scaleY(0.8)",transformOrigin:"100% 100%",opacity:0}}),l={"slide-up":{inKeyframes:n,outKeyframes:o},"slide-down":{inKeyframes:a,outKeyframes:i},"slide-left":{inKeyframes:new t.Keyframes("antSlideLeftIn",{"0%":{transform:"scaleX(0.8)",transformOrigin:"0% 0%",opacity:0},"100%":{transform:"scaleX(1)",transformOrigin:"0% 0%",opacity:1}}),outKeyframes:new t.Keyframes("antSlideLeftOut",{"0%":{transform:"scaleX(1)",transformOrigin:"0% 0%",opacity:1},"100%":{transform:"scaleX(0.8)",transformOrigin:"0% 0%",opacity:0}})},"slide-right":{inKeyframes:new t.Keyframes("antSlideRightIn",{"0%":{transform:"scaleX(0.8)",transformOrigin:"100% 0%",opacity:0},"100%":{transform:"scaleX(1)",transformOrigin:"100% 0%",opacity:1}}),outKeyframes:new t.Keyframes("antSlideRightOut",{"0%":{transform:"scaleX(1)",transformOrigin:"100% 0%",opacity:1},"100%":{transform:"scaleX(0.8)",transformOrigin:"100% 0%",opacity:0}})}};e.s(["initSlideMotion",0,(e,t)=>{let{antCls:n}=e,o=`${n}-${t}`,{inKeyframes:a,outKeyframes:i}=l[t];return[(0,r.initMotion)(o,a,i,e.motionDurationMid),{[` + ${o}-enter, + ${o}-appear + `]:{transform:"scale(0)",transformOrigin:"0% 0%",opacity:0,animationTimingFunction:e.motionEaseOutQuint,"&-prepare":{transform:"scale(1)"}},[`${o}-leave`]:{animationTimingFunction:e.motionEaseInQuint}}]},"slideDownIn",0,a,"slideDownOut",0,i,"slideUpIn",0,n,"slideUpOut",0,o])},950302,e=>{"use strict";var t=e.i(183293),r=e.i(372409),n=e.i(246422),o=e.i(838378),a=e.i(777489),i=e.i(664142);let l=e=>{let{optionHeight:t,optionFontSize:r,optionLineHeight:n,optionPadding:o}=e;return{position:"relative",display:"block",minHeight:t,padding:o,color:e.colorText,fontWeight:"normal",fontSize:r,lineHeight:n,boxSizing:"border-box"}};e.i(296059);var s=e.i(915654);function c(e,r){let{componentCls:n}=e,o=r?`${n}-${r}`:"",a={[`${n}-multiple${o}`]:{fontSize:e.fontSize,[`${n}-selector`]:{[`${n}-show-search&`]:{cursor:"text"}},[` + &${n}-show-arrow ${n}-selector, + &${n}-allow-clear ${n}-selector + `]:{paddingInlineEnd:e.calc(e.fontSizeIcon).add(e.controlPaddingHorizontal).equal()}}};return[((e,r)=>{let{componentCls:n,INTERNAL_FIXED_ITEM_MARGIN:o}=e,a=`${n}-selection-overflow`,i=e.multipleSelectItemHeight,l=(e=>{let{multipleSelectItemHeight:t,selectHeight:r,lineWidth:n}=e;return e.calc(r).sub(t).div(2).sub(n).equal()})(e),c=r?`${n}-${r}`:"",u=(e=>{let{multipleSelectItemHeight:t,paddingXXS:r,lineWidth:n,INTERNAL_FIXED_ITEM_MARGIN:o}=e,a=e.max(e.calc(r).sub(n).equal(),0),i=e.max(e.calc(a).sub(o).equal(),0);return{basePadding:a,containerPadding:i,itemHeight:(0,s.unit)(t),itemLineHeight:(0,s.unit)(e.calc(t).sub(e.calc(e.lineWidth).mul(2)).equal())}})(e);return{[`${n}-multiple${c}`]:Object.assign(Object.assign({},(e=>{let{componentCls:r,iconCls:n,borderRadiusSM:o,motionDurationSlow:a,paddingXS:i,multipleItemColorDisabled:l,multipleItemBorderColorDisabled:s,colorIcon:c,colorIconHover:u,INTERNAL_FIXED_ITEM_MARGIN:d}=e;return{[`${r}-selection-overflow`]:{position:"relative",display:"flex",flex:"auto",flexWrap:"wrap",maxWidth:"100%","&-item":{flex:"none",alignSelf:"center",maxWidth:"calc(100% - 4px)",display:"inline-flex"},[`${r}-selection-item`]:{display:"flex",alignSelf:"center",flex:"none",boxSizing:"border-box",maxWidth:"100%",marginBlock:d,borderRadius:o,cursor:"default",transition:`font-size ${a}, line-height ${a}, height ${a}`,marginInlineEnd:e.calc(d).mul(2).equal(),paddingInlineStart:i,paddingInlineEnd:e.calc(i).div(2).equal(),[`${r}-disabled&`]:{color:l,borderColor:s,cursor:"not-allowed"},"&-content":{display:"inline-block",marginInlineEnd:e.calc(i).div(2).equal(),overflow:"hidden",whiteSpace:"pre",textOverflow:"ellipsis"},"&-remove":Object.assign(Object.assign({},(0,t.resetIcon)()),{display:"inline-flex",alignItems:"center",color:c,fontWeight:"bold",fontSize:10,lineHeight:"inherit",cursor:"pointer",[`> ${n}`]:{verticalAlign:"-0.2em"},"&:hover":{color:u}})}}}})(e)),{[`${n}-selector`]:{display:"flex",alignItems:"center",width:"100%",height:"100%",paddingInline:u.basePadding,paddingBlock:u.containerPadding,borderRadius:e.borderRadius,[`${n}-disabled&`]:{background:e.multipleSelectorBgDisabled,cursor:"not-allowed"},"&:after":{display:"inline-block",width:0,margin:`${(0,s.unit)(o)} 0`,lineHeight:(0,s.unit)(i),visibility:"hidden",content:'"\\a0"'}},[`${n}-selection-item`]:{height:u.itemHeight,lineHeight:(0,s.unit)(u.itemLineHeight)},[`${n}-selection-wrap`]:{alignSelf:"flex-start","&:after":{lineHeight:(0,s.unit)(i),marginBlock:o}},[`${n}-prefix`]:{marginInlineStart:e.calc(e.inputPaddingHorizontalBase).sub(u.basePadding).equal()},[`${a}-item + ${a}-item, + ${n}-prefix + ${n}-selection-wrap + `]:{[`${n}-selection-search`]:{marginInlineStart:0},[`${n}-selection-placeholder`]:{insetInlineStart:0}},[`${a}-item-suffix`]:{minHeight:u.itemHeight,marginBlock:o},[`${n}-selection-search`]:{display:"inline-flex",position:"relative",maxWidth:"100%",marginInlineStart:e.calc(e.inputPaddingHorizontalBase).sub(l).equal(),[` + &-input, + &-mirror + `]:{height:i,fontFamily:e.fontFamily,lineHeight:(0,s.unit)(i),transition:`all ${e.motionDurationSlow}`},"&-input":{width:"100%",minWidth:4.1},"&-mirror":{position:"absolute",top:0,insetInlineStart:0,insetInlineEnd:"auto",zIndex:999,whiteSpace:"pre",visibility:"hidden"}},[`${n}-selection-placeholder`]:{position:"absolute",top:"50%",insetInlineStart:e.calc(e.inputPaddingHorizontalBase).sub(u.basePadding).equal(),insetInlineEnd:e.inputPaddingHorizontalBase,transform:"translateY(-50%)",transition:`all ${e.motionDurationSlow}`}})}})(e,r),a]}function u(e,r){let{componentCls:n,inputPaddingHorizontalBase:o,borderRadius:a}=e,i=e.calc(e.controlHeight).sub(e.calc(e.lineWidth).mul(2)).equal(),l=r?`${n}-${r}`:"";return{[`${n}-single${l}`]:{fontSize:e.fontSize,height:e.controlHeight,[`${n}-selector`]:Object.assign(Object.assign({},(0,t.resetComponent)(e,!0)),{display:"flex",borderRadius:a,flex:"1 1 auto",[`${n}-selection-wrap:after`]:{lineHeight:(0,s.unit)(i)},[`${n}-selection-search`]:{position:"absolute",inset:0,width:"100%","&-input":{width:"100%",WebkitAppearance:"textfield"}},[` + ${n}-selection-item, + ${n}-selection-placeholder + `]:{display:"block",padding:0,lineHeight:(0,s.unit)(i),transition:`all ${e.motionDurationSlow}, visibility 0s`,alignSelf:"center"},[`${n}-selection-placeholder`]:{transition:"none",pointerEvents:"none"},[`&:after,${n}-selection-item:empty:after,${n}-selection-placeholder:empty:after`]:{display:"inline-block",width:0,visibility:"hidden",content:'"\\a0"'}}),[` + &${n}-show-arrow ${n}-selection-item, + &${n}-show-arrow ${n}-selection-search, + &${n}-show-arrow ${n}-selection-placeholder + `]:{paddingInlineEnd:e.showArrowPaddingInlineEnd},[`&${n}-open ${n}-selection-item`]:{color:e.colorTextPlaceholder},[`&:not(${n}-customize-input)`]:{[`${n}-selector`]:{width:"100%",height:"100%",alignItems:"center",padding:`0 ${(0,s.unit)(o)}`,[`${n}-selection-search-input`]:{height:i,fontSize:e.fontSize},"&:after":{lineHeight:(0,s.unit)(i)}}},[`&${n}-customize-input`]:{[`${n}-selector`]:{"&:after":{display:"none"},[`${n}-selection-search`]:{position:"static",width:"100%"},[`${n}-selection-placeholder`]:{position:"absolute",insetInlineStart:0,insetInlineEnd:0,padding:`0 ${(0,s.unit)(o)}`,"&:after":{display:"none"}}}}}}}let d=(e,t)=>{let{componentCls:r,antCls:n,controlOutlineWidth:o}=e;return{[`&:not(${r}-customize-input) ${r}-selector`]:{border:`${(0,s.unit)(e.lineWidth)} ${e.lineType} ${t.borderColor}`,background:e.selectorBg},[`&:not(${r}-disabled):not(${r}-customize-input):not(${n}-pagination-size-changer)`]:{[`&:hover ${r}-selector`]:{borderColor:t.hoverBorderHover},[`${r}-focused& ${r}-selector`]:{borderColor:t.activeBorderColor,boxShadow:`0 0 0 ${(0,s.unit)(o)} ${t.activeOutlineColor}`,outline:0},[`${r}-prefix`]:{color:t.color}}}},f=(e,t)=>({[`&${e.componentCls}-status-${t.status}`]:Object.assign({},d(e,t))}),p=(e,t)=>{let{componentCls:r,antCls:n}=e;return{[`&:not(${r}-customize-input) ${r}-selector`]:{background:t.bg,border:`${(0,s.unit)(e.lineWidth)} ${e.lineType} transparent`,color:t.color},[`&:not(${r}-disabled):not(${r}-customize-input):not(${n}-pagination-size-changer)`]:{[`&:hover ${r}-selector`]:{background:t.hoverBg},[`${r}-focused& ${r}-selector`]:{background:e.selectorBg,borderColor:t.activeBorderColor,outline:0}}}},m=(e,t)=>({[`&${e.componentCls}-status-${t.status}`]:Object.assign({},p(e,t))}),g=(e,t)=>{let{componentCls:r,antCls:n}=e;return{[`&:not(${r}-customize-input) ${r}-selector`]:{borderWidth:`${(0,s.unit)(e.lineWidth)} 0`,borderStyle:`${e.lineType} none`,borderColor:`transparent transparent ${t.borderColor} transparent`,background:e.selectorBg,borderRadius:0},[`&:not(${r}-disabled):not(${r}-customize-input):not(${n}-pagination-size-changer)`]:{[`&:hover ${r}-selector`]:{borderColor:`transparent transparent ${t.hoverBorderHover} transparent`},[`${r}-focused& ${r}-selector`]:{borderColor:`transparent transparent ${t.activeBorderColor} transparent`,outline:0},[`${r}-prefix`]:{color:t.color}}}},h=(e,t)=>({[`&${e.componentCls}-status-${t.status}`]:Object.assign({},g(e,t))}),v=(0,n.genStyleHooks)("Select",(e,{rootPrefixCls:n})=>{let v=(0,o.mergeToken)(e,{rootPrefixCls:n,inputPaddingHorizontalBase:e.calc(e.paddingSM).sub(1).equal(),multipleSelectItemHeight:e.multipleItemHeight,selectHeight:e.controlHeight});return[(e=>{let{componentCls:n}=e;return[{[n]:{[`&${n}-in-form-item`]:{width:"100%"}}},(e=>{let{antCls:r,componentCls:n,inputPaddingHorizontalBase:o,iconCls:a}=e,i={[`${n}-clear`]:{opacity:1,background:e.colorBgBase,borderRadius:"50%"}};return{[n]:Object.assign(Object.assign({},(0,t.resetComponent)(e)),{position:"relative",display:"inline-flex",cursor:"pointer",[`&:not(${n}-customize-input) ${n}-selector`]:Object.assign(Object.assign({},(e=>{let{componentCls:t}=e;return{position:"relative",transition:`all ${e.motionDurationMid} ${e.motionEaseInOut}`,input:{cursor:"pointer"},[`${t}-show-search&`]:{cursor:"text",input:{cursor:"auto",color:"inherit",height:"100%"}},[`${t}-disabled&`]:{cursor:"not-allowed",input:{cursor:"not-allowed"}}}})(e)),(e=>{let{componentCls:t}=e;return{[`${t}-selection-search-input`]:{margin:0,padding:0,background:"transparent",border:"none",outline:"none",appearance:"none",fontFamily:"inherit","&::-webkit-search-cancel-button":{display:"none",appearance:"none"}}}})(e)),[`${n}-selection-item`]:Object.assign(Object.assign({flex:1,fontWeight:"normal",position:"relative",userSelect:"none"},t.textEllipsis),{[`> ${r}-typography`]:{display:"inline"}}),[`${n}-selection-placeholder`]:Object.assign(Object.assign({},t.textEllipsis),{flex:1,color:e.colorTextPlaceholder,pointerEvents:"none"}),[`${n}-arrow`]:Object.assign(Object.assign({},(0,t.resetIcon)()),{position:"absolute",top:"50%",insetInlineStart:"auto",insetInlineEnd:o,height:e.fontSizeIcon,marginTop:e.calc(e.fontSizeIcon).mul(-1).div(2).equal(),color:e.colorTextQuaternary,fontSize:e.fontSizeIcon,lineHeight:1,textAlign:"center",pointerEvents:"none",display:"flex",alignItems:"center",transition:`opacity ${e.motionDurationSlow} ease`,[a]:{verticalAlign:"top",transition:`transform ${e.motionDurationSlow}`,"> svg":{verticalAlign:"top"},[`&:not(${n}-suffix)`]:{pointerEvents:"auto"}},[`${n}-disabled &`]:{cursor:"not-allowed"},"> *:not(:last-child)":{marginInlineEnd:8}}),[`${n}-selection-wrap`]:{display:"flex",width:"100%",position:"relative",minWidth:0,"&:after":{content:'"\\a0"',width:0,overflow:"hidden"}},[`${n}-prefix`]:{flex:"none",marginInlineEnd:e.selectAffixPadding},[`${n}-clear`]:{position:"absolute",top:"50%",insetInlineStart:"auto",insetInlineEnd:o,zIndex:1,display:"inline-block",width:e.fontSizeIcon,height:e.fontSizeIcon,marginTop:e.calc(e.fontSizeIcon).mul(-1).div(2).equal(),color:e.colorTextQuaternary,fontSize:e.fontSizeIcon,fontStyle:"normal",lineHeight:1,textAlign:"center",textTransform:"none",cursor:"pointer",opacity:0,transition:`color ${e.motionDurationMid} ease, opacity ${e.motionDurationSlow} ease`,textRendering:"auto",transform:"translateZ(0)","&:before":{display:"block"},"&:hover":{color:e.colorIcon}},"@media(hover:none)":i,"&:hover":i}),[`${n}-status`]:{"&-error, &-warning, &-success, &-validating":{[`&${n}-has-feedback`]:{[`${n}-clear`]:{insetInlineEnd:e.calc(o).add(e.fontSize).add(e.paddingXS).equal()}}}}}})(e),function(e){let{componentCls:t}=e,r=e.calc(e.controlPaddingHorizontalSM).sub(e.lineWidth).equal();return[u(e),u((0,o.mergeToken)(e,{controlHeight:e.controlHeightSM,borderRadius:e.borderRadiusSM}),"sm"),{[`${t}-single${t}-sm`]:{[`&:not(${t}-customize-input)`]:{[`${t}-selector`]:{padding:`0 ${(0,s.unit)(r)}`},[`&${t}-show-arrow ${t}-selection-search`]:{insetInlineEnd:e.calc(r).add(e.calc(e.fontSize).mul(1.5)).equal()},[` + &${t}-show-arrow ${t}-selection-item, + &${t}-show-arrow ${t}-selection-placeholder + `]:{paddingInlineEnd:e.calc(e.fontSize).mul(1.5).equal()}}}},u((0,o.mergeToken)(e,{controlHeight:e.singleItemHeightLG,fontSize:e.fontSizeLG,borderRadius:e.borderRadiusLG}),"lg")]}(e),(e=>{let{componentCls:t}=e,r=(0,o.mergeToken)(e,{selectHeight:e.controlHeightSM,multipleSelectItemHeight:e.multipleItemHeightSM,borderRadius:e.borderRadiusSM,borderRadiusSM:e.borderRadiusXS}),n=(0,o.mergeToken)(e,{fontSize:e.fontSizeLG,selectHeight:e.controlHeightLG,multipleSelectItemHeight:e.multipleItemHeightLG,borderRadius:e.borderRadiusLG,borderRadiusSM:e.borderRadius});return[c(e),c(r,"sm"),{[`${t}-multiple${t}-sm`]:{[`${t}-selection-placeholder`]:{insetInline:e.calc(e.controlPaddingHorizontalSM).sub(e.lineWidth).equal()},[`${t}-selection-search`]:{marginInlineStart:2}}},c(n,"lg")]})(e),(e=>{let{antCls:r,componentCls:n}=e,o=`${n}-item`,s=`&${r}-slide-up-enter${r}-slide-up-enter-active`,c=`&${r}-slide-up-appear${r}-slide-up-appear-active`,u=`&${r}-slide-up-leave${r}-slide-up-leave-active`,d=`${n}-dropdown-placement-`,f=`${o}-option-selected`;return[{[`${n}-dropdown`]:Object.assign(Object.assign({},(0,t.resetComponent)(e)),{position:"absolute",top:-9999,zIndex:e.zIndexPopup,boxSizing:"border-box",padding:e.paddingXXS,overflow:"hidden",fontSize:e.fontSize,fontVariant:"initial",backgroundColor:e.colorBgElevated,borderRadius:e.borderRadiusLG,outline:"none",boxShadow:e.boxShadowSecondary,[` + ${s}${d}bottomLeft, + ${c}${d}bottomLeft + `]:{animationName:i.slideUpIn},[` + ${s}${d}topLeft, + ${c}${d}topLeft, + ${s}${d}topRight, + ${c}${d}topRight + `]:{animationName:i.slideDownIn},[`${u}${d}bottomLeft`]:{animationName:i.slideUpOut},[` + ${u}${d}topLeft, + ${u}${d}topRight + `]:{animationName:i.slideDownOut},"&-hidden":{display:"none"},[o]:Object.assign(Object.assign({},l(e)),{cursor:"pointer",transition:`background ${e.motionDurationSlow} ease`,borderRadius:e.borderRadiusSM,"&-group":{color:e.colorTextDescription,fontSize:e.fontSizeSM,cursor:"default"},"&-option":{display:"flex","&-content":Object.assign({flex:"auto"},t.textEllipsis),"&-state":{flex:"none",display:"flex",alignItems:"center"},[`&-active:not(${o}-option-disabled)`]:{backgroundColor:e.optionActiveBg},[`&-selected:not(${o}-option-disabled)`]:{color:e.optionSelectedColor,fontWeight:e.optionSelectedFontWeight,backgroundColor:e.optionSelectedBg,[`${o}-option-state`]:{color:e.colorPrimary}},"&-disabled":{[`&${o}-option-selected`]:{backgroundColor:e.colorBgContainerDisabled},color:e.colorTextDisabled,cursor:"not-allowed"},"&-grouped":{paddingInlineStart:e.calc(e.controlPaddingHorizontal).mul(2).equal()}},"&-empty":Object.assign(Object.assign({},l(e)),{color:e.colorTextDisabled})}),[`${f}:has(+ ${f})`]:{borderEndStartRadius:0,borderEndEndRadius:0,[`& + ${f}`]:{borderStartStartRadius:0,borderStartEndRadius:0}},"&-rtl":{direction:"rtl"}})},(0,i.initSlideMotion)(e,"slide-up"),(0,i.initSlideMotion)(e,"slide-down"),(0,a.initMoveMotion)(e,"move-up"),(0,a.initMoveMotion)(e,"move-down")]})(e),{[`${n}-rtl`]:{direction:"rtl"}},(0,r.genCompactItemStyle)(e,{borderElCls:`${n}-selector`,focusElCls:`${n}-focused`})]})(v),{[v.componentCls]:Object.assign(Object.assign(Object.assign(Object.assign({},{"&-outlined":Object.assign(Object.assign(Object.assign(Object.assign({},d(v,{borderColor:v.colorBorder,hoverBorderHover:v.hoverBorderColor,activeBorderColor:v.activeBorderColor,activeOutlineColor:v.activeOutlineColor,color:v.colorText})),f(v,{status:"error",borderColor:v.colorError,hoverBorderHover:v.colorErrorHover,activeBorderColor:v.colorError,activeOutlineColor:v.colorErrorOutline,color:v.colorError})),f(v,{status:"warning",borderColor:v.colorWarning,hoverBorderHover:v.colorWarningHover,activeBorderColor:v.colorWarning,activeOutlineColor:v.colorWarningOutline,color:v.colorWarning})),{[`&${v.componentCls}-disabled`]:{[`&:not(${v.componentCls}-customize-input) ${v.componentCls}-selector`]:{background:v.colorBgContainerDisabled,color:v.colorTextDisabled}},[`&${v.componentCls}-multiple ${v.componentCls}-selection-item`]:{background:v.multipleItemBg,border:`${(0,s.unit)(v.lineWidth)} ${v.lineType} ${v.multipleItemBorderColor}`}})}),{"&-filled":Object.assign(Object.assign(Object.assign(Object.assign({},p(v,{bg:v.colorFillTertiary,hoverBg:v.colorFillSecondary,activeBorderColor:v.activeBorderColor,color:v.colorText})),m(v,{status:"error",bg:v.colorErrorBg,hoverBg:v.colorErrorBgHover,activeBorderColor:v.colorError,color:v.colorError})),m(v,{status:"warning",bg:v.colorWarningBg,hoverBg:v.colorWarningBgHover,activeBorderColor:v.colorWarning,color:v.colorWarning})),{[`&${v.componentCls}-disabled`]:{[`&:not(${v.componentCls}-customize-input) ${v.componentCls}-selector`]:{borderColor:v.colorBorder,background:v.colorBgContainerDisabled,color:v.colorTextDisabled}},[`&${v.componentCls}-multiple ${v.componentCls}-selection-item`]:{background:v.colorBgContainer,border:`${(0,s.unit)(v.lineWidth)} ${v.lineType} ${v.colorSplit}`}})}),{"&-borderless":{[`${v.componentCls}-selector`]:{background:"transparent",border:`${(0,s.unit)(v.lineWidth)} ${v.lineType} transparent`},[`&${v.componentCls}-disabled`]:{[`&:not(${v.componentCls}-customize-input) ${v.componentCls}-selector`]:{color:v.colorTextDisabled}},[`&${v.componentCls}-multiple ${v.componentCls}-selection-item`]:{background:v.multipleItemBg,border:`${(0,s.unit)(v.lineWidth)} ${v.lineType} ${v.multipleItemBorderColor}`},[`&${v.componentCls}-status-error`]:{[`${v.componentCls}-prefix, ${v.componentCls}-selection-item`]:{color:v.colorError}},[`&${v.componentCls}-status-warning`]:{[`${v.componentCls}-prefix, ${v.componentCls}-selection-item`]:{color:v.colorWarning}}}}),{"&-underlined":Object.assign(Object.assign(Object.assign(Object.assign({},g(v,{borderColor:v.colorBorder,hoverBorderHover:v.hoverBorderColor,activeBorderColor:v.activeBorderColor,activeOutlineColor:v.activeOutlineColor,color:v.colorText})),h(v,{status:"error",borderColor:v.colorError,hoverBorderHover:v.colorErrorHover,activeBorderColor:v.colorError,activeOutlineColor:v.colorErrorOutline,color:v.colorError})),h(v,{status:"warning",borderColor:v.colorWarning,hoverBorderHover:v.colorWarningHover,activeBorderColor:v.colorWarning,activeOutlineColor:v.colorWarningOutline,color:v.colorWarning})),{[`&${v.componentCls}-disabled`]:{[`&:not(${v.componentCls}-customize-input) ${v.componentCls}-selector`]:{color:v.colorTextDisabled}},[`&${v.componentCls}-multiple ${v.componentCls}-selection-item`]:{background:v.multipleItemBg,border:`${(0,s.unit)(v.lineWidth)} ${v.lineType} ${v.multipleItemBorderColor}`}})})}]},e=>{let{fontSize:t,lineHeight:r,lineWidth:n,controlHeight:o,controlHeightSM:a,controlHeightLG:i,paddingXXS:l,controlPaddingHorizontal:s,zIndexPopupBase:c,colorText:u,fontWeightStrong:d,controlItemBgActive:f,controlItemBgHover:p,colorBgContainer:m,colorFillSecondary:g,colorBgContainerDisabled:h,colorTextDisabled:v,colorPrimaryHover:y,colorPrimary:b,controlOutline:w}=e,C=2*l,x=2*n,S=Math.min(o-C,o-x),$=Math.min(a-C,a-x),E=Math.min(i-C,i-x);return{INTERNAL_FIXED_ITEM_MARGIN:Math.floor(l/2),zIndexPopup:c+50,optionSelectedColor:u,optionSelectedFontWeight:d,optionSelectedBg:f,optionActiveBg:p,optionPadding:`${(o-t*r)/2}px ${s}px`,optionFontSize:t,optionLineHeight:r,optionHeight:o,selectorBg:m,clearBg:m,singleItemHeightLG:i,multipleItemBg:g,multipleItemBorderColor:"transparent",multipleItemHeight:S,multipleItemHeightSM:$,multipleItemHeightLG:E,multipleSelectorBgDisabled:h,multipleItemColorDisabled:v,multipleItemBorderColorDisabled:"transparent",showArrowPaddingInlineEnd:Math.ceil(1.25*e.fontSize),hoverBorderColor:y,activeBorderColor:b,activeOutlineColor:w,selectAffixPadding:l}},{unitless:{optionLineHeight:!0,optionSelectedFontWeight:!0}});e.s(["default",0,v],950302)},121229,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"}}]},name:"check",theme:"outlined"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["default",0,a],121229)},729151,e=>{"use strict";var t=e.i(271645),r=e.i(121229),n=e.i(726289),o=e.i(864517),a=e.i(247153),i=e.i(739295),l=e.i(38953);function s({suffixIcon:e,clearIcon:s,menuItemSelectedIcon:c,removeIcon:u,loading:d,multiple:f,hasFeedback:p,prefixCls:m,showSuffixIcon:g,feedbackIcon:h,showArrow:v,componentName:y}){let b=null!=s?s:t.createElement(n.default,null),w=r=>null!==e||p||v?t.createElement(t.Fragment,null,!1!==g&&r,p&&h):null,C=null;if(void 0!==e)C=w(e);else if(d)C=w(t.createElement(i.default,{spin:!0}));else{let e=`${m}-suffix`;C=({open:r,showSearch:n})=>r&&n?w(t.createElement(l.default,{className:e})):w(t.createElement(a.default,{className:e}))}let x=null;x=void 0!==c?c:f?t.createElement(r.default,null):null;return{clearIcon:b,suffixIcon:C,itemIcon:x,removeIcon:void 0!==u?u:t.createElement(o.default,null)}}e.s(["default",()=>s])},327494,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(123829),o=e.i(955492),a=e.i(869301),i=e.i(529681),l=e.i(122767),s=e.i(613541),c=e.i(805484),u=e.i(52956),d=e.i(242064),f=e.i(721132),p=e.i(937328),m=e.i(321883),g=e.i(517455),h=e.i(62139),v=e.i(792812),y=e.i(249616),b=e.i(104458),w=e.i(85566),C=e.i(950302),x=e.i(729151),S=e.i(617206),$=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 E="SECRET_COMBOBOX_MODE_DO_NOT_USE",k=t.forwardRef((e,o)=>{var a,c,k,O,j,T,_,P;let I,{prefixCls:F,bordered:N,className:R,rootClassName:M,getPopupContainer:A,popupClassName:B,dropdownClassName:z,listHeight:L=256,placement:H,listItemHeight:D,size:V,disabled:W,notFoundContent:U,status:G,builtinPlacements:q,dropdownMatchSelectWidth:K,popupMatchSelectWidth:X,direction:J,style:Y,allowClear:Q,variant:Z,dropdownStyle:ee,transitionName:et,tagRender:er,maxCount:en,prefix:eo,dropdownRender:ea,popupRender:ei,onDropdownVisibleChange:el,onOpenChange:es,styles:ec,classNames:eu}=e,ed=$(e,["prefixCls","bordered","className","rootClassName","getPopupContainer","popupClassName","dropdownClassName","listHeight","placement","listItemHeight","size","disabled","notFoundContent","status","builtinPlacements","dropdownMatchSelectWidth","popupMatchSelectWidth","direction","style","allowClear","variant","dropdownStyle","transitionName","tagRender","maxCount","prefix","dropdownRender","popupRender","onDropdownVisibleChange","onOpenChange","styles","classNames"]),{getPopupContainer:ef,getPrefixCls:ep,renderEmpty:em,direction:eg,virtual:eh,popupMatchSelectWidth:ev,popupOverflow:ey}=t.useContext(d.ConfigContext),{showSearch:eb,style:ew,styles:eC,className:ex,classNames:eS}=(0,d.useComponentConfig)("select"),[,e$]=(0,b.useToken)(),eE=null!=D?D:null==e$?void 0:e$.controlHeight,ek=ep("select",F),eO=ep(),ej=null!=J?J:eg,{compactSize:eT,compactItemClassnames:e_}=(0,y.useCompactItemContext)(ek,ej),[eP,eI]=(0,v.default)("select",Z,N),eF=(0,m.default)(ek),[eN,eR,eM]=(0,C.default)(ek,eF),eA=t.useMemo(()=>{let{mode:t}=e;if("combobox"!==t)return t===E?"combobox":t},[e.mode]),eB="multiple"===eA||"tags"===eA,ez=(T=e.suffixIcon,void 0!==(_=e.showArrow)?_:null!==T),eL=null!=(a=null!=X?X:K)?a:ev,eH=(null==(c=null==ec?void 0:ec.popup)?void 0:c.root)||(null==(k=eC.popup)?void 0:k.root)||ee,eD=(P=ei||ea,t.default.useMemo(()=>{if(P)return(...e)=>t.default.createElement(S.default,{space:!0},P.apply(void 0,e))},[P])),{status:eV,hasFeedback:eW,isFormItemInput:eU,feedbackIcon:eG}=t.useContext(h.FormItemInputContext),eq=(0,u.getMergedStatus)(eV,G);I=void 0!==U?U:"combobox"===eA?null:(null==em?void 0:em("Select"))||t.createElement(f.default,{componentName:"Select"});let{suffixIcon:eK,itemIcon:eX,removeIcon:eJ,clearIcon:eY}=(0,x.default)(Object.assign(Object.assign({},ed),{multiple:eB,hasFeedback:eW,feedbackIcon:eG,showSuffixIcon:ez,prefixCls:ek,componentName:"Select"})),eQ=(0,i.default)(ed,["suffixIcon","itemIcon"]),eZ=(0,r.default)((null==(O=null==eu?void 0:eu.popup)?void 0:O.root)||(null==(j=null==eS?void 0:eS.popup)?void 0:j.root)||B||z,{[`${ek}-dropdown-${ej}`]:"rtl"===ej},M,eS.root,null==eu?void 0:eu.root,eM,eF,eR),e0=(0,g.default)(e=>{var t;return null!=(t=null!=V?V:eT)?t:e}),e1=t.useContext(p.default),e2=(0,r.default)({[`${ek}-lg`]:"large"===e0,[`${ek}-sm`]:"small"===e0,[`${ek}-rtl`]:"rtl"===ej,[`${ek}-${eP}`]:eI,[`${ek}-in-form-item`]:eU},(0,u.getStatusClassNames)(ek,eq,eW),e_,ex,R,eS.root,null==eu?void 0:eu.root,M,eM,eF,eR),e4=t.useMemo(()=>void 0!==H?H:"rtl"===ej?"bottomRight":"bottomLeft",[H,ej]),[e6]=(0,l.useZIndex)("SelectLike",null==eH?void 0:eH.zIndex);return eN(t.createElement(n.default,Object.assign({ref:o,virtual:eh,showSearch:eb},eQ,{style:Object.assign(Object.assign(Object.assign(Object.assign({},eC.root),null==ec?void 0:ec.root),ew),Y),dropdownMatchSelectWidth:eL,transitionName:(0,s.getTransitionName)(eO,"slide-up",et),builtinPlacements:(0,w.default)(q,ey),listHeight:L,listItemHeight:eE,mode:eA,prefixCls:ek,placement:e4,direction:ej,prefix:eo,suffixIcon:eK,menuItemSelectedIcon:eX,removeIcon:eJ,allowClear:!0===Q?{clearIcon:eY}:Q,notFoundContent:I,className:e2,getPopupContainer:A||ef,dropdownClassName:eZ,disabled:null!=W?W:e1,dropdownStyle:Object.assign(Object.assign({},eH),{zIndex:e6}),maxCount:eB?en:void 0,tagRender:eB?er:void 0,dropdownRender:eD,onDropdownVisibleChange:es||el})))}),O=(0,c.default)(k,"dropdownAlign");k.SECRET_COMBOBOX_MODE_DO_NOT_USE=E,k.Option=a.Option,k.OptGroup=o.OptGroup,k._InternalPanelDoNotUseOrYouWillBeFired=O,e.s(["default",0,k],327494)},199133,e=>{"use strict";var t=e.i(327494);e.s(["Select",()=>t.default])},290571,e=>{"use strict";function t(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}"function"==typeof SuppressedError&&SuppressedError,e.s(["__rest",()=>t])},480731,e=>{"use strict";let t={Increase:"increase",ModerateIncrease:"moderateIncrease",Decrease:"decrease",ModerateDecrease:"moderateDecrease",Unchanged:"unchanged"},r={Slate:"slate",Gray:"gray",Zinc:"zinc",Neutral:"neutral",Stone:"stone",Red:"red",Orange:"orange",Amber:"amber",Yellow:"yellow",Lime:"lime",Green:"green",Emerald:"emerald",Teal:"teal",Cyan:"cyan",Sky:"sky",Blue:"blue",Indigo:"indigo",Violet:"violet",Purple:"purple",Fuchsia:"fuchsia",Pink:"pink",Rose:"rose"},n={XS:"xs",SM:"sm",MD:"md",LG:"lg",XL:"xl"},o={Left:"left",Right:"right"},a={Top:"top",Bottom:"bottom"};e.s(["BaseColors",()=>r,"DeltaTypes",()=>t,"HorizontalPositions",()=>o,"Sizes",()=>n,"VerticalPositions",()=>a])},673706,e=>{"use strict";e.i(480731);let t=["slate","gray","zinc","neutral","stone","red","orange","amber","yellow","lime","green","emerald","teal","cyan","sky","blue","indigo","violet","purple","fuchsia","pink","rose"],r=e=>e.toString(),n=e=>e.reduce((e,t)=>e+t,0),o=(e,t)=>{for(let r=0;r{e.forEach(e=>{"function"==typeof e?e(t):null!=e&&(e.current=t)})}}function i(e){return t=>`tremor-${e}-${t}`}function l(e,r){let n=t.includes(e);if("white"===e||"black"===e||"transparent"===e||!r||!n){let t=e.includes("#")||e.includes("--")||e.includes("rgb")?`[${e}]`:e;return{bgColor:`bg-${t} dark:bg-${t}`,hoverBgColor:`hover:bg-${t} dark:hover:bg-${t}`,selectBgColor:`data-[selected]:bg-${t} dark:data-[selected]:bg-${t}`,textColor:`text-${t} dark:text-${t}`,selectTextColor:`data-[selected]:text-${t} dark:data-[selected]:text-${t}`,hoverTextColor:`hover:text-${t} dark:hover:text-${t}`,borderColor:`border-${t} dark:border-${t}`,selectBorderColor:`data-[selected]:border-${t} dark:data-[selected]:border-${t}`,hoverBorderColor:`hover:border-${t} dark:hover:border-${t}`,ringColor:`ring-${t} dark:ring-${t}`,strokeColor:`stroke-${t} dark:stroke-${t}`,fillColor:`fill-${t} dark:fill-${t}`}}return{bgColor:`bg-${e}-${r} dark:bg-${e}-${r}`,selectBgColor:`data-[selected]:bg-${e}-${r} dark:data-[selected]:bg-${e}-${r}`,hoverBgColor:`hover:bg-${e}-${r} dark:hover:bg-${e}-${r}`,textColor:`text-${e}-${r} dark:text-${e}-${r}`,selectTextColor:`data-[selected]:text-${e}-${r} dark:data-[selected]:text-${e}-${r}`,hoverTextColor:`hover:text-${e}-${r} dark:hover:text-${e}-${r}`,borderColor:`border-${e}-${r} dark:border-${e}-${r}`,selectBorderColor:`data-[selected]:border-${e}-${r} dark:data-[selected]:border-${e}-${r}`,hoverBorderColor:`hover:border-${e}-${r} dark:hover:border-${e}-${r}`,ringColor:`ring-${e}-${r} dark:ring-${e}-${r}`,strokeColor:`stroke-${e}-${r} dark:stroke-${e}-${r}`,fillColor:`fill-${e}-${r} dark:fill-${e}-${r}`}}e.s(["defaultValueFormatter",()=>r,"getColorClassNames",()=>l,"isValueInArray",()=>o,"makeClassName",()=>i,"mergeRefs",()=>a,"sumNumericArray",()=>n],673706)},689074,21243,98801,e=>{"use strict";var t=e.i(290571),r=e.i(271645);let n=e=>{var n=(0,t.__rest)(e,[]);return r.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},n),r.default.createElement("path",{d:"M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM11 15V17H13V15H11ZM11 7V13H13V7H11Z"}))};e.s(["default",()=>n],689074);let o=e=>{var n=(0,t.__rest)(e,[]);return r.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},n),r.default.createElement("path",{d:"M1.18164 12C2.12215 6.87976 6.60812 3 12.0003 3C17.3924 3 21.8784 6.87976 22.8189 12C21.8784 17.1202 17.3924 21 12.0003 21C6.60812 21 2.12215 17.1202 1.18164 12ZM12.0003 17C14.7617 17 17.0003 14.7614 17.0003 12C17.0003 9.23858 14.7617 7 12.0003 7C9.23884 7 7.00026 9.23858 7.00026 12C7.00026 14.7614 9.23884 17 12.0003 17ZM12.0003 15C10.3434 15 9.00026 13.6569 9.00026 12C9.00026 10.3431 10.3434 9 12.0003 9C13.6571 9 15.0003 10.3431 15.0003 12C15.0003 13.6569 13.6571 15 12.0003 15Z"}))};e.s(["default",()=>o],21243);let a=e=>{var n=(0,t.__rest)(e,[]);return r.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},n),r.default.createElement("path",{d:"M4.52047 5.93457L1.39366 2.80777L2.80788 1.39355L22.6069 21.1925L21.1927 22.6068L17.8827 19.2968C16.1814 20.3755 14.1638 21.0002 12.0003 21.0002C6.60812 21.0002 2.12215 17.1204 1.18164 12.0002C1.61832 9.62282 2.81932 7.5129 4.52047 5.93457ZM14.7577 16.1718L13.2937 14.7078C12.902 14.8952 12.4634 15.0002 12.0003 15.0002C10.3434 15.0002 9.00026 13.657 9.00026 12.0002C9.00026 11.537 9.10522 11.0984 9.29263 10.7067L7.82866 9.24277C7.30514 10.0332 7.00026 10.9811 7.00026 12.0002C7.00026 14.7616 9.23884 17.0002 12.0003 17.0002C13.0193 17.0002 13.9672 16.6953 14.7577 16.1718ZM7.97446 3.76015C9.22127 3.26959 10.5793 3.00016 12.0003 3.00016C17.3924 3.00016 21.8784 6.87992 22.8189 12.0002C22.5067 13.6998 21.8038 15.2628 20.8068 16.5925L16.947 12.7327C16.9821 12.4936 17.0003 12.249 17.0003 12.0002C17.0003 9.23873 14.7617 7.00016 12.0003 7.00016C11.7514 7.00016 11.5068 7.01833 11.2677 7.05343L7.97446 3.76015Z"}))};e.s(["default",()=>a],98801)},444755,e=>{"use strict";let t=(e,r)=>{if(0===e.length)return r.classGroupId;let n=e[0],o=r.nextPart.get(n),a=o?t(e.slice(1),o):void 0;if(a)return a;if(0===r.validators.length)return;let i=e.join("-");return r.validators.find(({validator:e})=>e(i))?.classGroupId},r=/^\[(.+)\]$/,n=(e,t,r,i)=>{e.forEach(e=>{if("string"==typeof e){(""===e?t:o(t,e)).classGroupId=r;return}"function"==typeof e?a(e)?n(e(i),t,r,i):t.validators.push({validator:e,classGroupId:r}):Object.entries(e).forEach(([e,a])=>{n(a,o(t,e),r,i)})})},o=(e,t)=>{let r=e;return t.split("-").forEach(e=>{r.nextPart.has(e)||r.nextPart.set(e,{nextPart:new Map,validators:[]}),r=r.nextPart.get(e)}),r},a=e=>e.isThemeGetter,i=(e,t)=>t?e.map(([e,r])=>[e,r.map(e=>"string"==typeof e?t+e:"object"==typeof e?Object.fromEntries(Object.entries(e).map(([e,r])=>[t+e,r])):e)]):e,l=e=>{if(e.length<=1)return e;let t=[],r=[];return e.forEach(e=>{"["===e[0]?(t.push(...r.sort(),e),r=[]):r.push(e)}),t.push(...r.sort()),t},s=/\s+/;function c(){let e,t,r=0,n="";for(;r{let t;if("string"==typeof e)return e;let r="";for(let n=0;n{if(e<1)return{get:()=>void 0,set:()=>{}};let t=0,r=new Map,n=new Map,o=(o,a)=>{r.set(o,a),++t>e&&(t=0,n=r,r=new Map)};return{get(e){let t=r.get(e);return void 0!==t?t:void 0!==(t=n.get(e))?(o(e,t),t):void 0},set(e,t){r.has(e)?r.set(e,t):o(e,t)}}})((s=o.reduce((e,t)=>t(e),e())).cacheSize),parseClassName:(e=>{let{separator:t,experimentalParseClassName:r}=e,n=1===t.length,o=t[0],a=t.length,i=e=>{let r,i=[],l=0,s=0;for(let c=0;cs?r-s:void 0}};return r?e=>r({className:e,parseClassName:i}):i})(s),...(e=>{let o=(e=>{let{theme:t,prefix:r}=e,o={nextPart:new Map,validators:[]};return i(Object.entries(e.classGroups),r).forEach(([e,r])=>{n(r,o,e,t)}),o})(e),{conflictingClassGroups:a,conflictingClassGroupModifiers:l}=e;return{getClassGroupId:e=>{let n=e.split("-");return""===n[0]&&1!==n.length&&n.shift(),t(n,o)||(e=>{if(r.test(e)){let t=r.exec(e)[1],n=t?.substring(0,t.indexOf(":"));if(n)return"arbitrary.."+n}})(e)},getConflictingClassGroupIds:(e,t)=>{let r=a[e]||[];return t&&l[e]?[...r,...l[e]]:r}}})(s)}).cache.get,f=a.cache.set,p=m,m(l)};function m(e){let t=u(e);if(t)return t;let r=((e,t)=>{let{parseClassName:r,getClassGroupId:n,getConflictingClassGroupIds:o}=t,a=[],i=e.trim().split(s),c="";for(let e=i.length-1;e>=0;e-=1){let t=i[e],{modifiers:s,hasImportantModifier:u,baseClassName:d,maybePostfixModifierPosition:f}=r(t),p=!!f,m=n(p?d.substring(0,f):d);if(!m){if(!p||!(m=n(d))){c=t+(c.length>0?" "+c:c);continue}p=!1}let g=l(s).join(":"),h=u?g+"!":g,v=h+m;if(a.includes(v))continue;a.push(v);let y=o(m,p);for(let e=0;e0?" "+c:c)}return c})(e,a);return f(e,r),r}return function(){return p(c.apply(null,arguments))}}let f=e=>{let t=t=>t[e]||[];return t.isThemeGetter=!0,t},p=/^\[(?:([a-z-]+):)?(.+)\]$/i,m=/^\d+\/\d+$/,g=new Set(["px","full","screen"]),h=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,v=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,y=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,b=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,w=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,C=e=>S(e)||g.has(e)||m.test(e),x=e=>M(e,"length",A),S=e=>!!e&&!Number.isNaN(Number(e)),$=e=>M(e,"number",S),E=e=>!!e&&Number.isInteger(Number(e)),k=e=>e.endsWith("%")&&S(e.slice(0,-1)),O=e=>p.test(e),j=e=>h.test(e),T=new Set(["length","size","percentage"]),_=e=>M(e,T,B),P=e=>M(e,"position",B),I=new Set(["image","url"]),F=e=>M(e,I,L),N=e=>M(e,"",z),R=()=>!0,M=(e,t,r)=>{let n=p.exec(e);return!!n&&(n[1]?"string"==typeof t?n[1]===t:t.has(n[1]):r(n[2]))},A=e=>v.test(e)&&!y.test(e),B=()=>!1,z=e=>b.test(e),L=e=>w.test(e),H=()=>{let e=f("colors"),t=f("spacing"),r=f("blur"),n=f("brightness"),o=f("borderColor"),a=f("borderRadius"),i=f("borderSpacing"),l=f("borderWidth"),s=f("contrast"),c=f("grayscale"),u=f("hueRotate"),d=f("invert"),p=f("gap"),m=f("gradientColorStops"),g=f("gradientColorStopPositions"),h=f("inset"),v=f("margin"),y=f("opacity"),b=f("padding"),w=f("saturate"),T=f("scale"),I=f("sepia"),M=f("skew"),A=f("space"),B=f("translate"),z=()=>["auto","contain","none"],L=()=>["auto","hidden","clip","visible","scroll"],H=()=>["auto",O,t],D=()=>[O,t],V=()=>["",C,x],W=()=>["auto",S,O],U=()=>["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top"],G=()=>["solid","dashed","dotted","double","none"],q=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],K=()=>["start","end","center","between","around","evenly","stretch"],X=()=>["","0",O],J=()=>["auto","avoid","all","avoid-page","page","left","right","column"],Y=()=>[S,O];return{cacheSize:500,separator:":",theme:{colors:[R],spacing:[C,x],blur:["none","",j,O],brightness:Y(),borderColor:[e],borderRadius:["none","","full",j,O],borderSpacing:D(),borderWidth:V(),contrast:Y(),grayscale:X(),hueRotate:Y(),invert:X(),gap:D(),gradientColorStops:[e],gradientColorStopPositions:[k,x],inset:H(),margin:H(),opacity:Y(),padding:D(),saturate:Y(),scale:Y(),sepia:X(),skew:Y(),space:D(),translate:D()},classGroups:{aspect:[{aspect:["auto","square","video",O]}],container:["container"],columns:[{columns:[j]}],"break-after":[{"break-after":J()}],"break-before":[{"break-before":J()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:[...U(),O]}],overflow:[{overflow:L()}],"overflow-x":[{"overflow-x":L()}],"overflow-y":[{"overflow-y":L()}],overscroll:[{overscroll:z()}],"overscroll-x":[{"overscroll-x":z()}],"overscroll-y":[{"overscroll-y":z()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:[h]}],"inset-x":[{"inset-x":[h]}],"inset-y":[{"inset-y":[h]}],start:[{start:[h]}],end:[{end:[h]}],top:[{top:[h]}],right:[{right:[h]}],bottom:[{bottom:[h]}],left:[{left:[h]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",E,O]}],basis:[{basis:H()}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["wrap","wrap-reverse","nowrap"]}],flex:[{flex:["1","auto","initial","none",O]}],grow:[{grow:X()}],shrink:[{shrink:X()}],order:[{order:["first","last","none",E,O]}],"grid-cols":[{"grid-cols":[R]}],"col-start-end":[{col:["auto",{span:["full",E,O]},O]}],"col-start":[{"col-start":W()}],"col-end":[{"col-end":W()}],"grid-rows":[{"grid-rows":[R]}],"row-start-end":[{row:["auto",{span:[E,O]},O]}],"row-start":[{"row-start":W()}],"row-end":[{"row-end":W()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",O]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",O]}],gap:[{gap:[p]}],"gap-x":[{"gap-x":[p]}],"gap-y":[{"gap-y":[p]}],"justify-content":[{justify:["normal",...K()]}],"justify-items":[{"justify-items":["start","end","center","stretch"]}],"justify-self":[{"justify-self":["auto","start","end","center","stretch"]}],"align-content":[{content:["normal",...K(),"baseline"]}],"align-items":[{items:["start","end","center","baseline","stretch"]}],"align-self":[{self:["auto","start","end","center","stretch","baseline"]}],"place-content":[{"place-content":[...K(),"baseline"]}],"place-items":[{"place-items":["start","end","center","baseline","stretch"]}],"place-self":[{"place-self":["auto","start","end","center","stretch"]}],p:[{p:[b]}],px:[{px:[b]}],py:[{py:[b]}],ps:[{ps:[b]}],pe:[{pe:[b]}],pt:[{pt:[b]}],pr:[{pr:[b]}],pb:[{pb:[b]}],pl:[{pl:[b]}],m:[{m:[v]}],mx:[{mx:[v]}],my:[{my:[v]}],ms:[{ms:[v]}],me:[{me:[v]}],mt:[{mt:[v]}],mr:[{mr:[v]}],mb:[{mb:[v]}],ml:[{ml:[v]}],"space-x":[{"space-x":[A]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[A]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit","svw","lvw","dvw",O,t]}],"min-w":[{"min-w":[O,t,"min","max","fit"]}],"max-w":[{"max-w":[O,t,"none","full","min","max","fit","prose",{screen:[j]},j]}],h:[{h:[O,t,"auto","min","max","fit","svh","lvh","dvh"]}],"min-h":[{"min-h":[O,t,"min","max","fit","svh","lvh","dvh"]}],"max-h":[{"max-h":[O,t,"min","max","fit","svh","lvh","dvh"]}],size:[{size:[O,t,"auto","min","max","fit"]}],"font-size":[{text:["base",j,x]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",$]}],"font-family":[{font:[R]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:["tighter","tight","normal","wide","wider","widest",O]}],"line-clamp":[{"line-clamp":["none",S,$]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",C,O]}],"list-image":[{"list-image":["none",O]}],"list-style-type":[{list:["none","disc","decimal",O]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[e]}],"placeholder-opacity":[{"placeholder-opacity":[y]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[e]}],"text-opacity":[{"text-opacity":[y]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...G(),"wavy"]}],"text-decoration-thickness":[{decoration:["auto","from-font",C,x]}],"underline-offset":[{"underline-offset":["auto",C,O]}],"text-decoration-color":[{decoration:[e]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:D()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",O]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",O]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[y]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:[...U(),P]}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",_]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},F]}],"bg-color":[{bg:[e]}],"gradient-from-pos":[{from:[g]}],"gradient-via-pos":[{via:[g]}],"gradient-to-pos":[{to:[g]}],"gradient-from":[{from:[m]}],"gradient-via":[{via:[m]}],"gradient-to":[{to:[m]}],rounded:[{rounded:[a]}],"rounded-s":[{"rounded-s":[a]}],"rounded-e":[{"rounded-e":[a]}],"rounded-t":[{"rounded-t":[a]}],"rounded-r":[{"rounded-r":[a]}],"rounded-b":[{"rounded-b":[a]}],"rounded-l":[{"rounded-l":[a]}],"rounded-ss":[{"rounded-ss":[a]}],"rounded-se":[{"rounded-se":[a]}],"rounded-ee":[{"rounded-ee":[a]}],"rounded-es":[{"rounded-es":[a]}],"rounded-tl":[{"rounded-tl":[a]}],"rounded-tr":[{"rounded-tr":[a]}],"rounded-br":[{"rounded-br":[a]}],"rounded-bl":[{"rounded-bl":[a]}],"border-w":[{border:[l]}],"border-w-x":[{"border-x":[l]}],"border-w-y":[{"border-y":[l]}],"border-w-s":[{"border-s":[l]}],"border-w-e":[{"border-e":[l]}],"border-w-t":[{"border-t":[l]}],"border-w-r":[{"border-r":[l]}],"border-w-b":[{"border-b":[l]}],"border-w-l":[{"border-l":[l]}],"border-opacity":[{"border-opacity":[y]}],"border-style":[{border:[...G(),"hidden"]}],"divide-x":[{"divide-x":[l]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[l]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[y]}],"divide-style":[{divide:G()}],"border-color":[{border:[o]}],"border-color-x":[{"border-x":[o]}],"border-color-y":[{"border-y":[o]}],"border-color-s":[{"border-s":[o]}],"border-color-e":[{"border-e":[o]}],"border-color-t":[{"border-t":[o]}],"border-color-r":[{"border-r":[o]}],"border-color-b":[{"border-b":[o]}],"border-color-l":[{"border-l":[o]}],"divide-color":[{divide:[o]}],"outline-style":[{outline:["",...G()]}],"outline-offset":[{"outline-offset":[C,O]}],"outline-w":[{outline:[C,x]}],"outline-color":[{outline:[e]}],"ring-w":[{ring:V()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[e]}],"ring-opacity":[{"ring-opacity":[y]}],"ring-offset-w":[{"ring-offset":[C,x]}],"ring-offset-color":[{"ring-offset":[e]}],shadow:[{shadow:["","inner","none",j,N]}],"shadow-color":[{shadow:[R]}],opacity:[{opacity:[y]}],"mix-blend":[{"mix-blend":[...q(),"plus-lighter","plus-darker"]}],"bg-blend":[{"bg-blend":q()}],filter:[{filter:["","none"]}],blur:[{blur:[r]}],brightness:[{brightness:[n]}],contrast:[{contrast:[s]}],"drop-shadow":[{"drop-shadow":["","none",j,O]}],grayscale:[{grayscale:[c]}],"hue-rotate":[{"hue-rotate":[u]}],invert:[{invert:[d]}],saturate:[{saturate:[w]}],sepia:[{sepia:[I]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[r]}],"backdrop-brightness":[{"backdrop-brightness":[n]}],"backdrop-contrast":[{"backdrop-contrast":[s]}],"backdrop-grayscale":[{"backdrop-grayscale":[c]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[u]}],"backdrop-invert":[{"backdrop-invert":[d]}],"backdrop-opacity":[{"backdrop-opacity":[y]}],"backdrop-saturate":[{"backdrop-saturate":[w]}],"backdrop-sepia":[{"backdrop-sepia":[I]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":[i]}],"border-spacing-x":[{"border-spacing-x":[i]}],"border-spacing-y":[{"border-spacing-y":[i]}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["none","all","","colors","opacity","shadow","transform",O]}],duration:[{duration:Y()}],ease:[{ease:["linear","in","out","in-out",O]}],delay:[{delay:Y()}],animate:[{animate:["none","spin","ping","pulse","bounce",O]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[T]}],"scale-x":[{"scale-x":[T]}],"scale-y":[{"scale-y":[T]}],rotate:[{rotate:[E,O]}],"translate-x":[{"translate-x":[B]}],"translate-y":[{"translate-y":[B]}],"skew-x":[{"skew-x":[M]}],"skew-y":[{"skew-y":[M]}],"transform-origin":[{origin:["center","top","top-right","right","bottom-right","bottom","bottom-left","left","top-left",O]}],accent:[{accent:["auto",e]}],appearance:[{appearance:["none","auto"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",O]}],"caret-color":[{caret:[e]}],"pointer-events":[{"pointer-events":["none","auto"]}],resize:[{resize:["none","y","x",""]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":D()}],"scroll-mx":[{"scroll-mx":D()}],"scroll-my":[{"scroll-my":D()}],"scroll-ms":[{"scroll-ms":D()}],"scroll-me":[{"scroll-me":D()}],"scroll-mt":[{"scroll-mt":D()}],"scroll-mr":[{"scroll-mr":D()}],"scroll-mb":[{"scroll-mb":D()}],"scroll-ml":[{"scroll-ml":D()}],"scroll-p":[{"scroll-p":D()}],"scroll-px":[{"scroll-px":D()}],"scroll-py":[{"scroll-py":D()}],"scroll-ps":[{"scroll-ps":D()}],"scroll-pe":[{"scroll-pe":D()}],"scroll-pt":[{"scroll-pt":D()}],"scroll-pr":[{"scroll-pr":D()}],"scroll-pb":[{"scroll-pb":D()}],"scroll-pl":[{"scroll-pl":D()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",O]}],fill:[{fill:[e,"none"]}],"stroke-w":[{stroke:[C,x,$]}],stroke:[{stroke:[e,"none"]}],sr:["sr-only","not-sr-only"],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-s","border-w-e","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-s","border-color-e","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]}}},D=(e,t,r)=>{void 0!==r&&(e[t]=r)},V=(e,t)=>{if(t)for(let r in t)D(e,r,t[r])},W=(e,t)=>{if(t)for(let r in t){let n=t[r];void 0!==n&&(e[r]=(e[r]||[]).concat(n))}},U=((e,...t)=>"function"==typeof e?d(H,e,...t):d(()=>((e,{cacheSize:t,prefix:r,separator:n,experimentalParseClassName:o,extend:a={},override:i={}})=>{for(let a in D(e,"cacheSize",t),D(e,"prefix",r),D(e,"separator",n),D(e,"experimentalParseClassName",o),i)V(e[a],i[a]);for(let t in a)W(e[t],a[t]);return e})(H(),e),...t))({extend:{classGroups:{shadow:[{shadow:[{tremor:["input","card","dropdown"],"dark-tremor":["input","card","dropdown"]}]}],rounded:[{rounded:[{tremor:["small","default","full"],"dark-tremor":["small","default","full"]}]}],"font-size":[{text:[{tremor:["default","title","metric"],"dark-tremor":["default","title","metric"]}]}]}}});e.s(["tremorTwMerge",()=>U],444755)},103471,e=>{"use strict";var t=e.i(444755),r=e.i(271645);let n=e=>["string","number"].includes(typeof e)?e:e instanceof Array?e.map(n).join(""):"object"==typeof e&&e?n(e.props.children):void 0;function o(e){let t=new Map;return r.default.Children.map(e,e=>{var r;t.set(e.props.value,null!=(r=n(e))?r:e.props.value)}),t}function a(e,t){return r.default.Children.map(t,t=>{var r;if((null!=(r=n(t))?r:t.props.value).toLowerCase().includes(e.toLowerCase()))return t})}let i=(e,r,n=!1)=>(0,t.tremorTwMerge)(r?"bg-tremor-background-subtle dark:bg-dark-tremor-background-subtle":"bg-tremor-background dark:bg-dark-tremor-background",!r&&"hover:bg-tremor-background-muted dark:hover:bg-dark-tremor-background-muted",e?"text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis":"text-tremor-content dark:text-dark-tremor-content",r&&"text-tremor-content-subtle dark:text-dark-tremor-content-subtle",n&&"text-red-500 placeholder:text-red-500 dark:text-red-500 dark:placeholder:text-red-500",n?"border-red-500 dark:border-red-500":"border-tremor-border dark:border-dark-tremor-border");function l(e){return null!=e&&""!==e}e.s(["constructValueToNameMapping",()=>o,"getFilteredOptions",()=>a,"getNodeText",()=>n,"getSelectButtonColors",()=>i,"hasValue",()=>l])},779241,677955,e=>{"use strict";var t=e.i(290571),r=e.i(271645),n=e.i(673706),o=e.i(689074),a=e.i(21243),i=e.i(98801),l=e.i(103471),s=e.i(444755);let c=r.default.forwardRef((e,c)=>{let{value:u,defaultValue:d,type:f,placeholder:p="Type...",icon:m,error:g=!1,errorMessage:h,disabled:v=!1,stepper:y,makeInputClassName:b,className:w,onChange:C,onValueChange:x,autoFocus:S,pattern:$}=e,E=(0,t.__rest)(e,["value","defaultValue","type","placeholder","icon","error","errorMessage","disabled","stepper","makeInputClassName","className","onChange","onValueChange","autoFocus","pattern"]),[k,O]=(0,r.useState)(S||!1),[j,T]=(0,r.useState)(!1),_=(0,r.useCallback)(()=>T(!j),[j,T]),P=(0,r.useRef)(null),I=(0,l.hasValue)(u||d);return r.default.useEffect(()=>{let e=()=>O(!0),t=()=>O(!1),r=P.current;return r&&(r.addEventListener("focus",e),r.addEventListener("blur",t),S&&r.focus()),()=>{r&&(r.removeEventListener("focus",e),r.removeEventListener("blur",t))}},[S]),r.default.createElement(r.default.Fragment,null,r.default.createElement("div",{className:(0,s.tremorTwMerge)(b("root"),"relative w-full flex items-center min-w-[10rem] outline-none rounded-tremor-default transition duration-100 border","shadow-tremor-input","dark:shadow-dark-tremor-input",(0,l.getSelectButtonColors)(I,v,g),k&&(0,s.tremorTwMerge)("ring-2","border-tremor-brand-subtle ring-tremor-brand-muted","dark:border-dark-tremor-brand-subtle dark:ring-dark-tremor-brand-muted"),w)},m?r.default.createElement(m,{className:(0,s.tremorTwMerge)(b("icon"),"shrink-0 h-5 w-5 mx-2.5 absolute left-0 flex items-center","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")}):null,r.default.createElement("input",Object.assign({ref:(0,n.mergeRefs)([P,c]),defaultValue:d,value:u,type:j?"text":f,className:(0,s.tremorTwMerge)(b("input"),"w-full bg-transparent focus:outline-none focus:ring-0 border-none text-tremor-default rounded-tremor-default transition duration-100 py-2","text-tremor-content-emphasis","dark:text-dark-tremor-content-emphasis","[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none","password"===f?g?"pr-16":"pr-12":g?"pr-8":"pr-3",m?"pl-10":"pl-3",v?"placeholder:text-tremor-content-subtle dark:placeholder:text-dark-tremor-content-subtle":"placeholder:text-tremor-content dark:placeholder:text-dark-tremor-content"),placeholder:p,disabled:v,"data-testid":"base-input",onChange:e=>{null==C||C(e),null==x||x(e.target.value)},pattern:$},E)),"password"!==f||v?null:r.default.createElement("button",{className:(0,s.tremorTwMerge)(b("toggleButton"),"absolute inset-y-0 right-0 flex items-center px-2.5 rounded-lg"),type:"button",onClick:()=>_(),"aria-label":j?"Hide password":"Show Password"},j?r.default.createElement(i.default,{className:(0,s.tremorTwMerge)("flex-none h-5 w-5 transition","text-tremor-content-subtle hover:text-tremor-content","dark:text-dark-tremor-content-subtle hover:dark:text-dark-tremor-content"),"aria-hidden":!0}):r.default.createElement(a.default,{className:(0,s.tremorTwMerge)("flex-none h-5 w-5 transition","text-tremor-content-subtle hover:text-tremor-content","dark:text-dark-tremor-content-subtle hover:dark:text-dark-tremor-content"),"aria-hidden":!0})),g?r.default.createElement(o.default,{className:(0,s.tremorTwMerge)(b("errorIcon"),"text-red-500 shrink-0 h-5 w-5 absolute right-0 flex items-center","password"===f?"mr-10":"number"===f?y?"mr-20":"mr-3":"mx-2.5")}):null,null!=y?y:null),g&&h?r.default.createElement("p",{className:(0,s.tremorTwMerge)(b("errorMessage"),"text-sm text-red-500 mt-1")},h):null)});c.displayName="BaseInput",e.s(["default",()=>c],677955);let u=(0,n.makeClassName)("TextInput"),d=r.default.forwardRef((e,n)=>{let{type:o="text"}=e,a=(0,t.__rest)(e,["type"]);return r.default.createElement(c,Object.assign({ref:n,type:o,makeInputClassName:u},a))});d.displayName="TextInput",e.s(["TextInput",()=>d],779241)},827252,e=>{"use strict";e.i(247167);var t=e.i(931067),r=e.i(271645);let n={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 336a48 48 0 1096 0 48 48 0 10-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z"}}]},name:"info-circle",theme:"outlined"};var o=e.i(9583),a=r.forwardRef(function(e,a){return r.createElement(o.default,(0,t.default)({},e,{ref:a,icon:n}))});e.s(["InfoCircleOutlined",0,a],827252)},592968,e=>{"use strict";var t=e.i(491816);e.s(["Tooltip",()=>t.default])},602869,122550,82946,431703,e=>{"use strict";e.s(["addAllowedIP",()=>eH,"adminGlobalActivity",()=>e1,"adminGlobalActivityPerModel",()=>e4,"adminGlobalCacheActivity",()=>e2,"adminSpendLogsCall",()=>eY,"adminTopEndUsersCall",()=>eZ,"adminTopKeysCall",()=>eQ,"adminTopModelsCall",()=>e6,"adminspendByProvider",()=>e0,"agentDailyActivityCall",()=>eO,"agentHubPublicModelsCall",()=>eM,"alertingSettingsCall",()=>er,"allEndUsersCall",()=>eK,"allTagNamesCall",()=>eq,"applyGuardrail",()=>nh,"approveGuardrailSubmission",()=>tU,"approveMCPServer",()=>rA,"availableTeamListCall",()=>em,"budgetCreateCall",()=>Z,"budgetDeleteCall",()=>Q,"budgetUpdateCall",()=>ee,"buildMcpOAuthAuthorizeUrl",()=>nT,"cacheTemporaryMcpServer",()=>nO,"cachingHealthCheckCall",()=>tM,"callMCPTool",()=>rG,"cancelModelCostMapReload",()=>q,"checkEuAiActCompliance",()=>nK,"checkGdprCompliance",()=>nX,"claimOnboardingToken",()=>eT,"convertPromptFileToJson",()=>rg,"createAgentCall",()=>rh,"createGuardrailCall",()=>ry,"createMCPServer",()=>rj,"createMCPToolset",()=>rI,"createMemory",()=>n9,"createPassThroughEndpoint",()=>t_,"createPolicyAttachmentCall",()=>rn,"createPolicyCall",()=>t5,"createPolicyVersion",()=>t8,"createPromptCall",()=>rf,"createSearchTool",()=>rL,"credentialCreateCall",()=>tn,"credentialDeleteCall",()=>ti,"credentialGetCall",()=>ta,"credentialListCall",()=>to,"credentialUpdateCall",()=>tl,"customerDailyActivityCall",()=>ek,"deleteAgentCall",()=>nn,"deleteAllowedIP",()=>eD,"deleteCallback",()=>nE,"deleteClaudeCodePlugin",()=>nq,"deleteConfigFieldSetting",()=>tI,"deleteGuardrailCall",()=>ni,"deleteMCPServer",()=>r_,"deleteMCPToolset",()=>rN,"deleteMemory",()=>ot,"deletePassThroughEndpointsCall",()=>tF,"deletePolicyAttachmentCall",()=>ro,"deletePolicyCall",()=>re,"deletePromptCall",()=>rm,"deleteSearchTool",()=>rD,"deleteToolPolicyOverride",()=>n1,"disableClaudeCodePlugin",()=>nG,"discoverAgentCardCall",()=>rv,"enableClaudeCodePlugin",()=>nU,"enrichPolicyTemplate",()=>t0,"enrichPolicyTemplateStream",()=>t4,"estimateAttachmentImpactCall",()=>rs,"exchangeLoginCode",()=>nL,"exchangeMcpOAuthToken",()=>n_,"fetchAvailableSearchProviders",()=>rV,"fetchDiscoverableMCPServers",()=>rS,"fetchMCPAccessGroups",()=>rk,"fetchMCPClientIp",()=>rO,"fetchMCPServerHealth",()=>rE,"fetchMCPServers",()=>r$,"fetchMCPSubmissions",()=>rM,"fetchMCPToolsets",()=>rP,"fetchMemoryList",()=>n8,"fetchOpenAPIRegistry",()=>rx,"fetchSearchTools",()=>rz,"fetchToolDetail",()=>nZ,"fetchToolPolicyOptions",()=>nJ,"fetchToolsList",()=>nY,"formatDate",()=>x,"getAgentCreateMetadata",()=>R,"getAgentInfo",()=>nf,"getAgentsList",()=>nd,"getAllowedIPs",()=>eL,"getBudgetList",()=>tC,"getCacheSettingsCall",()=>tE,"getCallbackConfigsCall",()=>S,"getCallbacksCall",()=>tx,"getCategoryYaml",()=>nc,"getClaudeCodePluginsList",()=>nV,"getConfigFieldSetting",()=>tT,"getDefaultTeamSettings",()=>rZ,"getEmailEventSettings",()=>ne,"getGeneralSettingsCall",()=>tS,"getGlobalLitellmHeaderName",()=>B,"getGuardrailInfo",()=>np,"getGuardrailProviderSpecificParams",()=>ns,"getGuardrailUISettings",()=>nl,"getGuardrailsList",()=>tV,"getGuardrailsUsageDetail",()=>tK,"getGuardrailsUsageLogs",()=>tX,"getGuardrailsUsageOverview",()=>tq,"getInternalUserSettings",()=>rw,"getLicenseInfo",()=>nS,"getMCPOAuthUserCredentialStatus",()=>n4,"getMCPSemanticFilterSettings",()=>tL,"getMCPUserEnvVars",()=>n6,"getMajorAirlines",()=>nu,"getModelCostMapReloadStatus",()=>X,"getModelCostMapSource",()=>K,"getOnboardingCredentials",()=>ej,"getOpenAPISchema",()=>V,"getPassThroughEndpointsCall",()=>tj,"getPoliciesList",()=>tJ,"getPolicyAttachmentsList",()=>rr,"getPolicyInfo",()=>rt,"getPolicyInfoWithGuardrails",()=>tQ,"getPolicyTemplates",()=>tZ,"getPossibleUserRoles",()=>tt,"getPromptInfo",()=>ru,"getPromptVersions",()=>rd,"getPromptsList",()=>rc,"getProviderCreateMetadata",()=>N,"getProxyBaseUrl",()=>_,"getProxyUISettings",()=>tB,"getPublicModelHubInfo",()=>D,"getRemainingUsers",()=>nx,"getResolvedGuardrails",()=>ri,"getRouterSettingsCall",()=>t$,"getSSOSettings",()=>nb,"getTeamPermissionsCall",()=>r1,"getToolUsageLogs",()=>nQ,"getUISettings",()=>tz,"getUiConfig",()=>H,"getUiSettings",()=>nH,"handleError",()=>F,"individualModelHealthCheckCall",()=>tR,"invitationCreateCall",()=>et,"keyAliasesCall",()=>e9,"keyCreateCall",()=>eo,"keyCreateForAgentCall",()=>ea,"keyCreateServiceAccountCall",()=>en,"keyDeleteCall",()=>el,"keyInfoCall",()=>e5,"keyInfoV1Call",()=>e7,"keyListCall",()=>e8,"keyUpdateCall",()=>ts,"latestHealthChecksCall",()=>tA,"listGuardrailSubmissions",()=>tW,"listMCPTools",()=>rU,"listMCPUserEnvVarStatus",()=>n3,"listPolicyVersions",()=>t7,"loginCall",()=>nz,"makeAgentsPublicCall",()=>no,"makeMCPPublicCall",()=>na,"makeModelGroupPublic",()=>L,"mcpHubPublicServersCall",()=>eA,"modelAvailableCall",()=>eW,"modelCostMap",()=>W,"modelCreateCall",()=>J,"modelDeleteCall",()=>Y,"modelHubCall",()=>ez,"modelHubPublicModelsCall",()=>eR,"modelInfoCall",()=>eF,"modelInfoV1Call",()=>eN,"modelPatchUpdateCall",()=>tu,"organizationCreateCall",()=>ev,"organizationDailyActivityCall",()=>eE,"organizationDeleteCall",()=>eb,"organizationInfoCall",()=>eh,"organizationListCall",()=>eg,"organizationMemberAddCall",()=>tg,"organizationMemberDeleteCall",()=>th,"organizationMemberUpdateCall",()=>tv,"organizationUpdateCall",()=>ey,"patchAgentCall",()=>nm,"perUserAnalyticsCall",()=>nB,"proxyBaseUrl",()=>T,"ragIngestCall",()=>r9,"regenerateKeyCall",()=>e_,"registerClaudeCodePlugin",()=>nW,"registerMCPServer",()=>rR,"registerMcpOAuthClient",()=>nj,"rejectGuardrailSubmission",()=>tG,"rejectMCPServer",()=>rB,"reloadModelCostMap",()=>U,"resetEmailEventSettings",()=>nr,"resolvePoliciesCall",()=>rl,"scheduleModelCostMapReload",()=>G,"searchToolQueryCall",()=>nI,"serverRootPath",()=>k,"serviceHealthCheck",()=>tw,"sessionSpendLogsCall",()=>r4,"setCallbacksCall",()=>tN,"setGlobalLitellmHeaderName",()=>A,"skillHubPublicCall",()=>eB,"storeMCPOAuthUserCredential",()=>n2,"storeMCPUserEnvVars",()=>n5,"suggestPolicyTemplates",()=>t1,"switchToWorkerUrl",()=>P,"tagCreateCall",()=>rq,"tagDailyActivityCall",()=>eS,"tagDauCall",()=>nF,"tagDeleteCall",()=>rQ,"tagDistinctCall",()=>nM,"tagInfoCall",()=>rX,"tagListCall",()=>rY,"tagMauCall",()=>nR,"tagUpdateCall",()=>rK,"tagWauCall",()=>nN,"tagsSpendLogsCall",()=>eG,"teamBulkMemberAddCall",()=>tf,"teamCreateCall",()=>tr,"teamDailyActivityCall",()=>e$,"teamDeleteCall",()=>ec,"teamInfoCall",()=>ef,"teamListCall",()=>ep,"teamMemberAddCall",()=>td,"teamMemberDeleteCall",()=>tm,"teamMemberUpdateCall",()=>tp,"teamPermissionsUpdateCall",()=>r2,"teamSpendLogsCall",()=>eU,"teamUpdateCall",()=>tc,"testCacheConnectionCall",()=>tk,"testConnectionRequest",()=>e3,"testCustomCodeGuardrail",()=>nv,"testMCPSemanticFilter",()=>tD,"testMCPToolsListRequest",()=>nk,"testPipelineCall",()=>ra,"testPoliciesAndGuardrails",()=>tY,"testPolicyTemplate",()=>t2,"testSearchToolConnection",()=>rW,"transformRequestCall",()=>ew,"uiAuditLogsCall",()=>nC,"uiSpendLogDetailsCall",()=>rb,"uiSpendLogsCall",()=>eJ,"updateCacheSettingsCall",()=>tO,"updateConfigFieldSetting",()=>tP,"updateDefaultTeamSettings",()=>r0,"updateEmailEventSettings",()=>nt,"updateGuardrailCall",()=>ng,"updateInternalUserSettings",()=>rC,"updateMCPSemanticFilterSettings",()=>tH,"updateMCPServer",()=>rT,"updateMCPToolset",()=>rF,"updateMemory",()=>oe,"updatePassThroughEndpoint",()=>n$,"updatePolicyCall",()=>t3,"updatePolicyVersionStatus",()=>t9,"updatePromptCall",()=>rp,"updateSSOSettings",()=>nw,"updateSearchTool",()=>rH,"updateToolPolicy",()=>n0,"updateUiSettings",()=>nD,"updateUsefulLinksCall",()=>eV,"usageAiChatStream",()=>t6,"userAgentSummaryCall",()=>nA,"userBulkUpdateUserCall",()=>tb,"userCreateCall",()=>ei,"userDailyActivityAggregatedCall",()=>te,"userDailyActivityCall",()=>ex,"userDeleteCall",()=>es,"userFilterUICall",()=>eX,"userGetInfoV2",()=>ed,"userListCall",()=>eu,"userUpdateUserCall",()=>ty,"validateBlockedWordsFile",()=>ny,"vectorStoreCreateCall",()=>r6,"vectorStoreDeleteCall",()=>r3,"vectorStoreInfoCall",()=>r7,"vectorStoreListCall",()=>r5,"vectorStoreSearchCall",()=>nP,"vectorStoreUpdateCall",()=>r8],602869);var t=e.i(247167),r=e.i(888259),n=e.i(268004);e.s(["default",()=>v,"jsonFields",()=>g],82946);var o=e.i(843476),a=e.i(271645),i=e.i(808613),l=e.i(311451),s=e.i(28651),c=e.i(199133),u=e.i(779241),d=e.i(827252),f=e.i(592968);let p=e=>e?e.replace(/_/g," ").replace(/\b\w/g,e=>e.toUpperCase()):e;function m(e,t){return e.length>t?e.substring(0,t)+"...":e}e.s(["formItemValidateJSON",0,(e,t)=>{if(!t)return Promise.resolve();try{return JSON.parse(t),Promise.resolve()}catch(e){return Promise.reject("Please enter valid JSON")}},"formatLabel",0,p,"truncateString",()=>m],122550);let g=["metadata","config","enforced_params","aliases"],h=(e,t)=>g.includes(e)||"json"===t.format,v=({schemaComponent:e,excludedFields:t=[],form:r,overrideLabels:n={},overrideTooltips:m={},customValidation:g={},defaultValues:v={}})=>{let[y,b]=(0,a.useState)(null),[w,C]=(0,a.useState)(null);return((0,a.useEffect)(()=>{(async()=>{try{let n=(await V()).components.schemas[e];if(!n)throw Error(`Schema component "${e}" not found`);b(n);let o={};Object.keys(n.properties).filter(e=>!t.includes(e)&&void 0!==v[e]).forEach(e=>{o[e]=v[e]}),r.setFieldsValue(o)}catch(e){console.error("Schema fetch error:",e),C(e instanceof Error?e.message:"Failed to fetch schema")}})()},[e,r,t]),w)?(0,o.jsxs)("div",{className:"text-red-500",children:["Error: ",w]}):y?.properties?(0,o.jsx)("div",{children:Object.entries(y.properties).filter(([e])=>!t.includes(e)).map(([e,t])=>{let r,a,b,w,C,x,S,$;return a=(e=>{if(e.type)return e.type;if(e.anyOf){let t=e.anyOf.map(e=>e.type);if(t.includes("number")||t.includes("integer"))return"number";t.includes("string")}return"string"})(t),b=y?.required?.includes(e),w=n[e]||t.title||p(e),C=m[e]||t.description,x=[],b&&x.push({required:!0,message:`${w} is required`}),g[e]&&x.push({validator:g[e]}),h(e,t)&&x.push({validator:async(e,t)=>{if(t&&!(e=>{if(!e)return!0;try{return JSON.parse(e),!0}catch{return!1}})(t))throw Error("Please enter valid JSON")}}),S=C?(0,o.jsxs)("span",{children:[w," ",(0,o.jsx)(f.Tooltip,{title:C,children:(0,o.jsx)(d.InfoCircleOutlined,{style:{marginLeft:"4px"}})})]}):w,r=h(e,t)?(0,o.jsx)(l.Input.TextArea,{rows:4,placeholder:"Enter as JSON",className:"font-mono"}):t.enum?(0,o.jsx)(c.Select,{children:t.enum.map(e=>(0,o.jsx)(c.Select.Option,{value:e,children:e},e))}):"number"===a||"integer"===a?(0,o.jsx)(s.InputNumber,{style:{width:"100%"},precision:"integer"===a?0:void 0}):"duration"===e?(0,o.jsx)(u.TextInput,{placeholder:"eg: 30s, 30h, 30d"}):(0,o.jsx)(u.TextInput,{placeholder:C||""}),(0,o.jsx)(i.Form.Item,{label:S,name:e,className:"mt-8",rules:x,initialValue:v[e],help:(0,o.jsx)("div",{className:"text-xs text-gray-500",children:($=({max_budget:"Enter maximum budget in USD (e.g., 100.50)",budget_duration:"Select a time period for budget reset",tpm_limit:"Enter maximum tokens per minute (whole number)",rpm_limit:"Enter maximum requests per minute (whole number)",duration:"Enter duration (e.g., 30s, 24h, 7d)",metadata:'Enter JSON object with key-value pairs\nExample: {"team": "research", "project": "nlp"}',config:'Enter configuration as JSON object\nExample: {"setting": "value"}',permissions:"Enter comma-separated permission strings",enforced_params:'Enter parameters as JSON object\nExample: {"param": "value"}',blocked:"Enter true/false or specific block conditions",aliases:'Enter aliases as JSON object\nExample: {"alias1": "value1", "alias2": "value2"}',models:"Select one or more model names",key_alias:"Enter a unique identifier for this key",tags:"Enter comma-separated tag strings"})[e]||({string:"Text input",number:"Numeric input",integer:"Whole number input",boolean:"True/False value"})[a]||"Text input",h(e,t)?`${$} +Must be valid JSON format`:t.enum?`Select from available options +Allowed values: ${t.enum.join(", ")}`:$)}),children:r},e)})}):null};var y=e.i(727749);class b extends Error{status;body;constructor(e,t,r){super(e),this.name="ApiError",this.status=t,this.body=r}}let w=e=>{let t=e?.detail,r=Array.isArray(t)?t.map(e=>e?.msg||JSON.stringify(e)).join("; "):"string"==typeof t?t:void 0;return e?.error&&(e.error.message||("string"==typeof e.error?e.error:void 0))||e?.message||r||JSON.stringify(e)};function C(e){let{getBaseUrl:t,getAuthHeaderName:r,onError:n,fetchImpl:o}=e;async function a(e,i,l={}){let{accessToken:s,body:c,rawBody:u,query:d,headers:f,signal:p}=l,m=((e,t)=>{if(!t)return e;let r=new URLSearchParams;for(let[e,n]of Object.entries(t))null!=n&&(Array.isArray(n)?n.forEach(t=>null!=t&&r.append(e,String(t))):r.append(e,String(n)));let n=r.toString();return n?e.includes("?")?`${e}&${n}`:`${e}?${n}`:e})(`${t()}${i}`,d),g={};void 0===u&&(g["Content-Type"]="application/json"),s&&(g[r?r():"Authorization"]=`Bearer ${s}`),f&&Object.assign(g,f);let h={method:e,headers:g,signal:p};void 0!==u?h.body=u:void 0!==c&&(h.body=JSON.stringify(c));let v=await (o??fetch)(m,h);if(!v.ok){let e,t=await v.text(),r=t;try{r=JSON.parse(t),e=w(r)}catch{e=t||`HTTP ${v.status}`}throw n?.(e),new b(e,v.status,r)}let y=await v.text();return y?JSON.parse(y):void 0}return{request:a,get:(e,t)=>a("GET",e,t),post:(e,t)=>a("POST",e,t),put:(e,t)=>a("PUT",e,t),delete:(e,t)=>a("DELETE",e,t),patch:(e,t)=>a("PATCH",e,t)}}e.s(["createApiClient",()=>C,"deriveErrorMessage",0,w],431703);let x=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}-${r}-${n}`},S=async e=>{try{return await z.get("/callbacks/configs",{accessToken:e})}catch(e){throw console.error("Failed to get callbacks:",e),e}},$=e=>t.default.env.NEXT_PUBLIC_BASE_URL?t.default.env.NEXT_PUBLIC_BASE_URL:e,E=$(null),k="/",O="litellm_worker_url",j=window.localStorage.getItem(O),T=(()=>{if(!j)return null;try{let e=new URL(j);if("http:"===e.protocol||"https:"===e.protocol)return j}catch{}return window.localStorage.removeItem(O),null})()??E;console.log=function(){};let _=()=>{if(T)return T;let e=window.location;return e?.origin??""};function P(e){(!e||function(e){try{let t=new URL(e);return"http:"===t.protocol||"https:"===t.protocol}catch{return!1}}(e))&&(e?window.localStorage.setItem(O,e):window.localStorage.removeItem(O),T=e??E)}let I=0,F=async e=>{let t=Date.now();if(t-I>6e4){if(("string"==typeof e?e:JSON.stringify(e)).includes("Authentication Error - Expired Key")){y.default.info("UI Session Expired. Logging out."),I=t,(0,n.clearTokenCookies)();let e=window.location;e&&(window.location.href=e.pathname)}I=t}else console.log("Error suppressed to prevent spam:",e)},N=async()=>{let e=T?`${T}/public/providers/fields`:"/public/providers/fields",t=await fetch(e,{method:"GET"});if(!t.ok){let e=await t.text();throw console.error("Failed to fetch provider create metadata:",t.status,e),Error("Failed to load provider configuration")}return await t.json()},R=async()=>{let e=T?`${T}/public/agents/fields`:"/public/agents/fields",t=await fetch(e,{method:"GET"});if(!t.ok){let e=await t.text();throw console.error("Failed to fetch agent create metadata:",t.status,e),Error("Failed to load agent configuration")}return await t.json()},M="Authorization";function A(e="Authorization"){console.log(`setGlobalLitellmHeaderName: ${e}`),M=e}function B(){return M}let z=C({getBaseUrl:_,getAuthHeaderName:B,onError:F}),L=async(e,t)=>{let r=T?`${T}/model_group/make_public`:"/model_group/make_public";return(await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({model_groups:t})})).json()},H=async()=>{console.log("Getting UI config");let e=E?`${E}/litellm/.well-known/litellm-ui-config`:"/litellm/.well-known/litellm-ui-config",t=await fetch(e),r=await t.json();return console.log("jsonData in getUiConfig:",r),k=r.server_root_path,((e,t=null)=>{window.localStorage.getItem(O)||(T=(({explicitBase:e,serverRootPath:t})=>{let r,n=(e??"").trim().replace(/\/+$/,""),o=""===(r=(t??"").trim())||"/"===r?"":(r.startsWith("/")?r:`/${r}`).replace(/\/+$/,"");return""===o||n.endsWith(o)?n:`${n}${o}`})({explicitBase:t||$(window.location?.origin??null),serverRootPath:e}))})(r.server_root_path,r.proxy_base_url),r},D=async()=>{let e=T?`${T}/public/model_hub/info`:"/public/model_hub/info",t=await fetch(e);return await t.json()},V=async()=>{let e=T?`${T}/openapi.json`:"/openapi.json",t=await fetch(e);return await t.json()},W=async()=>{try{let e=T?`${T}/public/litellm_model_cost_map`:"/public/litellm_model_cost_map",t=await fetch(e,{method:"GET",headers:{"Content-Type":"application/json"}}),r=await t.json();return console.log(`received litellm model cost data: ${r}`),r}catch(e){throw console.error("Failed to get model cost map:",e),e}},U=async e=>{try{let t=T?`${T}/reload/model_cost_map`:"/reload/model_cost_map",r=await fetch(t,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}}),n=await r.json();return console.log(`Model cost map reload response: ${n}`),n}catch(e){throw console.error("Failed to reload model cost map:",e),e}},G=async(e,t)=>{try{let r=T?`${T}/schedule/model_cost_map_reload?hours=${t}`:`/schedule/model_cost_map_reload?hours=${t}`,n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}}),o=await n.json();return console.log(`Schedule model cost map reload response: ${o}`),o}catch(e){throw console.error("Failed to schedule model cost map reload:",e),e}},q=async e=>{try{let t=T?`${T}/schedule/model_cost_map_reload`:"/schedule/model_cost_map_reload",r=await fetch(t,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}}),n=await r.json();return console.log(`Cancel model cost map reload response: ${n}`),n}catch(e){throw console.error("Failed to cancel model cost map reload:",e),e}},K=async e=>{try{let t=T?`${T}/model/cost_map/source`:"/model/cost_map/source",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw Error(`HTTP ${r.status}: ${e}`)}let n=await r.json();return console.log("Model cost map source info:",n),n}catch(e){throw console.error("Failed to get model cost map source info:",e),e}},X=async e=>{try{let t=T?`${T}/schedule/model_cost_map_reload/status`:"/schedule/model_cost_map_reload/status";console.log("Fetching status from URL:",t);let r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){console.error(`Status request failed with status: ${r.status}`);let e=await r.text();throw console.error("Error response:",e),Error(`HTTP ${r.status}: ${e}`)}let n=await r.json();return console.log("Model cost map reload status:",n),n}catch(e){throw console.error("Failed to get model cost map reload status:",e),e}},J=async(e,t)=>{try{let n=await z.post("/model/new",{accessToken:e,body:{...t}});return console.log("API Response:",n),r.default.destroy(),y.default.success(`Model ${t.model_name} created successfully`),n}catch(e){throw console.error("Failed to create key:",e),e}},Y=async(e,t)=>{console.log(`model_id in model delete call: ${t}`);try{let r=await z.post("/model/delete",{accessToken:e,body:{id:t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},Q=async(e,t)=>{if(console.log(`budget_id in budget delete call: ${t}`),null!=e)try{let r=await z.post("/budget/delete",{accessToken:e,body:{id:t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},Z=async(e,t)=>{try{console.log("Form Values in budgetCreateCall:",t),console.log("Form Values after check:",t);let r=await z.post("/budget/new",{accessToken:e,body:{...t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},ee=async(e,t)=>{try{console.log("Form Values in budgetUpdateCall:",t),console.log("Form Values after check:",t);let r=await z.post("/budget/update",{accessToken:e,body:{...t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},et=async(e,t)=>{try{let r=await z.post("/invitation/new",{accessToken:e,body:{user_id:t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},er=async e=>{try{return await z.get("/alerting/settings",{accessToken:e})}catch(e){throw console.error("Failed to get callbacks:",e),e}},en=async(e,t)=>{try{for(let e of(console.log("Form Values in keyCreateServiceAccountCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),g))if(t[e]){console.log(`formValues.${e}:`,t[e]);try{t[e]=JSON.parse(t[e])}catch(t){throw Error(`Failed to parse ${e}: `+t)}}console.log("Form Values after check:",t);let r=T?`${T}/key/service-account/generate`:"/key/service-account/generate",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({...t})});if(!n.ok){let e=await n.text();throw F(e),console.error("Error response from the server:",e),Error(e)}let o=await n.json();return console.log("API Response:",o),o}catch(e){throw console.error("Failed to create key:",e),e}},eo=async(e,t,r)=>{try{for(let e of(console.log("Form Values in keyCreateCall:",r),r.description&&(r.metadata||(r.metadata={}),r.metadata.description=r.description,delete r.description,r.metadata=JSON.stringify(r.metadata)),g))if(r[e]){console.log(`formValues.${e}:`,r[e]);try{r[e]=JSON.parse(r[e])}catch(t){throw Error(`Failed to parse ${e}: `+t)}}console.log("Form Values after check:",r);let n=T?`${T}/key/generate`:"/key/generate",o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...r})});if(!o.ok){let e=await o.text();throw F(e),console.error("Error response from the server:",e),Error(e)}let a=await o.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},ea=async(e,t,r,n,o,a)=>{let i=T?`${T}/key/generate`:"/key/generate",l={agent_id:t,key_alias:r,models:n.length>0?n:[]};a&&(l.team_id=a),o&&Object.keys(o).length>0&&(l.metadata=o);let s=await fetch(i,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(l)});if(!s.ok)throw F(await s.text()),Error("Failed to create key for agent");return s.json()},ei=async(e,t,r)=>{try{if(console.log("Form Values in keyCreateCall:",r),r.description&&(r.metadata||(r.metadata={}),r.metadata.description=r.description,delete r.description,r.metadata=JSON.stringify(r.metadata)),r.auto_create_key=!1,r.metadata){console.log("formValues.metadata:",r.metadata);try{r.metadata=JSON.parse(r.metadata)}catch(e){throw Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",r);let n=T?`${T}/user/new`:"/user/new",o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...r})});if(!o.ok){let e=await o.text();throw F(e),console.error("Error response from the server:",e),Error(e)}let a=await o.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},el=async(e,t)=>{try{return console.log("in keyDeleteCall:",t),await z.post("/key/delete",{accessToken:e,body:{keys:[t]}})}catch(e){throw console.error("Failed to create key:",e),e}},es=async(e,t)=>{try{return console.log("in userDeleteCall:",t),await z.post("/user/delete",{accessToken:e,body:{user_ids:t}})}catch(e){throw console.error("Failed to delete user(s):",e),e}},ec=async(e,t)=>{try{return console.log("in teamDeleteCall:",t),await z.post("/team/delete",{accessToken:e,body:{team_ids:[t]}})}catch(e){throw console.error("Failed to delete key:",e),e}},eu=async(e,t=null,r=null,n=null,o=null,a=null,i=null,l=null,s=null,c=null,u=null)=>{try{return await z.get("/user/list",{accessToken:e,query:{user_ids:t&&t.length>0?t.join(","):void 0,page:r||void 0,page_size:n||void 0,user_email:o||void 0,role:a||void 0,team:i||void 0,sso_user_ids:l||void 0,sort_by:s||void 0,sort_order:c||void 0,organization_ids:u&&u.length>0?u.join(","):void 0}})}catch(e){throw console.error("Failed to create key:",e),e}},ed=async(e,t)=>{try{return await z.get("/v2/user/info",{accessToken:e,query:{user_id:t||void 0}})}catch(e){throw console.error("Failed to fetch user info v2:",e),e}},ef=async(e,t)=>{try{return await z.get("/team/info",{accessToken:e,query:{team_id:t||void 0}})}catch(e){throw console.error("Failed to create key:",e),e}},ep=async(e,t,r=null,n=null,o=null)=>{try{return await z.get("/team/list",{accessToken:e,query:{user_id:r||void 0,organization_id:t||void 0,team_id:n||void 0,team_alias:o||void 0}})}catch(e){throw console.error("Failed to create key:",e),e}},em=async e=>{try{console.log("in availableTeamListCall");let t=await z.get("/team/available",{accessToken:e});return console.log("/team/available_teams API Response:",t),t}catch(e){throw e}},eg=async(e,t=null,r=null)=>{try{return await z.get("/organization/list",{accessToken:e,query:{org_id:t||void 0,org_alias:r||void 0}})}catch(e){throw console.error("Failed to create key:",e),e}},eh=async(e,t)=>{try{let r=T?`${T}/organization/info`:"/organization/info";t&&(r=`${r}?organization_id=${t}`),console.log("in teamInfoCall");let n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}let o=await n.json();return console.log("API Response:",o),o}catch(e){throw console.error("Failed to create key:",e),e}},ev=async(e,t)=>{try{if(console.log("Form Values in organizationCreateCall:",t),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw console.error("Failed to parse metadata:",e),Error("Failed to parse metadata: "+e)}}let r=await z.post("/organization/new",{accessToken:e,body:{...t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},ey=async(e,t)=>{try{console.log("Form Values in organizationUpdateCall:",t);let r=await z.patch("/organization/update",{accessToken:e,body:{...t}});return console.log("Update Team Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},eb=async(e,t)=>{try{let r=T?`${T}/organization/delete`:"/organization/delete",n=await fetch(r,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({organization_ids:[t]})});if(!n.ok){let e=await n.text();throw F(e),Error(`Error deleting organization: ${e}`)}return await n.json()}catch(e){throw console.error("Failed to delete organization:",e),e}},ew=async(e,t)=>{try{let r=T?`${T}/utils/transform_request`:"/utils/transform_request",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error("Failed to create key:",e),e}},eC=async({accessToken:e,endpoint:t,startTime:r,endTime:n,page:o=1,extraQueryParams:a})=>{try{let i,l,s,c,u=(i=t.startsWith("/")?t:`/${t}`,l=T?`${T}${i}`:i,(s=new URLSearchParams).append("start_date",x(r)),s.append("end_date",x(n)),s.append("page_size","1000"),s.append("page",o.toString()),s.append("timezone",new Date().getTimezoneOffset().toString()),a&&Object.entries(a).forEach(([e,t])=>{((e,t,r)=>{if(null!=r){if(Array.isArray(r)){r.length>0&&e.append(t,r.join(","));return}e.append(t,`${r}`)}})(s,e,t)}),(c=s.toString())?`${l}?${c}`:l),d=await fetch(u,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!d.ok){let e=await d.json(),t=w(e);throw F(t),Error(t)}return await d.json()}catch(e){throw console.error(`Failed to fetch daily activity (${t}):`,e),e}},ex=async(e,t,r,n=1,o=null)=>eC({accessToken:e,endpoint:"/user/daily/activity",startTime:t,endTime:r,page:n,extraQueryParams:{user_id:o}}),eS=async(e,t,r,n=1,o=null)=>eC({accessToken:e,endpoint:"/tag/daily/activity",startTime:t,endTime:r,page:n,extraQueryParams:{tags:o}}),e$=async(e,t,r,n=1,o=null)=>eC({accessToken:e,endpoint:"/team/daily/activity",startTime:t,endTime:r,page:n,extraQueryParams:{team_ids:o,exclude_team_ids:"litellm-dashboard"}}),eE=async(e,t,r,n=1,o=null)=>eC({accessToken:e,endpoint:"/organization/daily/activity",startTime:t,endTime:r,page:n,extraQueryParams:{organization_ids:o}}),ek=async(e,t,r,n=1,o=null)=>eC({accessToken:e,endpoint:"/customer/daily/activity",startTime:t,endTime:r,page:n,extraQueryParams:{end_user_ids:o}}),eO=async(e,t,r,n=1,o=null)=>eC({accessToken:e,endpoint:"/agent/daily/activity",startTime:t,endTime:r,page:n,extraQueryParams:{agent_ids:o}}),ej=async e=>{try{let t=T?`${T}/onboarding/get_token`:"/onboarding/get_token";t+=`?invite_link=${e}`;let r=await fetch(t,{method:"GET",headers:{"Content-Type":"application/json"}});if(!r.ok){let e=await r.json(),t=w(e);throw F(t),Error(t)}return await r.json()}catch(e){throw console.error("Failed to create key:",e),e}},eT=async(e,t,r,n)=>{try{let o=await z.post("/onboarding/claim_token",{accessToken:e,body:{invitation_link:t,user_id:r,password:n}});return console.log(o),o}catch(e){throw console.error("Failed to delete key:",e),e}},e_=async(e,t,r)=>{try{let n=T?`${T}/key/${t}/regenerate`:`/key/${t}/regenerate`,o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!o.ok){let e=await o.json(),t=w(e);throw F(t),Error(t)}let a=await o.json();return console.log("Regenerate key Response:",a),a}catch(e){throw console.error("Failed to regenerate key:",e),e}},eP=!1,eI=null,eF=async(e,t,r,n=1,o=50,a,i,l,s,c)=>{try{console.log("modelInfoCall:",e,t,r,n,o,a,i,l,s,c);let u=T?`${T}/v2/model/info`:"/v2/model/info",d=new URLSearchParams;d.append("include_team_models","true"),d.append("page",n.toString()),d.append("size",o.toString()),a&&a.trim()&&d.append("search",a.trim()),i&&i.trim()&&d.append("modelId",i.trim()),l&&l.trim()&&d.append("teamId",l.trim()),s&&s.trim()&&d.append("sortBy",s.trim()),c&&c.trim()&&d.append("sortOrder",c.trim()),d.toString()&&(u+=`?${d.toString()}`);let f=await fetch(u,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!f.ok){let e=await f.text();throw e+=`error shown=${eP}`,eP||(e.includes("No model list passed")&&(e="No Models Exist. Click Add Model to get started."),y.default.info(e),eP=!0,eI&&clearTimeout(eI),eI=setTimeout(()=>{eP=!1},1e4)),Error("Network response was not ok")}let p=await f.json();return console.log("modelInfoCall:",p),p}catch(e){throw console.error("Failed to create key:",e),e}},eN=async(e,t)=>{try{let r=T?`${T}/v1/model/info`:"/v1/model/info";r+=`?litellm_model_id=${t}`;let n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}let o=await n.json();return console.log("modelInfoV1Call:",o),o}catch(e){throw console.error("Failed to create key:",e),e}},eR=async()=>{let e=T?`${T}/public/model_hub`:"/public/model_hub",t=await fetch(e,{method:"GET",headers:{"Content-Type":"application/json"}});return t.ok?t.json():(console.error(`modelHubPublicModelsCall failed with status ${t.status}`),[])},eM=async()=>{let e=T?`${T}/public/agent_hub`:"/public/agent_hub",t=await fetch(e,{method:"GET",headers:{"Content-Type":"application/json"}});return t.ok?t.json():(console.error(`agentHubPublicModelsCall failed with status ${t.status}`),[])},eA=async()=>{let e=T?`${T}/public/mcp_hub`:"/public/mcp_hub",t=await fetch(e,{method:"GET",headers:{"Content-Type":"application/json"}});return t.ok?t.json():(console.error(`mcpHubPublicServersCall failed with status ${t.status}`),[])},eB=async()=>{let e=T?`${T}/public/skill_hub`:"/public/skill_hub",t=await fetch(e,{method:"GET",headers:{"Content-Type":"application/json"}});return t.ok?t.json():(console.error(`skillHubPublicCall failed with status ${t.status}`),{plugins:[]})},ez=async e=>{try{let t=await z.get("/model_group/info",{accessToken:e});return console.log("modelHubCall:",t),t}catch(e){throw console.error("Failed to create key:",e),e}},eL=async e=>{try{let t=await z.get("/get/allowed_ips",{accessToken:e});return console.log("getAllowedIPs:",t),t.data}catch(e){throw console.error("Failed to get allowed IPs:",e),e}},eH=async(e,t)=>{try{let r=await z.post("/add/allowed_ip",{accessToken:e,body:{ip:t}});return console.log("addAllowedIP:",r),r}catch(e){throw console.error("Failed to add allowed IP:",e),e}},eD=async(e,t)=>{try{let r=await z.post("/delete/allowed_ip",{accessToken:e,body:{ip:t}});return console.log("deleteAllowedIP:",r),r}catch(e){throw console.error("Failed to delete allowed IP:",e),e}},eV=async(e,t)=>{try{return await z.post("/model_hub/update_useful_links",{accessToken:e,body:{useful_links:t}})}catch(e){throw console.error("Failed to create key:",e),e}},eW=async(e,t,r,n=!1,o=null,a=!1,i=!1,l)=>{console.log("in /models calls, globalLitellmHeaderName",M);try{return await z.get("/models",{accessToken:e,query:{include_model_access_groups:"True",return_wildcard_routes:!0===n?"True":void 0,only_model_access_groups:!0===i?"True":void 0,team_id:o||void 0,scope:l||void 0}})}catch(e){throw console.error("Failed to create key:",e),e}},eU=async e=>{try{let t=await z.get("/global/spend/teams",{accessToken:e});return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},eG=async(e,t,r,n)=>{try{let o=T?`${T}/global/spend/tags`:"/global/spend/tags";t&&r&&(o=`${o}?start_date=${t}&end_date=${r}`),n&&(o+=`&tags=${n.join(",")}`),console.log("in tagsSpendLogsCall:",o);let a=await fetch(`${o}`,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!a.ok){let e=await a.json(),t=w(e);throw F(t),Error(t)}let i=await a.json();return console.log(i),i}catch(e){throw console.error("Failed to create key:",e),e}},eq=async e=>{try{let t=await z.get("/global/spend/all_tag_names",{accessToken:e});return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},eK=async e=>{try{let t=await z.get("/customer/list",{accessToken:e});return console.log(t),t}catch(e){throw console.error("Failed to fetch end users:",e),e}},eX=async(e,t)=>{try{return await z.get("/user/filter/ui",{accessToken:e,query:{user_email:t.get("user_email")||void 0,user_id:t.get("user_id")||void 0,team_id:t.get("team_id")||void 0}})}catch(e){throw console.error("Failed to create key:",e),e}},eJ=async({accessToken:e,start_date:t,end_date:r,page:n=1,page_size:o=50,params:a={}})=>{try{let i=T?`${T}/spend/logs/ui`:"/spend/logs/ui",l=new URLSearchParams;for(let[e,i]of(l.append("start_date",t),l.append("end_date",r),l.append("page",n.toString()),l.append("page_size",o.toString()),Object.entries(a)))null!=i&&("min_spend"===e||"max_spend"===e?l.append(e,i.toString()):"string"==typeof i&&""!==i&&l.append(e,String(i)));let s=l.toString();s&&(i+=`?${s}`);let c=await fetch(i,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!c.ok){let e=await c.json(),t=w(e);throw F(t),Error(t)}let u=await c.json();return console.log("Spend Logs Response:",u),u}catch(e){throw console.error("Failed to fetch spend logs:",e),e}},eY=async e=>{try{let t=await z.get("/global/spend/logs",{accessToken:e});return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},eQ=async e=>{try{let t=T?`${T}/global/spend/keys?limit=5`:"/global/spend/keys?limit=5",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json(),t=w(e);throw F(t),Error(t)}let n=await r.json();return console.log(n),n}catch(e){throw console.error("Failed to create key:",e),e}},eZ=async(e,t,r,n)=>{try{let o=await z.post("/global/spend/end_users",{accessToken:e,body:t?{api_key:t,startTime:r,endTime:n}:{startTime:r,endTime:n}});return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},e0=async(e,t,r,n)=>{try{let o=await z.get("/global/spend/provider",{accessToken:e,query:{...r&&n?{start_date:r,end_date:n}:{},...t?{api_key:t}:{}}});return console.log(o),o}catch(e){throw console.error("Failed to fetch spend data:",e),e}},e1=async(e,t,r)=>{try{let n=await z.get("/global/activity",{accessToken:e,query:t&&r?{start_date:t,end_date:r}:void 0});return console.log(n),n}catch(e){throw console.error("Failed to fetch spend data:",e),e}},e2=async(e,t,r)=>{try{let n=T?`${T}/global/activity/cache_hits`:"/global/activity/cache_hits";t&&r&&(n+=`?start_date=${t}&end_date=${r}`);let o={method:"GET",headers:{[M]:`Bearer ${e}`}},a=await fetch(n,o);if(!a.ok){let e=await a.json(),t=w(e);throw F(t),Error(t)}let i=await a.json();return console.log(i),i}catch(e){throw console.error("Failed to fetch spend data:",e),e}},e4=async(e,t,r)=>{try{let n=T?`${T}/global/activity/model`:"/global/activity/model";t&&r&&(n+=`?start_date=${t}&end_date=${r}`);let o={method:"GET",headers:{[M]:`Bearer ${e}`}},a=await fetch(n,o);if(!a.ok){let e=await a.json(),t=w(e);throw F(t),Error(t)}let i=await a.json();return console.log(i),i}catch(e){throw console.error("Failed to fetch spend data:",e),e}},e6=async e=>{try{let t=T?`${T}/global/spend/models?limit=5`:"/global/spend/models?limit=5",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json(),t=w(e);throw F(t),Error(t)}let n=await r.json();return console.log(n),n}catch(e){throw console.error("Failed to create key:",e),e}},e5=async(e,t)=>{try{let r=T?`${T}/v2/key/info`:"/v2/key/info",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({keys:t})});if(!n.ok){let e=await n.text();if(e.includes("Invalid proxy server token passed"))throw Error("Invalid proxy server token passed");throw F(e),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},e3=async(e,t,r,n)=>{try{console.log("Sending model connection test request:",JSON.stringify(t));let o=T?`${T}/health/test_connection`:"/health/test_connection",a=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify({litellm_params:t,model_info:r,mode:n})}),i=a.headers.get("content-type");if(!i||!i.includes("application/json")){let e=await a.text();throw console.error("Received non-JSON response:",e),Error(`Received non-JSON response (${a.status}: ${a.statusText}). Check network tab for details.`)}let l=await a.json();if((!a.ok||"error"===l.status)&&"error"!==l.status)return{status:"error",message:l.error?.message||`Connection test failed: ${a.status} ${a.statusText}`};return l}catch(e){throw console.error("Model connection test error:",e),e}},e7=async(e,t)=>{try{console.log("entering keyInfoV1Call");let r=T?`${T}/key/info`:"/key/info";r=`${r}?key=${t}`;let n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(console.log("response",n),!n.ok){let e=await n.text();F(e),y.default.fromBackend("Failed to fetch key info - "+e)}let o=await n.json();return console.log("data",o),o}catch(e){throw console.error("Failed to fetch key info:",e),e}},e8=async(e,t,r,n,o,a,i,l,s=null,c=null,u=null,d=null)=>{try{return await z.get("/key/list",{accessToken:e,query:{team_id:r||void 0,organization_id:t||void 0,key_alias:n||void 0,key_hash:a||void 0,user_id:o||void 0,page:i?i.toString():void 0,size:l?l.toString():void 0,sort_by:s||void 0,sort_order:c||void 0,expand:u||void 0,status:d||void 0,return_full_object:"true",include_team_keys:"true",include_created_by_keys:"true",substring_matching:"true"}})}catch(e){throw console.error("Failed to create key:",e),e}},e9=async(e,t=1,r=50,n,o)=>{try{return await z.get("/key/aliases",{accessToken:e,query:{page:String(t),size:String(r),search:n||void 0,team_id:o||void 0}})}catch(e){throw console.error("Failed to fetch key aliases:",e),e}},te=async(e,t,r,n=null)=>{try{let o=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}-${r}-${n}`};return await z.get("/user/daily/activity/aggregated",{accessToken:e,query:{start_date:o(t),end_date:o(r),timezone:new Date().getTimezoneOffset().toString(),user_id:n||void 0}})}catch(e){throw console.error("Failed to fetch aggregated user daily activity:",e),e}},tt=async e=>{try{let t=await z.get("/user/available_roles",{accessToken:e});return console.log("response from user/available_role",t),t}catch(e){throw e}},tr=async(e,t)=>{try{if(console.log("Form Values in teamCreateCall:",t),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw Error("Failed to parse metadata: "+e)}}let r=await z.post("/team/new",{accessToken:e,body:{...t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},tn=async(e,t)=>{try{if(console.log("Form Values in credentialCreateCall:",t),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw Error("Failed to parse metadata: "+e)}}let r=await z.post("/credentials",{accessToken:e,body:{...t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},to=async e=>{try{console.log("in credentialListCall");let t=await z.get("/credentials",{accessToken:e});return console.log("/credentials API Response:",t),t}catch(e){throw console.error("Failed to create key:",e),e}},ta=async(e,t,r)=>{try{let n="/credentials";t?n+=`/by_name/${t}`:r&&(n+=`/by_model/${r}`),console.log("in credentialListCall");let o=await z.get(n,{accessToken:e});return console.log("/credentials API Response:",o),o}catch(e){throw console.error("Failed to create key:",e),e}},ti=async(e,t)=>{try{console.log("in credentialDeleteCall:",t);let r=await z.delete(`/credentials/${t}`,{accessToken:e});return console.log(r),r}catch(e){throw console.error("Failed to delete key:",e),e}},tl=async(e,t,r)=>{try{if(console.log("Form Values in credentialUpdateCall:",r),r.metadata){console.log("formValues.metadata:",r.metadata);try{r.metadata=JSON.parse(r.metadata)}catch(e){throw Error("Failed to parse metadata: "+e)}}let n=await z.patch(`/credentials/${t}`,{accessToken:e,body:{...r}});return console.log("API Response:",n),n}catch(e){throw console.error("Failed to create key:",e),e}},ts=async(e,t)=>{try{if(console.log("Form Values in keyUpdateCall:",t),t.model_tpm_limit){console.log("formValues.model_tpm_limit:",t.model_tpm_limit);try{t.model_tpm_limit=JSON.parse(t.model_tpm_limit)}catch(e){throw Error("Failed to parse model_tpm_limit: "+e)}}if(t.model_rpm_limit){console.log("formValues.model_rpm_limit:",t.model_rpm_limit);try{t.model_rpm_limit=JSON.parse(t.model_rpm_limit)}catch(e){throw Error("Failed to parse model_rpm_limit: "+e)}}let r=T?`${T}/key/update`:"/key/update",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({...t})});if(!n.ok){let e=await n.text();throw F(e),console.error("Error response from the server:",e),Error(e)}let o=await n.json();return console.log("Update key Response:",o),o}catch(e){throw console.error("Failed to create key:",e),e}},tc=async(e,t)=>{try{console.log("Form Values in teamUpateCall:",t);let r=T?`${T}/team/update`:"/team/update",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({...t})});if(!n.ok){let e=await n.text();throw F(e),console.error("Error response from the server:",e),y.default.fromBackend("Failed to update team settings: "+e),Error(e)}let o=await n.json();return console.log("Update Team Response:",o),o}catch(e){throw console.error("Failed to update team:",e),e}},tu=async(e,t,r)=>{try{console.log("Form Values in modelUpateCall:",t);let n=T?`${T}/model/${r}/update`:`/model/${r}/update`,o=await fetch(n,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({...t})});if(!o.ok){let e=await o.text();throw F(e),console.error("Error update from the server:",e),Error("Network response was not ok")}let a=await o.json();return console.log("Update model Response:",a),a}catch(e){throw console.error("Failed to update model:",e),e}},td=async(e,t,r)=>{try{console.log("Form Values in teamMemberAddCall:",r);let n=T?`${T}/team/member_add`:"/team/member_add",o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({team_id:t,member:r})});if(!o.ok){let e=await o.text(),t={};try{t=JSON.parse(e)}catch(t){console.warn("Failed to parse error body as JSON:",e)}let r=t?.detail?.error||"Failed to add team member",n=Error(r);throw n.raw=t,n}let a=await o.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},tf=async(e,t,r,n,o)=>{try{console.log("Bulk add team members:",{teamId:t,members:r,maxBudgetInTeam:n});let a=T?`${T}/team/bulk_member_add`:"/team/bulk_member_add",i={team_id:t};o?i.all_users=!0:i.members=r,null!=n&&(i.max_budget_in_team=n);let l=await fetch(a,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(i)});if(!l.ok){let e=await l.text(),t={};try{t=JSON.parse(e)}catch(t){console.warn("Failed to parse error body as JSON:",e)}let r=t?.detail?.error||"Failed to bulk add team members",n=Error(r);throw n.raw=t,n}let s=await l.json();return console.log("Bulk team member add API Response:",s),s}catch(e){throw console.error("Failed to bulk add team members:",e),e}},tp=async(e,t,r)=>{try{console.log("Form Values in teamMemberUpdateCall:",r),console.log("Budget value:",r.max_budget_in_team),console.log("TPM limit:",r.tpm_limit),console.log("RPM limit:",r.rpm_limit);let n=T?`${T}/team/member_update`:"/team/member_update",o={team_id:t,role:r.role,user_id:r.user_id},a=e=>null==e||""===e?null:e;void 0!==r.user_email&&(o.user_email=r.user_email),"max_budget_in_team"in r&&(o.max_budget_in_team=a(r.max_budget_in_team)),"tpm_limit"in r&&(o.tpm_limit=a(r.tpm_limit)),"rpm_limit"in r&&(o.rpm_limit=a(r.rpm_limit)),"budget_duration"in r&&(o.budget_duration=a(r.budget_duration)),void 0!==r.allowed_models&&(o.allowed_models=r.allowed_models),console.log("Final request body:",o);let i=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(o)});if(!i.ok){let e=await i.text(),t={};try{t=JSON.parse(e)}catch(t){console.warn("Failed to parse error body as JSON:",e)}let r=t?.detail?.error||"Failed to add team member",n=Error(r);throw n.raw=t,n}let l=await i.json();return console.log("API Response:",l),l}catch(e){throw console.error("Failed to update team member:",e),e}},tm=async(e,t,r)=>{try{console.log("Form Values in teamMemberAddCall:",r);let n=await z.post("/team/member_delete",{accessToken:e,body:{team_id:t,...void 0!==r.user_email&&{user_email:r.user_email},...void 0!==r.user_id&&{user_id:r.user_id}}});return console.log("API Response:",n),n}catch(e){throw console.error("Failed to create key:",e),e}},tg=async(e,t,r)=>{try{console.log("Form Values in teamMemberAddCall:",r);let n=T?`${T}/organization/member_add`:"/organization/member_add",o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({organization_id:t,member:r})});if(!o.ok){let e=await o.text();throw F(e),console.error("Error response from the server:",e),Error(e)}let a=await o.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create organization member:",e),e}},th=async(e,t,r)=>{try{console.log("Form Values in organizationMemberDeleteCall:",r);let n=await z.delete("/organization/member_delete",{accessToken:e,body:{organization_id:t,user_id:r}});return console.log("API Response:",n),n}catch(e){throw console.error("Failed to delete organization member:",e),e}},tv=async(e,t,r)=>{try{console.log("Form Values in organizationMemberUpdateCall:",r);let n=await z.patch("/organization/member_update",{accessToken:e,body:{organization_id:t,...r}});return console.log("API Response:",n),n}catch(e){throw console.error("Failed to update organization member:",e),e}},ty=async(e,t,r)=>{try{console.log("Form Values in userUpdateUserCall:",t);let n={...t};null!==r&&(n.user_role=r);let o=await z.post("/user/update",{accessToken:e,body:n});return console.log("API Response:",o),o}catch(e){throw console.error("Failed to create key:",e),e}},tb=async(e,t,r,n=!1)=>{try{let o;if(console.log("Form Values in userUpdateUserCall:",t),n)o={all_users:!0,user_updates:t};else if(r&&r.length>0){let e=[];for(let n of r)e.push({user_id:n,...t});o={users:e}}else throw Error("Must provide either userIds or set allUsers=true");let a=await z.post("/user/bulk_update",{accessToken:e,body:o});return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},tw=async(e,t)=>{try{let r=T?`${T}/health/services?service=${t}`:`/health/services?service=${t}`;console.log("Checking Slack Budget Alerts service health");let n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw F(e),Error(e)}return await n.json()}catch(e){throw console.error("Failed to perform health check:",e),e}},tC=async e=>{try{return await z.get("/budget/list",{accessToken:e})}catch(e){throw console.error("Failed to get callbacks:",e),e}},tx=async(e,t,r)=>{try{return await z.get("/get/config/callbacks",{accessToken:e})}catch(e){throw console.error("Failed to get callbacks:",e),e}},tS=async e=>{try{let t=T?`${T}/config/list?config_type=general_settings`:"/config/list?config_type=general_settings",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json(),t=w(e);throw F(t),Error(t)}return await r.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},t$=async e=>{try{return await z.get("/router/settings",{accessToken:e})}catch(e){throw console.error("Failed to get router settings:",e),e}},tE=async e=>{try{return await z.get("/cache/settings",{accessToken:e})}catch(e){throw console.error("Failed to get cache settings:",e),e}},tk=async(e,t)=>{try{return await z.post("/cache/settings/test",{accessToken:e,body:{cache_settings:t}})}catch(e){throw console.error("Failed to test cache connection:",e),e}},tO=async(e,t)=>{try{return await z.post("/cache/settings",{accessToken:e,body:{cache_settings:t}})}catch(e){throw console.error("Failed to update cache settings:",e),e}},tj=async(e,t)=>{try{let r="/config/pass_through_endpoint";return t&&(r+=`/team/${t}`),await z.get(r,{accessToken:e})}catch(e){throw console.error("Failed to get callbacks:",e),e}},tT=async(e,t)=>{try{let r=T?`${T}/config/field/info?field_name=${t}`:`/config/field/info?field_name=${t}`,n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error("Failed to set callbacks:",e),e}},t_=async(e,t)=>{try{return await z.post("/config/pass_through_endpoint",{accessToken:e,body:{...t}})}catch(e){throw console.error("Failed to set callbacks:",e),e}},tP=async(e,t,r)=>{try{let n=await z.post("/config/field/update",{accessToken:e,body:{field_name:t,field_value:r,config_type:"general_settings"}});return y.default.success("Successfully updated value!"),n}catch(e){throw console.error("Failed to set callbacks:",e),e}},tI=async(e,t)=>{try{let r=await z.post("/config/field/delete",{accessToken:e,body:{field_name:t,config_type:"general_settings"}});return y.default.success("Field reset on proxy"),r}catch(e){throw console.error("Failed to get callbacks:",e),e}},tF=async(e,t)=>{try{let r=T?`${T}/config/pass_through_endpoint?endpoint_id=${t}`:`/config/pass_through_endpoint?endpoint_id=${t}`,n=await fetch(r,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},tN=async(e,t)=>{try{return await z.post("/config/update",{accessToken:e,body:{...t}})}catch(e){throw console.error("Failed to set callbacks:",e),e}},tR=async(e,t)=>{try{let r=T?`${T}/health?model_id=${encodeURIComponent(t)}`:`/health?model_id=${encodeURIComponent(t)}`,n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error(`Failed to call /health for model id ${t}:`,e),e}},tM=async e=>{try{let t=T?`${T}/cache/ping`:"/cache/ping",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw F(e),Error(e)}return await r.json()}catch(e){throw console.error("Failed to call /cache/ping:",e),e}},tA=async e=>{try{let t=T?`${T}/health/latest`:"/health/latest",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw F(e),Error(e)}return await r.json()}catch(e){throw console.error("Failed to call /health/latest:",e),e}},tB=async e=>{try{return console.log("Getting proxy UI settings"),console.log("proxyBaseUrl in getProxyUISettings:",T),await z.get("/sso/get/ui_settings",{accessToken:e})}catch(e){throw console.error("Failed to get callbacks:",e),e}},tz=async e=>{try{let t=T?`${T}/get/ui_settings`:"/get/ui_settings",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json(),t=w(e);return console.error("Failed to get UI settings:",t),null}return await r.json()}catch(e){return console.error("Failed to get UI settings:",e),null}},tL=async e=>{try{return await z.get("/get/mcp_semantic_filter_settings",{accessToken:e})}catch(e){throw console.error("Failed to get MCP semantic filter settings:",e),e}},tH=async(e,t)=>{try{let r=T?`${T}/update/mcp_semantic_filter_settings`:"/update/mcp_semantic_filter_settings",n=await fetch(r,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error("Failed to update MCP semantic filter settings:",e),e}},tD=async(e,t,r)=>{try{let n=T?`${T}/v1/responses`:"/v1/responses",o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({model:t,input:[{role:"user",content:r,type:"message"}],tools:[{type:"mcp",server_url:"litellm_proxy",require_approval:"never"}],tool_choice:"required"})}),a=o.headers.get("x-litellm-semantic-filter"),i=o.headers.get("x-litellm-semantic-filter-tools");if(!o.ok){let e=await o.json(),t=w(e);throw F(t),Error(t)}return{data:await o.json(),headers:{filter:a,tools:i}}}catch(e){throw console.error("Failed to test MCP semantic filter:",e),e}},tV=async e=>{try{let t=T?`${T}/v2/guardrails/list`:"/v2/guardrails/list",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok)throw Error(`v2 guardrails/list returned ${r.status}`);return await r.json()}catch(t){console.log("v2/guardrails/list failed, falling back to v1:",t);try{let t=T?`${T}/guardrails/list`:"/guardrails/list",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json(),t=w(e);throw F(t),Error(t)}return await r.json()}catch(e){throw console.error("Failed to get guardrails list:",e),e}}},tW=async(e,t)=>z.get("/guardrails/submissions",{accessToken:e,query:{...t?.status?{status:t.status}:{},...t?.team_id?{team_id:t.team_id}:{},...t?.team_guardrail!==void 0?{team_guardrail:t.team_guardrail}:{},...t?.search?{search:t.search}:{}}}),tU=async(e,t)=>z.post(`/guardrails/submissions/${encodeURIComponent(t)}/approve`,{accessToken:e}),tG=async(e,t)=>z.post(`/guardrails/submissions/${encodeURIComponent(t)}/reject`,{accessToken:e}),tq=async(e,t,r)=>{try{let n=T?`${T}/guardrails/usage/overview`:"/guardrails/usage/overview",o=new URLSearchParams;t&&o.append("start_date",t),r&&o.append("end_date",r),o.toString()&&(n+=`?${o.toString()}`);let a=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!a.ok){let e=await a.json();throw Error(w(e))}return a.json()}catch(e){throw console.error("Failed to get guardrails usage overview:",e),e}},tK=async(e,t,r,n)=>{try{let o=T?`${T}/guardrails/usage/detail/${encodeURIComponent(t)}`:`/guardrails/usage/detail/${encodeURIComponent(t)}`,a=new URLSearchParams;r&&a.append("start_date",r),n&&a.append("end_date",n),a.toString()&&(o+=`?${a.toString()}`);let i=await fetch(o,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!i.ok){let e=await i.json();throw Error(w(e))}return i.json()}catch(e){throw console.error("Failed to get guardrails usage detail:",e),e}},tX=async(e,t)=>{try{let r=T?`${T}/guardrails/usage/logs`:"/guardrails/usage/logs",n=new URLSearchParams;t.guardrailId&&n.append("guardrail_id",t.guardrailId),t.policyId&&n.append("policy_id",t.policyId),null!=t.page&&n.append("page",String(t.page)),null!=t.pageSize&&n.append("page_size",String(t.pageSize)),t.action&&n.append("action",t.action),t.startDate&&n.append("start_date",t.startDate),t.endDate&&n.append("end_date",t.endDate),n.toString()&&(r+=`?${n.toString()}`);let o=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.json();throw Error(w(e))}return o.json()}catch(e){throw console.error("Failed to get guardrails usage logs:",e),e}},tJ=async e=>{try{return await z.get("/policies/list",{accessToken:e})}catch(e){throw console.error("Failed to get policies list:",e),e}},tY=async(e,t,r)=>{try{let n=T?`${T}/utils/test_policies_and_guardrails`:"/utils/test_policies_and_guardrails",o=await fetch(n,{method:"POST",signal:r,headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({policy_names:t.policy_names??null,guardrail_names:t.guardrail_names??null,inputs:t.inputs??null,inputs_list:t.inputs_list??null,request_data:t.request_data??{},input_type:t.input_type??"request",agent_id:t.agent_id??null})});if(!o.ok){let e=await o.text(),t="Failed to test policies and guardrails";try{let r=JSON.parse(e);r.detail?t="string"==typeof r.detail?r.detail:JSON.stringify(r.detail):r.message&&(t=r.message)}catch{t=e||t}throw F(t),Error(t)}return await o.json()}catch(e){throw console.error("Failed to test policies and guardrails:",e),e}},tQ=async(e,t)=>{try{return await z.get(`/policy/info/${t}`,{accessToken:e})}catch(e){throw console.error(`Failed to get policy info for ${t}:`,e),e}},tZ=async e=>{try{return await z.get("/policy/templates",{accessToken:e})}catch(e){throw console.error("Failed to get policy templates:",e),e}},t0=async(e,t,r,n,o)=>{try{let a=T?`${T}/policy/templates/enrich`:"/policy/templates/enrich",i={template_id:t,parameters:r};n&&(i.model=n),o&&(i.competitors=o);let l=await fetch(a,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(i)});if(!l.ok){let e=await l.json(),t=w(e);throw F(t),Error(t)}return await l.json()}catch(e){throw console.error("Failed to enrich policy template:",e),e}},t1=async(e,t,r,n)=>{try{return await z.post("/policy/templates/suggest",{accessToken:e,body:{attack_examples:t.filter(e=>e.trim()),description:r,model:n}})}catch(e){throw console.error("Failed to suggest policy templates:",e),e}},t2=async(e,t,r)=>{try{return await z.post("/policy/templates/test",{accessToken:e,body:{guardrail_definitions:t,text:r}})}catch(e){throw console.error("Failed to test policy template:",e),e}},t4=async(e,t,r,n,o,a,i,l,s)=>{let c=T?`${T}/policy/templates/enrich/stream`:"/policy/templates/enrich/stream",u={template_id:t,parameters:r,model:n};l?.instruction&&(u.instruction=l.instruction),l?.existingCompetitors&&(u.competitors=l.existingCompetitors);let d=await fetch(c,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(u)});if(!d.ok){let e=w(await d.json());throw F(e),Error(e)}let f=d.body?.getReader();if(!f)throw Error("No response body");let p=new TextDecoder,m="";for(;;){let{done:e,value:t}=await f.read();if(e)break;let r=(m+=p.decode(t,{stream:!0})).split("\n");for(let e of(m=r.pop()||"",r))if(e.startsWith("data: "))try{let t=JSON.parse(e.slice(6));"competitor"===t.type?o(t.name):"status"===t.type?s?.(t.message):"done"===t.type?a(t):"error"===t.type&&i?.(t.message)}catch{}}},t6=async(e,t,r,n,o,a,i,l,s)=>{let c=T?`${T}/usage/ai/chat`:"/usage/ai/chat",u=await fetch(c,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({messages:t,model:r}),signal:s});if(!u.ok){let e=w(await u.json());throw F(e),Error(e)}let d=u.body?.getReader();if(!d)throw Error("No response body");let f=new TextDecoder,p="";for(;;){let{done:e,value:t}=await d.read();if(e)break;let r=(p+=f.decode(t,{stream:!0})).split("\n");for(let e of(p=r.pop()||"",r))if(e.startsWith("data: "))try{let t=JSON.parse(e.slice(6));"chunk"===t.type?n(t.content):"status"===t.type?i?.(t.message):"tool_call"===t.type?l?.(t):"done"===t.type?o():"error"===t.type&&a?.(t.message)}catch{}}},t5=async(e,t)=>{try{return await z.post("/policies",{accessToken:e,body:t})}catch(e){throw console.error("Failed to create policy:",e),e}},t3=async(e,t,r)=>{try{return await z.put(`/policies/${t}`,{accessToken:e,body:r})}catch(e){throw console.error("Failed to update policy:",e),e}},t7=async(e,t)=>{try{let r=encodeURIComponent(t),n=T?`${T}/policies/name/${r}/versions`:`/policies/name/${r}/versions`,o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.json(),t=w(e);throw F(t),Error(t)}return await o.json()}catch(e){throw console.error("Failed to list policy versions:",e),e}},t8=async(e,t,r)=>{try{let n=encodeURIComponent(t),o=T?`${T}/policies/name/${n}/versions`:`/policies/name/${n}/versions`,a=await fetch(o,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({source_policy_id:r??void 0})});if(!a.ok){let e=await a.json(),t=w(e);throw F(t),Error(t)}return await a.json()}catch(e){throw console.error("Failed to create policy version:",e),e}},t9=async(e,t,r)=>{try{return await z.put(`/policies/${t}/status`,{accessToken:e,body:{version_status:r}})}catch(e){throw console.error("Failed to update policy version status:",e),e}},re=async(e,t)=>{try{return await z.delete(`/policies/${t}`,{accessToken:e})}catch(e){throw console.error("Failed to delete policy:",e),e}},rt=async(e,t)=>{try{return await z.get(`/policies/${t}`,{accessToken:e})}catch(e){throw console.error("Failed to get policy info:",e),e}},rr=async e=>{try{return await z.get("/policies/attachments/list",{accessToken:e})}catch(e){throw console.error("Failed to get policy attachments list:",e),e}},rn=async(e,t)=>{try{return await z.post("/policies/attachments",{accessToken:e,body:t})}catch(e){throw console.error("Failed to create policy attachment:",e),e}},ro=async(e,t)=>{try{let r=T?`${T}/policies/attachments/${t}`:`/policies/attachments/${t}`,n=await fetch(r,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error("Failed to delete policy attachment:",e),e}},ra=async(e,t,r)=>{try{return await z.post("/policies/test-pipeline",{accessToken:e,body:{pipeline:t,test_messages:r}})}catch(e){throw console.error("Failed to test pipeline:",e),e}},ri=async(e,t)=>{try{let r=T?`${T}/policies/${t}/resolved-guardrails`:`/policies/${t}/resolved-guardrails`,n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error("Failed to get resolved guardrails:",e),e}},rl=async(e,t)=>{try{return await z.post("/policies/resolve",{accessToken:e,body:t})}catch(e){throw console.error("Failed to resolve policies:",e),e}},rs=async(e,t)=>{try{let r=T?`${T}/policies/attachments/estimate-impact`:"/policies/attachments/estimate-impact",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let e=await n.json(),t=w(e);throw F(t),Error(t)}return await n.json()}catch(e){throw console.error("Failed to estimate attachment impact:",e),e}},rc=async(e,t)=>{try{return await z.get("/prompts/list",{accessToken:e,query:{environment:t||void 0}})}catch(e){throw console.error("Failed to get prompts list:",e),e}},ru=async(e,t,r)=>{try{return await z.get(`/prompts/${t}/info`,{accessToken:e,query:{environment:r||void 0}})}catch(e){throw console.error("Failed to get prompt info:",e),e}},rd=async(e,t,r)=>{try{let n=T?`${T}/prompts/${t}/versions`:`/prompts/${t}/versions`;r&&(n+=`?environment=${encodeURIComponent(r)}`);let o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.json(),t=w(e);throw 404!==o.status&&F(t),Error(t)}return await o.json()}catch(e){throw console.error("Failed to get prompt versions:",e),e}},rf=async(e,t)=>{try{return await z.post("/prompts",{accessToken:e,body:t})}catch(e){throw console.error("Failed to create prompt:",e),e}},rp=async(e,t,r)=>{try{return await z.put(`/prompts/${t}`,{accessToken:e,body:r})}catch(e){throw console.error("Failed to update prompt:",e),e}},rm=async(e,t)=>{try{return await z.delete(`/prompts/${t}`,{accessToken:e})}catch(e){throw console.error("Failed to delete prompt:",e),e}},rg=async(e,t)=>{try{let r=new FormData;r.append("file",t);let n=T?`${T}/utils/dotprompt_json_converter`:"/utils/dotprompt_json_converter",o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`},body:r});if(!o.ok){let e=await o.json(),t=w(e);throw F(t),Error(t)}return await o.json()}catch(e){throw console.error("Failed to convert prompt file:",e),e}},rh=async(e,t)=>{try{let r=T?`${T}/v1/agents`:"/v1/agents",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({...t})});if(!n.ok){let e=await n.text();throw F(e),Error(e)}let o=await n.json();return console.log("Create agent response:",o),o}catch(e){throw console.error("Failed to create agent:",e),e}},rv=async(e,t,r)=>{let n=T?`${T}/v1/a2a/discover`:"/v1/a2a/discover",o={url:t};r?.discovery_mode&&(o.discovery_mode=r.discovery_mode),r?.params&&(o.params=r.params);let a=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(o)});if(!a.ok){let e=await a.text();throw F(e),Error(e)}return await a.json()},ry=async(e,t)=>{try{let r=T?`${T}/guardrails`:"/guardrails",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({guardrail:t})});if(!n.ok){let e=await n.text();throw F(e),Error(e)}let o=await n.json();return console.log("Create guardrail response:",o),o}catch(e){throw console.error("Failed to create guardrail:",e),e}},rb=async(e,t,r)=>{try{let n=T?`${T}/spend/logs/ui/${t}?start_date=${encodeURIComponent(r)}`:`/spend/logs/ui/${t}?start_date=${encodeURIComponent(r)}`;console.log("Fetching log details from:",n);let o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.json(),t=w(e);throw F(t),Error(t)}let a=await o.json();return console.log("Fetched log details:",a),a}catch(e){throw console.error("Failed to fetch log details:",e),e}},rw=async e=>{try{let t=await z.get("/get/internal_user_settings",{accessToken:e});return console.log("Fetched SSO settings:",t),t}catch(e){throw console.error("Failed to fetch SSO settings:",e),e}},rC=async(e,t)=>{try{let r=T?`${T}/update/internal_user_settings`:"/update/internal_user_settings";console.log("Updating internal user settings:",t);let n=await fetch(r,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let e=await n.text();throw F(e),Error(e)}let o=await n.json();return console.log("Updated internal user settings:",o),y.default.success("Internal user settings updated successfully"),o}catch(e){throw console.error("Failed to update internal user settings:",e),e}},rx=async e=>{try{let t=T?`${T}/v1/mcp/openapi-registry`:"/v1/mcp/openapi-registry",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json();throw Error(w(e))}return await r.json()}catch(e){throw console.error("Failed to fetch OpenAPI registry:",e),e}},rS=async e=>{try{return await z.get("/v1/mcp/discover",{accessToken:e})}catch(e){throw console.error("Failed to fetch discoverable MCP servers:",e),e}},r$=async(e,t)=>{try{return await z.get("/v1/mcp/server",{accessToken:e,query:{team_id:t||void 0}})}catch(e){throw console.error("Failed to fetch MCP servers:",e),e}},rE=async(e,t)=>{try{return await z.get("/v1/mcp/server/health",{accessToken:e,query:{server_ids:t&&t.length>0?t:void 0}})}catch(e){throw console.error("Failed to fetch MCP server health:",e),e}},rk=async e=>{try{let t=await z.get("/v1/mcp/access_groups",{accessToken:e});return console.log("Fetched MCP access groups:",t),t.access_groups||[]}catch(e){throw console.error("Failed to fetch MCP access groups:",e),e}},rO=async e=>{try{let t=T?`${T}/v1/mcp/network/client-ip`:"/v1/mcp/network/client-ip",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`}});if(!r.ok)return null;return(await r.json()).ip||null}catch{return null}},rj=async(e,t)=>{try{console.log("Form Values in createMCPServer:",t);let r=await z.post("/v1/mcp/server",{accessToken:e,body:{...t}});return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},rT=async(e,t)=>{try{return await z.put("/v1/mcp/server",{accessToken:e,body:t})}catch(e){throw console.error("Failed to update MCP server:",e),e}},r_=async(e,t)=>{try{console.log("in deleteMCPServer:",t),await z.delete(`/v1/mcp/server/${t}`,{accessToken:e})}catch(e){throw console.error("Failed to delete key:",e),e}},rP=async e=>{try{return await z.get("/v1/mcp/toolset",{accessToken:e})}catch(e){throw console.error("Failed to fetch MCP toolsets:",e),e}},rI=async(e,t)=>{try{return await z.post("/v1/mcp/toolset",{accessToken:e,body:t})}catch(e){throw console.error("Failed to create MCP toolset:",e),e}},rF=async(e,t)=>{try{return await z.put("/v1/mcp/toolset",{accessToken:e,body:t})}catch(e){throw console.error("Failed to update MCP toolset:",e),e}},rN=async(e,t)=>{try{await z.delete(`/v1/mcp/toolset/${t}`,{accessToken:e})}catch(e){throw console.error("Failed to delete MCP toolset:",e),e}},rR=async(e,t)=>{try{return await z.post("/v1/mcp/server/register",{accessToken:e,body:t})}catch(e){throw console.error("Failed to register MCP server:",e),e}},rM=async e=>{try{let t=(T?`${T}`:"")+"/v1/mcp/server/submissions",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json().catch(()=>({})),t=w(e);throw F(t),Error(t)}return r.json()}catch(e){throw console.error("Failed to fetch MCP submissions:",e),e}},rA=async(e,t)=>{try{let r=(T?`${T}`:"")+`/v1/mcp/server/${encodeURIComponent(t)}/approve`,n=await fetch(r,{method:"PUT",headers:{[M]:`Bearer ${e}`}});if(!n.ok){let e=await n.json().catch(()=>({})),t=w(e);throw F(t),Error(t)}return n.json()}catch(e){throw console.error("Failed to approve MCP server:",e),e}},rB=async(e,t,r)=>{try{let n=(T?`${T}`:"")+`/v1/mcp/server/${encodeURIComponent(t)}/reject`,o=await fetch(n,{method:"PUT",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({review_notes:r??null})});if(!o.ok){let e=await o.json().catch(()=>({})),t=w(e);throw F(t),Error(t)}return o.json()}catch(e){throw console.error("Failed to reject MCP server:",e),e}},rz=async e=>{try{let t=await z.get("/search_tools/list",{accessToken:e});return console.log("Fetched search tools:",t),t}catch(e){throw console.error("Failed to fetch search tools:",e),e}},rL=async(e,t)=>{try{console.log("Creating search tool with values:",t);let r=await z.post("/search_tools",{accessToken:e,body:{search_tool:t}});return console.log("Created search tool:",r),r}catch(e){throw console.error("Failed to create search tool:",e),e}},rH=async(e,t,r)=>{try{console.log("Updating search tool with ID:",t,"values:",r);let n=await z.put(`/search_tools/${t}`,{accessToken:e,body:{search_tool:r}});return console.log("Updated search tool:",n),n}catch(e){throw console.error("Failed to update search tool:",e),e}},rD=async(e,t)=>{try{console.log("Deleting search tool:",t);let r=await z.delete(`/search_tools/${t}`,{accessToken:e});return console.log("Deleted search tool:",r),r}catch(e){throw console.error("Failed to delete search tool:",e),e}},rV=async e=>{try{let t=T?`${T}/search_tools/ui/available_providers`:"/search_tools/ui/available_providers";console.log("Fetching available search providers from:",t);let r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.json(),t=w(e);throw F(t),Error(t)}let n=await r.json();return console.log("Fetched available search providers:",n),n}catch(e){throw console.error("Failed to fetch available search providers:",e),e}},rW=async(e,t)=>{try{let r=await z.post("/search_tools/test_connection",{accessToken:e,body:{litellm_params:t}});return console.log("Test connection response:",r),r}catch(e){throw console.error("Failed to test search tool connection:",e),e}},rU=async(e,t,r,n)=>{let o,a=`server_id=${t}${n?"&include_disabled_tools=true":""}`,i=T?`${T}/mcp-rest/tools/list?${a}`:`/mcp-rest/tools/list?${a}`;console.log("Fetching MCP tools from:",i);let l={[M]:`Bearer ${e}`,"Content-Type":"application/json",...r};try{o=await fetch(i,{method:"GET",headers:l})}catch(e){return console.error("Failed to fetch MCP tools (network error):",e),{tools:[],error:"network_error",message:e instanceof Error?e.message:"Failed to fetch MCP tools",stack_trace:null}}let s=null;try{s=await o.json()}catch(e){return console.error("Failed to parse MCP tools response:",e),{tools:[],error:"parse_error",message:"Failed to parse MCP tools response",status:o.status,statusText:o.statusText,stack_trace:null}}if(console.log("Fetched MCP tools response:",s),!o.ok){let e=s&&(s.message||s.error)||"Failed to fetch MCP tools";return{tools:[],error:s&&s.error||`http_${o.status}`,message:e,status:o.status,statusText:o.statusText,details:s,stack_trace:null}}return s},rG=async(e,t,r,n,o)=>{try{let a=T?`${T}/mcp-rest/tools/call`:"/mcp-rest/tools/call";console.log("Calling MCP tool:",r,"with arguments:",n,"for server:",t);let i={[M]:`Bearer ${e}`,"Content-Type":"application/json",...o?.customHeaders||{}},l={server_id:t,name:r,arguments:n};o?.guardrails&&o.guardrails.length>0&&(l.litellm_metadata={guardrails:o.guardrails});let s=await fetch(a,{method:"POST",headers:i,body:JSON.stringify(l)});if(!s.ok){let e="Network response was not ok",t=null,r=await s.text();try{let n=JSON.parse(r);n.detail?"string"==typeof n.detail?e=n.detail:"object"==typeof n.detail&&(e=n.detail.message||n.detail.error||"An error occurred",t=n.detail):e=n.message||n.error||e}catch(t){console.error("Failed to parse JSON error response:",t),r&&(e=r)}let n=Error(e);throw n.status=s.status,n.statusText=s.statusText,n.details=t,F(e),n}let c=await s.json();return console.log("MCP tool call response:",c),c}catch(e){throw console.error("Failed to call MCP tool:",e),console.error("Error type:",typeof e),e instanceof Error&&(console.error("Error message:",e.message),console.error("Error stack:",e.stack)),e}},rq=async(e,t)=>{try{let r=T?`${T}/tag/new`:"/tag/new",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify(t)});if(!n.ok){let e=await n.text();await F(e);return}return await n.json()}catch(e){throw console.error("Error creating tag:",e),e}},rK=async(e,t)=>{try{let r=T?`${T}/tag/update`:"/tag/update",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify(t)});if(!n.ok){let e=await n.text();await F(e);return}return await n.json()}catch(e){throw console.error("Error updating tag:",e),e}},rX=async(e,t)=>{try{let r=T?`${T}/tag/info`:"/tag/info",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify({names:t})});if(!n.ok){let e=await n.text();return await F(e),{}}return await n.json()}catch(e){throw console.error("Error getting tag info:",e),e}},rJ=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}-${r}-${n}`},rY=async(e,t,r)=>{try{let n=T?`${T}/tag/list`:"/tag/list";if(t&&r){let e=new URLSearchParams({start_date:rJ(t),end_date:rJ(r)});n=`${n}?${e.toString()}`}let o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`}});if(!o.ok){let e=await o.text();return await F(e),{}}return await o.json()}catch(e){throw console.error("Error listing tags:",e),e}},rQ=async(e,t)=>{try{let r=T?`${T}/tag/delete`:"/tag/delete",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify({name:t})});if(!n.ok){let e=await n.text();await F(e);return}return await n.json()}catch(e){throw console.error("Error deleting tag:",e),e}},rZ=async e=>{try{let t=await z.get("/get/default_team_settings",{accessToken:e});return console.log("Fetched default team settings:",t),t}catch(e){throw console.error("Failed to fetch default team settings:",e),e}},r0=async(e,t)=>{try{console.log("Updating default team settings:",t);let r=await z.patch("/update/default_team_settings",{accessToken:e,body:t});return console.log("Updated default team settings:",r),r}catch(e){throw console.error("Failed to update default team settings:",e),e}},r1=async(e,t)=>{try{let r=T?`${T}/team/permissions_list?team_id=${t}`:`/team/permissions_list?team_id=${t}`,n=await fetch(r,{method:"GET",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`}});if(!n.ok){let e=await n.json(),t=w(e);return console.error("Available permissions fetch failed:",t),{all_available_permissions:[],team_member_permissions:[]}}return await n.json()}catch(e){throw console.error("Failed to get team permissions:",e),e}},r2=async(e,t,r)=>{try{let n=await z.post("/team/permissions_update",{accessToken:e,body:{team_id:t,team_member_permissions:r}});return console.log("Team permissions response:",n),n}catch(e){throw console.error("Failed to update team permissions:",e),e}},r4=async(e,t,r=1,n=100)=>{try{let o=new URLSearchParams({session_id:t,page:String(r),page_size:String(n)}),a=T?`${T}/spend/logs/session/ui?${o.toString()}`:`/spend/logs/session/ui?${o.toString()}`,i=await fetch(a,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!i.ok){let e=await i.json(),t=w(e);throw F(t),Error(t)}return await i.json()}catch(e){throw console.error("Failed to fetch session logs:",e),e}},r6=async(e,t)=>{try{let r=T?`${T}/vector_store/new`:"/vector_store/new",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json();throw Error(e.detail||"Failed to create vector store")}return await n.json()}catch(e){throw console.error("Error creating vector store:",e),e}},r5=async(e,t=1,r=100)=>{try{let t=T?`${T}/vector_store/list`:"/vector_store/list",r=await fetch(t,{method:"GET",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`}});if(!r.ok){let e=await r.json();throw Error(e.detail||"Failed to list vector stores")}return await r.json()}catch(e){throw console.error("Error listing vector stores:",e),e}},r3=async(e,t)=>{try{let r=T?`${T}/vector_store/delete`:"/vector_store/delete",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify({vector_store_id:t})});if(!n.ok){let e=await n.json();throw Error(e.detail||"Failed to delete vector store")}return await n.json()}catch(e){throw console.error("Error deleting vector store:",e),e}},r7=async(e,t)=>{try{let r=T?`${T}/vector_store/info`:"/vector_store/info",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify({vector_store_id:t})});if(!n.ok){let e=await n.json();throw Error(e.detail||"Failed to get vector store info")}return await n.json()}catch(e){throw console.error("Error getting vector store info:",e),e}},r8=async(e,t)=>{try{let r=T?`${T}/vector_store/update`:"/vector_store/update",n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",[M]:`Bearer ${e}`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json();throw Error(e.detail||"Failed to update vector store")}return await n.json()}catch(e){throw console.error("Error updating vector store:",e),e}},r9=async(e,t,r,n,o,a,i)=>{try{let l=T?`${T}/rag/ingest`:"/rag/ingest",s=new FormData;s.append("file",t);let c={ingest_options:{vector_store:{custom_llm_provider:r,...n&&{vector_store_id:n},...i&&i}}};(o||a)&&(c.ingest_options.litellm_vector_store_params={},o&&(c.ingest_options.litellm_vector_store_params.vector_store_name=o),a&&(c.ingest_options.litellm_vector_store_params.vector_store_description=a)),s.append("request",JSON.stringify(c));let u=await fetch(l,{method:"POST",headers:{[M]:`Bearer ${e}`},body:s});if(!u.ok){let e=await u.json();throw Error(e.error?.message||e.detail||"Failed to ingest document")}return await u.json()}catch(e){throw console.error("Error ingesting document:",e),e}},ne=async e=>{try{let t=T?`${T}/email/event_settings`:"/email/event_settings",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw F(e),Error("Failed to get email event settings")}let n=await r.json();return console.log("Email event settings response:",n),n}catch(e){throw console.error("Failed to get email event settings:",e),e}},nt=async(e,t)=>{try{let r=T?`${T}/email/event_settings`:"/email/event_settings",n=await fetch(r,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let e=await n.text();throw F(e),Error("Failed to update email event settings")}let o=await n.json();return console.log("Update email event settings response:",o),o}catch(e){throw console.error("Failed to update email event settings:",e),e}},nr=async e=>{try{let t=T?`${T}/email/event_settings/reset`:"/email/event_settings/reset",r=await fetch(t,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw F(e),Error("Failed to reset email event settings")}let n=await r.json();return console.log("Reset email event settings response:",n),n}catch(e){throw console.error("Failed to reset email event settings:",e),e}},nn=async(e,t)=>{try{let r=T?`${T}/v1/agents/${t}`:`/v1/agents/${t}`,n=await fetch(r,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw F(e),Error(e)}let o=await n.json();return console.log("Delete agent response:",o),o}catch(e){throw console.error("Failed to delete agent:",e),e}},no=async(e,t)=>{try{let r=T?`${T}/v1/agents/make_public`:"/v1/agents/make_public",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({agent_ids:t})});if(!n.ok){let e=await n.text();throw F(e),Error(e)}let o=await n.json();return console.log("Make agents public response:",o),o}catch(e){throw console.error("Failed to make agents public:",e),e}},na=async(e,t)=>{try{let r=T?`${T}/v1/mcp/make_public`:"/v1/mcp/make_public",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({mcp_server_ids:t})});if(!n.ok){let e=await n.text();throw F(e),Error(e)}let o=await n.json();return console.log("Make agents public response:",o),o}catch(e){throw console.error("Failed to make agents public:",e),e}},ni=async(e,t)=>{try{let r=T?`${T}/guardrails/${t}`:`/guardrails/${t}`,n=await fetch(r,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw F(e),Error(e)}let o=await n.json();return console.log("Delete guardrail response:",o),o}catch(e){throw console.error("Failed to delete guardrail:",e),e}},nl=async e=>{try{let t=T?`${T}/guardrails/ui/add_guardrail_settings`:"/guardrails/ui/add_guardrail_settings",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw F(e),Error("Failed to get guardrail UI settings")}let n=await r.json();return console.log("Guardrail UI settings response:",n),n}catch(e){throw console.error("Failed to get guardrail UI settings:",e),e}},ns=async e=>{try{let t=T?`${T}/guardrails/ui/provider_specific_params`:"/guardrails/ui/provider_specific_params",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw F(e),Error("Failed to get guardrail provider specific parameters")}let n=await r.json();return console.log("Guardrail provider specific params response:",n),n}catch(e){throw console.error("Failed to get guardrail provider specific parameters:",e),e}},nc=async(e,t)=>{try{let r=encodeURIComponent(t),n=T?`${T}/guardrails/ui/category_yaml/${r}`:`/guardrails/ui/category_yaml/${r}`;console.log(`Fetching category YAML from: ${n}`);let o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.text();throw console.error(`Failed to get category YAML. Status: ${o.status}, Error:`,e),F(e),Error(`Failed to get category YAML: ${o.status} ${e}`)}let a=await o.json();return console.log("Category YAML response:",a),a}catch(e){throw console.error("Failed to get category YAML:",e),e}},nu=async e=>{try{let t=T?`${T}/guardrails/ui/major_airlines`:"/guardrails/ui/major_airlines",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw console.error(`Failed to get major airlines. Status: ${r.status}, Error:`,e),F(e),Error(`Failed to get major airlines: ${r.status} ${e}`)}return await r.json()}catch(e){throw console.error("Failed to get major airlines:",e),e}},nd=async(e,t=!1)=>{try{let r=t?"?health_check=true":"",n=T?`${T}/v1/agents${r}`:`/v1/agents${r}`,o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.text();throw F(e),Error("Failed to get agents list")}let a=await o.json();return console.log("Agents list response:",a),{agents:a}}catch(e){throw console.error("Failed to get agents list:",e),e}},nf=async(e,t)=>{try{let r=T?`${T}/v1/agents/${t}`:`/v1/agents/${t}`,n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw F(e),Error("Failed to get agent info")}let o=await n.json();return console.log("Agent info response:",o),o}catch(e){throw console.error("Failed to get agent info:",e),e}},np=async(e,t)=>{try{let r=T?`${T}/guardrails/${t}/info`:`/guardrails/${t}/info`,n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw F(e),Error("Failed to get guardrail info")}let o=await n.json();return console.log("Guardrail info response:",o),o}catch(e){throw console.error("Failed to get guardrail info:",e),e}},nm=async(e,t,r)=>{try{let n=T?`${T}/v1/agents/${t}`:`/v1/agents/${t}`,o=await fetch(n,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!o.ok){let e=await o.text();throw F(e),Error("Failed to patch agent")}let a=await o.json();return console.log("Patch agent response:",a),a}catch(e){throw console.error("Failed to update guardrail:",e),e}},ng=async(e,t,r)=>{try{let n=T?`${T}/guardrails/${t}`:`/guardrails/${t}`,o=await fetch(n,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!o.ok){let e=await o.text();throw F(e),Error("Failed to update guardrail")}let a=await o.json();return console.log("Update guardrail response:",a),a}catch(e){throw console.error("Failed to update guardrail:",e),e}},nh=async(e,t,r,n,o)=>{try{let a=T?`${T}/guardrails/apply_guardrail`:"/guardrails/apply_guardrail",i={guardrail_name:t,text:r};n&&(i.language=n),o&&o.length>0&&(i.entities=o);let l=await fetch(a,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(i)});if(!l.ok){let e=await l.text(),t="Failed to apply guardrail";try{let r=JSON.parse(e);r.error?.message?t=r.error.message:r.detail?t=r.detail:r.message&&(t=r.message)}catch(r){t=e||t}throw F(e),Error(t)}let s=await l.json();return console.log("Apply guardrail response:",s),s}catch(e){throw console.error("Failed to apply guardrail:",e),e}},nv=async(e,t)=>{try{let r=T?`${T}/guardrails/test_custom_code`:"/guardrails/test_custom_code",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let e=await n.text(),t="Failed to test custom code guardrail";try{let r=JSON.parse(e);r.error?.message?t=r.error.message:r.detail?t=r.detail:r.message&&(t=r.message)}catch(r){t=e||t}throw F(e),Error(t)}let o=await n.json();return console.log("Test custom code guardrail response:",o),o}catch(e){throw console.error("Failed to test custom code guardrail:",e),e}},ny=async(e,t)=>{try{let r=T?`${T}/guardrails/validate_blocked_words_file`:"/guardrails/validate_blocked_words_file",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({file_content:t})});if(!n.ok){let e=await n.text();throw F(e),Error("Failed to validate blocked words file")}let o=await n.json();return console.log("Validate blocked words file response:",o),o}catch(e){throw console.error("Failed to validate blocked words file:",e),e}},nb=async e=>{try{let t=await z.get("/get/sso_settings",{accessToken:e});return console.log("Fetched SSO configuration:",t),t}catch(e){throw console.error("Failed to fetch SSO configuration:",e),e}},nw=async(e,t)=>{try{let r=T?`${T}/update/sso_settings`:"/update/sso_settings";console.log("Updating SSO configuration:",t);let n=await fetch(r,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let e=await n.json(),t="object"==typeof e?.detail?e.detail?.error||e.detail?.message:e?.detail,r="string"==typeof t&&t.length>0?t:w(e);F(r);let o=Error(r);throw e?.detail!==void 0&&(o.detail=e.detail),o.rawError=e,o}let o=await n.json();return console.log("Updated SSO configuration:",o),o}catch(e){throw console.error("Failed to update SSO configuration:",e),e}},nC=async({accessToken:e,page:t=1,page_size:r=50,params:n={}})=>{try{let o=T?`${T}/audit`:"/audit",a=new URLSearchParams;for(let[e,o]of(a.append("page",t.toString()),a.append("page_size",r.toString()),Object.entries(n)))null!=o&&""!==o&&a.append(e,String(o));o+=`?${a.toString()}`;let i=await fetch(o,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!i.ok){let e=await i.json(),t=w(e);throw F(t),Error(t)}return await i.json()}catch(e){throw console.error("Failed to fetch audit logs:",e),e}},nx=async e=>{try{let t=T?`${T}/user/available_users`:"/user/available_users",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`}});if(!r.ok){if(404===r.status)return null;let e=await r.text();throw F(e),Error("Network response was not ok")}return await r.json()}catch(e){throw console.error("Failed to fetch remaining users:",e),e}},nS=async e=>{try{let t=T?`${T}/health/license`:"/health/license",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`}});if(!r.ok){if(404===r.status)return null;let e=await r.text();throw F(e),Error("Network response was not ok")}return await r.json()}catch(e){throw console.error("Failed to fetch license info:",e),e}},n$=async(e,t,r)=>{try{let n=T?`${T}/config/pass_through_endpoint/${encodeURIComponent(t)}`:`/config/pass_through_endpoint/${encodeURIComponent(t)}`,o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!o.ok){let e=await o.json(),t=w(e);throw F(t),Error(t)}let a=await o.json();return y.default.success("Pass through endpoint updated successfully"),a}catch(e){throw console.error("Failed to update pass through endpoint:",e),e}},nE=async(e,t)=>{try{return await z.post("/config/callback/delete",{accessToken:e,body:{callback_name:t}})}catch(e){throw console.error("Failed to delete specific callback:",e),e}},nk=async(e,t,r)=>{try{console.log("Testing MCP tools list with config:",JSON.stringify(t));let n=T?`${T}/mcp-rest/test/tools/list`:"/mcp-rest/test/tools/list",o={"Content-Type":"application/json"};e&&(o["x-litellm-api-key"]=e),r?o.Authorization=`Bearer ${r}`:e&&(o[M]=`Bearer ${e}`);let a=await fetch(n,{method:"POST",headers:o,body:JSON.stringify(t)}),i=a.headers.get("content-type");if(!i||!i.includes("application/json")){let e=await a.text();throw console.error("Received non-JSON response:",e),Error(`Received non-JSON response (${a.status}: ${a.statusText}). Check network tab for details.`)}let l=await a.json();if((!a.ok||l.error)&&!l.error)return{tools:[],error:"request_failed",message:l.message||`MCP tools list failed: ${a.status} ${a.statusText}`};return l}catch(e){throw console.error("MCP tools list test error:",e),e}},nO=async(e,t)=>{let r=T?`${T}/v1/mcp/server/oauth/session`:"/v1/mcp/server/oauth/session",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)}),o=await n.json();if(!n.ok)throw Error(w(o)||o?.error||"Failed to cache MCP server");return o},nj=async(e,t,r)=>{let n=_(),o=encodeURIComponent(t.trim()),a=`${n}/v1/mcp/server/oauth/${o}/register`,i=await fetch(a,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json",Accept:"application/json, text/event-stream"},body:JSON.stringify(r)}),l=await i.json();if(!i.ok)throw Error(w(l)||l?.detail||"Failed to register OAuth client");return l},nT=({serverId:e,clientId:t,redirectUri:r,state:n,codeChallenge:o,scope:a})=>{let i=_(),l=encodeURIComponent(e.trim()),s=`${i}/v1/mcp/server/oauth/${l}/authorize`,c=new URLSearchParams({redirect_uri:r,state:n,response_type:"code",code_challenge:o,code_challenge_method:"S256"});return t&&t.trim().length>0&&c.set("client_id",t),a&&a.trim().length>0&&c.set("scope",a),`${s}?${c.toString()}`},n_=async({serverId:e,code:t,clientId:r,clientSecret:n,codeVerifier:o,redirectUri:a,accessToken:i})=>{let l=_(),s=encodeURIComponent(e.trim()),c=`${l}/v1/mcp/server/oauth/${s}/token`,u=new URLSearchParams;u.set("grant_type","authorization_code"),u.set("code",t),r&&r.trim().length>0&&u.set("client_id",r),n&&n.trim().length>0&&u.set("client_secret",n),u.set("code_verifier",o),u.set("redirect_uri",a);let d={"Content-Type":"application/x-www-form-urlencoded"};i&&(d.Authorization=`Bearer ${i}`);let f=await fetch(c,{method:"POST",headers:d,body:u.toString()}),p=await f.json();if(!f.ok)throw Error(w(p)||p?.detail||"OAuth token exchange failed");return p},nP=async(e,t,r)=>{try{let n=`${_()}/v1/vector_stores/${t}/search`,o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({query:r})});if(!o.ok){let e=await o.text();return await F(e),null}return await o.json()}catch(e){throw console.error("Error testing vector store search:",e),e}},nI=async(e,t,r,n)=>{try{let o=`${_()}/v1/search/${t}`,a=await fetch(o,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({query:r,max_results:n||5})});if(!a.ok){let e=await a.text();return await F(e),null}return await a.json()}catch(e){throw console.error("Error querying search tool:",e),e}},nF=async(e,t,r,n)=>{try{let o,a,i,l=n&&n.length>0;return await z.get("/tag/dau",{accessToken:e,query:{end_date:(o=t.getFullYear(),a=String(t.getMonth()+1).padStart(2,"0"),i=String(t.getDate()).padStart(2,"0"),`${o}-${a}-${i}`),tag_filters:l?n:void 0,tag_filter:!l&&r?r:void 0}})}catch(e){throw console.error("Failed to fetch DAU:",e),e}},nN=async(e,t,r,n)=>{try{let o,a,i,l=n&&n.length>0;return await z.get("/tag/wau",{accessToken:e,query:{end_date:(o=t.getFullYear(),a=String(t.getMonth()+1).padStart(2,"0"),i=String(t.getDate()).padStart(2,"0"),`${o}-${a}-${i}`),tag_filters:l?n:void 0,tag_filter:!l&&r?r:void 0}})}catch(e){throw console.error("Failed to fetch WAU:",e),e}},nR=async(e,t,r,n)=>{try{let o,a,i,l=n&&n.length>0;return await z.get("/tag/mau",{accessToken:e,query:{end_date:(o=t.getFullYear(),a=String(t.getMonth()+1).padStart(2,"0"),i=String(t.getDate()).padStart(2,"0"),`${o}-${a}-${i}`),tag_filters:l?n:void 0,tag_filter:!l&&r?r:void 0}})}catch(e){throw console.error("Failed to fetch MAU:",e),e}},nM=async e=>{try{return await z.get("/tag/distinct",{accessToken:e})}catch(e){throw console.error("Failed to fetch distinct tags:",e),e}},nA=async(e,t,r,n)=>{try{let o=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}-${r}-${n}`};return await z.get("/tag/summary",{accessToken:e,query:{start_date:o(t),end_date:o(r),tag_filters:n&&n.length>0?n:void 0}})}catch(e){throw console.error("Failed to fetch user agent summary:",e),e}},nB=async(e,t=1,r=50,n)=>{try{return await z.get("/tag/user-agent/per-user-analytics",{accessToken:e,query:{page:t.toString(),page_size:r.toString(),tag_filters:n&&n.length>0?n:void 0}})}catch(e){throw console.error("Failed to fetch per-user analytics:",e),e}},nz=async(e,t,r)=>{let o=_(),a=r?"/v3/login":"/v2/login",i=o?`${o}${a}`:a,l=JSON.stringify({username:e,password:t}),s=await fetch(i,{method:"POST",body:l,credentials:"include",headers:{"Content-Type":"application/json"}});if(!s.ok)throw Error(w(await s.json()));let c=await s.json();if(r&&c.code){let e=o?`${o}/v3/login/exchange`:"/v3/login/exchange",t=await fetch(e,{method:"POST",body:JSON.stringify({code:c.code}),credentials:"include",headers:{"Content-Type":"application/json"}});if(!t.ok)throw Error(w(await t.json()));let r=await t.json();return r.token&&(0,n.storeLoginToken)(r.token),r}return c.token&&(0,n.storeLoginToken)(c.token),c},nL=async(e,t)=>{let r=t||_(),n=await fetch(`${r}/v3/login/exchange`,{method:"POST",body:JSON.stringify({code:e}),headers:{"Content-Type":"application/json"}});if(!n.ok)throw Error(w(await n.json()));let o=await n.json();return o.token&&(document.cookie=`token=${o.token}; path=/; SameSite=Lax`),o.token},nH=async()=>{let e=_(),t=e?`${e}/get/ui_settings`:"/get/ui_settings",r=await fetch(t,{method:"GET"});if(!r.ok)throw Error(w(await r.json()));return await r.json()},nD=async(e,t)=>{let r=_(),n=r?`${r}/update/ui_settings`:"/update/ui_settings",o=await fetch(n,{method:"PATCH",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!o.ok)throw Error(w(await o.json()));return await o.json()},nV=async(e,t=!1)=>{try{let r=_(),n=r?`${r}/claude-code/plugins?enabled_only=${t}`:`/claude-code/plugins?enabled_only=${t}`,o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.text(),t=w(JSON.parse(e));throw F(t),Error(t)}return await o.json()}catch(e){throw console.error("Failed to fetch Claude Code plugins list:",e),e}},nW=async(e,t)=>{try{let r=_(),n=r?`${r}/claude-code/plugins`:"/claude-code/plugins",o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!o.ok){let e=await o.text(),t=w(JSON.parse(e));throw F(t),Error(t)}return await o.json()}catch(e){throw console.error("Failed to register Claude Code plugin:",e),e}},nU=async(e,t)=>{try{let r=_(),n=r?`${r}/claude-code/plugins/${t}/enable`:`/claude-code/plugins/${t}/enable`,o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.text(),t=w(JSON.parse(e));throw F(t),Error(t)}return await o.json()}catch(e){throw console.error(`Failed to enable plugin "${t}":`,e),e}},nG=async(e,t)=>{try{let r=_(),n=r?`${r}/claude-code/plugins/${t}/disable`:`/claude-code/plugins/${t}/disable`,o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.text(),t=w(JSON.parse(e));throw F(t),Error(t)}return await o.json()}catch(e){throw console.error(`Failed to disable plugin "${t}":`,e),e}},nq=async(e,t)=>{try{let r=_(),n=r?`${r}/claude-code/plugins/${t}`:`/claude-code/plugins/${t}`,o=await fetch(n,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok){let e=await o.text(),t=w(JSON.parse(e));throw F(t),Error(t)}return await o.json()}catch(e){throw console.error(`Failed to delete plugin "${t}":`,e),e}},nK=async(e,t)=>{let r=T?`${T}/compliance/eu-ai-act`:"/compliance/eu-ai-act",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok)throw Error(await n.text());return n.json()},nX=async(e,t)=>{let r=T?`${T}/compliance/gdpr`:"/compliance/gdpr",n=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok)throw Error(await n.text());return n.json()},nJ=async e=>{let t=T?`${T}/v1/tool/policy/options`:"/v1/tool/policy/options",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok)throw Error(await r.text());return r.json()},nY=async e=>{let t=T?`${T}/v1/tool/list`:"/v1/tool/list",r=await fetch(t,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!r.ok)throw Error(await r.text());return(await r.json()).tools??[]},nQ=async(e,t,r)=>{let n=encodeURIComponent(t),o=T?`${T}/v1/tool/${n}/logs`:`/v1/tool/${n}/logs`,a=new URLSearchParams;null!=r.page&&a.append("page",String(r.page)),null!=r.pageSize&&a.append("page_size",String(r.pageSize)),r.startDate&&a.append("start_date",r.startDate),r.endDate&&a.append("end_date",r.endDate);let i=a.toString()?`${o}?${a.toString()}`:o,l=await fetch(i,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!l.ok)throw Error(w(await l.json().catch(()=>({}))));return l.json()},nZ=async(e,t)=>{let r=encodeURIComponent(t),n=T?`${T}/v1/tool/${r}/detail`:`/v1/tool/${r}/detail`,o=await fetch(n,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok)throw Error(await o.text());return o.json()},n0=async(e,t,r,n)=>{let o=T?`${T}/v1/tool/policy`:"/v1/tool/policy",a={tool_name:t};null!=r.input_policy&&(a.input_policy=r.input_policy),null!=r.output_policy&&(a.output_policy=r.output_policy),n?.team_id!=null&&(a.team_id=n.team_id||void 0),n?.key_hash!=null&&(a.key_hash=n.key_hash||void 0),n?.key_alias!=null&&(a.key_alias=n.key_alias||void 0);let i=await fetch(o,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(a)});if(!i.ok)throw Error(await i.text());return i.json()},n1=async(e,t,r)=>{let n=encodeURIComponent(t),o=new URLSearchParams;null!=r.team_id&&""!==r.team_id&&o.set("team_id",r.team_id),null!=r.key_hash&&""!==r.key_hash&&o.set("key_hash",r.key_hash);let a=o.toString(),i=T?`${T}/v1/tool/${n}/overrides${a?`?${a}`:""}`:`/v1/tool/${n}/overrides${a?`?${a}`:""}`,l=await fetch(i,{method:"DELETE",headers:{[M]:`Bearer ${e}`}});if(!l.ok)throw Error(await l.text());return l.json()},n2=async(e,t,r)=>{let n=T?`${T}/v1/mcp/server/${t}/oauth-user-credential`:`/v1/mcp/server/${t}/oauth-user-credential`,o=await fetch(n,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!o.ok){let e=await o.json().catch(()=>({})),t=e?.detail;throw Error((Array.isArray(t)?t.map(e=>e&&"object"==typeof e?e.msg??JSON.stringify(e):String(e)).join("; "):"string"==typeof t?t:t&&"string"==typeof t.error?t.error:void 0)||"Failed to store OAuth credential")}return o.json()},n4=async(e,t)=>{let r=T?`${T}/v1/mcp/server/${t}/oauth-user-credential/status`:`/v1/mcp/server/${t}/oauth-user-credential/status`,n=await fetch(r,{method:"GET",headers:{[M]:`Bearer ${e}`}});return n.ok?n.json():{server_id:t,has_credential:!1,is_expired:!1}},n6=async(e,t)=>z.get(`/v1/mcp/server/${t}/user-env-vars`,{accessToken:e}),n5=async(e,t,r)=>z.post(`/v1/mcp/server/${t}/user-env-vars`,{accessToken:e,body:{values:r}}),n3=async e=>{try{return await z.get("/v1/mcp/user-env-vars/status",{accessToken:e})}catch{return[]}},n7=e=>e.split("/").map(encodeURIComponent).join("/"),n8=async(e,t={})=>{let r=T?`${T}/v1/memory`:"/v1/memory",n=new URLSearchParams;t.keyPrefix?n.append("key_prefix",t.keyPrefix):t.key&&n.append("key",t.key),null!=t.page&&n.append("page",String(t.page)),null!=t.pageSize&&n.append("page_size",String(t.pageSize));let o=n.toString()?`${r}?${n.toString()}`:r,a=await fetch(o,{method:"GET",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!a.ok)throw Error(await a.text());return a.json()},n9=async(e,t)=>{let r=T?`${T}/v1/memory`:"/v1/memory",n={key:t.key,value:t.value};void 0!==t.metadata&&(n.metadata=t.metadata);let o=await fetch(r,{method:"POST",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(n)});if(!o.ok)throw Error(await o.text());return o.json()},oe=async(e,t,r)=>{let n=n7(t),o=T?`${T}/v1/memory/${n}`:`/v1/memory/${n}`,a=await fetch(o,{method:"PUT",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(r)});if(!a.ok)throw Error(await a.text());return a.json()},ot=async(e,t)=>{let r=n7(t),n=T?`${T}/v1/memory/${r}`:`/v1/memory/${r}`,o=await fetch(n,{method:"DELETE",headers:{[M]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!o.ok)throw Error(await o.text())}},180166,e=>{"use strict";var t={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},r=new class{#e=t;#t=!1;setTimeoutProvider(e){this.#e=e}setTimeout(e,t){return this.#e.setTimeout(e,t)}clearTimeout(e){this.#e.clearTimeout(e)}setInterval(e,t){return this.#e.setInterval(e,t)}clearInterval(e){this.#e.clearInterval(e)}};function n(e){setTimeout(e,0)}e.s(["systemSetTimeoutZero",()=>n,"timeoutManager",()=>r])},619273,e=>{"use strict";var t=e.i(180166),r="u"=0&&e!==1/0}function i(e,t){return Math.max(e+(t||0)-Date.now(),0)}function l(e,t){return"function"==typeof e?e(t):e}function s(e,t){return"function"==typeof e?e(t):e}function c(e,t){let{type:r="all",exact:n,fetchStatus:o,predicate:a,queryKey:i,stale:l}=e;if(i){if(n){if(t.queryHash!==d(i,t.options))return!1}else if(!p(t.queryKey,i))return!1}if("all"!==r){let e=t.isActive();if("active"===r&&!e||"inactive"===r&&e)return!1}return("boolean"!=typeof l||t.isStale()===l)&&(!o||o===t.state.fetchStatus)&&(!a||!!a(t))}function u(e,t){let{exact:r,status:n,predicate:o,mutationKey:a}=e;if(a){if(!t.options.mutationKey)return!1;if(r){if(f(t.options.mutationKey)!==f(a))return!1}else if(!p(t.options.mutationKey,a))return!1}return(!n||t.state.status===n)&&(!o||!!o(t))}function d(e,t){return(t?.queryKeyHashFn||f)(e)}function f(e){return JSON.stringify(e,(e,t)=>v(t)?Object.keys(t).sort().reduce((e,r)=>(e[r]=t[r],e),{}):t)}function p(e,t){return e===t||typeof e==typeof t&&!!e&&!!t&&"object"==typeof e&&"object"==typeof t&&Object.keys(t).every(r=>p(e[r],t[r]))}var m=Object.prototype.hasOwnProperty;function g(e,t){if(!t||Object.keys(e).length!==Object.keys(t).length)return!1;for(let r in e)if(e[r]!==t[r])return!1;return!0}function h(e){return Array.isArray(e)&&e.length===Object.keys(e).length}function v(e){if(!y(e))return!1;let t=e.constructor;if(void 0===t)return!0;let r=t.prototype;return!!y(r)&&!!r.hasOwnProperty("isPrototypeOf")&&Object.getPrototypeOf(e)===Object.prototype}function y(e){return"[object Object]"===Object.prototype.toString.call(e)}function b(e){return new Promise(r=>{t.timeoutManager.setTimeout(r,e)})}function w(e,t,r){return"function"==typeof r.structuralSharing?r.structuralSharing(e,t):!1!==r.structuralSharing?function e(t,r,n=0){if(t===r)return t;if(n>500)return r;let o=h(t)&&h(r);if(!o&&!(v(t)&&v(r)))return r;let a=(o?t:Object.keys(t)).length,i=o?r:Object.keys(r),l=i.length,s=o?Array(l):{},c=0;for(let u=0;ur?n.slice(1):n}function S(e,t,r=0){let n=[t,...e];return r&&n.length>r?n.slice(0,-1):n}var $=Symbol();function E(e,t){return!e.queryFn&&t?.initialPromise?()=>t.initialPromise:e.queryFn&&e.queryFn!==$?e.queryFn:()=>Promise.reject(Error(`Missing queryFn: '${e.queryHash}'`))}function k(e,t){return"function"==typeof e?e(...t):!!e}function O(e,t,r){let n,o=!1;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(n??=t(),o||(o=!0,n.aborted?r():n.addEventListener("abort",r,{once:!0})),n)}),e}e.s(["addConsumeAwareSignal",()=>O,"addToEnd",()=>x,"addToStart",()=>S,"ensureQueryFn",()=>E,"functionalUpdate",()=>o,"hashKey",()=>f,"hashQueryKeyByOptions",()=>d,"isServer",()=>r,"isValidTimeout",()=>a,"keepPreviousData",()=>C,"matchMutation",()=>u,"matchQuery",()=>c,"noop",()=>n,"partialMatchKey",()=>p,"replaceData",()=>w,"resolveEnabled",()=>s,"resolveStaleTime",()=>l,"shallowEqualObjects",()=>g,"shouldThrowError",()=>k,"skipToken",()=>$,"sleep",()=>b,"timeUntilStale",()=>i])},540143,e=>{"use strict";let t,r,n,o,a,i;var l=e.i(180166).systemSetTimeoutZero,s=(t=[],r=0,n=e=>{e()},o=e=>{e()},a=l,{batch:e=>{let i;r++;try{i=e()}finally{let e;--r||(e=t,t=[],e.length&&a(()=>{o(()=>{e.forEach(e=>{n(e)})})}))}return i},batchCalls:e=>(...t)=>{i(()=>{e(...t)})},schedule:i=e=>{r?t.push(e):a(()=>{n(e)})},setNotifyFunction:e=>{n=e},setBatchNotifyFunction:e=>{o=e},setScheduler:e=>{a=e}});e.s(["notifyManager",()=>s])},915823,e=>{"use strict";var t=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}};e.s(["Subscribable",()=>t])},175555,e=>{"use strict";var t=e.i(915823),r=e.i(619273),n=new class extends t.Subscribable{#r;#n;#o;constructor(){super(),this.#o=e=>{if(!r.isServer&&window.addEventListener){let t=()=>e();return window.addEventListener("visibilitychange",t,!1),()=>{window.removeEventListener("visibilitychange",t)}}}}onSubscribe(){this.#n||this.setEventListener(this.#o)}onUnsubscribe(){this.hasListeners()||(this.#n?.(),this.#n=void 0)}setEventListener(e){this.#o=e,this.#n?.(),this.#n=e(e=>{"boolean"==typeof e?this.setFocused(e):this.onFocus()})}setFocused(e){this.#r!==e&&(this.#r=e,this.onFocus())}onFocus(){let e=this.isFocused();this.listeners.forEach(t=>{t(e)})}isFocused(){return"boolean"==typeof this.#r?this.#r:globalThis.document?.visibilityState!=="hidden"}};e.s(["focusManager",()=>n])},936553,814448,793803,e=>{"use strict";var t=e.i(175555),r=e.i(915823),n=e.i(619273),o=new class extends r.Subscribable{#a=!0;#n;#o;constructor(){super(),this.#o=e=>{if(!n.isServer&&window.addEventListener){let t=()=>e(!0),r=()=>e(!1);return window.addEventListener("online",t,!1),window.addEventListener("offline",r,!1),()=>{window.removeEventListener("online",t),window.removeEventListener("offline",r)}}}}onSubscribe(){this.#n||this.setEventListener(this.#o)}onUnsubscribe(){this.hasListeners()||(this.#n?.(),this.#n=void 0)}setEventListener(e){this.#o=e,this.#n?.(),this.#n=e(this.setOnline.bind(this))}setOnline(e){this.#a!==e&&(this.#a=e,this.listeners.forEach(t=>{t(e)}))}isOnline(){return this.#a}};function a(){let e,t,r=new Promise((r,n)=>{e=r,t=n});function n(e){Object.assign(r,e),delete r.resolve,delete r.reject}return r.status="pending",r.catch(()=>{}),r.resolve=t=>{n({status:"fulfilled",value:t}),e(t)},r.reject=e=>{n({status:"rejected",reason:e}),t(e)},r}function i(e){return Math.min(1e3*2**e,3e4)}function l(e){return(e??"online")!=="online"||o.isOnline()}e.s(["onlineManager",()=>o],814448),e.s(["pendingThenable",()=>a],793803);var s=class extends Error{constructor(e){super("CancelledError"),this.revert=e?.revert,this.silent=e?.silent}};function c(e){let r,c=!1,u=0,d=a(),f=()=>t.focusManager.isFocused()&&("always"===e.networkMode||o.isOnline())&&e.canRun(),p=()=>l(e.networkMode)&&e.canRun(),m=e=>{"pending"===d.status&&(r?.(),d.resolve(e))},g=e=>{"pending"===d.status&&(r?.(),d.reject(e))},h=()=>new Promise(t=>{r=e=>{("pending"!==d.status||f())&&t(e)},e.onPause?.()}).then(()=>{r=void 0,"pending"===d.status&&e.onContinue?.()}),v=()=>{let t;if("pending"!==d.status)return;let r=0===u?e.initialPromise:void 0;try{t=r??e.fn()}catch(e){t=Promise.reject(e)}Promise.resolve(t).then(m).catch(t=>{if("pending"!==d.status)return;let r=e.retry??3*!n.isServer,o=e.retryDelay??i,a="function"==typeof o?o(u,t):o,l=!0===r||"number"==typeof r&&uf()?void 0:h()).then(()=>{c?g(t):v()}))})};return{promise:d,status:()=>d.status,cancel:t=>{if("pending"===d.status){let r=new s(t);g(r),e.onCancel?.(r)}},continue:()=>(r?.(),d),cancelRetry:()=>{c=!0},continueRetry:()=>{c=!1},canStart:p,start:()=>(p()?v():h().then(v),d)}}e.s(["CancelledError",()=>s,"canFetch",()=>l,"createRetryer",()=>c],936553)},88587,e=>{"use strict";var t=e.i(180166),r=e.i(619273),n=class{#i;destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),(0,r.isValidTimeout)(this.gcTime)&&(this.#i=t.timeoutManager.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(r.isServer?1/0:3e5))}clearGcTimeout(){this.#i&&(t.timeoutManager.clearTimeout(this.#i),this.#i=void 0)}};e.s(["Removable",()=>n])},286491,e=>{"use strict";var t=e.i(619273),r=e.i(540143),n=e.i(936553),o=e.i(88587),a=class extends o.Removable{#l;#s;#c;#u;#d;#f;#p;constructor(e){super(),this.#p=!1,this.#f=e.defaultOptions,this.setOptions(e.options),this.observers=[],this.#u=e.client,this.#c=this.#u.getQueryCache(),this.queryKey=e.queryKey,this.queryHash=e.queryHash,this.#l=s(this.options),this.state=e.state??this.#l,this.scheduleGc()}get meta(){return this.options.meta}get promise(){return this.#d?.promise}setOptions(e){if(this.options={...this.#f,...e},this.updateGcTime(this.options.gcTime),this.state&&void 0===this.state.data){let e=s(this.options);void 0!==e.data&&(this.setState(l(e.data,e.dataUpdatedAt)),this.#l=e)}}optionalRemove(){this.observers.length||"idle"!==this.state.fetchStatus||this.#c.remove(this)}setData(e,r){let n=(0,t.replaceData)(this.state.data,e,this.options);return this.#m({data:n,type:"success",dataUpdatedAt:r?.updatedAt,manual:r?.manual}),n}setState(e,t){this.#m({type:"setState",state:e,setStateOptions:t})}cancel(e){let r=this.#d?.promise;return this.#d?.cancel(e),r?r.then(t.noop).catch(t.noop):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}reset(){this.destroy(),this.setState(this.#l)}isActive(){return this.observers.some(e=>!1!==(0,t.resolveEnabled)(e.options.enabled,this))}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===t.skipToken||this.state.dataUpdateCount+this.state.errorUpdateCount===0}isStatic(){return this.getObserversCount()>0&&this.observers.some(e=>"static"===(0,t.resolveStaleTime)(e.options.staleTime,this))}isStale(){return this.getObserversCount()>0?this.observers.some(e=>e.getCurrentResult().isStale):void 0===this.state.data||this.state.isInvalidated}isStaleByTime(e=0){return void 0===this.state.data||"static"!==e&&(!!this.state.isInvalidated||!(0,t.timeUntilStale)(this.state.dataUpdatedAt,e))}onFocus(){let e=this.observers.find(e=>e.shouldFetchOnWindowFocus());e?.refetch({cancelRefetch:!1}),this.#d?.continue()}onOnline(){let e=this.observers.find(e=>e.shouldFetchOnReconnect());e?.refetch({cancelRefetch:!1}),this.#d?.continue()}addObserver(e){this.observers.includes(e)||(this.observers.push(e),this.clearGcTimeout(),this.#c.notify({type:"observerAdded",query:this,observer:e}))}removeObserver(e){this.observers.includes(e)&&(this.observers=this.observers.filter(t=>t!==e),this.observers.length||(this.#d&&(this.#p?this.#d.cancel({revert:!0}):this.#d.cancelRetry()),this.scheduleGc()),this.#c.notify({type:"observerRemoved",query:this,observer:e}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||this.#m({type:"invalidate"})}async fetch(e,r){let o;if("idle"!==this.state.fetchStatus&&this.#d?.status()!=="rejected"){if(void 0!==this.state.data&&r?.cancelRefetch)this.cancel({silent:!0});else if(this.#d)return this.#d.continueRetry(),this.#d.promise}if(e&&this.setOptions(e),!this.options.queryFn){let e=this.observers.find(e=>e.options.queryFn);e&&this.setOptions(e.options)}let a=new AbortController,i=e=>{Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(this.#p=!0,a.signal)})},l=()=>{let e,n=(0,t.ensureQueryFn)(this.options,r),o=(i(e={client:this.#u,queryKey:this.queryKey,meta:this.meta}),e);return(this.#p=!1,this.options.persister)?this.options.persister(n,o,this):n(o)},s=(i(o={fetchOptions:r,options:this.options,queryKey:this.queryKey,client:this.#u,state:this.state,fetchFn:l}),o);this.options.behavior?.onFetch(s,this),this.#s=this.state,("idle"===this.state.fetchStatus||this.state.fetchMeta!==s.fetchOptions?.meta)&&this.#m({type:"fetch",meta:s.fetchOptions?.meta}),this.#d=(0,n.createRetryer)({initialPromise:r?.initialPromise,fn:s.fetchFn,onCancel:e=>{e instanceof n.CancelledError&&e.revert&&this.setState({...this.#s,fetchStatus:"idle"}),a.abort()},onFail:(e,t)=>{this.#m({type:"failed",failureCount:e,error:t})},onPause:()=>{this.#m({type:"pause"})},onContinue:()=>{this.#m({type:"continue"})},retry:s.options.retry,retryDelay:s.options.retryDelay,networkMode:s.options.networkMode,canRun:()=>!0});try{let e=await this.#d.start();if(void 0===e)throw Error(`${this.queryHash} data is undefined`);return this.setData(e),this.#c.config.onSuccess?.(e,this),this.#c.config.onSettled?.(e,this.state.error,this),e}catch(e){if(e instanceof n.CancelledError){if(e.silent)return this.#d.promise;else if(e.revert){if(void 0===this.state.data)throw e;return this.state.data}}throw this.#m({type:"error",error:e}),this.#c.config.onError?.(e,this),this.#c.config.onSettled?.(this.state.data,e,this),e}finally{this.scheduleGc()}}#m(e){let t=t=>{switch(e.type){case"failed":return{...t,fetchFailureCount:e.failureCount,fetchFailureReason:e.error};case"pause":return{...t,fetchStatus:"paused"};case"continue":return{...t,fetchStatus:"fetching"};case"fetch":return{...t,...i(t.data,this.options),fetchMeta:e.meta??null};case"success":let r={...t,...l(e.data,e.dataUpdatedAt),dataUpdateCount:t.dataUpdateCount+1,...!e.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return this.#s=e.manual?r:void 0,r;case"error":let n=e.error;return{...t,error:n,errorUpdateCount:t.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:t.fetchFailureCount+1,fetchFailureReason:n,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...t,isInvalidated:!0};case"setState":return{...t,...e.state}}};this.state=t(this.state),r.notifyManager.batch(()=>{this.observers.forEach(e=>{e.onQueryUpdate()}),this.#c.notify({query:this,type:"updated",action:e})})}};function i(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:(0,n.canFetch)(t.networkMode)?"fetching":"paused",...void 0===e&&{error:null,status:"pending"}}}function l(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:"success"}}function s(e){let t="function"==typeof e.initialData?e.initialData():e.initialData,r=void 0!==t,n=r?"function"==typeof e.initialDataUpdatedAt?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:r?n??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:r?"success":"pending",fetchStatus:"idle"}}e.s(["Query",()=>a,"fetchState",()=>i])},912598,e=>{"use strict";var t=e.i(271645),r=e.i(843476),n=t.createContext(void 0),o=e=>{let r=t.useContext(n);if(e)return e;if(!r)throw Error("No QueryClient set, use QueryClientProvider to set one");return r},a=({client:e,children:o})=>(t.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),(0,r.jsx)(n.Provider,{value:e,children:o}));e.s(["QueryClientProvider",()=>a,"useQueryClient",()=>o])}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/00ff280cdb7d7ee5.js b/litellm/proxy/_experimental/out/_next/static/chunks/00ff280cdb7d7ee5.js new file mode 100644 index 00000000000..ef84e7aadbe --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/00ff280cdb7d7ee5.js @@ -0,0 +1 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,829087,397126,229315,343084,953760,e=>{"use strict";e.i(247167);var t=e.i(271645);new WeakMap,new WeakMap;var n='input:not([inert]):not([inert] *),select:not([inert]):not([inert] *),textarea:not([inert]):not([inert] *),a[href]:not([inert]):not([inert] *),button:not([inert]):not([inert] *),[tabindex]:not(slot):not([inert]):not([inert] *),audio[controls]:not([inert]):not([inert] *),video[controls]:not([inert]):not([inert] *),[contenteditable]:not([contenteditable="false"]):not([inert]):not([inert] *),details>summary:first-of-type:not([inert]):not([inert] *),details:not([inert]):not([inert] *)',r="u"typeof window&&void 0!==window.CSS&&"function"==typeof window.CSS.escape)t=r(window.CSS.escape(e.name));else try{t=r(e.name)}catch(e){return console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s",e.message),!1}var o=h(t,e.form);return!o||o===e},v=function(e){return m(e)&&"radio"===e.type&&!g(e)},y=function(e){var t,n,r,o,l,u,a,c=e&&i(e),s=null==(t=c)?void 0:t.host,f=!1;if(c&&c!==e)for(f=!!(null!=(n=s)&&null!=(r=n.ownerDocument)&&r.contains(s)||null!=e&&null!=(o=e.ownerDocument)&&o.contains(e));!f&&s;)f=!!(null!=(u=s=null==(l=c=i(s))?void 0:l.host)&&null!=(a=u.ownerDocument)&&a.contains(s));return f},w=function(e){var t=e.getBoundingClientRect(),n=t.width,r=t.height;return 0===n&&0===r},b=function(e,t){var n=t.displayCheck,r=t.getShadowRoot;if("full-native"===n&&"checkVisibility"in e)return!e.checkVisibility({checkOpacity:!1,opacityProperty:!1,contentVisibilityAuto:!0,visibilityProperty:!0,checkVisibilityCSS:!0});if("hidden"===getComputedStyle(e).visibility)return!0;var l=o.call(e,"details>summary:first-of-type")?e.parentElement:e;if(o.call(l,"details:not([open]) *"))return!0;if(n&&"full"!==n&&"full-native"!==n&&"legacy-full"!==n){if("non-zero-area"===n)return w(e)}else{if("function"==typeof r){for(var u=e;e;){var a=e.parentElement,c=i(e);if(a&&!a.shadowRoot&&!0===r(a))return w(e);e=e.assignedSlot?e.assignedSlot:a||c===e.ownerDocument?a:c.host}e=u}if(y(e))return!e.getClientRects().length;if("legacy-full"!==n)return!0}return!1},x=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if("FIELDSET"===t.tagName&&t.disabled){for(var n=0;nf(t))&&!!E(e,t)},S=function(e){var t=parseInt(e.getAttribute("tabindex"),10);return!!isNaN(t)||!!(t>=0)},T=function(e){var t=[],n=[];return e.forEach(function(e,r){var o=!!e.scopeParent,i=o?e.scopeParent:e,l=d(i,o),u=o?T(e.candidates):i;0===l?o?t.push.apply(t,u):t.push(i):n.push({documentOrder:r,tabIndex:l,item:e,isScope:o,content:u})}),n.sort(p).reduce(function(e,t){return t.isScope?e.push.apply(e,t.content):e.push(t.content),e},[]).concat(t)},L=function(e,t){return T((t=t||{}).getShadowRoot?c([e],t.includeContainer,{filter:R.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:S}):a(e,t.includeContainer,R.bind(null,t)))},A=function(e,t){if(t=t||{},!e)throw Error("No node provided");return!1!==o.call(e,n)&&R(t,e)};e.s(["isTabbable",()=>A,"tabbable",()=>L],397126);var C=e.i(174080);function P(){return"u">typeof window}function O(e){return M(e)?(e.nodeName||"").toLowerCase():"#document"}function k(e){var t;return(null==e||null==(t=e.ownerDocument)?void 0:t.defaultView)||window}function D(e){var t;return null==(t=(M(e)?e.ownerDocument:e.document)||window.document)?void 0:t.documentElement}function M(e){return!!P()&&(e instanceof Node||e instanceof k(e).Node)}function N(e){return!!P()&&(e instanceof Element||e instanceof k(e).Element)}function F(e){return!!P()&&(e instanceof HTMLElement||e instanceof k(e).HTMLElement)}function I(e){return!(!P()||"u"{try{return e.matches(t)}catch(e){return!1}})}let z=["transform","translate","scale","rotate","perspective"],K=["transform","translate","scale","rotate","perspective","filter"],U=["paint","layout","strict","content"];function X(e){let t=$(),n=N(e)?J(e):e;return z.some(e=>!!n[e]&&"none"!==n[e])||!!n.containerType&&"normal"!==n.containerType||!t&&!!n.backdropFilter&&"none"!==n.backdropFilter||!t&&!!n.filter&&"none"!==n.filter||K.some(e=>(n.willChange||"").includes(e))||U.some(e=>(n.contain||"").includes(e))}function Y(e){let t=Z(e);for(;F(t)&&!G(t);){if(X(t))return t;if(j(t))break;t=Z(t)}return null}function $(){return!("u"J,"getContainingBlock",()=>Y,"getDocumentElement",()=>D,"getFrameElement",()=>et,"getNodeName",()=>O,"getNodeScroll",()=>Q,"getOverflowAncestors",()=>ee,"getParentNode",()=>Z,"getWindow",()=>k,"isContainingBlock",()=>X,"isElement",()=>N,"isHTMLElement",()=>F,"isLastTraversableNode",()=>G,"isOverflowElement",()=>W,"isShadowRoot",()=>I,"isTableElement",()=>V,"isTopLayer",()=>j,"isWebKit",()=>$],229315);let en=["top","right","bottom","left"],er=en.reduce((e,t)=>e.concat(t,t+"-start",t+"-end"),[]),eo=Math.min,ei=Math.max,el=Math.round,eu=Math.floor,ea=e=>({x:e,y:e}),ec={left:"right",right:"left",bottom:"top",top:"bottom"},es={start:"end",end:"start"};function ef(e,t,n){return ei(e,eo(t,n))}function ed(e,t){return"function"==typeof e?e(t):e}function ep(e){return e.split("-")[0]}function em(e){return e.split("-")[1]}function eh(e){return"x"===e?"y":"x"}function eg(e){return"y"===e?"height":"width"}let ev=new Set(["top","bottom"]);function ey(e){return ev.has(ep(e))?"y":"x"}function ew(e){return eh(ey(e))}function eb(e,t,n){void 0===n&&(n=!1);let r=em(e),o=ew(e),i=eg(o),l="x"===o?r===(n?"end":"start")?"right":"left":"start"===r?"bottom":"top";return t.reference[i]>t.floating[i]&&(l=eC(l)),[l,eC(l)]}function ex(e){let t=eC(e);return[eE(e),t,eE(t)]}function eE(e){return e.replace(/start|end/g,e=>es[e])}let eR=["left","right"],eS=["right","left"],eT=["top","bottom"],eL=["bottom","top"];function eA(e,t,n,r){let o=em(e),i=function(e,t,n){switch(e){case"top":case"bottom":if(n)return t?eS:eR;return t?eR:eS;case"left":case"right":return t?eT:eL;default:return[]}}(ep(e),"start"===n,r);return o&&(i=i.map(e=>e+"-"+o),t&&(i=i.concat(i.map(eE)))),i}function eC(e){return e.replace(/left|right|bottom|top/g,e=>ec[e])}function eP(e){return"number"!=typeof e?{top:0,right:0,bottom:0,left:0,...e}:{top:e,right:e,bottom:e,left:e}}function eO(e){let{x:t,y:n,width:r,height:o}=e;return{width:r,height:o,top:n,left:t,right:t+r,bottom:n+o,x:t,y:n}}function ek(e,t,n){let r,{reference:o,floating:i}=e,l=ey(t),u=ew(t),a=eg(u),c=ep(t),s="y"===l,f=o.x+o.width/2-i.width/2,d=o.y+o.height/2-i.height/2,p=o[a]/2-i[a]/2;switch(c){case"top":r={x:f,y:o.y-i.height};break;case"bottom":r={x:f,y:o.y+o.height};break;case"right":r={x:o.x+o.width,y:d};break;case"left":r={x:o.x-i.width,y:d};break;default:r={x:o.x,y:o.y}}switch(em(t)){case"start":r[u]-=p*(n&&s?-1:1);break;case"end":r[u]+=p*(n&&s?-1:1)}return r}async function eD(e,t){var n;void 0===t&&(t={});let{x:r,y:o,platform:i,rects:l,elements:u,strategy:a}=e,{boundary:c="clippingAncestors",rootBoundary:s="viewport",elementContext:f="floating",altBoundary:d=!1,padding:p=0}=ed(t,e),m=eP(p),h=u[d?"floating"===f?"reference":"floating":f],g=eO(await i.getClippingRect({element:null==(n=await (null==i.isElement?void 0:i.isElement(h)))||n?h:h.contextElement||await (null==i.getDocumentElement?void 0:i.getDocumentElement(u.floating)),boundary:c,rootBoundary:s,strategy:a})),v="floating"===f?{x:r,y:o,width:l.floating.width,height:l.floating.height}:l.reference,y=await (null==i.getOffsetParent?void 0:i.getOffsetParent(u.floating)),w=await (null==i.isElement?void 0:i.isElement(y))&&await (null==i.getScale?void 0:i.getScale(y))||{x:1,y:1},b=eO(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:u,rect:v,offsetParent:y,strategy:a}):v);return{top:(g.top-b.top+m.top)/w.y,bottom:(b.bottom-g.bottom+m.bottom)/w.y,left:(g.left-b.left+m.left)/w.x,right:(b.right-g.right+m.right)/w.x}}e.s(["clamp",()=>ef,"createCoords",()=>ea,"evaluate",()=>ed,"floor",()=>eu,"getAlignment",()=>em,"getAlignmentAxis",()=>ew,"getAlignmentSides",()=>eb,"getAxisLength",()=>eg,"getExpandedPlacements",()=>ex,"getOppositeAlignmentPlacement",()=>eE,"getOppositeAxis",()=>eh,"getOppositeAxisPlacements",()=>eA,"getOppositePlacement",()=>eC,"getPaddingObject",()=>eP,"getSide",()=>ep,"getSideAxis",()=>ey,"max",()=>ei,"min",()=>eo,"placements",()=>er,"rectToClientRect",()=>eO,"round",()=>el,"sides",()=>en],343084);let eM=async(e,t,n)=>{let{placement:r="bottom",strategy:o="absolute",middleware:i=[],platform:l}=n,u=i.filter(Boolean),a=await (null==l.isRTL?void 0:l.isRTL(t)),c=await l.getElementRects({reference:e,floating:t,strategy:o}),{x:s,y:f}=ek(c,r,a),d=r,p={},m=0;for(let n=0;ne[t]>=0)}function eI(e){let t=eo(...e.map(e=>e.left)),n=eo(...e.map(e=>e.top));return{x:t,y:n,width:ei(...e.map(e=>e.right))-t,height:ei(...e.map(e=>e.bottom))-n}}let eB=new Set(["left","top"]);async function eW(e,t){let{placement:n,platform:r,elements:o}=e,i=await (null==r.isRTL?void 0:r.isRTL(o.floating)),l=ep(n),u=em(n),a="y"===ey(n),c=eB.has(l)?-1:1,s=i&&a?-1:1,f=ed(t,e),{mainAxis:d,crossAxis:p,alignmentAxis:m}="number"==typeof f?{mainAxis:f,crossAxis:0,alignmentAxis:null}:{mainAxis:f.mainAxis||0,crossAxis:f.crossAxis||0,alignmentAxis:f.alignmentAxis};return u&&"number"==typeof m&&(p="end"===u?-1*m:m),a?{x:p*s,y:d*c}:{x:d*c,y:p*s}}function eH(e){let t=J(e),n=parseFloat(t.width)||0,r=parseFloat(t.height)||0,o=F(e),i=o?e.offsetWidth:n,l=o?e.offsetHeight:r,u=el(n)!==i||el(r)!==l;return u&&(n=i,r=l),{width:n,height:r,$:u}}function eV(e){return N(e)?e:e.contextElement}function e_(e){let t=eV(e);if(!F(t))return ea(1);let n=t.getBoundingClientRect(),{width:r,height:o,$:i}=eH(t),l=(i?el(n.width):n.width)/r,u=(i?el(n.height):n.height)/o;return l&&Number.isFinite(l)||(l=1),u&&Number.isFinite(u)||(u=1),{x:l,y:u}}let ej=ea(0);function ez(e){let t=k(e);return $()&&t.visualViewport?{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}:ej}function eK(e,t,n,r){var o;void 0===t&&(t=!1),void 0===n&&(n=!1);let i=e.getBoundingClientRect(),l=eV(e),u=ea(1);t&&(r?N(r)&&(u=e_(r)):u=e_(e));let a=(void 0===(o=n)&&(o=!1),r&&(!o||r===k(l))&&o)?ez(l):ea(0),c=(i.left+a.x)/u.x,s=(i.top+a.y)/u.y,f=i.width/u.x,d=i.height/u.y;if(l){let e=k(l),t=r&&N(r)?k(r):r,n=e,o=et(n);for(;o&&r&&t!==n;){let e=e_(o),t=o.getBoundingClientRect(),r=J(o),i=t.left+(o.clientLeft+parseFloat(r.paddingLeft))*e.x,l=t.top+(o.clientTop+parseFloat(r.paddingTop))*e.y;c*=e.x,s*=e.y,f*=e.x,d*=e.y,c+=i,s+=l,o=et(n=k(o))}}return eO({width:f,height:d,x:c,y:s})}function eU(e,t){let n=Q(e).scrollLeft;return t?t.left+n:eK(D(e)).left+n}function eX(e,t){let n=e.getBoundingClientRect();return{x:n.left+t.scrollLeft-eU(e,n),y:n.top+t.scrollTop}}let eY=new Set(["absolute","fixed"]);function e$(e,t,n){var r;let o;if("viewport"===t)o=function(e,t){let n=k(e),r=D(e),o=n.visualViewport,i=r.clientWidth,l=r.clientHeight,u=0,a=0;if(o){i=o.width,l=o.height;let e=$();(!e||e&&"fixed"===t)&&(u=o.offsetLeft,a=o.offsetTop)}let c=eU(r);if(c<=0){let e=r.ownerDocument,t=e.body,n=getComputedStyle(t),o="CSS1Compat"===e.compatMode&&parseFloat(n.marginLeft)+parseFloat(n.marginRight)||0,l=Math.abs(r.clientWidth-t.clientWidth-o);l<=25&&(i-=l)}else c<=25&&(i+=c);return{width:i,height:l,x:u,y:a}}(e,n);else if("document"===t){let t,n,i,l,u,a,c;r=D(e),t=D(r),n=Q(r),i=r.ownerDocument.body,l=ei(t.scrollWidth,t.clientWidth,i.scrollWidth,i.clientWidth),u=ei(t.scrollHeight,t.clientHeight,i.scrollHeight,i.clientHeight),a=-n.scrollLeft+eU(r),c=-n.scrollTop,"rtl"===J(i).direction&&(a+=ei(t.clientWidth,i.clientWidth)-l),o={width:l,height:u,x:a,y:c}}else if(N(t)){let e,r,i,l,u,a;r=(e=eK(t,!0,"fixed"===n)).top+t.clientTop,i=e.left+t.clientLeft,l=F(t)?e_(t):ea(1),u=t.clientWidth*l.x,a=t.clientHeight*l.y,o={width:u,height:a,x:i*l.x,y:r*l.y}}else{let n=ez(e);o={x:t.x-n.x,y:t.y-n.y,width:t.width,height:t.height}}return eO(o)}function eq(e){return"static"===J(e).position}function eG(e,t){if(!F(e)||"fixed"===J(e).position)return null;if(t)return t(e);let n=e.offsetParent;return D(e)===n&&(n=n.ownerDocument.body),n}function eJ(e,t){let n=k(e);if(j(e))return n;if(!F(e)){let t=Z(e);for(;t&&!G(t);){if(N(t)&&!eq(t))return t;t=Z(t)}return n}let r=eG(e,t);for(;r&&V(r)&&eq(r);)r=eG(r,t);return r&&G(r)&&eq(r)&&!X(r)?n:r||Y(e)||n}let eQ=async function(e){let t=this.getOffsetParent||eJ,n=this.getDimensions,r=await n(e.floating);return{reference:function(e,t,n){let r=F(t),o=D(t),i="fixed"===n,l=eK(e,!0,i,t),u={scrollLeft:0,scrollTop:0},a=ea(0);if(r||!r&&!i)if(("body"!==O(t)||W(o))&&(u=Q(t)),r){let e=eK(t,!0,i,t);a.x=e.x+t.clientLeft,a.y=e.y+t.clientTop}else o&&(a.x=eU(o));i&&!r&&o&&(a.x=eU(o));let c=!o||r||i?ea(0):eX(o,u);return{x:l.left+u.scrollLeft-a.x-c.x,y:l.top+u.scrollTop-a.y-c.y,width:l.width,height:l.height}}(e.reference,await t(e.floating),e.strategy),floating:{x:0,y:0,width:r.width,height:r.height}}},eZ={convertOffsetParentRelativeRectToViewportRelativeRect:function(e){let{elements:t,rect:n,offsetParent:r,strategy:o}=e,i="fixed"===o,l=D(r),u=!!t&&j(t.floating);if(r===l||u&&i)return n;let a={scrollLeft:0,scrollTop:0},c=ea(1),s=ea(0),f=F(r);if((f||!f&&!i)&&(("body"!==O(r)||W(l))&&(a=Q(r)),F(r))){let e=eK(r);c=e_(r),s.x=e.x+r.clientLeft,s.y=e.y+r.clientTop}let d=!l||f||i?ea(0):eX(l,a);return{width:n.width*c.x,height:n.height*c.y,x:n.x*c.x-a.scrollLeft*c.x+s.x+d.x,y:n.y*c.y-a.scrollTop*c.y+s.y+d.y}},getDocumentElement:D,getClippingRect:function(e){let{element:t,boundary:n,rootBoundary:r,strategy:o}=e,i=[..."clippingAncestors"===n?j(t)?[]:function(e,t){let n=t.get(e);if(n)return n;let r=ee(e,[],!1).filter(e=>N(e)&&"body"!==O(e)),o=null,i="fixed"===J(e).position,l=i?Z(e):e;for(;N(l)&&!G(l);){let t=J(l),n=X(l);n||"fixed"!==t.position||(o=null),(i?!n&&!o:!n&&"static"===t.position&&!!o&&eY.has(o.position)||W(l)&&!n&&function e(t,n){let r=Z(t);return!(r===n||!N(r)||G(r))&&("fixed"===J(r).position||e(r,n))}(e,l))?r=r.filter(e=>e!==l):o=t,l=Z(l)}return t.set(e,r),r}(t,this._c):[].concat(n),r],l=i[0],u=i.reduce((e,n)=>{let r=e$(t,n,o);return e.top=ei(r.top,e.top),e.right=eo(r.right,e.right),e.bottom=eo(r.bottom,e.bottom),e.left=ei(r.left,e.left),e},e$(t,l,o));return{width:u.right-u.left,height:u.bottom-u.top,x:u.left,y:u.top}},getOffsetParent:eJ,getElementRects:eQ,getClientRects:function(e){return Array.from(e.getClientRects())},getDimensions:function(e){let{width:t,height:n}=eH(e);return{width:t,height:n}},getScale:e_,isElement:N,isRTL:function(e){return"rtl"===J(e).direction}};function e0(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}function e1(e,t,n,r){let o;void 0===r&&(r={});let{ancestorScroll:i=!0,ancestorResize:l=!0,elementResize:u="function"==typeof ResizeObserver,layoutShift:a="function"==typeof IntersectionObserver,animationFrame:c=!1}=r,s=eV(e),f=i||l?[...s?ee(s):[],...ee(t)]:[];f.forEach(e=>{i&&e.addEventListener("scroll",n,{passive:!0}),l&&e.addEventListener("resize",n)});let d=s&&a?function(e,t){let n,r=null,o=D(e);function i(){var e;clearTimeout(n),null==(e=r)||e.disconnect(),r=null}return!function l(u,a){void 0===u&&(u=!1),void 0===a&&(a=1),i();let c=e.getBoundingClientRect(),{left:s,top:f,width:d,height:p}=c;if(u||t(),!d||!p)return;let m={rootMargin:-eu(f)+"px "+-eu(o.clientWidth-(s+d))+"px "+-eu(o.clientHeight-(f+p))+"px "+-eu(s)+"px",threshold:ei(0,eo(1,a))||1},h=!0;function g(t){let r=t[0].intersectionRatio;if(r!==a){if(!h)return l();r?l(!1,r):n=setTimeout(()=>{l(!1,1e-7)},1e3)}1!==r||e0(c,e.getBoundingClientRect())||l(),h=!1}try{r=new IntersectionObserver(g,{...m,root:o.ownerDocument})}catch(e){r=new IntersectionObserver(g,m)}r.observe(e)}(!0),i}(s,n):null,p=-1,m=null;u&&(m=new ResizeObserver(e=>{let[r]=e;r&&r.target===s&&m&&(m.unobserve(t),cancelAnimationFrame(p),p=requestAnimationFrame(()=>{var e;null==(e=m)||e.observe(t)})),n()}),s&&!c&&m.observe(s),m.observe(t));let h=c?eK(e):null;return c&&function t(){let r=eK(e);h&&!e0(h,r)&&n(),h=r,o=requestAnimationFrame(t)}(),n(),()=>{var e;f.forEach(e=>{i&&e.removeEventListener("scroll",n),l&&e.removeEventListener("resize",n)}),null==d||d(),null==(e=m)||e.disconnect(),m=null,c&&cancelAnimationFrame(o)}}let e2=function(e){return void 0===e&&(e=0),{name:"offset",options:e,async fn(t){var n,r;let{x:o,y:i,placement:l,middlewareData:u}=t,a=await eW(t,e);return l===(null==(n=u.offset)?void 0:n.placement)&&null!=(r=u.arrow)&&r.alignmentOffset?{}:{x:o+a.x,y:i+a.y,data:{...a,placement:l}}}}},e3=function(e){return void 0===e&&(e={}),{name:"autoPlacement",options:e,async fn(t){var n,r,o,i;let{rects:l,middlewareData:u,placement:a,platform:c,elements:s}=t,{crossAxis:f=!1,alignment:d,allowedPlacements:p=er,autoAlignment:m=!0,...h}=ed(e,t),g=void 0!==d||p===er?((i=d||null)?[...p.filter(e=>em(e)===i),...p.filter(e=>em(e)!==i)]:p.filter(e=>ep(e)===e)).filter(e=>!i||em(e)===i||!!m&&eE(e)!==e):p,v=await c.detectOverflow(t,h),y=(null==(n=u.autoPlacement)?void 0:n.index)||0,w=g[y];if(null==w)return{};let b=eb(w,l,await (null==c.isRTL?void 0:c.isRTL(s.floating)));if(a!==w)return{reset:{placement:g[0]}};let x=[v[ep(w)],v[b[0]],v[b[1]]],E=[...(null==(r=u.autoPlacement)?void 0:r.overflows)||[],{placement:w,overflows:x}],R=g[y+1];if(R)return{data:{index:y+1,overflows:E},reset:{placement:R}};let S=E.map(e=>{let t=em(e.placement);return[e.placement,t&&f?e.overflows.slice(0,2).reduce((e,t)=>e+t,0):e.overflows[0],e.overflows]}).sort((e,t)=>e[1]-t[1]),T=(null==(o=S.filter(e=>e[2].slice(0,em(e[0])?2:3).every(e=>e<=0))[0])?void 0:o[0])||S[0][0];return T!==a?{data:{index:y+1,overflows:E},reset:{placement:T}}:{}}}},e5=function(e){return void 0===e&&(e={}),{name:"shift",options:e,async fn(t){let{x:n,y:r,placement:o,platform:i}=t,{mainAxis:l=!0,crossAxis:u=!1,limiter:a={fn:e=>{let{x:t,y:n}=e;return{x:t,y:n}}},...c}=ed(e,t),s={x:n,y:r},f=await i.detectOverflow(t,c),d=ey(ep(o)),p=eh(d),m=s[p],h=s[d];if(l){let e="y"===p?"top":"left",t="y"===p?"bottom":"right",n=m+f[e],r=m-f[t];m=ef(n,m,r)}if(u){let e="y"===d?"top":"left",t="y"===d?"bottom":"right",n=h+f[e],r=h-f[t];h=ef(n,h,r)}let g=a.fn({...t,[p]:m,[d]:h});return{...g,data:{x:g.x-n,y:g.y-r,enabled:{[p]:l,[d]:u}}}}}},e7=function(e){return void 0===e&&(e={}),{name:"flip",options:e,async fn(t){var n,r,o,i,l;let{placement:u,middlewareData:a,rects:c,initialPlacement:s,platform:f,elements:d}=t,{mainAxis:p=!0,crossAxis:m=!0,fallbackPlacements:h,fallbackStrategy:g="bestFit",fallbackAxisSideDirection:v="none",flipAlignment:y=!0,...w}=ed(e,t);if(null!=(n=a.arrow)&&n.alignmentOffset)return{};let b=ep(u),x=ey(s),E=ep(s)===s,R=await (null==f.isRTL?void 0:f.isRTL(d.floating)),S=h||(E||!y?[eC(s)]:ex(s)),T="none"!==v;!h&&T&&S.push(...eA(s,y,v,R));let L=[s,...S],A=await f.detectOverflow(t,w),C=[],P=(null==(r=a.flip)?void 0:r.overflows)||[];if(p&&C.push(A[b]),m){let e=eb(u,c,R);C.push(A[e[0]],A[e[1]])}if(P=[...P,{placement:u,overflows:C}],!C.every(e=>e<=0)){let e=((null==(o=a.flip)?void 0:o.index)||0)+1,t=L[e];if(t&&("alignment"!==m||x===ey(t)||P.every(e=>ey(e.placement)!==x||e.overflows[0]>0)))return{data:{index:e,overflows:P},reset:{placement:t}};let n=null==(i=P.filter(e=>e.overflows[0]<=0).sort((e,t)=>e.overflows[1]-t.overflows[1])[0])?void 0:i.placement;if(!n)switch(g){case"bestFit":{let e=null==(l=P.filter(e=>{if(T){let t=ey(e.placement);return t===x||"y"===t}return!0}).map(e=>[e.placement,e.overflows.filter(e=>e>0).reduce((e,t)=>e+t,0)]).sort((e,t)=>e[1]-t[1])[0])?void 0:l[0];e&&(n=e);break}case"initialPlacement":n=s}if(u!==n)return{reset:{placement:n}}}return{}}}},e4=function(e){return void 0===e&&(e={}),{name:"size",options:e,async fn(t){var n,r;let o,i,{placement:l,rects:u,platform:a,elements:c}=t,{apply:s=()=>{},...f}=ed(e,t),d=await a.detectOverflow(t,f),p=ep(l),m=em(l),h="y"===ey(l),{width:g,height:v}=u.floating;"top"===p||"bottom"===p?(o=p,i=m===(await (null==a.isRTL?void 0:a.isRTL(c.floating))?"start":"end")?"left":"right"):(i=p,o="end"===m?"top":"bottom");let y=v-d.top-d.bottom,w=g-d.left-d.right,b=eo(v-d[o],y),x=eo(g-d[i],w),E=!t.middlewareData.shift,R=b,S=x;if(null!=(n=t.middlewareData.shift)&&n.enabled.x&&(S=w),null!=(r=t.middlewareData.shift)&&r.enabled.y&&(R=y),E&&!m){let e=ei(d.left,0),t=ei(d.right,0),n=ei(d.top,0),r=ei(d.bottom,0);h?S=g-2*(0!==e||0!==t?e+t:ei(d.left,d.right)):R=v-2*(0!==n||0!==r?n+r:ei(d.top,d.bottom))}await s({...t,availableWidth:S,availableHeight:R});let T=await a.getDimensions(c.floating);return g!==T.width||v!==T.height?{reset:{rects:!0}}:{}}}},e9=function(e){return void 0===e&&(e={}),{name:"hide",options:e,async fn(t){let{rects:n,platform:r}=t,{strategy:o="referenceHidden",...i}=ed(e,t);switch(o){case"referenceHidden":{let e=eN(await r.detectOverflow(t,{...i,elementContext:"reference"}),n.reference);return{data:{referenceHiddenOffsets:e,referenceHidden:eF(e)}}}case"escaped":{let e=eN(await r.detectOverflow(t,{...i,altBoundary:!0}),n.floating);return{data:{escapedOffsets:e,escaped:eF(e)}}}default:return{}}}}},e8=e=>({name:"arrow",options:e,async fn(t){let{x:n,y:r,placement:o,rects:i,platform:l,elements:u,middlewareData:a}=t,{element:c,padding:s=0}=ed(e,t)||{};if(null==c)return{};let f=eP(s),d={x:n,y:r},p=ew(o),m=eg(p),h=await l.getDimensions(c),g="y"===p,v=g?"clientHeight":"clientWidth",y=i.reference[m]+i.reference[p]-d[p]-i.floating[m],w=d[p]-i.reference[p],b=await (null==l.getOffsetParent?void 0:l.getOffsetParent(c)),x=b?b[v]:0;x&&await (null==l.isElement?void 0:l.isElement(b))||(x=u.floating[v]||i.floating[m]);let E=x/2-h[m]/2-1,R=eo(f[g?"top":"left"],E),S=eo(f[g?"bottom":"right"],E),T=x-h[m]-S,L=x/2-h[m]/2+(y/2-w/2),A=ef(R,L,T),C=!a.arrow&&null!=em(o)&&L!==A&&i.reference[m]/2-(Le.y-t.y),n=[],r=null;for(let e=0;er.height/2?n.push([o]):n[n.length-1].push(o),r=o}return n.map(e=>eO(eI(e)))}(s),d=eO(eI(s)),p=eP(u),m=await i.getElementRects({reference:{getBoundingClientRect:function(){if(2===f.length&&f[0].left>f[1].right&&null!=a&&null!=c)return f.find(e=>a>e.left-p.left&&ae.top-p.top&&c=2){if("y"===ey(n)){let e=f[0],t=f[f.length-1],r="top"===ep(n),o=e.top,i=t.bottom,l=r?e.left:t.left,u=r?e.right:t.right;return{top:o,bottom:i,left:l,right:u,width:u-l,height:i-o,x:l,y:o}}let e="left"===ep(n),t=ei(...f.map(e=>e.right)),r=eo(...f.map(e=>e.left)),o=f.filter(n=>e?n.left===r:n.right===t),i=o[0].top,l=o[o.length-1].bottom;return{top:i,bottom:l,left:r,right:t,width:t-r,height:l-i,x:r,y:i}}return d}},floating:r.floating,strategy:l});return o.reference.x!==m.reference.x||o.reference.y!==m.reference.y||o.reference.width!==m.reference.width||o.reference.height!==m.reference.height?{reset:{rects:m}}:{}}}},te=function(e){return void 0===e&&(e={}),{options:e,fn(t){let{x:n,y:r,placement:o,rects:i,middlewareData:l}=t,{offset:u=0,mainAxis:a=!0,crossAxis:c=!0}=ed(e,t),s={x:n,y:r},f=ey(o),d=eh(f),p=s[d],m=s[f],h=ed(u,t),g="number"==typeof h?{mainAxis:h,crossAxis:0}:{mainAxis:0,crossAxis:0,...h};if(a){let e="y"===d?"height":"width",t=i.reference[d]-i.floating[e]+g.mainAxis,n=i.reference[d]+i.reference[e]-g.mainAxis;pn&&(p=n)}if(c){var v,y;let e="y"===d?"width":"height",t=eB.has(ep(o)),n=i.reference[f]-i.floating[e]+(t&&(null==(v=l.offset)?void 0:v[f])||0)+(t?0:g.crossAxis),r=i.reference[f]+i.reference[e]+(t?0:(null==(y=l.offset)?void 0:y[f])||0)-(t?g.crossAxis:0);mr&&(m=r)}return{[d]:p,[f]:m}}}},tt=(e,t,n)=>{let r=new Map,o={platform:eZ,...n},i={...o.platform,_c:r};return eM(e,t,{...o,platform:i})};e.s(["arrow",()=>e8,"autoPlacement",()=>e3,"autoUpdate",()=>e1,"computePosition",()=>tt,"detectOverflow",()=>eD,"flip",()=>e7,"hide",()=>e9,"inline",()=>e6,"limitShift",()=>te,"offset",()=>e2,"shift",()=>e5,"size",()=>e4],953760);var tn="u">typeof document?t.useLayoutEffect:t.useEffect;function tr(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(!tr(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(!Object.prototype.hasOwnProperty.call(t,o[r]))return!1;for(r=n;0!=r--;){let n=o[r];if(("_owner"!==n||!e.$$typeof)&&!tr(e[n],t[n]))return!1}return!0}return e!=e&&t!=t}function to(e){let n=t.useRef(e);return tn(()=>{n.current=e}),n}var ti="u">typeof document?t.useLayoutEffect:t.useEffect;let tl=!1,tu=0,ta=()=>"floating-ui-"+tu++,tc=t["useId".toString()]||function(){let[e,n]=t.useState(()=>tl?ta():void 0);return ti(()=>{null==e&&n(ta())},[]),t.useEffect(()=>{tl||(tl=!0)},[]),e},ts=t.createContext(null),tf=t.createContext(null),td=()=>{var e;return(null==(e=t.useContext(ts))?void 0:e.id)||null};function tp(e){return(null==e?void 0:e.ownerDocument)||document}function tm(e){return tp(e).defaultView||window}function th(e){return!!e&&e instanceof tm(e).Element}function tg(e){return!!e&&e instanceof tm(e).HTMLElement}function tv(e,t){let n=["mouse","pen"];return t||n.push("",void 0),n.includes(e)}function ty(e){let n=(0,t.useRef)(e);return ti(()=>{n.current=e}),n}let tw="data-floating-ui-safe-polygon";function tb(e,t,n){return n&&!tv(n)?0:"number"==typeof e?e:null==e?void 0:e[t]}let tx=function(e,n){let{enabled:r=!0,delay:o=0,handleClose:i=null,mouseOnly:l=!1,restMs:u=0,move:a=!0}=void 0===n?{}:n,{open:c,onOpenChange:s,dataRef:f,events:d,elements:{domReference:p,floating:m},refs:h}=e,g=t.useContext(tf),v=td(),y=ty(i),w=ty(o),b=t.useRef(),x=t.useRef(),E=t.useRef(),R=t.useRef(),S=t.useRef(!0),T=t.useRef(!1),L=t.useRef(()=>{}),A=t.useCallback(()=>{var e;let t=null==(e=f.current.openEvent)?void 0:e.type;return(null==t?void 0:t.includes("mouse"))&&"mousedown"!==t},[f]);t.useEffect(()=>{if(r)return d.on("dismiss",e),()=>{d.off("dismiss",e)};function e(){clearTimeout(x.current),clearTimeout(R.current),S.current=!0}},[r,d]),t.useEffect(()=>{if(!r||!y.current||!c)return;function e(){A()&&s(!1)}let t=tp(m).documentElement;return t.addEventListener("mouseleave",e),()=>{t.removeEventListener("mouseleave",e)}},[m,c,s,r,y,f,A]);let C=t.useCallback(function(e){void 0===e&&(e=!0);let t=tb(w.current,"close",b.current);t&&!E.current?(clearTimeout(x.current),x.current=setTimeout(()=>s(!1),t)):e&&(clearTimeout(x.current),s(!1))},[w,s]),P=t.useCallback(()=>{L.current(),E.current=void 0},[]),O=t.useCallback(()=>{if(T.current){let e=tp(h.floating.current).body;e.style.pointerEvents="",e.removeAttribute(tw),T.current=!1}},[h]);return t.useEffect(()=>{if(r&&th(p))return c&&p.addEventListener("mouseleave",i),null==m||m.addEventListener("mouseleave",i),a&&p.addEventListener("mousemove",n,{once:!0}),p.addEventListener("mouseenter",n),p.addEventListener("mouseleave",o),()=>{c&&p.removeEventListener("mouseleave",i),null==m||m.removeEventListener("mouseleave",i),a&&p.removeEventListener("mousemove",n),p.removeEventListener("mouseenter",n),p.removeEventListener("mouseleave",o)};function t(){return!!f.current.openEvent&&["click","mousedown"].includes(f.current.openEvent.type)}function n(e){if(clearTimeout(x.current),S.current=!1,l&&!tv(b.current)||u>0&&0===tb(w.current,"open"))return;f.current.openEvent=e;let t=tb(w.current,"open",b.current);t?x.current=setTimeout(()=>{s(!0)},t):s(!0)}function o(n){if(t())return;L.current();let r=tp(m);if(clearTimeout(R.current),y.current){c||clearTimeout(x.current),E.current=y.current({...e,tree:g,x:n.clientX,y:n.clientY,onClose(){O(),P(),C()}});let t=E.current;r.addEventListener("mousemove",t),L.current=()=>{r.removeEventListener("mousemove",t)};return}C()}function i(n){t()||null==y.current||y.current({...e,tree:g,x:n.clientX,y:n.clientY,onClose(){O(),P(),C()}})(n)}},[p,m,r,e,l,u,a,C,P,O,s,c,g,w,y,f]),ti(()=>{var e,t,n;if(r&&c&&null!=(e=y.current)&&e.__options.blockPointerEvents&&A()){let e=tp(m).body;if(e.setAttribute(tw,""),e.style.pointerEvents="none",T.current=!0,th(p)&&m){let e=null==g||null==(t=g.nodesRef.current.find(e=>e.id===v))||null==(n=t.context)?void 0:n.elements.floating;return e&&(e.style.pointerEvents=""),p.style.pointerEvents="auto",m.style.pointerEvents="auto",()=>{p.style.pointerEvents="",m.style.pointerEvents=""}}}},[r,c,v,m,p,g,y,f,A]),ti(()=>{c||(b.current=void 0,P(),O())},[c,P,O]),t.useEffect(()=>()=>{P(),clearTimeout(x.current),clearTimeout(R.current),O()},[r,P,O]),t.useMemo(()=>{if(!r)return{};function e(e){b.current=e.pointerType}return{reference:{onPointerDown:e,onPointerEnter:e,onMouseMove(){c||0===u||(clearTimeout(R.current),R.current=setTimeout(()=>{S.current||s(!0)},u))}},floating:{onMouseEnter(){clearTimeout(x.current)},onMouseLeave(){d.emit("dismiss",{type:"mouseLeave",data:{returnFocus:!1}}),C(!1)}}}},[d,r,u,c,s,C])};function tE(e,t){if(!e||!t)return!1;let n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&function(e){if("u"{var n;return e.parentId===t&&(null==(n=e.context)?void 0:n.open)})||[],r=n;for(;r.length;)r=e.filter(e=>{var t;return null==(t=r)?void 0:t.some(t=>{var n;return e.parentId===t.id&&(null==(n=e.context)?void 0:n.open)})})||[],n=n.concat(r);return n}let tS=t["useInsertionEffect".toString()]||(e=>e());function tT(e){let n=t.useRef(()=>{});return tS(()=>{n.current=e}),t.useCallback(function(){for(var e=arguments.length,t=Array(e),r=0;r!1),E="function"==typeof p?x:p,R=t.useRef(!1),{escapeKeyBubbles:S,outsidePressBubbles:T}=tP(y);return t.useEffect(()=>{if(!r||!f)return;function e(e){if("Escape"===e.key){let e=w?tR(w.nodesRef.current,l):[];if(e.length>0){let t=!0;if(e.forEach(e=>{var n;if(null!=(n=e.context)&&n.open&&!e.context.dataRef.current.__escapeKeyBubbles){t=!1;return}}),!t)return}i.emit("dismiss",{type:"escapeKey",data:{returnFocus:{preventScroll:!1}}}),o(!1)}}function t(e){var t;let n=R.current;if(R.current=!1,n||"function"==typeof E&&!E(e))return;let r="composedPath"in e?e.composedPath()[0]:e.target;if(tg(r)&&c){let t=c.ownerDocument.defaultView||window,n=r.scrollWidth>r.clientWidth,o=r.scrollHeight>r.clientHeight,i=o&&e.offsetX>r.clientWidth;if(o&&"rtl"===t.getComputedStyle(r).direction&&(i=e.offsetX<=r.offsetWidth-r.clientWidth),i||n&&e.offsetY>r.clientHeight)return}let u=w&&tR(w.nodesRef.current,l).some(t=>{var n;return tL(e,null==(n=t.context)?void 0:n.elements.floating)});if(tL(e,c)||tL(e,a)||u)return;let s=w?tR(w.nodesRef.current,l):[];if(s.length>0){let e=!0;if(s.forEach(t=>{var n;if(null!=(n=t.context)&&n.open&&!t.context.dataRef.current.__outsidePressBubbles){e=!1;return}}),!e)return}i.emit("dismiss",{type:"outsidePress",data:{returnFocus:b?{preventScroll:!0}:function(e){let t,n;if(0===e.mozInputSource&&e.isTrusted)return!0;let r=/Android/i;return(r.test(null!=(n=navigator.userAgentData)&&n.platform?n.platform:navigator.platform)||r.test((t=navigator.userAgentData)&&Array.isArray(t.brands)?t.brands.map(e=>{let{brand:t,version:n}=e;return t+"/"+n}).join(" "):navigator.userAgent))&&e.pointerType?"click"===e.type&&1===e.buttons:0===e.detail&&!e.pointerType}(e)||0===(t=e).width&&0===t.height||1===t.width&&1===t.height&&0===t.pressure&&0===t.detail&&"mouse"!==t.pointerType||t.width<1&&t.height<1&&0===t.pressure&&0===t.detail}}),o(!1)}function n(){o(!1)}s.current.__escapeKeyBubbles=S,s.current.__outsidePressBubbles=T;let p=tp(c);d&&p.addEventListener("keydown",e),E&&p.addEventListener(m,t);let h=[];return v&&(th(a)&&(h=ee(a)),th(c)&&(h=h.concat(ee(c))),!th(u)&&u&&u.contextElement&&(h=h.concat(ee(u.contextElement)))),(h=h.filter(e=>{var t;return e!==(null==(t=p.defaultView)?void 0:t.visualViewport)})).forEach(e=>{e.addEventListener("scroll",n,{passive:!0})}),()=>{d&&p.removeEventListener("keydown",e),E&&p.removeEventListener(m,t),h.forEach(e=>{e.removeEventListener("scroll",n)})}},[s,c,a,u,d,E,m,i,w,l,r,o,v,f,S,T,b]),t.useEffect(()=>{R.current=!1},[E,m]),t.useMemo(()=>f?{reference:{[tA[g]]:()=>{h&&(i.emit("dismiss",{type:"referencePress",data:{returnFocus:!1}}),o(!1))}},floating:{[tC[m]]:()=>{R.current=!0}}}:{},[f,i,h,m,g,o])},tk=function(e,n){let{open:r,onOpenChange:o,dataRef:i,events:l,refs:u,elements:{floating:a,domReference:c}}=e,{enabled:s=!0,keyboardOnly:f=!0}=void 0===n?{}:n,d=t.useRef(""),p=t.useRef(!1),m=t.useRef();return t.useEffect(()=>{if(!s)return;let e=tp(a).defaultView||window;function t(){!r&&tg(c)&&c===function(e){let t=e.activeElement;for(;(null==(n=t)||null==(r=n.shadowRoot)?void 0:r.activeElement)!=null;){var n,r;t=t.shadowRoot.activeElement}return t}(tp(c))&&(p.current=!0)}return e.addEventListener("blur",t),()=>{e.removeEventListener("blur",t)}},[a,c,r,s]),t.useEffect(()=>{if(s)return l.on("dismiss",e),()=>{l.off("dismiss",e)};function e(e){("referencePress"===e.type||"escapeKey"===e.type)&&(p.current=!0)}},[l,s]),t.useEffect(()=>()=>{clearTimeout(m.current)},[]),t.useMemo(()=>s?{reference:{onPointerDown(e){let{pointerType:t}=e;d.current=t,p.current=!!(t&&f)},onMouseLeave(){p.current=!1},onFocus(e){var t;p.current||"focus"===e.type&&(null==(t=i.current.openEvent)?void 0:t.type)==="mousedown"&&i.current.openEvent&&tL(i.current.openEvent,c)||(i.current.openEvent=e.nativeEvent,o(!0))},onBlur(e){p.current=!1;let t=e.relatedTarget,n=th(t)&&t.hasAttribute("data-floating-ui-focus-guard")&&"outside"===t.getAttribute("data-type");m.current=setTimeout(()=>{tE(u.floating.current,t)||tE(c,t)||n||o(!1)})}}}:{},[s,f,c,u,i,o])},tD=function(e,n){let{open:r}=e,{enabled:o=!0,role:i="dialog"}=void 0===n?{}:n,l=tc(),u=tc();return t.useMemo(()=>{let e={id:l,role:i};return o?"tooltip"===i?{reference:{"aria-describedby":r?l:void 0},floating:e}:{reference:{"aria-expanded":r?"true":"false","aria-haspopup":"alertdialog"===i?"dialog":i,"aria-controls":r?l:void 0,..."listbox"===i&&{role:"combobox"},..."menu"===i&&{id:u}},floating:{...e,..."menu"===i&&{"aria-labelledby":u}}}:{}},[o,i,r,l,u])};function tM(e,t,n){let r=new Map;return{..."floating"===n&&{tabIndex:-1},...e,...t.map(e=>e?e[n]:null).concat(e).reduce((e,t)=>(t&&Object.entries(t).forEach(t=>{let[n,o]=t;if(0===n.indexOf("on")){if(r.has(n)||r.set(n,[]),"function"==typeof o){var i;null==(i=r.get(n))||i.push(o),e[n]=function(){for(var e,t=arguments.length,o=Array(t),i=0;ie(...o))}}}else e[n]=o}),e),{})}}let tN=function(e){void 0===e&&(e=[]);let n=e,r=t.useCallback(t=>tM(t,e,"reference"),n),o=t.useCallback(t=>tM(t,e,"floating"),n),i=t.useCallback(t=>tM(t,e,"item"),e.map(e=>null==e?void 0:e.item));return t.useMemo(()=>({getReferenceProps:r,getFloatingProps:o,getItemProps:i}),[r,o,i])};var tF=e.i(444755);let tI=e=>{let[n,r]=(0,t.useState)(!1),[o,i]=(0,t.useState)(),{x:l,y:u,refs:a,strategy:c,context:s}=function(e){void 0===e&&(e={});let{open:n=!1,onOpenChange:r,nodeId:o}=e,i=function(e){void 0===e&&(e={});let{placement:n="bottom",strategy:r="absolute",middleware:o=[],platform:i,whileElementsMounted:l,open:u}=e,[a,c]=t.useState({x:null,y:null,strategy:r,placement:n,middlewareData:{},isPositioned:!1}),[s,f]=t.useState(o);tr(s,o)||f(o);let d=t.useRef(null),p=t.useRef(null),m=t.useRef(a),h=to(l),g=to(i),[v,y]=t.useState(null),[w,b]=t.useState(null),x=t.useCallback(e=>{d.current!==e&&(d.current=e,y(e))},[]),E=t.useCallback(e=>{p.current!==e&&(p.current=e,b(e))},[]),R=t.useCallback(()=>{if(!d.current||!p.current)return;let e={placement:n,strategy:r,middleware:s};g.current&&(e.platform=g.current),tt(d.current,p.current,e).then(e=>{let t={...e,isPositioned:!0};S.current&&!tr(m.current,t)&&(m.current=t,C.flushSync(()=>{c(t)}))})},[s,n,r,g]);tn(()=>{!1===u&&m.current.isPositioned&&(m.current.isPositioned=!1,c(e=>({...e,isPositioned:!1})))},[u]);let S=t.useRef(!1);tn(()=>(S.current=!0,()=>{S.current=!1}),[]),tn(()=>{if(v&&w)if(h.current)return h.current(v,w,R);else R()},[v,w,R,h]);let T=t.useMemo(()=>({reference:d,floating:p,setReference:x,setFloating:E}),[x,E]),L=t.useMemo(()=>({reference:v,floating:w}),[v,w]);return t.useMemo(()=>({...a,update:R,refs:T,elements:L,reference:x,floating:E}),[a,R,T,L,x,E])}(e),l=t.useContext(tf),u=t.useRef(null),a=t.useRef({}),c=t.useState(()=>{let e;return e=new Map,{emit(t,n){var r;null==(r=e.get(t))||r.forEach(e=>e(n))},on(t,n){e.set(t,[...e.get(t)||[],n])},off(t,n){e.set(t,(e.get(t)||[]).filter(e=>e!==n))}}})[0],[s,f]=t.useState(null),d=t.useCallback(e=>{let t=th(e)?{getBoundingClientRect:()=>e.getBoundingClientRect(),contextElement:e}:e;i.refs.setReference(t)},[i.refs]),p=t.useCallback(e=>{(th(e)||null===e)&&(u.current=e,f(e)),(th(i.refs.reference.current)||null===i.refs.reference.current||null!==e&&!th(e))&&i.refs.setReference(e)},[i.refs]),m=t.useMemo(()=>({...i.refs,setReference:p,setPositionReference:d,domReference:u}),[i.refs,p,d]),h=t.useMemo(()=>({...i.elements,domReference:s}),[i.elements,s]),g=tT(r),v=t.useMemo(()=>({...i,refs:m,elements:h,dataRef:a,nodeId:o,events:c,open:n,onOpenChange:g}),[i,o,c,n,g,m,h]);return ti(()=>{let e=null==l?void 0:l.nodesRef.current.find(e=>e.id===o);e&&(e.context=v)}),t.useMemo(()=>({...i,context:v,refs:m,reference:p,positionReference:d}),[i,m,v,p,d])}({open:n,onOpenChange:t=>{t&&e?i(setTimeout(()=>{r(t)},e)):(clearTimeout(o),r(t))},placement:"top",whileElementsMounted:e1,middleware:[e2(5),e7({fallbackAxisSideDirection:"start"}),e5()]}),{getReferenceProps:f,getFloatingProps:d}=tN([tx(s,{move:!1}),tk(s),tO(s),tD(s,{role:"tooltip"})]);return{tooltipProps:{open:n,x:l,y:u,refs:a,strategy:c,getFloatingProps:d},getReferenceProps:f}},tB=({text:e,open:n,x:r,y:o,refs:i,strategy:l,getFloatingProps:u})=>n&&e?t.default.createElement("div",Object.assign({className:(0,tF.tremorTwMerge)("max-w-xs text-sm z-20 rounded-tremor-default opacity-100 px-2.5 py-1","text-white bg-tremor-background-emphasis","dark:text-tremor-content-emphasis dark:bg-white"),ref:i.setFloating,style:{position:l,top:null!=o?o:0,left:null!=r?r:0}},u()),e):null;tB.displayName="Tooltip",e.s(["default",()=>tB,"useTooltip",()=>tI],829087)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/01361b81a268feda.js b/litellm/proxy/_experimental/out/_next/static/chunks/01361b81a268feda.js new file mode 100644 index 00000000000..39be5ce51c8 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/01361b81a268feda.js @@ -0,0 +1,86 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,509345,e=>{"use strict";var t,a,l=e.i(843476),r=e.i(271645),i=e.i(464571),s=e.i(326373),n=e.i(653496),o=e.i(755151),d=e.i(646563),c=e.i(245094),m=e.i(602869),u=e.i(808613),p=e.i(311451),g=e.i(212931),x=e.i(199133),h=e.i(262218),f=e.i(898586),y=e.i(727749),j=e.i(770914),_=e.i(515831),b=e.i(175712),v=e.i(519756);let{Text:w}=f.Typography,{Option:N}=x.Select,C=({visible:e,prebuiltPatterns:t,categories:a,selectedPatternName:r,patternAction:s,onPatternNameChange:n,onActionChange:o,onAdd:d,onCancel:c})=>(0,l.jsxs)(g.Modal,{title:"Add prebuilt pattern",open:e,onCancel:c,footer:null,width:800,children:[(0,l.jsxs)(j.Space,{direction:"vertical",style:{width:"100%"},size:"large",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(w,{strong:!0,children:"Pattern type"}),(0,l.jsx)(x.Select,{placeholder:"Choose pattern type",value:r,onChange:n,style:{width:"100%",marginTop:8},showSearch:!0,filterOption:(e,a)=>{let l=t.find(e=>e.name===a?.value);return!!l&&(l.display_name.toLowerCase().includes(e.toLowerCase())||l.name.toLowerCase().includes(e.toLowerCase()))},children:a.map(e=>{let a=t.filter(t=>t.category===e);return 0===a.length?null:(0,l.jsx)(x.Select.OptGroup,{label:e,children:a.map(e=>(0,l.jsx)(N,{value:e.name,children:e.display_name},e.name))},e)})})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(w,{strong:!0,children:"Action"}),(0,l.jsx)(w,{type:"secondary",style:{display:"block",marginTop:4,marginBottom:8},children:"Choose what action the guardrail should take when this pattern is detected"}),(0,l.jsxs)(x.Select,{value:s,onChange:o,style:{width:"100%"},children:[(0,l.jsx)(N,{value:"BLOCK",children:"Block"}),(0,l.jsx)(N,{value:"MASK",children:"Mask"})]})]})]}),(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"8px",marginTop:"24px"},children:[(0,l.jsx)(i.Button,{onClick:c,children:"Cancel"}),(0,l.jsx)(i.Button,{type:"primary",onClick:d,children:"Add"})]})]}),{Text:S}=f.Typography,{Option:k}=x.Select,I=({visible:e,patternName:t,patternRegex:a,patternAction:r,onNameChange:s,onRegexChange:n,onActionChange:o,onAdd:d,onCancel:c})=>(0,l.jsxs)(g.Modal,{title:"Add custom regex pattern",open:e,onCancel:c,footer:null,width:800,children:[(0,l.jsxs)(j.Space,{direction:"vertical",style:{width:"100%"},size:"large",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(S,{strong:!0,children:"Pattern name"}),(0,l.jsx)(p.Input,{placeholder:"e.g., internal_id, employee_code",value:t,onChange:e=>s(e.target.value),style:{marginTop:8}})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(S,{strong:!0,children:"Regex pattern"}),(0,l.jsx)(p.Input,{placeholder:"e.g., ID-[0-9]{6}",value:a,onChange:e=>n(e.target.value),style:{marginTop:8}}),(0,l.jsx)(S,{type:"secondary",style:{fontSize:12},children:"Enter a valid regular expression to match sensitive data"})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(S,{strong:!0,children:"Action"}),(0,l.jsx)(S,{type:"secondary",style:{display:"block",marginTop:4,marginBottom:8},children:"Choose what action the guardrail should take when this pattern is detected"}),(0,l.jsxs)(x.Select,{value:r,onChange:o,style:{width:"100%"},children:[(0,l.jsx)(k,{value:"BLOCK",children:"Block"}),(0,l.jsx)(k,{value:"MASK",children:"Mask"})]})]})]}),(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"8px",marginTop:"24px"},children:[(0,l.jsx)(i.Button,{onClick:c,children:"Cancel"}),(0,l.jsx)(i.Button,{type:"primary",onClick:d,children:"Add"})]})]}),{Text:A}=f.Typography,{Option:O}=x.Select,P=({visible:e,keyword:t,action:a,description:r,onKeywordChange:s,onActionChange:n,onDescriptionChange:o,onAdd:d,onCancel:c})=>(0,l.jsxs)(g.Modal,{title:"Add blocked keyword",open:e,onCancel:c,footer:null,width:800,children:[(0,l.jsxs)(j.Space,{direction:"vertical",style:{width:"100%"},size:"large",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(A,{strong:!0,children:"Keyword"}),(0,l.jsx)(p.Input,{placeholder:"Enter sensitive keyword or phrase",value:t,onChange:e=>s(e.target.value),style:{marginTop:8}})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(A,{strong:!0,children:"Action"}),(0,l.jsx)(A,{type:"secondary",style:{display:"block",marginTop:4,marginBottom:8},children:"Choose what action the guardrail should take when this keyword is detected"}),(0,l.jsxs)(x.Select,{value:a,onChange:n,style:{width:"100%"},children:[(0,l.jsx)(O,{value:"BLOCK",children:"Block"}),(0,l.jsx)(O,{value:"MASK",children:"Mask"})]})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(A,{strong:!0,children:"Description (optional)"}),(0,l.jsx)(p.Input.TextArea,{placeholder:"Explain why this keyword is sensitive",value:r,onChange:e=>o(e.target.value),rows:3,style:{marginTop:8}})]})]}),(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"flex-end",gap:"8px",marginTop:"24px"},children:[(0,l.jsx)(i.Button,{onClick:c,children:"Cancel"}),(0,l.jsx)(i.Button,{type:"primary",onClick:d,children:"Add"})]})]});var T=e.i(291542),L=e.i(955135);let{Text:B}=f.Typography,{Option:F}=x.Select,$=({patterns:e,onActionChange:t,onRemove:a})=>{let r=[{title:"Type",dataIndex:"type",key:"type",width:100,render:e=>(0,l.jsx)(h.Tag,{color:"prebuilt"===e?"blue":"green",children:"prebuilt"===e?"Prebuilt":"Custom"})},{title:"Pattern name",dataIndex:"name",key:"name",render:(e,t)=>t.display_name||t.name},{title:"Regex pattern",dataIndex:"pattern",key:"pattern",render:e=>e?(0,l.jsxs)(B,{code:!0,style:{fontSize:12},children:[e.substring(0,40),"..."]}):"-"},{title:"Action",dataIndex:"action",key:"action",width:150,render:(e,a)=>(0,l.jsxs)(x.Select,{value:e,onChange:e=>t(a.id,e),style:{width:120},size:"small",children:[(0,l.jsx)(F,{value:"BLOCK",children:"Block"}),(0,l.jsx)(F,{value:"MASK",children:"Mask"})]})},{title:"",key:"actions",width:100,render:(e,t)=>(0,l.jsx)(i.Button,{type:"text",danger:!0,size:"small",icon:(0,l.jsx)(L.DeleteOutlined,{}),onClick:()=>a(t.id),children:"Delete"})}];return 0===e.length?(0,l.jsx)("div",{style:{textAlign:"center",padding:"40px 0",color:"#999"},children:"No patterns added."}):(0,l.jsx)(T.Table,{dataSource:e,columns:r,rowKey:"id",pagination:!1,size:"small"})},{Text:E}=f.Typography,{Option:M}=x.Select,R=({keywords:e,onActionChange:t,onRemove:a})=>{let r=[{title:"Keyword",dataIndex:"keyword",key:"keyword"},{title:"Action",dataIndex:"action",key:"action",width:150,render:(e,a)=>(0,l.jsxs)(x.Select,{value:e,onChange:e=>t(a.id,"action",e),style:{width:120},size:"small",children:[(0,l.jsx)(M,{value:"BLOCK",children:"Block"}),(0,l.jsx)(M,{value:"MASK",children:"Mask"})]})},{title:"Description",dataIndex:"description",key:"description",render:e=>e||"-"},{title:"",key:"actions",width:100,render:(e,t)=>(0,l.jsx)(i.Button,{type:"text",danger:!0,size:"small",icon:(0,l.jsx)(L.DeleteOutlined,{}),onClick:()=>a(t.id),children:"Delete"})}];return 0===e.length?(0,l.jsx)("div",{style:{textAlign:"center",padding:"40px 0",color:"#999"},children:"No keywords added."}):(0,l.jsx)(T.Table,{dataSource:e,columns:r,rowKey:"id",pagination:!1,size:"small"})};var G=e.i(362024),z=e.i(993914);let{Title:D,Text:K}=f.Typography,{Option:q}=x.Select,H=({availableCategories:e,selectedCategories:t,onCategoryAdd:a,onCategoryRemove:s,onCategoryUpdate:n,accessToken:o,pendingSelection:c,onPendingSelectionChange:u})=>{let[p,g]=r.default.useState(""),f=void 0!==c?c:p,y=u||g,[j,_]=r.default.useState({}),[v,w]=r.default.useState({}),[N,C]=r.default.useState({}),[S,k]=r.default.useState([]),[I,A]=r.default.useState(""),[O,P]=r.default.useState(!1),B=async e=>{if(o&&!j[e]){C(t=>({...t,[e]:!0}));try{let t=await (0,m.getCategoryYaml)(o,e),a=t.yaml_content;if("json"===t.file_type)try{let e=JSON.parse(a);a=JSON.stringify(e,null,2)}catch(t){console.warn(`Failed to format JSON for ${e}:`,t)}_(t=>({...t,[e]:a})),w(a=>({...a,[e]:t.file_type||"yaml"}))}catch(t){console.error(`Failed to fetch content for category ${e}:`,t)}finally{C(t=>({...t,[e]:!1}))}}};r.default.useEffect(()=>{if(f&&o){let e=j[f];if(e)return void A(e);P(!0),console.log(`Fetching content for category: ${f}`,{accessToken:o?"present":"missing"}),(0,m.getCategoryYaml)(o,f).then(e=>{console.log(`Successfully fetched content for ${f}:`,e);let t=e.yaml_content;if("json"===e.file_type)try{let e=JSON.parse(t);t=JSON.stringify(e,null,2)}catch(e){console.warn(`Failed to format JSON for ${f}:`,e)}A(t),_(e=>({...e,[f]:t})),w(t=>({...t,[f]:e.file_type||"yaml"}))}).catch(e=>{console.error(`Failed to fetch preview content for category ${f}:`,e),A("")}).finally(()=>{P(!1)})}else A(""),P(!1)},[f,o]);let F=[{title:"Category",dataIndex:"display_name",key:"display_name",render:(t,a)=>{let r=e.find(e=>e.name===a.category);return(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{style:{fontWeight:500},children:t}),r?.description&&(0,l.jsx)("div",{style:{fontSize:"12px",color:"#888",marginTop:"4px"},children:r.description})]})}},{title:"Action",dataIndex:"action",key:"action",width:150,render:(e,t)=>(0,l.jsxs)(x.Select,{value:e,onChange:e=>n(t.id,"action",e),style:{width:"100%"},children:[(0,l.jsx)(q,{value:"BLOCK",children:(0,l.jsx)(h.Tag,{color:"red",children:"BLOCK"})}),(0,l.jsx)(q,{value:"MASK",children:(0,l.jsx)(h.Tag,{color:"orange",children:"MASK"})})]})},{title:"Severity Threshold",dataIndex:"severity_threshold",key:"severity_threshold",width:180,render:(e,t)=>(0,l.jsxs)(x.Select,{value:e,onChange:e=>n(t.id,"severity_threshold",e),style:{width:"100%"},children:[(0,l.jsx)(q,{value:"low",children:"Low"}),(0,l.jsx)(q,{value:"medium",children:"Medium"}),(0,l.jsx)(q,{value:"high",children:"High"})]})},{title:"",key:"actions",width:80,render:(e,t)=>(0,l.jsx)(i.Button,{icon:(0,l.jsx)(L.DeleteOutlined,{}),onClick:()=>s(t.id),size:"small",children:"Remove"})}],$=e.filter(e=>!t.some(t=>t.category===e.name));return(0,l.jsxs)(b.Card,{title:(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",flexWrap:"wrap",gap:8},children:[(0,l.jsx)(D,{level:5,style:{margin:0},children:"Blocked topics"}),(0,l.jsx)(K,{type:"secondary",style:{fontSize:12,fontWeight:400},children:"Select topics to block using keyword and semantic analysis"})]}),size:"small",children:[(0,l.jsxs)("div",{style:{marginBottom:16,display:"flex",gap:8},children:[(0,l.jsx)(x.Select,{placeholder:"Select a content category",value:f||void 0,onChange:y,style:{flex:1},showSearch:!0,optionLabelProp:"label",filterOption:(e,t)=>(t?.label?.toString().toLowerCase()??"").includes(e.toLowerCase()),children:$.map(e=>(0,l.jsx)(q,{value:e.name,label:e.display_name,children:(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{style:{fontWeight:500},children:e.display_name}),(0,l.jsx)("div",{style:{fontSize:"12px",color:"#666",marginTop:"2px"},children:e.description})]})},e.name))}),(0,l.jsx)(i.Button,{type:"primary",onClick:()=>{if(!f)return;let l=e.find(e=>e.name===f);!l||t.some(e=>e.category===f)||(a({id:`category-${Date.now()}`,category:l.name,display_name:l.display_name,action:l.default_action,severity_threshold:"medium"}),y(""),A(""))},disabled:!f,icon:(0,l.jsx)(d.PlusOutlined,{}),children:"Add"})]}),f&&(0,l.jsxs)("div",{style:{marginBottom:16,padding:"12px",background:"#f9f9f9",border:"1px solid #e0e0e0",borderRadius:"4px"},children:[(0,l.jsxs)("div",{style:{marginBottom:8,fontWeight:500,fontSize:"14px"},children:["Preview: ",e.find(e=>e.name===f)?.display_name,v[f]&&(0,l.jsxs)("span",{style:{marginLeft:8,fontSize:"12px",color:"#888",fontWeight:400},children:["(",v[f]?.toUpperCase(),")"]})]}),O?(0,l.jsx)("div",{style:{padding:"16px",textAlign:"center",color:"#888"},children:"Loading content..."}):I?(0,l.jsx)("pre",{style:{background:"#fff",padding:"12px",borderRadius:"4px",overflow:"auto",maxHeight:"300px",maxWidth:"100%",fontSize:"12px",lineHeight:"1.5",margin:0,border:"1px solid #e0e0e0",whiteSpace:"pre-wrap",wordBreak:"break-word"},children:(0,l.jsx)("code",{children:I})}):(0,l.jsx)("div",{style:{padding:"8px",textAlign:"center",color:"#888",fontSize:"12px"},children:"Unable to load category content"})]}),t.length>0?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(T.Table,{dataSource:t,columns:F,pagination:!1,size:"small",rowKey:"id"}),(0,l.jsx)("div",{style:{marginTop:16},children:(0,l.jsx)(G.Collapse,{activeKey:S,onChange:e=>{let t=Array.isArray(e)?e:e?[e]:[],a=new Set(S);t.forEach(e=>{a.has(e)||j[e]||B(e)}),k(t)},ghost:!0,items:t.map(e=>{let t=(v[e.category]||"yaml").toUpperCase();return{key:e.category,label:(0,l.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8},children:[(0,l.jsx)(z.FileTextOutlined,{}),(0,l.jsxs)("span",{children:["View ",t," for ",e.display_name]})]}),children:N[e.category]?(0,l.jsx)("div",{style:{padding:"16px",textAlign:"center",color:"#888"},children:"Loading content..."}):j[e.category]?(0,l.jsx)("pre",{style:{background:"#f5f5f5",padding:"16px",borderRadius:"4px",overflow:"auto",maxHeight:"400px",fontSize:"12px",lineHeight:"1.5",margin:0},children:(0,l.jsx)("code",{children:j[e.category]})}):(0,l.jsx)("div",{style:{padding:"16px",textAlign:"center",color:"#888"},children:"Content will load when expanded"})}})})})]}):(0,l.jsx)("div",{style:{textAlign:"center",padding:"24px",color:"#888",border:"1px dashed #d9d9d9",borderRadius:"4px"},children:"No blocked topics selected. Add topics to detect and block harmful content."})]})};var J=e.i(790848),U=e.i(28651);let{Title:W,Text:V}=f.Typography,{Option:Y}=x.Select,Q={competitor_intent_type:"airline",brand_self:[],locations:[],policy:{competitor_comparison:"refuse",possible_competitor_comparison:"reframe"},threshold_high:.7,threshold_medium:.45,threshold_low:.3},X=({enabled:e,config:t,onChange:a,accessToken:i})=>{let s=t??Q,[n,o]=(0,r.useState)([]),[d,c]=(0,r.useState)(!1);(0,r.useEffect)(()=>{"airline"===s.competitor_intent_type&&i&&0===n.length&&(c(!0),(0,m.getMajorAirlines)(i).then(e=>o(e.airlines??[])).catch(()=>o([])).finally(()=>c(!1)))},[s.competitor_intent_type,i,n.length]);let p=e=>{a(e,e?{...Q}:null)},g=(t,l)=>{a(e,{...s,[t]:l})},h=(t,l)=>{a(e,{...s,policy:{...s.policy,[t]:l}})},f=(t,l)=>{a(e,{...s,[t]:l.filter(Boolean)})};return e?(0,l.jsxs)(b.Card,{title:(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,l.jsx)(W,{level:5,style:{margin:0},children:"Competitor Intent Filter"}),(0,l.jsx)(J.Switch,{checked:e,onChange:p})]}),size:"small",children:[(0,l.jsx)(V,{type:"secondary",style:{display:"block",marginBottom:16},children:"Block or reframe competitor comparison questions. Airline type uses major airlines (excluding your brand); generic requires manual competitor list."}),(0,l.jsxs)(u.Form,{layout:"vertical",size:"small",children:[(0,l.jsx)(u.Form.Item,{label:"Type",children:(0,l.jsxs)(x.Select,{value:s.competitor_intent_type,onChange:e=>g("competitor_intent_type",e),style:{width:"100%"},children:[(0,l.jsx)(Y,{value:"airline",children:"Airline (auto-load competitors from IATA)"}),(0,l.jsx)(Y,{value:"generic",children:"Generic (specify competitors manually)"})]})}),(0,l.jsx)(u.Form.Item,{label:"Your Brand (brand_self)",required:!0,help:"airline"===s.competitor_intent_type?"Select your airline from the list (excluded from competitors) or type to add a custom term":"Names/codes users use for your brand",children:(0,l.jsx)(x.Select,{mode:"tags",style:{width:"100%"},placeholder:d?"Loading airlines...":"airline"===s.competitor_intent_type?"Search or select airline, or type to add custom":"Type and press Enter to add",value:s.brand_self,onChange:t=>"airline"===s.competitor_intent_type&&n.length>0?(t=>{let l=t.filter(Boolean),r=[],i=new Set;for(let e of l){let t=n.find(t=>t.match.split("|")[0]?.trim().toLowerCase()===e.toLowerCase());if(t)for(let e of t.match.split("|").map(e=>e.trim().toLowerCase()).filter(Boolean))i.has(e)||(i.add(e),r.push(e));else i.has(e.toLowerCase())||(i.add(e.toLowerCase()),r.push(e))}a(e,{...s,brand_self:r})})(t??[]):f("brand_self",t??[]),tokenSeparators:[","],loading:d,showSearch:!0,filterOption:(e,t)=>(t?.label?.toString().toLowerCase()??"").includes(e.toLowerCase()),optionFilterProp:"label",options:"airline"===s.competitor_intent_type&&n.length>0?n.map(e=>{let t=e.match.split("|")[0]?.trim()??e.id,a=e.match.split("|").map(e=>e.trim().toLowerCase()).filter(Boolean);return{value:t.toLowerCase(),label:`${t}${a.length>1?` (${a.slice(1).join(", ")})`:""}`}}):void 0})}),"airline"===s.competitor_intent_type&&(0,l.jsx)(u.Form.Item,{label:"Locations (optional)",help:"Countries, cities, airports for disambiguation (e.g. qatar, doha)",children:(0,l.jsx)(x.Select,{mode:"tags",style:{width:"100%"},placeholder:"Type and press Enter to add",value:s.locations??[],onChange:e=>f("locations",e??[]),tokenSeparators:[","]})}),"generic"===s.competitor_intent_type&&(0,l.jsx)(u.Form.Item,{label:"Competitors",required:!0,help:"Competitor names to detect (required for generic type)",children:(0,l.jsx)(x.Select,{mode:"tags",style:{width:"100%"},placeholder:"Type and press Enter to add",value:s.competitors??[],onChange:e=>f("competitors",e??[]),tokenSeparators:[","]})}),(0,l.jsx)(u.Form.Item,{label:"Policy: Competitor comparison",children:(0,l.jsxs)(x.Select,{value:s.policy?.competitor_comparison??"refuse",onChange:e=>h("competitor_comparison",e),style:{width:"100%"},children:[(0,l.jsx)(Y,{value:"refuse",children:"Refuse (block request)"}),(0,l.jsx)(Y,{value:"reframe",children:"Reframe (suggest alternative)"})]})}),(0,l.jsx)(u.Form.Item,{label:"Policy: Possible competitor comparison",children:(0,l.jsxs)(x.Select,{value:s.policy?.possible_competitor_comparison??"reframe",onChange:e=>h("possible_competitor_comparison",e),style:{width:"100%"},children:[(0,l.jsx)(Y,{value:"refuse",children:"Refuse (block request)"}),(0,l.jsx)(Y,{value:"reframe",children:"Reframe (suggest alternative to backend LLM)"})]})}),(0,l.jsx)(u.Form.Item,{label:"Confidence thresholds",help:(0,l.jsxs)(l.Fragment,{children:["Classify competitor intent by confidence (0–1). Higher confidence → stronger intent.",(0,l.jsxs)("ul",{style:{marginBottom:0,marginTop:4,paddingLeft:20},children:[(0,l.jsxs)("li",{children:[(0,l.jsx)("strong",{children:"High (≥)"}),': Treat as full competitor comparison → uses "Competitor comparison" policy']}),(0,l.jsxs)("li",{children:[(0,l.jsx)("strong",{children:"Medium (≥)"}),': Treat as possible comparison → uses "Possible competitor comparison" policy']}),(0,l.jsxs)("li",{children:[(0,l.jsx)("strong",{children:"Low (≥)"}),": Log only; allow request. Below Low → allow with no action"]})]}),"Raise thresholds to be more permissive; lower them to be stricter."]}),children:(0,l.jsxs)(j.Space,{wrap:!0,children:[(0,l.jsx)(u.Form.Item,{label:"High",style:{marginBottom:0},help:"e.g. 0.7",children:(0,l.jsx)(U.InputNumber,{min:0,max:1,step:.05,value:s.threshold_high??.7,onChange:e=>g("threshold_high",e??.7),style:{width:80}})}),(0,l.jsx)(u.Form.Item,{label:"Medium",style:{marginBottom:0},help:"e.g. 0.45",children:(0,l.jsx)(U.InputNumber,{min:0,max:1,step:.05,value:s.threshold_medium??.45,onChange:e=>g("threshold_medium",e??.45),style:{width:80}})}),(0,l.jsx)(u.Form.Item,{label:"Low",style:{marginBottom:0},help:"e.g. 0.3",children:(0,l.jsx)(U.InputNumber,{min:0,max:1,step:.05,value:s.threshold_low??.3,onChange:e=>g("threshold_low",e??.3),style:{width:80}})})]})})]})]}):(0,l.jsx)(b.Card,{title:(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,l.jsx)(W,{level:5,style:{margin:0},children:"Competitor Intent Filter"}),(0,l.jsx)(J.Switch,{checked:!1,onChange:p})]}),size:"small",children:(0,l.jsx)(V,{type:"secondary",children:"Block or reframe competitor comparison questions. When enabled, airline type auto-loads competitors from IATA; generic type requires manual competitor list."})})},{Title:Z,Text:ee}=f.Typography,et=({prebuiltPatterns:e,categories:t,selectedPatterns:a,blockedWords:s,onPatternAdd:n,onPatternRemove:o,onPatternActionChange:c,onBlockedWordAdd:u,onBlockedWordRemove:p,onBlockedWordUpdate:g,onFileUpload:x,accessToken:h,showStep:f,contentCategories:w=[],selectedContentCategories:N=[],onContentCategoryAdd:S,onContentCategoryRemove:k,onContentCategoryUpdate:A,pendingCategorySelection:O,onPendingCategorySelectionChange:T,competitorIntentEnabled:L=!1,competitorIntentConfig:B=null,onCompetitorIntentChange:F})=>{let[E,M]=(0,r.useState)(!1),[G,z]=(0,r.useState)(!1),[D,K]=(0,r.useState)(!1),[q,J]=(0,r.useState)(""),[U,W]=(0,r.useState)("BLOCK"),[V,Y]=(0,r.useState)(""),[Q,et]=(0,r.useState)(""),[ea,el]=(0,r.useState)("BLOCK"),[er,ei]=(0,r.useState)(""),[es,en]=(0,r.useState)("BLOCK"),[eo,ed]=(0,r.useState)(""),[ec,em]=(0,r.useState)(!1),eu=async e=>{em(!0);try{let t=await e.text();if(h){let e=await (0,m.validateBlockedWordsFile)(h,t);if(e.valid)x&&x(t),y.default.success(e.message||"File uploaded successfully");else{let t=e.error||e.errors&&e.errors.join(", ")||"Invalid file";y.default.error(`Validation failed: ${t}`)}}}catch(e){y.default.error(`Failed to upload file: ${e}`)}finally{em(!1)}return!1};return(0,l.jsxs)("div",{className:"space-y-6",children:[!f&&(0,l.jsx)("div",{children:(0,l.jsx)(ee,{type:"secondary",children:"Configure patterns, keywords, and content categories to detect and filter sensitive information in requests and responses."})}),(!f||"patterns"===f)&&(0,l.jsxs)(b.Card,{title:(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,l.jsx)(Z,{level:5,style:{margin:0},children:"Pattern Detection"}),(0,l.jsx)(ee,{type:"secondary",style:{fontSize:14,fontWeight:400},children:"Detect sensitive information using regex patterns (SSN, credit cards, API keys, etc.)"})]}),size:"small",children:[(0,l.jsx)("div",{style:{marginBottom:16},children:(0,l.jsxs)(j.Space,{children:[(0,l.jsx)(i.Button,{type:"primary",onClick:()=>M(!0),icon:(0,l.jsx)(d.PlusOutlined,{}),children:"Add prebuilt pattern"}),(0,l.jsx)(i.Button,{onClick:()=>K(!0),icon:(0,l.jsx)(d.PlusOutlined,{}),children:"Add custom regex"})]})}),(0,l.jsx)($,{patterns:a,onActionChange:c,onRemove:o})]}),(!f||"keywords"===f)&&(0,l.jsxs)(b.Card,{title:(0,l.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,l.jsx)(Z,{level:5,style:{margin:0},children:"Blocked Keywords"}),(0,l.jsx)(ee,{type:"secondary",style:{fontSize:14,fontWeight:400},children:"Block or mask specific sensitive terms and phrases"})]}),size:"small",children:[(0,l.jsx)("div",{style:{marginBottom:16},children:(0,l.jsxs)(j.Space,{children:[(0,l.jsx)(i.Button,{type:"primary",onClick:()=>z(!0),icon:(0,l.jsx)(d.PlusOutlined,{}),children:"Add keyword"}),(0,l.jsx)(_.Upload,{beforeUpload:eu,accept:".yaml,.yml",showUploadList:!1,children:(0,l.jsx)(i.Button,{icon:(0,l.jsx)(v.UploadOutlined,{}),loading:ec,children:"Upload YAML file"})})]})}),(0,l.jsx)(R,{keywords:s,onActionChange:g,onRemove:p})]}),(!f||"competitor_intent"===f||"categories"===f)&&F&&(0,l.jsx)(X,{enabled:L,config:B,onChange:F,accessToken:h}),(!f||"categories"===f)&&w.length>0&&S&&k&&A&&(0,l.jsx)(H,{availableCategories:w,selectedCategories:N,onCategoryAdd:S,onCategoryRemove:k,onCategoryUpdate:A,accessToken:h,pendingSelection:O,onPendingSelectionChange:T}),(0,l.jsx)(C,{visible:E,prebuiltPatterns:e,categories:t,selectedPatternName:q,patternAction:U,onPatternNameChange:J,onActionChange:e=>W(e),onAdd:()=>{if(!q)return void y.default.error("Please select a pattern");let t=e.find(e=>e.name===q);n({id:`pattern-${Date.now()}`,type:"prebuilt",name:q,display_name:t?.display_name,action:U}),M(!1),J(""),W("BLOCK")},onCancel:()=>{M(!1),J(""),W("BLOCK")}}),(0,l.jsx)(I,{visible:D,patternName:V,patternRegex:Q,patternAction:ea,onNameChange:Y,onRegexChange:et,onActionChange:e=>el(e),onAdd:()=>{V&&Q?(n({id:`custom-${Date.now()}`,type:"custom",name:V,pattern:Q,action:ea}),K(!1),Y(""),et(""),el("BLOCK")):y.default.error("Please provide pattern name and regex")},onCancel:()=>{K(!1),Y(""),et(""),el("BLOCK")}}),(0,l.jsx)(P,{visible:G,keyword:er,action:es,description:eo,onKeywordChange:ei,onActionChange:e=>en(e),onDescriptionChange:ed,onAdd:()=>{er?(u({id:`word-${Date.now()}`,keyword:er,action:es,description:eo||void 0}),z(!1),ei(""),ed(""),en("BLOCK")):y.default.error("Please enter a keyword")},onCancel:()=>{z(!1),ei(""),ed(""),en("BLOCK")}})]})};var ea=((t={}).PresidioPII="Presidio PII",t.Bedrock="Bedrock Guardrail",t.Lakera="Lakera",t);let el={},er=e=>{let t={};return t.PresidioPII="Presidio PII",t.Bedrock="Bedrock Guardrail",t.Lakera="Lakera",t.LlmAsAJudge="LiteLLM LLM as a Judge",Object.entries(e).forEach(([e,a])=>{a&&"object"==typeof a&&"ui_friendly_name"in a&&(t[e.split("_").map((e,t)=>e.charAt(0).toUpperCase()+e.slice(1)).join("")]=a.ui_friendly_name)}),el=t,t},ei=()=>Object.keys(el).length>0?el:ea,es={PresidioPII:"presidio",Bedrock:"bedrock",Lakera:"lakera_v2",LitellmContentFilter:"litellm_content_filter",ToolPermission:"tool_permission",BlockCodeExecution:"block_code_execution",Promptguard:"promptguard",LlmAsAJudge:"llm_as_a_judge",Xecguard:"xecguard",QostodianNexus:"qostodian_nexus",Repelloai:"repelloai"},en=e=>{Object.entries(e).forEach(([e,t])=>{t&&"object"==typeof t&&"ui_friendly_name"in t&&(es[e.split("_").map((e,t)=>e.charAt(0).toUpperCase()+e.slice(1)).join("")]=e)})},eo=e=>!!e&&"Presidio PII"===ei()[e],ed=e=>!!e&&"LiteLLM Content Filter"===ei()[e],ec=e=>!!e&&"llm_as_a_judge"===es[e],em="../ui/assets/logos/",eu={"Zscaler AI Guard":`${em}zscaler.svg`,"Presidio PII":`${em}microsoft_azure.svg`,"Bedrock Guardrail":`${em}bedrock.svg`,Lakera:`${em}lakeraai.jpeg`,"Azure Content Safety Prompt Shield":`${em}microsoft_azure.svg`,"Azure Content Safety Text Moderation":`${em}microsoft_azure.svg`,"Aporia AI":`${em}aporia.png`,"PANW Prisma AIRS":`${em}palo_alto_networks.jpeg`,"Cisco AI Defense":`${em}cisco.png`,"Noma Security":`${em}noma_security.png`,"Javelin Guardrails":`${em}javelin.png`,"Pillar Guardrail":`${em}pillar.jpeg`,"Google Cloud Model Armor":`${em}google.svg`,"Guardrails AI":`${em}guardrails_ai.jpeg`,"Lasso Guardrail":`${em}lasso.png`,"Pangea Guardrail":`${em}pangea.png`,"AIM Guardrail":`${em}aim_security.jpeg`,"Cato Networks Guardrail":`${em}cato_networks.svg`,"OpenAI Moderation":`${em}openai_small.svg`,EnkryptAI:`${em}enkrypt_ai.avif`,"Prompt Security":`${em}prompt_security.png`,PromptGuard:`${em}promptguard.svg`,XecGuard:`${em}xecguard.svg`,"LiteLLM Content Filter":`${em}litellm_logo.jpg`,"LiteLLM LLM as a Judge":`${em}litellm_logo.jpg`,Akto:`${em}akto.svg`,"Qostodian Nexus":`${em}qohash.jpg`,"RepelloAI Argus":`${em}repelloai.png`},ep=e=>{if(!e)return{logo:"",displayName:"-"};let t=Object.keys(es).find(t=>es[t].toLowerCase()===e.toLowerCase());if(!t)return{logo:"",displayName:e};let a=ei()[t];return{logo:eu[a]||"",displayName:a||e}};function eg(e){return!0===e?"yes":!1===e?"no":"inherit"}function ex(e){return!0===e?"yes":!1===e?"no":"inherit"}var eh=e.i(435451);let{Title:ef}=f.Typography,ey=({field:e,fieldKey:t,fullFieldKey:a,value:s})=>{let[n,o]=r.default.useState([]),[d,c]=r.default.useState(e.dict_key_options||[]);return r.default.useEffect(()=>{if(s&&"object"==typeof s){let t=Object.keys(s);o(t.map(e=>({key:e,id:`${e}_${Date.now()}_${Math.random()}`}))),c((e.dict_key_options||[]).filter(e=>!t.includes(e)))}},[s,e.dict_key_options]),(0,l.jsxs)("div",{className:"space-y-3",children:[n.map(t=>(0,l.jsxs)("div",{className:"flex items-center space-x-3 p-3 border rounded-lg",children:[(0,l.jsx)("div",{className:"w-24 font-medium text-sm",children:t.key}),(0,l.jsx)("div",{className:"flex-1",children:(0,l.jsx)(u.Form.Item,{name:Array.isArray(a)?[...a,t.key]:[a,t.key],style:{marginBottom:0},initialValue:s&&"object"==typeof s?s[t.key]:void 0,normalize:"number"===e.dict_value_type?e=>{if(null==e||""===e)return;let t=Number(e);return isNaN(t)?e:t}:void 0,children:"number"===e.dict_value_type?(0,l.jsx)(eh.default,{step:1,width:200,placeholder:`Enter ${t.key} value`}):"boolean"===e.dict_value_type?(0,l.jsxs)(x.Select,{placeholder:`Select ${t.key} value`,children:[(0,l.jsx)(x.Select.Option,{value:!0,children:"True"}),(0,l.jsx)(x.Select.Option,{value:!1,children:"False"})]}):(0,l.jsx)(p.Input,{placeholder:`Enter ${t.key} value`})})}),(0,l.jsx)(i.Button,{type:"text",danger:!0,size:"small",onClick:()=>{var e,a;return e=t.id,a=t.key,void(o(n.filter(t=>t.id!==e)),c([...d,a].sort()))},children:"Remove"})]},t.id)),d.length>0&&(0,l.jsxs)("div",{className:"flex items-center space-x-3 mt-2",children:[(0,l.jsx)(x.Select,{placeholder:"Select category to configure",style:{width:200},onSelect:e=>e&&void(!e||(o([...n,{key:e,id:`${e}_${Date.now()}`}]),c(d.filter(t=>t!==e)))),value:void 0,children:d.map(e=>(0,l.jsx)(x.Select.Option,{value:e,children:e},e))}),(0,l.jsx)("span",{className:"text-sm text-gray-500",children:"Select a category to add threshold configuration"})]})]})},ej=({optionalParams:e,parentFieldKey:t,values:a})=>e.fields&&0!==Object.keys(e.fields).length?(0,l.jsxs)("div",{className:"guardrail-optional-params",children:[(0,l.jsxs)("div",{className:"mb-8 pb-4 border-b border-gray-100",children:[(0,l.jsx)(ef,{level:3,className:"mb-2 font-semibold text-gray-900",children:"Optional Parameters"}),(0,l.jsx)("p",{className:"text-gray-600 text-sm",children:e.description||"Configure additional settings for this guardrail provider"})]}),(0,l.jsx)("div",{className:"space-y-8",children:Object.entries(e.fields).map(([e,r])=>{let i,s;return i=`${t}.${e}`,(console.log("value",s=a?.[e]),"dict"===r.type&&r.dict_key_options)?(0,l.jsxs)("div",{className:"mb-8 p-6 bg-gray-50 rounded-lg border border-gray-200",children:[(0,l.jsx)("div",{className:"mb-4 font-medium text-gray-900 text-base",children:e}),(0,l.jsx)("p",{className:"text-sm text-gray-600 mb-4",children:r.description}),(0,l.jsx)(ey,{field:r,fieldKey:e,fullFieldKey:[t,e],value:s})]},i):(0,l.jsx)("div",{className:"mb-8 p-6 bg-white rounded-lg border border-gray-200 shadow-sm",children:(0,l.jsx)(u.Form.Item,{name:[t,e],label:(0,l.jsxs)("div",{className:"mb-2",children:[(0,l.jsx)("div",{className:"font-medium text-gray-900 text-base",children:e}),(0,l.jsx)("p",{className:"text-sm text-gray-600 mt-1",children:r.description})]}),rules:r.required?[{required:!0,message:`${e} is required`}]:void 0,className:"mb-0",initialValue:void 0!==s?s:r.default_value,normalize:"number"===r.type?e=>{if(null==e||""===e)return;let t=Number(e);return isNaN(t)?e:t}:void 0,children:"select"===r.type&&r.options?(0,l.jsx)(x.Select,{placeholder:r.description,children:r.options.map(e=>(0,l.jsx)(x.Select.Option,{value:e,children:e},e))}):"multiselect"===r.type&&r.options?(0,l.jsx)(x.Select,{mode:"multiple",placeholder:r.description,children:r.options.map(e=>(0,l.jsx)(x.Select.Option,{value:e,children:e},e))}):"bool"===r.type||"boolean"===r.type?(0,l.jsxs)(x.Select,{placeholder:r.description,children:[(0,l.jsx)(x.Select.Option,{value:!0,children:"True"}),(0,l.jsx)(x.Select.Option,{value:!1,children:"False"})]}):"number"===r.type?(0,l.jsx)(eh.default,{step:1,width:400,placeholder:r.description}):e.includes("password")||e.includes("secret")||e.includes("key")?(0,l.jsx)(p.Input.Password,{placeholder:r.description}):(0,l.jsx)(p.Input,{placeholder:r.description})})},i)})})]}):null;var e_=e.i(482725),eb=e.i(850627);let ev=({selectedProvider:e,accessToken:t,providerParams:a=null,value:i=null})=>{let[s,n]=(0,r.useState)(!1),[o,d]=(0,r.useState)(a),[c,g]=(0,r.useState)(null);if((0,r.useEffect)(()=>{if(a)return void d(a);let e=async()=>{if(t){n(!0),g(null);try{let e=await (0,m.getGuardrailProviderSpecificParams)(t);console.log("Provider params API response:",e),d(e),er(e),en(e)}catch(e){console.error("Error fetching provider params:",e),g("Failed to load provider parameters")}finally{n(!1)}}};a||e()},[t,a]),!e)return null;if(s)return(0,l.jsx)(e_.Spin,{tip:"Loading provider parameters..."});if(c)return(0,l.jsx)("div",{className:"text-red-500",children:c});let h=es[e]?.toLowerCase(),f=o&&o[h];if(console.log("Provider key:",h),console.log("Provider fields:",f),!f||0===Object.keys(f).length)return(0,l.jsx)("div",{children:"No configuration fields available for this provider."});console.log("Value:",i);let y=new Set(["patterns","blocked_words","blocked_words_file","categories","severity_threshold","pattern_redaction_format","keyword_redaction_tag"]),j=ed(e),_=(e,t="",a)=>Object.entries(e).map(([e,r])=>{let s=t?`${t}.${e}`:e,n=a?a[e]:i?.[e];if(console.log("Field value:",n),"ui_friendly_name"===e||"optional_params"===e&&"nested"===r.type&&r.fields||j&&y.has(e))return null;if("nested"===r.type&&r.fields)return(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"mb-2 font-medium",children:e}),(0,l.jsx)("div",{className:"ml-4 border-l-2 border-gray-200 pl-4",children:_(r.fields,s,n)})]},s);let o=void 0!==n?n:r.default_value??("percentage"===r.type?.5:void 0);return(0,l.jsx)(u.Form.Item,{name:s,label:e,tooltip:r.description,rules:r.required?[{required:!0,message:`${e} is required`}]:void 0,initialValue:o,children:"select"===r.type&&r.options?(0,l.jsx)(x.Select,{placeholder:r.description,defaultValue:n||r.default_value,children:r.options.map(e=>(0,l.jsx)(x.Select.Option,{value:e,children:e},e))}):"multiselect"===r.type&&r.options?(0,l.jsx)(x.Select,{mode:"multiple",placeholder:r.description,defaultValue:n||r.default_value,children:r.options.map(e=>(0,l.jsx)(x.Select.Option,{value:e,children:e},e))}):"bool"===r.type||"boolean"===r.type?(0,l.jsxs)(x.Select,{placeholder:r.description,children:[(0,l.jsx)(x.Select.Option,{value:!0,children:"True"}),(0,l.jsx)(x.Select.Option,{value:!1,children:"False"})]}):"percentage"===r.type&&null!=r.min&&null!=r.max?(0,l.jsx)(eb.Slider,{min:r.min,max:r.max,step:r.step??.1,marks:{[r.min]:"0%",[(r.min+r.max)/2]:"50%",[r.max]:"100%"}}):"number"===r.type?(0,l.jsx)(eh.default,{step:1,width:400,placeholder:r.description,defaultValue:void 0!==n?Number(n):void 0}):e.includes("password")||e.includes("secret")||e.includes("key")?(0,l.jsx)(p.Input.Password,{placeholder:r.description,defaultValue:n||""}):(0,l.jsx)(p.Input,{placeholder:r.description,defaultValue:n||""})},s)});return(0,l.jsx)(l.Fragment,{children:_(f)})};var ew=e.i(592968),eN=e.i(750113);let eC=({availableModels:e,form:t})=>(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)("div",{style:{background:"#f6ffed",border:"1px solid #b7eb8f",borderRadius:6,padding:"10px 14px",marginBottom:16,fontSize:13,color:"#389e0d"},children:["After each LLM response, the ",(0,l.jsx)("strong",{children:"Judge Model"})," scores it 0–100 against your criteria. If the weighted average falls below the threshold, the response is blocked (or logged)."]}),(0,l.jsx)(u.Form.Item,{name:"judge_model",label:(0,l.jsxs)("span",{children:["Judge Model ",(0,l.jsx)(ew.Tooltip,{title:"The LLM that reads each response and grades it. Pick a capable model — it never sees end-user data beyond what the LLM returned.",children:(0,l.jsx)(eN.QuestionCircleOutlined,{style:{color:"#8c8c8c"}})})]}),rules:[{required:!0,message:"Select a judge model"}],children:(0,l.jsx)(x.Select,{showSearch:!0,placeholder:"Select a model",options:e.map(e=>({label:e,value:e}))})}),(0,l.jsx)(u.Form.Item,{name:"overall_threshold",label:(0,l.jsxs)("span",{children:["Minimum Score to Pass ",(0,l.jsx)(ew.Tooltip,{title:"0–100. If the weighted average of criterion scores falls below this, the guardrail triggers. 80 is a good default.",children:(0,l.jsx)(eN.QuestionCircleOutlined,{style:{color:"#8c8c8c"}})})]}),initialValue:80,children:(0,l.jsx)(U.InputNumber,{min:0,max:100,addonAfter:"/ 100",style:{width:"100%"}})}),(0,l.jsx)(u.Form.Item,{name:"on_failure",label:(0,l.jsxs)("span",{children:["On Failure ",(0,l.jsx)(ew.Tooltip,{title:"Block: return HTTP 422 when the score is too low. Log: record the result but let the response through.",children:(0,l.jsx)(eN.QuestionCircleOutlined,{style:{color:"#8c8c8c"}})})]}),initialValue:"block",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:"block",children:"Block (return 422)"}),(0,l.jsx)(x.Select.Option,{value:"log",children:"Log only"})]})}),(0,l.jsx)(u.Form.Item,{label:(0,l.jsxs)("span",{children:["Evaluation Criteria ",(0,l.jsx)(ew.Tooltip,{title:"Each criterion is something the judge checks. Weights must add up to 100%.",children:(0,l.jsx)(eN.QuestionCircleOutlined,{style:{color:"#8c8c8c"}})})]}),children:(0,l.jsx)(u.Form.List,{name:"criteria",initialValue:[{name:"",weight:100,description:""}],children:(e,{add:a,remove:r})=>(0,l.jsxs)(l.Fragment,{children:[e.map(({key:e,name:t,...a})=>(0,l.jsxs)("div",{style:{border:"1px solid #f0f0f0",borderRadius:6,padding:"12px 12px 0",marginBottom:8},children:[(0,l.jsxs)("div",{style:{display:"flex",gap:8,alignItems:"flex-end"},children:[(0,l.jsx)(u.Form.Item,{...a,name:[t,"name"],rules:[{required:!0,message:"Enter criterion name"}],style:{flex:2,marginBottom:8},children:(0,l.jsx)(p.Input,{placeholder:"Criterion name (e.g. Policy accuracy)"})}),(0,l.jsx)(u.Form.Item,{...a,name:[t,"weight"],label:(0,l.jsx)(ew.Tooltip,{title:"How much this criterion counts toward the final score. All weights must add up to 100%.",children:(0,l.jsxs)("span",{style:{fontSize:12,color:"#595959"},children:["Weight ",(0,l.jsx)(eN.QuestionCircleOutlined,{style:{color:"#bfbfbf"}})]})}),rules:[{required:!0,message:"Enter weight"}],style:{flex:1,marginBottom:8},children:(0,l.jsx)(U.InputNumber,{min:0,max:100,addonAfter:"%",style:{width:"100%"},placeholder:"e.g. 50"})}),(0,l.jsx)("div",{style:{marginBottom:8},children:(0,l.jsx)(i.Button,{type:"text",danger:!0,size:"small",onClick:()=>r(t),children:"×"})})]}),(0,l.jsx)(u.Form.Item,{...a,name:[t,"description"],rules:[{required:!0,message:"Describe what to check"}],style:{marginBottom:8},children:(0,l.jsx)(p.Input,{placeholder:"What should the judge check for this criterion?"})})]},e)),(0,l.jsx)(i.Button,{type:"dashed",block:!0,style:{marginTop:4},onClick:()=>a({name:"",weight:0,description:""}),icon:(0,l.jsx)(d.PlusOutlined,{}),children:"Add Criterion"}),e.length>0&&(0,l.jsx)(u.Form.Item,{shouldUpdate:!0,noStyle:!0,children:()=>{let e=(t.getFieldValue("criteria")||[]).reduce((e,t)=>e+(Number(t?.weight)||0),0),a=100===e;return(0,l.jsxs)("div",{style:{marginTop:6,fontSize:12,color:a?"#52c41a":"#faad14"},children:["Weights total: ",e,"%",a?" ✓":" — must add up to 100%"]})}})]})})})]});var eS=e.i(536916),ek=e.i(149192),eI=e.i(741585),eI=eI,eA=e.i(724154);e.i(247167);var eO=e.i(931067);let eP={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"}}]},name:"filter",theme:"outlined"};var eT=e.i(9583),eL=r.forwardRef(function(e,t){return r.createElement(eT.default,(0,eO.default)({},e,{ref:t,icon:eP}))});let{Text:eB}=f.Typography,{Option:eF}=x.Select,e$=({categories:e,selectedCategories:t,onChange:a})=>(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex items-center mb-2",children:[(0,l.jsx)(eL,{className:"text-gray-500 mr-1"}),(0,l.jsx)(eB,{className:"text-gray-500 font-medium",children:"Filter by category"})]}),(0,l.jsx)(x.Select,{mode:"multiple",placeholder:"Select categories to filter by",style:{width:"100%"},onChange:a,value:t,allowClear:!0,showSearch:!0,optionFilterProp:"children",className:"mb-4",tagRender:e=>(0,l.jsx)(h.Tag,{color:"blue",closable:e.closable,onClose:e.onClose,className:"mr-2 mb-2",children:e.label}),children:e.map(e=>(0,l.jsx)(eF,{value:e.category,children:e.category},e.category))})]}),eE=({onSelectAll:e,onUnselectAll:t,hasSelectedEntities:a})=>(0,l.jsxs)("div",{className:"bg-gray-50 p-5 rounded-lg mb-6 border border-gray-200 shadow-sm",children:[(0,l.jsxs)("div",{className:"flex items-center justify-between mb-4",children:[(0,l.jsxs)("div",{className:"flex items-center",children:[(0,l.jsx)(eB,{strong:!0,className:"text-gray-700 text-base",children:"Quick Actions"}),(0,l.jsx)(ew.Tooltip,{title:"Apply action to all PII types at once",children:(0,l.jsx)("div",{className:"ml-2 text-gray-400 cursor-help text-xs",children:"ⓘ"})})]}),(0,l.jsx)(i.Button,{color:"danger",variant:"outlined",onClick:t,disabled:!a,icon:(0,l.jsx)(ek.CloseOutlined,{}),children:"Unselect All"})]}),(0,l.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,l.jsx)(i.Button,{color:"primary",variant:"outlined",onClick:()=>e("MASK"),className:"h-10",block:!0,icon:(0,l.jsx)(eI.default,{}),children:"Select All & Mask"}),(0,l.jsx)(i.Button,{color:"danger",variant:"outlined",onClick:()=>e("BLOCK"),className:"h-10 hover:bg-red-100",block:!0,icon:(0,l.jsx)(eA.StopOutlined,{}),children:"Select All & Block"})]})]}),eM=({entities:e,selectedEntities:t,selectedActions:a,actions:r,onEntitySelect:i,onActionSelect:s,entityToCategoryMap:n})=>(0,l.jsxs)("div",{className:"border rounded-lg overflow-hidden shadow-sm",children:[(0,l.jsxs)("div",{className:"bg-gray-50 px-5 py-3 border-b flex",children:[(0,l.jsx)(eB,{strong:!0,className:"flex-1 text-gray-700",children:"PII Type"}),(0,l.jsx)(eB,{strong:!0,className:"w-32 text-right text-gray-700",children:"Action"})]}),(0,l.jsx)("div",{className:"max-h-[400px] overflow-y-auto",children:0===e.length?(0,l.jsx)("div",{className:"py-10 text-center text-gray-500",children:"No PII types match your filter criteria"}):e.map(e=>(0,l.jsxs)("div",{className:`px-5 py-3 flex items-center justify-between hover:bg-gray-50 border-b ${t.includes(e)?"bg-blue-50":""}`,children:[(0,l.jsxs)("div",{className:"flex items-center flex-1",children:[(0,l.jsx)(eS.Checkbox,{checked:t.includes(e),onChange:()=>i(e),className:"mr-3"}),(0,l.jsx)(eB,{className:t.includes(e)?"font-medium text-gray-900":"text-gray-700",children:e.replace(/_/g," ")}),n.get(e)&&(0,l.jsx)(h.Tag,{className:"ml-2 text-xs",color:"blue",children:n.get(e)})]}),(0,l.jsx)("div",{className:"w-32",children:(0,l.jsx)(x.Select,{value:t.includes(e)&&a[e]||"MASK",onChange:t=>s(e,t),style:{width:120},disabled:!t.includes(e),className:`${!t.includes(e)?"opacity-50":""}`,dropdownMatchSelectWidth:!1,children:r.map(e=>(0,l.jsx)(eF,{value:e,children:(0,l.jsxs)("div",{className:"flex items-center",children:[(e=>{switch(e){case"MASK":return(0,l.jsx)(eI.default,{style:{marginRight:4}});case"BLOCK":return(0,l.jsx)(eA.StopOutlined,{style:{marginRight:4}});default:return null}})(e),e]})},e))})})]},e))})]}),{Title:eR,Text:eG}=f.Typography,ez=({entities:e,actions:t,selectedEntities:a,selectedActions:i,onEntitySelect:s,onActionSelect:n,entityCategories:o=[]})=>{let[d,c]=(0,r.useState)([]),m=new Map;o.forEach(e=>{e.entities.forEach(t=>{m.set(t,e.category)})});let u=e.filter(e=>0===d.length||d.includes(m.get(e)||""));return(0,l.jsxs)("div",{className:"pii-configuration",children:[(0,l.jsxs)("div",{className:"flex justify-between items-center mb-5",children:[(0,l.jsx)("div",{className:"flex items-center",children:(0,l.jsx)(eR,{level:4,className:"!m-0 font-semibold text-gray-800",children:"Configure PII Protection"})}),(0,l.jsxs)(eG,{className:"text-gray-500",children:[a.length," items selected"]})]}),(0,l.jsxs)("div",{className:"mb-6",children:[(0,l.jsx)(e$,{categories:o,selectedCategories:d,onChange:c}),(0,l.jsx)(eE,{onSelectAll:t=>{e.forEach(e=>{a.includes(e)||s(e),n(e,t)})},onUnselectAll:()=>{a.forEach(e=>{s(e)})},hasSelectedEntities:a.length>0})]}),(0,l.jsx)(eM,{entities:u,selectedEntities:a,selectedActions:i,actions:t,onEntitySelect:s,onActionSelect:n,entityToCategoryMap:m})]})};var eD=e.i(304967),eK=e.i(599724),eq=e.i(312361),eH=e.i(21548),eJ=e.i(827252);let eU={rules:[],default_action:"deny",on_disallowed_action:"block",violation_message_template:""},eW=({value:e,onChange:t,disabled:a=!1})=>{let r={...eU,...e||{},rules:e?.rules?[...e.rules]:[]},s=e=>{let a={...r,...e};t?.(a)},n=(e,t)=>{s({rules:r.rules.map((a,l)=>l===e?{...a,...t}:a)})},o=(e,t)=>{let a=r.rules[e];if(!a)return;let l=Object.entries(a.allowed_param_patterns||{});t(l);let i={};l.forEach(([e,t])=>{i[e]=t}),n(e,{allowed_param_patterns:Object.keys(i).length>0?i:void 0})};return(0,l.jsxs)(eD.Card,{children:[(0,l.jsxs)("div",{className:"flex items-center justify-between",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"text-lg font-semibold",children:"LiteLLM Tool Permission Guardrail"}),(0,l.jsx)(eK.Text,{className:"text-sm text-gray-500",children:"Provide regex patterns (e.g., ^mcp__github_.*$) for tool names or types and optionally constrain payload fields."})]}),!a&&(0,l.jsx)(i.Button,{icon:(0,l.jsx)(d.PlusOutlined,{}),type:"primary",onClick:()=>{s({rules:[...r.rules,{id:`rule_${Math.random().toString(36).slice(2,8)}`,decision:"allow",allowed_param_patterns:void 0}]})},className:"!bg-blue-600 !text-white hover:!bg-blue-500",children:"Add Rule"})]}),(0,l.jsx)(eq.Divider,{}),0===r.rules.length?(0,l.jsx)(eH.Empty,{description:"No tool rules added yet"}):(0,l.jsx)("div",{className:"space-y-4",children:r.rules.map((e,t)=>{let d;return(0,l.jsxs)(eD.Card,{className:"bg-gray-50",children:[(0,l.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,l.jsxs)(eK.Text,{className:"font-semibold",children:["Rule ",t+1]}),(0,l.jsx)(i.Button,{icon:(0,l.jsx)(L.DeleteOutlined,{}),danger:!0,type:"text",disabled:a,onClick:()=>{s({rules:r.rules.filter((e,a)=>a!==t)})},children:"Remove"})]}),(0,l.jsxs)("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"text-sm font-medium",children:"Rule ID"}),(0,l.jsx)(p.Input,{disabled:a,placeholder:"unique_rule_id",value:e.id,onChange:e=>n(t,{id:e.target.value})})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"text-sm font-medium",children:"Tool Name (optional)"}),(0,l.jsx)(p.Input,{disabled:a,placeholder:"^mcp__github_.*$",value:e.tool_name??"",onChange:e=>n(t,{tool_name:""===e.target.value.trim()?void 0:e.target.value})})]})]}),(0,l.jsx)("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 mt-4",children:(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"text-sm font-medium",children:"Tool Type (optional)"}),(0,l.jsx)(p.Input,{disabled:a,placeholder:"^function$",value:e.tool_type??"",onChange:e=>n(t,{tool_type:""===e.target.value.trim()?void 0:e.target.value})})]})}),(0,l.jsxs)("div",{className:"mt-4 flex flex-col gap-2",children:[(0,l.jsx)(eK.Text,{className:"text-sm font-medium",children:"Decision"}),(0,l.jsxs)(x.Select,{disabled:a,value:e.decision,style:{width:200},onChange:e=>n(t,{decision:e}),children:[(0,l.jsx)(x.Select.Option,{value:"allow",children:"Allow"}),(0,l.jsx)(x.Select.Option,{value:"deny",children:"Deny"})]})]}),(0,l.jsx)("div",{className:"mt-4",children:0===(d=Object.entries(e.allowed_param_patterns||{})).length?(0,l.jsx)(i.Button,{disabled:a,size:"small",onClick:()=>n(t,{allowed_param_patterns:{"":""}}),children:"+ Restrict tool arguments (optional)"}):(0,l.jsxs)("div",{className:"space-y-2",children:[(0,l.jsx)(eK.Text,{className:"text-sm text-gray-600",children:"Argument constraints (dot or array paths)"}),d.map(([r,s],n)=>(0,l.jsxs)(j.Space,{align:"start",children:[(0,l.jsx)(p.Input,{disabled:a,placeholder:"messages[0].content",value:r,onChange:e=>{var a;return a=e.target.value,void o(t,e=>{if(!e[n])return;let[,t]=e[n];e[n]=[a,t]})}}),(0,l.jsx)(p.Input,{disabled:a,placeholder:"^email@.*$",value:s,onChange:e=>{var a;return a=e.target.value,void o(t,e=>{if(!e[n])return;let[t]=e[n];e[n]=[t,a]})}}),(0,l.jsx)(i.Button,{disabled:a,icon:(0,l.jsx)(L.DeleteOutlined,{}),danger:!0,onClick:()=>o(t,e=>{e.splice(n,1)})})]},`${e.id||t}-${n}`)),(0,l.jsx)(i.Button,{disabled:a,size:"small",onClick:()=>n(t,{allowed_param_patterns:{...e.allowed_param_patterns||{},"":""}}),children:"+ Add another constraint"})]})})]},e.id||t)})}),(0,l.jsx)(eq.Divider,{}),(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"text-sm font-medium",children:"Default action"}),(0,l.jsxs)(x.Select,{disabled:a,value:r.default_action,onChange:e=>s({default_action:e}),children:[(0,l.jsx)(x.Select.Option,{value:"allow",children:"Allow"}),(0,l.jsx)(x.Select.Option,{value:"deny",children:"Deny"})]})]}),(0,l.jsxs)("div",{children:[(0,l.jsxs)(eK.Text,{className:"text-sm font-medium flex items-center gap-1",children:["On disallowed action",(0,l.jsx)(ew.Tooltip,{title:"Block returns an error when a forbidden tool is invoked. Rewrite strips the tool call but lets the rest of the response continue.",children:(0,l.jsx)(eJ.InfoCircleOutlined,{})})]}),(0,l.jsxs)(x.Select,{disabled:a,value:r.on_disallowed_action,onChange:e=>s({on_disallowed_action:e}),children:[(0,l.jsx)(x.Select.Option,{value:"block",children:"Block"}),(0,l.jsx)(x.Select.Option,{value:"rewrite",children:"Rewrite"})]})]})]}),(0,l.jsxs)("div",{className:"mt-4",children:[(0,l.jsx)(eK.Text,{className:"text-sm font-medium",children:"Violation message (optional)"}),(0,l.jsx)(p.Input.TextArea,{disabled:a,rows:3,placeholder:"This violates our org policy...",value:r.violation_message_template,onChange:e=>s({violation_message_template:e.target.value})})]})]})},{Title:eV,Text:eY,Link:eQ}=f.Typography,{Option:eX}=x.Select,eZ={pre_call:"Before LLM Call - Runs before the LLM call and checks the input (Recommended)",during_call:"During LLM Call - Runs in parallel with the LLM call, with response held until check completes",post_call:"After LLM Call - Runs after the LLM call and checks only the output",logging_only:"Logging Only - Only runs on logging callbacks without affecting the LLM call",pre_mcp_call:"Before MCP Tool Call - Runs before MCP tool execution and validates tool calls",during_mcp_call:"During MCP Tool Call - Runs in parallel with MCP tool execution for monitoring"},e0=({visible:e,onClose:t,accessToken:a,onSuccess:s,preset:n})=>{let[o]=u.Form.useForm(),[d,c]=(0,r.useState)(!1),[f,j]=(0,r.useState)(null),[_,b]=(0,r.useState)(null),[v,w]=(0,r.useState)([]),[N,C]=(0,r.useState)({}),[S,k]=(0,r.useState)(0),[I,A]=(0,r.useState)(null),[O,P]=(0,r.useState)([]),[T,L]=(0,r.useState)(2),[B,F]=(0,r.useState)({}),[$,E]=(0,r.useState)([]),[M,R]=(0,r.useState)([]),[G,z]=(0,r.useState)([]),[D,K]=(0,r.useState)(""),[q,H]=(0,r.useState)(!1),[J,U]=(0,r.useState)(null),[W,V]=(0,r.useState)(""),[Y,Q]=(0,r.useState)(void 0),[X,Z]=(0,r.useState)("warn"),[ee,ea]=(0,r.useState)(""),[el,em]=(0,r.useState)(!1),[ep,eg]=(0,r.useState)([]),[ex,eh]=(0,r.useState)({rules:[],default_action:"deny",on_disallowed_action:"block",violation_message_template:""}),ef=(0,r.useMemo)(()=>!!f&&"tool_permission"===(es[f]||"").toLowerCase(),[f]);(0,r.useEffect)(()=>{a&&(async()=>{try{let[e,t,l]=await Promise.all([(0,m.getGuardrailUISettings)(a),(0,m.getGuardrailProviderSpecificParams)(a),(0,m.modelAvailableCall)(a,"","").catch(()=>null)]);b(e),A(t),l?.data&&eg(l.data.map(e=>e.id)),er(t),en(t)}catch(e){console.error("Error fetching guardrail data:",e),y.default.fromBackend("Failed to load guardrail configuration")}})()},[a]),(0,r.useEffect)(()=>{if(!n||!e||!_)return;j(n.provider);let t={provider:n.provider,guardrail_name:n.guardrailNameSuggestion,mode:n.mode,default_on:n.defaultOn,skip_system_message_choice:"inherit",skip_tool_message_choice:"inherit"};if("BlockCodeExecution"===n.provider&&(t.confidence_threshold=.5),o.setFieldsValue(t),n.categoryName&&_.content_filter_settings?.content_categories){let e=_.content_filter_settings.content_categories.find(e=>e.name===n.categoryName);e&&z([{id:`category-${Date.now()}`,category:e.name,display_name:e.display_name,action:e.default_action,severity_threshold:"medium"}])}},[n,e,_]);let ey=e=>{j(e);let t={config:void 0,presidio_analyzer_api_base:void 0,presidio_anonymizer_api_base:void 0};"BlockCodeExecution"===e&&(t.confidence_threshold=.5),o.setFieldsValue(t),w([]),C({}),P([]),L(2),F({}),E([]),R([]),z([]),K(""),H(!1),U(null),eh({rules:[],default_action:"deny",on_disallowed_action:"block",violation_message_template:""}),"LlmAsAJudge"===e&&o.setFieldsValue({mode:"post_call"})},e_=e=>{w(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},eb=(e,t)=>{C(a=>({...a,[e]:t}))},ew=async()=>{try{if(0===S&&(await o.validateFields(["guardrail_name","provider","mode","default_on"]),f)){let e=["guardrail_name","provider","mode","default_on"];"PresidioPII"===f&&e.push("presidio_analyzer_api_base","presidio_anonymizer_api_base"),await o.validateFields(e)}if(1===S&&eo(f)&&0===v.length)return void y.default.fromBackend("Please select at least one PII entity to continue");k(S+1)}catch(e){console.error("Form validation failed:",e)}},eN=()=>{o.resetFields(),j(null),w([]),C({}),P([]),L(2),F({}),E([]),R([]),z([]),K(""),eh({rules:[],default_action:"deny",on_disallowed_action:"block",violation_message_template:""}),V(""),Q(void 0),Z("warn"),ea(""),em(!1),k(0)},eS=()=>{eN(),t()},ek=async()=>{try{var e,l;c(!0),await o.validateFields();let r=o.getFieldsValue(!0),i=es[r.provider],n={guardrail_name:r.guardrail_name,litellm_params:{guardrail:i,mode:r.mode,default_on:r.default_on},guardrail_info:{}},d=(e=r.skip_system_message_choice,"yes"===e||"no"!==e&&void 0);void 0!==d&&(n.litellm_params.skip_system_message_in_guardrail=d);let u=(l=r.skip_tool_message_choice,"yes"===l||"no"!==l&&void 0);if(void 0!==u&&(n.litellm_params.skip_tool_message_in_guardrail=u),"PresidioPII"===r.provider&&v.length>0){let e={};v.forEach(t=>{e[t]=N[t]||"MASK"}),n.litellm_params.pii_entities_config=e,r.presidio_analyzer_api_base&&(n.litellm_params.presidio_analyzer_api_base=r.presidio_analyzer_api_base),r.presidio_anonymizer_api_base&&(n.litellm_params.presidio_anonymizer_api_base=r.presidio_anonymizer_api_base)}if(ed(r.provider)){let e=q&&J?.brand_self?.length>0;if(0===$.length&&0===M.length&&0===G.length&&!e){y.default.fromBackend("Please configure at least one content filter setting (category, pattern, keyword, or competitor intent)"),c(!1);return}$.length>0&&(n.litellm_params.patterns=$.map(e=>({pattern_type:"prebuilt"===e.type?"prebuilt":"regex",pattern_name:"prebuilt"===e.type?e.name:void 0,pattern:"custom"===e.type?e.pattern:void 0,name:e.name,action:e.action}))),M.length>0&&(n.litellm_params.blocked_words=M.map(e=>({keyword:e.keyword,action:e.action,description:e.description}))),G.length>0&&(n.litellm_params.categories=G.map(e=>({category:e.category,enabled:!0,action:e.action,severity_threshold:e.severity_threshold||"medium"}))),q&&J?.brand_self?.length>0&&(n.litellm_params.competitor_intent_config={competitor_intent_type:J.competitor_intent_type??"airline",brand_self:J.brand_self,locations:J.locations?.length>0?J.locations:void 0,competitors:"generic"===J.competitor_intent_type&&J.competitors?.length>0?J.competitors:void 0,policy:J.policy,threshold_high:J.threshold_high,threshold_medium:J.threshold_medium,threshold_low:J.threshold_low})}else if(r.config)try{n.guardrail_info=JSON.parse(r.config)}catch(e){y.default.fromBackend("Invalid JSON in configuration"),c(!1);return}if("llm_as_a_judge"===i){let e=r.criteria||[];if(0===e.length){y.default.fromBackend("Add at least one evaluation criterion"),c(!1);return}let t=e.reduce((e,t)=>e+(Number(t?.weight)||0),0);if(100!==t){y.default.fromBackend(`Criterion weights must sum to 100% (currently ${t}%)`),c(!1);return}n.litellm_params.judge_model=r.judge_model,n.litellm_params.overall_threshold=r.overall_threshold??80,n.litellm_params.on_failure=r.on_failure??"block",n.litellm_params.criteria=e.map(e=>({name:e.name,weight:Number(e.weight),description:e.description||""}))}if("tool_permission"===i){if(0===ex.rules.length){y.default.fromBackend("Add at least one tool permission rule"),c(!1);return}n.litellm_params.rules=ex.rules,n.litellm_params.default_action=ex.default_action,n.litellm_params.on_disallowed_action=ex.on_disallowed_action,ex.violation_message_template&&(n.litellm_params.violation_message_template=ex.violation_message_template)}if(ed(r.provider)&&(void 0!==Y&&Y>0&&(n.litellm_params.end_session_after_n_fails=Y),X&&"realtime"===W&&(n.litellm_params.on_violation=X),ee.trim()&&(n.litellm_params.realtime_violation_message=ee.trim())),console.log("values: ",JSON.stringify(r)),I&&f&&"llm_as_a_judge"!==i){let e=es[f]?.toLowerCase();console.log("providerKey: ",e);let t=I[e]||{},a=new Set;console.log("providerSpecificParams: ",JSON.stringify(t)),Object.keys(t).forEach(e=>{"optional_params"!==e&&a.add(e)}),t.optional_params&&t.optional_params.fields&&Object.keys(t.optional_params.fields).forEach(e=>{a.add(e)}),console.log("allowedParams: ",a),a.forEach(e=>{let t=r[e];(null==t||""===t)&&(t=r.optional_params?.[e]),null!=t&&""!==t&&(n.litellm_params[e]=t)})}if(!a)throw Error("No access token available");console.log("Sending guardrail data:",JSON.stringify(n)),await (0,m.createGuardrailCall)(a,n),y.default.success("Guardrail created successfully"),eN(),s(),t()}catch(e){console.error("Failed to create guardrail:",e),y.default.fromBackend("Failed to create guardrail: "+(e instanceof Error?e.message:String(e)))}finally{c(!1)}},eI=e=>{if(!_||!ed(f))return null;let t=_.content_filter_settings;return t?(0,l.jsx)(et,{prebuiltPatterns:t.prebuilt_patterns||[],categories:t.pattern_categories||[],selectedPatterns:$,blockedWords:M,onPatternAdd:e=>E([...$,e]),onPatternRemove:e=>E($.filter(t=>t.id!==e)),onPatternActionChange:(e,t)=>{E($.map(a=>a.id===e?{...a,action:t}:a))},onBlockedWordAdd:e=>R([...M,e]),onBlockedWordRemove:e=>R(M.filter(t=>t.id!==e)),onBlockedWordUpdate:(e,t,a)=>{R(M.map(l=>l.id===e?{...l,[t]:a}:l))},contentCategories:t.content_categories||[],selectedContentCategories:G,onContentCategoryAdd:e=>z([...G,e]),onContentCategoryRemove:e=>z(G.filter(t=>t.id!==e)),onContentCategoryUpdate:(e,t,a)=>{z(G.map(l=>l.id===e?{...l,[t]:a}:l))},pendingCategorySelection:D,onPendingCategorySelectionChange:K,accessToken:a,showStep:e,competitorIntentEnabled:q,competitorIntentConfig:J,onCompetitorIntentChange:(e,t)=>{H(e),U(t)}}):null},eA=ed(f)?[{title:"Basic Info",optional:!1},{title:"Topics",optional:!1},{title:"Patterns",optional:!1},{title:"Keywords",optional:!1},{title:"Endpoint Settings (Optional)",optional:!0}]:eo(f)?[{title:"Basic Info",optional:!1},{title:"PII Configuration",optional:!1}]:[{title:"Basic Info",optional:!1},{title:"Provider Configuration",optional:!1}];return(0,l.jsx)(g.Modal,{title:null,open:e,onCancel:eS,maskClosable:!1,footer:null,width:1e3,closable:!1,className:"top-8",styles:{body:{padding:0}},children:(0,l.jsxs)("div",{className:"flex flex-col",children:[(0,l.jsxs)("div",{className:"flex items-center justify-between px-6 py-4 border-b border-gray-200",children:[(0,l.jsx)("h3",{className:"text-base font-semibold text-gray-900 m-0",children:"Create guardrail"}),(0,l.jsx)("button",{onClick:eS,className:"text-gray-400 hover:text-gray-600 bg-transparent border-none cursor-pointer text-base leading-none p-1",children:"✕"})]}),(0,l.jsx)("div",{className:"overflow-auto px-6 py-4",style:{maxHeight:"calc(80vh - 120px)"},children:(0,l.jsx)(u.Form,{form:o,layout:"vertical",initialValues:{mode:"pre_call",default_on:!1,skip_system_message_choice:"inherit",skip_tool_message_choice:"inherit"},children:eA.map((e,t)=>{let r=t{r&&k(t)},style:{minHeight:24},children:[(0,l.jsx)("span",{className:"text-sm",style:{fontWeight:i?600:500,color:i?"#1e293b":r?"#4f46e5":"#94a3b8"},children:e.title}),e.optional&&!i&&(0,l.jsx)("span",{className:"text-[11px] text-slate-400",children:"optional"}),r&&(0,l.jsx)("span",{className:"text-[11px] text-indigo-500 hover:underline",children:"Edit"})]}),i&&(0,l.jsx)("div",{className:"mt-3",children:(()=>{switch(S){case 0:return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(u.Form.Item,{name:"guardrail_name",label:"Guardrail Name",rules:[{required:!0,message:"Please enter a guardrail name"}],children:(0,l.jsx)(p.Input,{placeholder:"Enter a name for this guardrail"})}),(0,l.jsx)(u.Form.Item,{name:"provider",label:"Guardrail Provider",rules:[{required:!0,message:"Please select a provider"}],children:(0,l.jsx)(x.Select,{placeholder:"Select a guardrail provider",onChange:ey,labelInValue:!1,optionLabelProp:"label",dropdownRender:e=>e,showSearch:!0,children:Object.entries(ei()).map(([e,t])=>(0,l.jsx)(eX,{value:e,label:(0,l.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:[eu[t]&&(0,l.jsx)("img",{src:eu[t],alt:"",style:{height:"20px",width:"20px",marginRight:"8px",objectFit:"contain"},onError:e=>{e.currentTarget.style.display="none"}}),(0,l.jsx)("span",{children:t})]}),children:(0,l.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:[eu[t]&&(0,l.jsx)("img",{src:eu[t],alt:"",style:{height:"20px",width:"20px",marginRight:"8px",objectFit:"contain"},onError:e=>{e.currentTarget.style.display="none"}}),(0,l.jsx)("span",{children:t})]})},e))})}),(0,l.jsx)(u.Form.Item,{name:"mode",label:"Mode",tooltip:"How the guardrail should be applied",rules:[{required:!0,message:"Please select a mode"}],children:(0,l.jsx)(x.Select,{optionLabelProp:"label",mode:"multiple",children:_?.supported_modes?.map(e=>(0,l.jsx)(eX,{value:e,label:e,children:(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:e}),"pre_call"===e&&(0,l.jsx)(h.Tag,{color:"green",style:{marginLeft:"8px"},children:"Recommended"})]}),(0,l.jsx)("div",{style:{fontSize:"12px",color:"#888"},children:eZ[e]})]})},e))||(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(eX,{value:"pre_call",label:"pre_call",children:(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:"pre_call"})," ",(0,l.jsx)(h.Tag,{color:"green",children:"Recommended"})]}),(0,l.jsx)("div",{style:{fontSize:"12px",color:"#888"},children:eZ.pre_call})]})}),(0,l.jsx)(eX,{value:"during_call",label:"during_call",children:(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{children:(0,l.jsx)("strong",{children:"during_call"})}),(0,l.jsx)("div",{style:{fontSize:"12px",color:"#888"},children:eZ.during_call})]})}),(0,l.jsx)(eX,{value:"post_call",label:"post_call",children:(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{children:(0,l.jsx)("strong",{children:"post_call"})}),(0,l.jsx)("div",{style:{fontSize:"12px",color:"#888"},children:eZ.post_call})]})}),(0,l.jsx)(eX,{value:"logging_only",label:"logging_only",children:(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{children:(0,l.jsx)("strong",{children:"logging_only"})}),(0,l.jsx)("div",{style:{fontSize:"12px",color:"#888"},children:eZ.logging_only})]})})]})})}),(0,l.jsx)(u.Form.Item,{name:"default_on",label:"Always On",tooltip:"If enabled, this guardrail will be applied to all requests by default.",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:!0,children:"Yes"}),(0,l.jsx)(x.Select.Option,{value:!1,children:"No"})]})}),(0,l.jsx)(u.Form.Item,{name:"skip_system_message_choice",label:"Skip system messages in guardrail",tooltip:"Unified guardrails only: omit role: system from guardrail evaluation input (OpenAI chat + Anthropic messages). The model still receives full messages. Use global default follows litellm_settings.skip_system_message_in_guardrail.",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:"inherit",children:"Use global default"}),(0,l.jsx)(x.Select.Option,{value:"yes",children:"Yes — exclude from guardrail scan"}),(0,l.jsx)(x.Select.Option,{value:"no",children:"No — always include in scan"})]})}),(0,l.jsx)(u.Form.Item,{name:"skip_tool_message_choice",label:"Skip tool messages in guardrail",tooltip:"Unified guardrails only: omit role: tool from guardrail evaluation input (OpenAI chat + Anthropic messages). The model still receives full messages. Use global default follows litellm_settings.skip_tool_message_in_guardrail.",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:"inherit",children:"Use global default"}),(0,l.jsx)(x.Select.Option,{value:"yes",children:"Yes — exclude from guardrail scan"}),(0,l.jsx)(x.Select.Option,{value:"no",children:"No — always include in scan"})]})}),!ef&&!ed(f)&&!ec(f)&&(0,l.jsx)(ev,{selectedProvider:f,accessToken:a,providerParams:I})]});case 1:if(eo(f))return _&&"PresidioPII"===f?(0,l.jsx)(ez,{entities:_.supported_entities,actions:_.supported_actions,selectedEntities:v,selectedActions:N,onEntitySelect:e_,onActionSelect:eb,entityCategories:_.pii_entity_categories}):null;if(ed(f))return eI("categories");if(ec(f))return(0,l.jsx)(eC,{availableModels:ep,form:o});if(!f)return null;if(ef)return(0,l.jsx)(eW,{value:ex,onChange:eh});if(!I)return null;console.log("guardrail_provider_map: ",es),console.log("selectedProvider: ",f);let e=es[f]?.toLowerCase(),t=I&&I[e];return t&&t.optional_params?(0,l.jsx)(ej,{optionalParams:t.optional_params,parentFieldKey:"optional_params"}):null;case 2:if(ed(f))return eI("patterns");return null;case 3:if(ed(f))return eI("keywords");return null;case 4:return(0,l.jsxs)("div",{className:"space-y-6",children:[(0,l.jsx)("div",{children:(0,l.jsxs)("p",{className:"text-sm text-gray-500",children:["Configure settings for a specific call type. Most guardrails don't need this — skip it unless you're using a specific endpoint like ",(0,l.jsx)("code",{children:"/v1/realtime"}),"."]})}),(0,l.jsxs)("div",{children:[(0,l.jsx)("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Call type"}),(0,l.jsx)(x.Select,{placeholder:"Select a call type",value:W||void 0,onChange:e=>{V(e),em(!1)},style:{width:260},allowClear:!0,options:[{value:"realtime",label:"/v1/realtime"}]}),(0,l.jsx)("p",{className:"text-xs text-gray-400 mt-1",children:"More call types coming soon."})]}),"realtime"===W&&(0,l.jsxs)("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[(0,l.jsxs)("button",{type:"button",onClick:()=>em(e=>!e),className:"w-full flex items-center justify-between px-4 py-3 bg-gray-50 hover:bg-gray-100 text-sm font-medium text-gray-700",children:[(0,l.jsx)("span",{children:"/v1/realtime settings"}),(0,l.jsx)("svg",{className:`w-4 h-4 text-gray-500 transition-transform ${el?"rotate-180":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:(0,l.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"})})]}),el&&(0,l.jsxs)("div",{className:"space-y-5 px-4 py-4 border-t border-gray-200",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"End session after X violations"}),(0,l.jsx)("p",{className:"text-xs text-gray-400 mb-2",children:"Automatically close the session after this many guardrail violations. Leave empty to never auto-close."}),(0,l.jsx)("input",{type:"number",min:1,placeholder:"e.g. 3",value:Y??"",onChange:e=>Q(e.target.value?parseInt(e.target.value,10):void 0),className:"border border-gray-300 rounded px-3 py-1.5 text-sm w-32"})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:"On violation"}),(0,l.jsx)("div",{className:"space-y-2",children:["warn","end_session"].map(e=>(0,l.jsxs)("label",{className:"flex items-start gap-2 cursor-pointer",children:[(0,l.jsx)("input",{type:"radio",name:"on_violation",value:e,checked:X===e,onChange:()=>Z(e),className:"mt-0.5"}),(0,l.jsxs)("div",{children:[(0,l.jsx)("span",{className:"text-sm font-medium text-gray-800",children:"warn"===e?"Warn":"End session"}),(0,l.jsx)("p",{className:"text-xs text-gray-400 m-0",children:"warn"===e?"Bot speaks the message, session continues":"Bot speaks the message, connection closes immediately"})]})]},e))})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Message the user hears"}),(0,l.jsx)("p",{className:"text-xs text-gray-400 mb-2",children:"What the bot says aloud when this guardrail fires. Falls back to the default violation message if empty."}),(0,l.jsx)("textarea",{rows:3,placeholder:"e.g. I'm not able to continue this conversation. Please contact us at 1-800-774-2678.",value:ee,onChange:e=>ea(e.target.value),className:"border border-gray-300 rounded px-3 py-2 text-sm w-full resize-none"})]})]})]})]});default:return null}})()})]})]},t)})})}),(0,l.jsxs)("div",{className:"flex items-center justify-end space-x-3 px-6 py-3 border-t border-gray-200",children:[(0,l.jsx)(i.Button,{onClick:eS,children:"Cancel"}),S>0&&(0,l.jsx)(i.Button,{onClick:()=>{k(S-1)},children:"Previous"}),S{let[d]=u.Form.useForm(),[c,h]=(0,r.useState)(!1),[f,j]=(0,r.useState)(o?.provider||null),[_,b]=(0,r.useState)(null),[v,w]=(0,r.useState)([]),[N,C]=(0,r.useState)({});(0,r.useEffect)(()=>{(async()=>{try{if(!a)return;let e=await (0,m.getGuardrailUISettings)(a);b(e)}catch(e){console.error("Error fetching guardrail settings:",e),y.default.fromBackend("Failed to load guardrail settings")}})()},[a]),(0,r.useEffect)(()=>{o?.pii_entities_config&&Object.keys(o.pii_entities_config).length>0&&(w(Object.keys(o.pii_entities_config)),C(o.pii_entities_config))},[o]);let S=e=>{w(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},k=(e,t)=>{C(a=>({...a,[e]:t}))},I=async()=>{try{h(!0);let e=await d.validateFields(),l=es[e.provider],r=n&&"object"==typeof n?{...n}:{};r.guardrail=l,r.mode=e.mode,r.default_on=e.default_on;let o=e.skip_system_message_choice;"yes"===o?r.skip_system_message_in_guardrail=!0:"no"===o?r.skip_system_message_in_guardrail=!1:delete r.skip_system_message_in_guardrail;let c=e.skip_tool_message_choice;"yes"===c?r.skip_tool_message_in_guardrail=!0:"no"===c?r.skip_tool_message_in_guardrail=!1:delete r.skip_tool_message_in_guardrail;let u={};if("PresidioPII"===e.provider&&v.length>0){let e={};v.forEach(t=>{e[t]=N[t]||"MASK"}),r.pii_entities_config=e}else if(e.config)try{let t=JSON.parse(e.config);"Bedrock"===e.provider&&t?(t.guardrail_id&&(r.guardrailIdentifier=t.guardrail_id),t.guardrail_version&&(r.guardrailVersion=t.guardrail_version)):u=t}catch(e){y.default.fromBackend("Invalid JSON in configuration"),h(!1);return}let p={guardrail_id:s,guardrail:{guardrail_name:e.guardrail_name,litellm_params:r,guardrail_info:u}};if(!a)throw Error("No access token available");console.log("Sending guardrail update data:",JSON.stringify(p));let g=`/guardrails/${s}`,x=await fetch(g,{method:"PUT",headers:{[(0,m.getGlobalLitellmHeaderName)()]:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify(p)});if(!x.ok){let e=await x.text();throw Error(e||"Failed to update guardrail")}y.default.success("Guardrail updated successfully"),i(),t()}catch(e){console.error("Failed to update guardrail:",e),y.default.fromBackend("Failed to update guardrail: "+(e instanceof Error?e.message:String(e)))}finally{h(!1)}};return(0,l.jsx)(g.Modal,{title:"Edit Guardrail",open:e,onCancel:t,footer:null,width:700,children:(0,l.jsxs)(u.Form,{form:d,layout:"vertical",initialValues:o,children:[(0,l.jsx)(u.Form.Item,{name:"guardrail_name",label:"Guardrail Name",rules:[{required:!0,message:"Please enter a guardrail name"}],children:(0,l.jsx)(ts.TextInput,{placeholder:"Enter a name for this guardrail"})}),(0,l.jsx)(u.Form.Item,{name:"provider",label:"Guardrail Provider",rules:[{required:!0,message:"Please select a provider"}],children:(0,l.jsx)(x.Select,{placeholder:"Select a guardrail provider",onChange:e=>{j(e),d.setFieldsValue({config:void 0}),w([]),C({})},disabled:!0,optionLabelProp:"label",children:Object.entries(ei()).map(([e,t])=>(0,l.jsx)(td,{value:e,label:t,children:(0,l.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:[eu[t]&&(0,l.jsx)("img",{src:eu[t],alt:"",style:{height:"20px",width:"20px",marginRight:"8px",objectFit:"contain"},onError:e=>{e.currentTarget.style.display="none"}}),(0,l.jsx)("span",{children:t})]})},e))})}),(0,l.jsx)(u.Form.Item,{name:"mode",label:"Mode",tooltip:"How the guardrail should be applied",rules:[{required:!0,message:"Please select a mode"}],children:(0,l.jsx)(x.Select,{children:_?.supported_modes?.map(e=>(0,l.jsx)(td,{value:e,children:e},e))||(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(td,{value:"pre_call",children:"pre_call"}),(0,l.jsx)(td,{value:"post_call",children:"post_call"})]})})}),(0,l.jsx)(u.Form.Item,{name:"default_on",label:"Always On",tooltip:"If enabled, this guardrail will be applied to all requests by default",valuePropName:"checked",children:(0,l.jsx)(J.Switch,{})}),(0,l.jsx)(u.Form.Item,{name:"skip_system_message_choice",label:"Skip system messages in guardrail",tooltip:"Unified guardrails only: whether role: system content is omitted from guardrail input (LLM still receives full messages). Use global default follows litellm_settings.skip_system_message_in_guardrail.",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(td,{value:"inherit",children:"Use global default"}),(0,l.jsx)(td,{value:"yes",children:"Yes — exclude from guardrail scan"}),(0,l.jsx)(td,{value:"no",children:"No — always include in scan"})]})}),(0,l.jsx)(u.Form.Item,{name:"skip_tool_message_choice",label:"Skip tool messages in guardrail",tooltip:"Unified guardrails only: whether role: tool content is omitted from guardrail input (LLM still receives full messages). Use global default follows litellm_settings.skip_tool_message_in_guardrail.",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(td,{value:"inherit",children:"Use global default"}),(0,l.jsx)(td,{value:"yes",children:"Yes — exclude from guardrail scan"}),(0,l.jsx)(td,{value:"no",children:"No — always include in scan"})]})}),(()=>{if(!f)return null;if("PresidioPII"===f)return _&&f&&"PresidioPII"===f?(0,l.jsx)(ez,{entities:_.supported_entities,actions:_.supported_actions,selectedEntities:v,selectedActions:N,onEntitySelect:S,onActionSelect:k,entityCategories:_.pii_entity_categories}):null;switch(f){case"Aporia":return(0,l.jsx)(u.Form.Item,{label:"Aporia Configuration",name:"config",tooltip:"JSON configuration for Aporia",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "api_key": "your_aporia_api_key", + "project_name": "your_project_name" +}`})});case"AimSecurity":return(0,l.jsx)(u.Form.Item,{label:"Aim Security Configuration",name:"config",tooltip:"JSON configuration for Aim Security",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "api_key": "your_aim_api_key" +}`})});case"Bedrock":return(0,l.jsx)(u.Form.Item,{label:"Amazon Bedrock Configuration",name:"config",tooltip:"JSON configuration for Amazon Bedrock guardrails",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "guardrail_id": "your_guardrail_id", + "guardrail_version": "your_guardrail_version" +}`})});case"CatoNetworks":return(0,l.jsx)(u.Form.Item,{label:"Cato Networks Configuration",name:"config",tooltip:"JSON configuration for Cato Networks",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "api_key": "your_cato_api_key" +}`})});case"GuardrailsAI":return(0,l.jsx)(u.Form.Item,{label:"Guardrails.ai Configuration",name:"config",tooltip:"JSON configuration for Guardrails.ai",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "api_key": "your_guardrails_api_key", + "guardrail_id": "your_guardrail_id" +}`})});case"LakeraAI":return(0,l.jsx)(u.Form.Item,{label:"Lakera AI Configuration",name:"config",tooltip:"JSON configuration for Lakera AI",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "api_key": "your_lakera_api_key" +}`})});case"PromptInjection":return(0,l.jsx)(u.Form.Item,{label:"Prompt Injection Configuration",name:"config",tooltip:"JSON configuration for prompt injection detection",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "threshold": 0.8 +}`})});default:return(0,l.jsx)(u.Form.Item,{label:"Custom Configuration",name:"config",tooltip:"JSON configuration for your custom guardrail",children:(0,l.jsx)(p.Input.TextArea,{rows:4,placeholder:`{ + "key1": "value1", + "key2": "value2" +}`})})}})(),(0,l.jsxs)("div",{className:"flex justify-end space-x-2 mt-4",children:[(0,l.jsx)(e7.Button,{variant:"secondary",onClick:t,children:"Cancel"}),(0,l.jsx)(e7.Button,{onClick:I,loading:c,children:"Update Guardrail"})]})]})})};var tm=((a={}).DB="db",a.CONFIG="config",a);let tu=({guardrailsList:e,isLoading:t,onDeleteClick:a,accessToken:i,onGuardrailUpdated:s,isAdmin:n=!1,onGuardrailClick:o})=>{let[d,c]=(0,r.useState)([{id:"created_at",desc:!0}]),[m,u]=(0,r.useState)(!1),[p,g]=(0,r.useState)(null),x=e=>e?new Date(e).toLocaleString():"-",h=[{header:"Guardrail ID",accessorKey:"guardrail_id",cell:e=>(0,l.jsx)(ew.Tooltip,{title:String(e.getValue()||""),children:(0,l.jsx)(e7.Button,{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:()=>e.getValue()&&o(e.getValue()),children:e.getValue()?`${String(e.getValue()).slice(0,7)}...`:""})})},{header:"Name",accessorKey:"guardrail_name",cell:({row:e})=>{let t=e.original;return(0,l.jsx)(ew.Tooltip,{title:t.guardrail_name,children:(0,l.jsx)("span",{className:"text-xs font-medium",children:t.guardrail_name||"-"})})}},{header:"Provider",accessorKey:"litellm_params.guardrail",cell:({row:e})=>{let{logo:t,displayName:a}=ep(e.original.litellm_params.guardrail);return(0,l.jsxs)("div",{className:"flex items-center space-x-2",children:[t&&(0,l.jsx)("img",{src:t,alt:`${a} logo`,className:"w-4 h-4",onError:e=>{e.target.style.display="none"}}),(0,l.jsx)("span",{className:"text-xs",children:a})]})}},{header:"Mode",accessorKey:"litellm_params.mode",cell:({row:e})=>{let t=e.original;return(0,l.jsx)("span",{className:"text-xs",children:t.litellm_params.mode})}},{header:"Default On",accessorKey:"litellm_params.default_on",cell:({row:e})=>{let t=e.original;return(0,l.jsx)(tl.Badge,{color:t.litellm_params?.default_on?"green":"gray",className:"text-xs font-normal",size:"xs",children:t.litellm_params?.default_on?"Default On":"Default Off"})}},{header:"Created At",accessorKey:"created_at",cell:({row:e})=>{let t=e.original;return(0,l.jsx)(ew.Tooltip,{title:t.created_at,children:(0,l.jsx)("span",{className:"text-xs",children:x(t.created_at)})})}},{header:"Updated At",accessorKey:"updated_at",cell:({row:e})=>{let t=e.original;return(0,l.jsx)(ew.Tooltip,{title:t.updated_at,children:(0,l.jsx)("span",{className:"text-xs",children:x(t.updated_at)})})}},{id:"actions",header:"Actions",cell:({row:e})=>{let t=e.original,r=t.guardrail_definition_location===tm.CONFIG;return(0,l.jsx)("div",{className:"flex space-x-2",children:r?(0,l.jsx)(ew.Tooltip,{title:"Config guardrail cannot be deleted on the dashboard. Please delete it from the config file.",children:(0,l.jsx)(e3.Icon,{"data-testid":"config-delete-icon",icon:e9.TrashIcon,size:"sm",className:"cursor-not-allowed text-gray-400",title:"Config guardrail cannot be deleted on the dashboard. Please delete it from the config file.","aria-label":"Delete guardrail (config)"})}):(0,l.jsx)(ew.Tooltip,{title:"Delete guardrail",children:(0,l.jsx)(e3.Icon,{icon:e9.TrashIcon,size:"sm",onClick:()=>t.guardrail_id&&a(t.guardrail_id,t.guardrail_name||"Unnamed Guardrail"),className:"cursor-pointer hover:text-red-500"})})})}}],f=(0,tr.useReactTable)({data:e,columns:h,state:{sorting:d},onSortingChange:c,getCoreRowModel:(0,ti.getCoreRowModel)(),getSortedRowModel:(0,ti.getSortedRowModel)(),enableSorting:!0});return(0,l.jsxs)("div",{className:"rounded-lg custom-border relative",children:[(0,l.jsx)("div",{className:"overflow-x-auto",children:(0,l.jsxs)(e1.Table,{className:"[&_td]:py-0.5 [&_th]:py-1",children:[(0,l.jsx)(e5.TableHead,{children:f.getHeaderGroups().map(e=>(0,l.jsx)(e6.TableRow,{children:e.headers.map(e=>(0,l.jsx)(e8.TableHeaderCell,{className:`py-1 h-8 ${"actions"===e.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)]":""}`,onClick:e.column.getToggleSortingHandler(),children:(0,l.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,l.jsx)("div",{className:"flex items-center",children:e.isPlaceholder?null:(0,tr.flexRender)(e.column.columnDef.header,e.getContext())}),"actions"!==e.id&&(0,l.jsx)("div",{className:"w-4",children:e.column.getIsSorted()?({asc:(0,l.jsx)(tt.ChevronUpIcon,{className:"h-4 w-4 text-blue-500"}),desc:(0,l.jsx)(ta.ChevronDownIcon,{className:"h-4 w-4 text-blue-500"})})[e.column.getIsSorted()]:(0,l.jsx)(te.SwitchVerticalIcon,{className:"h-4 w-4 text-gray-400"})})]})},e.id))},e.id))}),(0,l.jsx)(e2.TableBody,{children:t?(0,l.jsx)(e6.TableRow,{children:(0,l.jsx)(e4.TableCell,{colSpan:h.length,className:"h-8 text-center",children:(0,l.jsx)("div",{className:"text-center text-gray-500",children:(0,l.jsx)("p",{children:"Loading..."})})})}):e.length>0?f.getRowModel().rows.map(e=>(0,l.jsx)(e6.TableRow,{className:"h-8",children:e.getVisibleCells().map(e=>(0,l.jsx)(e4.TableCell,{className:`py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap ${"actions"===e.column.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)]":""}`,children:(0,tr.flexRender)(e.column.columnDef.cell,e.getContext())},e.id))},e.id)):(0,l.jsx)(e6.TableRow,{children:(0,l.jsx)(e4.TableCell,{colSpan:h.length,className:"h-8 text-center",children:(0,l.jsx)("div",{className:"text-center text-gray-500",children:(0,l.jsx)("p",{children:"No guardrails found"})})})})})]})}),p&&(0,l.jsx)(tc,{visible:m,onClose:()=>u(!1),accessToken:i,onSuccess:()=>{u(!1),g(null),s()},guardrailId:p.guardrail_id||"",fullLitellmParams:p.litellm_params,initialValues:{guardrail_name:p.guardrail_name||"",provider:Object.keys(es).find(e=>es[e]===p?.litellm_params.guardrail)||"",mode:p.litellm_params.mode,default_on:p.litellm_params.default_on,pii_entities_config:p.litellm_params.pii_entities_config,skip_system_message_choice:eg(p.litellm_params?.skip_system_message_in_guardrail),skip_tool_message_choice:ex(p.litellm_params?.skip_tool_message_in_guardrail),...p.guardrail_info}})]})};var tp=e.i(708347),tg=e.i(500330),eI=eI,tx=e.i(530212),th=e.i(350967),tf=e.i(197647),ty=e.i(653824),tj=e.i(881073),t_=e.i(404206),tb=e.i(723731),tv=e.i(629569),tw=e.i(678784),tN=e.i(118366),tC=e.i(560445);let{Text:tS}=f.Typography,{Option:tk}=x.Select,tI=({categories:e,onActionChange:t,onSeverityChange:a,onRemove:r,readOnly:s=!1})=>{let n=[{title:"Category",dataIndex:"display_name",key:"display_name",render:(e,t)=>(0,l.jsxs)("div",{children:[(0,l.jsx)(tS,{strong:!0,children:e}),e!==t.category&&(0,l.jsx)("div",{children:(0,l.jsx)(tS,{type:"secondary",style:{fontSize:12},children:t.category})})]})},{title:"Severity Threshold",dataIndex:"severity_threshold",key:"severity_threshold",width:180,render:(e,t)=>s?(0,l.jsx)(h.Tag,{color:{high:"red",medium:"orange",low:"yellow"}[e],children:e.toUpperCase()}):(0,l.jsxs)(x.Select,{value:e,onChange:e=>a?.(t.id,e),style:{width:150},size:"small",children:[(0,l.jsx)(tk,{value:"high",children:"High"}),(0,l.jsx)(tk,{value:"medium",children:"Medium"}),(0,l.jsx)(tk,{value:"low",children:"Low"})]})},{title:"Action",dataIndex:"action",key:"action",width:150,render:(e,a)=>s?(0,l.jsx)(h.Tag,{color:"BLOCK"===e?"red":"blue",children:e}):(0,l.jsxs)(x.Select,{value:e,onChange:e=>t?.(a.id,e),style:{width:120},size:"small",children:[(0,l.jsx)(tk,{value:"BLOCK",children:"Block"}),(0,l.jsx)(tk,{value:"MASK",children:"Mask"})]})}];return(s||n.push({title:"",key:"actions",width:100,render:(e,t)=>(0,l.jsx)(i.Button,{type:"text",danger:!0,size:"small",icon:(0,l.jsx)(L.DeleteOutlined,{}),onClick:()=>r?.(t.id),children:"Delete"})}),0===e.length)?(0,l.jsx)("div",{style:{textAlign:"center",padding:"40px 0",color:"#999"},children:"No categories configured."}):(0,l.jsx)(T.Table,{dataSource:e,columns:n,rowKey:"id",pagination:!1,size:"small"})},tA=({patterns:e,blockedWords:t,categories:a=[],readOnly:r=!0,onPatternActionChange:i,onPatternRemove:s,onBlockedWordUpdate:n,onBlockedWordRemove:o,onCategoryActionChange:d,onCategorySeverityChange:c,onCategoryRemove:m})=>{if(0===e.length&&0===t.length&&0===a.length)return null;let u=()=>{};return(0,l.jsxs)(l.Fragment,{children:[a.length>0&&(0,l.jsxs)(eD.Card,{className:"mt-6",children:[(0,l.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,l.jsx)(eK.Text,{className:"text-lg font-semibold",children:"Content Categories"}),(0,l.jsxs)(tl.Badge,{color:"blue",children:[a.length," categories configured"]})]}),(0,l.jsx)(tI,{categories:a,onActionChange:r?void 0:d,onSeverityChange:r?void 0:c,onRemove:r?void 0:m,readOnly:r})]}),e.length>0&&(0,l.jsxs)(eD.Card,{className:"mt-6",children:[(0,l.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,l.jsx)(eK.Text,{className:"text-lg font-semibold",children:"Pattern Detection"}),(0,l.jsxs)(tl.Badge,{color:"blue",children:[e.length," patterns configured"]})]}),(0,l.jsx)($,{patterns:e,onActionChange:r?u:i||u,onRemove:r?u:s||u})]}),t.length>0&&(0,l.jsxs)(eD.Card,{className:"mt-6",children:[(0,l.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,l.jsx)(eK.Text,{className:"text-lg font-semibold",children:"Blocked Keywords"}),(0,l.jsxs)(tl.Badge,{color:"blue",children:[t.length," keywords configured"]})]}),(0,l.jsx)(R,{keywords:t,onActionChange:r?u:n||u,onRemove:r?u:o||u})]})]})},{Text:tO}=f.Typography,tP=({guardrailData:e,guardrailSettings:t,isEditing:a,accessToken:i,onDataChange:s,onUnsavedChanges:n})=>{let[o,d]=(0,r.useState)([]),[c,m]=(0,r.useState)([]),[u,p]=(0,r.useState)([]),[g,x]=(0,r.useState)([]),[h,f]=(0,r.useState)([]),[y,j]=(0,r.useState)([]),[_,b]=(0,r.useState)(!1),[v,w]=(0,r.useState)(null),[N,C]=(0,r.useState)(!1),[S,k]=(0,r.useState)(null);(0,r.useEffect)(()=>{if(e?.litellm_params?.patterns){let t=e.litellm_params.patterns.map((e,t)=>({id:`pattern-${t}`,type:"prebuilt"===e.pattern_type?"prebuilt":"custom",name:e.pattern_name||e.name,display_name:e.display_name,pattern:e.pattern,action:e.action||"BLOCK"}));d(t),x(t)}else d([]),x([]);if(e?.litellm_params?.blocked_words){let t=e.litellm_params.blocked_words.map((e,t)=>({id:`word-${t}`,keyword:e.keyword,action:e.action||"BLOCK",description:e.description}));m(t),f(t)}else m([]),f([]);if(e?.litellm_params?.categories?.length>0){let a=t?.content_filter_settings?.content_categories?Object.fromEntries(t.content_filter_settings.content_categories.map(e=>[e.name,e])):{},l=e.litellm_params.categories.map((e,t)=>{let l=a[e.category];return{id:`category-${t}`,category:e.category,display_name:l?.display_name??e.category,action:e.action||"BLOCK",severity_threshold:e.severity_threshold||"medium"}});p(l),j(l)}else p([]),j([]);let a=e?.litellm_params?.competitor_intent_config;if(a&&"object"==typeof a){let e=!!(a.brand_self&&Array.isArray(a.brand_self)&&a.brand_self.length>0),t={competitor_intent_type:a.competitor_intent_type??"airline",brand_self:Array.isArray(a.brand_self)?a.brand_self:[],locations:Array.isArray(a.locations)?a.locations:[],competitors:Array.isArray(a.competitors)?a.competitors:[],policy:a.policy??{competitor_comparison:"refuse",possible_competitor_comparison:"reframe"},threshold_high:"number"==typeof a.threshold_high?a.threshold_high:.7,threshold_medium:"number"==typeof a.threshold_medium?a.threshold_medium:.45,threshold_low:"number"==typeof a.threshold_low?a.threshold_low:.3};b(e),w(t),C(e),k(t)}else b(!1),w(null),C(!1),k(null)},[e,t?.content_filter_settings?.content_categories]),(0,r.useEffect)(()=>{s&&s(o,c,u,_,v)},[o,c,u,_,v,s]);let I=r.default.useMemo(()=>{let e=JSON.stringify(o)!==JSON.stringify(g),t=JSON.stringify(c)!==JSON.stringify(h),a=JSON.stringify(u)!==JSON.stringify(y),l=_!==N||JSON.stringify(v)!==JSON.stringify(S);return e||t||a||l},[o,c,u,_,v,g,h,y,N,S]);return((0,r.useEffect)(()=>{a&&n&&n(I)},[I,a,n]),e?.litellm_params?.guardrail!=="litellm_content_filter")?null:a?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(eq.Divider,{orientation:"left",children:"Content Filter Configuration"}),I&&(0,l.jsx)(tC.Alert,{type:"warning",showIcon:!0,className:"mb-4",message:(0,l.jsx)(tO,{children:'You have unsaved changes to patterns or keywords. Remember to click "Save Changes" at the bottom.'})}),(0,l.jsx)("div",{className:"mb-6",children:t&&t.content_filter_settings&&(0,l.jsx)(et,{prebuiltPatterns:t.content_filter_settings.prebuilt_patterns||[],categories:t.content_filter_settings.pattern_categories||[],selectedPatterns:o,blockedWords:c,onPatternAdd:e=>d([...o,e]),onPatternRemove:e=>d(o.filter(t=>t.id!==e)),onPatternActionChange:(e,t)=>d(o.map(a=>a.id===e?{...a,action:t}:a)),onBlockedWordAdd:e=>m([...c,e]),onBlockedWordRemove:e=>m(c.filter(t=>t.id!==e)),onBlockedWordUpdate:(e,t,a)=>m(c.map(l=>l.id===e?{...l,[t]:a}:l)),onFileUpload:e=>{console.log("File uploaded:",e)},accessToken:i,contentCategories:t.content_filter_settings.content_categories||[],selectedContentCategories:u,onContentCategoryAdd:e=>p([...u,e]),onContentCategoryRemove:e=>p(u.filter(t=>t.id!==e)),onContentCategoryUpdate:(e,t,a)=>p(u.map(l=>l.id===e?{...l,[t]:a}:l)),competitorIntentEnabled:_,competitorIntentConfig:v,onCompetitorIntentChange:(e,t)=>{b(e),w(t)}})})]}):(0,l.jsx)(tA,{patterns:o,blockedWords:c,categories:u,readOnly:!0})};var tT=e.i(788191),tL=e.i(245704),tB=e.i(518617);let tF={icon:{tag:"svg",attrs:{viewBox:"0 0 1024 1024",focusable:"false"},children:[{tag:"path",attrs:{d:"M715.8 493.5L335 165.1c-14.2-12.2-35-1.2-35 18.5v656.8c0 19.7 20.8 30.7 35 18.5l380.8-328.4c10.9-9.4 10.9-27.6 0-37z"}}]},name:"caret-right",theme:"outlined"};var t$=r.forwardRef(function(e,t){return r.createElement(eT.default,(0,eO.default)({},e,{ref:t,icon:tF}))}),tE=e.i(987432);let tM={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M892 772h-80v-80c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v80h-80c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h80v80c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-80h80c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zM373.5 498.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.8-1.7-203.2 89.2-203.2 200 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.8-1.1 6.4-4.8 5.9-8.8zM824 472c0-109.4-87.9-198.3-196.9-200C516.3 270.3 424 361.2 424 472c0 62.8 29 118.8 74.2 155.5a300.95 300.95 0 00-86.4 60.4C357 742.6 326 814.8 324 891.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.5C505.8 695.7 563 672 624 672c110.4 0 200-89.5 200-200zm-109.5 90.5C690.3 586.7 658.2 600 624 600s-66.3-13.3-90.5-37.5a127.26 127.26 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-.1 34.2-13.4 66.3-37.6 90.5z"}}]},name:"usergroup-add",theme:"outlined"};var tR=r.forwardRef(function(e,t){return r.createElement(eT.default,(0,eO.default)({},e,{ref:t,icon:tM}))}),tG=e.i(872934);let{Panel:tz}=G.Collapse,{TextArea:tD}=p.Input,tK={empty:{name:"Empty Template",code:`async def apply_guardrail(inputs, request_data, input_type): + # inputs: {texts, images, tools, tool_calls, structured_messages, model} + # request_data: {model, user_id, team_id, end_user_id, metadata} + # input_type: "request" or "response" + return allow()`},blockSSN:{name:"Block SSN",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()`},redactEmail:{name:"Redact Emails",code:`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)`},blockSQL:{name:"Block SQL Injection",code:`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()`},validateJSON:{name:"Validate JSON",code:`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()`},externalAPI:{name:"External API Check (async)",code:`async def apply_guardrail(inputs, request_data, input_type): + # Call an external moderation API (async for non-blocking) + for text in inputs["texts"]: + response = await http_post( + "https://api.example.com/moderate", + body={"text": text, "user_id": request_data["user_id"]}, + headers={"Authorization": "Bearer YOUR_API_KEY"}, + timeout=10 + ) + + if not response["success"]: + # API call failed, allow by default or block + return allow() + + if response["body"].get("flagged"): + return block(response["body"].get("reason", "Content flagged")) + + return allow()`}},tq={"Return Values":[{name:"allow()",desc:"Let request/response through"},{name:"block(reason)",desc:"Reject with message"},{name:"modify(texts=[], images=[], tool_calls=[])",desc:"Transform content"}],"HTTP Requests (async)":[{name:"await http_request(url, method, headers, body)",desc:"Make async HTTP request"},{name:"await http_get(url, headers)",desc:"Async GET request"},{name:"await http_post(url, body, headers)",desc:"Async POST request"}],"Regex Functions":[{name:"regex_match(text, pattern)",desc:"Returns True if pattern found"},{name:"regex_replace(text, pattern, replacement)",desc:"Replace all matches"},{name:"regex_find_all(text, pattern)",desc:"Return list of matches"}],"JSON Functions":[{name:"json_parse(text)",desc:"Parse JSON string, returns None on error"},{name:"json_stringify(obj)",desc:"Convert to JSON string"},{name:"json_schema_valid(obj, schema)",desc:"Validate against JSON schema"}],"URL Functions":[{name:"extract_urls(text)",desc:"Extract all URLs from text"},{name:"is_valid_url(url)",desc:"Check if URL is valid"},{name:"all_urls_valid(text)",desc:"Check all URLs in text are valid"}],"Code Detection":[{name:"detect_code(text)",desc:"Returns True if code detected"},{name:"detect_code_languages(text)",desc:"Returns list of detected languages"},{name:'contains_code_language(text, ["sql"])',desc:"Check for specific languages"}],"Text Utilities":[{name:"contains(text, substring)",desc:"Check if substring exists"},{name:"contains_any(text, [substr1, substr2])",desc:"Check if any substring exists"},{name:"word_count(text)",desc:"Count words"},{name:"char_count(text)",desc:"Count characters"},{name:"lower(text) / upper(text) / trim(text)",desc:"String transforms"}]},tH=[{value:"pre_call",label:"pre_call (Request)"},{value:"post_call",label:"post_call (Response)"},{value:"during_call",label:"during_call (Parallel)"},{value:"logging_only",label:"logging_only"},{value:"pre_mcp_call",label:"pre_mcp_call (Before MCP Tool Call)"},{value:"post_mcp_call",label:"post_mcp_call (After MCP Tool Call)"},{value:"during_mcp_call",label:"during_mcp_call (During MCP Tool Call)"}],tJ=({visible:e,onClose:t,onSuccess:a,accessToken:i,editData:s})=>{let n=!!s,[o,d]=(0,r.useState)(""),[u,p]=(0,r.useState)(["pre_call"]),[h,f]=(0,r.useState)(!1),[j,_]=(0,r.useState)("empty"),[b,v]=(0,r.useState)(tK.empty.code),[w,N]=(0,r.useState)(!1),[C,S]=(0,r.useState)(!1),[k,I]=(0,r.useState)(!1),A={texts:["Hello, my SSN is 123-45-6789"],images:[],tools:[{type:"function",function:{name:"get_weather",description:"Get the current weather in a location",parameters:{type:"object",properties:{location:{type:"string",description:"City name"}},required:["location"]}}}],tool_calls:[],structured_messages:[{role:"system",content:"You are a helpful assistant."},{role:"user",content:"Hello, my SSN is 123-45-6789"}],model:"gpt-4"},O={texts:["The weather in San Francisco is 72°F and sunny."],images:[],tools:[],tool_calls:[{id:"call_abc123",type:"function",function:{name:"get_weather",arguments:'{"location": "San Francisco"}'}}],structured_messages:[],model:"gpt-4"},P={texts:['Tool: read_wiki_structure\nArguments: {"repoName": "BerriAI/litellm"}'],images:[],tools:[{type:"function",function:{name:"read_wiki_structure",description:"Read the structure of a GitHub repository (MCP tool passed as OpenAI tool)",parameters:{type:"object",properties:{repoName:{type:"string",description:"Repository name, e.g. BerriAI/litellm"}},required:["repoName"]}}}],tool_calls:[{id:"call_mcp_001",type:"function",function:{name:"read_wiki_structure",arguments:'{"repoName": "BerriAI/litellm"}'}}],structured_messages:[{role:"user",content:'Tool: read_wiki_structure\nArguments: {"repoName": "BerriAI/litellm"}'}],model:"mcp-tool-call"},[T,L]=(0,r.useState)(JSON.stringify(A,null,2)),[B,F]=(0,r.useState)(null),[$,E]=(0,r.useState)(null),M=(0,r.useRef)(null),R=e=>null==e?["pre_call"]:Array.isArray(e)?e.length?e:["pre_call"]:[e];(0,r.useEffect)(()=>{e&&(s?(d(s.guardrail_name||""),p(R(s.litellm_params?.mode)),f(s.litellm_params?.default_on||!1),v(s.litellm_params?.custom_code||tK.empty.code),_("")):(d(""),p(["pre_call"]),f(!1),_("empty"),v(tK.empty.code)),F(null),I(!1))},[e,s]);let z=async e=>{try{await navigator.clipboard.writeText(e),E(e),setTimeout(()=>E(null),2e3)}catch(e){console.error("Failed to copy:",e)}},D=async()=>{if(!o.trim())return void y.default.fromBackend("Please enter a guardrail name");if(!b.trim())return void y.default.fromBackend("Please enter custom code");if(!i)return void y.default.fromBackend("No access token available");N(!0);try{if(n&&s){let e={litellm_params:{custom_code:b}};o!==s.guardrail_name&&(e.guardrail_name=o);let t=R(s.litellm_params?.mode);(u.length!==t.length||u.some((e,a)=>e!==t[a]))&&(e.litellm_params.mode=u),h!==s.litellm_params?.default_on&&(e.litellm_params.default_on=h),await (0,m.updateGuardrailCall)(i,s.guardrail_id,e),y.default.success("Custom code guardrail updated successfully")}else await (0,m.createGuardrailCall)(i,{guardrail_name:o,litellm_params:{guardrail:"custom_code",mode:u,default_on:h,custom_code:b},guardrail_info:{}}),y.default.success("Custom code guardrail created successfully");a(),t()}catch(e){console.error("Failed to save guardrail:",e),y.default.fromBackend(`Failed to ${n?"update":"create"} guardrail: `+(e instanceof Error?e.message:String(e)))}finally{N(!1)}},K=async()=>{if(!i)return void F({error:"No access token available"});S(!0),F(null);try{let e;try{e=JSON.parse(T)}catch(e){F({error:"Invalid test input JSON"}),S(!1);return}e.texts||(e.texts=[]);let t=["pre_call","pre_mcp_call"],a=["post_call","post_mcp_call"],l=u.some(e=>t.includes(e))?"request":u.some(e=>a.includes(e))?"response":"request",r=await (0,m.testCustomCodeGuardrail)(i,{custom_code:b,test_input:e,input_type:l,request_data:{model:"test-model",metadata:{}}});r.success&&r.result?F(r.result):r.error?F({error:r.error,error_type:r.error_type}):F({error:"Unknown error occurred"})}catch(e){console.error("Failed to test custom code:",e),F({error:e instanceof Error?e.message:"Failed to test custom code"})}finally{S(!1)}},q=b.split("\n").length;return(0,l.jsxs)(g.Modal,{open:e,onCancel:t,footer:null,width:1400,className:"custom-code-modal",closable:!0,destroyOnClose:!0,children:[(0,l.jsxs)("div",{className:"flex flex-col h-[80vh]",children:[(0,l.jsxs)("div",{className:"pb-4 border-b border-gray-200",children:[(0,l.jsx)("h2",{className:"text-xl font-semibold text-gray-900",children:n?"Edit Custom Guardrail":"Create Custom Guardrail"}),(0,l.jsx)("p",{className:"text-sm text-gray-500 mt-1",children:"Define custom logic using Python-like syntax"})]}),(0,l.jsxs)("div",{className:"flex items-center gap-4 py-4 border-b border-gray-100",children:[(0,l.jsxs)("div",{className:"flex-1 max-w-[200px]",children:[(0,l.jsx)("label",{className:"block text-xs font-medium text-gray-600 mb-1",children:"Guardrail Name"}),(0,l.jsx)(ts.TextInput,{value:o,onValueChange:d,placeholder:"e.g., block-pii-custom"})]}),(0,l.jsxs)("div",{className:"w-[280px]",children:[(0,l.jsx)("label",{className:"block text-xs font-medium text-gray-600 mb-1",children:"Mode (can select multiple)"}),(0,l.jsx)(x.Select,{mode:"multiple",value:u,onChange:p,options:tH,className:"w-full",size:"middle",placeholder:"Select modes"})]}),(0,l.jsxs)("div",{className:"w-[180px]",children:[(0,l.jsx)("label",{className:"block text-xs font-medium text-gray-600 mb-1",children:"Template"}),(0,l.jsx)(x.Select,{value:j,onChange:e=>{_(e),v(tK[e].code)},className:"w-full",size:"middle",dropdownRender:e=>(0,l.jsxs)(l.Fragment,{children:[e,(0,l.jsx)(eq.Divider,{style:{margin:"8px 0"}}),(0,l.jsxs)("div",{style:{padding:"8px 12px",cursor:"pointer",color:"#1890ff",fontSize:"12px",display:"flex",alignItems:"center",gap:"4px"},onClick:e=>{e.preventDefault(),window.open("https://models.litellm.ai/guardrails","_blank")},onMouseEnter:e=>{e.currentTarget.style.backgroundColor="#f0f0f0"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="transparent"},children:[(0,l.jsx)(tR,{}),(0,l.jsx)("span",{children:"Browse Community templates"}),(0,l.jsx)(tG.ExportOutlined,{style:{fontSize:"10px"}})]})]}),children:(0,l.jsx)(x.Select.OptGroup,{label:"STANDARD",children:Object.entries(tK).map(([e,t])=>(0,l.jsx)(x.Select.Option,{value:e,children:t.name},e))})})]}),(0,l.jsxs)("div",{className:"flex items-center gap-2 pt-5",children:[(0,l.jsx)("span",{className:"text-sm text-gray-600",children:"Default On"}),(0,l.jsx)(J.Switch,{checked:h,onChange:f})]})]}),(0,l.jsxs)("div",{className:"flex flex-1 overflow-hidden mt-4 gap-6",children:[(0,l.jsxs)("div",{className:"flex-[2] flex flex-col min-w-0 overflow-y-auto",children:[(0,l.jsxs)("div",{className:"flex items-center justify-between mb-2 flex-shrink-0",children:[(0,l.jsx)("span",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide",children:"Python Logic"}),(0,l.jsx)("span",{className:"text-xs text-gray-400",children:"Restricted environment (no imports)"})]}),(0,l.jsxs)("div",{className:"relative rounded-lg overflow-hidden border border-gray-700 bg-[#1e1e1e] flex-shrink-0",style:{minHeight:"300px",maxHeight:"400px"},children:[(0,l.jsx)("div",{className:"absolute left-0 top-0 bottom-0 w-12 bg-[#1e1e1e] border-r border-gray-700 text-right pr-3 pt-3 select-none overflow-hidden",style:{fontFamily:"'Fira Code', 'Monaco', 'Consolas', monospace",fontSize:"14px",lineHeight:"1.6"},children:Array.from({length:Math.max(q,20)},(e,t)=>(0,l.jsx)("div",{className:"text-gray-500 h-[22.4px]",children:t+1},t+1))}),(0,l.jsx)("textarea",{ref:M,value:b,onChange:e=>v(e.target.value),onKeyDown:e=>{if("Tab"===e.key){e.preventDefault();let t=e.currentTarget,a=t.selectionStart,l=t.selectionEnd;v(b.substring(0,a)+" "+b.substring(l)),setTimeout(()=>{t.selectionStart=t.selectionEnd=a+4},0)}},spellCheck:!1,className:"w-full h-full pl-14 pr-4 pt-3 pb-3 resize-none focus:outline-none bg-transparent text-gray-200",style:{fontFamily:"'Fira Code', 'Monaco', 'Consolas', monospace",fontSize:"14px",lineHeight:"1.6",tabSize:4}})]}),(0,l.jsx)(G.Collapse,{activeKey:k?["test"]:[],onChange:e=>I(e.includes("test")),className:"mt-3 bg-white border border-gray-200 rounded-lg flex-shrink-0",expandIcon:({isActive:e})=>(0,l.jsx)(t$,{rotate:90*!!e}),children:(0,l.jsx)(tz,{header:(0,l.jsxs)("span",{className:"flex items-center gap-2 text-sm font-medium",children:[(0,l.jsx)(tT.PlayCircleOutlined,{className:"text-blue-500"}),"Test Your Guardrail"]}),children:(0,l.jsxs)("div",{className:"space-y-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex items-center justify-between mb-2",children:[(0,l.jsx)("label",{className:"block text-xs font-medium text-gray-600",children:"Test Input (JSON)"}),(0,l.jsxs)("div",{className:"flex items-center gap-2",children:[(0,l.jsx)("span",{className:"text-xs text-gray-500",children:"Load example:"}),(0,l.jsx)("button",{type:"button",onClick:()=>L(JSON.stringify(A,null,2)),className:"px-2 py-1 text-xs rounded border border-orange-200 bg-orange-50 text-orange-700 hover:bg-orange-100 transition-colors",children:"Pre-call"}),(0,l.jsx)("button",{type:"button",onClick:()=>L(JSON.stringify(P,null,2)),className:"px-2 py-1 text-xs rounded border border-purple-200 bg-purple-50 text-purple-700 hover:bg-purple-100 transition-colors",children:"Pre MCP"}),(0,l.jsx)("button",{type:"button",onClick:()=>L(JSON.stringify(O,null,2)),className:"px-2 py-1 text-xs rounded border border-green-200 bg-green-50 text-green-700 hover:bg-green-100 transition-colors",children:"Post-call"})]})]}),(0,l.jsx)("div",{className:"mb-2 p-2 bg-gray-50 rounded text-xs text-gray-600 border border-gray-200",children:(0,l.jsxs)("div",{className:"grid grid-cols-2 gap-x-4 gap-y-1",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:"texts"}),": Message content (always)"]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:"images"}),": Base64 images (vision)"]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:"tools"}),": Tool definitions ",(0,l.jsx)("span",{className:"text-orange-600",children:"(pre_call)"}),", MCP as OpenAI tool ",(0,l.jsx)("span",{className:"text-purple-600",children:"(pre_mcp_call)"})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:"tool_calls"}),": LLM tool calls"," ",(0,l.jsx)("span",{className:"text-green-600",children:"(post_call)"})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:"structured_messages"}),": Full messages"," ",(0,l.jsx)("span",{className:"text-orange-600",children:"(pre_call)"})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:"model"}),": Model name (always)"]})]})}),(0,l.jsx)(tD,{value:T,onChange:e=>L(e.target.value),rows:8,className:"font-mono text-xs",placeholder:'{"texts": ["test message"], ...}'})]}),(0,l.jsxs)("div",{className:"flex items-center gap-3",children:[(0,l.jsx)(e7.Button,{size:"xs",onClick:K,disabled:C,icon:tT.PlayCircleOutlined,children:C?"Running...":"Run Test"}),B&&(0,l.jsx)("div",{className:`flex items-center gap-2 text-sm ${B.error?"text-red-600":"allow"===B.action?"text-green-600":"block"===B.action?"text-orange-600":"text-blue-600"}`,children:B.error?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(tB.CloseCircleOutlined,{}),(0,l.jsxs)("span",{children:[B.error_type&&(0,l.jsxs)("span",{className:"font-medium",children:["[",B.error_type,"] "]}),B.error]})]}):"allow"===B.action?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(tL.CheckCircleOutlined,{})," Allowed"]}):"block"===B.action?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(tB.CloseCircleOutlined,{})," Blocked: ",B.reason]}):"modify"===B.action?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(tL.CheckCircleOutlined,{})," Modified",B.texts&&B.texts.length>0&&(0,l.jsxs)("span",{className:"text-xs text-gray-500 ml-1",children:["→ ",B.texts[0].substring(0,50),B.texts[0].length>50?"...":""]})]}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(tL.CheckCircleOutlined,{})," ",B.action||"Unknown"]})})]})]})},"test")}),(0,l.jsxs)("div",{className:"mt-3 p-4 bg-gradient-to-r from-blue-50 to-indigo-50 border border-blue-200 rounded-lg flex items-center justify-between flex-shrink-0",children:[(0,l.jsxs)("div",{className:"flex items-center gap-3",children:[(0,l.jsx)("div",{className:"bg-blue-100 rounded-full p-2",children:(0,l.jsx)(tR,{className:"text-blue-600 text-lg"})}),(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"text-sm font-medium text-gray-900",children:"Built a useful guardrail?"}),(0,l.jsx)("div",{className:"text-xs text-gray-600",children:"Share it with the community and help others build faster"})]})]}),(0,l.jsx)(e7.Button,{size:"xs",onClick:()=>window.open("https://github.com/BerriAI/litellm-guardrails","_blank"),icon:tG.ExportOutlined,className:"bg-blue-600 hover:bg-blue-700 text-white border-0",children:"Contribute Template"})]})]}),(0,l.jsxs)("div",{className:"w-[300px] flex-shrink-0 overflow-auto border-l border-gray-200 pl-6",children:[(0,l.jsxs)("div",{className:"flex items-center gap-2 mb-3",children:[(0,l.jsx)(c.CodeOutlined,{className:"text-blue-500"}),(0,l.jsx)("span",{className:"font-semibold text-gray-700",children:"Available Primitives"})]}),(0,l.jsx)("p",{className:"text-xs text-gray-500 mb-3",children:"Click to copy functions to clipboard"}),(0,l.jsx)(G.Collapse,{defaultActiveKey:["Return Values"],className:"primitives-collapse bg-transparent border-0",expandIconPosition:"end",children:Object.entries(tq).map(([e,t])=>(0,l.jsx)(tz,{header:(0,l.jsx)("span",{className:"text-sm font-medium text-gray-700",children:e}),className:"bg-white mb-2 rounded-lg border border-gray-200",children:(0,l.jsx)("div",{className:"space-y-2",children:t.map(e=>(0,l.jsx)("button",{onClick:()=>z(e.name),className:`w-full text-left px-2 py-2 rounded transition-colors ${$===e.name?"bg-green-100":"bg-gray-50 hover:bg-blue-50"}`,children:$===e.name?(0,l.jsxs)("span",{className:"flex items-center gap-1 text-xs font-mono text-green-700",children:[(0,l.jsx)(tL.CheckCircleOutlined,{})," Copied!"]}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("div",{className:"text-xs font-mono text-gray-800",children:e.name}),(0,l.jsx)("div",{className:"text-[10px] text-gray-500 mt-0.5",children:e.desc})]})},e.name))})},e))})]})]}),(0,l.jsxs)("div",{className:"flex items-center justify-between pt-4 mt-4 border-t border-gray-200",children:[(0,l.jsx)("span",{className:"text-xs text-gray-400",children:"Changes are auto-saved to local draft"}),(0,l.jsxs)("div",{className:"flex items-center gap-3",children:[(0,l.jsx)(e7.Button,{variant:"secondary",onClick:t,children:"Cancel"}),(0,l.jsx)(e7.Button,{onClick:D,loading:w,disabled:w||!o.trim(),icon:tE.SaveOutlined,children:n?"Update Guardrail":"Save Guardrail"})]})]})]}),(0,l.jsx)("style",{children:` + .custom-code-modal .ant-modal-content { + padding: 24px; + } + .custom-code-modal .ant-modal-close { + top: 20px; + right: 20px; + } + .primitives-collapse .ant-collapse-item { + border: none !important; + } + .primitives-collapse .ant-collapse-header { + padding: 8px 12px !important; + } + .primitives-collapse .ant-collapse-content-box { + padding: 8px 12px !important; + } + `})]})},tU=({guardrailId:e,onClose:t,accessToken:a,isAdmin:s})=>{let n,[o,d]=(0,r.useState)(null),[g,h]=(0,r.useState)(null),[f,j]=(0,r.useState)(!0),[_,b]=(0,r.useState)(!1),[v]=u.Form.useForm(),[w,N]=(0,r.useState)([]),[C,S]=(0,r.useState)({}),[k,I]=(0,r.useState)(null),[A,O]=(0,r.useState)({}),[P,T]=(0,r.useState)(!1),L={rules:[],default_action:"deny",on_disallowed_action:"block",violation_message_template:""},[B,F]=(0,r.useState)(L),[$,E]=(0,r.useState)(!1),[M,R]=(0,r.useState)(!1),G=r.default.useRef({patterns:[],blockedWords:[],categories:[]}),z=(0,r.useCallback)((e,t,a,l,r)=>{G.current={patterns:e,blockedWords:t,categories:a||[],competitorIntentEnabled:l,competitorIntentConfig:r}},[]),D=async()=>{try{if(j(!0),!a)return;let t=await (0,m.getGuardrailInfo)(a,e);if(d(t),t.litellm_params?.pii_entities_config){let e=t.litellm_params.pii_entities_config;if(N([]),S({}),Object.keys(e).length>0){let t=[],a={};Object.entries(e).forEach(([e,l])=>{t.push(e),a[e]="string"==typeof l?l:"MASK"}),N(t),S(a)}}else N([]),S({})}catch(e){y.default.fromBackend("Failed to load guardrail information"),console.error("Error fetching guardrail info:",e)}finally{j(!1)}},K=async()=>{try{if(!a)return;let e=await (0,m.getGuardrailProviderSpecificParams)(a);h(e)}catch(e){console.error("Error fetching guardrail provider specific params:",e)}},q=async()=>{try{if(!a)return;let e=await (0,m.getGuardrailUISettings)(a);I(e)}catch(e){console.error("Error fetching guardrail UI settings:",e)}};(0,r.useEffect)(()=>{K()},[a]),(0,r.useEffect)(()=>{D(),q()},[e,a]),(0,r.useEffect)(()=>{if(o&&v){let e={...o.litellm_params||{}};delete e.skip_system_message_in_guardrail,delete e.skip_tool_message_in_guardrail,v.setFieldsValue({guardrail_name:o.guardrail_name,...e,skip_system_message_choice:eg(o.litellm_params?.skip_system_message_in_guardrail),skip_tool_message_choice:ex(o.litellm_params?.skip_tool_message_in_guardrail),guardrail_info:o.guardrail_info?JSON.stringify(o.guardrail_info,null,2):"",...o.litellm_params?.optional_params&&{optional_params:o.litellm_params.optional_params}})}},[o,g,v]);let H=(0,r.useCallback)(()=>{o?.litellm_params?.guardrail==="tool_permission"?F({rules:o.litellm_params?.rules||[],default_action:(o.litellm_params?.default_action||"deny").toLowerCase(),on_disallowed_action:(o.litellm_params?.on_disallowed_action||"block").toLowerCase(),violation_message_template:o.litellm_params?.violation_message_template||""}):F(L),E(!1)},[o]);(0,r.useEffect)(()=>{H()},[H]);let J=async t=>{try{if(!a)return;let d={litellm_params:{}};t.guardrail_name!==o.guardrail_name&&(d.guardrail_name=t.guardrail_name),t.default_on!==o.litellm_params?.default_on&&(d.litellm_params.default_on=t.default_on);let c=eg(o.litellm_params?.skip_system_message_in_guardrail),u=t.skip_system_message_choice;void 0!==u&&u!==c&&("inherit"===u?d.litellm_params.skip_system_message_in_guardrail=null:"yes"===u?d.litellm_params.skip_system_message_in_guardrail=!0:d.litellm_params.skip_system_message_in_guardrail=!1);let p=ex(o.litellm_params?.skip_tool_message_in_guardrail),x=t.skip_tool_message_choice;void 0!==x&&x!==p&&("inherit"===x?d.litellm_params.skip_tool_message_in_guardrail=null:"yes"===x?d.litellm_params.skip_tool_message_in_guardrail=!0:d.litellm_params.skip_tool_message_in_guardrail=!1);let h=o.guardrail_info,f=t.guardrail_info?JSON.parse(t.guardrail_info):void 0;JSON.stringify(h)!==JSON.stringify(f)&&(d.guardrail_info=f);let j=o.litellm_params?.pii_entities_config||{},_={};if(w.forEach(e=>{_[e]=C[e]||"MASK"}),JSON.stringify(j)!==JSON.stringify(_)&&(d.litellm_params.pii_entities_config=_),o.litellm_params?.guardrail==="litellm_content_filter"&&P){var l,r,i,s,n;let e,t=(l=G.current.patterns||[],r=G.current.blockedWords||[],i=G.current.categories||[],s=G.current.competitorIntentEnabled,n=G.current.competitorIntentConfig,e={patterns:l.map(e=>({pattern_type:"prebuilt"===e.type?"prebuilt":"regex",pattern_name:"prebuilt"===e.type?e.name:void 0,pattern:"custom"===e.type?e.pattern:void 0,name:e.name,action:e.action})),blocked_words:r.map(e=>({keyword:e.keyword,action:e.action,description:e.description}))},void 0!==i&&(e.categories=i.map(e=>({category:e.category,enabled:!0,action:e.action,severity_threshold:e.severity_threshold||"medium"}))),s&&n&&n.brand_self.length>0&&(e.competitor_intent_config={competitor_intent_type:n.competitor_intent_type,brand_self:n.brand_self,locations:n.locations?.length?n.locations:void 0,competitors:"generic"===n.competitor_intent_type&&n.competitors?.length?n.competitors:void 0,policy:n.policy,threshold_high:n.threshold_high,threshold_medium:n.threshold_medium,threshold_low:n.threshold_low}),e);d.litellm_params.patterns=t.patterns,d.litellm_params.blocked_words=t.blocked_words,d.litellm_params.categories=t.categories,d.litellm_params.competitor_intent_config=t.competitor_intent_config??null}if(o.litellm_params?.guardrail==="tool_permission"){let e=o.litellm_params?.rules||[],t=B.rules||[],a=JSON.stringify(e)!==JSON.stringify(t),l=(o.litellm_params?.default_action||"deny").toLowerCase(),r=(B.default_action||"deny").toLowerCase(),i=l!==r,s=(o.litellm_params?.on_disallowed_action||"block").toLowerCase(),n=(B.on_disallowed_action||"block").toLowerCase(),c=s!==n,m=o.litellm_params?.violation_message_template||"",u=B.violation_message_template||"",p=m!==u;($||a||i||c||p)&&(d.litellm_params.rules=t,d.litellm_params.default_action=r,d.litellm_params.on_disallowed_action=n,d.litellm_params.violation_message_template=u||null)}let v=Object.keys(es).find(e=>es[e]===o.litellm_params?.guardrail);console.log("values: ",JSON.stringify(t)),console.log("currentProvider: ",v);let N=o.litellm_params?.guardrail==="tool_permission";if(g&&v&&!N){let e=g[es[v]?.toLowerCase()]||{},a=new Set;console.log("providerSpecificParams: ",JSON.stringify(e)),Object.keys(e).forEach(e=>{"optional_params"!==e&&a.add(e)}),e.optional_params&&e.optional_params.fields&&Object.keys(e.optional_params.fields).forEach(e=>{a.add(e)}),console.log("allowedParams: ",a),a.forEach(e=>{if("patterns"===e||"blocked_words"===e||"categories"===e)return;let a=t[e];(null==a||""===a)&&(a=t.optional_params?.[e]);let l=o.litellm_params?.[e];JSON.stringify(a)!==JSON.stringify(l)&&(null!=a&&""!==a?d.litellm_params[e]=a:null!=l&&""!==l&&(d.litellm_params[e]=null))})}if(0===Object.keys(d.litellm_params).length&&delete d.litellm_params,0===Object.keys(d).length){y.default.info("No changes detected"),b(!1);return}await (0,m.updateGuardrailCall)(a,e,d),y.default.success("Guardrail updated successfully"),T(!1),D(),b(!1)}catch(e){console.error("Error updating guardrail:",e),y.default.fromBackend("Failed to update guardrail")}};if(f)return(0,l.jsx)("div",{className:"p-4",children:"Loading..."});if(!o)return(0,l.jsx)("div",{className:"p-4",children:"Guardrail not found"});let U=e=>e?new Date(e).toLocaleString():"-",{logo:W,displayName:V}=ep(o.litellm_params?.guardrail||""),Y=async(e,t)=>{await (0,tg.copyToClipboard)(e)&&(O(e=>({...e,[t]:!0})),setTimeout(()=>{O(e=>({...e,[t]:!1}))},2e3))},Q="config"===o.guardrail_definition_location;return(0,l.jsxs)("div",{className:"p-4",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(i.Button,{type:"text",icon:(0,l.jsx)(tx.ArrowLeftIcon,{className:"w-4 h-4"}),onClick:t,className:"mb-4",children:"Back to Guardrails"}),(0,l.jsx)(tv.Title,{children:o.guardrail_name||"Unnamed Guardrail"}),(0,l.jsxs)("div",{className:"flex items-center cursor-pointer",children:[(0,l.jsx)(eK.Text,{className:"text-gray-500 font-mono",children:o.guardrail_id}),(0,l.jsx)(i.Button,{type:"text",size:"small",icon:A["guardrail-id"]?(0,l.jsx)(tw.CheckIcon,{size:12}):(0,l.jsx)(tN.CopyIcon,{size:12}),onClick:()=>Y(o.guardrail_id,"guardrail-id"),className:`left-2 z-10 transition-all duration-200 ${A["guardrail-id"]?"text-green-600 bg-green-50 border-green-200":"text-gray-500 hover:text-gray-700 hover:bg-gray-100"}`})]})]}),(0,l.jsxs)(ty.TabGroup,{children:[(0,l.jsxs)(tj.TabList,{className:"mb-4",children:[(0,l.jsx)(tf.Tab,{children:"Overview"},"overview"),s?(0,l.jsx)(tf.Tab,{children:"Settings"},"settings"):(0,l.jsx)(l.Fragment,{})]}),(0,l.jsxs)(tb.TabPanels,{children:[(0,l.jsxs)(t_.TabPanel,{children:[(0,l.jsxs)(th.Grid,{numItems:1,numItemsSm:2,numItemsLg:3,className:"gap-6",children:[(0,l.jsxs)(eD.Card,{children:[(0,l.jsx)(eK.Text,{children:"Provider"}),(0,l.jsxs)("div",{className:"mt-2 flex items-center space-x-2",children:[W&&(0,l.jsx)("img",{src:W,alt:`${V} logo`,className:"w-6 h-6",onError:e=>{e.target.style.display="none"}}),(0,l.jsx)(tv.Title,{children:V})]})]}),(0,l.jsxs)(eD.Card,{children:[(0,l.jsx)(eK.Text,{children:"Mode"}),(0,l.jsxs)("div",{className:"mt-2",children:[(0,l.jsx)(tv.Title,{children:o.litellm_params?.mode||"-"}),(0,l.jsx)(tl.Badge,{color:o.litellm_params?.default_on?"green":"gray",children:o.litellm_params?.default_on?"Default On":"Default Off"})]})]}),(0,l.jsxs)(eD.Card,{children:[(0,l.jsx)(eK.Text,{children:"Created At"}),(0,l.jsxs)("div",{className:"mt-2",children:[(0,l.jsx)(tv.Title,{children:U(o.created_at)}),(0,l.jsxs)(eK.Text,{children:["Last Updated: ",U(o.updated_at)]})]})]})]}),o.litellm_params?.pii_entities_config&&Object.keys(o.litellm_params.pii_entities_config).length>0&&(0,l.jsx)(eD.Card,{className:"mt-6",children:(0,l.jsxs)("div",{className:"flex justify-between items-center",children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"PII Protection"}),(0,l.jsxs)(tl.Badge,{color:"blue",children:[Object.keys(o.litellm_params.pii_entities_config).length," PII entities configured"]})]})}),o.litellm_params?.pii_entities_config&&Object.keys(o.litellm_params.pii_entities_config).length>0&&(0,l.jsxs)(eD.Card,{className:"mt-6",children:[(0,l.jsx)(eK.Text,{className:"mb-4 text-lg font-semibold",children:"PII Entity Configuration"}),(0,l.jsxs)("div",{className:"border rounded-lg overflow-hidden shadow-sm",children:[(0,l.jsxs)("div",{className:"bg-gray-50 px-5 py-3 border-b flex",children:[(0,l.jsx)(eK.Text,{className:"flex-1 font-semibold text-gray-700",children:"Entity Type"}),(0,l.jsx)(eK.Text,{className:"flex-1 font-semibold text-gray-700",children:"Configuration"})]}),(0,l.jsx)("div",{className:"max-h-[400px] overflow-y-auto",children:Object.entries(o.litellm_params?.pii_entities_config).map(([e,t])=>(0,l.jsxs)("div",{className:"px-5 py-3 flex border-b hover:bg-gray-50 transition-colors",children:[(0,l.jsx)(eK.Text,{className:"flex-1 font-medium text-gray-900",children:e}),(0,l.jsx)(eK.Text,{className:"flex-1",children:(0,l.jsxs)("span",{className:`inline-flex items-center gap-1.5 ${"MASK"===t?"text-blue-600":"text-red-600"}`,children:["MASK"===t?(0,l.jsx)(eI.default,{}):(0,l.jsx)(eA.StopOutlined,{}),String(t)]})})]},e))})]})]}),o.litellm_params?.guardrail==="tool_permission"&&(0,l.jsx)(eD.Card,{className:"mt-6",children:(0,l.jsx)(eW,{value:B,disabled:!0})}),o.litellm_params?.guardrail==="custom_code"&&o.litellm_params?.custom_code&&(0,l.jsxs)(eD.Card,{className:"mt-6",children:[(0,l.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,l.jsxs)("div",{className:"flex items-center gap-2",children:[(0,l.jsx)(c.CodeOutlined,{className:"text-blue-500"}),(0,l.jsx)(eK.Text,{className:"font-medium text-lg",children:"Custom Code"})]}),s&&!Q&&(0,l.jsx)(i.Button,{size:"small",icon:(0,l.jsx)(c.CodeOutlined,{}),onClick:()=>R(!0),children:"Edit Code"})]}),(0,l.jsx)("div",{className:"relative rounded-lg overflow-hidden border border-gray-700 bg-[#1e1e1e]",children:(0,l.jsx)("pre",{className:"p-4 text-sm text-gray-200 overflow-x-auto",style:{fontFamily:"'Fira Code', 'Monaco', 'Consolas', monospace"},children:(0,l.jsx)("code",{children:o.litellm_params.custom_code})})})]}),(0,l.jsx)(tP,{guardrailData:o,guardrailSettings:k,isEditing:!1,accessToken:a})]}),s&&(0,l.jsx)(t_.TabPanel,{children:(0,l.jsxs)(eD.Card,{children:[(0,l.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,l.jsx)(tv.Title,{children:"Guardrail Settings"}),Q&&(0,l.jsx)(ew.Tooltip,{title:"Guardrail is defined in the config file and cannot be edited.",children:(0,l.jsx)(eJ.InfoCircleOutlined,{})}),!_&&!Q&&(o.litellm_params?.guardrail==="custom_code"?(0,l.jsx)(i.Button,{icon:(0,l.jsx)(c.CodeOutlined,{}),onClick:()=>R(!0),children:"Edit Code"}):(0,l.jsx)(i.Button,{onClick:()=>b(!0),children:"Edit Settings"}))]}),_?(0,l.jsxs)(u.Form,{form:v,onFinish:J,initialValues:{guardrail_name:o.guardrail_name,...(n={...o.litellm_params||{}},delete n.skip_system_message_in_guardrail,delete n.skip_tool_message_in_guardrail,n),skip_system_message_choice:eg(o.litellm_params?.skip_system_message_in_guardrail),skip_tool_message_choice:ex(o.litellm_params?.skip_tool_message_in_guardrail),guardrail_info:o.guardrail_info?JSON.stringify(o.guardrail_info,null,2):"",...o.litellm_params?.optional_params&&{optional_params:o.litellm_params.optional_params}},layout:"vertical",children:[(0,l.jsx)(u.Form.Item,{label:"Guardrail Name",name:"guardrail_name",rules:[{required:!0,message:"Please input a guardrail name"}],children:(0,l.jsx)(p.Input,{placeholder:"Enter guardrail name"})}),(0,l.jsx)(u.Form.Item,{label:"Default On",name:"default_on",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:!0,children:"Yes"}),(0,l.jsx)(x.Select.Option,{value:!1,children:"No"})]})}),(0,l.jsx)(u.Form.Item,{label:"Skip system messages in guardrail",name:"skip_system_message_choice",tooltip:"Unified guardrails: omit role: system from guardrail input (LLM still gets full messages). Use global default follows litellm_settings.skip_system_message_in_guardrail.",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:"inherit",children:"Use global default"}),(0,l.jsx)(x.Select.Option,{value:"yes",children:"Yes — exclude from guardrail scan"}),(0,l.jsx)(x.Select.Option,{value:"no",children:"No — always include in scan"})]})}),(0,l.jsx)(u.Form.Item,{label:"Skip tool messages in guardrail",name:"skip_tool_message_choice",tooltip:"Unified guardrails: omit role: tool from guardrail input (LLM still gets full messages). Use global default follows litellm_settings.skip_tool_message_in_guardrail.",children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:"inherit",children:"Use global default"}),(0,l.jsx)(x.Select.Option,{value:"yes",children:"Yes — exclude from guardrail scan"}),(0,l.jsx)(x.Select.Option,{value:"no",children:"No — always include in scan"})]})}),o.litellm_params?.guardrail==="presidio"&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(eq.Divider,{orientation:"left",children:"PII Protection"}),(0,l.jsx)("div",{className:"mb-6",children:k&&(0,l.jsx)(ez,{entities:k.supported_entities,actions:k.supported_actions,selectedEntities:w,selectedActions:C,onEntitySelect:e=>{N(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},onActionSelect:(e,t)=>{S(a=>({...a,[e]:t}))},entityCategories:k.pii_entity_categories})})]}),(0,l.jsx)(tP,{guardrailData:o,guardrailSettings:k,isEditing:!0,accessToken:a,onDataChange:z,onUnsavedChanges:T}),(o.litellm_params?.guardrail==="tool_permission"||g)&&(0,l.jsx)(eq.Divider,{orientation:"left",children:"Provider Settings"}),o.litellm_params?.guardrail==="tool_permission"?(0,l.jsx)(eW,{value:B,onChange:F}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(ev,{selectedProvider:Object.keys(es).find(e=>es[e]===o.litellm_params?.guardrail)||null,accessToken:a,providerParams:g,value:o.litellm_params}),g&&(()=>{let e=Object.keys(es).find(e=>es[e]===o.litellm_params?.guardrail);if(!e)return null;let t=g[es[e]?.toLowerCase()];return t&&t.optional_params?(0,l.jsx)(ej,{optionalParams:t.optional_params,parentFieldKey:"optional_params",values:o.litellm_params}):null})()]}),(0,l.jsx)(eq.Divider,{orientation:"left",children:"Advanced Settings"}),(0,l.jsx)(u.Form.Item,{label:"Guardrail Information",name:"guardrail_info",children:(0,l.jsx)(p.Input.TextArea,{rows:5})}),(0,l.jsxs)("div",{className:"flex justify-end gap-2 mt-6",children:[(0,l.jsx)(i.Button,{onClick:()=>{b(!1),T(!1),H()},children:"Cancel"}),(0,l.jsx)(i.Button,{type:"primary",htmlType:"submit",children:"Save Changes"})]})]}):(0,l.jsxs)("div",{className:"space-y-4",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"Guardrail ID"}),(0,l.jsx)("div",{className:"font-mono",children:o.guardrail_id})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"Guardrail Name"}),(0,l.jsx)("div",{children:o.guardrail_name||"Unnamed Guardrail"})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"Provider"}),(0,l.jsx)("div",{children:V})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"Mode"}),(0,l.jsx)("div",{children:o.litellm_params?.mode||"-"})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"Default On"}),(0,l.jsx)(tl.Badge,{color:o.litellm_params?.default_on?"green":"gray",children:o.litellm_params?.default_on?"Yes":"No"})]}),o.litellm_params?.pii_entities_config&&Object.keys(o.litellm_params.pii_entities_config).length>0&&(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"PII Protection"}),(0,l.jsx)("div",{className:"mt-2",children:(0,l.jsxs)(tl.Badge,{color:"blue",children:[Object.keys(o.litellm_params.pii_entities_config).length," PII entities configured"]})})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"Created At"}),(0,l.jsx)("div",{children:U(o.created_at)})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)(eK.Text,{className:"font-medium",children:"Last Updated"}),(0,l.jsx)("div",{children:U(o.updated_at)})]}),o.litellm_params?.guardrail==="tool_permission"&&(0,l.jsx)(eW,{value:B,disabled:!0})]})]})})]})]}),(0,l.jsx)(tJ,{visible:M,onClose:()=>R(!1),onSuccess:()=>{R(!1),D()},accessToken:a,editData:o?{guardrail_id:o.guardrail_id,guardrail_name:o.guardrail_name,litellm_params:o.litellm_params}:null})]})};var tW=e.i(573421),tV=e.i(19732),tY=e.i(928685),tQ=e.i(166406),tX=e.i(637235),tZ=e.i(240647);let{Text:t0}=f.Typography,t1=function({results:e,errors:t}){let[a,i]=(0,r.useState)(new Set),s=e=>{let t=new Set(a);t.has(e)?t.delete(e):t.add(e),i(t)},n=async e=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0;{let t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.focus(),t.select();let a=document.execCommand("copy");if(document.body.removeChild(t),!a)throw Error("execCommand failed");return!0}}catch(e){return console.error("Copy failed:",e),!1}};return e||t?(0,l.jsxs)("div",{className:"space-y-3 pt-4 border-t border-gray-200",children:[(0,l.jsx)("h3",{className:"text-sm font-semibold text-gray-900",children:"Results"}),e&&e.map(e=>{let t=a.has(e.guardrailName);return(0,l.jsx)(eD.Card,{className:"bg-green-50 border-green-200",children:(0,l.jsxs)("div",{className:"space-y-3",children:[(0,l.jsxs)("div",{className:"flex items-center justify-between",children:[(0,l.jsxs)("div",{className:"flex items-center space-x-2 cursor-pointer flex-1",onClick:()=>s(e.guardrailName),children:[t?(0,l.jsx)(tZ.RightOutlined,{className:"text-gray-500 text-xs"}):(0,l.jsx)(o.DownOutlined,{className:"text-gray-500 text-xs"}),(0,l.jsx)(tL.CheckCircleOutlined,{className:"text-green-600 text-lg"}),(0,l.jsx)("span",{className:"text-sm font-medium text-green-800",children:e.guardrailName})]}),(0,l.jsxs)("div",{className:"flex items-center gap-3",children:[(0,l.jsxs)("div",{className:"flex items-center space-x-1 text-xs text-gray-600",children:[(0,l.jsx)(tX.ClockCircleOutlined,{}),(0,l.jsxs)("span",{className:"font-medium",children:[e.latency,"ms"]})]}),!t&&(0,l.jsx)(e7.Button,{size:"xs",variant:"secondary",icon:tQ.CopyOutlined,onClick:async()=>{await n(e.response_text)?y.default.success("Result copied to clipboard"):y.default.fromBackend("Failed to copy result")},children:"Copy"})]})]}),!t&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)("div",{className:"bg-white border border-green-200 rounded p-3",children:[(0,l.jsx)("label",{className:"text-xs font-medium text-gray-600 mb-2 block",children:"Output Text"}),(0,l.jsx)("div",{className:"font-mono text-sm text-gray-900 whitespace-pre-wrap break-words",children:e.response_text})]}),(0,l.jsxs)("div",{className:"text-xs text-gray-600",children:[(0,l.jsx)("span",{className:"font-medium",children:"Characters:"})," ",e.response_text.length]})]})]})},e.guardrailName)}),t&&t.map(e=>{let t=a.has(e.guardrailName);return(0,l.jsx)(eD.Card,{className:"bg-red-50 border-red-200",children:(0,l.jsxs)("div",{className:"flex items-start space-x-2",children:[(0,l.jsx)("div",{className:"cursor-pointer mt-0.5",onClick:()=>s(e.guardrailName),children:t?(0,l.jsx)(tZ.RightOutlined,{className:"text-gray-500 text-xs"}):(0,l.jsx)(o.DownOutlined,{className:"text-gray-500 text-xs"})}),(0,l.jsx)("div",{className:"text-red-600 mt-0.5",children:(0,l.jsx)("svg",{className:"w-5 h-5",fill:"currentColor",viewBox:"0 0 20 20",children:(0,l.jsx)("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z",clipRule:"evenodd"})})}),(0,l.jsxs)("div",{className:"flex-1",children:[(0,l.jsxs)("div",{className:"flex items-center justify-between mb-1",children:[(0,l.jsxs)("p",{className:"text-sm font-medium text-red-800 cursor-pointer",onClick:()=>s(e.guardrailName),children:[e.guardrailName," - Error"]}),(0,l.jsxs)("div",{className:"flex items-center space-x-1 text-xs text-gray-600",children:[(0,l.jsx)(tX.ClockCircleOutlined,{}),(0,l.jsxs)("span",{className:"font-medium",children:[e.latency,"ms"]})]})]}),!t&&(0,l.jsx)("p",{className:"text-sm text-red-700 mt-1",children:e.error.message})]})]})},e.guardrailName)})]}):null},{TextArea:t2}=p.Input,{Text:t4}=f.Typography,t5=function({guardrailNames:e,onSubmit:t,isLoading:a,results:i,errors:s,onClose:n}){let[o,d]=(0,r.useState)(""),c=()=>{o.trim()?t(o):y.default.fromBackend("Please enter text to test")},m=async e=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0;{let t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.focus(),t.select();let a=document.execCommand("copy");if(document.body.removeChild(t),!a)throw Error("execCommand failed");return!0}}catch(e){return console.error("Copy failed:",e),!1}},u=async()=>{await m(o)?y.default.success("Input copied to clipboard"):y.default.fromBackend("Failed to copy input")};return(0,l.jsxs)("div",{className:"space-y-4 h-full flex flex-col",children:[(0,l.jsx)("div",{className:"flex items-center justify-between pb-3 border-b border-gray-200",children:(0,l.jsx)("div",{className:"flex items-center space-x-3",children:(0,l.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,l.jsxs)("div",{className:"flex items-center space-x-2 mb-1",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-gray-900",children:"Test Guardrails:"}),(0,l.jsx)("div",{className:"flex flex-wrap gap-2",children:e.map(e=>(0,l.jsx)("div",{className:"inline-flex items-center space-x-1 bg-blue-50 px-3 py-1 rounded-md border border-blue-200",children:(0,l.jsx)("span",{className:"font-mono text-blue-700 font-medium text-sm",children:e})},e))})]}),(0,l.jsxs)("p",{className:"text-sm text-gray-500",children:["Test ",e.length>1?"guardrails":"guardrail"," and compare results"]})]})})}),(0,l.jsxs)("div",{className:"flex-1 overflow-auto space-y-4",children:[(0,l.jsxs)("div",{className:"space-y-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex justify-between items-center mb-2",children:[(0,l.jsxs)("div",{className:"flex items-center gap-2",children:[(0,l.jsx)("label",{className:"text-sm font-medium text-gray-700",children:"Input Text"}),(0,l.jsx)(ew.Tooltip,{title:"Press Enter to submit. Use Shift+Enter for new line.",children:(0,l.jsx)(eJ.InfoCircleOutlined,{className:"text-gray-400 cursor-help"})})]}),o&&(0,l.jsx)(e7.Button,{size:"xs",variant:"secondary",icon:tQ.CopyOutlined,onClick:u,children:"Copy Input"})]}),(0,l.jsx)(t2,{value:o,onChange:e=>d(e.target.value),onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||e.ctrlKey||e.metaKey||(e.preventDefault(),c())},placeholder:"Enter text to test with guardrails...",rows:8,className:"font-mono text-sm"}),(0,l.jsxs)("div",{className:"flex justify-between items-center mt-1",children:[(0,l.jsxs)(t4,{className:"text-xs text-gray-500",children:["Press ",(0,l.jsx)("kbd",{className:"px-1 py-0.5 bg-gray-100 border border-gray-300 rounded text-xs",children:"Enter"})," to submit •"," ",(0,l.jsx)("kbd",{className:"px-1 py-0.5 bg-gray-100 border border-gray-300 rounded text-xs",children:"Shift+Enter"})," for new line"]}),(0,l.jsxs)(t4,{className:"text-xs text-gray-500",children:["Characters: ",o.length]})]})]}),(0,l.jsx)("div",{className:"pt-2",children:(0,l.jsx)(e7.Button,{onClick:c,loading:a,disabled:!o.trim(),className:"w-full",children:a?`Testing ${e.length} guardrail${e.length>1?"s":""}...`:`Test ${e.length} guardrail${e.length>1?"s":""}`})})]}),(0,l.jsx)(t1,{results:i,errors:s})]})]})},t8=({guardrailsList:e,isLoading:t,accessToken:a,onClose:i})=>{let[s,n]=(0,r.useState)(new Set),[o,d]=(0,r.useState)(""),[c,u]=(0,r.useState)([]),[g,x]=(0,r.useState)([]),[h,j]=(0,r.useState)(!1),_=e.filter(e=>e.guardrail_name?.toLowerCase().includes(o.toLowerCase())),v=async e=>{if(0===s.size||!a)return;j(!0),u([]),x([]);let t=[],l=[];await Promise.all(Array.from(s).map(async r=>{let i=Date.now();try{let l=await (0,m.applyGuardrail)(a,r,e,null,null),s=Date.now()-i;t.push({guardrailName:r,response_text:l.response_text,latency:s})}catch(t){let e=Date.now()-i;console.error(`Error testing guardrail ${r}:`,t),l.push({guardrailName:r,error:t,latency:e})}})),u(t),x(l),j(!1),t.length>0&&y.default.success(`${t.length} guardrail${t.length>1?"s":""} applied successfully`),l.length>0&&y.default.fromBackend(`${l.length} guardrail${l.length>1?"s":""} failed`)};return(0,l.jsx)("div",{className:"w-full h-[calc(100vh-200px)]",children:(0,l.jsx)(b.Card,{className:"h-full",styles:{body:{padding:0,height:"100%"}},children:(0,l.jsxs)("div",{className:"flex h-full",children:[(0,l.jsxs)("div",{className:"w-1/4 border-r border-gray-200 flex flex-col overflow-hidden",children:[(0,l.jsx)("div",{className:"p-4 border-b border-gray-200",children:(0,l.jsxs)("div",{className:"mb-3",children:[(0,l.jsx)("h3",{className:"text-lg font-semibold mb-3",children:"Guardrails"}),(0,l.jsx)(p.Input,{prefix:(0,l.jsx)(tY.SearchOutlined,{}),placeholder:"Search guardrails...",value:o,onChange:e=>d(e.target.value)})]})}),(0,l.jsx)("div",{className:"flex-1 overflow-auto",children:t?(0,l.jsx)("div",{className:"flex items-center justify-center h-32",children:(0,l.jsx)(e_.Spin,{})}):0===_.length?(0,l.jsx)("div",{className:"p-4",children:(0,l.jsx)(eH.Empty,{description:o?"No guardrails match your search":"No guardrails available"})}):(0,l.jsx)(tW.List,{dataSource:_,renderItem:e=>(0,l.jsx)(tW.List.Item,{onClick:()=>{var t;let a;e.guardrail_name&&(t=e.guardrail_name,(a=new Set(s)).has(t)?a.delete(t):a.add(t),n(a))},style:{paddingLeft:24,paddingRight:16},className:`cursor-pointer hover:bg-gray-50 transition-colors ${s.has(e.guardrail_name||"")?"bg-blue-50 border-l-4 border-l-blue-500":"border-l-4 border-l-transparent"}`,children:(0,l.jsx)(tW.List.Item.Meta,{title:(0,l.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,l.jsx)(tV.ExperimentOutlined,{className:"text-gray-400"}),(0,l.jsx)("span",{className:"font-medium text-gray-900",children:e.guardrail_name})]}),description:(0,l.jsxs)("div",{className:"text-xs space-y-1 mt-1",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("span",{className:"font-medium",children:"Type: "}),(0,l.jsx)("span",{className:"text-gray-600",children:e.litellm_params.guardrail})]}),(0,l.jsxs)("div",{children:[(0,l.jsx)("span",{className:"font-medium",children:"Mode: "}),(0,l.jsx)("span",{className:"text-gray-600",children:e.litellm_params.mode})]})]})})})})}),(0,l.jsx)("div",{className:"p-3 border-t border-gray-200 bg-gray-50",children:(0,l.jsxs)(f.Typography.Text,{className:"text-xs text-gray-600",children:[s.size," of ",_.length," selected"]})})]}),(0,l.jsxs)("div",{className:"w-3/4 flex flex-col bg-white",children:[(0,l.jsx)("div",{className:"p-4 border-b border-gray-200 flex justify-between items-center",children:(0,l.jsx)(f.Typography.Title,{level:2,className:"text-xl font-semibold mb-0",children:"Guardrail Testing Playground"})}),(0,l.jsx)("div",{className:"flex-1 overflow-auto p-4",children:0===s.size?(0,l.jsxs)("div",{className:"h-full flex flex-col items-center justify-center text-gray-400",children:[(0,l.jsx)(tV.ExperimentOutlined,{style:{fontSize:"48px",marginBottom:"16px"}}),(0,l.jsx)(f.Typography.Paragraph,{className:"text-lg font-medium text-gray-600 mb-2",children:"Select Guardrails to Test"}),(0,l.jsx)(f.Typography.Paragraph,{className:"text-center text-gray-500 max-w-md",children:"Choose one or more guardrails from the left sidebar to start testing and comparing results."})]}):(0,l.jsx)("div",{className:"h-full",children:(0,l.jsx)(t5,{guardrailNames:Array.from(s),onSubmit:v,results:c.length>0?c:null,errors:g.length>0?g:null,isLoading:h,onClose:()=>n(new Set)})})})]})]})})})};var t6=e.i(127952),t3=e.i(266537);let t7="../ui/assets/logos/",t9=[{id:"cf_denied_financial",name:"Denied Financial Advice",description:"Detects requests for personalized financial advice, investment recommendations, or financial planning.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Topic Blocker"],eval:{f1:100,precision:100,recall:100,testCases:207,latency:"<0.1ms"}},{id:"cf_denied_insults",name:"Insults & Personal Attacks",description:"Detects insults, name-calling, and personal attacks directed at the chatbot, staff, or other people.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Topic Blocker"],eval:{f1:100,precision:100,recall:100,testCases:299,latency:"<0.1ms"}},{id:"cf_denied_legal",name:"Denied Legal Advice",description:"Detects requests for unauthorized legal advice, case analysis, or legal recommendations.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Topic Blocker"]},{id:"cf_denied_medical",name:"Denied Medical Advice",description:"Detects requests for medical diagnosis, treatment recommendations, or health advice.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Topic Blocker"]},{id:"cf_harmful_violence",name:"Harmful Violence",description:"Detects content related to violence, criminal planning, attacks, and violent threats.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Safety"]},{id:"cf_harmful_self_harm",name:"Harmful Self-Harm",description:"Detects content related to self-harm, suicide, and dangerous self-destructive behavior.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Safety"]},{id:"cf_harmful_child_safety",name:"Harmful Child Safety",description:"Detects content that could endanger child safety or exploit minors.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Safety"]},{id:"cf_harmful_illegal_weapons",name:"Harmful Illegal Weapons",description:"Detects content related to illegal weapons manufacturing, distribution, or acquisition.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Safety"]},{id:"cf_bias_gender",name:"Bias: Gender",description:"Detects gender-based discrimination, stereotypes, and biased language.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Bias"]},{id:"cf_bias_racial",name:"Bias: Racial",description:"Detects racial discrimination, stereotypes, and racially biased content.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Bias"]},{id:"cf_bias_religious",name:"Bias: Religious",description:"Detects religious discrimination, intolerance, and religiously biased content.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Bias"]},{id:"cf_bias_sexual_orientation",name:"Bias: Sexual Orientation",description:"Detects discrimination based on sexual orientation and related biased content.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Bias"]},{id:"cf_prompt_injection_jailbreak",name:"Prompt Injection: Jailbreak",description:"Detects jailbreak attempts designed to bypass AI safety guidelines and restrictions.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Prompt Injection"]},{id:"cf_prompt_injection_data_exfil",name:"Prompt Injection: Data Exfiltration",description:"Detects attempts to extract sensitive data through prompt manipulation.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Prompt Injection"]},{id:"cf_prompt_injection_sql",name:"Prompt Injection: SQL",description:"Detects SQL injection attempts embedded in prompts.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Prompt Injection"]},{id:"cf_prompt_injection_malicious_code",name:"Prompt Injection: Malicious Code",description:"Detects attempts to inject malicious code through prompts.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Prompt Injection"]},{id:"cf_prompt_injection_system_prompt",name:"Prompt Injection: System Prompt",description:"Detects attempts to extract or override system prompts.",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Prompt Injection"]},{id:"cf_toxic_abuse",name:"Toxic & Abusive Language",description:"Detects toxic, abusive, and hateful language across multiple languages (EN, AU, DE, ES, FR).",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Toxicity"]},{id:"cf_patterns",name:"Pattern Matching",description:"Detect and block sensitive data patterns like SSNs, credit card numbers, API keys, and custom regex patterns.",category:"litellm",subcategory:"Patterns",logo:`${t7}litellm_logo.jpg`,tags:["PII","Regex","Data Protection"]},{id:"cf_keywords",name:"Keyword Blocking",description:"Block or mask content containing specific keywords or phrases. Upload custom word lists or add individual terms.",category:"litellm",subcategory:"Keywords",logo:`${t7}litellm_logo.jpg`,tags:["Keywords","Blocklist"]},{id:"block_code_execution",name:"Block Code Execution",description:"Detects markdown fenced code blocks in requests and responses. Block or mask executable code (e.g. Python, JavaScript, Bash) by language with configurable confidence.",category:"litellm",subcategory:"Code Safety",logo:`${t7}litellm_logo.jpg`,tags:["Code","Safety","Prompt Injection"]},{id:"cf_competitor_intent",name:"Competitor Name Blocking",description:"Block or reframe competitor comparison and ranking intent. Detect when users ask to compare or recommend competitors (airline or generic competitor lists).",category:"litellm",subcategory:"Content Category",logo:`${t7}litellm_logo.jpg`,tags:["Content Category","Competitor","Topic Blocker"]},{id:"presidio",name:"Presidio PII",description:"Microsoft Presidio for PII detection and anonymization. Supports 30+ entity types with configurable actions.",category:"partner",logo:`${t7}microsoft_azure.svg`,tags:["PII","Microsoft"],providerKey:"PresidioPII"},{id:"bedrock",name:"Bedrock Guardrail",description:"AWS Bedrock Guardrails for content filtering, topic avoidance, and sensitive information detection.",category:"partner",logo:`${t7}bedrock.svg`,tags:["AWS","Content Safety"],providerKey:"Bedrock"},{id:"lakera",name:"Lakera",description:"AI security platform protecting against prompt injections, data leakage, and harmful content.",category:"partner",logo:`${t7}lakeraai.jpeg`,tags:["Security","Prompt Injection"],providerKey:"Lakera"},{id:"openai_moderation",name:"OpenAI Moderation",description:"OpenAI's content moderation API for detecting harmful content across multiple categories.",category:"partner",logo:`${t7}openai_small.svg`,tags:["Content Moderation","OpenAI"]},{id:"google_model_armor",name:"Google Cloud Model Armor",description:"Google Cloud's model protection service for safe and responsible AI deployments.",category:"partner",logo:`${t7}google.svg`,tags:["Google Cloud","Safety"]},{id:"guardrails_ai",name:"Guardrails AI",description:"Open-source framework for adding structural, type, and quality guarantees to LLM outputs.",category:"partner",logo:`${t7}guardrails_ai.jpeg`,tags:["Open Source","Validation"]},{id:"zscaler",name:"Zscaler AI Guard",description:"Enterprise AI security from Zscaler for monitoring and protecting AI/ML workloads.",category:"partner",logo:`${t7}zscaler.svg`,tags:["Enterprise","Security"]},{id:"panw",name:"PANW Prisma AIRS",description:"Palo Alto Networks Prisma AI Runtime Security for securing AI applications in production.",category:"partner",logo:`${t7}palo_alto_networks.jpeg`,tags:["Enterprise","Security"]},{id:"cisco_ai_defense",name:"Cisco AI Defense",description:"Cisco AI Defense Inspection API for runtime protection: prompt injection, PII/PCI/PHI, harassment, hate speech, profanity, violence, and code detection.",category:"partner",logo:`${t7}cisco.png`,tags:["Enterprise","Security","Prompt Injection","PII"],providerKey:"CiscoAiDefense"},{id:"noma",name:"Noma Security",description:"AI security platform for detecting and preventing AI-specific threats and vulnerabilities.",category:"partner",logo:`${t7}noma_security.png`,tags:["Security","Threat Detection"]},{id:"aporia",name:"Aporia AI",description:"Real-time AI guardrails for hallucination detection, topic control, and policy enforcement.",category:"partner",logo:`${t7}aporia.png`,tags:["Hallucination","Policy"]},{id:"aim",name:"AIM Guardrail",description:"AIM Security guardrails for comprehensive AI threat detection and mitigation.",category:"partner",logo:`${t7}aim_security.jpeg`,tags:["Security","Threat Detection"]},{id:"cato_networks",name:"Cato Networks Guardrail",description:"Cato Networks guardrails for comprehensive AI threat detection and mitigation.",category:"partner",logo:`${t7}cato_networks.svg`,tags:["Security","Threat Detection"]},{id:"prompt_security",name:"Prompt Security",description:"Protect against prompt injection attacks, data leakage, and other LLM security threats.",category:"partner",logo:`${t7}prompt_security.png`,tags:["Prompt Injection","Security"]},{id:"lasso",name:"Lasso Guardrail",description:"Content moderation and safety guardrails for responsible AI deployments.",category:"partner",logo:`${t7}lasso.png`,tags:["Content Moderation"]},{id:"pangea",name:"Pangea Guardrail",description:"Pangea's AI guardrails for secure, compliant, and trustworthy AI applications.",category:"partner",logo:`${t7}pangea.png`,tags:["Compliance","Security"]},{id:"enkryptai",name:"EnkryptAI",description:"AI security and governance platform for enterprise AI safety and compliance.",category:"partner",logo:`${t7}enkrypt_ai.avif`,tags:["Enterprise","Governance"]},{id:"javelin",name:"Javelin Guardrails",description:"AI gateway with built-in guardrails for secure and compliant AI operations.",category:"partner",logo:`${t7}javelin.png`,tags:["Gateway","Security"]},{id:"pillar",name:"Pillar Guardrail",description:"AI safety platform for monitoring, testing, and securing AI systems.",category:"partner",logo:`${t7}pillar.jpeg`,tags:["Monitoring","Safety"]},{id:"akto",name:"Akto Guardrail",description:"AI security platform from Akto.io with automatic monitoring and guardrails for AI/ML applications.",category:"partner",logo:`${t7}akto.svg`,tags:["Security","Safety","Monitoring"]},{id:"promptguard",name:"PromptGuard",description:"AI security gateway with prompt injection detection, PII redaction, topic filtering, entity blocklists, and hallucination detection. Self-hostable with drop-in proxy integration.",category:"partner",logo:`${t7}promptguard.svg`,tags:["Security","Prompt Injection","PII"],providerKey:"Promptguard",eval:{f1:94.9,precision:100,recall:90.4,testCases:5384,latency:"~150ms"}},{id:"xecguard",name:"XecGuard",description:"CyCraft XecGuard AI security gateway. Multi-policy scanning (prompt injection, harmful content, PII, system-prompt enforcement) plus RAG context grounding.",category:"partner",logo:`${t7}xecguard.svg`,tags:["Security","Policy","Grounding","RAG"],providerKey:"Xecguard"},{id:"repelloai",name:"RepelloAI Argus",description:"RepelloAI Argus scans prompts and responses against policies configured per asset in the Repello dashboard.",category:"partner",logo:`${t7}repelloai.png`,tags:["Security","Policy","Prompt Injection"],providerKey:"Repelloai"}];var ae=e.i(826910);let at=({src:e,name:t})=>{let[a,i]=(0,r.useState)(!1);return a||!e?(0,l.jsx)("div",{style:{width:28,height:28,borderRadius:6,backgroundColor:"#e5e7eb",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,fontWeight:600,color:"#6b7280",flexShrink:0},children:t?.charAt(0)||"?"}):(0,l.jsx)("img",{src:e,alt:"",style:{width:28,height:28,borderRadius:6,objectFit:"contain",flexShrink:0},onError:()=>i(!0)})},aa=({card:e,onClick:t})=>{let[a,i]=(0,r.useState)(!1);return(0,l.jsxs)("div",{onClick:t,onMouseEnter:()=>i(!0),onMouseLeave:()=>i(!1),style:{borderRadius:12,border:a?"1px solid #93c5fd":"1px solid #e5e7eb",backgroundColor:"#ffffff",padding:"20px 20px 16px 20px",cursor:"pointer",transition:"border-color 0.15s, box-shadow 0.15s",display:"flex",flexDirection:"column",minHeight:170,boxShadow:a?"0 1px 6px rgba(59,130,246,0.08)":"none"},children:[(0,l.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:10,marginBottom:10},children:[(0,l.jsx)(at,{src:e.logo,name:e.name}),(0,l.jsx)("span",{style:{fontSize:14,fontWeight:600,color:"#111827",lineHeight:1.3},children:e.name})]}),(0,l.jsx)("p",{className:"line-clamp-3",style:{fontSize:12,color:"#6b7280",lineHeight:1.6,margin:0,flex:1},children:e.description}),e.eval&&(0,l.jsxs)("div",{style:{marginTop:10,display:"flex",alignItems:"center",gap:4},children:[(0,l.jsx)(ae.CheckCircleFilled,{style:{color:"#16a34a",fontSize:12}}),(0,l.jsxs)("span",{style:{fontSize:11,color:"#16a34a",fontWeight:500},children:["F1: ",e.eval.f1,"% · ",e.eval.testCases," test cases"]})]})]})};var al=e.i(447566);let ar={cf_denied_financial:{provider:"LitellmContentFilter",categoryName:"denied_financial_advice",guardrailNameSuggestion:"Denied Financial Advice",mode:"pre_call",defaultOn:!1},cf_denied_legal:{provider:"LitellmContentFilter",categoryName:"denied_legal_advice",guardrailNameSuggestion:"Denied Legal Advice",mode:"pre_call",defaultOn:!1},cf_denied_medical:{provider:"LitellmContentFilter",categoryName:"denied_medical_advice",guardrailNameSuggestion:"Denied Medical Advice",mode:"pre_call",defaultOn:!1},cf_denied_insults:{provider:"LitellmContentFilter",categoryName:"denied_insults",guardrailNameSuggestion:"Insults & Personal Attacks",mode:"pre_call",defaultOn:!1},cf_harmful_violence:{provider:"LitellmContentFilter",categoryName:"harmful_violence",guardrailNameSuggestion:"Harmful Violence",mode:"pre_call",defaultOn:!1},cf_harmful_self_harm:{provider:"LitellmContentFilter",categoryName:"harmful_self_harm",guardrailNameSuggestion:"Harmful Self-Harm",mode:"pre_call",defaultOn:!1},cf_harmful_child_safety:{provider:"LitellmContentFilter",categoryName:"harmful_child_safety",guardrailNameSuggestion:"Harmful Child Safety",mode:"pre_call",defaultOn:!1},cf_harmful_illegal_weapons:{provider:"LitellmContentFilter",categoryName:"harmful_illegal_weapons",guardrailNameSuggestion:"Harmful Illegal Weapons",mode:"pre_call",defaultOn:!1},cf_bias_gender:{provider:"LitellmContentFilter",categoryName:"bias_gender",guardrailNameSuggestion:"Bias: Gender",mode:"pre_call",defaultOn:!1},cf_bias_racial:{provider:"LitellmContentFilter",categoryName:"bias_racial",guardrailNameSuggestion:"Bias: Racial",mode:"pre_call",defaultOn:!1},cf_bias_religious:{provider:"LitellmContentFilter",categoryName:"bias_religious",guardrailNameSuggestion:"Bias: Religious",mode:"pre_call",defaultOn:!1},cf_bias_sexual_orientation:{provider:"LitellmContentFilter",categoryName:"bias_sexual_orientation",guardrailNameSuggestion:"Bias: Sexual Orientation",mode:"pre_call",defaultOn:!1},cf_prompt_injection_jailbreak:{provider:"LitellmContentFilter",categoryName:"prompt_injection_jailbreak",guardrailNameSuggestion:"Prompt Injection: Jailbreak",mode:"pre_call",defaultOn:!1},cf_prompt_injection_data_exfil:{provider:"LitellmContentFilter",categoryName:"prompt_injection_data_exfiltration",guardrailNameSuggestion:"Prompt Injection: Data Exfiltration",mode:"pre_call",defaultOn:!1},cf_prompt_injection_sql:{provider:"LitellmContentFilter",categoryName:"prompt_injection_sql",guardrailNameSuggestion:"Prompt Injection: SQL",mode:"pre_call",defaultOn:!1},cf_prompt_injection_malicious_code:{provider:"LitellmContentFilter",categoryName:"prompt_injection_malicious_code",guardrailNameSuggestion:"Prompt Injection: Malicious Code",mode:"pre_call",defaultOn:!1},cf_prompt_injection_system_prompt:{provider:"LitellmContentFilter",categoryName:"prompt_injection_system_prompt",guardrailNameSuggestion:"Prompt Injection: System Prompt",mode:"pre_call",defaultOn:!1},cf_toxic_abuse:{provider:"LitellmContentFilter",categoryName:"harm_toxic_abuse",guardrailNameSuggestion:"Toxic & Abusive Language",mode:"pre_call",defaultOn:!1},cf_patterns:{provider:"LitellmContentFilter",guardrailNameSuggestion:"Pattern Matching",mode:"pre_call",defaultOn:!1},cf_keywords:{provider:"LitellmContentFilter",guardrailNameSuggestion:"Keyword Blocking",mode:"pre_call",defaultOn:!1},block_code_execution:{provider:"BlockCodeExecution",guardrailNameSuggestion:"Block Code Execution",mode:"pre_call",defaultOn:!1},cf_competitor_intent:{provider:"LitellmContentFilter",guardrailNameSuggestion:"Competitor Name Blocking",mode:"pre_call",defaultOn:!1},presidio:{provider:"PresidioPII",guardrailNameSuggestion:"Presidio PII",mode:"pre_call",defaultOn:!1},bedrock:{provider:"Bedrock",guardrailNameSuggestion:"Bedrock Guardrail",mode:"pre_call",defaultOn:!1},lakera:{provider:"Lakera",guardrailNameSuggestion:"Lakera",mode:"pre_call",defaultOn:!1},openai_moderation:{provider:"OpenaiModeration",guardrailNameSuggestion:"OpenAI Moderation",mode:"pre_call",defaultOn:!1},google_model_armor:{provider:"ModelArmor",guardrailNameSuggestion:"Google Cloud Model Armor",mode:"pre_call",defaultOn:!1},guardrails_ai:{provider:"GuardrailsAi",guardrailNameSuggestion:"Guardrails AI",mode:"pre_call",defaultOn:!1},zscaler:{provider:"ZscalerAiGuard",guardrailNameSuggestion:"Zscaler AI Guard",mode:"pre_call",defaultOn:!1},panw:{provider:"PanwPrismaAirs",guardrailNameSuggestion:"PANW Prisma AIRS",mode:"pre_call",defaultOn:!1},cisco_ai_defense:{provider:"CiscoAiDefense",guardrailNameSuggestion:"Cisco AI Defense",mode:"pre_call",defaultOn:!1},noma:{provider:"Noma",guardrailNameSuggestion:"Noma Security",mode:"pre_call",defaultOn:!1},aporia:{provider:"AporiaAi",guardrailNameSuggestion:"Aporia AI",mode:"pre_call",defaultOn:!1},aim:{provider:"Aim",guardrailNameSuggestion:"AIM Guardrail",mode:"pre_call",defaultOn:!1},cato_networks:{provider:"Cato Networks",guardrailNameSuggestion:"Cato Networks Guardrail",mode:"pre_call",defaultOn:!1},prompt_security:{provider:"PromptSecurity",guardrailNameSuggestion:"Prompt Security",mode:"pre_call",defaultOn:!1},lasso:{provider:"Lasso",guardrailNameSuggestion:"Lasso Guardrail",mode:"pre_call",defaultOn:!1},pangea:{provider:"Pangea",guardrailNameSuggestion:"Pangea Guardrail",mode:"pre_call",defaultOn:!1},enkryptai:{provider:"Enkryptai",guardrailNameSuggestion:"EnkryptAI",mode:"pre_call",defaultOn:!1},javelin:{provider:"Javelin",guardrailNameSuggestion:"Javelin Guardrails",mode:"pre_call",defaultOn:!1},pillar:{provider:"Pillar",guardrailNameSuggestion:"Pillar Guardrail",mode:"pre_call",defaultOn:!1},akto:{provider:"Akto",guardrailNameSuggestion:"Akto Guardrail",mode:"pre_call",defaultOn:!1},promptguard:{provider:"Promptguard",guardrailNameSuggestion:"PromptGuard",mode:"pre_call",defaultOn:!1},xecguard:{provider:"Xecguard",guardrailNameSuggestion:"XecGuard",mode:"pre_call",defaultOn:!1},repelloai:{provider:"Repelloai",guardrailNameSuggestion:"RepelloAI Argus",mode:"pre_call",defaultOn:!1}},ai=({card:e,onBack:t,accessToken:a,onGuardrailCreated:s})=>{let[n,o]=(0,r.useState)(!1),[d,c]=(0,r.useState)("overview"),m=[{property:"Provider",value:"litellm"===e.category?"LiteLLM Content Filter":"Partner Guardrail"},...e.subcategory?[{property:"Subcategory",value:e.subcategory}]:[],..."litellm"===e.category?[{property:"Cost",value:"$0 / request"}]:[],..."litellm"===e.category?[{property:"External Dependencies",value:"None"}]:[],..."litellm"===e.category?[{property:"Latency",value:e.eval?.latency||"<1ms"}]:[]],u=e.eval?[{metric:"Precision",value:`${e.eval.precision}%`},{metric:"Recall",value:`${e.eval.recall}%`},{metric:"F1 Score",value:`${e.eval.f1}%`},{metric:"Test Cases",value:String(e.eval.testCases)},{metric:"False Positives",value:"0"},{metric:"False Negatives",value:"0"},{metric:"Latency (p50)",value:e.eval.latency}]:[],p=[{key:"overview",label:"Overview"},...e.eval?[{key:"eval",label:"Eval Results"}]:[]];return(0,l.jsxs)("div",{style:{maxWidth:960,margin:"0 auto"},children:[(0,l.jsxs)("div",{onClick:t,style:{display:"inline-flex",alignItems:"center",gap:6,color:"#5f6368",cursor:"pointer",fontSize:14,marginBottom:24},children:[(0,l.jsx)(al.ArrowLeftOutlined,{style:{fontSize:11}}),(0,l.jsx)("span",{children:e.name})]}),(0,l.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:16,marginBottom:8},children:[(0,l.jsx)("img",{src:e.logo,alt:"",style:{width:40,height:40,borderRadius:8,objectFit:"contain"},onError:e=>{e.target.style.display="none"}}),(0,l.jsx)("h1",{style:{fontSize:28,fontWeight:400,color:"#202124",margin:0,lineHeight:1.2},children:e.name})]}),(0,l.jsx)("p",{style:{fontSize:14,color:"#5f6368",margin:"0 0 20px 0",lineHeight:1.6},children:e.description}),(0,l.jsx)("div",{style:{display:"flex",gap:10,marginBottom:32},children:(0,l.jsx)(i.Button,{onClick:()=>o(!0),style:{borderRadius:20,padding:"4px 20px",height:36,borderColor:"#dadce0",color:"#1a73e8",fontWeight:500,fontSize:14},children:"Create Guardrail"})}),(0,l.jsx)("div",{style:{borderBottom:"1px solid #dadce0",marginBottom:28},children:(0,l.jsx)("div",{style:{display:"flex",gap:0},children:p.map(e=>(0,l.jsx)("div",{onClick:()=>c(e.key),style:{padding:"12px 20px",fontSize:14,color:d===e.key?"#1a73e8":"#5f6368",borderBottom:d===e.key?"3px solid #1a73e8":"3px solid transparent",cursor:"pointer",fontWeight:d===e.key?500:400,marginBottom:-1},children:e.label},e.key))})}),"overview"===d&&(0,l.jsxs)("div",{style:{display:"flex",gap:64},children:[(0,l.jsxs)("div",{style:{flex:1,minWidth:0},children:[(0,l.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 12px 0"},children:"Overview"}),(0,l.jsx)("p",{style:{fontSize:14,color:"#3c4043",lineHeight:1.7,margin:"0 0 32px 0"},children:e.description}),(0,l.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 4px 0"},children:"Guardrail Details"}),(0,l.jsx)("p",{style:{fontSize:13,color:"#5f6368",margin:"0 0 16px 0"},children:"Details are as follows"}),(0,l.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:14},children:[(0,l.jsx)("thead",{children:(0,l.jsxs)("tr",{style:{borderBottom:"1px solid #dadce0"},children:[(0,l.jsx)("th",{style:{textAlign:"left",padding:"12px 0",color:"#5f6368",fontWeight:500,width:200},children:"Property"}),(0,l.jsx)("th",{style:{textAlign:"left",padding:"12px 0",color:"#5f6368",fontWeight:500},children:e.name})]})}),(0,l.jsx)("tbody",{children:m.map((e,t)=>(0,l.jsxs)("tr",{style:{borderBottom:"1px solid #f1f3f4"},children:[(0,l.jsx)("td",{style:{padding:"12px 0",color:"#3c4043"},children:e.property}),(0,l.jsx)("td",{style:{padding:"12px 0",color:"#202124"},children:e.value})]},t))})]})]}),(0,l.jsxs)("div",{style:{width:240,flexShrink:0},children:[(0,l.jsxs)("div",{style:{marginBottom:28},children:[(0,l.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Guardrail ID"}),(0,l.jsxs)("div",{style:{fontSize:13,color:"#202124",wordBreak:"break-all"},children:["litellm/",e.id]})]}),(0,l.jsxs)("div",{style:{marginBottom:28},children:[(0,l.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Type"}),(0,l.jsx)("div",{style:{fontSize:13,color:"#202124"},children:"litellm"===e.category?"Content Filter":"Partner"})]}),e.tags.length>0&&(0,l.jsxs)("div",{style:{marginBottom:28},children:[(0,l.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:8},children:"Tags"}),(0,l.jsx)("div",{style:{display:"flex",flexWrap:"wrap",gap:6},children:e.tags.map(e=>(0,l.jsx)("span",{style:{fontSize:12,padding:"4px 12px",borderRadius:16,border:"1px solid #dadce0",color:"#3c4043",backgroundColor:"#fff"},children:e},e))})]})]})]}),"eval"===d&&(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 16px 0"},children:"Eval Results"}),(0,l.jsxs)("table",{style:{width:"100%",maxWidth:560,borderCollapse:"collapse",fontSize:14},children:[(0,l.jsx)("thead",{children:(0,l.jsxs)("tr",{style:{backgroundColor:"#f8f9fa",borderBottom:"1px solid #dadce0"},children:[(0,l.jsx)("th",{style:{textAlign:"left",padding:"12px 16px",color:"#5f6368",fontWeight:500},children:"Metric"}),(0,l.jsx)("th",{style:{textAlign:"left",padding:"12px 16px",color:"#5f6368",fontWeight:500},children:"Value"})]})}),(0,l.jsx)("tbody",{children:u.map((e,t)=>(0,l.jsxs)("tr",{style:{borderBottom:"1px solid #f1f3f4"},children:[(0,l.jsx)("td",{style:{padding:"12px 16px",color:"#3c4043"},children:e.metric}),(0,l.jsx)("td",{style:{padding:"12px 16px",color:"#202124",fontWeight:500},children:e.value})]},t))})]})]}),(0,l.jsx)(e0,{visible:n,onClose:()=>o(!1),accessToken:a,onSuccess:()=>{o(!1),s()},preset:ar[e.id]})]})},as=({accessToken:e,onGuardrailCreated:t})=>{let[a,i]=(0,r.useState)(""),[s,n]=(0,r.useState)(null),[o,d]=(0,r.useState)(!1),c=t9.filter(e=>{if(!a)return!0;let t=a.toLowerCase();return e.name.toLowerCase().includes(t)||e.description.toLowerCase().includes(t)||e.tags.some(e=>e.toLowerCase().includes(t))}),m=c.filter(e=>"litellm"===e.category),u=c.filter(e=>"partner"===e.category);return s?(0,l.jsx)(ai,{card:s,onBack:()=>n(null),accessToken:e,onGuardrailCreated:t}):(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{style:{marginBottom:24},children:(0,l.jsx)(p.Input,{size:"large",placeholder:"Search guardrails",prefix:(0,l.jsx)(tY.SearchOutlined,{style:{color:"#9ca3af"}}),value:a,onChange:e=>i(e.target.value),style:{borderRadius:8}})}),(0,l.jsxs)("div",{style:{marginBottom:40},children:[(0,l.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:4},children:[(0,l.jsx)("h2",{style:{fontSize:20,fontWeight:600,color:"#111827",margin:0},children:"LiteLLM Content Filter"}),(0,l.jsx)("span",{style:{display:"inline-flex",alignItems:"center",gap:6,fontSize:14,color:"#1a73e8",cursor:"pointer"},onClick:()=>d(!o),children:o?(0,l.jsx)(l.Fragment,{children:"Show less"}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(t3.ArrowRightOutlined,{style:{fontSize:12}}),`Show all (${m.length})`]})})]}),(0,l.jsx)("p",{style:{fontSize:13,color:"#6b7280",margin:"4px 0 20px 0"},children:"Built-in guardrails powered by LiteLLM. Zero latency, no external dependencies, no additional cost."}),(0,l.jsx)("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:16},children:(o?m:m.slice(0,10)).map(e=>(0,l.jsx)(aa,{card:e,onClick:()=>n(e)},e.id))})]}),(0,l.jsxs)("div",{style:{marginBottom:40},children:[(0,l.jsx)("h2",{style:{fontSize:20,fontWeight:600,color:"#111827",margin:"0 0 4px 0"},children:"Partner Guardrails"}),(0,l.jsx)("p",{style:{fontSize:13,color:"#6b7280",margin:"4px 0 20px 0"},children:"Third-party guardrail integrations from leading AI security providers."}),(0,l.jsx)("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:16},children:u.map(e=>(0,l.jsx)(aa,{card:e,onClick:()=>n(e)},e.id))})]})]})};var an=e.i(988846),ao=e.i(837007),ad=e.i(409797),ac=e.i(54131),am=e.i(995926),au=e.i(634831),ap=e.i(438100),ag=e.i(302202),ax=e.i(328196),ah=e.i(168118),af=e.i(663435),ay=e.i(954616),aj=e.i(912598),a_=e.i(431703),ab=e.i(135214),av=e.i(243652);let aw=async(e,t)=>{let a=(0,m.getProxyBaseUrl)(),l=`${a}/guardrails/register`,r=await fetch(l,{method:"POST",headers:{[(0,m.getGlobalLitellmHeaderName)()]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!r.ok){let e=await r.json().catch(()=>({})),t=(0,a_.deriveErrorMessage)(e);throw(0,m.handleError)(t),Error(t)}return r.json()},aN=(0,av.createQueryKeys)("guardrails");function aC(e){var t;let a=e.litellm_params??{},l=e.guardrail_info??{},r=a.headers,i=Array.isArray(r)?r.map(e=>({key:(e.key??e.name??"").toString(),value:String(e.value??"")})):"object"==typeof r&&null!==r?Object.entries(r).map(([e,t])=>({key:e,value:String(t??"")})):[],s=a.api_base??a.url??"",n=l.model??a.model??"—",o=a.forward_api_key??!0,d=Array.isArray(a.extra_headers)?a.extra_headers.filter(e=>"string"==typeof e):[];return{id:e.guardrail_id,team:e.team_id??"—",name:e.guardrail_name,endpoint:s,status:"pending_review"===(t=e.status)?"pending":"active"===t||"rejected"===t?t:"active",model:n,forwardKey:o,description:l.description??"",method:a.method??"POST",customHeaders:i,extraHeaders:d,submittedAt:function(e){if(!e)return"—";try{let t=new Date(e);return isNaN(t.getTime())?e:t.toISOString().slice(0,10)}catch{return e}}(e.submitted_at),submittedBy:e.submitted_by_email??e.submitted_by_user_id??"—",mode:a.mode,unreachable_fallback:a.unreachable_fallback,additionalProviderParams:a.additional_provider_specific_params,guardrailType:a.guardrail}}let aS={active:{label:"Active",bg:"bg-green-50",text:"text-green-700",dot:"bg-green-500"},pending:{label:"Pending Review",bg:"bg-yellow-50",text:"text-yellow-700",dot:"bg-yellow-500"},rejected:{label:"Rejected",bg:"bg-red-50",text:"text-red-700",dot:"bg-red-500"}},ak={"ML Platform":"bg-purple-100 text-purple-700","Data Science":"bg-blue-100 text-blue-700",Security:"bg-red-100 text-red-700","Customer Success":"bg-orange-100 text-orange-700",Legal:"bg-gray-100 text-gray-700",Finance:"bg-green-100 text-green-700"};function aI({label:e,value:t,color:a}){return(0,l.jsxs)("div",{className:"bg-white border border-gray-200 rounded-lg px-4 py-3",children:[(0,l.jsx)("div",{className:`text-2xl font-bold ${a}`,children:t}),(0,l.jsx)("div",{className:"text-xs text-gray-500 mt-0.5",children:e})]})}function aA({enabled:e,onToggle:t}){return(0,l.jsx)("button",{type:"button",onClick:t,role:"switch","aria-checked":e,className:`relative inline-flex h-5 w-9 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 ${e?"bg-blue-500":"bg-gray-200"}`,children:(0,l.jsx)("span",{className:`inline-block h-3.5 w-3.5 transform rounded-full bg-white shadow transition-transform ${e?"translate-x-4":"translate-x-0.5"}`})})}function aO({guardrail:e,isSelected:t,isHeadersExpanded:a,onSelect:r,onToggleForwardKey:i,onToggleHeaders:s,onApprove:n,onReject:o}){let d=aS[e.status],c=ak[e.team]??"bg-gray-100 text-gray-700";return(0,l.jsxs)("div",{className:`bg-white border rounded-lg p-4 transition-all ${t?"border-blue-400 ring-1 ring-blue-200":"border-gray-200"}`,children:[(0,l.jsxs)("div",{className:"flex items-start justify-between gap-4",children:[(0,l.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,l.jsxs)("div",{className:"flex items-center gap-2 mb-1.5 flex-wrap",children:[(0,l.jsxs)("span",{className:`text-xs font-medium px-2 py-0.5 rounded-full ${c}`,children:["Team: ",e.team]}),(0,l.jsxs)("span",{className:`inline-flex items-center gap-1.5 text-xs font-medium px-2 py-0.5 rounded-full ${d.bg} ${d.text}`,children:[(0,l.jsx)("span",{className:`w-1.5 h-1.5 rounded-full ${d.dot}`}),d.label]})]}),(0,l.jsx)("h3",{className:"text-sm font-semibold text-gray-900 mb-1",children:e.name}),(0,l.jsx)("p",{className:"text-xs text-gray-500 mb-2 line-clamp-1",children:e.description}),(0,l.jsxs)("div",{className:"flex items-center gap-1.5 mb-2",children:[(0,l.jsx)(ag.ServerIcon,{className:"h-3.5 w-3.5 text-gray-400 flex-shrink-0"}),(0,l.jsx)("code",{className:"text-xs text-gray-500 font-mono truncate",children:e.endpoint})]}),(0,l.jsxs)("div",{className:"flex items-center gap-4 text-xs text-gray-500",children:[(0,l.jsxs)("span",{children:["Model: ",(0,l.jsx)("span",{className:"font-medium text-gray-700",children:e.model})]}),(0,l.jsxs)("span",{children:["Submitted: ",(0,l.jsx)("span",{className:"font-medium text-gray-700",children:e.submittedAt})]})]})]}),(0,l.jsxs)("div",{className:"flex flex-col items-end gap-2 flex-shrink-0",children:[(0,l.jsxs)("div",{className:"flex items-center gap-2",children:[(0,l.jsx)("span",{className:"text-xs text-gray-500 whitespace-nowrap",children:"Forward API Key"}),(0,l.jsx)(aA,{enabled:e.forwardKey,onToggle:i})]}),(0,l.jsxs)("div",{className:"flex items-center gap-2 mt-1",children:[(0,l.jsx)("button",{type:"button",onClick:r,className:"text-xs border border-gray-300 text-gray-600 hover:bg-gray-50 px-3 py-1.5 rounded-md transition-colors font-medium",children:t?"Close":"Review"}),"pending"===e.status&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("button",{type:"button",onClick:n,className:"text-xs bg-green-500 hover:bg-green-600 text-white px-3 py-1.5 rounded-md transition-colors font-medium",children:"Approve"}),(0,l.jsx)("button",{type:"button",onClick:o,className:"text-xs border border-red-300 text-red-600 hover:bg-red-50 px-3 py-1.5 rounded-md transition-colors font-medium",children:"Reject"})]})]})]})]}),(0,l.jsxs)("div",{className:"mt-3 pt-3 border-t border-gray-100",children:[(0,l.jsxs)("button",{type:"button",onClick:s,className:"flex items-center gap-1.5 text-xs text-gray-500 hover:text-gray-700 transition-colors",children:[a?(0,l.jsx)(ac.ChevronUpIcon,{className:"h-3.5 w-3.5"}):(0,l.jsx)(ad.ChevronDownIcon,{className:"h-3.5 w-3.5"}),"Static headers",e.customHeaders.length>0&&(0,l.jsx)("span",{className:"ml-1 bg-gray-100 text-gray-600 rounded-full px-1.5 py-0.5 text-xs",children:e.customHeaders.length})]}),a&&(0,l.jsx)("div",{className:"mt-2",children:0===e.customHeaders.length?(0,l.jsx)("p",{className:"text-xs text-gray-400 italic",children:"No static headers configured."}):(0,l.jsx)("div",{className:"space-y-1",children:e.customHeaders.map((e,t)=>(0,l.jsxs)("div",{className:"flex items-center gap-2 text-xs font-mono",children:[(0,l.jsx)("span",{className:"text-gray-500 bg-gray-50 border border-gray-200 rounded px-2 py-0.5",children:e.key}),(0,l.jsx)("span",{className:"text-gray-400",children:":"}),(0,l.jsx)("span",{className:"text-gray-700 bg-gray-50 border border-gray-200 rounded px-2 py-0.5",children:e.value})]},`${e.key}-${t}`))})})]})]})}function aP({label:e,children:t}){return(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"text-xs font-semibold text-gray-500 mb-1",children:e}),(0,l.jsx)("div",{children:t})]})}function aT({guardrail:e,onClose:t,onApprove:a,onReject:i,onToggleForwardKey:s,onUpdateCustomHeaders:n,onUpdateExtraHeaders:o}){let[d,c]=(0,r.useState)(!1),[m,u]=(0,r.useState)(""),[p,g]=(0,r.useState)(""),[x,h]=(0,r.useState)(""),f=aS[e.status],y=ak[e.team]??"bg-gray-100 text-gray-700";return(0,l.jsx)("div",{className:"w-96 flex-shrink-0 bg-white overflow-auto",children:(0,l.jsxs)("div",{className:"p-5",children:[(0,l.jsxs)("div",{className:"flex items-start justify-between mb-4",children:[(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex items-center gap-2 mb-1",children:[(0,l.jsxs)("span",{className:`text-xs font-medium px-2 py-0.5 rounded-full ${y}`,children:["Team: ",e.team]}),(0,l.jsxs)("span",{className:`inline-flex items-center gap-1.5 text-xs font-medium px-2 py-0.5 rounded-full ${f.bg} ${f.text}`,children:[(0,l.jsx)("span",{className:`w-1.5 h-1.5 rounded-full ${f.dot}`}),f.label]})]}),(0,l.jsx)("h2",{className:"text-base font-semibold text-gray-900",children:e.name}),(0,l.jsxs)("p",{className:"text-xs text-gray-500 mt-0.5",children:["Submitted by ",e.submittedBy," on ",e.submittedAt]})]}),(0,l.jsx)("button",{type:"button",onClick:t,className:"text-gray-400 hover:text-gray-600 transition-colors","aria-label":"Close detail panel",children:(0,l.jsx)(am.XIcon,{className:"h-4 w-4"})})]}),(0,l.jsx)("p",{className:"text-sm text-gray-600 mb-5",children:e.description}),(0,l.jsxs)("div",{className:"space-y-4",children:[(0,l.jsx)(aP,{label:"Endpoint",children:(0,l.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,l.jsx)("code",{className:"text-xs font-mono text-gray-700 break-all",children:e.endpoint}),(0,l.jsx)("a",{href:e.endpoint,target:"_blank",rel:"noopener noreferrer",className:"text-gray-400 hover:text-blue-500 flex-shrink-0",children:(0,l.jsx)(au.ExternalLinkIcon,{className:"h-3.5 w-3.5"})})]})}),(0,l.jsx)(aP,{label:"Method",children:(0,l.jsx)("span",{className:"text-xs font-mono font-medium text-gray-700 bg-gray-100 px-2 py-0.5 rounded",children:e.method})}),(0,l.jsxs)("div",{className:"border border-blue-100 bg-blue-50 rounded-lg p-3",children:[(0,l.jsxs)("div",{className:"flex items-center justify-between mb-2",children:[(0,l.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,l.jsx)(ap.KeyIcon,{className:"h-3.5 w-3.5 text-blue-500"}),(0,l.jsx)("span",{className:"text-xs font-semibold text-blue-800",children:"Forward LiteLLM API Key"})]}),(0,l.jsx)(aA,{enabled:e.forwardKey,onToggle:s})]}),(0,l.jsxs)("p",{className:"text-xs text-blue-700 leading-relaxed",children:["When enabled, the caller's LiteLLM API key is forwarded as an"," ",(0,l.jsx)("code",{className:"font-mono bg-blue-100 px-1 rounded",children:"Authorization"})," header to your guardrail endpoint. This allows your guardrail to authenticate model calls using the original caller's credentials."]})]}),(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex items-center gap-1.5 mb-2",children:[(0,l.jsx)("span",{className:"text-xs font-semibold text-gray-700",children:"Static headers"}),e.customHeaders.length>0&&(0,l.jsx)("span",{className:"bg-gray-100 text-gray-600 rounded-full px-1.5 py-0.5 text-xs",children:e.customHeaders.length})]}),(0,l.jsx)("p",{className:"text-xs text-gray-400 mb-2",children:"Sent with every request to the guardrail."}),0===e.customHeaders.length?(0,l.jsx)("p",{className:"text-xs text-gray-400 italic mb-2",children:"No static headers configured."}):(0,l.jsx)("ul",{className:"list-none space-y-1 mb-2",children:e.customHeaders.map((t,a)=>(0,l.jsxs)("li",{className:"flex items-center justify-between gap-2 text-xs font-mono bg-gray-50 border border-gray-200 rounded px-2 py-1.5",children:[(0,l.jsxs)("span",{className:"text-gray-700 truncate",children:[t.key,": ",t.value]}),(0,l.jsx)("button",{type:"button",onClick:()=>n(e.customHeaders.filter((e,t)=>t!==a)),className:"text-gray-400 hover:text-red-600 flex-shrink-0","aria-label":`Remove ${t.key}`,children:(0,l.jsx)(am.XIcon,{className:"h-3.5 w-3.5"})})]},`${t.key}-${a}`))}),(0,l.jsxs)("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-end",children:[(0,l.jsx)("input",{type:"text",value:p,onChange:e=>g(e.target.value),placeholder:"Header name (e.g. X-API-Key)",className:"flex-1 min-w-0 text-xs font-mono border border-gray-200 rounded px-2 py-1.5 text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-blue-500",onKeyDown:t=>{if("Enter"===t.key){t.preventDefault();let a=p.trim(),l=x.trim();a&&!e.customHeaders.some(e=>e.key.toLowerCase()===a.toLowerCase())&&(n([...e.customHeaders,{key:a,value:l}]),g(""),h(""))}}}),(0,l.jsx)("input",{type:"text",value:x,onChange:e=>h(e.target.value),placeholder:"Value",className:"flex-1 min-w-0 text-xs font-mono border border-gray-200 rounded px-2 py-1.5 text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-blue-500",onKeyDown:t=>{if("Enter"===t.key){t.preventDefault();let a=p.trim(),l=x.trim();a&&!e.customHeaders.some(e=>e.key.toLowerCase()===a.toLowerCase())&&(n([...e.customHeaders,{key:a,value:l}]),g(""),h(""))}}}),(0,l.jsx)("button",{type:"button",onClick:()=>{let t=p.trim(),a=x.trim();t&&!e.customHeaders.some(e=>e.key.toLowerCase()===t.toLowerCase())&&(n([...e.customHeaders,{key:t,value:a}]),g(""),h(""))},className:"text-xs font-medium text-blue-600 hover:text-blue-700 border border-blue-200 bg-blue-50 hover:bg-blue-100 px-2 py-1.5 rounded transition-colors flex-shrink-0",children:"Add"})]})]}),(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex items-center gap-1.5 mb-2",children:[(0,l.jsx)("span",{className:"text-xs font-semibold text-gray-700",children:"Forward client headers"}),e.extraHeaders.length>0&&(0,l.jsx)("span",{className:"bg-gray-100 text-gray-600 rounded-full px-1.5 py-0.5 text-xs",children:e.extraHeaders.length})]}),(0,l.jsx)("p",{className:"text-xs text-gray-400 mb-2",children:"Allowed header names to forward from the client request to the guardrail (e.g. x-request-id)."}),0===e.extraHeaders.length?(0,l.jsx)("p",{className:"text-xs text-gray-400 italic mb-2",children:"No forward client headers configured."}):(0,l.jsx)("ul",{className:"list-none space-y-1 mb-2",children:e.extraHeaders.map((t,a)=>(0,l.jsxs)("li",{className:"flex items-center justify-between gap-2 text-xs font-mono bg-gray-50 border border-gray-200 rounded px-2 py-1.5",children:[(0,l.jsx)("span",{className:"text-gray-700 truncate",children:t}),(0,l.jsx)("button",{type:"button",onClick:()=>o(e.extraHeaders.filter((e,t)=>t!==a)),className:"text-gray-400 hover:text-red-600 flex-shrink-0","aria-label":`Remove ${t}`,children:(0,l.jsx)(am.XIcon,{className:"h-3.5 w-3.5"})})]},`${t}-${a}`))}),(0,l.jsxs)("div",{className:"flex gap-2",children:[(0,l.jsx)("input",{type:"text",value:m,onChange:e=>u(e.target.value),placeholder:"e.g. x-request-id",className:"flex-1 min-w-0 text-xs font-mono border border-gray-200 rounded px-2 py-1.5 text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-blue-500",onKeyDown:t=>{if("Enter"===t.key){t.preventDefault();let a=m.trim().toLowerCase();a&&!e.extraHeaders.map(e=>e.toLowerCase()).includes(a)&&(o([...e.extraHeaders,a]),u(""))}}}),(0,l.jsx)("button",{type:"button",onClick:()=>{let t=m.trim().toLowerCase();t&&!e.extraHeaders.map(e=>e.toLowerCase()).includes(t)&&(o([...e.extraHeaders,t]),u(""))},className:"text-xs font-medium text-blue-600 hover:text-blue-700 border border-blue-200 bg-blue-50 hover:bg-blue-100 px-2 py-1.5 rounded transition-colors",children:"Add"})]})]}),(0,l.jsxs)("div",{className:"border border-gray-200 rounded-lg overflow-hidden",children:[(0,l.jsxs)("button",{type:"button",onClick:()=>c(!d),className:"w-full flex items-center justify-between px-3 py-2 text-left text-xs font-semibold text-gray-700 bg-gray-50 hover:bg-gray-100 transition-colors",children:[(0,l.jsx)("span",{children:"Equivalent config"}),d?(0,l.jsx)(ac.ChevronUpIcon,{className:"h-3.5 w-3.5 text-gray-500"}):(0,l.jsx)(ad.ChevronDownIcon,{className:"h-3.5 w-3.5 text-gray-500"})]}),d&&(0,l.jsx)("pre",{className:"p-3 text-xs font-mono text-gray-700 bg-white border-t border-gray-200 overflow-x-auto whitespace-pre-wrap break-all",children:function(e){let t=["litellm_settings:"," guardrails:",` - guardrail_name: "${e.name.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`," litellm_params:",` guardrail: ${e.guardrailType??"generic_guardrail_api"}`,` mode: ${e.mode??"pre_call"} # or post_call, during_call`,` api_base: ${e.endpoint||"https://your-guardrail-api.com"}`," api_key: os.environ/YOUR_GUARDRAIL_API_KEY # optional",` unreachable_fallback: ${e.unreachable_fallback??"fail_closed"} # default: fail_closed. Set to fail_open to proceed if the guardrail endpoint is unreachable.`,` forward_api_key: ${e.forwardKey}`];if(e.model&&"—"!==e.model&&t.push(` model: "${e.model}" # LLM model name sent to the guardrail for context`),e.customHeaders.length>0)for(let a of(t.push(" headers: # static headers (sent with every request)"),e.customHeaders))t.push(` ${a.key}: "${String(a.value).replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`);if(e.extraHeaders.length>0)for(let a of(t.push(" extra_headers: # forward these client request headers to the guardrail"),e.extraHeaders))t.push(` - ${a}`);if(e.additionalProviderParams&&Object.keys(e.additionalProviderParams).length>0)for(let[a,l]of(t.push(" additional_provider_specific_params:"),Object.entries(e.additionalProviderParams))){let e="string"==typeof l?`"${l}"`:String(l);t.push(` ${a}: ${e}`)}return t.join("\n")}(e)})]}),(0,l.jsxs)("div",{className:"flex items-start gap-2 bg-gray-50 border border-gray-200 rounded-lg p-3",children:[(0,l.jsx)(ah.InfoIcon,{className:"h-3.5 w-3.5 text-gray-400 flex-shrink-0 mt-0.5"}),(0,l.jsxs)("p",{className:"text-xs text-gray-500 leading-relaxed",children:["This guardrail runs on a separate instance. It receives the user request and forwards the result to the next step in the pipeline. See"," ",(0,l.jsx)("a",{href:"https://docs.litellm.ai/docs/adding_provider/generic_guardrail_api",target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline",children:"LiteLLM Generic Guardrail API docs"})," ","for configuration details."]})]})]}),(0,l.jsxs)("div",{className:"mt-5 pt-4 border-t border-gray-100 space-y-2",children:[(0,l.jsxs)("button",{type:"button",className:"w-full flex items-center justify-center gap-2 border border-gray-300 text-gray-700 hover:bg-gray-50 text-sm font-medium py-2 rounded-md transition-colors",children:[(0,l.jsx)(au.ExternalLinkIcon,{className:"h-4 w-4"}),"Test Endpoint"]}),"pending"===e.status&&(0,l.jsxs)("div",{className:"flex gap-2",children:[(0,l.jsxs)("button",{type:"button",onClick:a,className:"flex-1 flex items-center justify-center gap-1.5 bg-green-500 hover:bg-green-600 text-white text-sm font-medium py-2 rounded-md transition-colors",children:[(0,l.jsx)(tw.CheckIcon,{className:"h-4 w-4"}),"Approve"]}),(0,l.jsxs)("button",{type:"button",onClick:i,className:"flex-1 flex items-center justify-center gap-1.5 border border-red-300 text-red-600 hover:bg-red-50 text-sm font-medium py-2 rounded-md transition-colors",children:[(0,l.jsx)(am.XIcon,{className:"h-4 w-4"}),"Reject"]})]})]})]})})}function aL({action:e,guardrailName:t,onConfirm:a,onCancel:r}){let i="approve"===e;return(0,l.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50",children:(0,l.jsxs)("div",{className:"bg-white rounded-xl shadow-xl p-6 max-w-sm w-full mx-4",children:[(0,l.jsx)("div",{className:`w-10 h-10 rounded-full flex items-center justify-center mb-4 ${i?"bg-green-100":"bg-red-100"}`,children:i?(0,l.jsx)(tw.CheckIcon,{className:"h-5 w-5 text-green-600"}):(0,l.jsx)(ax.AlertCircleIcon,{className:"h-5 w-5 text-red-600"})}),(0,l.jsx)("h3",{className:"text-base font-semibold text-gray-900 mb-1",children:i?"Approve Guardrail":"Reject Guardrail"}),(0,l.jsxs)("p",{className:"text-sm text-gray-500 mb-5",children:["Are you sure you want to ",e," ",(0,l.jsxs)("span",{className:"font-medium text-gray-700",children:['"',t,'"']}),"?"," ",i?"This will make it active and available for use.":"This will mark it as rejected and notify the team."]}),(0,l.jsxs)("div",{className:"flex gap-3",children:[(0,l.jsx)("button",{type:"button",onClick:r,className:"flex-1 border border-gray-300 text-gray-700 hover:bg-gray-50 text-sm font-medium py-2 rounded-md transition-colors",children:"Cancel"}),(0,l.jsx)("button",{type:"button",onClick:a,className:`flex-1 text-white text-sm font-medium py-2 rounded-md transition-colors ${i?"bg-green-500 hover:bg-green-600":"bg-red-500 hover:bg-red-600"}`,children:i?"Approve":"Reject"})]})]})})}function aB({accessToken:e}){let[t,a]=(0,r.useState)([]),[i,s]=(0,r.useState)({total:0,pending_review:0,active:0,rejected:0}),[n,o]=(0,r.useState)(""),[d,c]=(0,r.useState)("all"),[h,f]=(0,r.useState)(null),[j,_]=(0,r.useState)(new Set),[b,v]=(0,r.useState)(null),[w,N]=(0,r.useState)(!0),[C,S]=(0,r.useState)(null),[k,I]=(0,r.useState)(""),[A,O]=(0,r.useState)(!1),[P]=u.Form.useForm(),T=(()=>{let{accessToken:e}=(0,ab.default)(),t=(0,aj.useQueryClient)();return(0,ay.useMutation)({mutationFn:async t=>{if(!e)throw Error("Access token is required");return aw(e,t)},onSuccess:()=>{t.invalidateQueries({queryKey:aN.all})}})})();(0,r.useEffect)(()=>{let e=setTimeout(()=>I(n),300);return()=>clearTimeout(e)},[n]);let L=(0,r.useCallback)(async()=>{if(!e)return void N(!1);N(!0),S(null);try{let t="all"===d?void 0:"pending"===d?"pending_review":d,l=await (0,m.listGuardrailSubmissions)(e,{status:t,search:k.trim()||void 0});a(l.submissions.map(aC)),s(l.summary)}catch(e){S(e instanceof Error?e.message:"Failed to load submissions"),a([])}finally{N(!1)}},[e,d,k]);(0,r.useEffect)(()=>{L()},[L]);let B=t.find(e=>e.id===h)??null,F=i.total,$=i.pending_review,E=i.active,M=i.rejected;async function R(l){if(!e)return;let r=t.find(e=>e.id===l);if(!r)return;let i=!r.forwardKey;try{await (0,m.updateGuardrailCall)(e,l,{litellm_params:{forward_api_key:i}}),a(e=>e.map(e=>e.id===l?{...e,forwardKey:i}:e)),y.default.success(i?"Forward API key enabled":"Forward API key disabled")}catch{y.default.fromBackend("Failed to update forward API key")}}async function G(t,l){if(!e)return;let r={};for(let{key:e,value:t}of l)e.trim()&&(r[e.trim()]=t);try{await (0,m.updateGuardrailCall)(e,t,{litellm_params:{headers:r}}),a(e=>e.map(e=>e.id===t?{...e,customHeaders:l.filter(e=>e.key.trim())}:e)),y.default.success("Static headers updated")}catch{y.default.fromBackend("Failed to update static headers")}}async function z(t,l){if(e)try{await (0,m.updateGuardrailCall)(e,t,{litellm_params:{extra_headers:l}}),a(e=>e.map(e=>e.id===t?{...e,extraHeaders:l}:e)),y.default.success("Forward client headers updated")}catch{y.default.fromBackend("Failed to update forward client headers")}}async function D(t){if(e)try{await (0,m.approveGuardrailSubmission)(e,t),v(null),h===t&&f(null),await L(),y.default.success("Guardrail approved")}catch{y.default.fromBackend("Failed to approve guardrail")}}async function K(t){if(e)try{await (0,m.rejectGuardrailSubmission)(e,t),v(null),h===t&&f(null),await L(),y.default.success("Guardrail rejected")}catch{y.default.fromBackend("Failed to reject guardrail")}}return(0,l.jsxs)("div",{className:"flex h-full",children:[(0,l.jsxs)("div",{className:`flex-1 min-w-0 p-6 overflow-auto ${B?"border-r border-gray-200":""}`,children:[(0,l.jsxs)("div",{className:"grid grid-cols-4 gap-4 mb-6",children:[(0,l.jsx)(aI,{label:"Total Submitted",value:F,color:"text-gray-900"}),(0,l.jsx)(aI,{label:"Pending Review",value:$,color:"text-yellow-600"}),(0,l.jsx)(aI,{label:"Active",value:E,color:"text-green-600"}),(0,l.jsx)(aI,{label:"Rejected",value:M,color:"text-red-600"})]}),(0,l.jsxs)("div",{className:"flex items-center gap-3 mb-5",children:[(0,l.jsxs)("div",{className:"relative flex-1 max-w-xs",children:[(0,l.jsx)(an.SearchIcon,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400"}),(0,l.jsx)("input",{type:"text",placeholder:"Search guardrails...",value:n,onChange:e=>o(e.target.value),className:"w-full pl-9 pr-4 py-2 border border-gray-200 rounded-md text-sm text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"})]}),(0,l.jsxs)("select",{value:d,onChange:e=>c(e.target.value),className:"border border-gray-200 rounded-md px-3 py-2 text-sm text-gray-700 focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 bg-white",children:[(0,l.jsx)("option",{value:"all",children:"All Status"}),(0,l.jsx)("option",{value:"pending",children:"Pending Review"}),(0,l.jsx)("option",{value:"active",children:"Active"}),(0,l.jsx)("option",{value:"rejected",children:"Rejected"})]}),(0,l.jsxs)("button",{type:"button",onClick:()=>O(!0),className:"ml-auto flex items-center gap-2 bg-blue-500 hover:bg-blue-600 text-white text-sm font-medium px-4 py-2 rounded-md transition-colors",children:[(0,l.jsx)(ao.PlusIcon,{className:"h-4 w-4"}),"Add Guardrail"]})]}),(0,l.jsxs)("div",{className:"space-y-3",children:[w&&(0,l.jsx)("div",{className:"text-center py-12 text-gray-500 text-sm",children:"Loading submissions…"}),C&&(0,l.jsx)("div",{className:"text-center py-12 text-red-600 text-sm",children:C}),!w&&!C&&0===t.length&&(0,l.jsx)("div",{className:"text-center py-12 text-gray-400 text-sm",children:"No guardrails match your filters."}),!w&&!C&&t.map(e=>(0,l.jsx)(aO,{guardrail:e,isSelected:h===e.id,isHeadersExpanded:j.has(e.id),onSelect:()=>f(h===e.id?null:e.id),onToggleForwardKey:()=>R(e.id),onToggleHeaders:()=>{var t;return t=e.id,void _(e=>{let a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a})},onApprove:()=>v({id:e.id,action:"approve"}),onReject:()=>v({id:e.id,action:"reject"})},e.id))]})]}),B&&(0,l.jsx)(aT,{guardrail:B,onClose:()=>f(null),onApprove:()=>v({id:B.id,action:"approve"}),onReject:()=>v({id:B.id,action:"reject"}),onToggleForwardKey:()=>R(B.id),onUpdateCustomHeaders:e=>G(B.id,e),onUpdateExtraHeaders:e=>z(B.id,e)}),b&&(0,l.jsx)(aL,{action:b.action,guardrailName:t.find(e=>e.id===b.id)?.name??"",onConfirm:()=>"approve"===b.action?D(b.id):K(b.id),onCancel:()=>v(null)}),(0,l.jsxs)(g.Modal,{title:"Submit Guardrail for Review",open:A,onCancel:()=>{O(!1),P.resetFields()},onOk:()=>P.submit(),okText:"Submit for Review",children:[(0,l.jsx)("div",{className:"rounded-md bg-blue-50 border border-blue-200 px-4 py-3 text-sm text-blue-800 mb-4",children:"Your guardrail will be sent for admin review before it becomes active."}),(0,l.jsxs)(u.Form,{form:P,layout:"vertical",initialValues:{mode:"pre_call"},onFinish:async e=>{let t={...e.extra_litellm_params?JSON.parse(e.extra_litellm_params):{},guardrail:"generic_guardrail_api",mode:e.mode,api_base:e.api_base};try{await T.mutateAsync({team_id:e.team_id,guardrail_name:e.guardrail_name,litellm_params:t,guardrail_info:e.guardrail_info?JSON.parse(e.guardrail_info):void 0}),y.default.success("Guardrail submitted for review"),O(!1),P.resetFields(),L()}catch{}},children:[(0,l.jsx)(u.Form.Item,{label:"Team",name:"team_id",rules:[{required:!0,message:"Select a team"}],children:(0,l.jsx)(af.default,{})}),(0,l.jsx)(u.Form.Item,{label:"Guardrail Name",name:"guardrail_name",rules:[{required:!0,message:"Enter a guardrail name"}],children:(0,l.jsx)(p.Input,{placeholder:"e.g. pii-detection"})}),(0,l.jsx)(u.Form.Item,{label:"Mode",name:"mode",rules:[{required:!0,message:"Select a mode"}],children:(0,l.jsxs)(x.Select,{children:[(0,l.jsx)(x.Select.Option,{value:"pre_call",children:"Pre Call"}),(0,l.jsx)(x.Select.Option,{value:"post_call",children:"Post Call"}),(0,l.jsx)(x.Select.Option,{value:"during_call",children:"During Call"})]})}),(0,l.jsx)(u.Form.Item,{label:"API Base URL",name:"api_base",rules:[{required:!0,message:"Enter the API base URL"},{type:"url",message:"Must be a valid URL"}],children:(0,l.jsx)(p.Input,{placeholder:"https://your-guardrail-api.com/v1/check",className:"font-mono"})}),(0,l.jsx)(u.Form.Item,{label:"Additional litellm_params (optional)",name:"extra_litellm_params",tooltip:"JSON object merged into litellm_params. e.g. forward_api_key, headers, model, unreachable_fallback",rules:[{validator:(e,t)=>{if(!t)return Promise.resolve();try{let e=JSON.parse(t);if("object"!=typeof e||Array.isArray(e))return Promise.reject("Must be a JSON object");return Promise.resolve()}catch{return Promise.reject("Invalid JSON")}}}],children:(0,l.jsx)(p.Input.TextArea,{rows:3,className:"font-mono text-xs",placeholder:'{"forward_api_key": true, "headers": {"X-Custom": "value"}}'})}),(0,l.jsx)(u.Form.Item,{label:"Guardrail Info (optional)",name:"guardrail_info",rules:[{validator:(e,t)=>{if(!t)return Promise.resolve();try{return JSON.parse(t),Promise.resolve()}catch{return Promise.reject("Invalid JSON")}}}],children:(0,l.jsx)(p.Input.TextArea,{rows:3,className:"font-mono text-xs",placeholder:'{"description": "Detects PII in requests"}'})})]})]})]})}let aF=({accessToken:e,userRole:t})=>{let[a,u]=(0,r.useState)([]),[p,g]=(0,r.useState)(!1),[x,h]=(0,r.useState)(!1),[f,j]=(0,r.useState)(!1),[_,b]=(0,r.useState)(!1),[v,w]=(0,r.useState)(null),[N,C]=(0,r.useState)(!1),[S,k]=(0,r.useState)(null),I=!!t&&(0,tp.isAdminRole)(t),A=async()=>{if(e){j(!0);try{let t=await (0,m.getGuardrailsList)(e);console.log(`guardrails: ${JSON.stringify(t)}`),u(t.guardrails)}catch(e){console.error("Error fetching guardrails:",e)}finally{j(!1)}}};(0,r.useEffect)(()=>{A()},[e]);let O=()=>{A()},P=async()=>{if(v&&e){b(!0);try{await (0,m.deleteGuardrailCall)(e,v.guardrail_id),y.default.success(`Guardrail "${v.guardrail_name}" deleted successfully`),await A()}catch(e){console.error("Error deleting guardrail:",e),y.default.fromBackend("Failed to delete guardrail")}finally{b(!1),C(!1),w(null)}}},T=v&&v.litellm_params?ep(v.litellm_params.guardrail).displayName:void 0;return(0,l.jsx)("div",{className:"w-full mx-auto flex-auto overflow-y-auto m-8 p-2",children:(0,l.jsx)(n.Tabs,{defaultActiveKey:"guardrails",items:[...I?[{key:"garden",label:"Guardrail Garden",children:(0,l.jsx)(as,{accessToken:e,onGuardrailCreated:O})},{key:"guardrails",label:"Guardrails",children:(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("div",{className:"flex justify-between items-center mb-4",children:(0,l.jsx)(s.Dropdown,{menu:{items:[{key:"provider",icon:(0,l.jsx)(d.PlusOutlined,{}),label:"Add Provider Guardrail",onClick:()=>{S&&k(null),g(!0)}},{key:"custom_code",icon:(0,l.jsx)(c.CodeOutlined,{}),label:"Create Custom Code Guardrail",onClick:()=>{S&&k(null),h(!0)}}]},trigger:["click"],disabled:!e,children:(0,l.jsxs)(i.Button,{disabled:!e,children:["+ Add New Guardrail ",(0,l.jsx)(o.DownOutlined,{className:"ml-2"})]})})}),S?(0,l.jsx)(tU,{guardrailId:S,onClose:()=>k(null),accessToken:e,isAdmin:I}):(0,l.jsx)(tu,{guardrailsList:a,isLoading:f,onDeleteClick:(e,t)=>{w(a.find(t=>t.guardrail_id===e)||null),C(!0)},accessToken:e,onGuardrailUpdated:A,isAdmin:I,onGuardrailClick:e=>k(e)}),(0,l.jsx)(e0,{visible:p,onClose:()=>{g(!1)},accessToken:e,onSuccess:O}),(0,l.jsx)(tJ,{visible:x,onClose:()=>{h(!1)},accessToken:e,onSuccess:O}),(0,l.jsx)(t6.default,{isOpen:N,title:"Delete Guardrail",message:`Are you sure you want to delete guardrail: ${v?.guardrail_name}? This action cannot be undone.`,resourceInformationTitle:"Guardrail Information",resourceInformation:[{label:"Name",value:v?.guardrail_name},{label:"ID",value:v?.guardrail_id,code:!0},{label:"Provider",value:T},{label:"Mode",value:v?.litellm_params.mode},{label:"Default On",value:v?.litellm_params.default_on?"Yes":"No"}],onCancel:()=>{C(!1),w(null)},onOk:P,confirmLoading:_})]})},{key:"playground",label:"Test Playground",disabled:!e,children:(0,l.jsx)(t8,{guardrailsList:a,isLoading:f,accessToken:e,onClose:()=>{}})}]:[],{key:"submitted",label:"Submitted Guardrails",children:(0,l.jsx)(aB,{accessToken:e})}]})})};function a$(){let{accessToken:e,userRole:t}=(0,ab.default)();return(0,l.jsx)(aF,{accessToken:e,userRole:t})}e.s(["default",()=>a$],509345)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/023c1ee26a3e0735.js b/litellm/proxy/_experimental/out/_next/static/chunks/023c1ee26a3e0735.js new file mode 100644 index 00000000000..37394c8985f --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/023c1ee26a3e0735.js @@ -0,0 +1 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,916925,e=>{"use strict";var r,t=((r={}).A2A_Agent="A2A Agent",r.AI21="Ai21",r.AI21_CHAT="Ai21 Chat",r.AIML="AI/ML API",r.AIOHTTP_OPENAI="Aiohttp Openai",r.Anthropic="Anthropic",r.ANTHROPIC_TEXT="Anthropic Text",r.AssemblyAI="AssemblyAI",r.AUTO_ROUTER="Auto Router",r.Bedrock="Amazon Bedrock",r.BedrockMantle="Amazon Bedrock Mantle",r.SageMaker="AWS SageMaker",r.Azure="Azure",r.Azure_AI_Studio="Azure AI Foundry (Studio)",r.AZURE_TEXT="Azure Text",r.BASETEN="Baseten",r.BYTEZ="Bytez",r.Cerebras="Cerebras",r.CLARIFAI="Clarifai",r.CLOUDFLARE="Cloudflare",r.CODESTRAL="Codestral",r.Cohere="Cohere",r.COHERE_CHAT="Cohere Chat",r.COMETAPI="Cometapi",r.COMPACTIFAI="Compactifai",r.Cursor="Cursor",r.Dashscope="Dashscope",r.Databricks="Databricks (Qwen API)",r.DATAROBOT="Datarobot",r.DeepInfra="DeepInfra",r.Deepgram="Deepgram",r.Deepseek="Deepseek",r.DOCKER_MODEL_RUNNER="Docker Model Runner",r.DOTPROMPT="Dotprompt",r.ElevenLabs="ElevenLabs",r.EMPOWER="Empower",r.FalAI="Fal AI",r.FEATHERLESS_AI="Featherless Ai",r.FireworksAI="Fireworks AI",r.FRIENDLIAI="Friendliai",r.GALADRIEL="Galadriel",r.GITHUB_COPILOT="Github Copilot",r.Google_AI_Studio="Google AI Studio",r.GradientAI="GradientAI",r.Groq="Groq",r.HEROKU="Heroku",r.Hosted_Vllm="vllm",r.HUGGINGFACE="Huggingface",r.HYPERBOLIC="Hyperbolic",r.Infinity="Infinity",r.JinaAI="Jina AI",r.LAMBDA_AI="Lambda Ai",r.LEMONADE="Lemonade",r.LLAMAFILE="Llamafile",r.LM_STUDIO="Lm Studio",r.LLAMA="Meta Llama",r.MARITALK="Maritalk",r.MiniMax="MiniMax",r.MistralAI="Mistral AI",r.MOONSHOT="Moonshot",r.MORPH="Morph",r.NEBIUS="Nebius",r.NLP_CLOUD="Nlp Cloud",r.NOVITA="Novita",r.NSCALE="Nscale",r.NVIDIA_NIM="Nvidia Nim",r.Ollama="Ollama",r.OLLAMA_CHAT="Ollama Chat",r.OOBABOOGA="Oobabooga",r.OpenAI="OpenAI",r.OPENAI_LIKE="Openai Like",r.OpenAI_Compatible="OpenAI-Compatible Endpoints (Together AI, etc.)",r.OpenAI_Text="OpenAI Text Completion",r.OpenAI_Text_Compatible="OpenAI-Compatible Text Completion Models (Together AI, etc.)",r.Openrouter="Openrouter",r.Oracle="Oracle Cloud Infrastructure (OCI)",r.OVHCLOUD="Ovhcloud",r.Perplexity="Perplexity",r.PETALS="Petals",r.PG_VECTOR="Pg Vector",r.PREDIBASE="Predibase",r.RECRAFT="Recraft",r.REPLICATE="Replicate",r.RunwayML="RunwayML",r.SAGEMAKER_LEGACY="Sagemaker",r.Sambanova="Sambanova",r.SAP="SAP Generative AI Hub",r.Snowflake="Snowflake",r.Soniox="Soniox",r.TEXT_COMPLETION_CODESTRAL="Text-Completion-Codestral",r.TogetherAI="TogetherAI",r.TOPAZ="Topaz",r.Triton="Triton",r.V0="V0",r.VERCEL_AI_GATEWAY="Vercel Ai Gateway",r.Vertex_AI="Vertex AI (Anthropic, Gemini, etc.)",r.VERTEX_AI_BETA="Vertex Ai Beta",r.VLLM="Vllm",r.VolcEngine="VolcEngine",r.Voyage="Voyage AI",r.WANDB="Wandb",r.WATSONX="Watsonx",r.WATSONX_TEXT="Watsonx Text",r.xAI="xAI",r.XINFERENCE="Xinference",r.ZAI="Z.AI (Zhipu AI)",r);let a={A2A_Agent:"a2a_agent",AI21:"ai21",AI21_CHAT:"ai21_chat",AIML:"aiml",AIOHTTP_OPENAI:"aiohttp_openai",Anthropic:"anthropic",ANTHROPIC_TEXT:"anthropic_text",AssemblyAI:"assemblyai",AUTO_ROUTER:"auto_router",Azure:"azure",Azure_AI_Studio:"azure_ai",AZURE_TEXT:"azure_text",BASETEN:"baseten",Bedrock:"bedrock",BedrockMantle:"bedrock_mantle",BYTEZ:"bytez",Cerebras:"cerebras",CLARIFAI:"clarifai",CLOUDFLARE:"cloudflare",CODESTRAL:"codestral",Cohere:"cohere",COHERE_CHAT:"cohere_chat",COMETAPI:"cometapi",COMPACTIFAI:"compactifai",Cursor:"cursor",Dashscope:"dashscope",Databricks:"databricks",DATAROBOT:"datarobot",DeepInfra:"deepinfra",Deepgram:"deepgram",Deepseek:"deepseek",DOCKER_MODEL_RUNNER:"docker_model_runner",DOTPROMPT:"dotprompt",ElevenLabs:"elevenlabs",EMPOWER:"empower",FalAI:"fal_ai",FEATHERLESS_AI:"featherless_ai",FireworksAI:"fireworks_ai",FRIENDLIAI:"friendliai",GALADRIEL:"galadriel",GITHUB_COPILOT:"github_copilot",Google_AI_Studio:"gemini",GradientAI:"gradient_ai",Groq:"groq",HEROKU:"heroku",Hosted_Vllm:"hosted_vllm",HUGGINGFACE:"huggingface",HYPERBOLIC:"hyperbolic",Infinity:"infinity",JinaAI:"jina_ai",LAMBDA_AI:"lambda_ai",LEMONADE:"lemonade",LLAMAFILE:"llamafile",LLAMA:"meta_llama",LM_STUDIO:"lm_studio",MARITALK:"maritalk",MiniMax:"minimax",MistralAI:"mistral",MOONSHOT:"moonshot",MORPH:"morph",NEBIUS:"nebius",NLP_CLOUD:"nlp_cloud",NOVITA:"novita",NSCALE:"nscale",NVIDIA_NIM:"nvidia_nim",Ollama:"ollama",OLLAMA_CHAT:"ollama_chat",OOBABOOGA:"oobabooga",OpenAI:"openai",OPENAI_LIKE:"openai_like",OpenAI_Compatible:"openai",OpenAI_Text:"text-completion-openai",OpenAI_Text_Compatible:"text-completion-openai",Openrouter:"openrouter",Oracle:"oci",OVHCLOUD:"ovhcloud",Perplexity:"perplexity",PETALS:"petals",PG_VECTOR:"pg_vector",PREDIBASE:"predibase",RECRAFT:"recraft",REPLICATE:"replicate",RunwayML:"runwayml",SAGEMAKER_LEGACY:"sagemaker",SageMaker:"sagemaker_chat",Sambanova:"sambanova",SAP:"sap",Snowflake:"snowflake",Soniox:"soniox",TEXT_COMPLETION_CODESTRAL:"text-completion-codestral",TogetherAI:"together_ai",TOPAZ:"topaz",Triton:"triton",V0:"v0",VERCEL_AI_GATEWAY:"vercel_ai_gateway",Vertex_AI:"vertex_ai",VERTEX_AI_BETA:"vertex_ai_beta",VLLM:"vllm",VolcEngine:"volcengine",Voyage:"voyage",WANDB:"wandb",WATSONX:"watsonx",WATSONX_TEXT:"watsonx_text",xAI:"xai",XINFERENCE:"xinference",ZAI:"zai"},o="/ui/assets/logos/",l={"A2A Agent":`${o}a2a_agent.png`,Ai21:`${o}ai21.svg`,"Ai21 Chat":`${o}ai21.svg`,"AI/ML API":`${o}aiml_api.svg`,"Aiohttp Openai":`${o}openai_small.svg`,Anthropic:`${o}anthropic.svg`,"Anthropic Text":`${o}anthropic.svg`,AssemblyAI:`${o}assemblyai_small.png`,Azure:`${o}microsoft_azure.svg`,"Azure AI Foundry (Studio)":`${o}microsoft_azure.svg`,"Azure Text":`${o}microsoft_azure.svg`,Baseten:`${o}baseten.svg`,"Amazon Bedrock":`${o}bedrock.svg`,"Amazon Bedrock Mantle":`${o}bedrock.svg`,"AWS SageMaker":`${o}bedrock.svg`,Cerebras:`${o}cerebras.svg`,Cloudflare:`${o}cloudflare.svg`,Codestral:`${o}mistral.svg`,Cohere:`${o}cohere.svg`,"Cohere Chat":`${o}cohere.svg`,Cometapi:`${o}cometapi.svg`,Cursor:`${o}cursor.svg`,"Databricks (Qwen API)":`${o}databricks.svg`,Dashscope:`${o}dashscope.svg`,Deepseek:`${o}deepseek.svg`,Deepgram:`${o}deepgram.png`,DeepInfra:`${o}deepinfra.png`,ElevenLabs:`${o}elevenlabs.png`,"Fal AI":`${o}fal_ai.jpg`,"Featherless Ai":`${o}featherless.svg`,"Fireworks AI":`${o}fireworks.svg`,Friendliai:`${o}friendli.svg`,"Github Copilot":`${o}github_copilot.svg`,"Google AI Studio":`${o}google.svg`,GradientAI:`${o}gradientai.svg`,Groq:`${o}groq.svg`,vllm:`${o}vllm.png`,Huggingface:`${o}huggingface.svg`,Hyperbolic:`${o}hyperbolic.svg`,Infinity:`${o}infinity.png`,"Jina AI":`${o}jina.png`,"Lambda Ai":`${o}lambda.svg`,"Lm Studio":`${o}lmstudio.svg`,"Meta Llama":`${o}meta_llama.svg`,MiniMax:`${o}minimax.svg`,"Mistral AI":`${o}mistral.svg`,Moonshot:`${o}moonshot.svg`,Morph:`${o}morph.svg`,Nebius:`${o}nebius.svg`,Novita:`${o}novita.svg`,"Nvidia Nim":`${o}nvidia_nim.svg`,Ollama:`${o}ollama.svg`,"Ollama Chat":`${o}ollama.svg`,Oobabooga:`${o}openai_small.svg`,OpenAI:`${o}openai_small.svg`,"Openai Like":`${o}openai_small.svg`,"OpenAI Text Completion":`${o}openai_small.svg`,"OpenAI-Compatible Text Completion Models (Together AI, etc.)":`${o}openai_small.svg`,"OpenAI-Compatible Endpoints (Together AI, etc.)":`${o}openai_small.svg`,Openrouter:`${o}openrouter.svg`,"Oracle Cloud Infrastructure (OCI)":`${o}oracle.svg`,Perplexity:`${o}perplexity-ai.svg`,Recraft:`${o}recraft.svg`,Replicate:`${o}replicate.svg`,RunwayML:`${o}runwayml.png`,Sagemaker:`${o}bedrock.svg`,Sambanova:`${o}sambanova.svg`,"SAP Generative AI Hub":`${o}sap.png`,Snowflake:`${o}snowflake.svg`,Soniox:`${o}soniox.svg`,"Text-Completion-Codestral":`${o}mistral.svg`,TogetherAI:`${o}togetherai.svg`,Topaz:`${o}topaz.svg`,Triton:`${o}nvidia_triton.png`,V0:`${o}v0.svg`,"Vercel Ai Gateway":`${o}vercel.svg`,"Vertex AI (Anthropic, Gemini, etc.)":`${o}google.svg`,"Vertex Ai Beta":`${o}google.svg`,Vllm:`${o}vllm.png`,VolcEngine:`${o}volcengine.png`,"Voyage AI":`${o}voyage.webp`,Watsonx:`${o}watsonx.svg`,"Watsonx Text":`${o}watsonx.svg`,xAI:`${o}xai.svg`,Xinference:`${o}xinference.svg`};e.s(["Providers",()=>t,"getPlaceholder",0,e=>{if("AI/ML API"===e)return"aiml/flux-pro/v1.1";if("Vertex AI (Anthropic, Gemini, etc.)"===e)return"gemini-pro";if("Anthropic"==e)return"claude-3-opus";if("Amazon Bedrock"==e)return"claude-3-opus";if("AWS SageMaker"==e)return"sagemaker/jumpstart-dft-meta-textgeneration-llama-2-7b";else if("Google AI Studio"==e)return"gemini-pro";else if("Azure AI Foundry (Studio)"==e)return"azure_ai/command-r-plus";else if("Azure"==e)return"my-deployment";else if("Oracle Cloud Infrastructure (OCI)"==e)return"oci/xai.grok-4";else if("Snowflake"==e)return"snowflake/mistral-7b";else if("Voyage AI"==e)return"voyage/";else if("Jina AI"==e)return"jina_ai/";else if("VolcEngine"==e)return"volcengine/";else if("DeepInfra"==e)return"deepinfra/";else if("Fal AI"==e)return"fal_ai/fal-ai/flux-pro/v1.1-ultra";else if("RunwayML"==e)return"runwayml/gen4_turbo";else if("Watsonx"===e)return"watsonx/ibm/granite-3-3-8b-instruct";else if("Cursor"===e)return"cursor/claude-4-sonnet";else if("Z.AI (Zhipu AI)"===e)return"zai/glm-4.5";else return"gpt-3.5-turbo"},"getProviderLogoAndName",0,e=>{if(!e)return{logo:"",displayName:"-"};if("gemini"===e.toLowerCase()){let e="Google AI Studio";return{logo:l[e],displayName:e}}let r=Object.keys(a).find(r=>a[r].toLowerCase()===e.toLowerCase());if(!r)return{logo:"",displayName:e};let o=t[r];return{logo:l[o],displayName:o}},"getProviderModels",0,(e,r)=>{console.log(`Provider key: ${e}`);let t=a[e];console.log(`Provider mapped to: ${t}`);let o=[];return e&&"object"==typeof r&&(Object.entries(r).forEach(([e,r])=>{if(null!==r&&"object"==typeof r&&"litellm_provider"in r){let a=r.litellm_provider;(a===t||"string"==typeof a&&(a.startsWith(`${t}_`)||a.startsWith(`${t}-`)))&&o.push(e)}}),"Cohere"==e&&(console.log("Adding cohere chat models"),Object.entries(r).forEach(([e,r])=>{null!==r&&"object"==typeof r&&"litellm_provider"in r&&"cohere_chat"===r.litellm_provider&&o.push(e)})),"AWS SageMaker"==e&&(console.log("Adding sagemaker chat models"),Object.entries(r).forEach(([e,r])=>{null!==r&&"object"==typeof r&&"litellm_provider"in r&&"sagemaker_chat"===r.litellm_provider&&o.push(e)}))),o},"providerLogoMap",0,l,"provider_map",0,a])},362024,e=>{"use strict";var r=e.i(988122);e.s(["Collapse",()=>r.default])},240647,e=>{"use strict";var r=e.i(286612);e.s(["RightOutlined",()=>r.default])},149121,e=>{"use strict";var r=e.i(843476),t=e.i(271645),a=e.i(152990),o=e.i(682830),l=e.i(269200),s=e.i(427612),i=e.i(64848),n=e.i(942232),d=e.i(496020),c=e.i(977572);function u({data:e=[],columns:u,onRowClick:m,renderSubComponent:g,renderChildRows:p,getRowCanExpand:f,isLoading:b=!1,loadingMessage:A="🚅 Loading logs...",noDataMessage:h="No logs found",enableSorting:v=!1}){let x=!!(g||p)&&!!f,[C,I]=(0,t.useState)([]),y=(0,a.useReactTable)({data:e,columns:u,...v&&{state:{sorting:C},onSortingChange:I,enableSortingRemoval:!1},...x&&{getRowCanExpand:f},getRowId:(e,r)=>e?.request_id??String(r),getCoreRowModel:(0,o.getCoreRowModel)(),...v&&{getSortedRowModel:(0,o.getSortedRowModel)()},...x&&{getExpandedRowModel:(0,o.getExpandedRowModel)()}});return(0,r.jsx)("div",{className:"rounded-lg custom-border overflow-x-auto w-full max-w-full box-border",children:(0,r.jsxs)(l.Table,{className:"[&_td]:py-0.5 [&_th]:py-1 table-fixed w-full box-border",style:{minWidth:"400px"},children:[(0,r.jsx)(s.TableHead,{children:y.getHeaderGroups().map(e=>(0,r.jsx)(d.TableRow,{children:e.headers.map(e=>{let t=v&&e.column.getCanSort(),o=e.column.getIsSorted();return(0,r.jsx)(i.TableHeaderCell,{className:`py-1 h-8 ${t?"cursor-pointer select-none hover:bg-gray-50":""}`,onClick:t?e.column.getToggleSortingHandler():void 0,children:e.isPlaceholder?null:(0,r.jsxs)("div",{className:"flex items-center gap-1",children:[(0,a.flexRender)(e.column.columnDef.header,e.getContext()),t&&(0,r.jsx)("span",{className:"text-gray-400",children:"asc"===o?"↑":"desc"===o?"↓":"⇅"})]})},e.id)})},e.id))}),(0,r.jsx)(n.TableBody,{children:b?(0,r.jsx)(d.TableRow,{children:(0,r.jsx)(c.TableCell,{colSpan:u.length,className:"h-8 text-center",children:(0,r.jsx)("div",{className:"text-center text-gray-500",children:(0,r.jsx)("p",{children:A})})})}):y.getRowModel().rows.length>0?y.getRowModel().rows.map(e=>(0,r.jsxs)(t.Fragment,{children:[(0,r.jsx)(d.TableRow,{className:`h-8 ${m?"cursor-pointer hover:bg-gray-50":""}`,onClick:()=>m?.(e.original),children:e.getVisibleCells().map(e=>(0,r.jsx)(c.TableCell,{className:"py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap",children:(0,a.flexRender)(e.column.columnDef.cell,e.getContext())},e.id))}),x&&e.getIsExpanded()&&p&&p({row:e}),x&&e.getIsExpanded()&&g&&!p&&(0,r.jsx)(d.TableRow,{children:(0,r.jsx)(c.TableCell,{colSpan:e.getVisibleCells().length,className:"p-0",children:(0,r.jsx)("div",{className:"w-full max-w-full overflow-hidden box-border",children:g({row:e})})})})]},e.id)):(0,r.jsx)(d.TableRow,{children:(0,r.jsx)(c.TableCell,{colSpan:u.length,className:"h-8 text-center",children:(0,r.jsx)("div",{className:"text-center text-gray-500",children:(0,r.jsx)("p",{children:h})})})})})]})})}e.s(["DataTable",()=>u])},738014,e=>{"use strict";var r=e.i(135214),t=e.i(602869),a=e.i(266027);let o=(0,e.i(243652).createQueryKeys)("users");e.s(["useCurrentUser",0,()=>{let{accessToken:e,userId:l}=(0,r.default)();return(0,a.useQuery)({queryKey:o.detail(l),queryFn:async()=>await (0,t.userGetInfoV2)(e),enabled:!!(e&&l)})}])},980187,e=>{"use strict";e.s(["createTeamAliasMap",0,e=>e?e.reduce((e,r)=>(e[r.team_id]=r.team_alias,e),{}):{},"resolveTeamAliasFromTeamID",0,(e,r)=>{let t=r.find(r=>r.team_id===e);return t?t.team_alias:null}])},888288,e=>{"use strict";var r=e.i(271645);let t=(e,t)=>{let a=void 0!==t,[o,l]=(0,r.useState)(e);return[a?t:o,e=>{a||l(e)}]};e.s(["default",()=>t])},37091,e=>{"use strict";var r=e.i(290571),t=e.i(95779),a=e.i(444755),o=e.i(673706),l=e.i(271645);let s=l.default.forwardRef((e,s)=>{let{color:i,children:n,className:d}=e,c=(0,r.__rest)(e,["color","children","className"]);return l.default.createElement("p",Object.assign({ref:s,className:(0,a.tremorTwMerge)(i?(0,o.getColorClassNames)(i,t.colorPalette.lightText).textColor:"text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis",d)},c),n)});s.displayName="Subtitle",e.s(["Subtitle",()=>s],37091)},497650,e=>{"use strict";var r=e.i(309821);e.s(["Progress",()=>r.default])},160818,e=>{"use strict";e.i(247167);var r=e.i(931067),t=e.i(271645);let a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M854.4 800.9c.2-.3.5-.6.7-.9C920.6 722.1 960 621.7 960 512s-39.4-210.1-104.8-288c-.2-.3-.5-.5-.7-.8-1.1-1.3-2.1-2.5-3.2-3.7-.4-.5-.8-.9-1.2-1.4l-4.1-4.7-.1-.1c-1.5-1.7-3.1-3.4-4.6-5.1l-.1-.1c-3.2-3.4-6.4-6.8-9.7-10.1l-.1-.1-4.8-4.8-.3-.3c-1.5-1.5-3-2.9-4.5-4.3-.5-.5-1-1-1.6-1.5-1-1-2-1.9-3-2.8-.3-.3-.7-.6-1-1C736.4 109.2 629.5 64 512 64s-224.4 45.2-304.3 119.2c-.3.3-.7.6-1 1-1 .9-2 1.9-3 2.9-.5.5-1 1-1.6 1.5-1.5 1.4-3 2.9-4.5 4.3l-.3.3-4.8 4.8-.1.1c-3.3 3.3-6.5 6.7-9.7 10.1l-.1.1c-1.6 1.7-3.1 3.4-4.6 5.1l-.1.1c-1.4 1.5-2.8 3.1-4.1 4.7-.4.5-.8.9-1.2 1.4-1.1 1.2-2.1 2.5-3.2 3.7-.2.3-.5.5-.7.8C103.4 301.9 64 402.3 64 512s39.4 210.1 104.8 288c.2.3.5.6.7.9l3.1 3.7c.4.5.8.9 1.2 1.4l4.1 4.7c0 .1.1.1.1.2 1.5 1.7 3 3.4 4.6 5l.1.1c3.2 3.4 6.4 6.8 9.6 10.1l.1.1c1.6 1.6 3.1 3.2 4.7 4.7l.3.3c3.3 3.3 6.7 6.5 10.1 9.6 80.1 74 187 119.2 304.5 119.2s224.4-45.2 304.3-119.2a300 300 0 0010-9.6l.3-.3c1.6-1.6 3.2-3.1 4.7-4.7l.1-.1c3.3-3.3 6.5-6.7 9.6-10.1l.1-.1c1.5-1.7 3.1-3.3 4.6-5 0-.1.1-.1.1-.2 1.4-1.5 2.8-3.1 4.1-4.7.4-.5.8-.9 1.2-1.4a99 99 0 003.3-3.7zm4.1-142.6c-13.8 32.6-32 62.8-54.2 90.2a444.07 444.07 0 00-81.5-55.9c11.6-46.9 18.8-98.4 20.7-152.6H887c-3 40.9-12.6 80.6-28.5 118.3zM887 484H743.5c-1.9-54.2-9.1-105.7-20.7-152.6 29.3-15.6 56.6-34.4 81.5-55.9A373.86 373.86 0 01887 484zM658.3 165.5c39.7 16.8 75.8 40 107.6 69.2a394.72 394.72 0 01-59.4 41.8c-15.7-45-35.8-84.1-59.2-115.4 3.7 1.4 7.4 2.9 11 4.4zm-90.6 700.6c-9.2 7.2-18.4 12.7-27.7 16.4V697a389.1 389.1 0 01115.7 26.2c-8.3 24.6-17.9 47.3-29 67.8-17.4 32.4-37.8 58.3-59 75.1zm59-633.1c11 20.6 20.7 43.3 29 67.8A389.1 389.1 0 01540 327V141.6c9.2 3.7 18.5 9.1 27.7 16.4 21.2 16.7 41.6 42.6 59 75zM540 640.9V540h147.5c-1.6 44.2-7.1 87.1-16.3 127.8l-.3 1.2A445.02 445.02 0 00540 640.9zm0-156.9V383.1c45.8-2.8 89.8-12.5 130.9-28.1l.3 1.2c9.2 40.7 14.7 83.5 16.3 127.8H540zm-56 56v100.9c-45.8 2.8-89.8 12.5-130.9 28.1l-.3-1.2c-9.2-40.7-14.7-83.5-16.3-127.8H484zm-147.5-56c1.6-44.2 7.1-87.1 16.3-127.8l.3-1.2c41.1 15.6 85 25.3 130.9 28.1V484H336.5zM484 697v185.4c-9.2-3.7-18.5-9.1-27.7-16.4-21.2-16.7-41.7-42.7-59.1-75.1-11-20.6-20.7-43.3-29-67.8 37.2-14.6 75.9-23.3 115.8-26.1zm0-370a389.1 389.1 0 01-115.7-26.2c8.3-24.6 17.9-47.3 29-67.8 17.4-32.4 37.8-58.4 59.1-75.1 9.2-7.2 18.4-12.7 27.7-16.4V327zM365.7 165.5c3.7-1.5 7.3-3 11-4.4-23.4 31.3-43.5 70.4-59.2 115.4-21-12-40.9-26-59.4-41.8 31.8-29.2 67.9-52.4 107.6-69.2zM165.5 365.7c13.8-32.6 32-62.8 54.2-90.2 24.9 21.5 52.2 40.3 81.5 55.9-11.6 46.9-18.8 98.4-20.7 152.6H137c3-40.9 12.6-80.6 28.5-118.3zM137 540h143.5c1.9 54.2 9.1 105.7 20.7 152.6a444.07 444.07 0 00-81.5 55.9A373.86 373.86 0 01137 540zm228.7 318.5c-39.7-16.8-75.8-40-107.6-69.2 18.5-15.8 38.4-29.7 59.4-41.8 15.7 45 35.8 84.1 59.2 115.4-3.7-1.4-7.4-2.9-11-4.4zm292.6 0c-3.7 1.5-7.3 3-11 4.4 23.4-31.3 43.5-70.4 59.2-115.4 21 12 40.9 26 59.4 41.8a373.81 373.81 0 01-107.6 69.2z"}}]},name:"global",theme:"outlined"};var o=e.i(9583),l=t.forwardRef(function(e,l){return t.createElement(o.default,(0,r.default)({},e,{ref:l,icon:a}))});e.s(["GlobalOutlined",0,l],160818)},793130,e=>{"use strict";var r=e.i(290571),t=e.i(429427),a=e.i(371330),o=e.i(271645),l=e.i(394487),s=e.i(503269),i=e.i(214520),n=e.i(746725),d=e.i(914189),c=e.i(144279),u=e.i(294316),m=e.i(601893),g=e.i(140721),p=e.i(942803),f=e.i(233538),b=e.i(694421),A=e.i(700020),h=e.i(35889),v=e.i(998348),x=e.i(722678);let C=(0,o.createContext)(null);C.displayName="GroupContext";let I=o.Fragment,y=Object.assign((0,A.forwardRefWithAs)(function(e,r){var I;let y=(0,o.useId)(),T=(0,p.useProvidedId)(),E=(0,m.useDisabled)(),{id:O=T||`headlessui-switch-${y}`,disabled:M=E||!1,checked:_,defaultChecked:N,onChange:k,name:w,value:L,form:D,autoFocus:S=!1,...R}=e,$=(0,o.useContext)(C),[j,P]=(0,o.useState)(null),V=(0,o.useRef)(null),H=(0,u.useSyncRefs)(V,r,null===$?null:$.setSwitch,P),Y=(0,i.useDefaultValue)(N),[z,B]=(0,s.useControllable)(_,k,null!=Y&&Y),F=(0,n.useDisposables)(),[G,U]=(0,o.useState)(!1),W=(0,d.useEvent)(()=>{U(!0),null==B||B(!z),F.nextFrame(()=>{U(!1)})}),K=(0,d.useEvent)(e=>{if((0,f.isDisabledReactIssue7711)(e.currentTarget))return e.preventDefault();e.preventDefault(),W()}),X=(0,d.useEvent)(e=>{e.key===v.Keys.Space?(e.preventDefault(),W()):e.key===v.Keys.Enter&&(0,b.attemptSubmit)(e.currentTarget)}),q=(0,d.useEvent)(e=>e.preventDefault()),Z=(0,x.useLabelledBy)(),Q=(0,h.useDescribedBy)(),{isFocusVisible:J,focusProps:ee}=(0,t.useFocusRing)({autoFocus:S}),{isHovered:er,hoverProps:et}=(0,a.useHover)({isDisabled:M}),{pressed:ea,pressProps:eo}=(0,l.useActivePress)({disabled:M}),el=(0,o.useMemo)(()=>({checked:z,disabled:M,hover:er,focus:J,active:ea,autofocus:S,changing:G}),[z,er,J,ea,M,G,S]),es=(0,A.mergeProps)({id:O,ref:H,role:"switch",type:(0,c.useResolveButtonType)(e,j),tabIndex:-1===e.tabIndex?0:null!=(I=e.tabIndex)?I:0,"aria-checked":z,"aria-labelledby":Z,"aria-describedby":Q,disabled:M||void 0,autoFocus:S,onClick:K,onKeyUp:X,onKeyPress:q},ee,et,eo),ei=(0,o.useCallback)(()=>{if(void 0!==Y)return null==B?void 0:B(Y)},[B,Y]),en=(0,A.useRender)();return o.default.createElement(o.default.Fragment,null,null!=w&&o.default.createElement(g.FormFields,{disabled:M,data:{[w]:L||"on"},overrides:{type:"checkbox",checked:z},form:D,onReset:ei}),en({ourProps:es,theirProps:R,slot:el,defaultTag:"button",name:"Switch"}))}),{Group:function(e){var r;let[t,a]=(0,o.useState)(null),[l,s]=(0,x.useLabels)(),[i,n]=(0,h.useDescriptions)(),d=(0,o.useMemo)(()=>({switch:t,setSwitch:a}),[t,a]),c=(0,A.useRender)();return o.default.createElement(n,{name:"Switch.Description",value:i},o.default.createElement(s,{name:"Switch.Label",value:l,props:{htmlFor:null==(r=d.switch)?void 0:r.id,onClick(e){t&&(e.currentTarget instanceof HTMLLabelElement&&e.preventDefault(),t.click(),t.focus({preventScroll:!0}))}}},o.default.createElement(C.Provider,{value:d},c({ourProps:{},theirProps:e,slot:{},defaultTag:I,name:"Switch.Group"}))))},Label:x.Label,Description:h.Description});var T=e.i(888288),E=e.i(95779),O=e.i(444755),M=e.i(673706),_=e.i(829087);let N=(0,M.makeClassName)("Switch"),k=o.default.forwardRef((e,t)=>{let{checked:a,defaultChecked:l=!1,onChange:s,color:i,name:n,error:d,errorMessage:c,disabled:u,required:m,tooltip:g,id:p}=e,f=(0,r.__rest)(e,["checked","defaultChecked","onChange","color","name","error","errorMessage","disabled","required","tooltip","id"]),b={bgColor:i?(0,M.getColorClassNames)(i,E.colorPalette.background).bgColor:"bg-tremor-brand dark:bg-dark-tremor-brand",ringColor:i?(0,M.getColorClassNames)(i,E.colorPalette.ring).ringColor:"ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted"},[A,h]=(0,T.default)(l,a),[v,x]=(0,o.useState)(!1),{tooltipProps:C,getReferenceProps:I}=(0,_.useTooltip)(300);return o.default.createElement("div",{className:"flex flex-row items-center justify-start"},o.default.createElement(_.default,Object.assign({text:g},C)),o.default.createElement("div",Object.assign({ref:(0,M.mergeRefs)([t,C.refs.setReference]),className:(0,O.tremorTwMerge)(N("root"),"flex flex-row relative h-5")},f,I),o.default.createElement("input",{type:"checkbox",className:(0,O.tremorTwMerge)(N("input"),"absolute w-5 h-5 cursor-pointer left-0 top-0 opacity-0"),name:n,required:m,checked:A,onChange:e=>{e.preventDefault()}}),o.default.createElement(y,{checked:A,onChange:e=>{h(e),null==s||s(e)},disabled:u,className:(0,O.tremorTwMerge)(N("switch"),"w-10 h-5 group relative inline-flex shrink-0 cursor-pointer items-center justify-center rounded-tremor-full","focus:outline-none",u?"cursor-not-allowed":""),onFocus:()=>x(!0),onBlur:()=>x(!1),id:p},o.default.createElement("span",{className:(0,O.tremorTwMerge)(N("sr-only"),"sr-only")},"Switch ",A?"on":"off"),o.default.createElement("span",{"aria-hidden":"true",className:(0,O.tremorTwMerge)(N("background"),A?b.bgColor:"bg-tremor-border dark:bg-dark-tremor-border","pointer-events-none absolute mx-auto h-3 w-9 rounded-tremor-full transition-colors duration-100 ease-in-out")}),o.default.createElement("span",{"aria-hidden":"true",className:(0,O.tremorTwMerge)(N("round"),A?(0,O.tremorTwMerge)(b.bgColor,"translate-x-5 border-tremor-background dark:border-dark-tremor-background"):"translate-x-0 bg-tremor-border dark:bg-dark-tremor-border border-tremor-background dark:border-dark-tremor-background","pointer-events-none absolute left-0 inline-block h-5 w-5 transform rounded-tremor-full border-2 shadow-tremor-input duration-100 ease-in-out transition",v?(0,O.tremorTwMerge)("ring-2",b.ringColor):"")}))),d&&c?o.default.createElement("p",{className:(0,O.tremorTwMerge)(N("errorMessage"),"text-sm text-red-500 mt-1 ")},c):null)});k.displayName="Switch",e.s(["Switch",()=>k],793130)},418371,e=>{"use strict";var r=e.i(843476),t=e.i(271645),a=e.i(916925);e.s(["ProviderLogo",0,({provider:e,className:o="w-4 h-4"})=>{let[l,s]=(0,t.useState)(!1),{logo:i}=(0,a.getProviderLogoAndName)(e);return l||!i?(0,r.jsx)("div",{className:`${o} rounded-full bg-gray-200 flex items-center justify-center text-xs`,children:e?.charAt(0)||"-"}):(0,r.jsx)("img",{src:i,alt:`${e} logo`,className:o,onError:()=>s(!0)})}])},289793,e=>{"use strict";var r=e.i(602869),t=e.i(266027),a=e.i(243652),o=e.i(708347),l=e.i(135214);let s=(0,a.createQueryKeys)("agents");e.s(["useAgents",0,()=>{let{accessToken:e,userRole:a}=(0,l.default)();return(0,t.useQuery)({queryKey:s.list({}),queryFn:async()=>await (0,r.getAgentsList)(e),enabled:!!e&&o.all_admin_roles.includes(a||"")})}])},366283,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(95779),o=e.i(444755),l=e.i(673706);let s=(0,l.makeClassName)("Callout"),i=t.default.forwardRef((e,i)=>{let{title:n,icon:d,color:c,className:u,children:m}=e,g=(0,r.__rest)(e,["title","icon","color","className","children"]);return t.default.createElement("div",Object.assign({ref:i,className:(0,o.tremorTwMerge)(s("root"),"flex flex-col overflow-hidden rounded-tremor-default text-tremor-default border-l-4 py-3 pr-3 pl-4",c?(0,o.tremorTwMerge)((0,l.getColorClassNames)(c,a.colorPalette.background).bgColor,(0,l.getColorClassNames)(c,a.colorPalette.darkBorder).borderColor,(0,l.getColorClassNames)(c,a.colorPalette.darkText).textColor,"dark:bg-opacity-10 bg-opacity-10"):(0,o.tremorTwMerge)("bg-tremor-brand-faint border-tremor-brand-emphasis text-tremor-brand-emphasis","dark:bg-dark-tremor-brand-muted/70 dark:border-dark-tremor-brand-emphasis dark:text-dark-tremor-brand-emphasis"),u)},g),t.default.createElement("div",{className:(0,o.tremorTwMerge)(s("header"),"flex items-start")},d?t.default.createElement(d,{className:(0,o.tremorTwMerge)(s("icon"),"flex-none h-5 w-5 mr-1.5")}):null,t.default.createElement("h4",{className:(0,o.tremorTwMerge)(s("title"),"font-semibold")},n)),t.default.createElement("p",{className:(0,o.tremorTwMerge)(s("body"),"overflow-y-auto",m?"mt-2":"")},m))});i.displayName="Callout",e.s(["Callout",()=>i],366283)},973706,e=>{"use strict";var r=e.i(843476),t=e.i(72713),a=e.i(637235),o=e.i(994388),l=e.i(599724),s=e.i(166540),i=e.i(271645);let n=[{label:"Today",shortLabel:"today",getValue:()=>({from:(0,s.default)().startOf("day").toDate(),to:(0,s.default)().endOf("day").toDate()})},{label:"Last 7 days",shortLabel:"7d",getValue:()=>({from:(0,s.default)().subtract(7,"days").startOf("day").toDate(),to:(0,s.default)().endOf("day").toDate()})},{label:"Last 30 days",shortLabel:"30d",getValue:()=>({from:(0,s.default)().subtract(30,"days").startOf("day").toDate(),to:(0,s.default)().endOf("day").toDate()})},{label:"Month to date",shortLabel:"MTD",getValue:()=>({from:(0,s.default)().startOf("month").toDate(),to:(0,s.default)().endOf("day").toDate()})},{label:"Year to date",shortLabel:"YTD",getValue:()=>({from:(0,s.default)().startOf("year").toDate(),to:(0,s.default)().endOf("day").toDate()})}];e.s(["default",0,({value:e,onValueChange:d,label:c="Select Time Range",showTimeRange:u=!0})=>{let[m,g]=(0,i.useState)(!1),[p,f]=(0,i.useState)(e),[b,A]=(0,i.useState)(null),[h,v]=(0,i.useState)(""),[x,C]=(0,i.useState)(""),I=(0,i.useRef)(null),y=(0,i.useCallback)(e=>{if(!e.from||!e.to)return null;for(let r of n){let t=r.getValue(),a=(0,s.default)(e.from).isSame((0,s.default)(t.from),"day"),o=(0,s.default)(e.to).isSame((0,s.default)(t.to),"day");if(a&&o)return r.shortLabel}return null},[]);(0,i.useEffect)(()=>{A(y(e))},[e,y]);let T=(0,i.useCallback)(()=>{if(!h||!x)return{isValid:!0,error:""};let e=(0,s.default)(h,"YYYY-MM-DD"),r=(0,s.default)(x,"YYYY-MM-DD");return e.isValid()&&r.isValid()?r.isBefore(e)?{isValid:!1,error:"End date cannot be before start date"}:{isValid:!0,error:""}:{isValid:!1,error:"Invalid date format"}},[h,x])();(0,i.useEffect)(()=>{e.from&&v((0,s.default)(e.from).format("YYYY-MM-DD")),e.to&&C((0,s.default)(e.to).format("YYYY-MM-DD")),f(e)},[e]),(0,i.useEffect)(()=>{let e=e=>{I.current&&!I.current.contains(e.target)&&g(!1)};return m&&document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[m]);let E=(0,i.useCallback)((e,r)=>{if(!e||!r)return"Select date range";let t=e=>(0,s.default)(e).format("D MMM, HH:mm");return`${t(e)} - ${t(r)}`},[]),O=(0,i.useCallback)(e=>{let r;if(!e.from)return e;let t={...e},a=new Date(e.from);return r=new Date(e.to?e.to:e.from),a.toDateString()===r.toDateString(),a.setHours(0,0,0,0),r.setHours(23,59,59,999),t.from=a,t.to=r,t},[]),M=(0,i.useCallback)(()=>{try{if(h&&x&&T.isValid){let e=(0,s.default)(h,"YYYY-MM-DD").startOf("day"),r=(0,s.default)(x,"YYYY-MM-DD").endOf("day");if(e.isValid()&&r.isValid()){let t={from:e.toDate(),to:r.toDate()};f(t);let a=y(t);A(a)}}}catch(e){console.warn("Invalid date format:",e)}},[h,x,T.isValid,y]);return(0,i.useEffect)(()=>{M()},[M]),(0,r.jsxs)("div",{className:"flex items-center gap-3",children:[c&&(0,r.jsx)(l.Text,{className:"text-sm font-medium text-gray-700 whitespace-nowrap",children:c}),(0,r.jsxs)("div",{className:"relative",ref:I,children:[(0,r.jsx)("div",{className:"w-[300px] px-3 py-2 text-sm border border-gray-300 rounded-md bg-white cursor-pointer hover:border-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500",onClick:()=>g(!m),children:(0,r.jsxs)("div",{className:"flex items-center justify-between",children:[(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)(a.ClockCircleOutlined,{className:"text-gray-600"}),(0,r.jsx)("span",{className:"text-gray-900",children:E(e.from,e.to)})]}),(0,r.jsx)("svg",{className:`w-4 h-4 text-gray-400 transition-transform ${m?"rotate-180":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})}),m&&(0,r.jsx)("div",{className:"absolute top-full right-0 z-[9999] min-w-[600px] mt-1 bg-white border border-gray-200 rounded-lg shadow-xl",children:(0,r.jsxs)("div",{className:"flex",children:[(0,r.jsxs)("div",{className:"w-1/2 border-r border-gray-200",children:[(0,r.jsx)("div",{className:"p-3 border-b border-gray-200",children:(0,r.jsx)("span",{className:"text-sm font-semibold text-gray-900",children:"Relative time"})}),(0,r.jsx)("div",{className:"h-[350px] overflow-y-auto",children:n.map(e=>{let t=b===e.shortLabel;return(0,r.jsxs)("div",{className:`flex items-center justify-between px-5 py-4 cursor-pointer border-b border-gray-100 transition-colors ${t?"bg-blue-50 hover:bg-blue-100 border-blue-200":"hover:bg-gray-50"}`,onClick:()=>(e=>{let{from:r,to:t}=e.getValue();f({from:r,to:t}),A(e.shortLabel),v((0,s.default)(r).format("YYYY-MM-DD")),C((0,s.default)(t).format("YYYY-MM-DD"))})(e),children:[(0,r.jsx)("span",{className:`text-sm ${t?"text-blue-700 font-medium":"text-gray-700"}`,children:e.label}),(0,r.jsx)("span",{className:`text-xs px-2 py-1 rounded capitalize ${t?"text-blue-700 bg-blue-100":"text-gray-500 bg-gray-100"}`,children:e.shortLabel})]},e.label)})})]}),(0,r.jsxs)("div",{className:"w-1/2 relative",children:[(0,r.jsx)("div",{className:"p-3.5 border-b border-gray-200",children:(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)(t.CalendarOutlined,{className:"text-gray-600"}),(0,r.jsx)("span",{className:"text-sm font-semibold text-gray-900",children:"Start and end dates"})]})}),(0,r.jsxs)("div",{className:"p-6 space-y-6 pb-20",children:[(0,r.jsxs)("div",{children:[(0,r.jsx)("label",{className:"text-sm text-gray-700 mb-1 block",children:"Start date"}),(0,r.jsx)("input",{type:"date",value:h,onChange:e=>v(e.target.value),className:`w-65 px-3 py-2 text-sm border rounded-md cursor-pointer hover:border-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 ${!T.isValid?"border-red-300 focus:border-red-500 focus:ring-red-200":"border-gray-300"}`})]}),(0,r.jsxs)("div",{children:[(0,r.jsx)("label",{className:"text-sm text-gray-700 mb-1 block",children:"End date"}),(0,r.jsx)("input",{type:"date",value:x,onChange:e=>C(e.target.value),className:`w-65 px-3 py-2 text-sm border rounded-md cursor-pointer hover:border-gray-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 ${!T.isValid?"border-red-300 focus:border-red-500 focus:ring-red-200":"border-gray-300"}`})]}),!T.isValid&&T.error&&(0,r.jsx)("div",{className:"bg-red-50 border border-red-200 rounded-md p-3",children:(0,r.jsxs)("div",{className:"flex items-center gap-2",children:[(0,r.jsx)("svg",{className:"w-4 h-4 text-red-500",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.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-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"})}),(0,r.jsx)("span",{className:"text-sm text-red-700 font-medium",children:T.error})]})}),p.from&&p.to&&T.isValid&&(0,r.jsxs)("div",{className:"bg-blue-50 p-3 rounded-md space-y-1",children:[(0,r.jsxs)("div",{className:"text-xs text-blue-800",children:[(0,r.jsx)("span",{className:"font-medium",children:"From:"})," ",(0,s.default)(p.from).format("MMM D, YYYY [at] HH:mm:ss")]}),(0,r.jsxs)("div",{className:"text-xs text-blue-800",children:[(0,r.jsx)("span",{className:"font-medium",children:"To:"})," ",(0,s.default)(p.to).format("MMM D, YYYY [at] HH:mm:ss")]})]})]}),(0,r.jsx)("div",{className:"absolute bottom-4 right-4",children:(0,r.jsxs)("div",{className:"flex gap-2",children:[(0,r.jsx)(o.Button,{variant:"secondary",onClick:()=>{f(e),e.from&&v((0,s.default)(e.from).format("YYYY-MM-DD")),e.to&&C((0,s.default)(e.to).format("YYYY-MM-DD")),A(y(e)),g(!1)},children:"Cancel"}),(0,r.jsx)(o.Button,{onClick:()=>{p.from&&p.to&&T.isValid&&(d(p),requestIdleCallback(()=>{d(O(p))},{timeout:100}),g(!1))},disabled:!p.from||!p.to||!T.isValid,children:"Apply"})]})})]})]})})]})]})}])}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/04711b0f8ffa7bbd.js b/litellm/proxy/_experimental/out/_next/static/chunks/04711b0f8ffa7bbd.js deleted file mode 100644 index 6cfa66f43a4..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/04711b0f8ffa7bbd.js +++ /dev/null @@ -1,7 +0,0 @@ -(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,309821,e=>{"use strict";e.i(247167);var t=e.i(271645);e.i(262370);var r=e.i(135551),n=e.i(201072),o=e.i(121229),i=e.i(726289),l=e.i(864517),a=e.i(343794),s=e.i(529681),c=e.i(242064),u=e.i(931067),d=e.i(209428),p=e.i(703923),f={percent:0,prefixCls:"rc-progress",strokeColor:"#2db7f5",strokeLinecap:"round",strokeWidth:1,trailColor:"#D9D9D9",trailWidth:1,gapPosition:"bottom"},g=function(){var e=(0,t.useRef)([]),r=(0,t.useRef)(null);return(0,t.useEffect)(function(){var t=Date.now(),n=!1;e.current.forEach(function(e){if(e){n=!0;var o=e.style;o.transitionDuration=".3s, .3s, .3s, .06s",r.current&&t-r.current<100&&(o.transitionDuration="0s, 0s")}}),n&&(r.current=Date.now())}),e.current},m=e.i(410160),b=e.i(392221),h=e.i(654310),v=0,y=(0,h.default)();let $=function(e){var r=t.useState(),n=(0,b.default)(r,2),o=n[0],i=n[1];return t.useEffect(function(){var e;i("rc_progress_".concat((y?(e=v,v+=1):e="TEST_OR_SSR",e)))},[]),e||o};var C=function(e){var r=e.bg,n=e.children;return t.createElement("div",{style:{width:"100%",height:"100%",background:r}},n)};function k(e,t){return Object.keys(e).map(function(r){var n=parseFloat(r),o="".concat(Math.floor(n*t),"%");return"".concat(e[r]," ").concat(o)})}var x=t.forwardRef(function(e,r){var n=e.prefixCls,o=e.color,i=e.gradientId,l=e.radius,a=e.style,s=e.ptg,c=e.strokeLinecap,u=e.strokeWidth,d=e.size,p=e.gapDegree,f=o&&"object"===(0,m.default)(o),g=d/2,b=t.createElement("circle",{className:"".concat(n,"-circle-path"),r:l,cx:g,cy:g,stroke:f?"#FFF":void 0,strokeLinecap:c,strokeWidth:u,opacity:+(0!==s),style:a,ref:r});if(!f)return b;var h="".concat(i,"-conic"),v=k(o,(360-p)/360),y=k(o,1),$="conic-gradient(from ".concat(p?"".concat(180+p/2,"deg"):"0deg",", ").concat(v.join(", "),")"),x="linear-gradient(to ".concat(p?"bottom":"top",", ").concat(y.join(", "),")");return t.createElement(t.Fragment,null,t.createElement("mask",{id:h},b),t.createElement("foreignObject",{x:0,y:0,width:d,height:d,mask:"url(#".concat(h,")")},t.createElement(C,{bg:x},t.createElement(C,{bg:$}))))}),S=function(e,t,r,n,o,i,l,a,s,c){var u=arguments.length>10&&void 0!==arguments[10]?arguments[10]:0,d=(100-n)/100*t;return"round"===s&&100!==n&&(d+=c/2)>=t&&(d=t-.01),{stroke:"string"==typeof a?a:void 0,strokeDasharray:"".concat(t,"px ").concat(e),strokeDashoffset:d+u,transform:"rotate(".concat(o+r/100*360*((360-i)/360)+(0===i?0:({bottom:0,top:180,left:90,right:-90})[l]),"deg)"),transformOrigin:"".concat(50,"px ").concat(50,"px"),transition:"stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s",fillOpacity:0}},O=["id","prefixCls","steps","strokeWidth","trailWidth","gapDegree","gapPosition","trailColor","strokeLinecap","style","className","strokeColor","percent"];function w(e){var t=null!=e?e:[];return Array.isArray(t)?t:[t]}let E=function(e){var r,n,o,i,l=(0,d.default)((0,d.default)({},f),e),s=l.id,c=l.prefixCls,b=l.steps,h=l.strokeWidth,v=l.trailWidth,y=l.gapDegree,C=void 0===y?0:y,k=l.gapPosition,E=l.trailColor,j=l.strokeLinecap,N=l.style,I=l.className,P=l.strokeColor,D=l.percent,R=(0,p.default)(l,O),z=$(s),A="".concat(z,"-gradient"),M=50-h/2,T=2*Math.PI*M,W=C>0?90+C/2:-90,B=(360-C)/360*T,F="object"===(0,m.default)(b)?b:{count:b,gap:2},X=F.count,L=F.gap,H=w(D),_=w(P),q=_.find(function(e){return e&&"object"===(0,m.default)(e)}),G=q&&"object"===(0,m.default)(q)?"butt":j,V=S(T,B,0,100,W,C,k,E,G,h),K=g();return t.createElement("svg",(0,u.default)({className:(0,a.default)("".concat(c,"-circle"),I),viewBox:"0 0 ".concat(100," ").concat(100),style:N,id:s,role:"presentation"},R),!X&&t.createElement("circle",{className:"".concat(c,"-circle-trail"),r:M,cx:50,cy:50,stroke:E,strokeLinecap:G,strokeWidth:v||h,style:V}),X?(r=Math.round(X*(H[0]/100)),n=100/X,o=0,Array(X).fill(null).map(function(e,i){var l=i<=r-1?_[0]:E,a=l&&"object"===(0,m.default)(l)?"url(#".concat(A,")"):void 0,s=S(T,B,o,n,W,C,k,l,"butt",h,L);return o+=(B-s.strokeDashoffset+L)*100/B,t.createElement("circle",{key:i,className:"".concat(c,"-circle-path"),r:M,cx:50,cy:50,stroke:a,strokeWidth:h,opacity:1,style:s,ref:function(e){K[i]=e}})})):(i=0,H.map(function(e,r){var n=_[r]||_[_.length-1],o=S(T,B,i,e,W,C,k,n,G,h);return i+=e,t.createElement(x,{key:r,color:n,ptg:e,radius:M,prefixCls:c,gradientId:A,style:o,strokeLinecap:G,strokeWidth:h,gapDegree:C,ref:function(e){K[r]=e},size:100})}).reverse()))};var j=e.i(491816);e.i(765846);var N=e.i(896091);function I(e){return!e||e<0?0:e>100?100:e}function P({success:e,successPercent:t}){let r=t;return e&&"progress"in e&&(r=e.progress),e&&"percent"in e&&(r=e.percent),r}let D=(e,t,r)=>{var n,o,i,l;let a=-1,s=-1;if("step"===t){let t=r.steps,n=r.strokeWidth;"string"==typeof e||void 0===e?(a="small"===e?2:14,s=null!=n?n:8):"number"==typeof e?[a,s]=[e,e]:[a=14,s=8]=Array.isArray(e)?e:[e.width,e.height],a*=t}else if("line"===t){let t=null==r?void 0:r.strokeWidth;"string"==typeof e||void 0===e?s=t||("small"===e?6:8):"number"==typeof e?[a,s]=[e,e]:[a=-1,s=8]=Array.isArray(e)?e:[e.width,e.height]}else("circle"===t||"dashboard"===t)&&("string"==typeof e||void 0===e?[a,s]="small"===e?[60,60]:[120,120]:"number"==typeof e?[a,s]=[e,e]:Array.isArray(e)&&(a=null!=(o=null!=(n=e[0])?n:e[1])?o:120,s=null!=(l=null!=(i=e[0])?i:e[1])?l:120));return[a,s]},R=e=>{let{prefixCls:r,trailColor:n=null,strokeLinecap:o="round",gapPosition:i,gapDegree:l,width:s=120,type:c,children:u,success:d,size:p=s,steps:f}=e,[g,m]=D(p,"circle"),{strokeWidth:b}=e;void 0===b&&(b=Math.max(3/g*100,6));let h=t.useMemo(()=>l||0===l?l:"dashboard"===c?75:void 0,[l,c]),v=(({percent:e,success:t,successPercent:r})=>{let n=I(P({success:t,successPercent:r}));return[n,I(I(e)-n)]})(e),y="[object Object]"===Object.prototype.toString.call(e.strokeColor),$=(({success:e={},strokeColor:t})=>{let{strokeColor:r}=e;return[r||N.presetPrimaryColors.green,t||null]})({success:d,strokeColor:e.strokeColor}),C=(0,a.default)(`${r}-inner`,{[`${r}-circle-gradient`]:y}),k=t.createElement(E,{steps:f,percent:f?v[1]:v,strokeWidth:b,trailWidth:b,strokeColor:f?$[1]:$,strokeLinecap:o,trailColor:n,prefixCls:r,gapDegree:h,gapPosition:i||"dashboard"===c&&"bottom"||void 0}),x=g<=20,S=t.createElement("div",{className:C,style:{width:g,height:m,fontSize:.15*g+6}},k,!x&&u);return x?t.createElement(j.default,{title:u},S):S};e.i(296059);var z=e.i(694758),A=e.i(915654),M=e.i(183293),T=e.i(246422),W=e.i(838378);let B="--progress-line-stroke-color",F="--progress-percent",X=e=>{let t=e?"100%":"-100%";return new z.Keyframes(`antProgress${e?"RTL":"LTR"}Active`,{"0%":{transform:`translateX(${t}) scaleX(0)`,opacity:.1},"20%":{transform:`translateX(${t}) scaleX(0)`,opacity:.5},to:{transform:"translateX(0) scaleX(1)",opacity:0}})},L=(0,T.genStyleHooks)("Progress",e=>{let t=e.calc(e.marginXXS).div(2).equal(),r=(0,W.mergeToken)(e,{progressStepMarginInlineEnd:t,progressStepMinWidth:t,progressActiveMotionDuration:"2.4s"});return[(e=>{let{componentCls:t,iconCls:r}=e;return{[t]:Object.assign(Object.assign({},(0,M.resetComponent)(e)),{display:"inline-block","&-rtl":{direction:"rtl"},"&-line":{position:"relative",width:"100%",fontSize:e.fontSize},[`${t}-outer`]:{display:"inline-flex",alignItems:"center",width:"100%"},[`${t}-inner`]:{position:"relative",display:"inline-block",width:"100%",flex:1,overflow:"hidden",verticalAlign:"middle",backgroundColor:e.remainingColor,borderRadius:e.lineBorderRadius},[`${t}-inner:not(${t}-circle-gradient)`]:{[`${t}-circle-path`]:{stroke:e.defaultColor}},[`${t}-success-bg, ${t}-bg`]:{position:"relative",background:e.defaultColor,borderRadius:e.lineBorderRadius,transition:`all ${e.motionDurationSlow} ${e.motionEaseInOutCirc}`},[`${t}-layout-bottom`]:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",[`${t}-text`]:{width:"max-content",marginInlineStart:0,marginTop:e.marginXXS}},[`${t}-bg`]:{overflow:"hidden","&::after":{content:'""',background:{_multi_value_:!0,value:["inherit",`var(${B})`]},height:"100%",width:`calc(1 / var(${F}) * 100%)`,display:"block"},[`&${t}-bg-inner`]:{minWidth:"max-content","&::after":{content:"none"},[`${t}-text-inner`]:{color:e.colorWhite,[`&${t}-text-bright`]:{color:"rgba(0, 0, 0, 0.45)"}}}},[`${t}-success-bg`]:{position:"absolute",insetBlockStart:0,insetInlineStart:0,backgroundColor:e.colorSuccess},[`${t}-text`]:{display:"inline-block",marginInlineStart:e.marginXS,color:e.colorText,lineHeight:1,width:"2em",whiteSpace:"nowrap",textAlign:"start",verticalAlign:"middle",wordBreak:"normal",[r]:{fontSize:e.fontSize},[`&${t}-text-outer`]:{width:"max-content"},[`&${t}-text-outer${t}-text-start`]:{width:"max-content",marginInlineStart:0,marginInlineEnd:e.marginXS}},[`${t}-text-inner`]:{display:"flex",justifyContent:"center",alignItems:"center",width:"100%",height:"100%",marginInlineStart:0,padding:`0 ${(0,A.unit)(e.paddingXXS)}`,[`&${t}-text-start`]:{justifyContent:"start"},[`&${t}-text-end`]:{justifyContent:"end"}},[`&${t}-status-active`]:{[`${t}-bg::before`]:{position:"absolute",inset:0,backgroundColor:e.colorBgContainer,borderRadius:e.lineBorderRadius,opacity:0,animationName:X(),animationDuration:e.progressActiveMotionDuration,animationTimingFunction:e.motionEaseOutQuint,animationIterationCount:"infinite",content:'""'}},[`&${t}-rtl${t}-status-active`]:{[`${t}-bg::before`]:{animationName:X(!0)}},[`&${t}-status-exception`]:{[`${t}-bg`]:{backgroundColor:e.colorError},[`${t}-text`]:{color:e.colorError}},[`&${t}-status-exception ${t}-inner:not(${t}-circle-gradient)`]:{[`${t}-circle-path`]:{stroke:e.colorError}},[`&${t}-status-success`]:{[`${t}-bg`]:{backgroundColor:e.colorSuccess},[`${t}-text`]:{color:e.colorSuccess}},[`&${t}-status-success ${t}-inner:not(${t}-circle-gradient)`]:{[`${t}-circle-path`]:{stroke:e.colorSuccess}}})}})(r),(e=>{let{componentCls:t,iconCls:r}=e;return{[t]:{[`${t}-circle-trail`]:{stroke:e.remainingColor},[`&${t}-circle ${t}-inner`]:{position:"relative",lineHeight:1,backgroundColor:"transparent"},[`&${t}-circle ${t}-text`]:{position:"absolute",insetBlockStart:"50%",insetInlineStart:0,width:"100%",margin:0,padding:0,color:e.circleTextColor,fontSize:e.circleTextFontSize,lineHeight:1,whiteSpace:"normal",textAlign:"center",transform:"translateY(-50%)",[r]:{fontSize:e.circleIconFontSize}},[`${t}-circle&-status-exception`]:{[`${t}-text`]:{color:e.colorError}},[`${t}-circle&-status-success`]:{[`${t}-text`]:{color:e.colorSuccess}}},[`${t}-inline-circle`]:{lineHeight:1,[`${t}-inner`]:{verticalAlign:"bottom"}}}})(r),(e=>{let{componentCls:t}=e;return{[t]:{[`${t}-steps`]:{display:"inline-block","&-outer":{display:"flex",flexDirection:"row",alignItems:"center"},"&-item":{flexShrink:0,minWidth:e.progressStepMinWidth,marginInlineEnd:e.progressStepMarginInlineEnd,backgroundColor:e.remainingColor,transition:`all ${e.motionDurationSlow}`,"&-active":{backgroundColor:e.defaultColor}}}}}})(r),(e=>{let{componentCls:t,iconCls:r}=e;return{[t]:{[`${t}-small&-line, ${t}-small&-line ${t}-text ${r}`]:{fontSize:e.fontSizeSM}}}})(r)]},e=>({circleTextColor:e.colorText,defaultColor:e.colorInfo,remainingColor:e.colorFillSecondary,lineBorderRadius:100,circleTextFontSize:"1em",circleIconFontSize:`${e.fontSize/e.fontSizeSM}em`}));var H=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 _=e=>{let{prefixCls:r,direction:n,percent:o,size:i,strokeWidth:l,strokeColor:s,strokeLinecap:c="round",children:u,trailColor:d=null,percentPosition:p,success:f}=e,{align:g,type:m}=p,b=s&&"string"!=typeof s?((e,t)=>{let{from:r=N.presetPrimaryColors.blue,to:n=N.presetPrimaryColors.blue,direction:o="rtl"===t?"to left":"to right"}=e,i=H(e,["from","to","direction"]);if(0!==Object.keys(i).length){let e,t=(e=[],Object.keys(i).forEach(t=>{let r=Number.parseFloat(t.replace(/%/g,""));Number.isNaN(r)||e.push({key:r,value:i[t]})}),(e=e.sort((e,t)=>e.key-t.key)).map(({key:e,value:t})=>`${t} ${e}%`).join(", ")),r=`linear-gradient(${o}, ${t})`;return{background:r,[B]:r}}let l=`linear-gradient(${o}, ${r}, ${n})`;return{background:l,[B]:l}})(s,n):{[B]:s,background:s},h="square"===c||"butt"===c?0:void 0,[v,y]=D(null!=i?i:[-1,l||("small"===i?6:8)],"line",{strokeWidth:l}),$=Object.assign(Object.assign({width:`${I(o)}%`,height:y,borderRadius:h},b),{[F]:I(o)/100}),C=P(e),k={width:`${I(C)}%`,height:y,borderRadius:h,backgroundColor:null==f?void 0:f.strokeColor},x=t.createElement("div",{className:`${r}-inner`,style:{backgroundColor:d||void 0,borderRadius:h}},t.createElement("div",{className:(0,a.default)(`${r}-bg`,`${r}-bg-${m}`),style:$},"inner"===m&&u),void 0!==C&&t.createElement("div",{className:`${r}-success-bg`,style:k})),S="outer"===m&&"start"===g,O="outer"===m&&"end"===g;return"outer"===m&&"center"===g?t.createElement("div",{className:`${r}-layout-bottom`},x,u):t.createElement("div",{className:`${r}-outer`,style:{width:v<0?"100%":v}},S&&u,x,O&&u)},q=e=>{let{size:r,steps:n,rounding:o=Math.round,percent:i=0,strokeWidth:l=8,strokeColor:s,trailColor:c=null,prefixCls:u,children:d}=e,p=o(i/100*n),[f,g]=D(null!=r?r:["small"===r?2:14,l],"step",{steps:n,strokeWidth:l}),m=f/n,b=Array.from({length:n});for(let e=0;et.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 V=["normal","exception","active","success"],K=t.forwardRef((e,u)=>{let d,{prefixCls:p,className:f,rootClassName:g,steps:m,strokeColor:b,percent:h=0,size:v="default",showInfo:y=!0,type:$="line",status:C,format:k,style:x,percentPosition:S={}}=e,O=G(e,["prefixCls","className","rootClassName","steps","strokeColor","percent","size","showInfo","type","status","format","style","percentPosition"]),{align:w="end",type:E="outer"}=S,j=Array.isArray(b)?b[0]:b,N="string"==typeof b||Array.isArray(b)?b:void 0,z=t.useMemo(()=>{if(j){let e="string"==typeof j?j:Object.values(j)[0];return new r.FastColor(e).isLight()}return!1},[b]),A=t.useMemo(()=>{var t,r;let n=P(e);return Number.parseInt(void 0!==n?null==(t=null!=n?n:0)?void 0:t.toString():null==(r=null!=h?h:0)?void 0:r.toString(),10)},[h,e.success,e.successPercent]),M=t.useMemo(()=>!V.includes(C)&&A>=100?"success":C||"normal",[C,A]),{getPrefixCls:T,direction:W,progress:B}=t.useContext(c.ConfigContext),F=T("progress",p),[X,H,K]=L(F),U="line"===$,Q=U&&!m,Y=t.useMemo(()=>{let r;if(!y)return null;let s=P(e),c=k||(e=>`${e}%`),u=U&&z&&"inner"===E;return"inner"===E||k||"exception"!==M&&"success"!==M?r=c(I(h),I(s)):"exception"===M?r=U?t.createElement(i.default,null):t.createElement(l.default,null):"success"===M&&(r=U?t.createElement(n.default,null):t.createElement(o.default,null)),t.createElement("span",{className:(0,a.default)(`${F}-text`,{[`${F}-text-bright`]:u,[`${F}-text-${w}`]:Q,[`${F}-text-${E}`]:Q}),title:"string"==typeof r?r:void 0},r)},[y,h,A,M,$,F,k]);"line"===$?d=m?t.createElement(q,Object.assign({},e,{strokeColor:N,prefixCls:F,steps:"object"==typeof m?m.count:m}),Y):t.createElement(_,Object.assign({},e,{strokeColor:j,prefixCls:F,direction:W,percentPosition:{align:w,type:E}}),Y):("circle"===$||"dashboard"===$)&&(d=t.createElement(R,Object.assign({},e,{strokeColor:j,prefixCls:F,progressStatus:M}),Y));let J=(0,a.default)(F,`${F}-status-${M}`,{[`${F}-${"dashboard"===$&&"circle"||$}`]:"line"!==$,[`${F}-inline-circle`]:"circle"===$&&D(v,"circle")[0]<=20,[`${F}-line`]:Q,[`${F}-line-align-${w}`]:Q,[`${F}-line-position-${E}`]:Q,[`${F}-steps`]:m,[`${F}-show-info`]:y,[`${F}-${v}`]:"string"==typeof v,[`${F}-rtl`]:"rtl"===W},null==B?void 0:B.className,f,g,H,K);return X(t.createElement("div",Object.assign({ref:u,style:Object.assign(Object.assign({},null==B?void 0:B.style),x),className:J,role:"progressbar","aria-valuenow":A,"aria-valuemin":0,"aria-valuemax":100},(0,s.default)(O,["trailColor","strokeWidth","width","gapDegree","gapPosition","strokeLinecap","success","successPercent"])),d))});e.s(["default",0,K],309821)},91874,e=>{"use strict";var t=e.i(931067),r=e.i(209428),n=e.i(211577),o=e.i(392221),i=e.i(703923),l=e.i(343794),a=e.i(914949),s=e.i(271645),c=["prefixCls","className","style","checked","disabled","defaultChecked","type","title","onChange"],u=(0,s.forwardRef)(function(e,u){var d=e.prefixCls,p=void 0===d?"rc-checkbox":d,f=e.className,g=e.style,m=e.checked,b=e.disabled,h=e.defaultChecked,v=e.type,y=void 0===v?"checkbox":v,$=e.title,C=e.onChange,k=(0,i.default)(e,c),x=(0,s.useRef)(null),S=(0,s.useRef)(null),O=(0,a.default)(void 0!==h&&h,{value:m}),w=(0,o.default)(O,2),E=w[0],j=w[1];(0,s.useImperativeHandle)(u,function(){return{focus:function(e){var t;null==(t=x.current)||t.focus(e)},blur:function(){var e;null==(e=x.current)||e.blur()},input:x.current,nativeElement:S.current}});var N=(0,l.default)(p,f,(0,n.default)((0,n.default)({},"".concat(p,"-checked"),E),"".concat(p,"-disabled"),b));return s.createElement("span",{className:N,title:$,style:g,ref:S},s.createElement("input",(0,t.default)({},k,{className:"".concat(p,"-input"),ref:x,onChange:function(t){b||("checked"in e||j(t.target.checked),null==C||C({target:(0,r.default)((0,r.default)({},e),{},{type:y,checked:t.target.checked}),stopPropagation:function(){t.stopPropagation()},preventDefault:function(){t.preventDefault()},nativeEvent:t.nativeEvent}))},disabled:b,checked:!!E,type:y})),s.createElement("span",{className:"".concat(p,"-inner")}))});e.s(["default",0,u])},681216,e=>{"use strict";var t=e.i(271645),r=e.i(963188);function n(e){let n=t.default.useRef(null),o=()=>{r.default.cancel(n.current),n.current=null};return[()=>{o(),n.current=(0,r.default)(()=>{n.current=null})},t=>{n.current&&(t.stopPropagation(),o()),null==e||e(t)}]}e.s(["default",()=>n])},421512,236836,e=>{"use strict";let t=e.i(271645).default.createContext(null);e.s(["default",0,t],421512),e.i(296059);var r=e.i(915654),n=e.i(183293),o=e.i(246422),i=e.i(838378);function l(e,t){return(e=>{let{checkboxCls:t}=e,o=`${t}-wrapper`;return[{[`${t}-group`]:Object.assign(Object.assign({},(0,n.resetComponent)(e)),{display:"inline-flex",flexWrap:"wrap",columnGap:e.marginXS,[`> ${e.antCls}-row`]:{flex:1}}),[o]:Object.assign(Object.assign({},(0,n.resetComponent)(e)),{display:"inline-flex",alignItems:"baseline",cursor:"pointer","&:after":{display:"inline-block",width:0,overflow:"hidden",content:"'\\a0'"},[`& + ${o}`]:{marginInlineStart:0},[`&${o}-in-form-item`]:{'input[type="checkbox"]':{width:14,height:14}}}),[t]:Object.assign(Object.assign({},(0,n.resetComponent)(e)),{position:"relative",whiteSpace:"nowrap",lineHeight:1,cursor:"pointer",borderRadius:e.borderRadiusSM,alignSelf:"center",[`${t}-input`]:{position:"absolute",inset:0,zIndex:1,cursor:"pointer",opacity:0,margin:0,[`&:focus-visible + ${t}-inner`]:(0,n.genFocusOutline)(e)},[`${t}-inner`]:{boxSizing:"border-box",display:"block",width:e.checkboxSize,height:e.checkboxSize,direction:"ltr",backgroundColor:e.colorBgContainer,border:`${(0,r.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderRadius:e.borderRadiusSM,borderCollapse:"separate",transition:`all ${e.motionDurationSlow}`,"&:after":{boxSizing:"border-box",position:"absolute",top:"50%",insetInlineStart:"25%",display:"table",width:e.calc(e.checkboxSize).div(14).mul(5).equal(),height:e.calc(e.checkboxSize).div(14).mul(8).equal(),border:`${(0,r.unit)(e.lineWidthBold)} solid ${e.colorWhite}`,borderTop:0,borderInlineStart:0,transform:"rotate(45deg) scale(0) translate(-50%,-50%)",opacity:0,content:'""',transition:`all ${e.motionDurationFast} ${e.motionEaseInBack}, opacity ${e.motionDurationFast}`}},"& + span":{paddingInlineStart:e.paddingXS,paddingInlineEnd:e.paddingXS}})},{[` - ${o}:not(${o}-disabled), - ${t}:not(${t}-disabled) - `]:{[`&:hover ${t}-inner`]:{borderColor:e.colorPrimary}},[`${o}:not(${o}-disabled)`]:{[`&:hover ${t}-checked:not(${t}-disabled) ${t}-inner`]:{backgroundColor:e.colorPrimaryHover,borderColor:"transparent"},[`&:hover ${t}-checked:not(${t}-disabled):after`]:{borderColor:e.colorPrimaryHover}}},{[`${t}-checked`]:{[`${t}-inner`]:{backgroundColor:e.colorPrimary,borderColor:e.colorPrimary,"&:after":{opacity:1,transform:"rotate(45deg) scale(1) translate(-50%,-50%)",transition:`all ${e.motionDurationMid} ${e.motionEaseOutBack} ${e.motionDurationFast}`}}},[` - ${o}-checked:not(${o}-disabled), - ${t}-checked:not(${t}-disabled) - `]:{[`&:hover ${t}-inner`]:{backgroundColor:e.colorPrimaryHover,borderColor:"transparent"}}},{[t]:{"&-indeterminate":{"&":{[`${t}-inner`]:{backgroundColor:`${e.colorBgContainer}`,borderColor:`${e.colorBorder}`,"&:after":{top:"50%",insetInlineStart:"50%",width:e.calc(e.fontSizeLG).div(2).equal(),height:e.calc(e.fontSizeLG).div(2).equal(),backgroundColor:e.colorPrimary,border:0,transform:"translate(-50%, -50%) scale(1)",opacity:1,content:'""'}},[`&:hover ${t}-inner`]:{backgroundColor:`${e.colorBgContainer}`,borderColor:`${e.colorPrimary}`}}}}},{[`${o}-disabled`]:{cursor:"not-allowed"},[`${t}-disabled`]:{[`&, ${t}-input`]:{cursor:"not-allowed",pointerEvents:"none"},[`${t}-inner`]:{background:e.colorBgContainerDisabled,borderColor:e.colorBorder,"&:after":{borderColor:e.colorTextDisabled}},"&:after":{display:"none"},"& + span":{color:e.colorTextDisabled},[`&${t}-indeterminate ${t}-inner::after`]:{background:e.colorTextDisabled}}}]})((0,i.mergeToken)(t,{checkboxCls:`.${e}`,checkboxSize:t.controlInteractiveSize}))}let a=(0,o.genStyleHooks)("Checkbox",(e,{prefixCls:t})=>[l(t,e)]);e.s(["default",0,a,"getStyle",()=>l],236836)},536916,374276,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(91874),o=e.i(611935),i=e.i(121872),l=e.i(26905),a=e.i(242064),s=e.i(937328),c=e.i(321883),u=e.i(62139),d=e.i(421512),p=e.i(236836),f=e.i(681216),g=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=t.forwardRef((e,m)=>{var b;let{prefixCls:h,className:v,rootClassName:y,children:$,indeterminate:C=!1,style:k,onMouseEnter:x,onMouseLeave:S,skipGroup:O=!1,disabled:w}=e,E=g(e,["prefixCls","className","rootClassName","children","indeterminate","style","onMouseEnter","onMouseLeave","skipGroup","disabled"]),{getPrefixCls:j,direction:N,checkbox:I}=t.useContext(a.ConfigContext),P=t.useContext(d.default),{isFormItemInput:D}=t.useContext(u.FormItemInputContext),R=t.useContext(s.default),z=null!=(b=(null==P?void 0:P.disabled)||w)?b:R,A=t.useRef(E.value),M=t.useRef(null),T=(0,o.composeRef)(m,M);t.useEffect(()=>{null==P||P.registerValue(E.value)},[]),t.useEffect(()=>{if(!O)return E.value!==A.current&&(null==P||P.cancelValue(A.current),null==P||P.registerValue(E.value),A.current=E.value),()=>null==P?void 0:P.cancelValue(E.value)},[E.value]),t.useEffect(()=>{var e;(null==(e=M.current)?void 0:e.input)&&(M.current.input.indeterminate=C)},[C]);let W=j("checkbox",h),B=(0,c.default)(W),[F,X,L]=(0,p.default)(W,B),H=Object.assign({},E);P&&!O&&(H.onChange=(...e)=>{E.onChange&&E.onChange.apply(E,e),P.toggleOption&&P.toggleOption({label:$,value:E.value})},H.name=P.name,H.checked=P.value.includes(E.value));let _=(0,r.default)(`${W}-wrapper`,{[`${W}-rtl`]:"rtl"===N,[`${W}-wrapper-checked`]:H.checked,[`${W}-wrapper-disabled`]:z,[`${W}-wrapper-in-form-item`]:D},null==I?void 0:I.className,v,y,L,B,X),q=(0,r.default)({[`${W}-indeterminate`]:C},l.TARGET_CLS,X),[G,V]=(0,f.default)(H.onClick);return F(t.createElement(i.default,{component:"Checkbox",disabled:z},t.createElement("label",{className:_,style:Object.assign(Object.assign({},null==I?void 0:I.style),k),onMouseEnter:x,onMouseLeave:S,onClick:G},t.createElement(n.default,Object.assign({},H,{onClick:V,prefixCls:W,className:q,disabled:z,ref:T})),null!=$&&t.createElement("span",{className:`${W}-label`},$))))});var b=e.i(8211),h=e.i(529681),v=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 y=t.forwardRef((e,n)=>{let{defaultValue:o,children:i,options:l=[],prefixCls:s,className:u,rootClassName:f,style:g,onChange:y}=e,$=v(e,["defaultValue","children","options","prefixCls","className","rootClassName","style","onChange"]),{getPrefixCls:C,direction:k}=t.useContext(a.ConfigContext),[x,S]=t.useState($.value||o||[]),[O,w]=t.useState([]);t.useEffect(()=>{"value"in $&&S($.value||[])},[$.value]);let E=t.useMemo(()=>l.map(e=>"string"==typeof e||"number"==typeof e?{label:e,value:e}:e),[l]),j=e=>{w(t=>t.filter(t=>t!==e))},N=e=>{w(t=>[].concat((0,b.default)(t),[e]))},I=e=>{let t=x.indexOf(e.value),r=(0,b.default)(x);-1===t?r.push(e.value):r.splice(t,1),"value"in $||S(r),null==y||y(r.filter(e=>O.includes(e)).sort((e,t)=>E.findIndex(t=>t.value===e)-E.findIndex(e=>e.value===t)))},P=C("checkbox",s),D=`${P}-group`,R=(0,c.default)(P),[z,A,M]=(0,p.default)(P,R),T=(0,h.default)($,["value","disabled"]),W=l.length?E.map(e=>t.createElement(m,{prefixCls:P,key:e.value.toString(),disabled:"disabled"in e?e.disabled:$.disabled,value:e.value,checked:x.includes(e.value),onChange:e.onChange,className:(0,r.default)(`${D}-item`,e.className),style:e.style,title:e.title,id:e.id,required:e.required},e.label)):i,B=t.useMemo(()=>({toggleOption:I,value:x,disabled:$.disabled,name:$.name,registerValue:N,cancelValue:j}),[I,x,$.disabled,$.name,N,j]),F=(0,r.default)(D,{[`${D}-rtl`]:"rtl"===k},u,f,M,R,A);return z(t.createElement("div",Object.assign({className:F,style:g},T,{ref:n}),t.createElement(d.default.Provider,{value:B},W)))});m.Group=y,m.__ANT_CHECKBOX=!0,e.s(["default",0,m],374276),e.s(["Checkbox",0,m],536916)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/054be755a9981063.js b/litellm/proxy/_experimental/out/_next/static/chunks/054be755a9981063.js new file mode 100644 index 00000000000..298d8c4b2f2 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/054be755a9981063.js @@ -0,0 +1 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,566606,e=>{"use strict";var t=e.i(843476),l=e.i(271645),a=e.i(618566),s=e.i(947293),i=e.i(602869),r=e.i(954616),n=e.i(266027),o=e.i(612256);let d=(0,e.i(243652).createQueryKeys)("onboarding");var c=e.i(268004),u=e.i(482725),m=e.i(56456);function g(){return(0,t.jsx)("div",{className:"mx-auto w-full max-w-md mt-10 flex justify-center",children:(0,t.jsx)(u.Spin,{indicator:(0,t.jsx)(m.LoadingOutlined,{spin:!0}),size:"large"})})}var h=e.i(560445),x=e.i(464571);function p(){return(0,t.jsxs)("div",{className:"mx-auto w-full max-w-md mt-10",children:[(0,t.jsx)(h.Alert,{type:"error",message:"Failed to load invitation",description:"The invitation link may be invalid or expired.",showIcon:!0}),(0,t.jsx)("div",{className:"mt-4",children:(0,t.jsx)(x.Button,{href:"/ui/login",children:"Back to Login"})})]})}var f=e.i(175712),y=e.i(808613),w=e.i(311451),v=e.i(898586);function j({variant:e,userEmail:a,isPending:s,claimError:i,onSubmit:r}){let[n]=y.Form.useForm();return l.default.useEffect(()=>{a&&n.setFieldValue("user_email",a)},[a,n]),(0,t.jsx)("div",{className:"mx-auto w-full max-w-md mt-10",children:(0,t.jsxs)(f.Card,{children:[(0,t.jsx)(v.Typography.Title,{level:5,className:"text-center mb-5",children:"🚅 LiteLLM"}),(0,t.jsx)(v.Typography.Title,{level:3,children:"reset_password"===e?"Reset Password":"Sign Up"}),(0,t.jsx)(v.Typography.Text,{children:"reset_password"===e?"Reset your password to access Admin UI.":"Claim your user account to login to Admin UI."}),"signup"===e&&(0,t.jsx)(h.Alert,{className:"mt-4",type:"info",message:"SSO",description:(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)("span",{children:"SSO is under the Enterprise Tier."}),(0,t.jsx)(x.Button,{type:"primary",size:"small",href:"https://forms.gle/W3U4PZpJGFHWtHyA9",target:"_blank",children:"Get Free Trial"})]}),showIcon:!0}),(0,t.jsxs)(y.Form,{className:"mt-10 mb-5",layout:"vertical",form:n,onFinish:e=>r({password:e.password}),children:[(0,t.jsx)(y.Form.Item,{label:"Email Address",name:"user_email",children:(0,t.jsx)(w.Input,{type:"email",disabled:!0})}),(0,t.jsx)(y.Form.Item,{label:"Password",name:"password",rules:[{required:!0,message:"password required to sign up"}],help:"reset_password"===e?"Enter your new password":"Create a password for your account",children:(0,t.jsx)(w.Input.Password,{})}),i&&(0,t.jsx)(h.Alert,{type:"error",message:i,showIcon:!0,className:"mb-4"}),(0,t.jsx)("div",{className:"mt-10",children:(0,t.jsx)(x.Button,{htmlType:"submit",loading:s,children:"reset_password"===e?"Reset Password":"Sign Up"})})]})]})})}function S({variant:e}){let u=(0,a.useSearchParams)().get("invitation_id"),[m,h]=l.default.useState(null),{data:x,isLoading:f,isError:y}=(e=>{let{isLoading:t}=(0,o.useUIConfig)();return(0,n.useQuery)({queryKey:d.detail(e??""),queryFn:async()=>{if(!e)throw Error("inviteId is required");return(0,i.getOnboardingCredentials)(e)},enabled:!!e&&!t})})(u),{mutate:w,isPending:v}=(0,r.useMutation)({mutationFn:async({accessToken:e,inviteId:t,userId:l,password:a})=>await (0,i.claimOnboardingToken)(e,t,l,a)}),S=x?.token?(0,s.jwtDecode)(x.token):null,b=S?.user_email??"",_=S?.user_id??null,k=S?.key??null;return f?(0,t.jsx)(g,{}):y?(0,t.jsx)(p,{}):(0,t.jsx)(j,{variant:e,userEmail:b,isPending:v,claimError:m,onSubmit:e=>{k&&_&&u&&(h(null),w({accessToken:k,inviteId:u,userId:_,password:e.password},{onSuccess:e=>{if(!e?.token)return void h("Failed to start session. Please try again.");(0,c.clearTokenCookies)(),(0,c.storeLoginToken)(e.token);let t=(0,i.getProxyBaseUrl)();window.location.href=t?`${t}/ui/?login=success`:"/ui/?login=success"},onError:e=>{h(e.message||"Failed to submit. Please try again.")}}))}})}function b(){let e=(0,a.useSearchParams)().get("action");return(0,t.jsx)(S,{variant:"reset_password"===e?"reset_password":"signup"})}function _(){return(0,t.jsx)(l.Suspense,{fallback:(0,t.jsx)("div",{className:"flex items-center justify-center min-h-screen",children:"Loading..."}),children:(0,t.jsx)(b,{})})}e.s(["default",()=>_],566606)},700514,e=>{"use strict";var t=e.i(271645);e.s(["defaultPageSize",0,25,"useBaseUrl",0,()=>{let[e,l]=(0,t.useState)("http://localhost:4000");return(0,t.useEffect)(()=>{{let{protocol:e,host:t}=window.location;l(`${e}//${t}`)}},[]),e}])},50882,e=>{"use strict";var t=e.i(843476),l=e.i(621482),a=e.i(243652),s=e.i(602869),i=e.i(135214);let r=(0,a.createQueryKeys)("infiniteKeyAliases");var n=e.i(56456),o=e.i(152473),d=e.i(199133),c=e.i(271645);e.s(["PaginatedKeyAliasSelect",0,({value:e,onChange:a,placeholder:u="Select a key alias",style:m,pageSize:g=50,allowClear:h=!0,disabled:x=!1,allFilters:p})=>{let[f,y]=(0,c.useState)(""),[w,v]=(0,o.useDebouncedState)("",{wait:300}),{data:j,fetchNextPage:S,hasNextPage:b,isFetchingNextPage:_,isLoading:k}=((e=50,t,a)=>{let{accessToken:n}=(0,i.default)();return(0,l.useInfiniteQuery)({queryKey:r.list({filters:{size:e,...t&&{search:t},...a&&{team_id:a}}}),queryFn:async({pageParam:l})=>await (0,s.keyAliasesCall)(n,l,e,t,a),initialPageParam:1,getNextPageParam:e=>{if(e.current_page{if(!j?.pages)return[];let e=new Set,t=[];for(let l of j.pages)for(let a of l.aliases)!a||e.has(a)||(e.add(a),t.push({label:a,value:a}));return t},[j]);return(0,t.jsx)(d.Select,{value:e||void 0,onChange:e=>{a?.(e??"")},placeholder:u,style:{width:"100%",...m},allowClear:h,disabled:x,showSearch:!0,filterOption:!1,onSearch:e=>{y(e),v(e)},searchValue:f,onPopupScroll:e=>{let t=e.currentTarget;(t.scrollTop+t.clientHeight)/t.scrollHeight>=.8&&b&&!_&&S()},loading:k,notFoundContent:k?(0,t.jsx)(n.LoadingOutlined,{spin:!0}):"No key aliases found",options:N,popupRender:e=>(0,t.jsxs)(t.Fragment,{children:[e,_&&(0,t.jsx)("div",{style:{textAlign:"center",padding:8},children:(0,t.jsx)(n.LoadingOutlined,{spin:!0})})]})})}],50882)},502501,693569,e=>{"use strict";var t=e.i(843476),l=e.i(785242),a=e.i(135214),s=e.i(846835),i=e.i(268004),r=e.i(309426),n=e.i(350967),o=e.i(947293),d=e.i(618566),c=e.i(271645),u=e.i(566606),m=e.i(602869);let g=async(e,t,l,a,s)=>{let i;i="Admin"!=l&&"Admin Viewer"!=l?await (0,m.teamListCall)(e,a?.organization_id||null,t):await (0,m.teamListCall)(e,a?.organization_id||null),console.log(`givenTeams: ${i}`),s(i)};var h=e.i(702597),x=e.i(207082),p=e.i(109799),f=e.i(500330),y=e.i(871943),w=e.i(502547),v=e.i(360820),j=e.i(94629),S=e.i(152990),b=e.i(682830),_=e.i(389083),k=e.i(994388),N=e.i(752978),z=e.i(269200),I=e.i(942232),C=e.i(977572),D=e.i(427612),T=e.i(64848),A=e.i(496020),P=e.i(599724),O=e.i(827252),U=e.i(772345),R=e.i(464571),L=e.i(282786),K=e.i(981339),E=e.i(262218),B=e.i(592968),M=e.i(898586),$=e.i(355619),F=e.i(633627),V=e.i(374009),H=e.i(700514),W=e.i(50882),q=e.i(969550),J=e.i(304911),G=e.i(20147);function Q({teams:e,organizations:l,onSortChange:s,currentSort:i}){let{data:r}=(0,p.useOrganizations)(),n=r??l??[],[o,d]=(0,c.useState)(null),[u,g]=c.default.useState(()=>i?[{id:i.sortBy,desc:"desc"===i.sortOrder}]:[{id:"created_at",desc:!0}]),[h,Q]=c.default.useState({pageIndex:0,pageSize:50}),Z=u.length>0?u[0].id:null,X=u.length>0?u[0].desc?"desc":"asc":null,{data:Y,isPending:ee,isFetching:et,isError:el,refetch:ea}=(0,x.useKeys)(h.pageIndex+1,h.pageSize,{sortBy:Z||void 0,sortOrder:X||void 0,expand:"user"}),[es,ei]=(0,c.useState)({}),{filters:er,filteredKeys:en,filteredTotalCount:eo,allTeams:ed,allOrganizations:ec,handleFilterChange:eu,handleFilterReset:em}=function({keys:e,teams:t,organizations:l}){let s={"Team ID":"","Organization ID":"","Key Alias":"","User ID":"","Sort By":"created_at","Sort Order":"desc"},{accessToken:i}=(0,a.default)(),[r,n]=(0,c.useState)(s),[o,d]=(0,c.useState)(t||[]),[u,g]=(0,c.useState)(l||[]),[h,x]=(0,c.useState)(e),[p,f]=(0,c.useState)(null),y=(0,c.useRef)(0),w=(0,c.useCallback)((0,V.default)(async e=>{if(!i)return;let t=Date.now();y.current=t;try{let l=await (0,m.keyListCall)(i,e["Organization ID"]||null,e["Team ID"]||null,e["Key Alias"]||null,e["User ID"]||null,e["Key Hash"]||null,1,H.defaultPageSize,e["Sort By"]||null,e["Sort Order"]||null);t===y.current&&l&&(x(l.keys),f(l.total_count??null),console.log("called from debouncedSearch filters:",JSON.stringify(e)),console.log("called from debouncedSearch data:",JSON.stringify(l)))}catch(e){console.error("Error searching users:",e)}},300),[i]);return(0,c.useEffect)(()=>{if(!e)return void x([]);let t=[...e];r["Team ID"]&&(t=t.filter(e=>e.team_id===r["Team ID"])),r["Organization ID"]&&(t=t.filter(e=>(e.organization_id??e.org_id)===r["Organization ID"])),x(e=>e.length===t.length&&e.every((e,l)=>e===t[l])?e:t)},[e,r]),(0,c.useEffect)(()=>{let e=async()=>{let e=await (0,F.fetchAllTeams)(i);e.length>0&&d(e);let t=await (0,F.fetchAllOrganizations)(i);t.length>0&&g(t)};i&&e()},[i]),(0,c.useEffect)(()=>{t&&t.length>0&&d(e=>e.length{l&&l.length>0&&g(e=>e.length{n({"Team ID":e["Team ID"]||"","Organization ID":e["Organization ID"]||"","Key Alias":e["Key Alias"]||"","User ID":e["User ID"]||"","Sort By":e["Sort By"]||"created_at","Sort Order":e["Sort Order"]||"desc"}),t||w({...r,...e})},handleFilterReset:()=>{n(s),f(null),w(s)}}}({keys:(0,c.useMemo)(()=>Y?.keys??[],[Y]),teams:e,organizations:l}),eg=(0,c.useDeferredValue)(et),eh=(et||eg)&&!el,ex=eo??Y?.total_count??0;(0,c.useEffect)(()=>{if(ea){let e=()=>{ea()};return window.addEventListener("storage",e),()=>{window.removeEventListener("storage",e)}}},[ea]);let ep=(0,c.useMemo)(()=>[{id:"expander",header:()=>null,size:40,enableSorting:!1,cell:({row:e})=>e.getCanExpand()?(0,t.jsx)("button",{onClick:e.getToggleExpandedHandler(),style:{cursor:"pointer"},children:e.getIsExpanded()?"▼":"▶"}):null},{id:"token",accessorKey:"token",header:"Key ID",size:100,enableSorting:!0,cell:e=>{let l=e.getValue(),a=e.cell.column.getSize();return(0,t.jsx)(B.Tooltip,{title:l,children:(0,t.jsx)(k.Button,{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 block",style:{maxWidth:a,overflow:"hidden"},onClick:()=>d(e.row.original),children:l??"-"})})}},{id:"key_alias",accessorKey:"key_alias",header:"Key Alias",size:150,enableSorting:!0,cell:e=>{let l=e.getValue(),a=e.cell.column.getSize();return(0,t.jsx)("span",{className:"font-mono text-xs truncate block",style:{maxWidth:a,overflow:"hidden"},children:l??"-"})}},{id:"status",header:"Status",size:100,enableSorting:!1,cell:({row:e})=>{let l=e.original;if(!0!==l.blocked)return(0,t.jsx)(E.Tag,{color:"green","data-testid":`key-status-${l.token_id}`,children:"Active"});let a=l.metadata?.scim_blocked===!0;return(0,t.jsx)(B.Tooltip,{title:a?"Blocked by SCIM (external identity provider deactivated or deleted the owning user).":"Blocked. Requests using this key will be rejected with 401.",children:(0,t.jsx)(E.Tag,{color:"red","data-testid":`key-status-${l.token_id}`,children:"Blocked"})})}},{id:"key_name",accessorKey:"key_name",header:"Secret Key",size:120,enableSorting:!1,cell:e=>(0,t.jsx)("span",{className:"font-mono text-xs",children:e.getValue()})},{id:"team_alias",accessorKey:"team_id",header:"Team",size:120,enableSorting:!1,cell:l=>{let a=l.getValue();if(!a)return"-";let s=e?.find(e=>e.team_id===a),i=s?.team_alias||a,r=l.cell.column.getSize();return(0,t.jsx)("span",{className:"font-mono text-xs truncate block",style:{maxWidth:r,overflow:"hidden"},children:i})}},{id:"organization_alias",accessorKey:"org_id",header:"Organization",size:140,enableSorting:!1,cell:e=>{let l=e.getValue();if(!l)return"-";let a=n.find(e=>e.organization_id===l),s=a?.organization_alias||l,i=e.cell.column.getSize();return(0,t.jsx)("span",{className:"font-mono text-xs truncate block",style:{maxWidth:i,overflow:"hidden"},children:s})}},{id:"user",accessorKey:"user",header:()=>(0,t.jsxs)("span",{className:"flex items-center gap-1",children:["User",(0,t.jsx)(L.Popover,{content:"Displays the first available value: User Alias, User Email, or User ID.",trigger:"hover",children:(0,t.jsx)(O.InfoCircleOutlined,{className:"text-gray-400 text-xs cursor-help"})})]}),size:160,enableSorting:!1,cell:({row:e})=>{let l=e.original,a=l.user?.user_alias??null,s=l.user?.user_email??l.user_email??null,i=l.user_id??null,r="default_user_id"===i,n=a||s||i,o=(0,t.jsx)("div",{className:"flex flex-col gap-2 text-xs min-w-[200px] max-w-[300px]",children:[{label:"User Alias",value:a},{label:"User Email",value:s},{label:"User ID",value:i}].map(({label:e,value:l})=>(0,t.jsxs)("div",{className:"flex flex-col min-w-0",children:[(0,t.jsx)("span",{className:"text-gray-400",children:e}),l?(0,t.jsx)(M.Typography.Text,{className:"font-mono text-xs",ellipsis:{tooltip:l},copyable:!0,children:l}):(0,t.jsx)("span",{className:"font-mono",children:"-"})]},e))});return!r||a||s?(0,t.jsx)(L.Popover,{content:o,trigger:"hover",placement:"bottomLeft",children:(0,t.jsx)("span",{className:"font-mono text-xs truncate block cursor-default",style:{maxWidth:160,overflow:"hidden"},children:n||"-"})}):(0,t.jsx)(L.Popover,{content:o,trigger:"hover",placement:"bottomLeft",children:(0,t.jsx)("span",{className:"cursor-default",children:(0,t.jsx)(J.default,{userId:i})})})}},{id:"created_at",accessorKey:"created_at",header:"Created At",size:120,enableSorting:!0,cell:e=>{let t=e.getValue();return t?new Date(t).toLocaleDateString():"-"}},{id:"created_by",accessorKey:"created_by",header:"Created By",size:160,enableSorting:!1,cell:e=>{let l=e.getValue();if(!l)return"-";let a=e.row.original.created_by_user,s=a?.user_alias??null,i=a?.user_email??null,r="default_user_id"===l,n=s||i||l,o=(0,t.jsx)("div",{className:"flex flex-col gap-2 text-xs min-w-[200px] max-w-[300px]",children:[{label:"User Alias",value:s},{label:"User Email",value:i},{label:"User ID",value:l}].map(({label:e,value:l})=>(0,t.jsxs)("div",{className:"flex flex-col min-w-0",children:[(0,t.jsx)("span",{className:"text-gray-400",children:e}),l?(0,t.jsx)(M.Typography.Text,{className:"font-mono text-xs",ellipsis:{tooltip:l},copyable:!0,children:l}):(0,t.jsx)("span",{className:"font-mono",children:"-"})]},e))});return!r||s||i?(0,t.jsx)(L.Popover,{content:o,trigger:"hover",placement:"bottomLeft",children:(0,t.jsx)("span",{className:"font-mono text-xs truncate block cursor-default",style:{maxWidth:160,overflow:"hidden"},children:n})}):(0,t.jsx)(L.Popover,{content:o,trigger:"hover",placement:"bottomLeft",children:(0,t.jsx)("span",{className:"cursor-default",children:(0,t.jsx)(J.default,{userId:l})})})}},{id:"updated_at",accessorKey:"updated_at",header:"Updated At",size:120,enableSorting:!0,cell:e=>{let t=e.getValue();return t?new Date(t).toLocaleDateString():"Never"}},{id:"last_active",accessorKey:"last_active",header:()=>(0,t.jsxs)("span",{className:"flex items-center gap-1",children:["Last Active",(0,t.jsx)(L.Popover,{content:"This is a new field and is not backfilled. Only new key usage will update this value.",trigger:"hover",children:(0,t.jsx)(O.InfoCircleOutlined,{className:"text-gray-400 text-xs cursor-help"})})]}),size:130,enableSorting:!1,cell:e=>{let l=e.getValue();if(!l)return"Unknown";let a=new Date(l);return(0,t.jsx)(B.Tooltip,{title:a.toLocaleString(void 0,{dateStyle:"medium",timeStyle:"long"}),children:(0,t.jsx)("span",{children:a.toLocaleDateString()})})}},{id:"expires",accessorKey:"expires",header:"Expires",size:120,enableSorting:!1,cell:e=>{let t=e.getValue();return t?new Date(t).toLocaleDateString():"Never"}},{id:"spend",accessorKey:"spend",header:"Spend (USD)",size:100,enableSorting:!0,cell:e=>(0,f.formatNumberWithCommas)(e.getValue(),4)},{id:"max_budget",accessorKey:"max_budget",header:"Budget (USD)",size:110,enableSorting:!0,cell:e=>{let t=e.getValue();return null===t?"Unlimited":`$${(0,f.formatNumberWithCommas)(t)}`}},{id:"budget_reset_at",accessorKey:"budget_reset_at",header:"Budget Reset",size:130,enableSorting:!1,cell:e=>{let t=e.getValue();return t?new Date(t).toLocaleString():"Never"}},{id:"models",accessorKey:"models",header:"Models",size:200,enableSorting:!1,cell:e=>{let l=e.getValue();return(0,t.jsx)("div",{className:"flex flex-col py-2",children:Array.isArray(l)?(0,t.jsx)("div",{className:"flex flex-col",children:0===l.length?(0,t.jsx)(_.Badge,{size:"xs",className:"mb-1",color:"red",children:(0,t.jsx)(P.Text,{children:"All Proxy Models"})}):(0,t.jsx)(t.Fragment,{children:(0,t.jsxs)("div",{className:"flex items-start",children:[l.length>3&&(0,t.jsx)("div",{children:(0,t.jsx)(N.Icon,{icon:es[e.row.id]?y.ChevronDownIcon:w.ChevronRightIcon,className:"cursor-pointer",size:"xs",onClick:()=>{ei(t=>({...t,[e.row.id]:!t[e.row.id]}))}})}),(0,t.jsxs)("div",{className:"flex flex-wrap gap-1",children:[l.slice(0,3).map((e,l)=>"all-proxy-models"===e?(0,t.jsx)(_.Badge,{size:"xs",color:"red",children:(0,t.jsx)(P.Text,{children:"All Proxy Models"})},l):(0,t.jsx)(_.Badge,{size:"xs",color:"blue",children:(0,t.jsx)(P.Text,{children:e.length>30?`${(0,$.getModelDisplayName)(e).slice(0,30)}...`:(0,$.getModelDisplayName)(e)})},l)),l.length>3&&!es[e.row.id]&&(0,t.jsx)(_.Badge,{size:"xs",color:"gray",className:"cursor-pointer",children:(0,t.jsxs)(P.Text,{children:["+",l.length-3," ",l.length-3==1?"more model":"more models"]})}),es[e.row.id]&&(0,t.jsx)("div",{className:"flex flex-wrap gap-1",children:l.slice(3).map((e,l)=>"all-proxy-models"===e?(0,t.jsx)(_.Badge,{size:"xs",color:"red",children:(0,t.jsx)(P.Text,{children:"All Proxy Models"})},l+3):(0,t.jsx)(_.Badge,{size:"xs",color:"blue",children:(0,t.jsx)(P.Text,{children:e.length>30?`${(0,$.getModelDisplayName)(e).slice(0,30)}...`:(0,$.getModelDisplayName)(e)})},l+3))})]})]})})}):null})}},{id:"rate_limits",header:"Rate Limits",size:140,enableSorting:!1,cell:({row:e})=>{let l=e.original;return(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{children:["TPM: ",null!==l.tpm_limit?l.tpm_limit:"Unlimited"]}),(0,t.jsxs)("div",{children:["RPM: ",null!==l.rpm_limit?l.rpm_limit:"Unlimited"]})]})}}],[e,n]),ef=[{name:"Team ID",label:"Team ID",isSearchable:!0,searchFn:async e=>ed&&0!==ed.length?ed.filter(t=>t.team_id.toLowerCase().includes(e.toLowerCase())||t.team_alias&&t.team_alias.toLowerCase().includes(e.toLowerCase())).map(e=>({label:`${e.team_alias||e.team_id} (${e.team_id})`,value:e.team_id})):[]},{name:"Organization ID",label:"Organization ID",isSearchable:!0,searchFn:async e=>ec&&0!==ec.length?ec.filter(t=>t.organization_id?.toLowerCase().includes(e.toLowerCase())??!1).filter(e=>null!==e.organization_id&&void 0!==e.organization_id).map(e=>({label:`${e.organization_id||"Unknown"} (${e.organization_id})`,value:e.organization_id})):[]},{name:"Key Alias",label:"Key Alias",customComponent:W.PaginatedKeyAliasSelect},{name:"User ID",label:"User ID",isSearchable:!1},{name:"Key Hash",label:"Key Hash",isSearchable:!1}],ey=(0,S.useReactTable)({data:en,columns:ep.filter(e=>"expander"!==e.id),columnResizeMode:"onChange",columnResizeDirection:"ltr",state:{sorting:u,pagination:h},onSortingChange:e=>{let t="function"==typeof e?e(u):e;if(g(t),t&&t.length>0){let e=t[0],l=e.id,a=e.desc?"desc":"asc";eu({...er,"Sort By":l,"Sort Order":a},!0),s?.(l,a)}},onPaginationChange:Q,getCoreRowModel:(0,b.getCoreRowModel)(),getSortedRowModel:(0,b.getSortedRowModel)(),getPaginationRowModel:(0,b.getPaginationRowModel)(),enableSorting:!0,manualSorting:!1,manualPagination:!0,pageCount:Math.ceil(ex/h.pageSize)});c.default.useEffect(()=>{i&&g([{id:i.sortBy,desc:"desc"===i.sortOrder}])},[i]);let{pageIndex:ew,pageSize:ev}=ey.getState().pagination,ej=Math.min((ew+1)*ev,ex),eS=`${ew*ev+1} - ${ej}`;return(0,t.jsx)("div",{className:"w-full h-full overflow-hidden",children:o?(0,t.jsx)(G.default,{keyId:o.token,onClose:()=>d(null),keyData:o,teams:ed,onDelete:ea}):(0,t.jsxs)("div",{className:"border-b py-4 flex-1 overflow-hidden",children:[(0,t.jsx)("div",{className:"w-full mb-6",children:(0,t.jsx)(q.default,{options:ef,onApplyFilters:eu,initialValues:er,onResetFilters:em})}),(0,t.jsxs)("div",{className:"flex items-center justify-between w-full mb-4",children:[(0,t.jsxs)("div",{className:"inline-flex items-center gap-2",children:[ee?(0,t.jsx)(K.Skeleton.Node,{active:!0,style:{width:200,height:20}}):(0,t.jsxs)("span",{className:"inline-flex text-sm text-gray-700",children:["Showing ",eS," of ",ex," results"]}),(0,t.jsx)(R.Button,{type:"default",icon:(0,t.jsx)(U.SyncOutlined,{spin:eh}),onClick:()=>{ea()},disabled:eh,title:"Fetch data",children:eh?"Fetching":"Fetch"})]}),(0,t.jsxs)("div",{className:"inline-flex items-center gap-2",children:[ee?(0,t.jsx)(K.Skeleton.Node,{active:!0,style:{width:74,height:20}}):(0,t.jsxs)("span",{className:"text-sm text-gray-700",children:["Page ",ew+1," of ",ey.getPageCount()]}),ee?(0,t.jsx)(K.Skeleton.Button,{active:!0,size:"small",style:{width:84,height:30}}):(0,t.jsx)("button",{onClick:()=>ey.previousPage(),disabled:ee||!ey.getCanPreviousPage(),className:"px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed",children:"Previous"}),ee?(0,t.jsx)(K.Skeleton.Button,{active:!0,size:"small",style:{width:58,height:30}}):(0,t.jsx)("button",{onClick:()=>ey.nextPage(),disabled:ee||!ey.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)(z.Table,{className:"[&_td]:py-0.5 [&_th]:py-1",style:{width:ey.getCenterTotalSize()},children:[(0,t.jsx)(D.TableHead,{children:ey.getHeaderGroups().map(e=>(0,t.jsx)(A.TableRow,{children:e.headers.map(e=>(0,t.jsx)(T.TableHeaderCell,{"data-header-id":e.id,className:`py-1 h-8 relative hover:bg-gray-50 ${"actions"===e.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)]":""}`,style:{width:e.getSize(),position:"relative",cursor:e.column.getCanSort()?"pointer":"default"},onMouseEnter:()=>{let t=document.querySelector(`[data-header-id="${e.id}"] .resizer`);t&&(t.style.opacity="0.5")},onMouseLeave:()=>{let t=document.querySelector(`[data-header-id="${e.id}"] .resizer`);t&&!e.column.getIsResizing()&&(t.style.opacity="0")},onClick:e.column.getCanSort()?e.column.getToggleSortingHandler():void 0,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,S.flexRender)(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)(v.ChevronUpIcon,{className:"h-4 w-4 text-blue-500"}),desc:(0,t.jsx)(y.ChevronDownIcon,{className:"h-4 w-4 text-blue-500"})})[e.column.getIsSorted()]:(0,t.jsx)(j.SwitchVerticalIcon,{className:"h-4 w-4 text-gray-400"})}),(0,t.jsx)("div",{onDoubleClick:()=>e.column.resetSize(),onMouseDown:e.getResizeHandler(),onTouchStart:e.getResizeHandler(),className:`resizer ${ey.options.columnResizeDirection} ${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()}})]})},e.id))},e.id))}),(0,t.jsx)(I.TableBody,{children:ee?(0,t.jsx)(A.TableRow,{children:(0,t.jsx)(C.TableCell,{colSpan:ep.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"🚅 Loading keys..."})})})}):en.length>0?ey.getRowModel().rows.map(e=>(0,t.jsx)(A.TableRow,{className:"h-8",children:e.getVisibleCells().map(e=>(0,t.jsx)(C.TableCell,{style:{width:e.column.getSize(),maxWidth:"8-x",whiteSpace:"pre-wrap",overflow:"hidden"},className:`py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap ${"models"===e.column.id&&Array.isArray(e.getValue())&&e.getValue().length>3?"px-0":""}`,children:(0,S.flexRender)(e.column.columnDef.cell,e.getContext())},e.id))},e.id)):(0,t.jsx)(A.TableRow,{children:(0,t.jsx)(C.TableCell,{colSpan:ep.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"No keys found"})})})})})]})})})})]})})}let Z=({userID:e,userRole:l,teams:a,keys:s,setUserRole:x,userEmail:p,setUserEmail:f,setTeams:y,setKeys:w,premiumUser:v,organizations:j,addKey:S,createClicked:b,autoOpenCreate:_,prefillData:k})=>{let[N,z]=(0,c.useState)(null),[I,C]=(0,c.useState)(null),D=(0,d.useSearchParams)(),T=(0,i.getCookie)("token"),A=D.get("invitation_id"),[P,O]=(0,c.useState)(null),[U,R]=(0,c.useState)(null),[L,K]=(0,c.useState)([]),[E,B]=(0,c.useState)(null),[M,$]=(0,c.useState)(null);if((0,c.useEffect)(()=>{let e=()=>{let e=sessionStorage.getItem("token");sessionStorage.clear(),e&&sessionStorage.setItem("token",e)};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[]),(0,c.useEffect)(()=>{if(T){let e=(0,o.jwtDecode)(T);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),O(e.key),e.user_role){let t=function(e){if(!e)return"Undefined Role";switch(console.log(`Received user role: ${e}`),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";case"internal_user":return"Internal User";case"internal_user_viewer":return"Internal Viewer";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",t),x(t)}else console.log("User role not defined");e.user_email?f(e.user_email):console.log(`User Email is not set ${e}`)}}if(e&&P&&l&&!N){let t=sessionStorage.getItem("userModels"+e);t?K(JSON.parse(t)):(console.log(`currentOrg: ${JSON.stringify(I)}`),(async()=>{try{let t=await (0,m.getProxyUISettings)(P);B(t);let a=await (0,m.userGetInfoV2)(P,e);z(a),sessionStorage.setItem("userSpendData"+e,JSON.stringify(a));let s=(await (0,m.modelAvailableCall)(P,e,l)).data.map(e=>e.id);console.log("available_model_names:",s),K(s),console.log("userModels:",L),sessionStorage.setItem("userModels"+e,JSON.stringify(s))}catch(e){console.error("There was an error fetching the data",e),e.message.includes("Invalid proxy server token passed")&&F()}})(),g(P,e,l,I,y))}},[e,T,P,l]),(0,c.useEffect)(()=>{P&&(async()=>{try{let e=await (0,m.keyInfoCall)(P,[P]);console.log("keyInfo: ",e)}catch(e){e.message.includes("Invalid proxy server token passed")&&F()}})()},[P]),(0,c.useEffect)(()=>{console.log(`currentOrg: ${JSON.stringify(I)}, accessToken: ${P}, userID: ${e}, userRole: ${l}`),P&&(console.log("fetching teams"),g(P,e,l,I,y))},[I]),(0,c.useEffect)(()=>{if(null!==s&&null!=M&&null!==M.team_id){let e=0;for(let t of(console.log(`keys: ${JSON.stringify(s)}`),s))M.hasOwnProperty("team_id")&&null!==t.team_id&&t.team_id===M.team_id&&(e+=t.spend);console.log(`sum: ${e}`),R(e)}else if(null!==s){let e=0;for(let t of s)e+=t.spend;R(e)}},[M]),null!=A)return(0,t.jsx)(u.default,{});function F(){(0,i.clearTokenCookies)();let e=(0,m.getProxyBaseUrl)();console.log("proxyBaseUrl:",e);let t=e?`${e}/sso/key/generate`:"/sso/key/generate";return console.log("Full URL:",t),window.location.href=t,null}if(null==T)return console.log("All cookies before redirect:",document.cookie),F(),null;try{let e=(0,o.jwtDecode)(T);console.log("Decoded token:",e);let t=e.exp,l=Math.floor(Date.now()/1e3);if(t&&l>=t)return console.log("Token expired, redirecting to login"),F(),null}catch(e){return console.error("Error decoding token:",e),(0,i.clearTokenCookies)(),F(),null}if(null==P)return null;if(null==e)return(0,t.jsx)("h1",{children:"User ID is not set"});null==l&&x("App Owner");let V="Admin Viewer"!==l&&"proxy_admin_viewer"!==l;return console.log("inside user dashboard, selected team",M),console.log("All cookies after redirect:",document.cookie),(0,t.jsx)("div",{className:"w-full mx-4 h-[75vh]",children:(0,t.jsx)(n.Grid,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:(0,t.jsxs)(r.Col,{numColSpan:1,className:"flex flex-col gap-2",children:[V&&(0,t.jsx)(h.default,{team:M,teams:a,data:s,addKey:S,autoOpenCreate:_,prefillData:k},M?M.team_id:null),(0,t.jsx)(Q,{teams:a,organizations:j})]})})})};e.s(["default",0,Z],693569);var X=e.i(557951);function Y(){let{userId:e,userRole:i,userEmail:r,accessToken:n,premiumUser:o}=(0,a.default)(),{setUserRole:u,setUserEmail:m}=(0,X.useAuth)(),g=(0,d.useSearchParams)(),[h,x]=(0,c.useState)(null),[p,f]=(0,c.useState)([]),[y,w]=(0,c.useState)([]),[v,j]=(0,c.useState)(!1),S="true"===g.get("create"),b=(0,c.useMemo)(()=>{if(!S)return;let e=g.get("owned_by"),t=g.get("team_id"),l=g.get("key_alias"),a=g.get("models"),s=g.get("key_type");if(!e&&!t&&!l&&!a&&!s)return;let i=e&&["you","service_account","another_user"].includes(e)?e:void 0,r=s&&["default","llm_api","management"].includes(s)?s:void 0,n=l?l.trim().slice(0,256):void 0,o=a?a.split(",").slice(0,100).map(e=>e.trim().slice(0,256)).filter(e=>e.length>0):void 0;return{owned_by:i,team_id:t?.trim()||void 0,key_alias:n,models:o&&o.length>0?o:void 0,key_type:r}},[g,S]);return(0,c.useEffect)(()=>{n&&e&&i&&(0,l.teamListCall)(n,1,100,{userID:"Admin"!==i&&"Admin Viewer"!==i?e:null}).then(e=>x(e.teams??[])).catch(console.error),n&&(0,s.fetchOrganizations)(n,w)},[n,e,i]),(0,t.jsx)(Z,{userID:e,userRole:i,premiumUser:o??!1,teams:h,keys:p,setUserRole:u,userEmail:r,setUserEmail:m,setTeams:x,setKeys:f,organizations:y,addKey:e=>{f(t=>t?[...t,e]:[e]),j(e=>!e)},createClicked:v,autoOpenCreate:S,prefillData:b})}e.s(["default",()=>Y],502501)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/05e9ff30be0ddaae.js b/litellm/proxy/_experimental/out/_next/static/chunks/05e9ff30be0ddaae.js deleted file mode 100644 index f926944354f..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/05e9ff30be0ddaae.js +++ /dev/null @@ -1,4 +0,0 @@ -(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,751734,144582,e=>{"use strict";var t=e.i(271645);let r=(0,t.createContext)(0);e.s(["default",()=>r],751734);let n=(0,t.createContext)({selectedValue:void 0,handleValueChange:void 0});e.s(["default",()=>n],144582)},404206,e=>{"use strict";var t=e.i(290571),r=e.i(751734),n=e.i(144582),o=e.i(444755),a=e.i(673706),s=e.i(271645);let l=(0,a.makeClassName)("TabPanel"),i=s.default.forwardRef((e,a)=>{let{children:i,className:u}=e,c=(0,t.__rest)(e,["children","className"]),{selectedValue:d}=(0,s.useContext)(n.default),f=d===(0,s.useContext)(r.default);return s.default.createElement("div",Object.assign({ref:a,className:(0,o.tremorTwMerge)(l("root"),"w-full mt-2",f?"":"hidden",u),"aria-selected":f?"true":"false"},c),i)});i.displayName="TabPanel",e.s(["TabPanel",()=>i],404206)},429427,371330,80758,402155,368578,544508,746725,835696,941444,914189,394487,e=>{"use strict";let t;e.i(247167);var r=e.i(271645);let n="u">typeof document?r.default.useLayoutEffect:()=>{},o=e=>{var t;return null!=(t=null==e?void 0:e.ownerDocument)?t:document},a=e=>e&&"window"in e&&e.window===e?e:o(e).defaultView||window;"u">typeof Element&&Element.prototype;let s=["input:not([disabled]):not([type=hidden])","select:not([disabled])","textarea:not([disabled])","button:not([disabled])","a[href]","area[href]","summary","iframe","object","embed","audio[controls]","video[controls]",'[contenteditable]:not([contenteditable^="false"])',"permission"];s.join(":not([hidden]),"),s.push('[tabindex]:not([tabindex="-1"]):not([disabled])'),s.join(':not([hidden]):not([tabindex="-1"]),');let l=null;function i(e){return e.nativeEvent=e,e.isDefaultPrevented=()=>e.defaultPrevented,e.isPropagationStopped=()=>e.cancelBubble,e.persist=()=>{},e}function u(e){let t=(0,r.useRef)({isFocused:!1,observer:null});return n(()=>{let e=t.current;return()=>{e.observer&&(e.observer.disconnect(),e.observer=null)}},[]),(0,r.useCallback)(r=>{if(r.target instanceof HTMLButtonElement||r.target instanceof HTMLInputElement||r.target instanceof HTMLTextAreaElement||r.target instanceof HTMLSelectElement){t.current.isFocused=!0;let n=r.target;n.addEventListener("focusout",r=>{if(t.current.isFocused=!1,n.disabled){let t=i(r);null==e||e(t)}t.current.observer&&(t.current.observer.disconnect(),t.current.observer=null)},{once:!0}),t.current.observer=new MutationObserver(()=>{if(t.current.isFocused&&n.disabled){var e;null==(e=t.current.observer)||e.disconnect();let r=n===document.activeElement?null:document.activeElement;n.dispatchEvent(new FocusEvent("blur",{relatedTarget:r})),n.dispatchEvent(new FocusEvent("focusout",{bubbles:!0,relatedTarget:r}))}}),t.current.observer.observe(n,{attributes:!0,attributeFilter:["disabled"]})}},[e])}function c(e){var t;if("u"e.test(t.brand))||e.test(window.navigator.userAgent)}function d(e){var t;return"u">typeof window&&null!=window.navigator&&e.test((null==(t=window.navigator.userAgentData)?void 0:t.platform)||window.navigator.platform)}function f(e){let t=null;return()=>(null==t&&(t=e()),t)}let p=f(function(){return d(/^Mac/i)}),m=f(function(){return d(/^iPhone/i)}),v=f(function(){return d(/^iPad/i)||p()&&navigator.maxTouchPoints>1}),b=f(function(){return m()||v()});f(function(){return p()||b()});let g=f(function(){return c(/AppleWebKit/i)&&!h()}),h=f(function(){return c(/Chrome/i)}),y=f(function(){return c(/Android/i)}),E=f(function(){return c(/Firefox/i)});function w(e,t,r=!0){var n,o;let{metaKey:a,ctrlKey:s,altKey:i,shiftKey:u}=t;E()&&(null==(o=window.event)||null==(n=o.type)?void 0:n.startsWith("key"))&&"_blank"===e.target&&(p()?a=!0:s=!0);let c=g()&&p()&&!v()&&1?new KeyboardEvent("keydown",{keyIdentifier:"Enter",metaKey:a,ctrlKey:s,altKey:i,shiftKey:u}):new MouseEvent("click",{metaKey:a,ctrlKey:s,altKey:i,shiftKey:u,detail:1,bubbles:!0,cancelable:!0});if(w.isOpening=r,function(){if(null==l){l=!1;try{document.createElement("div").focus({get preventScroll(){return l=!0,!0}})}catch{}}return l}())e.focus({preventScroll:!0});else{let t=function(e){let t=e.parentNode,r=[],n=document.scrollingElement||document.documentElement;for(;t instanceof HTMLElement&&t!==n;)(t.offsetHeighttypeof window&&window.document&&window.document.createElement,new WeakMap;r.default.useId;let x=null,F=new Set,P=new Map,k=!1,L=!1,N={Tab:!0,Escape:!0};function C(e,t){for(let r of F)r(e,t)}function I(e){k=!0,w.isOpening||e.metaKey||!p()&&e.altKey||e.ctrlKey||"Control"===e.key||"Shift"===e.key||"Meta"===e.key||(x="keyboard",C("keyboard",e))}function S(e){x="pointer","pointerType"in e&&e.pointerType,("mousedown"===e.type||"pointerdown"===e.type)&&(k=!0,C("pointer",e))}function A(e){w.isOpening||(""!==e.pointerType||!e.isTrusted)&&(y()&&e.pointerType?"click"!==e.type||1!==e.buttons:0!==e.detail||e.pointerType)||(k=!0,x="virtual")}function M(e){e.target!==window&&e.target!==document&&e.isTrusted&&(k||L||(x="virtual",C("virtual",e)),k=!1,L=!1)}function R(){k=!1,L=!0}function O(e){if("u"typeof PointerEvent&&(r.addEventListener("pointerdown",S,!0),r.addEventListener("pointermove",S,!0),r.addEventListener("pointerup",S,!0)),t.addEventListener("beforeunload",()=>{D(e)},{once:!0}),P.set(t,{focus:n})}let D=(e,t)=>{let r=a(e),n=o(e);t&&n.removeEventListener("DOMContentLoaded",t),P.has(r)&&(r.HTMLElement.prototype.focus=P.get(r).focus,n.removeEventListener("keydown",I,!0),n.removeEventListener("keyup",I,!0),n.removeEventListener("click",A,!0),r.removeEventListener("focus",M,!0),r.removeEventListener("blur",R,!1),"u">typeof PointerEvent&&(n.removeEventListener("pointerdown",S,!0),n.removeEventListener("pointermove",S,!0),n.removeEventListener("pointerup",S,!0)),P.delete(r))};function H(){return"pointer"!==x}"u">typeof document&&("loading"!==(t=o(void 0)).readyState?O(void 0):t.addEventListener("DOMContentLoaded",()=>{O(void 0)}));let j=new Set(["checkbox","radio","range","color","file","image","button","submit","reset"]);function K(e,t){return!!t&&!!e&&e.contains(t)}function W(){let e=(0,r.useRef)(new Map),t=(0,r.useCallback)((t,r,n,o)=>{let a=(null==o?void 0:o.once)?(...t)=>{e.current.delete(n),n(...t)}:n;e.current.set(n,{type:r,eventTarget:t,fn:a,options:o}),t.addEventListener(r,a,o)},[]),n=(0,r.useCallback)((t,r,n,o)=>{var a;let s=(null==(a=e.current.get(n))?void 0:a.fn)||n;t.removeEventListener(r,s,o),e.current.delete(n)},[]),o=(0,r.useCallback)(()=>{e.current.forEach((e,t)=>{n(e.eventTarget,e.type,t,e.options)})},[n]);return(0,r.useEffect)(()=>o,[o]),{addGlobalListener:t,removeGlobalListener:n,removeAllGlobalListeners:o}}function B(e={}){var t;let{autoFocus:n=!1,isTextInput:s,within:l}=e,c=(0,r.useRef)({isFocused:!1,isFocusVisible:n||H()}),[d,f]=(0,r.useState)(!1),[p,m]=(0,r.useState)(()=>c.current.isFocused&&c.current.isFocusVisible),v=(0,r.useCallback)(()=>m(c.current.isFocused&&c.current.isFocusVisible),[]),b=(0,r.useCallback)(e=>{c.current.isFocused=e,f(e),v()},[v]);t={isTextInput:s},O(),(0,r.useEffect)(()=>{let e=(e,r)=>{var n;let s,l,i,u,d;n=!!(null==t?void 0:t.isTextInput),s=o(null==r?void 0:r.target),l="u">typeof window?a(null==r?void 0:r.target).HTMLInputElement:HTMLInputElement,i="u">typeof window?a(null==r?void 0:r.target).HTMLTextAreaElement:HTMLTextAreaElement,u="u">typeof window?a(null==r?void 0:r.target).HTMLElement:HTMLElement,d="u">typeof window?a(null==r?void 0:r.target).KeyboardEvent:KeyboardEvent,(n=n||s.activeElement instanceof l&&!j.has(s.activeElement.type)||s.activeElement instanceof i||s.activeElement instanceof u&&s.activeElement.isContentEditable)&&"keyboard"===e&&r instanceof d&&!N[r.key]||(e=>{c.current.isFocusVisible=e,v()})(H())};return F.add(e),()=>{F.delete(e)}},[]);let{focusProps:g}=function(e){let{isDisabled:t,onFocus:n,onBlur:a,onFocusChange:s}=e,l=(0,r.useCallback)(e=>{if(e.target===e.currentTarget)return a&&a(e),s&&s(!1),!0},[a,s]),i=u(l),c=(0,r.useCallback)(e=>{var t;let r=o(e.target),a=r?((e=document)=>e.activeElement)(r):((e=document)=>e.activeElement)();e.target===e.currentTarget&&a===(t=e.nativeEvent,t.target)&&(n&&n(e),s&&s(!0),i(e))},[s,n,i]);return{focusProps:{onFocus:!t&&(n||s||a)?c:void 0,onBlur:!t&&(a||s)?l:void 0}}}({isDisabled:l,onFocusChange:b}),{focusWithinProps:h}=function(e){let{isDisabled:t,onBlurWithin:n,onFocusWithin:a,onFocusWithinChange:s}=e,l=(0,r.useRef)({isFocusWithin:!1}),{addGlobalListener:c,removeAllGlobalListeners:d}=W(),f=(0,r.useCallback)(e=>{e.currentTarget.contains(e.target)&&l.current.isFocusWithin&&!e.currentTarget.contains(e.relatedTarget)&&(l.current.isFocusWithin=!1,d(),n&&n(e),s&&s(!1))},[n,s,l,d]),p=u(f),m=(0,r.useCallback)(e=>{var t;if(!e.currentTarget.contains(e.target))return;let r=o(e.target),n=((e=document)=>e.activeElement)(r);if(!l.current.isFocusWithin&&n===(t=e.nativeEvent,t.target)){a&&a(e),s&&s(!0),l.current.isFocusWithin=!0,p(e);let t=e.currentTarget;c(r,"focus",e=>{if(l.current.isFocusWithin&&!K(t,e.target)){let n=new r.defaultView.FocusEvent("blur",{relatedTarget:e.target});Object.defineProperty(n,"target",{value:t}),Object.defineProperty(n,"currentTarget",{value:t}),f(i(n))}},{capture:!0})}},[a,s,p,c,f]);return t?{focusWithinProps:{onFocus:void 0,onBlur:void 0}}:{focusWithinProps:{onFocus:m,onBlur:f}}}({isDisabled:!l,onFocusWithinChange:b});return{isFocused:d,isFocusVisible:p,focusProps:l?h:g}}e.s(["useFocusRing",()=>B],429427);let V=!1,_=0;function G(e){"touch"===e.pointerType&&(V=!0,setTimeout(()=>{V=!1},50))}function U(){if("u">typeof document)return 0===_&&"u">typeof PointerEvent&&document.addEventListener("pointerup",G),_++,()=>{!(--_>0)&&"u">typeof PointerEvent&&document.removeEventListener("pointerup",G)}}function $(e){let{onHoverStart:t,onHoverChange:n,onHoverEnd:a,isDisabled:s}=e,[l,i]=(0,r.useState)(!1),u=(0,r.useRef)({isHovered:!1,ignoreEmulatedMouseEvents:!1,pointerType:"",target:null}).current;(0,r.useEffect)(U,[]);let{addGlobalListener:c,removeAllGlobalListeners:d}=W(),{hoverProps:f,triggerHoverEnd:p}=(0,r.useMemo)(()=>{let e=(e,t)=>{let r=u.target;u.pointerType="",u.target=null,"touch"!==t&&u.isHovered&&r&&(u.isHovered=!1,d(),a&&a({type:"hoverend",target:r,pointerType:t}),n&&n(!1),i(!1))},r={};return"u">typeof PointerEvent&&(r.onPointerEnter=r=>{V&&"mouse"===r.pointerType||((r,a)=>{if(u.pointerType=a,s||"touch"===a||u.isHovered||!r.currentTarget.contains(r.target))return;u.isHovered=!0;let l=r.currentTarget;u.target=l,c(o(r.target),"pointerover",t=>{u.isHovered&&u.target&&!K(u.target,t.target)&&e(t,t.pointerType)},{capture:!0}),t&&t({type:"hoverstart",target:l,pointerType:a}),n&&n(!0),i(!0)})(r,r.pointerType)},r.onPointerLeave=t=>{!s&&t.currentTarget.contains(t.target)&&e(t,t.pointerType)}),{hoverProps:r,triggerHoverEnd:e}},[t,n,a,s,u,c,d]);return(0,r.useEffect)(()=>{s&&p({currentTarget:u.target},u.pointerType)},[s]),{hoverProps:f,isHovered:l}}e.s(["useHover",()=>$],371330);var q=Object.defineProperty,X=(e,t,r)=>{let n;return(n="symbol"!=typeof t?t+"":t)in e?q(e,n,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[n]=r,r};let Y=new class{constructor(){X(this,"current",this.detect()),X(this,"handoffState","pending"),X(this,"currentId",0)}set(e){this.current!==e&&(this.handoffState="pending",this.currentId=0,this.current=e)}reset(){this.set(this.detect())}nextId(){return++this.currentId}get isServer(){return"server"===this.current}get isClient(){return"client"===this.current}detect(){return"u"setTimeout(()=>{throw e}))}function J(){let e=[],t={addEventListener:(e,r,n,o)=>(e.addEventListener(r,n,o),t.add(()=>e.removeEventListener(r,n,o))),requestAnimationFrame(...e){let r=requestAnimationFrame(...e);return t.add(()=>cancelAnimationFrame(r))},nextFrame:(...e)=>t.requestAnimationFrame(()=>t.requestAnimationFrame(...e)),setTimeout(...e){let r=setTimeout(...e);return t.add(()=>clearTimeout(r))},microTask(...e){let r={current:!0};return Z(()=>{r.current&&e[0]()}),t.add(()=>{r.current=!1})},style(e,t,r){let n=e.style.getPropertyValue(t);return Object.assign(e.style,{[t]:r}),this.add(()=>{Object.assign(e.style,{[t]:n})})},group(e){let t=J();return e(t),this.add(()=>t.dispose())},add:t=>(e.includes(t)||e.push(t),()=>{let r=e.indexOf(t);if(r>=0)for(let t of e.splice(r,1))t()}),dispose(){for(let t of e.splice(0))t()}};return t}function Q(){let[e]=(0,r.useState)(J);return(0,r.useEffect)(()=>()=>e.dispose(),[e]),e}e.s(["env",()=>Y],80758),e.s(["getOwnerDocument",()=>z],402155),e.s(["microTask",()=>Z],368578),e.s(["disposables",()=>J],544508),e.s(["useDisposables",()=>Q],746725);let ee=(e,t)=>{Y.isServer?(0,r.useEffect)(e,t):(0,r.useLayoutEffect)(e,t)};function et(e){let t=(0,r.useRef)(e);return ee(()=>{t.current=e},[e]),t}e.s(["useIsoMorphicEffect",()=>ee],835696),e.s(["useLatestValue",()=>et],941444);let er=function(e){let t=et(e);return r.default.useCallback((...e)=>t.current(...e),[t])};function en({disabled:e=!1}={}){let t=(0,r.useRef)(null),[n,o]=(0,r.useState)(!1),a=Q(),s=er(()=>{t.current=null,o(!1),a.dispose()}),l=er(e=>{if(a.dispose(),null===t.current){t.current=e.currentTarget,o(!0);{let r=z(e.currentTarget);a.addEventListener(r,"pointerup",s,!1),a.addEventListener(r,"pointermove",e=>{if(t.current){var r,n;let a,s;o((a=e.width/2,s=e.height/2,r={top:e.clientY-s,right:e.clientX+a,bottom:e.clientY+s,left:e.clientX-a},n=t.current.getBoundingClientRect(),!(!r||!n||r.rightn.right||r.bottomn.bottom)))}},!1),a.addEventListener(r,"pointercancel",s,!1)}}});return{pressed:n,pressProps:e?{}:{onPointerDown:l,onPointerUp:s,onClick:s}}}e.s(["useEvent",()=>er],914189),e.s(["useActivePress",()=>en],394487)},397701,e=>{"use strict";function t(e,r,...n){if(e in r){let t=r[e];return"function"==typeof t?t(...n):t}let o=Error(`Tried to handle "${e}" but there is no handler defined. Only defined handlers are: ${Object.keys(r).map(e=>`"${e}"`).join(", ")}.`);throw Error.captureStackTrace&&Error.captureStackTrace(o,t),o}e.s(["match",()=>t])},652265,e=>{"use strict";let t,r,n,o,a;e.i(544508);var s=e.i(397701),l=e.i(402155);let i=["[contentEditable=true]","[tabindex]","a[href]","area[href]","button:not([disabled])","iframe","input:not([disabled])","select:not([disabled])","textarea:not([disabled])"].map(e=>`${e}:not([tabindex='-1'])`).join(","),u=["[data-autofocus]"].map(e=>`${e}:not([tabindex='-1'])`).join(",");var c=((t=c||{})[t.First=1]="First",t[t.Previous=2]="Previous",t[t.Next=4]="Next",t[t.Last=8]="Last",t[t.WrapAround=16]="WrapAround",t[t.NoScroll=32]="NoScroll",t[t.AutoFocus=64]="AutoFocus",t),d=((r=d||{})[r.Error=0]="Error",r[r.Overflow=1]="Overflow",r[r.Success=2]="Success",r[r.Underflow=3]="Underflow",r),f=((n=f||{})[n.Previous=-1]="Previous",n[n.Next=1]="Next",n);function p(e=document.body){return null==e?[]:Array.from(e.querySelectorAll(i)).sort((e,t)=>Math.sign((e.tabIndex||Number.MAX_SAFE_INTEGER)-(t.tabIndex||Number.MAX_SAFE_INTEGER)))}var m=((o=m||{})[o.Strict=0]="Strict",o[o.Loose=1]="Loose",o);function v(e,t=0){var r;return e!==(null==(r=(0,l.getOwnerDocument)(e))?void 0:r.body)&&(0,s.match)(t,{0:()=>e.matches(i),1(){let t=e;for(;null!==t;){if(t.matches(i))return!0;t=t.parentElement}return!1}})}var b=((a=b||{})[a.Keyboard=0]="Keyboard",a[a.Mouse=1]="Mouse",a);function g(e,t=e=>e){return e.slice().sort((e,r)=>{let n=t(e),o=t(r);if(null===n||null===o)return 0;let a=n.compareDocumentPosition(o);return a&Node.DOCUMENT_POSITION_FOLLOWING?-1:a&Node.DOCUMENT_POSITION_PRECEDING?1:0})}function h(e,t){return y(p(),t,{relativeTo:e})}function y(e,t,{sorted:r=!0,relativeTo:n=null,skipElements:o=[]}={}){var a,s,l;let i=Array.isArray(e)?e.length>0?e[0].ownerDocument:document:e.ownerDocument,c=Array.isArray(e)?r?g(e):e:64&t?function(e=document.body){return null==e?[]:Array.from(e.querySelectorAll(u)).sort((e,t)=>Math.sign((e.tabIndex||Number.MAX_SAFE_INTEGER)-(t.tabIndex||Number.MAX_SAFE_INTEGER)))}(e):p(e);o.length>0&&c.length>1&&(c=c.filter(e=>!o.some(t=>null!=t&&"current"in t?(null==t?void 0:t.current)===e:t===e))),n=null!=n?n:i.activeElement;let d=(()=>{if(5&t)return 1;if(10&t)return -1;throw Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),f=(()=>{if(1&t)return 0;if(2&t)return Math.max(0,c.indexOf(n))-1;if(4&t)return Math.max(0,c.indexOf(n))+1;if(8&t)return c.length-1;throw Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),m=32&t?{preventScroll:!0}:{},v=0,b=c.length,h;do{if(v>=b||v+b<=0)return 0;let e=f+v;if(16&t)e=(e+b)%b;else{if(e<0)return 3;if(e>=b)return 1}null==(h=c[e])||h.focus(m),v+=d}while(h!==i.activeElement)return 6&t&&null!=(l=null==(s=null==(a=h)?void 0:a.matches)?void 0:s.call(a,"textarea,input"))&&l&&h.select(),2}"u">typeof window&&"u">typeof document&&(document.addEventListener("keydown",e=>{e.metaKey||e.altKey||e.ctrlKey||(document.documentElement.dataset.headlessuiFocusVisible="")},!0),document.addEventListener("click",e=>{1===e.detail?delete document.documentElement.dataset.headlessuiFocusVisible:0===e.detail&&(document.documentElement.dataset.headlessuiFocusVisible="")},!0)),e.s(["Focus",()=>c,"FocusResult",()=>d,"FocusableMode",()=>m,"focusFrom",()=>h,"focusIn",()=>y,"getFocusableElements",()=>p,"isFocusableElement",()=>v,"sortByDomNode",()=>g])},144279,294316,e=>{"use strict";var t=e.i(271645);function r(e,r){return(0,t.useMemo)(()=>{var t;if(e.type)return e.type;let n=null!=(t=e.as)?t:"button";if("string"==typeof n&&"button"===n.toLowerCase()||(null==r?void 0:r.tagName)==="BUTTON"&&!r.hasAttribute("type"))return"button"},[e.type,e.as,r])}e.s(["useResolveButtonType",()=>r],144279);var n=e.i(914189);let o=Symbol();function a(e,t=!0){return Object.assign(e,{[o]:t})}function s(...e){let r=(0,t.useRef)(e);(0,t.useEffect)(()=>{r.current=e},[e]);let a=(0,n.useEvent)(e=>{for(let t of r.current)null!=t&&("function"==typeof t?t(e):t.current=e)});return e.every(e=>null==e||(null==e?void 0:e[o]))?void 0:a}e.s(["optionalRef",()=>a,"useSyncRefs",()=>s],294316)},732607,e=>{"use strict";function t(...e){return Array.from(new Set(e.flatMap(e=>"string"==typeof e?e.split(" "):[]))).filter(Boolean).join(" ")}e.s(["classNames",()=>t])},700020,e=>{"use strict";let t,r;var n=e.i(271645),o=e.i(732607),a=e.i(397701),s=((t=s||{})[t.None=0]="None",t[t.RenderStrategy=1]="RenderStrategy",t[t.Static=2]="Static",t),l=((r=l||{})[r.Unmount=0]="Unmount",r[r.Hidden=1]="Hidden",r);function i(){let e,t,r=(e=(0,n.useRef)([]),t=(0,n.useCallback)(t=>{for(let r of e.current)null!=r&&("function"==typeof r?r(t):r.current=t)},[]),(...r)=>{if(!r.every(e=>null==e))return e.current=r,t});return(0,n.useCallback)(e=>(function({ourProps:e,theirProps:t,slot:r,defaultTag:n,features:o,visible:s=!0,name:l,mergeRefs:i}){i=null!=i?i:c;let f=d(t,e);if(s)return u(f,r,n,l,i);let p=null!=o?o:0;if(2&p){let{static:e=!1,...t}=f;if(e)return u(t,r,n,l,i)}if(1&p){let{unmount:e=!0,...t}=f;return(0,a.match)(+!e,{0:()=>null,1:()=>u({...t,hidden:!0,style:{display:"none"}},r,n,l,i)})}return u(f,r,n,l,i)})({mergeRefs:r,...e}),[r])}function u(e,t={},r,a,s){let{as:l=r,children:i,refName:c="ref",...f}=v(e,["unmount","static"]),p=void 0!==e.ref?{[c]:e.ref}:{},b="function"==typeof i?i(t):i;"className"in f&&f.className&&"function"==typeof f.className&&(f.className=f.className(t)),f["aria-labelledby"]&&f["aria-labelledby"]===f.id&&(f["aria-labelledby"]=void 0);let g={};if(t){let e=!1,r=[];for(let[n,o]of Object.entries(t))"boolean"==typeof o&&(e=!0),!0===o&&r.push(n.replace(/([A-Z])/g,e=>`-${e.toLowerCase()}`));if(e)for(let e of(g["data-headlessui-state"]=r.join(" "),r))g[`data-${e}`]=""}if(l===n.Fragment&&(Object.keys(m(f)).length>0||Object.keys(m(g)).length>0))if(!(0,n.isValidElement)(b)||Array.isArray(b)&&b.length>1){if(Object.keys(m(f)).length>0)throw Error(['Passing props on "Fragment"!',"",`The current component <${a} /> is rendering a "Fragment".`,"However we need to passthrough the following props:",Object.keys(m(f)).concat(Object.keys(m(g))).map(e=>` - ${e}`).join(` -`),"","You can apply a few solutions:",['Add an `as="..."` prop, to ensure that we render an actual element instead of a "Fragment".',"Render a single element as the child so that we can forward the props onto that element."].map(e=>` - ${e}`).join(` -`)].join(` -`))}else{var h;let e=b.props,t=null==e?void 0:e.className,r="function"==typeof t?(...e)=>(0,o.classNames)(t(...e),f.className):(0,o.classNames)(t,f.className),a=d(b.props,m(v(f,["ref"])));for(let e in g)e in a&&delete g[e];return(0,n.cloneElement)(b,Object.assign({},a,g,p,{ref:s((h=b,n.default.version.split(".")[0]>="19"?h.props.ref:h.ref),p.ref)},r?{className:r}:{}))}return(0,n.createElement)(l,Object.assign({},v(f,["ref"]),l!==n.Fragment&&p,l!==n.Fragment&&g),b)}function c(...e){return e.every(e=>null==e)?void 0:t=>{for(let r of e)null!=r&&("function"==typeof r?r(t):r.current=t)}}function d(...e){if(0===e.length)return{};if(1===e.length)return e[0];let t={},r={};for(let n of e)for(let e in n)e.startsWith("on")&&"function"==typeof n[e]?(null!=r[e]||(r[e]=[]),r[e].push(n[e])):t[e]=n[e];if(t.disabled||t["aria-disabled"])for(let e in r)/^(on(?:Click|Pointer|Mouse|Key)(?:Down|Up|Press)?)$/.test(e)&&(r[e]=[e=>{var t;return null==(t=null==e?void 0:e.preventDefault)?void 0:t.call(e)}]);for(let e in r)Object.assign(t,{[e](t,...n){for(let o of r[e]){if((t instanceof Event||(null==t?void 0:t.nativeEvent)instanceof Event)&&t.defaultPrevented)return;o(t,...n)}}});return t}function f(...e){if(0===e.length)return{};if(1===e.length)return e[0];let t={},r={};for(let n of e)for(let e in n)e.startsWith("on")&&"function"==typeof n[e]?(null!=r[e]||(r[e]=[]),r[e].push(n[e])):t[e]=n[e];for(let e in r)Object.assign(t,{[e](...t){for(let n of r[e])null==n||n(...t)}});return t}function p(e){var t;return Object.assign((0,n.forwardRef)(e),{displayName:null!=(t=e.displayName)?t:e.name})}function m(e){let t=Object.assign({},e);for(let e in t)void 0===t[e]&&delete t[e];return t}function v(e,t=[]){let r=Object.assign({},e);for(let e of t)e in r&&delete r[e];return r}e.s(["RenderFeatures",()=>s,"RenderStrategy",()=>l,"compact",()=>m,"forwardRefWithAs",()=>p,"mergeProps",()=>f,"useRender",()=>i])},2788,e=>{"use strict";let t;var r=e.i(700020),n=((t=n||{})[t.None=1]="None",t[t.Focusable=2]="Focusable",t[t.Hidden=4]="Hidden",t);let o=(0,r.forwardRefWithAs)(function(e,t){var n;let{features:o=1,...a}=e,s={ref:t,"aria-hidden":(2&o)==2||(null!=(n=a["aria-hidden"])?n:void 0),hidden:(4&o)==4||void 0,style:{position:"fixed",top:1,left:1,width:1,height:0,padding:0,margin:-1,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",borderWidth:"0",...(4&o)==4&&(2&o)!=2&&{display:"none"}}};return(0,r.useRender)()({ourProps:s,theirProps:a,slot:{},defaultTag:"span",name:"Hidden"})});e.s(["Hidden",()=>o,"HiddenFeatures",()=>n])},998348,e=>{"use strict";let t;var r=((t=r||{}).Space=" ",t.Enter="Enter",t.Escape="Escape",t.Backspace="Backspace",t.Delete="Delete",t.ArrowLeft="ArrowLeft",t.ArrowUp="ArrowUp",t.ArrowRight="ArrowRight",t.ArrowDown="ArrowDown",t.Home="Home",t.End="End",t.PageUp="PageUp",t.PageDown="PageDown",t.Tab="Tab",t);e.s(["Keys",()=>r])},553521,e=>{"use strict";var t=e.i(271645),r=e.i(835696);function n(){let e=(0,t.useRef)(!1);return(0,r.useIsoMorphicEffect)(()=>(e.current=!0,()=>{e.current=!1}),[]),e}e.s(["useIsMounted",()=>n])},640497,e=>{"use strict";var t=e.i(271645),r=e.i(553521),n=e.i(2788);function o({onFocus:e}){let[o,a]=(0,t.useState)(!0),s=(0,r.useIsMounted)();return o?t.default.createElement(n.Hidden,{as:"button",type:"button",features:n.HiddenFeatures.Focusable,onFocus:t=>{t.preventDefault();let r,n=50;r=requestAnimationFrame(function t(){if(n--<=0){r&&cancelAnimationFrame(r);return}if(e()){if(cancelAnimationFrame(r),!s.current)return;a(!1);return}r=requestAnimationFrame(t)})}}):null}e.s(["FocusSentinel",()=>o])},963703,e=>{"use strict";var t=e.i(271645);let r=t.createContext(null);function n({children:e}){let n=t.useRef({groups:new Map,get(e,t){var r;let n=this.groups.get(e);n||(n=new Map,this.groups.set(e,n));let o=null!=(r=n.get(t))?r:0;return n.set(t,o+1),[Array.from(n.keys()).indexOf(t),function(){let e=n.get(t);e>1?n.set(t,e-1):n.delete(t)}]}});return t.createElement(r.Provider,{value:n},e)}function o(e){let n=t.useContext(r);if(!n)throw Error("You must wrap your component in a ");let o=t.useId(),[a,s]=n.current.get(e,o);return t.useEffect(()=>s,[]),a}e.s(["StableCollection",()=>n,"useStableCollectionIndex",()=>o])},970554,e=>{"use strict";let t,r,n;var o=e.i(429427),a=e.i(371330),s=e.i(271645),l=e.i(394487),i=e.i(914189),u=e.i(835696),c=e.i(941444),d=e.i(144279),f=e.i(294316),p=e.i(640497),m=e.i(2788),v=e.i(652265),b=e.i(397701),g=e.i(368578),h=e.i(402155),y=e.i(700020),E=e.i(963703),w=e.i(998348),T=((t=T||{})[t.Forwards=0]="Forwards",t[t.Backwards=1]="Backwards",t),x=((r=x||{})[r.Less=-1]="Less",r[r.Equal=0]="Equal",r[r.Greater=1]="Greater",r),F=((n=F||{})[n.SetSelectedIndex=0]="SetSelectedIndex",n[n.RegisterTab=1]="RegisterTab",n[n.UnregisterTab=2]="UnregisterTab",n[n.RegisterPanel=3]="RegisterPanel",n[n.UnregisterPanel=4]="UnregisterPanel",n);let P={0(e,t){var r;let n=(0,v.sortByDomNode)(e.tabs,e=>e.current),o=(0,v.sortByDomNode)(e.panels,e=>e.current),a=n.filter(e=>{var t;return!(null!=(t=e.current)&&t.hasAttribute("disabled"))}),s={...e,tabs:n,panels:o};if(t.index<0||t.index>n.length-1){let r=(0,b.match)(Math.sign(t.index-e.selectedIndex),{[-1]:()=>1,0:()=>(0,b.match)(Math.sign(t.index),{[-1]:()=>0,0:()=>0,1:()=>1}),1:()=>0});if(0===a.length)return s;let o=(0,b.match)(r,{0:()=>n.indexOf(a[0]),1:()=>n.indexOf(a[a.length-1])});return{...s,selectedIndex:-1===o?e.selectedIndex:o}}let l=n.slice(0,t.index),i=[...n.slice(t.index),...l].find(e=>a.includes(e));if(!i)return s;let u=null!=(r=n.indexOf(i))?r:e.selectedIndex;return -1===u&&(u=e.selectedIndex),{...s,selectedIndex:u}},1(e,t){if(e.tabs.includes(t.tab))return e;let r=e.tabs[e.selectedIndex],n=(0,v.sortByDomNode)([...e.tabs,t.tab],e=>e.current),o=e.selectedIndex;return e.info.current.isControlled||-1===(o=n.indexOf(r))&&(o=e.selectedIndex),{...e,tabs:n,selectedIndex:o}},2:(e,t)=>({...e,tabs:e.tabs.filter(e=>e!==t.tab)}),3:(e,t)=>e.panels.includes(t.panel)?e:{...e,panels:(0,v.sortByDomNode)([...e.panels,t.panel],e=>e.current)},4:(e,t)=>({...e,panels:e.panels.filter(e=>e!==t.panel)})},k=(0,s.createContext)(null);function L(e){let t=(0,s.useContext)(k);if(null===t){let t=Error(`<${e} /> is missing a parent component.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,L),t}return t}k.displayName="TabsDataContext";let N=(0,s.createContext)(null);function C(e){let t=(0,s.useContext)(N);if(null===t){let t=Error(`<${e} /> is missing a parent component.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,C),t}return t}function I(e,t){return(0,b.match)(t.type,P,e,t)}N.displayName="TabsActionsContext";let S=y.RenderFeatures.RenderStrategy|y.RenderFeatures.Static,A=Object.assign((0,y.forwardRefWithAs)(function(e,t){var r,n;let c=(0,s.useId)(),{id:p=`headlessui-tabs-tab-${c}`,disabled:m=!1,autoFocus:T=!1,...x}=e,{orientation:F,activation:P,selectedIndex:k,tabs:N,panels:I}=L("Tab"),S=C("Tab"),A=L("Tab"),[M,R]=(0,s.useState)(null),O=(0,s.useRef)(null),D=(0,f.useSyncRefs)(O,t,R);(0,u.useIsoMorphicEffect)(()=>S.registerTab(O),[S,O]);let H=(0,E.useStableCollectionIndex)("tabs"),j=N.indexOf(O);-1===j&&(j=H);let K=j===k,W=(0,i.useEvent)(e=>{var t;let r=e();if(r===v.FocusResult.Success&&"auto"===P){let e=null==(t=(0,h.getOwnerDocument)(O))?void 0:t.activeElement,r=A.tabs.findIndex(t=>t.current===e);-1!==r&&S.change(r)}return r}),B=(0,i.useEvent)(e=>{let t=N.map(e=>e.current).filter(Boolean);if(e.key===w.Keys.Space||e.key===w.Keys.Enter){e.preventDefault(),e.stopPropagation(),S.change(j);return}switch(e.key){case w.Keys.Home:case w.Keys.PageUp:return e.preventDefault(),e.stopPropagation(),W(()=>(0,v.focusIn)(t,v.Focus.First));case w.Keys.End:case w.Keys.PageDown:return e.preventDefault(),e.stopPropagation(),W(()=>(0,v.focusIn)(t,v.Focus.Last))}if(W(()=>(0,b.match)(F,{vertical:()=>e.key===w.Keys.ArrowUp?(0,v.focusIn)(t,v.Focus.Previous|v.Focus.WrapAround):e.key===w.Keys.ArrowDown?(0,v.focusIn)(t,v.Focus.Next|v.Focus.WrapAround):v.FocusResult.Error,horizontal:()=>e.key===w.Keys.ArrowLeft?(0,v.focusIn)(t,v.Focus.Previous|v.Focus.WrapAround):e.key===w.Keys.ArrowRight?(0,v.focusIn)(t,v.Focus.Next|v.Focus.WrapAround):v.FocusResult.Error}))===v.FocusResult.Success)return e.preventDefault()}),V=(0,s.useRef)(!1),_=(0,i.useEvent)(()=>{var e;V.current||(V.current=!0,null==(e=O.current)||e.focus({preventScroll:!0}),S.change(j),(0,g.microTask)(()=>{V.current=!1}))}),G=(0,i.useEvent)(e=>{e.preventDefault()}),{isFocusVisible:U,focusProps:$}=(0,o.useFocusRing)({autoFocus:T}),{isHovered:q,hoverProps:X}=(0,a.useHover)({isDisabled:m}),{pressed:Y,pressProps:z}=(0,l.useActivePress)({disabled:m}),Z=(0,s.useMemo)(()=>({selected:K,hover:q,active:Y,focus:U,autofocus:T,disabled:m}),[K,q,U,Y,T,m]),J=(0,y.mergeProps)({ref:D,onKeyDown:B,onMouseDown:G,onClick:_,id:p,role:"tab",type:(0,d.useResolveButtonType)(e,M),"aria-controls":null==(n=null==(r=I[j])?void 0:r.current)?void 0:n.id,"aria-selected":K,tabIndex:K?0:-1,disabled:m||void 0,autoFocus:T},$,X,z);return(0,y.useRender)()({ourProps:J,theirProps:x,slot:Z,defaultTag:"button",name:"Tabs.Tab"})}),{Group:(0,y.forwardRefWithAs)(function(e,t){let{defaultIndex:r=0,vertical:n=!1,manual:o=!1,onChange:a,selectedIndex:l=null,...d}=e,m=n?"vertical":"horizontal",b=o?"manual":"auto",g=null!==l,h=(0,c.useLatestValue)({isControlled:g}),w=(0,f.useSyncRefs)(t),[T,x]=(0,s.useReducer)(I,{info:h,selectedIndex:null!=l?l:r,tabs:[],panels:[]}),F=(0,s.useMemo)(()=>({selectedIndex:T.selectedIndex}),[T.selectedIndex]),P=(0,c.useLatestValue)(a||(()=>{})),L=(0,c.useLatestValue)(T.tabs),C=(0,s.useMemo)(()=>({orientation:m,activation:b,...T}),[m,b,T]),S=(0,i.useEvent)(e=>(x({type:1,tab:e}),()=>x({type:2,tab:e}))),A=(0,i.useEvent)(e=>(x({type:3,panel:e}),()=>x({type:4,panel:e}))),M=(0,i.useEvent)(e=>{R.current!==e&&P.current(e),g||x({type:0,index:e})}),R=(0,c.useLatestValue)(g?e.selectedIndex:T.selectedIndex),O=(0,s.useMemo)(()=>({registerTab:S,registerPanel:A,change:M}),[]);(0,u.useIsoMorphicEffect)(()=>{x({type:0,index:null!=l?l:r})},[l]),(0,u.useIsoMorphicEffect)(()=>{if(void 0===R.current||T.tabs.length<=0)return;let e=(0,v.sortByDomNode)(T.tabs,e=>e.current);e.some((e,t)=>T.tabs[t]!==e)&&M(e.indexOf(T.tabs[R.current]))});let D=(0,y.useRender)();return s.default.createElement(E.StableCollection,null,s.default.createElement(N.Provider,{value:O},s.default.createElement(k.Provider,{value:C},C.tabs.length<=0&&s.default.createElement(p.FocusSentinel,{onFocus:()=>{var e,t;for(let r of L.current)if((null==(e=r.current)?void 0:e.tabIndex)===0)return null==(t=r.current)||t.focus(),!0;return!1}}),D({ourProps:{ref:w},theirProps:d,slot:F,defaultTag:"div",name:"Tabs"}))))}),List:(0,y.forwardRefWithAs)(function(e,t){let{orientation:r,selectedIndex:n}=L("Tab.List"),o=(0,f.useSyncRefs)(t),a=(0,s.useMemo)(()=>({selectedIndex:n}),[n]);return(0,y.useRender)()({ourProps:{ref:o,role:"tablist","aria-orientation":r},theirProps:e,slot:a,defaultTag:"div",name:"Tabs.List"})}),Panels:(0,y.forwardRefWithAs)(function(e,t){let{selectedIndex:r}=L("Tab.Panels"),n=(0,f.useSyncRefs)(t),o=(0,s.useMemo)(()=>({selectedIndex:r}),[r]);return(0,y.useRender)()({ourProps:{ref:n},theirProps:e,slot:o,defaultTag:"div",name:"Tabs.Panels"})}),Panel:(0,y.forwardRefWithAs)(function(e,t){var r,n,a,l;let i=(0,s.useId)(),{id:c=`headlessui-tabs-panel-${i}`,tabIndex:d=0,...p}=e,{selectedIndex:v,tabs:b,panels:g}=L("Tab.Panel"),h=C("Tab.Panel"),w=(0,s.useRef)(null),T=(0,f.useSyncRefs)(w,t);(0,u.useIsoMorphicEffect)(()=>h.registerPanel(w),[h,w]);let x=(0,E.useStableCollectionIndex)("panels"),F=g.indexOf(w);-1===F&&(F=x);let P=F===v,{isFocusVisible:k,focusProps:N}=(0,o.useFocusRing)(),I=(0,s.useMemo)(()=>({selected:P,focus:k}),[P,k]),A=(0,y.mergeProps)({ref:T,id:c,role:"tabpanel","aria-labelledby":null==(n=null==(r=b[F])?void 0:r.current)?void 0:n.id,tabIndex:P?d:-1},N),M=(0,y.useRender)();return P||null!=(a=p.unmount)&&!a||null!=(l=p.static)&&l?M({ourProps:A,theirProps:p,slot:I,defaultTag:"div",features:S,visible:P,name:"Tabs.Panel"}):s.default.createElement(m.Hidden,{"aria-hidden":"true",...A})})});e.s(["Tab",()=>A])},405371,910342,e=>{"use strict";var t=e.i(290571),r=e.i(271645),n=e.i(480731);let o=(0,r.createContext)(n.BaseColors.Blue);e.s(["default",()=>o],910342);var a=e.i(970554),s=e.i(444755);let l=(0,e.i(673706).makeClassName)("TabList"),i=(0,r.createContext)("line"),u={line:(0,s.tremorTwMerge)("flex border-b space-x-4","border-tremor-border","dark:border-dark-tremor-border"),solid:(0,s.tremorTwMerge)("inline-flex p-0.5 rounded-tremor-default space-x-1.5","bg-tremor-background-subtle","dark:bg-dark-tremor-background-subtle")},c=r.default.forwardRef((e,n)=>{let{color:c,variant:d="line",children:f,className:p}=e,m=(0,t.__rest)(e,["color","variant","children","className"]);return r.default.createElement(a.Tab.List,Object.assign({ref:n,className:(0,s.tremorTwMerge)(l("root"),"justify-start overflow-x-clip",u[d],p)},m),r.default.createElement(i.Provider,{value:d},r.default.createElement(o.Provider,{value:c},f)))});c.displayName="TabList",e.s(["TabVariantContext",()=>i,"default",()=>c],405371)},197647,e=>{"use strict";var t=e.i(290571),r=e.i(970554),n=e.i(95779),o=e.i(444755),a=e.i(673706),s=e.i(271645),l=e.i(405371),i=e.i(910342);let u=(0,a.makeClassName)("Tab"),c=s.default.forwardRef((e,c)=>{let{icon:d,className:f,children:p}=e,m=(0,t.__rest)(e,["icon","className","children"]),v=(0,s.useContext)(l.TabVariantContext),b=(0,s.useContext)(i.default);return s.default.createElement(r.Tab,Object.assign({ref:c,className:(0,o.tremorTwMerge)(u("root"),"flex whitespace-nowrap truncate max-w-xs outline-none data-focus-visible:ring text-tremor-default transition duration-100",function(e,t){switch(e){case"line":return(0,o.tremorTwMerge)("data-[selected]:border-b-2 hover:border-b-2 border-transparent transition duration-100 -mb-px px-2 py-2","hover:border-tremor-content hover:text-tremor-content-emphasis text-tremor-content","[&:not([data-selected])]:dark:hover:border-dark-tremor-content-emphasis [&:not([data-selected])]:dark:hover:text-dark-tremor-content-emphasis [&:not([data-selected])]:dark:text-dark-tremor-content",t?(0,a.getColorClassNames)(t,n.colorPalette.border).selectBorderColor:["data-[selected]:border-tremor-brand data-[selected]:text-tremor-brand","data-[selected]:dark:border-dark-tremor-brand data-[selected]:dark:text-dark-tremor-brand"]);case"solid":return(0,o.tremorTwMerge)("border-transparent border rounded-tremor-small px-2.5 py-1","data-[selected]:border-tremor-border data-[selected]:bg-tremor-background data-[selected]:shadow-tremor-input [&:not([data-selected])]:hover:text-tremor-content-emphasis data-[selected]:text-tremor-brand [&:not([data-selected])]:text-tremor-content","dark:data-[selected]:border-dark-tremor-border dark:data-[selected]:bg-dark-tremor-background dark:data-[selected]:shadow-dark-tremor-input dark:[&:not([data-selected])]:hover:text-dark-tremor-content-emphasis dark:data-[selected]:text-dark-tremor-brand dark:[&:not([data-selected])]:text-dark-tremor-content",t?(0,a.getColorClassNames)(t,n.colorPalette.text).selectTextColor:"text-tremor-content dark:text-dark-tremor-content")}}(v,b),f,b&&(0,a.getColorClassNames)(b,n.colorPalette.text).selectTextColor)},m),d?s.default.createElement(d,{className:(0,o.tremorTwMerge)(u("icon"),"flex-none h-5 w-5",p?"mr-2":"")}):null,p?s.default.createElement("span",null,p):null)});c.displayName="Tab",e.s(["Tab",()=>c],197647)},653824,e=>{"use strict";var t=e.i(290571),r=e.i(970554),n=e.i(444755),o=e.i(673706),a=e.i(271645);let s=(0,o.makeClassName)("TabGroup"),l=a.default.forwardRef((e,o)=>{let{defaultIndex:l,index:i,onIndexChange:u,children:c,className:d}=e,f=(0,t.__rest)(e,["defaultIndex","index","onIndexChange","children","className"]);return a.default.createElement(r.Tab.Group,Object.assign({as:"div",ref:o,defaultIndex:l,selectedIndex:i,onChange:u,className:(0,n.tremorTwMerge)(s("root"),"w-full",d)},f),c)});l.displayName="TabGroup",e.s(["TabGroup",()=>l],653824)},881073,e=>{"use strict";var t=e.i(405371);e.s(["TabList",()=>t.default])},723731,e=>{"use strict";var t=e.i(290571),r=e.i(970554),n=e.i(751734),o=e.i(144582),a=e.i(444755),s=e.i(673706),l=e.i(271645);let i=(0,s.makeClassName)("TabPanels"),u=l.default.forwardRef((e,s)=>{let{children:u,className:c}=e,d=(0,t.__rest)(e,["children","className"]);return l.default.createElement(r.Tab.Panels,Object.assign({as:"div",ref:s,className:(0,a.tremorTwMerge)(i("root"),"w-full",c)},d),({selectedIndex:e})=>l.default.createElement(o.default.Provider,{value:{selectedValue:e}},l.default.Children.map(u,(e,t)=>l.default.createElement(n.default.Provider,{value:t},e))))});u.displayName="TabPanels",e.s(["TabPanels",()=>u],723731)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/07086b95c00d0763.js b/litellm/proxy/_experimental/out/_next/static/chunks/07086b95c00d0763.js new file mode 100644 index 00000000000..2a1b129cdf3 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/07086b95c00d0763.js @@ -0,0 +1,31 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,389543,e=>{"use strict";var t=e.i(843476),l=e.i(271645),r=e.i(304967),a=e.i(269200),s=e.i(427612),n=e.i(496020),i=e.i(389083),o=e.i(64848),c=e.i(977572),d=e.i(942232),u=e.i(599724),g=e.i(994388),m=e.i(752978),p=e.i(793130),h=e.i(404206),f=e.i(723731),y=e.i(653824),x=e.i(881073),b=e.i(197647),_=e.i(602869),j=e.i(28651),w=e.i(68155),k=e.i(220508),C=e.i(464571),S=e.i(727749),v=e.i(158392);let T=({accessToken:e,userRole:r,userID:a})=>{let[s,n]=(0,l.useState)({routerSettings:{},selectedStrategy:null,enableTagFiltering:!1}),[i,o]=(0,l.useState)([]),[c,d]=(0,l.useState)({}),[u,g]=(0,l.useState)({});return((0,l.useEffect)(()=>{e&&r&&a&&((0,_.getCallbacksCall)(e,a,r).then(e=>{console.log("callbacks",e);let t=e.router_settings;"model_group_retry_policy"in t&&delete t.model_group_retry_policy;let l=t.routing_strategy||null;n(e=>({...e,routerSettings:t,selectedStrategy:l}))}),(0,_.getRouterSettingsCall)(e).then(e=>{if(console.log("router settings from API",e),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}}),d(t);let l=e.fields.find(e=>"routing_strategy"===e.field_name);l?.options&&o(l.options),e.routing_strategy_descriptions&&g(e.routing_strategy_descriptions);let r=e.fields.find(e=>"enable_tag_filtering"===e.field_name);r?.field_value!==null&&r?.field_value!==void 0&&n(e=>({...e,enableTagFiltering:r.field_value}))}}))},[e,r,a]),e)?(0,t.jsxs)("div",{className:"w-full",children:[(0,t.jsx)(v.default,{value:s,onChange:n,routerFieldsMetadata:c,availableRoutingStrategies:i,routingStrategyDescriptions:u}),(0,t.jsxs)("div",{className:"border-t border-gray-200 pt-6 flex justify-end gap-3",children:[(0,t.jsx)(C.Button,{onClick:()=>window.location.reload(),children:"Reset"}),(0,t.jsx)(C.Button,{type:"primary",onClick:()=>{if(!e)return;let t=s.routerSettings;console.log("router_settings",t);let l=new Set(["allowed_fails","cooldown_time","num_retries","timeout","retry_after"]),r=new Set(["model_group_alias","retry_policy"]),a=Object.fromEntries(Object.entries({...t,enable_tag_filtering:s.enableTagFiltering}).map(([e,t])=>{if("routing_strategy_args"!==e&&"routing_strategy"!==e&&"enable_tag_filtering"!==e){let a=document.querySelector(`input[name="${e}"]`),s=((e,t,a)=>{if(void 0===t)return a;let s=t.trim();if("null"===s.toLowerCase())return null;if(l.has(e)){let e=Number(s);return Number.isNaN(e)?a:e}if(r.has(e)){if(""===s)return null;try{return JSON.parse(s)}catch{return a}}return"true"===s.toLowerCase()||"false"!==s.toLowerCase()&&s})(e,a?.value,t);return[e,s]}if("routing_strategy"===e)return[e,s.selectedStrategy];if("enable_tag_filtering"===e)return[e,s.enableTagFiltering];if("routing_strategy_args"===e&&"latency-based-routing"===s.selectedStrategy){let e={},t=document.querySelector('input[name="lowest_latency_buffer"]'),l=document.querySelector('input[name="ttl"]');return t?.value&&(e.lowest_latency_buffer=Number(t.value)),l?.value&&(e.ttl=Number(l.value)),console.log(`setRoutingStrategyArgs: ${e}`),["routing_strategy_args",e]}return null}).filter(e=>null!=e));console.log("updatedVariables",a);try{(0,_.setCallbacksCall)(e,{router_settings:a})}catch(e){S.default.fromBackend("Failed to update router settings: "+e)}S.default.success("router settings updated successfully")},children:"Save Changes"})]})]}):null};e.i(247167);var N=e.i(368670);let A=l.forwardRef(function(e,t){return l.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),l.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M14 5l7 7m0 0l-7 7m7-7H3"}))});var F=e.i(122577),I=e.i(592968),L=e.i(898586),M=e.i(356449),O=e.i(127952),B=e.i(418371),E=e.i(708347),R=e.i(888259),P=e.i(695411),D=e.i(212931);let $=(0,e.i(475254).default)("arrow-right",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]]);function G({open:e,onCancel:l,children:r}){return(0,t.jsx)(D.Modal,{title:(0,t.jsx)("div",{className:"pb-4 border-b border-gray-100",children:(0,t.jsxs)("div",{className:"flex items-center gap-2 text-gray-800",children:[(0,t.jsx)("div",{className:"p-2 bg-indigo-50 rounded-lg",children:(0,t.jsx)($,{className:"w-5 h-5 text-indigo-600"})}),(0,t.jsxs)("div",{children:[(0,t.jsx)("h2",{className:"text-lg font-bold m-0",children:"Configure Model Fallbacks"}),(0,t.jsx)("p",{className:"text-sm text-gray-500 font-normal m-0",children:"Manage multiple fallback chains for different models (up to 5 groups at a time)"})]})]})}),open:e,width:900,footer:null,onCancel:l,maskClosable:!1,className:"top-8",styles:{body:{padding:"24px"},header:{padding:"24px 24px 0 24px",border:"none"}},children:(0,t.jsx)("div",{className:"mt-6",children:r})})}var H=e.i(419470);function K({accessToken:e,value:r=[],onChange:a}){let[s,n]=(0,l.useState)(!1),[i,o]=(0,l.useState)([]),[c,d]=(0,l.useState)(0),[u,m]=(0,l.useState)(!1),[p,h]=(0,l.useState)([{id:"1",primaryModel:null,fallbackModels:[]}]);(0,l.useEffect)(()=>{s&&(h([{id:"1",primaryModel:null,fallbackModels:[]}]),d(e=>e+1))},[s]),(0,l.useEffect)(()=>{let t=async()=>{try{let t=await (0,P.fetchAvailableModels)(e);console.log("Fetched models for fallbacks:",t),o(t)}catch(e){console.error("Error fetching model info for fallbacks:",e)}};s&&t()},[e,s]);let f=Array.from(new Set(i.map(e=>e.model_group))).sort(),y=()=>{n(!1),h([{id:"1",primaryModel:null,fallbackModels:[]}])},x=async()=>{let e=p.filter(e=>!e.primaryModel||0===e.fallbackModels.length);if(e.length>0)return void R.default.error(`Please complete configuration for all groups. ${e.length} group(s) incomplete.`);let t=[...r||[],...p.map(e=>({[e.primaryModel]:e.fallbackModels}))];if(a){m(!0);try{await a(t),S.default.success(`${p.length} fallback configuration(s) added successfully!`),y()}catch(e){console.error("Error saving fallbacks:",e)}finally{m(!1)}}else S.default.fromBackend("onChange callback not provided")};return(0,t.jsxs)("div",{children:[(0,t.jsx)(g.Button,{className:"mx-auto",onClick:()=>n(!0),icon:()=>(0,t.jsx)("span",{className:"mr-1",children:"+"}),children:"Add Fallbacks"}),(0,t.jsxs)(G,{open:s,onCancel:y,children:[(0,t.jsx)(H.FallbackSelectionForm,{groups:p,onGroupsChange:h,availableModels:f,maxFallbacks:10,maxGroups:5},c),p.length>0&&(0,t.jsxs)("div",{className:"flex items-center justify-end space-x-3 pt-6 mt-6 border-t border-gray-100",children:[(0,t.jsx)(C.Button,{type:"default",onClick:y,disabled:u,children:"Cancel"}),(0,t.jsx)(C.Button,{type:"default",onClick:x,disabled:0===p.length||u,loading:u,children:u?"Saving Configuration...":"Save All Configurations"})]})]})]})}let U="inline-flex items-center gap-2 px-2.5 py-1 rounded-md border border-gray-200 bg-gray-50 text-sm font-medium text-gray-800 shrink-0";async function q(e,l){console.log=function(){};let r=window.location.origin,a=new M.default.OpenAI({apiKey:l,baseURL:r,dangerouslyAllowBrowser:!0});try{S.default.info("Testing fallback model response...");let l=await a.chat.completions.create({model:e,messages:[{role:"user",content:"Hi, this is a test message"}],mock_testing_fallbacks:!0});S.default.success((0,t.jsxs)("span",{children:["Test model=",(0,t.jsx)("strong",{children:e}),", received model=",(0,t.jsx)("strong",{children:l.model}),". See"," ",(0,t.jsx)("a",{href:"#",onClick:()=>window.open("https://docs.litellm.ai/docs/proxy/reliability","_blank"),style:{textDecoration:"underline",color:"blue"},children:"curl"})]}))}catch(e){S.default.fromBackend(`Error occurred while generating model response. Please try again. Error: ${e}`)}}let z=({accessToken:e,userRole:r,userID:i})=>{let[u,g]=(0,l.useState)({}),[p,h]=(0,l.useState)(!1),[f,y]=(0,l.useState)(null),[x,b]=(0,l.useState)(!1),{data:j}=(0,N.useModelCostMap)(),k=e=>null!=j&&"object"==typeof j&&e in j?j[e].litellm_provider??"":"";(0,l.useEffect)(()=>{e&&r&&i&&(0,_.getCallbacksCall)(e,i,r).then(e=>{console.log("callbacks",e);let t=e.router_settings;"model_group_retry_policy"in t&&delete t.model_group_retry_policy,g(t)})},[e,r,i]);let C=e=>{y(e),b(!0)},v=async()=>{if(!f||!e)return;let t=Object.keys(f)[0];if(!t)return;h(!0);let l=u.fallbacks.map(e=>{let l={...e};return t in l&&Array.isArray(l[t])&&delete l[t],l}).filter(e=>Object.keys(e).length>0),r={...u,fallbacks:l};try{await (0,_.setCallbacksCall)(e,{router_settings:r}),g(r),S.default.success("Router settings updated successfully")}catch(e){S.default.fromBackend("Failed to update router settings: "+e)}finally{h(!1),b(!1),y(null)}};if(!e)return null;let T=async t=>{if(!e)return;let l={...u,fallbacks:t};try{await (0,_.setCallbacksCall)(e,{router_settings:l}),g(l)}catch(t){throw S.default.fromBackend("Failed to update router settings: "+t),e&&r&&i&&(0,_.getCallbacksCall)(e,i,r).then(e=>{let t=e.router_settings;"model_group_retry_policy"in t&&delete t.model_group_retry_policy,g(t)}),t}},M=Array.isArray(u.fallbacks)&&u.fallbacks.length>0,R=(0,E.isProxyAdminRole)(r??"");return(0,t.jsxs)(t.Fragment,{children:[R&&(0,t.jsx)(K,{accessToken:e||"",value:u.fallbacks||[],onChange:T}),M?(0,t.jsxs)(a.Table,{children:[(0,t.jsx)(s.TableHead,{children:(0,t.jsxs)(n.TableRow,{children:[(0,t.jsx)(o.TableHeaderCell,{children:"Model Name"}),(0,t.jsx)(o.TableHeaderCell,{children:"Fallbacks"}),(0,t.jsx)(o.TableHeaderCell,{children:"Actions"})]})}),(0,t.jsx)(d.TableBody,{children:u.fallbacks.map((r,a)=>Object.entries(r).map(([s,i])=>{let o;return(0,t.jsxs)(n.TableRow,{children:[(0,t.jsx)(c.TableCell,{className:"align-top",children:(o=k?.(s)??s,(0,t.jsxs)("span",{className:U,children:[(0,t.jsx)(B.ProviderLogo,{provider:o,className:"w-4 h-4 shrink-0"}),(0,t.jsx)("span",{children:s})]}))}),(0,t.jsx)(c.TableCell,{className:"align-top",children:function(e,r,a){let s=Array.isArray(r)?r:[];if(0===s.length)return null;let n=({modelName:e})=>{let l=a?.(e)??e;return(0,t.jsxs)("span",{className:U,children:[(0,t.jsx)(B.ProviderLogo,{provider:l,className:"w-4 h-4 shrink-0"}),(0,t.jsx)("span",{children:e})]})};return(0,t.jsxs)("span",{className:"grid grid-cols-[auto_1fr] items-start gap-x-2 w-full min-w-0",children:[(0,t.jsx)("span",{className:"inline-flex items-center justify-center w-8 h-8 shrink-0 self-start text-blue-600","aria-hidden":!0,children:(0,t.jsx)(A,{className:"w-5 h-5 stroke-[2.5]"})}),(0,t.jsx)("span",{className:"flex flex-wrap items-start gap-1 min-w-0",children:s.map((e,r)=>(0,t.jsxs)(l.default.Fragment,{children:[r>0&&(0,t.jsx)(m.Icon,{icon:A,size:"xs",className:"shrink-0 text-gray-400"}),(0,t.jsx)(n,{modelName:e})]},e))})]})}(0,Array.isArray(i)?i:[],k)}),(0,t.jsx)(c.TableCell,{className:"align-top",children:R&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(I.Tooltip,{title:"Test fallback",children:(0,t.jsx)(m.Icon,{icon:F.PlayIcon,size:"sm",onClick:()=>q(Object.keys(r)[0],e||""),className:"cursor-pointer hover:text-blue-600"})}),(0,t.jsx)(I.Tooltip,{title:"Delete fallback",children:(0,t.jsx)("span",{"data-testid":"delete-fallback-button",role:"button",tabIndex:0,onClick:()=>C(r),onKeyDown:e=>"Enter"===e.key&&C(r),className:"cursor-pointer inline-flex",children:(0,t.jsx)(m.Icon,{icon:w.TrashIcon,size:"sm",className:"hover:text-red-600"})})})]})})]},a.toString()+s)}))})]}):(0,t.jsx)("div",{className:"rounded-lg border border-gray-200 bg-gray-50 px-4 py-6 text-center",children:(0,t.jsx)(L.Typography.Text,{type:"secondary",children:"No fallbacks configured. Add fallbacks to automatically try another model when the primary fails."})}),(0,t.jsx)(O.default,{isOpen:x,title:"Delete Fallback?",message:"Are you sure you want to delete this fallback? This action cannot be undone.",resourceInformationTitle:"Fallback Information",resourceInformation:[{label:"Model Name",value:f?Object.keys(f)[0]:"",code:!0}],onCancel:()=>{b(!1),y(null)},onOk:v,confirmLoading:p})]})};var J=e.i(175712),Q=e.i(525720),V=e.i(311451),Y=e.i(770914),X=e.i(646563),W=e.i(91979),Z=e.i(928685),ee=e.i(135214),et=e.i(954616),el=e.i(266027),er=e.i(912598),ea=e.i(243652);let es=(0,ea.createQueryKeys)("routingGroups"),en=async e=>{let t=await (0,_.getRouterSettingsCall)(e),l=t?.current_values??{},r=(Array.isArray(t?.fields)?t.fields:[]).find(e=>e?.field_name==="routing_strategy");return{routingGroups:Array.isArray(l.routing_groups)?l.routing_groups:[],routingStrategy:l.routing_strategy??null,availableStrategies:Array.isArray(r?.options)?r.options:[]}},ei=(0,ea.createQueryKeys)("routerFields"),eo=async e=>{try{let t=_.proxyBaseUrl?`${_.proxyBaseUrl}/router/fields`:"/router/fields";console.log("Fetching router fields from:",t);let l=await fetch(t,{method:"GET",headers:{[(0,_.getGlobalLitellmHeaderName)()]:`Bearer ${e}`,"Content-Type":"application/json"}});if(!l.ok){let e=await l.json(),t=e?.error&&(e.error.message||e.error)||e?.message||e?.detail||e?.error||JSON.stringify(e);throw Error(t)}let r=await l.json();return console.log("Fetched router fields:",r),r}catch(e){throw console.error("Failed to fetch router fields:",e),e}};var ec=e.i(625901),ed=e.i(592392),eu=e.i(291542),eg=e.i(653496),em=e.i(262218),ep=e.i(539677),eh=e.i(955135),ef=e.i(751904),ey=e.i(245094);let{Text:ex,Paragraph:eb}=L.Typography,e_=e=>{switch(e){case"simple-shuffle":return"Simple Shuffle";case"least-busy":return"Least Busy";case"usage-based-routing":return"Usage Based";case"latency-based-routing":return"Latency Based";default:return e}},ej=e=>e.models[0]??"",ew={backgroundColor:"#111827",color:"#f3f4f6",borderRadius:6,padding:16,fontSize:12,whiteSpace:"pre",overflowX:"auto"},ek=({group:e,baseUrl:r})=>{let a={curl:`curl -X POST '${r}/v1/chat/completions' \\ + -H 'Content-Type: application/json' \\ + -H 'Authorization: Bearer $LITELLM_API_KEY' \\ + -d '{ + "model": "${ej(e)}", + "messages": [{"role": "user", "content": "Hello!"}] + }'`,python:`from openai import OpenAI + +client = OpenAI( + api_key="$LITELLM_API_KEY", + base_url="${r}", +) + +response = client.chat.completions.create( + model="${ej(e)}", + messages=[{"role": "user", "content": "Hello!"}], +) + +print(response)`,javascript:`import OpenAI from "openai"; + +const client = new OpenAI({ + apiKey: process.env.LITELLM_API_KEY, + baseURL: "${r}", +}); + +const response = await client.chat.completions.create({ + model: "${ej(e)}", + messages: [{ role: "user", content: "Hello!" }], +}); + +console.log(response);`},[s,n]=(0,l.useState)("curl"),i=[{key:"curl",label:"cURL"},{key:"python",label:"Python (OpenAI SDK)"},{key:"javascript",label:"JavaScript (OpenAI SDK)"}].map(({key:e,label:l})=>({key:e,label:l,children:(0,t.jsx)(eb,{code:!0,className:"!mb-0",style:ew,children:a[e]})}));return(0,t.jsx)(eg.Tabs,{size:"small",activeKey:s,onChange:e=>n(e),items:i,tabBarExtraContent:(0,t.jsx)(eb,{copyable:{text:a[s],tooltips:["Copy","Copied"]},className:"!mb-0"})})},eC=({groups:e,loading:r,onEdit:a,onDelete:s,proxyBaseUrl:n})=>{let[i,o]=(0,l.useState)([]),c=n&&n.trim()?n:window.location?.origin?window.location.origin:"",d=[{title:"GROUP NAME",dataIndex:"group_name",key:"group_name",render:e=>(0,t.jsx)(ex,{strong:!0,className:"text-blue-600",children:e})},{title:"MODELS",dataIndex:"models",key:"models",render:e=>(0,t.jsx)(Q.Flex,{wrap:"wrap",gap:4,children:e.map(e=>(0,t.jsx)(em.Tag,{children:e},e))})},{title:"STRATEGY",dataIndex:"routing_strategy",key:"routing_strategy",render:e=>(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:[(0,t.jsx)(ep.BranchesOutlined,{className:"text-gray-400"}),(0,t.jsx)(ex,{children:e_(e)})]})},{title:"ACTIONS",key:"actions",width:120,align:"right",render:(e,l)=>(0,t.jsxs)(Q.Flex,{justify:"flex-end",align:"center",gap:8,children:[(0,t.jsx)(I.Tooltip,{title:"Edit",children:(0,t.jsx)(C.Button,{type:"text",icon:(0,t.jsx)(ef.EditOutlined,{}),onClick:e=>{e.stopPropagation(),a(l)}})}),(0,t.jsx)(I.Tooltip,{title:"Delete",children:(0,t.jsx)(C.Button,{type:"text",danger:!0,icon:(0,t.jsx)(eh.DeleteOutlined,{}),onClick:e=>{e.stopPropagation(),s(l)}})})]})}];return(0,t.jsx)(eu.Table,{rowKey:"group_name",columns:d,dataSource:e,loading:r,pagination:!1,expandable:{expandedRowKeys:i,onExpandedRowsChange:e=>o([...e]),expandedRowRender:e=>(0,t.jsxs)("div",{className:"bg-gray-50 border border-gray-200 rounded-md p-4 my-2",children:[(0,t.jsxs)(Q.Flex,{align:"center",gap:8,className:"mb-2",children:[(0,t.jsx)(ey.CodeOutlined,{className:"text-blue-500"}),(0,t.jsx)(ex,{strong:!0,children:"How routing works for this group"})]}),(0,t.jsxs)(eb,{className:"text-sm text-gray-600 mb-3",children:["Callers request any model in the group by name — LiteLLM picks a deployment behind the scenes using the"," ",(0,t.jsx)(ex,{strong:!0,children:e_(e.routing_strategy)})," strategy."]}),(0,t.jsx)(ek,{group:e,baseUrl:c})]})}})};var eS=e.i(808613),ev=e.i(199133);let{Text:eT,Paragraph:eN}=L.Typography,eA=new Set(["latency-based-routing","usage-based-routing"]),eF=/^[A-Za-z0-9._-]+$/,eI=({open:e,mode:r,initialValue:a,availableStrategies:s,strategyDescriptions:n,modelOptions:i,existingGroupNames:o,onClose:c,onSubmit:d,saving:u})=>{let[g]=eS.Form.useForm(),m=eS.Form.useWatch("routing_strategy",g),p={group_name:a?.group_name??"",models:a?.models??[],routing_strategy:a?.routing_strategy??s[0]??"simple-shuffle",routing_strategy_args:a?.routing_strategy_args?JSON.stringify(a.routing_strategy_args,null,2):""},h=(0,l.useMemo)(()=>new Set(o.filter(e=>e!==a?.group_name).map(e=>e.toLowerCase())),[o,a]),f=async()=>{let e=await g.validateFields(),t=eA.has(String(e.routing_strategy)),l=null;if(t&&e.routing_strategy_args&&e.routing_strategy_args.trim())try{l=JSON.parse(e.routing_strategy_args)}catch{g.setFields([{name:"routing_strategy_args",errors:["Must be valid JSON"]}]);return}await d({group_name:e.group_name.trim(),models:e.models,routing_strategy:e.routing_strategy,routing_strategy_args:l})};return(0,t.jsx)(D.Modal,{title:"create"===r?"Create Routing Group":`Edit ${a?.group_name??""}`,open:e,onCancel:c,onOk:f,okText:"create"===r?"Create Group":"Save Changes",cancelText:"Cancel",confirmLoading:u,destroyOnClose:!0,width:560,children:(0,t.jsxs)(eS.Form,{form:g,layout:"vertical",preserve:!1,initialValues:p,children:[(0,t.jsx)(eS.Form.Item,{label:"Group Name",name:"group_name",rules:[{required:!0,message:"Group name is required"},{max:64,message:"Must be 64 characters or fewer"},{pattern:eF,message:"Only letters, numbers, dot, underscore, and dash are allowed"},{validator:(e,t)=>t&&h.has(t.trim().toLowerCase())?Promise.reject(Error("A group with this name already exists")):Promise.resolve()}],extra:"Use this name as the model in API calls — LiteLLM routes the request to one of the group's models.",children:(0,t.jsx)(V.Input,{placeholder:"fast-chat",disabled:"edit"===r})}),(0,t.jsx)(eS.Form.Item,{label:"Models",name:"models",rules:[{required:!0,message:"Select at least one model"}],extra:"Models from your model list that this group routes between.",children:(0,t.jsx)(ev.Select,{mode:"multiple",allowClear:!0,placeholder:"Select models",options:i.map(e=>({label:e,value:e})),optionFilterProp:"label"})}),(0,t.jsx)(eS.Form.Item,{label:"Routing Strategy",name:"routing_strategy",rules:[{required:!0,message:"Strategy is required"}],children:(0,t.jsx)(ev.Select,{options:s.map(e=>({label:e,value:e})),placeholder:"Select strategy"})}),m&&n[m]&&(0,t.jsx)(eN,{className:"text-xs text-gray-500 -mt-2 mb-4",children:n[m]}),eA.has(String(m))&&(0,t.jsx)(eS.Form.Item,{label:"Strategy Arguments (JSON)",name:"routing_strategy_args",extra:"latency-based-routing"===m?'Example: { "ttl": 3600, "lowest_latency_buffer": 0 }':'Example: { "ttl": 60 }',children:(0,t.jsx)(V.Input.TextArea,{rows:4,placeholder:'{ "ttl": 3600 }',className:"font-mono text-xs"})}),(0,t.jsx)(Y.Space,{direction:"vertical",className:"w-full mt-2",children:(0,t.jsx)(eT,{type:"secondary",className:"text-xs",children:"Models not claimed by an explicit group fall through to the proxy's top-level routing strategy."})})]},"edit"===r?`edit-${a?.group_name??""}`:"create")})},{Text:eL}=L.Typography,eM=()=>{let{data:e,isLoading:r,refetch:a,isFetching:s}=(()=>{let{accessToken:e,userId:t,userRole:l}=(0,ee.default)();return(0,el.useQuery)({queryKey:es.lists(),queryFn:()=>en(e),enabled:!!(e&&t&&l)})})(),{data:n}=(()=>{let{accessToken:e,userId:t,userRole:l}=(0,ee.default)();return(0,el.useQuery)({queryKey:ei.detail("fields"),queryFn:async()=>await eo(e),enabled:!!(e&&t&&l)})})(),{data:i}=(0,ec.useModelHub)(),{accessToken:o}=(0,ee.default)(),c=(0,ed.default)(o),d=(()=>{let{accessToken:e}=(0,ee.default)(),t=(0,er.useQueryClient)();return(0,et.useMutation)({mutationFn:t=>(0,_.setCallbacksCall)(e,{router_settings:{routing_groups:t}}),onSuccess:()=>{t.invalidateQueries({queryKey:es.lists()})}})})(),[u,g]=(0,l.useState)(""),[m,p]=(0,l.useState)(!1),[h,f]=(0,l.useState)("create"),[y,x]=(0,l.useState)(null),[b,j]=(0,l.useState)(null),w=e?.routingGroups??[],k=(0,l.useMemo)(()=>{let e=u.trim().toLowerCase();return e?w.filter(t=>t.group_name.toLowerCase().includes(e)||t.routing_strategy.toLowerCase().includes(e)||t.models.some(t=>t.toLowerCase().includes(e))):w},[w,u]),v=(0,l.useMemo)(()=>e?.availableStrategies?.length?e.availableStrategies:n?.fields?.find(e=>"routing_strategy"===e.field_name)?.options??[],[e?.availableStrategies,n]),T=n?.routing_strategy_descriptions??{},N=(0,l.useMemo)(()=>Array.from(new Set((i?.data??[]).map(e=>e.model_group).filter(e=>!!e))),[i]),A=async e=>{let t="create"===h?[...w,e]:w.map(t=>t.group_name===y?.group_name?e:t);try{await d.mutateAsync(t),S.default.success("create"===h?`Created routing group "${e.group_name}"`:`Updated routing group "${e.group_name}"`),p(!1)}catch(e){S.default.error(e instanceof Error?e.message:"Failed to save routing group")}},F=async()=>{if(!b)return;let e=w.filter(e=>e.group_name!==b.group_name);try{await d.mutateAsync(e),S.default.success(`Deleted routing group "${b.group_name}"`),j(null)}catch(e){S.default.error(e instanceof Error?e.message:"Failed to delete routing group")}};return(0,t.jsxs)(Y.Space,{direction:"vertical",size:16,className:"w-full",children:[(0,t.jsxs)(J.Card,{bodyStyle:{padding:16},children:[(0,t.jsxs)(Q.Flex,{justify:"space-between",align:"center",gap:12,className:"mb-4",children:[(0,t.jsx)(V.Input,{allowClear:!0,prefix:(0,t.jsx)(Z.SearchOutlined,{className:"text-gray-400"}),placeholder:"Search groups...",value:u,onChange:e=>g(e.target.value),className:"max-w-sm"}),(0,t.jsxs)(Q.Flex,{align:"center",gap:12,children:[(0,t.jsx)(C.Button,{icon:(0,t.jsx)(W.ReloadOutlined,{}),onClick:()=>a(),loading:s&&!r,children:"Refresh"}),(0,t.jsx)(C.Button,{type:"primary",icon:(0,t.jsx)(X.PlusOutlined,{}),onClick:()=>{f("create"),x(null),p(!0)},children:"Create Group"}),(0,t.jsxs)(eL,{type:"secondary",className:"text-sm whitespace-nowrap",children:["Showing ",k.length," ",1===k.length?"result":"results"]})]})]}),(0,t.jsx)(eC,{groups:k,loading:r,onEdit:e=>{f("edit"),x(e),p(!0)},onDelete:e=>j(e),proxyBaseUrl:c.LITELLM_UI_API_DOC_BASE_URL?.trim()||c.PROXY_BASE_URL||""})]}),(0,t.jsx)(eI,{open:m,mode:h,initialValue:y,availableStrategies:v,strategyDescriptions:T,modelOptions:N,existingGroupNames:w.map(e=>e.group_name),onClose:()=>p(!1),onSubmit:A,saving:d.isPending}),(0,t.jsx)(D.Modal,{open:!!b,title:"Delete routing group?",okText:"Delete",okButtonProps:{danger:!0,loading:d.isPending},cancelText:"Cancel",onOk:F,onCancel:()=>j(null),children:(0,t.jsxs)(eL,{children:["Models in ",(0,t.jsx)(eL,{strong:!0,children:b?.group_name})," will fall back to the proxy's top-level routing strategy. This cannot be undone."]})})]})},eO=({accessToken:e,userRole:C,userID:S})=>{let[v,N]=(0,l.useState)([]);(0,l.useEffect)(()=>{e&&(0,_.getGeneralSettingsCall)(e).then(e=>{N(e)})},[e]);let A=(e,t)=>{N(v.map(l=>l.field_name===e?{...l,field_value:t}:l))};return e?(0,t.jsx)("div",{className:"w-full",children:(0,t.jsxs)(y.TabGroup,{className:"h-[75vh] w-full",children:[(0,t.jsxs)(x.TabList,{variant:"line",defaultValue:"1",className:"px-8 pt-4",children:[(0,t.jsx)(b.Tab,{value:"1",children:"Loadbalancing"}),(0,t.jsx)(b.Tab,{value:"2",children:"Routing Groups"}),(0,t.jsx)(b.Tab,{value:"3",children:"Fallbacks"}),(0,t.jsx)(b.Tab,{value:"4",children:"General"})]}),(0,t.jsxs)(f.TabPanels,{className:"px-8 py-6",children:[(0,t.jsx)(h.TabPanel,{children:(0,t.jsx)(T,{accessToken:e,userRole:C,userID:S})}),(0,t.jsx)(h.TabPanel,{children:(0,t.jsx)(eM,{})}),(0,t.jsx)(h.TabPanel,{children:(0,t.jsx)(z,{accessToken:e,userRole:C,userID:S})}),(0,t.jsx)(h.TabPanel,{children:(0,t.jsx)(r.Card,{children:(0,t.jsxs)(a.Table,{children:[(0,t.jsx)(s.TableHead,{children:(0,t.jsxs)(n.TableRow,{children:[(0,t.jsx)(o.TableHeaderCell,{children:"Setting"}),(0,t.jsx)(o.TableHeaderCell,{children:"Value"}),(0,t.jsx)(o.TableHeaderCell,{children:"Status"}),(0,t.jsx)(o.TableHeaderCell,{children:"Action"})]})}),(0,t.jsx)(d.TableBody,{children:v.filter(e=>"TypedDictionary"!==e.field_type).map((l,r)=>(0,t.jsxs)(n.TableRow,{children:[(0,t.jsxs)(c.TableCell,{children:[(0,t.jsx)(u.Text,{children:l.field_name}),(0,t.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:l.field_description})]}),(0,t.jsx)(c.TableCell,{children:"Integer"==l.field_type?(0,t.jsx)(j.InputNumber,{step:1,value:l.field_value,onChange:e=>A(l.field_name,e)}):"Boolean"==l.field_type?(0,t.jsx)(p.Switch,{checked:!0===l.field_value||"true"===l.field_value,onChange:e=>A(l.field_name,e)}):null}),(0,t.jsx)(c.TableCell,{children:!0==l.stored_in_db?(0,t.jsx)(i.Badge,{icon:k.CheckCircleIcon,className:"text-white",children:"In DB"}):!1==l.stored_in_db?(0,t.jsx)(i.Badge,{className:"text-gray bg-white outline",children:"In Config"}):(0,t.jsx)(i.Badge,{className:"text-gray bg-white outline",children:"Not Set"})}),(0,t.jsxs)(c.TableCell,{children:[(0,t.jsx)(g.Button,{onClick:()=>((t,l)=>{if(!e)return;let r=v[l].field_value;if(null!=r&&void 0!=r)try{(0,_.updateConfigFieldSetting)(e,t,r);let l=v.map(e=>e.field_name===t?{...e,stored_in_db:!0}:e);N(l)}catch(e){}})(l.field_name,r),children:"Update"}),(0,t.jsx)(m.Icon,{icon:w.TrashIcon,color:"red",onClick:()=>((t,l)=>{if(e)try{(0,_.deleteConfigFieldSetting)(e,t);let l=v.map(e=>e.field_name===t?{...e,stored_in_db:null,field_value:null}:e);N(l)}catch(e){}})(l.field_name,0),children:"Reset"})]})]},r))})]})})})]})]})}):null};function eB(){let{accessToken:e,userRole:l,userId:r}=(0,ee.default)();return(0,t.jsx)(eO,{userID:r,userRole:l,accessToken:e})}e.s(["default",()=>eB],389543)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/0a65da2cd24e2ab6.js b/litellm/proxy/_experimental/out/_next/static/chunks/0a65da2cd24e2ab6.js new file mode 100644 index 00000000000..0bb6bef6dc3 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/0a65da2cd24e2ab6.js @@ -0,0 +1,3 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,621642,25080,e=>{"use strict";var t=e.i(290571),r=e.i(271645),n=e.i(144582),a=e.i(888288),o=e.i(757440);let l=e=>{var n=(0,t.__rest)(e,[]);return r.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},n),r.default.createElement("path",{d:"M18.031 16.6168L22.3137 20.8995L20.8995 22.3137L16.6168 18.031C15.0769 19.263 13.124 20 11 20C6.032 20 2 15.968 2 11C2 6.032 6.032 2 11 2C15.968 2 20 6.032 20 11C20 13.124 19.263 15.0769 18.031 16.6168ZM16.0247 15.8748C17.2475 14.6146 18 12.8956 18 11C18 7.1325 14.8675 4 11 4C7.1325 4 4 7.1325 4 11C4 14.8675 7.1325 18 11 18C12.8956 18 14.6146 17.2475 15.8748 16.0247L16.0247 15.8748Z"}))};var s=e.i(446428);let i=e=>{var n=(0,t.__rest)(e,[]);return r.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",width:"100%",height:"100%",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},n),r.default.createElement("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),r.default.createElement("line",{x1:"6",y1:"6",x2:"18",y2:"18"}))};var u=e.i(444755),d=e.i(673706),c=e.i(103471),m=e.i(495470),f=e.i(854056);let h=(0,d.makeClassName)("MultiSelect"),p=r.default.forwardRef((e,d)=>{let{defaultValue:p=[],value:b,onValueChange:v,placeholder:g="Select...",placeholderSearch:w="Search",disabled:y=!1,icon:x,children:k,className:M,required:D,name:N,error:E=!1,errorMessage:S,id:P}=e,T=(0,t.__rest)(e,["defaultValue","value","onValueChange","placeholder","placeholderSearch","disabled","icon","children","className","required","name","error","errorMessage","id"]),C=(0,r.useRef)(null),[_,j]=(0,a.default)(p,b),{reactElementChildren:L,optionsAvailable:F}=(0,r.useMemo)(()=>{let e=r.default.Children.toArray(k).filter(r.isValidElement);return{reactElementChildren:e,optionsAvailable:(0,c.getFilteredOptions)("",e)}},[k]),[O,I]=(0,r.useState)(""),Y=(null!=_?_:[]).length>0,W=(0,r.useMemo)(()=>O?(0,c.getFilteredOptions)(O,L):F,[O,L,F]),H=()=>{I("")};return r.default.createElement("div",{className:(0,u.tremorTwMerge)("w-full min-w-[10rem] text-tremor-default",M)},r.default.createElement("div",{className:"relative"},r.default.createElement("select",{title:"multi-select-hidden",required:D,className:(0,u.tremorTwMerge)("h-full w-full absolute left-0 top-0 -z-10 opacity-0"),value:_,onChange:e=>{e.preventDefault()},name:N,disabled:y,multiple:!0,id:P,onFocus:()=>{let e=C.current;e&&e.focus()}},r.default.createElement("option",{className:"hidden",value:"",disabled:!0,hidden:!0},g),W.map(e=>{let t=e.props.value,n=e.props.children;return r.default.createElement("option",{className:"hidden",key:t,value:t},n)})),r.default.createElement(m.Listbox,Object.assign({as:"div",ref:d,defaultValue:_,value:_,onChange:e=>{null==v||v(e),j(e)},disabled:y,id:P,multiple:!0},T),({value:e})=>r.default.createElement(r.default.Fragment,null,r.default.createElement(m.ListboxButton,{className:(0,u.tremorTwMerge)("w-full outline-none text-left whitespace-nowrap truncate rounded-tremor-default focus:ring-2 transition duration-100 border pr-8 py-1.5","border-tremor-border shadow-tremor-input focus:border-tremor-brand-subtle focus:ring-tremor-brand-muted","dark:border-dark-tremor-border dark:shadow-dark-tremor-input dark:focus:border-dark-tremor-brand-subtle dark:focus:ring-dark-tremor-brand-muted",x?"pl-11 -ml-0.5":"pl-3",(0,c.getSelectButtonColors)(e.length>0,y,E)),ref:C},x&&r.default.createElement("span",{className:(0,u.tremorTwMerge)("absolute inset-y-0 left-0 flex items-center ml-px pl-2.5")},r.default.createElement(x,{className:(0,u.tremorTwMerge)(h("Icon"),"flex-none h-5 w-5","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")})),r.default.createElement("div",{className:"h-6 flex items-center"},e.length>0?r.default.createElement("div",{className:"flex flex-nowrap overflow-x-scroll [&::-webkit-scrollbar]:hidden [scrollbar-width:none] gap-x-1 mr-5 -ml-1.5 relative"},F.filter(t=>e.includes(t.props.value)).map((t,n)=>{var a;return r.default.createElement("div",{key:n,className:(0,u.tremorTwMerge)("max-w-[100px] lg:max-w-[200px] flex justify-center items-center pl-2 pr-1.5 py-1 font-medium","rounded-tremor-small","bg-tremor-background-muted dark:bg-dark-tremor-background-muted","bg-tremor-background-subtle dark:bg-dark-tremor-background-subtle","text-tremor-content-default dark:text-dark-tremor-content-default","text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis")},r.default.createElement("div",{className:"text-xs truncate "},null!=(a=t.props.children)?a:t.props.value),r.default.createElement("div",{onClick:r=>{r.preventDefault();let n=e.filter(e=>e!==t.props.value);null==v||v(n),j(n)}},r.default.createElement(i,{className:(0,u.tremorTwMerge)(h("clearIconItem"),"cursor-pointer rounded-tremor-full w-3.5 h-3.5 ml-2","text-tremor-content-subtle hover:text-tremor-content","dark:text-dark-tremor-content-subtle dark:hover:text-tremor-content")})))})):r.default.createElement("span",null,g)),r.default.createElement("span",{className:(0,u.tremorTwMerge)("absolute inset-y-0 right-0 flex items-center mr-2.5")},r.default.createElement(o.default,{className:(0,u.tremorTwMerge)(h("arrowDownIcon"),"flex-none h-5 w-5","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")}))),Y&&!y?r.default.createElement("button",{type:"button",className:(0,u.tremorTwMerge)("absolute inset-y-0 right-0 flex items-center mr-8"),onClick:e=>{e.preventDefault(),j([]),null==v||v([])}},r.default.createElement(s.default,{className:(0,u.tremorTwMerge)(h("clearIconAllItems"),"flex-none h-4 w-4","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")})):null,r.default.createElement(f.Transition,{enter:"transition ease duration-100 transform",enterFrom:"opacity-0 -translate-y-4",enterTo:"opacity-100 translate-y-0",leave:"transition ease duration-100 transform",leaveFrom:"opacity-100 translate-y-0",leaveTo:"opacity-0 -translate-y-4"},r.default.createElement(m.ListboxOptions,{anchor:"bottom start",className:(0,u.tremorTwMerge)("z-10 divide-y w-[var(--button-width)] overflow-y-auto outline-none rounded-tremor-default max-h-[228px] border [--anchor-gap:4px]","bg-tremor-background border-tremor-border divide-tremor-border shadow-tremor-dropdown","dark:bg-dark-tremor-background dark:border-dark-tremor-border dark:divide-dark-tremor-border dark:shadow-dark-tremor-dropdown")},r.default.createElement("div",{className:(0,u.tremorTwMerge)("flex items-center w-full px-2.5","bg-tremor-background-muted","dark:bg-dark-tremor-background-muted")},r.default.createElement("span",null,r.default.createElement(l,{className:(0,u.tremorTwMerge)("flex-none w-4 h-4 mr-2","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")})),r.default.createElement("input",{name:"search",type:"input",autoComplete:"off",placeholder:w,className:(0,u.tremorTwMerge)("w-full focus:outline-none focus:ring-none bg-transparent text-tremor-default py-2","text-tremor-content-emphasis","dark:text-dark-tremor-content-subtle"),onKeyDown:e=>{"Space"===e.code&&""!==e.target.value&&e.stopPropagation()},onChange:e=>I(e.target.value),value:O})),r.default.createElement(n.default.Provider,Object.assign({},{onBlur:{handleResetSearch:H}},{value:{selectedValue:e}}),W)))))),E&&S?r.default.createElement("p",{className:(0,u.tremorTwMerge)("errorMessage","text-sm text-rose-500 mt-1")},S):null)});p.displayName="MultiSelect",e.s(["MultiSelect",()=>p],621642);let b=(0,d.makeClassName)("MultiSelectItem"),v=r.default.forwardRef((e,a)=>{let{value:o,className:l,children:s}=e,i=(0,t.__rest)(e,["value","className","children"]),{selectedValue:c}=(0,r.useContext)(n.default),f=(0,d.isValueInArray)(o,c);return r.default.createElement(m.ListboxOption,Object.assign({className:(0,u.tremorTwMerge)(b("root"),"flex justify-start items-center cursor-default text-tremor-default p-2.5","data-[focus]:bg-tremor-background-muted data-[focus]:text-tremor-content-strong data-[select]ed:text-tremor-content-strong text-tremor-content-emphasis","dark:data-[focus]:bg-dark-tremor-background-muted dark:data-[focus]:text-dark-tremor-content-strong dark:data-[select]ed:text-dark-tremor-content-strong dark:data-[select]ed:bg-dark-tremor-background-muted dark:text-dark-tremor-content-emphasis",l),ref:a,key:o,value:o},i),r.default.createElement("input",{type:"checkbox",className:(0,u.tremorTwMerge)(b("checkbox"),"flex-none focus:ring-none focus:outline-none cursor-pointer mr-2.5","accent-tremor-brand","dark:accent-dark-tremor-brand"),checked:f,readOnly:!0}),r.default.createElement("span",{className:"whitespace-nowrap truncate"},null!=s?s:o))});v.displayName="MultiSelectItem",e.s(["MultiSelectItem",()=>v],25080)},144267,e=>{"use strict";let t,r,n;var a,o,l,s=e.i(843476),i=e.i(271645),u=e.i(290571);let d=e=>{var t=(0,u.__rest)(e,[]);return i.default.createElement("svg",Object.assign({},t,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"}),i.default.createElement("path",{fillRule:"evenodd",d:"M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z",clipRule:"evenodd"}))};var c=e.i(446428),m=e.i(435684);function f(e){let t=(0,m.toDate)(e);return t.setHours(0,0,0,0),t}function h(){return f(Date.now())}function p(e){let t=(0,m.toDate)(e);return t.setDate(1),t.setHours(0,0,0,0),t}var b=e.i(444755),v=e.i(103471),g=e.i(439189);function w(e,t){return(0,g.addDays)(e,-t)}var y=e.i(497245),x=e.i(96226);function k(e,t){var r;let{years:n=0,months:a=0,weeks:o=0,days:l=0,hours:s=0,minutes:i=0,seconds:u=0}=t,d=w((r=a+12*n,(0,y.addMonths)(e,-r)),l+7*o);return(0,x.constructFrom)(e,d.getTime()-1e3*(u+60*(i+60*s)))}function M(e){let t=(0,m.toDate)(e),r=(0,x.constructFrom)(e,0);return r.setFullYear(t.getFullYear(),0,1),r.setHours(0,0,0,0),r}function D(e){let t;return e.forEach(function(e){let r=(0,m.toDate)(e);(void 0===t||t{let r=(0,m.toDate)(e);(!t||t>r||isNaN(+r))&&(t=r)}),t||new Date(NaN)}let E={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}};function S(e){return (t={})=>{let r=t.width?String(t.width):e.defaultWidth;return e.formats[r]||e.formats[e.defaultWidth]}}let P={date:S({formats:{full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},defaultWidth:"full"}),time:S({formats:{full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},defaultWidth:"full"}),dateTime:S({formats:{full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},defaultWidth:"full"})},T={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"};function C(e){return(t,r)=>{let n;if("formatting"===(r?.context?String(r.context):"standalone")&&e.formattingValues){let t=e.defaultFormattingWidth||e.defaultWidth,a=r?.width?String(r.width):t;n=e.formattingValues[a]||e.formattingValues[t]}else{let t=e.defaultWidth,a=r?.width?String(r.width):e.defaultWidth;n=e.values[a]||e.values[t]}return n[e.argumentCallback?e.argumentCallback(t):t]}}function _(e){return(t,r={})=>{let n,a=r.width,o=a&&e.matchPatterns[a]||e.matchPatterns[e.defaultMatchWidth],l=t.match(o);if(!l)return null;let s=l[0],i=a&&e.parsePatterns[a]||e.parsePatterns[e.defaultParseWidth],u=Array.isArray(i)?function(e,t){for(let r=0;re.test(s)):function(e,t){for(let r in e)if(Object.prototype.hasOwnProperty.call(e,r)&&t(e[r]))return r}(i,e=>e.test(s));return n=e.valueCallback?e.valueCallback(u):u,{value:n=r.valueCallback?r.valueCallback(n):n,rest:t.slice(s.length)}}}let j={code:"en-US",formatDistance:(e,t,r)=>{let n,a=E[e];if(n="string"==typeof a?a:1===t?a.one:a.other.replace("{{count}}",t.toString()),r?.addSuffix)if(r.comparison&&r.comparison>0)return"in "+n;else return n+" ago";return n},formatLong:P,formatRelative:(e,t,r,n)=>T[e],localize:{ordinalNumber:(e,t)=>{let r=Number(e),n=r%100;if(n>20||n<10)switch(n%10){case 1:return r+"st";case 2:return r+"nd";case 3:return r+"rd"}return r+"th"},era:C({values:{narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},defaultWidth:"wide"}),quarter:C({values:{narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},defaultWidth:"wide",argumentCallback:e=>e-1}),month:C({values:{narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},defaultWidth:"wide"}),day:C({values:{narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},defaultWidth:"wide"}),dayPeriod:C({values:{narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},defaultWidth:"wide",formattingValues:{narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},defaultFormattingWidth:"wide"})},match:{ordinalNumber:(a={matchPattern:/^(\d+)(th|st|nd|rd)?/i,parsePattern:/\d+/i,valueCallback:e=>parseInt(e,10)},(e,t={})=>{let r=e.match(a.matchPattern);if(!r)return null;let n=r[0],o=e.match(a.parsePattern);if(!o)return null;let l=a.valueCallback?a.valueCallback(o[0]):o[0];return{value:l=t.valueCallback?t.valueCallback(l):l,rest:e.slice(n.length)}}),era:_({matchPatterns:{narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},defaultMatchWidth:"wide",parsePatterns:{any:[/^b/i,/^(a|c)/i]},defaultParseWidth:"any"}),quarter:_({matchPatterns:{narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},defaultMatchWidth:"wide",parsePatterns:{any:[/1/i,/2/i,/3/i,/4/i]},defaultParseWidth:"any",valueCallback:e=>e+1}),month:_({matchPatterns:{narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},defaultMatchWidth:"wide",parsePatterns:{narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},defaultParseWidth:"any"}),day:_({matchPatterns:{narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},defaultMatchWidth:"wide",parsePatterns:{narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},defaultParseWidth:"any"}),dayPeriod:_({matchPatterns:{narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},defaultMatchWidth:"any",parsePatterns:{any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},defaultParseWidth:"any"})},options:{weekStartsOn:0,firstWeekContainsDate:1}},L={};function F(e){let t=(0,m.toDate)(e),r=new Date(Date.UTC(t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),t.getMinutes(),t.getSeconds(),t.getMilliseconds()));return r.setUTCFullYear(t.getFullYear()),e-r}function O(e,t){let r=f(e),n=f(t);return Math.round((r-F(r)-(n-F(n)))/864e5)}function I(e,t){let r=t?.weekStartsOn??t?.locale?.options?.weekStartsOn??L.weekStartsOn??L.locale?.options?.weekStartsOn??0,n=(0,m.toDate)(e),a=n.getDay();return n.setDate(n.getDate()-(7*(a=a.getTime()?r+1:t.getTime()>=l.getTime()?r:r-1}function H(e){let t,r,n=(0,m.toDate)(e);return Math.round((Y(n)-(t=W(n),(r=(0,x.constructFrom)(n,0)).setFullYear(t,0,4),r.setHours(0,0,0,0),Y(r)))/6048e5)+1}function R(e,t){let r=(0,m.toDate)(e),n=r.getFullYear(),a=t?.firstWeekContainsDate??t?.locale?.options?.firstWeekContainsDate??L.firstWeekContainsDate??L.locale?.options?.firstWeekContainsDate??1,o=(0,x.constructFrom)(e,0);o.setFullYear(n+1,0,a),o.setHours(0,0,0,0);let l=I(o,t),s=(0,x.constructFrom)(e,0);s.setFullYear(n,0,a),s.setHours(0,0,0,0);let i=I(s,t);return r.getTime()>=l.getTime()?n+1:r.getTime()>=i.getTime()?n:n-1}function B(e,t){let r,n,a,o=(0,m.toDate)(e);return Math.round((I(o,t)-(r=t?.firstWeekContainsDate??t?.locale?.options?.firstWeekContainsDate??L.firstWeekContainsDate??L.locale?.options?.firstWeekContainsDate??1,n=R(o,t),(a=(0,x.constructFrom)(o,0)).setFullYear(n,0,r),a.setHours(0,0,0,0),I(a,t)))/6048e5)+1}function q(e,t){let r=Math.abs(e).toString().padStart(t,"0");return(e<0?"-":"")+r}let A={y(e,t){let r=e.getFullYear(),n=r>0?r:1-r;return q("yy"===t?n%100:n,t.length)},M(e,t){let r=e.getMonth();return"M"===t?String(r+1):q(r+1,2)},d:(e,t)=>q(e.getDate(),t.length),a(e,t){let r=e.getHours()/12>=1?"pm":"am";switch(t){case"a":case"aa":return r.toUpperCase();case"aaa":return r;case"aaaaa":return r[0];default:return"am"===r?"a.m.":"p.m."}},h:(e,t)=>q(e.getHours()%12||12,t.length),H:(e,t)=>q(e.getHours(),t.length),m:(e,t)=>q(e.getMinutes(),t.length),s:(e,t)=>q(e.getSeconds(),t.length),S(e,t){let r=t.length;return q(Math.trunc(e.getMilliseconds()*Math.pow(10,r-3)),t.length)}},Q={G:function(e,t,r){let n=+(e.getFullYear()>0);switch(t){case"G":case"GG":case"GGG":return r.era(n,{width:"abbreviated"});case"GGGGG":return r.era(n,{width:"narrow"});default:return r.era(n,{width:"wide"})}},y:function(e,t,r){if("yo"===t){let t=e.getFullYear();return r.ordinalNumber(t>0?t:1-t,{unit:"year"})}return A.y(e,t)},Y:function(e,t,r,n){let a=R(e,n),o=a>0?a:1-a;return"YY"===t?q(o%100,2):"Yo"===t?r.ordinalNumber(o,{unit:"year"}):q(o,t.length)},R:function(e,t){return q(W(e),t.length)},u:function(e,t){return q(e.getFullYear(),t.length)},Q:function(e,t,r){let n=Math.ceil((e.getMonth()+1)/3);switch(t){case"Q":return String(n);case"QQ":return q(n,2);case"Qo":return r.ordinalNumber(n,{unit:"quarter"});case"QQQ":return r.quarter(n,{width:"abbreviated",context:"formatting"});case"QQQQQ":return r.quarter(n,{width:"narrow",context:"formatting"});default:return r.quarter(n,{width:"wide",context:"formatting"})}},q:function(e,t,r){let n=Math.ceil((e.getMonth()+1)/3);switch(t){case"q":return String(n);case"qq":return q(n,2);case"qo":return r.ordinalNumber(n,{unit:"quarter"});case"qqq":return r.quarter(n,{width:"abbreviated",context:"standalone"});case"qqqqq":return r.quarter(n,{width:"narrow",context:"standalone"});default:return r.quarter(n,{width:"wide",context:"standalone"})}},M:function(e,t,r){let n=e.getMonth();switch(t){case"M":case"MM":return A.M(e,t);case"Mo":return r.ordinalNumber(n+1,{unit:"month"});case"MMM":return r.month(n,{width:"abbreviated",context:"formatting"});case"MMMMM":return r.month(n,{width:"narrow",context:"formatting"});default:return r.month(n,{width:"wide",context:"formatting"})}},L:function(e,t,r){let n=e.getMonth();switch(t){case"L":return String(n+1);case"LL":return q(n+1,2);case"Lo":return r.ordinalNumber(n+1,{unit:"month"});case"LLL":return r.month(n,{width:"abbreviated",context:"standalone"});case"LLLLL":return r.month(n,{width:"narrow",context:"standalone"});default:return r.month(n,{width:"wide",context:"standalone"})}},w:function(e,t,r,n){let a=B(e,n);return"wo"===t?r.ordinalNumber(a,{unit:"week"}):q(a,t.length)},I:function(e,t,r){let n=H(e);return"Io"===t?r.ordinalNumber(n,{unit:"week"}):q(n,t.length)},d:function(e,t,r){return"do"===t?r.ordinalNumber(e.getDate(),{unit:"date"}):A.d(e,t)},D:function(e,t,r){let n,a=O(n=(0,m.toDate)(e),M(n))+1;return"Do"===t?r.ordinalNumber(a,{unit:"dayOfYear"}):q(a,t.length)},E:function(e,t,r){let n=e.getDay();switch(t){case"E":case"EE":case"EEE":return r.day(n,{width:"abbreviated",context:"formatting"});case"EEEEE":return r.day(n,{width:"narrow",context:"formatting"});case"EEEEEE":return r.day(n,{width:"short",context:"formatting"});default:return r.day(n,{width:"wide",context:"formatting"})}},e:function(e,t,r,n){let a=e.getDay(),o=(a-n.weekStartsOn+8)%7||7;switch(t){case"e":return String(o);case"ee":return q(o,2);case"eo":return r.ordinalNumber(o,{unit:"day"});case"eee":return r.day(a,{width:"abbreviated",context:"formatting"});case"eeeee":return r.day(a,{width:"narrow",context:"formatting"});case"eeeeee":return r.day(a,{width:"short",context:"formatting"});default:return r.day(a,{width:"wide",context:"formatting"})}},c:function(e,t,r,n){let a=e.getDay(),o=(a-n.weekStartsOn+8)%7||7;switch(t){case"c":return String(o);case"cc":return q(o,t.length);case"co":return r.ordinalNumber(o,{unit:"day"});case"ccc":return r.day(a,{width:"abbreviated",context:"standalone"});case"ccccc":return r.day(a,{width:"narrow",context:"standalone"});case"cccccc":return r.day(a,{width:"short",context:"standalone"});default:return r.day(a,{width:"wide",context:"standalone"})}},i:function(e,t,r){let n=e.getDay(),a=0===n?7:n;switch(t){case"i":return String(a);case"ii":return q(a,t.length);case"io":return r.ordinalNumber(a,{unit:"day"});case"iii":return r.day(n,{width:"abbreviated",context:"formatting"});case"iiiii":return r.day(n,{width:"narrow",context:"formatting"});case"iiiiii":return r.day(n,{width:"short",context:"formatting"});default:return r.day(n,{width:"wide",context:"formatting"})}},a:function(e,t,r){let n=e.getHours()/12>=1?"pm":"am";switch(t){case"a":case"aa":return r.dayPeriod(n,{width:"abbreviated",context:"formatting"});case"aaa":return r.dayPeriod(n,{width:"abbreviated",context:"formatting"}).toLowerCase();case"aaaaa":return r.dayPeriod(n,{width:"narrow",context:"formatting"});default:return r.dayPeriod(n,{width:"wide",context:"formatting"})}},b:function(e,t,r){let n,a=e.getHours();switch(n=12===a?"noon":0===a?"midnight":a/12>=1?"pm":"am",t){case"b":case"bb":return r.dayPeriod(n,{width:"abbreviated",context:"formatting"});case"bbb":return r.dayPeriod(n,{width:"abbreviated",context:"formatting"}).toLowerCase();case"bbbbb":return r.dayPeriod(n,{width:"narrow",context:"formatting"});default:return r.dayPeriod(n,{width:"wide",context:"formatting"})}},B:function(e,t,r){let n,a=e.getHours();switch(n=a>=17?"evening":a>=12?"afternoon":a>=4?"morning":"night",t){case"B":case"BB":case"BBB":return r.dayPeriod(n,{width:"abbreviated",context:"formatting"});case"BBBBB":return r.dayPeriod(n,{width:"narrow",context:"formatting"});default:return r.dayPeriod(n,{width:"wide",context:"formatting"})}},h:function(e,t,r){if("ho"===t){let t=e.getHours()%12;return 0===t&&(t=12),r.ordinalNumber(t,{unit:"hour"})}return A.h(e,t)},H:function(e,t,r){return"Ho"===t?r.ordinalNumber(e.getHours(),{unit:"hour"}):A.H(e,t)},K:function(e,t,r){let n=e.getHours()%12;return"Ko"===t?r.ordinalNumber(n,{unit:"hour"}):q(n,t.length)},k:function(e,t,r){let n=e.getHours();return(0===n&&(n=24),"ko"===t)?r.ordinalNumber(n,{unit:"hour"}):q(n,t.length)},m:function(e,t,r){return"mo"===t?r.ordinalNumber(e.getMinutes(),{unit:"minute"}):A.m(e,t)},s:function(e,t,r){return"so"===t?r.ordinalNumber(e.getSeconds(),{unit:"second"}):A.s(e,t)},S:function(e,t){return A.S(e,t)},X:function(e,t,r){let n=e.getTimezoneOffset();if(0===n)return"Z";switch(t){case"X":return z(n);case"XXXX":case"XX":return V(n);default:return V(n,":")}},x:function(e,t,r){let n=e.getTimezoneOffset();switch(t){case"x":return z(n);case"xxxx":case"xx":return V(n);default:return V(n,":")}},O:function(e,t,r){let n=e.getTimezoneOffset();switch(t){case"O":case"OO":case"OOO":return"GMT"+G(n,":");default:return"GMT"+V(n,":")}},z:function(e,t,r){let n=e.getTimezoneOffset();switch(t){case"z":case"zz":case"zzz":return"GMT"+G(n,":");default:return"GMT"+V(n,":")}},t:function(e,t,r){return q(Math.trunc(e.getTime()/1e3),t.length)},T:function(e,t,r){return q(e.getTime(),t.length)}};function G(e,t=""){let r=e>0?"-":"+",n=Math.abs(e),a=Math.trunc(n/60),o=n%60;return 0===o?r+String(a):r+String(a)+t+q(o,2)}function z(e,t){return e%60==0?(e>0?"-":"+")+q(Math.abs(e)/60,2):V(e,t)}function V(e,t=""){let r=Math.abs(e);return(e>0?"-":"+")+q(Math.trunc(r/60),2)+t+q(r%60,2)}let $=(e,t)=>{switch(e){case"P":return t.date({width:"short"});case"PP":return t.date({width:"medium"});case"PPP":return t.date({width:"long"});default:return t.date({width:"full"})}},K=(e,t)=>{switch(e){case"p":return t.time({width:"short"});case"pp":return t.time({width:"medium"});case"ppp":return t.time({width:"long"});default:return t.time({width:"full"})}},X={p:K,P:(e,t)=>{let r,n=e.match(/(P+)(p+)?/)||[],a=n[1],o=n[2];if(!o)return $(e,t);switch(a){case"P":r=t.dateTime({width:"short"});break;case"PP":r=t.dateTime({width:"medium"});break;case"PPP":r=t.dateTime({width:"long"});break;default:r=t.dateTime({width:"full"})}return r.replace("{{date}}",$(a,t)).replace("{{time}}",K(o,t))}},Z=/^D+$/,U=/^Y+$/,J=["D","DD","YY","YYYY"];function ee(e){return e instanceof Date||"object"==typeof e&&"[object Date]"===Object.prototype.toString.call(e)}let et=/[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g,er=/P+p+|P+|p+|''|'(''|[^'])+('|$)|./g,en=/^'([^]*?)'?$/,ea=/''/g,eo=/[a-zA-Z]/;function el(e,t,r){let n=r?.locale??L.locale??j,a=r?.firstWeekContainsDate??r?.locale?.options?.firstWeekContainsDate??L.firstWeekContainsDate??L.locale?.options?.firstWeekContainsDate??1,o=r?.weekStartsOn??r?.locale?.options?.weekStartsOn??L.weekStartsOn??L.locale?.options?.weekStartsOn??0,l=(0,m.toDate)(e);if(!((ee(l)||"number"==typeof l)&&!isNaN(Number((0,m.toDate)(l)))))throw RangeError("Invalid time value");let s=t.match(er).map(e=>{let t=e[0];return"p"===t||"P"===t?(0,X[t])(e,n.formatLong):e}).join("").match(et).map(e=>{if("''"===e)return{isToken:!1,value:"'"};let t=e[0];if("'"===t){var r;let t;return{isToken:!1,value:(t=(r=e).match(en))?t[1].replace(ea,"'"):r}}if(Q[t])return{isToken:!0,value:e};if(t.match(eo))throw RangeError("Format string contains an unescaped latin alphabet character `"+t+"`");return{isToken:!1,value:e}});n.localize.preprocessor&&(s=n.localize.preprocessor(l,s));let i={firstWeekContainsDate:a,weekStartsOn:o,locale:n};return s.map(a=>{if(!a.isToken)return a.value;let o=a.value;return(!r?.useAdditionalWeekYearTokens&&U.test(o)||!r?.useAdditionalDayOfYearTokens&&Z.test(o))&&function(e,t,r){var n,a,o;let l,s=(n=e,a=t,o=r,l="Y"===n[0]?"years":"days of the month",`Use \`${n.toLowerCase()}\` instead of \`${n}\` (in \`${a}\`) for formatting ${l} to the input \`${o}\`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md`);if(console.warn(s),J.includes(e))throw RangeError(s)}(o,t,String(e)),(0,Q[o[0]])(l,o,n.localize,i)}).join("")}let es=(0,e.i(673706).makeClassName)("DateRangePicker"),ei=[{value:"tdy",text:"Today",from:h()},{value:"w",text:"Last 7 days",from:k(h(),{days:7})},{value:"t",text:"Last 30 days",from:k(h(),{days:30})},{value:"m",text:"Month to Date",from:p(h())},{value:"y",text:"Year to Date",from:M(h())}];function eu(e){let t=(0,m.toDate)(e),r=t.getMonth();return t.setFullYear(t.getFullYear(),r+1,0),t.setHours(23,59,59,999),t}function ed(e,t){let r,n,a,o,l=(0,m.toDate)(e),s=l.getFullYear(),i=l.getDate(),u=(0,x.constructFrom)(e,0);u.setFullYear(s,t,15),u.setHours(0,0,0,0);let d=(n=(r=(0,m.toDate)(u)).getFullYear(),a=r.getMonth(),(o=(0,x.constructFrom)(u,0)).setFullYear(n,a+1,0),o.setHours(0,0,0,0),o.getDate());return l.setMonth(t,Math.min(i,d)),l}function ec(e,t){let r=(0,m.toDate)(e);return isNaN(+r)?(0,x.constructFrom)(e,NaN):(r.setFullYear(t),r)}function em(e,t){let r=(0,m.toDate)(e),n=(0,m.toDate)(t);return 12*(r.getFullYear()-n.getFullYear())+(r.getMonth()-n.getMonth())}function ef(e,t){let r=(0,m.toDate)(e),n=(0,m.toDate)(t);return r.getFullYear()===n.getFullYear()&&r.getMonth()===n.getMonth()}function eh(e,t){return+(0,m.toDate)(e)<+(0,m.toDate)(t)}function ep(e,t){return+f(e)==+f(t)}function eb(e,t){let r=(0,m.toDate)(e),n=(0,m.toDate)(t);return r.getTime()>n.getTime()}function ev(e,t){return(0,g.addDays)(e,7*t)}function eg(e,t){return(0,y.addMonths)(e,12*t)}function ew(e,t){let r=t?.weekStartsOn??t?.locale?.options?.weekStartsOn??L.weekStartsOn??L.locale?.options?.weekStartsOn??0,n=(0,m.toDate)(e),a=n.getDay();return n.setDate(n.getDate()+((a0,a=n?t:1-t;if(a<=50)r=e||100;else{let t=a+50;r=e+100*Math.trunc(t/100)-100*(e>=t%100)}return n?r:1-r}function e1(e){return e%400==0||e%4==0&&e%100!=0}let e2=[31,28,31,30,31,30,31,31,30,31,30,31],e4=[31,29,31,30,31,30,31,31,30,31,30,31];function e3(e,t,r){let n=r?.weekStartsOn??r?.locale?.options?.weekStartsOn??L.weekStartsOn??L.locale?.options?.weekStartsOn??0,a=(0,m.toDate)(e),o=a.getDay(),l=7-n,s=t<0||t>6?t-(o+l)%7:((t%7+7)%7+l)%7-(o+l)%7;return(0,g.addDays)(a,s)}new class extends eM{priority=140;parse(e,t,r){switch(t){case"G":case"GG":case"GGG":return r.era(e,{width:"abbreviated"})||r.era(e,{width:"narrow"});case"GGGGG":return r.era(e,{width:"narrow"});default:return r.era(e,{width:"wide"})||r.era(e,{width:"abbreviated"})||r.era(e,{width:"narrow"})}}set(e,t,r){return t.era=r,e.setFullYear(r,0,1),e.setHours(0,0,0,0),e}incompatibleTokens=["R","u","t","T"]},new class extends eM{priority=130;incompatibleTokens=["Y","R","u","w","I","i","e","c","t","T"];parse(e,t,r){let n=e=>({year:e,isTwoDigitYear:"yy"===t});switch(t){case"y":return e$(eZ(4,e),n);case"yo":return e$(r.ordinalNumber(e,{unit:"year"}),n);default:return e$(eZ(t.length,e),n)}}validate(e,t){return t.isTwoDigitYear||t.year>0}set(e,t,r){let n=e.getFullYear();if(r.isTwoDigitYear){let t=e0(r.year,n);return e.setFullYear(t,0,1),e.setHours(0,0,0,0),e}let a="era"in t&&1!==t.era?1-r.year:r.year;return e.setFullYear(a,0,1),e.setHours(0,0,0,0),e}},new class extends eM{priority=130;parse(e,t,r){let n=e=>({year:e,isTwoDigitYear:"YY"===t});switch(t){case"Y":return e$(eZ(4,e),n);case"Yo":return e$(r.ordinalNumber(e,{unit:"year"}),n);default:return e$(eZ(t.length,e),n)}}validate(e,t){return t.isTwoDigitYear||t.year>0}set(e,t,r,n){let a=R(e,n);if(r.isTwoDigitYear){let t=e0(r.year,a);return e.setFullYear(t,0,n.firstWeekContainsDate),e.setHours(0,0,0,0),I(e,n)}let o="era"in t&&1!==t.era?1-r.year:r.year;return e.setFullYear(o,0,n.firstWeekContainsDate),e.setHours(0,0,0,0),I(e,n)}incompatibleTokens=["y","R","u","Q","q","M","L","I","d","D","i","t","T"]},new class extends eM{priority=130;parse(e,t){return"R"===t?eU(4,e):eU(t.length,e)}set(e,t,r){let n=(0,x.constructFrom)(e,0);return n.setFullYear(r,0,4),n.setHours(0,0,0,0),Y(n)}incompatibleTokens=["G","y","Y","u","Q","q","M","L","w","d","D","e","c","t","T"]},new class extends eM{priority=130;parse(e,t){return"u"===t?eU(4,e):eU(t.length,e)}set(e,t,r){return e.setFullYear(r,0,1),e.setHours(0,0,0,0),e}incompatibleTokens=["G","y","Y","R","w","I","i","e","c","t","T"]},new class extends eM{priority=120;parse(e,t,r){switch(t){case"Q":case"QQ":return eZ(t.length,e);case"Qo":return r.ordinalNumber(e,{unit:"quarter"});case"QQQ":return r.quarter(e,{width:"abbreviated",context:"formatting"})||r.quarter(e,{width:"narrow",context:"formatting"});case"QQQQQ":return r.quarter(e,{width:"narrow",context:"formatting"});default:return r.quarter(e,{width:"wide",context:"formatting"})||r.quarter(e,{width:"abbreviated",context:"formatting"})||r.quarter(e,{width:"narrow",context:"formatting"})}}validate(e,t){return t>=1&&t<=4}set(e,t,r){return e.setMonth((r-1)*3,1),e.setHours(0,0,0,0),e}incompatibleTokens=["Y","R","q","M","L","w","I","d","D","i","e","c","t","T"]},new class extends eM{priority=120;parse(e,t,r){switch(t){case"q":case"qq":return eZ(t.length,e);case"qo":return r.ordinalNumber(e,{unit:"quarter"});case"qqq":return r.quarter(e,{width:"abbreviated",context:"standalone"})||r.quarter(e,{width:"narrow",context:"standalone"});case"qqqqq":return r.quarter(e,{width:"narrow",context:"standalone"});default:return r.quarter(e,{width:"wide",context:"standalone"})||r.quarter(e,{width:"abbreviated",context:"standalone"})||r.quarter(e,{width:"narrow",context:"standalone"})}}validate(e,t){return t>=1&&t<=4}set(e,t,r){return e.setMonth((r-1)*3,1),e.setHours(0,0,0,0),e}incompatibleTokens=["Y","R","Q","M","L","w","I","d","D","i","e","c","t","T"]},new class extends eM{incompatibleTokens=["Y","R","q","Q","L","w","I","D","i","e","c","t","T"];priority=110;parse(e,t,r){let n=e=>e-1;switch(t){case"M":return e$(eK(eD,e),n);case"MM":return e$(eZ(2,e),n);case"Mo":return e$(r.ordinalNumber(e,{unit:"month"}),n);case"MMM":return r.month(e,{width:"abbreviated",context:"formatting"})||r.month(e,{width:"narrow",context:"formatting"});case"MMMMM":return r.month(e,{width:"narrow",context:"formatting"});default:return r.month(e,{width:"wide",context:"formatting"})||r.month(e,{width:"abbreviated",context:"formatting"})||r.month(e,{width:"narrow",context:"formatting"})}}validate(e,t){return t>=0&&t<=11}set(e,t,r){return e.setMonth(r,1),e.setHours(0,0,0,0),e}},new class extends eM{priority=110;parse(e,t,r){let n=e=>e-1;switch(t){case"L":return e$(eK(eD,e),n);case"LL":return e$(eZ(2,e),n);case"Lo":return e$(r.ordinalNumber(e,{unit:"month"}),n);case"LLL":return r.month(e,{width:"abbreviated",context:"standalone"})||r.month(e,{width:"narrow",context:"standalone"});case"LLLLL":return r.month(e,{width:"narrow",context:"standalone"});default:return r.month(e,{width:"wide",context:"standalone"})||r.month(e,{width:"abbreviated",context:"standalone"})||r.month(e,{width:"narrow",context:"standalone"})}}validate(e,t){return t>=0&&t<=11}set(e,t,r){return e.setMonth(r,1),e.setHours(0,0,0,0),e}incompatibleTokens=["Y","R","q","Q","M","w","I","D","i","e","c","t","T"]},new class extends eM{priority=100;parse(e,t,r){switch(t){case"w":return eK(eS,e);case"wo":return r.ordinalNumber(e,{unit:"week"});default:return eZ(t.length,e)}}validate(e,t){return t>=1&&t<=53}set(e,t,r,n){let a,o;return I((o=B(a=(0,m.toDate)(e),n)-r,a.setDate(a.getDate()-7*o),a),n)}incompatibleTokens=["y","R","u","q","Q","M","L","I","d","D","i","t","T"]},new class extends eM{priority=100;parse(e,t,r){switch(t){case"I":return eK(eS,e);case"Io":return r.ordinalNumber(e,{unit:"week"});default:return eZ(t.length,e)}}validate(e,t){return t>=1&&t<=53}set(e,t,r){let n,a;return Y((a=H(n=(0,m.toDate)(e))-r,n.setDate(n.getDate()-7*a),n))}incompatibleTokens=["y","Y","u","q","Q","M","L","w","d","D","e","c","t","T"]},new class extends eM{priority=90;subPriority=1;parse(e,t,r){switch(t){case"d":return eK(eN,e);case"do":return r.ordinalNumber(e,{unit:"date"});default:return eZ(t.length,e)}}validate(e,t){let r=e1(e.getFullYear()),n=e.getMonth();return r?t>=1&&t<=e4[n]:t>=1&&t<=e2[n]}set(e,t,r){return e.setDate(r),e.setHours(0,0,0,0),e}incompatibleTokens=["Y","R","q","Q","w","I","D","i","e","c","t","T"]},new class extends eM{priority=90;subpriority=1;parse(e,t,r){switch(t){case"D":case"DD":return eK(eE,e);case"Do":return r.ordinalNumber(e,{unit:"date"});default:return eZ(t.length,e)}}validate(e,t){return e1(e.getFullYear())?t>=1&&t<=366:t>=1&&t<=365}set(e,t,r){return e.setMonth(0,r),e.setHours(0,0,0,0),e}incompatibleTokens=["Y","R","q","Q","M","L","w","I","d","E","i","e","c","t","T"]},new class extends eM{priority=90;parse(e,t,r){switch(t){case"E":case"EE":case"EEE":return r.day(e,{width:"abbreviated",context:"formatting"})||r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"});case"EEEEE":return r.day(e,{width:"narrow",context:"formatting"});case"EEEEEE":return r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"});default:return r.day(e,{width:"wide",context:"formatting"})||r.day(e,{width:"abbreviated",context:"formatting"})||r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"})}}validate(e,t){return t>=0&&t<=6}set(e,t,r,n){return(e=e3(e,r,n)).setHours(0,0,0,0),e}incompatibleTokens=["D","i","e","c","t","T"]},new class extends eM{priority=90;parse(e,t,r,n){let a=e=>{let t=7*Math.floor((e-1)/7);return(e+n.weekStartsOn+6)%7+t};switch(t){case"e":case"ee":return e$(eZ(t.length,e),a);case"eo":return e$(r.ordinalNumber(e,{unit:"day"}),a);case"eee":return r.day(e,{width:"abbreviated",context:"formatting"})||r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"});case"eeeee":return r.day(e,{width:"narrow",context:"formatting"});case"eeeeee":return r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"});default:return r.day(e,{width:"wide",context:"formatting"})||r.day(e,{width:"abbreviated",context:"formatting"})||r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"})}}validate(e,t){return t>=0&&t<=6}set(e,t,r,n){return(e=e3(e,r,n)).setHours(0,0,0,0),e}incompatibleTokens=["y","R","u","q","Q","M","L","I","d","D","E","i","c","t","T"]},new class extends eM{priority=90;parse(e,t,r,n){let a=e=>{let t=7*Math.floor((e-1)/7);return(e+n.weekStartsOn+6)%7+t};switch(t){case"c":case"cc":return e$(eZ(t.length,e),a);case"co":return e$(r.ordinalNumber(e,{unit:"day"}),a);case"ccc":return r.day(e,{width:"abbreviated",context:"standalone"})||r.day(e,{width:"short",context:"standalone"})||r.day(e,{width:"narrow",context:"standalone"});case"ccccc":return r.day(e,{width:"narrow",context:"standalone"});case"cccccc":return r.day(e,{width:"short",context:"standalone"})||r.day(e,{width:"narrow",context:"standalone"});default:return r.day(e,{width:"wide",context:"standalone"})||r.day(e,{width:"abbreviated",context:"standalone"})||r.day(e,{width:"short",context:"standalone"})||r.day(e,{width:"narrow",context:"standalone"})}}validate(e,t){return t>=0&&t<=6}set(e,t,r,n){return(e=e3(e,r,n)).setHours(0,0,0,0),e}incompatibleTokens=["y","R","u","q","Q","M","L","I","d","D","E","i","e","t","T"]},new class extends eM{priority=90;parse(e,t,r){let n=e=>0===e?7:e;switch(t){case"i":case"ii":return eZ(t.length,e);case"io":return r.ordinalNumber(e,{unit:"day"});case"iii":return e$(r.day(e,{width:"abbreviated",context:"formatting"})||r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"}),n);case"iiiii":return e$(r.day(e,{width:"narrow",context:"formatting"}),n);case"iiiiii":return e$(r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"}),n);default:return e$(r.day(e,{width:"wide",context:"formatting"})||r.day(e,{width:"abbreviated",context:"formatting"})||r.day(e,{width:"short",context:"formatting"})||r.day(e,{width:"narrow",context:"formatting"}),n)}}validate(e,t){return t>=1&&t<=7}set(e,t,r){var n;let a,o,l;return n=e,a=(0,m.toDate)(n),0===(o=(0,m.toDate)(a).getDay())&&(o=7),l=o,(e=(0,g.addDays)(a,r-l)).setHours(0,0,0,0),e}incompatibleTokens=["y","Y","u","q","Q","M","L","w","d","D","E","e","c","t","T"]},new class extends eM{priority=80;parse(e,t,r){switch(t){case"a":case"aa":case"aaa":return r.dayPeriod(e,{width:"abbreviated",context:"formatting"})||r.dayPeriod(e,{width:"narrow",context:"formatting"});case"aaaaa":return r.dayPeriod(e,{width:"narrow",context:"formatting"});default:return r.dayPeriod(e,{width:"wide",context:"formatting"})||r.dayPeriod(e,{width:"abbreviated",context:"formatting"})||r.dayPeriod(e,{width:"narrow",context:"formatting"})}}set(e,t,r){return e.setHours(eJ(r),0,0,0),e}incompatibleTokens=["b","B","H","k","t","T"]},new class extends eM{priority=80;parse(e,t,r){switch(t){case"b":case"bb":case"bbb":return r.dayPeriod(e,{width:"abbreviated",context:"formatting"})||r.dayPeriod(e,{width:"narrow",context:"formatting"});case"bbbbb":return r.dayPeriod(e,{width:"narrow",context:"formatting"});default:return r.dayPeriod(e,{width:"wide",context:"formatting"})||r.dayPeriod(e,{width:"abbreviated",context:"formatting"})||r.dayPeriod(e,{width:"narrow",context:"formatting"})}}set(e,t,r){return e.setHours(eJ(r),0,0,0),e}incompatibleTokens=["a","B","H","k","t","T"]},new class extends eM{priority=80;parse(e,t,r){switch(t){case"B":case"BB":case"BBB":return r.dayPeriod(e,{width:"abbreviated",context:"formatting"})||r.dayPeriod(e,{width:"narrow",context:"formatting"});case"BBBBB":return r.dayPeriod(e,{width:"narrow",context:"formatting"});default:return r.dayPeriod(e,{width:"wide",context:"formatting"})||r.dayPeriod(e,{width:"abbreviated",context:"formatting"})||r.dayPeriod(e,{width:"narrow",context:"formatting"})}}set(e,t,r){return e.setHours(eJ(r),0,0,0),e}incompatibleTokens=["a","b","t","T"]},new class extends eM{priority=70;parse(e,t,r){switch(t){case"h":return eK(e_,e);case"ho":return r.ordinalNumber(e,{unit:"hour"});default:return eZ(t.length,e)}}validate(e,t){return t>=1&&t<=12}set(e,t,r){let n=e.getHours()>=12;return n&&r<12?e.setHours(r+12,0,0,0):n||12!==r?e.setHours(r,0,0,0):e.setHours(0,0,0,0),e}incompatibleTokens=["H","K","k","t","T"]},new class extends eM{priority=70;parse(e,t,r){switch(t){case"H":return eK(eP,e);case"Ho":return r.ordinalNumber(e,{unit:"hour"});default:return eZ(t.length,e)}}validate(e,t){return t>=0&&t<=23}set(e,t,r){return e.setHours(r,0,0,0),e}incompatibleTokens=["a","b","h","K","k","t","T"]},new class extends eM{priority=70;parse(e,t,r){switch(t){case"K":return eK(eC,e);case"Ko":return r.ordinalNumber(e,{unit:"hour"});default:return eZ(t.length,e)}}validate(e,t){return t>=0&&t<=11}set(e,t,r){return e.getHours()>=12&&r<12?e.setHours(r+12,0,0,0):e.setHours(r,0,0,0),e}incompatibleTokens=["h","H","k","t","T"]},new class extends eM{priority=70;parse(e,t,r){switch(t){case"k":return eK(eT,e);case"ko":return r.ordinalNumber(e,{unit:"hour"});default:return eZ(t.length,e)}}validate(e,t){return t>=1&&t<=24}set(e,t,r){return e.setHours(r<=24?r%24:r,0,0,0),e}incompatibleTokens=["a","b","h","H","K","t","T"]},new class extends eM{priority=60;parse(e,t,r){switch(t){case"m":return eK(ej,e);case"mo":return r.ordinalNumber(e,{unit:"minute"});default:return eZ(t.length,e)}}validate(e,t){return t>=0&&t<=59}set(e,t,r){return e.setMinutes(r,0,0),e}incompatibleTokens=["t","T"]},new class extends eM{priority=50;parse(e,t,r){switch(t){case"s":return eK(eL,e);case"so":return r.ordinalNumber(e,{unit:"second"});default:return eZ(t.length,e)}}validate(e,t){return t>=0&&t<=59}set(e,t,r){return e.setSeconds(r,0),e}incompatibleTokens=["t","T"]},new class extends eM{priority=30;parse(e,t){return e$(eZ(t.length,e),e=>Math.trunc(e*Math.pow(10,-t.length+3)))}set(e,t,r){return e.setMilliseconds(r),e}incompatibleTokens=["t","T"]},new class extends eM{priority=10;parse(e,t){switch(t){case"X":return eX(eA,e);case"XX":return eX(eQ,e);case"XXXX":return eX(eG,e);case"XXXXX":return eX(eV,e);default:return eX(ez,e)}}set(e,t,r){return t.timestampIsSet?e:(0,x.constructFrom)(e,e.getTime()-F(e)-r)}incompatibleTokens=["t","T","x"]},new class extends eM{priority=10;parse(e,t){switch(t){case"x":return eX(eA,e);case"xx":return eX(eQ,e);case"xxxx":return eX(eG,e);case"xxxxx":return eX(eV,e);default:return eX(ez,e)}}set(e,t,r){return t.timestampIsSet?e:(0,x.constructFrom)(e,e.getTime()-F(e)-r)}incompatibleTokens=["t","T","X"]},new class extends eM{priority=40;parse(e){return eK(eW,e)}set(e,t,r){return[(0,x.constructFrom)(e,1e3*r),{timestampIsSet:!0}]}incompatibleTokens="*"},new class extends eM{priority=20;parse(e){return eK(eW,e)}set(e,t,r){return[(0,x.constructFrom)(e,r),{timestampIsSet:!0}]}incompatibleTokens="*"};var e5=function(){return(e5=Object.assign||function(e){for(var t,r=1,n=arguments.length;rem(u,l)&&(l=(0,y.addMonths)(u,-1*((void 0===c?1:c)-1))),d&&0>em(l,d)&&(l=d),m=p(l),f=t.month,b=(h=(0,i.useState)(m))[0],v=[void 0===f?b:f,h[1]])[0],w=v[1],[g,function(e){if(!t.disableNavigation){var r,n=p(e);w(n),null==(r=t.onMonthChange)||r.call(t,n)}}]),M=k[0],D=k[1],N=function(e,t){for(var r=t.reverseMonths,n=t.numberOfMonths,a=p(e),o=em(p((0,y.addMonths)(a,n)),a),l=[],s=0;s=em(o,r)))return(0,y.addMonths)(o,-(n?void 0===a?1:a:1))}}(M,x),P=function(e){return N.some(function(t){return ef(e,t)})};return(0,s.jsx)(tc.Provider,{value:{currentMonth:M,displayMonths:N,goToMonth:D,goToDate:function(e,t){P(e)||(t&&eh(e,t)?D((0,y.addMonths)(e,1+-1*x.numberOfMonths)):D(e))},previousMonth:S,nextMonth:E,isDateDisplayed:P},children:e.children})}function tf(){var e=(0,i.useContext)(tc);if(!e)throw Error("useNavigation must be used within a NavigationProvider");return e}function th(e){var t,r=to(),n=r.classNames,a=r.styles,o=r.components,l=tf().goToMonth,i=function(t){l((0,y.addMonths)(t,e.displayIndex?-e.displayIndex:0))},u=null!=(t=null==o?void 0:o.CaptionLabel)?t:tl,d=(0,s.jsx)(u,{id:e.id,displayMonth:e.displayMonth});return(0,s.jsxs)("div",{className:n.caption_dropdowns,style:a.caption_dropdowns,children:[(0,s.jsx)("div",{className:n.vhidden,children:d}),(0,s.jsx)(tu,{onChange:i,displayMonth:e.displayMonth}),(0,s.jsx)(td,{onChange:i,displayMonth:e.displayMonth})]})}function tp(e){return(0,s.jsx)("svg",e5({width:"16px",height:"16px",viewBox:"0 0 120 120"},e,{children:(0,s.jsx)("path",{d:"M69.490332,3.34314575 C72.6145263,0.218951416 77.6798462,0.218951416 80.8040405,3.34314575 C83.8617626,6.40086786 83.9268205,11.3179931 80.9992143,14.4548388 L80.8040405,14.6568542 L35.461,60 L80.8040405,105.343146 C83.8617626,108.400868 83.9268205,113.317993 80.9992143,116.454839 L80.8040405,116.656854 C77.7463184,119.714576 72.8291931,119.779634 69.6923475,116.852028 L69.490332,116.656854 L18.490332,65.6568542 C15.4326099,62.5991321 15.367552,57.6820069 18.2951583,54.5451612 L18.490332,54.3431458 L69.490332,3.34314575 Z",fill:"currentColor",fillRule:"nonzero"})}))}function tb(e){return(0,s.jsx)("svg",e5({width:"16px",height:"16px",viewBox:"0 0 120 120"},e,{children:(0,s.jsx)("path",{d:"M49.8040405,3.34314575 C46.6798462,0.218951416 41.6145263,0.218951416 38.490332,3.34314575 C35.4326099,6.40086786 35.367552,11.3179931 38.2951583,14.4548388 L38.490332,14.6568542 L83.8333725,60 L38.490332,105.343146 C35.4326099,108.400868 35.367552,113.317993 38.2951583,116.454839 L38.490332,116.656854 C41.5480541,119.714576 46.4651794,119.779634 49.602025,116.852028 L49.8040405,116.656854 L100.804041,65.6568542 C103.861763,62.5991321 103.926821,57.6820069 100.999214,54.5451612 L100.804041,54.3431458 L49.8040405,3.34314575 Z",fill:"currentColor"})}))}var tv=(0,i.forwardRef)(function(e,t){var r=to(),n=r.classNames,a=r.styles,o=[n.button_reset,n.button];e.className&&o.push(e.className);var l=o.join(" "),i=e5(e5({},a.button_reset),a.button);return e.style&&Object.assign(i,e.style),(0,s.jsx)("button",e5({},e,{ref:t,type:"button",className:l,style:i}))});function tg(e){var t,r,n=to(),a=n.dir,o=n.locale,l=n.classNames,i=n.styles,u=n.labels,d=u.labelPrevious,c=u.labelNext,m=n.components;if(!e.nextMonth&&!e.previousMonth)return(0,s.jsx)(s.Fragment,{});var f=d(e.previousMonth,{locale:o}),h=[l.nav_button,l.nav_button_previous].join(" "),p=c(e.nextMonth,{locale:o}),b=[l.nav_button,l.nav_button_next].join(" "),v=null!=(t=null==m?void 0:m.IconRight)?t:tb,g=null!=(r=null==m?void 0:m.IconLeft)?r:tp;return(0,s.jsxs)("div",{className:l.nav,style:i.nav,children:[!e.hidePrevious&&(0,s.jsx)(tv,{name:"previous-month","aria-label":f,className:h,style:i.nav_button_previous,disabled:!e.previousMonth,onClick:e.onPreviousClick,children:"rtl"===a?(0,s.jsx)(v,{className:l.nav_icon,style:i.nav_icon}):(0,s.jsx)(g,{className:l.nav_icon,style:i.nav_icon})}),!e.hideNext&&(0,s.jsx)(tv,{name:"next-month","aria-label":p,className:b,style:i.nav_button_next,disabled:!e.nextMonth,onClick:e.onNextClick,children:"rtl"===a?(0,s.jsx)(g,{className:l.nav_icon,style:i.nav_icon}):(0,s.jsx)(v,{className:l.nav_icon,style:i.nav_icon})})]})}function tw(e){var t=to().numberOfMonths,r=tf(),n=r.previousMonth,a=r.nextMonth,o=r.goToMonth,l=r.displayMonths,i=l.findIndex(function(t){return ef(e.displayMonth,t)}),u=0===i,d=i===l.length-1;return(0,s.jsx)(tg,{displayMonth:e.displayMonth,hideNext:t>1&&(u||!d),hidePrevious:t>1&&(d||!u),nextMonth:a,previousMonth:n,onPreviousClick:function(){n&&o(n)},onNextClick:function(){a&&o(a)}})}function ty(e){var t,r,n=to(),a=n.classNames,o=n.disableNavigation,l=n.styles,i=n.captionLayout,u=n.components,d=null!=(t=null==u?void 0:u.CaptionLabel)?t:tl;return r=o?(0,s.jsx)(d,{id:e.id,displayMonth:e.displayMonth}):"dropdown"===i?(0,s.jsx)(th,{displayMonth:e.displayMonth,id:e.id}):"dropdown-buttons"===i?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(th,{displayMonth:e.displayMonth,displayIndex:e.displayIndex,id:e.id}),(0,s.jsx)(tw,{displayMonth:e.displayMonth,displayIndex:e.displayIndex,id:e.id})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(d,{id:e.id,displayMonth:e.displayMonth,displayIndex:e.displayIndex}),(0,s.jsx)(tw,{displayMonth:e.displayMonth,id:e.id})]}),(0,s.jsx)("div",{className:a.caption,style:l.caption,children:r})}function tx(e){var t=to(),r=t.footer,n=t.styles,a=t.classNames.tfoot;return r?(0,s.jsx)("tfoot",{className:a,style:n.tfoot,children:(0,s.jsx)("tr",{children:(0,s.jsx)("td",{colSpan:8,children:r})})}):(0,s.jsx)(s.Fragment,{})}function tk(){var e=to(),t=e.classNames,r=e.styles,n=e.showWeekNumber,a=e.locale,o=e.weekStartsOn,l=e.ISOWeek,i=e.formatters.formatWeekdayName,u=e.labels.labelWeekday,d=function(e,t,r){for(var n=r?Y(new Date):I(new Date,{locale:e,weekStartsOn:t}),a=[],o=0;o<7;o++){var l=(0,g.addDays)(n,o);a.push(l)}return a}(a,o,l);return(0,s.jsxs)("tr",{style:r.head_row,className:t.head_row,children:[n&&(0,s.jsx)("td",{style:r.head_cell,className:t.head_cell}),d.map(function(e,n){return(0,s.jsx)("th",{scope:"col",className:t.head_cell,style:r.head_cell,"aria-label":u(e,{locale:a}),children:i(e,{locale:a})},n)})]})}function tM(){var e,t=to(),r=t.classNames,n=t.styles,a=t.components,o=null!=(e=null==a?void 0:a.HeadRow)?e:tk;return(0,s.jsx)("thead",{style:n.head,className:r.head,children:(0,s.jsx)(o,{})})}function tD(e){var t=to(),r=t.locale,n=t.formatters.formatDay;return(0,s.jsx)(s.Fragment,{children:n(e.date,{locale:r})})}var tN=(0,i.createContext)(void 0);function tE(e){return e7(e.initialProps)?(0,s.jsx)(tS,{initialProps:e.initialProps,children:e.children}):(0,s.jsx)(tN.Provider,{value:{selected:void 0,modifiers:{disabled:[]}},children:e.children})}function tS(e){var t=e.initialProps,r=e.children,n=t.selected,a=t.min,o=t.max,l={disabled:[]};return n&&l.disabled.push(function(e){var t=o&&n.length>o-1,r=n.some(function(t){return ep(t,e)});return!!(t&&!r)}),(0,s.jsx)(tN.Provider,{value:{selected:n,onDayClick:function(e,r,l){var s,i;if((null==(s=t.onDayClick)||s.call(t,e,r,l),!r.selected||!a||(null==n?void 0:n.length)!==a)&&!(!r.selected&&o&&(null==n?void 0:n.length)===o)){var u=n?e6([],n,!0):[];if(r.selected){var d=u.findIndex(function(t){return ep(e,t)});u.splice(d,1)}else u.push(e);null==(i=t.onSelect)||i.call(t,u,e,r,l)}},modifiers:l},children:r})}function tP(){var e=(0,i.useContext)(tN);if(!e)throw Error("useSelectMultiple must be used within a SelectMultipleProvider");return e}var tT=(0,i.createContext)(void 0);function tC(e){return e8(e.initialProps)?(0,s.jsx)(t_,{initialProps:e.initialProps,children:e.children}):(0,s.jsx)(tT.Provider,{value:{selected:void 0,modifiers:{range_start:[],range_end:[],range_middle:[],disabled:[]}},children:e.children})}function t_(e){var t=e.initialProps,r=e.children,n=t.selected,a=n||{},o=a.from,l=a.to,i=t.min,u=t.max,d={range_start:[],range_end:[],range_middle:[],disabled:[]};if(o?(d.range_start=[o],l?(d.range_end=[l],ep(o,l)||(d.range_middle=[{after:o,before:l}])):d.range_end=[o]):l&&(d.range_start=[l],d.range_end=[l]),i&&(o&&!l&&d.disabled.push({after:w(o,i-1),before:(0,g.addDays)(o,i-1)}),o&&l&&d.disabled.push({after:o,before:(0,g.addDays)(o,i-1)}),!o&&l&&d.disabled.push({after:w(l,i-1),before:(0,g.addDays)(l,i-1)})),u){if(o&&!l&&(d.disabled.push({before:(0,g.addDays)(o,-u+1)}),d.disabled.push({after:(0,g.addDays)(o,u-1)})),o&&l){var c=u-(O(l,o)+1);d.disabled.push({before:w(o,c)}),d.disabled.push({after:(0,g.addDays)(l,c)})}!o&&l&&(d.disabled.push({before:(0,g.addDays)(l,-u+1)}),d.disabled.push({after:(0,g.addDays)(l,u-1)}))}return(0,s.jsx)(tT.Provider,{value:{selected:n,onDayClick:function(e,r,a){null==(u=t.onDayClick)||u.call(t,e,r,a);var o,l,s,i,u,d,c=(o=e,s=(l=n||{}).from,i=l.to,s&&i?ep(i,o)&&ep(s,o)?void 0:ep(i,o)?{from:i,to:void 0}:ep(s,o)?void 0:eb(s,o)?{from:o,to:i}:{from:s,to:o}:i?eb(o,i)?{from:i,to:o}:{from:o,to:i}:s?eh(o,s)?{from:o,to:s}:{from:s,to:o}:{from:o,to:void 0});null==(d=t.onSelect)||d.call(t,c,e,r,a)},modifiers:d},children:r})}function tj(){var e=(0,i.useContext)(tT);if(!e)throw Error("useSelectRange must be used within a SelectRangeProvider");return e}function tL(e){return Array.isArray(e)?e6([],e,!0):void 0!==e?[e]:[]}(o=l||(l={})).Outside="outside",o.Disabled="disabled",o.Selected="selected",o.Hidden="hidden",o.Today="today",o.RangeStart="range_start",o.RangeEnd="range_end",o.RangeMiddle="range_middle";var tF=l.Selected,tO=l.Disabled,tI=l.Hidden,tY=l.Today,tW=l.RangeEnd,tH=l.RangeMiddle,tR=l.RangeStart,tB=l.Outside,tq=(0,i.createContext)(void 0);function tA(e){var t,r,n,a,o=to(),l=tP(),i=tj(),u=((t={})[tF]=tL(o.selected),t[tO]=tL(o.disabled),t[tI]=tL(o.hidden),t[tY]=[o.today],t[tW]=[],t[tH]=[],t[tR]=[],t[tB]=[],r=t,o.fromDate&&r[tO].push({before:o.fromDate}),o.toDate&&r[tO].push({after:o.toDate}),e7(o)?r[tO]=r[tO].concat(l.modifiers[tO]):e8(o)&&(r[tO]=r[tO].concat(i.modifiers[tO]),r[tR]=i.modifiers[tR],r[tH]=i.modifiers[tH],r[tW]=i.modifiers[tW]),r),d=(n=o.modifiers,a={},Object.entries(n).forEach(function(e){var t=e[0],r=e[1];a[t]=tL(r)}),a),c=e5(e5({},u),d);return(0,s.jsx)(tq.Provider,{value:c,children:e.children})}function tQ(){var e=(0,i.useContext)(tq);if(!e)throw Error("useModifiers must be used within a ModifiersProvider");return e}function tG(e,t,r){var n=Object.keys(t).reduce(function(r,n){return t[n].some(function(t){if("boolean"==typeof t)return t;if(ee(t))return ep(e,t);if(Array.isArray(t)&&t.every(ee))return t.includes(e);if(t&&"object"==typeof t&&"from"in t)return n=t.from,a=t.to,n&&a?(0>O(a,n)&&(n=(r=[a,n])[0],a=r[1]),O(e,n)>=0&&O(a,e)>=0):a?ep(a,e):!!n&&ep(n,e);if(t&&"object"==typeof t&&"dayOfWeek"in t)return t.dayOfWeek.includes(e.getDay());if(t&&"object"==typeof t&&"before"in t&&"after"in t){var r,n,a,o=O(t.before,e),l=O(t.after,e),s=o>0,i=l<0;return eb(t.before,t.after)?i&&s:s||i}return t&&"object"==typeof t&&"after"in t?O(e,t.after)>0:t&&"object"==typeof t&&"before"in t?O(t.before,e)>0:"function"==typeof t&&t(e)})&&r.push(n),r},[]),a={};return n.forEach(function(e){return a[e]=!0}),r&&!ef(e,r)&&(a.outside=!0),a}var tz=(0,i.createContext)(void 0);function tV(e){var t=tf(),r=tQ(),n=(0,i.useState)(),a=n[0],o=n[1],l=(0,i.useState)(),u=l[0],d=l[1],c=function(e,t){for(var r,n,a=p(e[0]),o=eu(e[e.length-1]),l=a;l<=o;){var s=tG(l,t);if(!(!s.disabled&&!s.hidden)){l=(0,g.addDays)(l,1);continue}if(s.selected)return l;s.today&&!n&&(n=l),r||(r=l),l=(0,g.addDays)(l,1)}return n||r}(t.displayMonths,r),m=(null!=a?a:u&&t.isDateDisplayed(u))?u:c,f=function(e){o(e)},h=to(),b=function(e,n){if(a){var o=function e(t,r){var n=r.moveBy,a=r.direction,o=r.context,l=r.modifiers,s=r.retry,i=void 0===s?{count:0,lastFocused:t}:s,u=o.weekStartsOn,d=o.fromDate,c=o.toDate,m=o.locale,f=({day:g.addDays,week:ev,month:y.addMonths,year:eg,startOfWeek:function(e){return o.ISOWeek?Y(e):I(e,{locale:m,weekStartsOn:u})},endOfWeek:function(e){return o.ISOWeek?ey(e):ew(e,{locale:m,weekStartsOn:u})}})[n](t,"after"===a?1:-1);"before"===a&&d?f=D([d,f]):"after"===a&&c&&(f=N([c,f]));var h=!0;if(l){var p=tG(f,l);h=!p.disabled&&!p.hidden}return h?f:i.count>365?i.lastFocused:e(f,{moveBy:n,direction:a,context:o,modifiers:l,retry:e5(e5({},i),{count:i.count+1})})}(a,{moveBy:e,direction:n,context:h,modifiers:r});ep(a,o)||(t.goToDate(o,a),f(o))}};return(0,s.jsx)(tz.Provider,{value:{focusedDay:a,focusTarget:m,blur:function(){d(a),o(void 0)},focus:f,focusDayAfter:function(){return b("day","after")},focusDayBefore:function(){return b("day","before")},focusWeekAfter:function(){return b("week","after")},focusWeekBefore:function(){return b("week","before")},focusMonthBefore:function(){return b("month","before")},focusMonthAfter:function(){return b("month","after")},focusYearBefore:function(){return b("year","before")},focusYearAfter:function(){return b("year","after")},focusStartOfWeek:function(){return b("startOfWeek","before")},focusEndOfWeek:function(){return b("endOfWeek","after")}},children:e.children})}function t$(){var e=(0,i.useContext)(tz);if(!e)throw Error("useFocusContext must be used within a FocusProvider");return e}var tK=(0,i.createContext)(void 0);function tX(e){return e9(e.initialProps)?(0,s.jsx)(tZ,{initialProps:e.initialProps,children:e.children}):(0,s.jsx)(tK.Provider,{value:{selected:void 0},children:e.children})}function tZ(e){var t=e.initialProps,r=e.children,n={selected:t.selected,onDayClick:function(e,r,n){var a,o,l;if(null==(a=t.onDayClick)||a.call(t,e,r,n),r.selected&&!t.required){null==(o=t.onSelect)||o.call(t,void 0,e,r,n);return}null==(l=t.onSelect)||l.call(t,e,e,r,n)}};return(0,s.jsx)(tK.Provider,{value:n,children:r})}function tU(){var e=(0,i.useContext)(tK);if(!e)throw Error("useSelectSingle must be used within a SelectSingleProvider");return e}function tJ(e){var t,r,n,a,o,u,d,c,m,f,h,p,b,v,g,w,y,x,k,M,D,N,E,S,P,T,C,_,j,L,F,O,I,Y,W,H,R,B,q,A,Q,G,z=(0,i.useRef)(null),V=(t=e.date,r=e.displayMonth,u=to(),d=t$(),c=tG(t,tQ(),r),m=to(),f=tU(),h=tP(),p=tj(),v=(b=t$()).focusDayAfter,g=b.focusDayBefore,w=b.focusWeekAfter,y=b.focusWeekBefore,x=b.blur,k=b.focus,M=b.focusMonthBefore,D=b.focusMonthAfter,N=b.focusYearBefore,E=b.focusYearAfter,S=b.focusStartOfWeek,P=b.focusEndOfWeek,T={onClick:function(e){var r,n,a,o;e9(m)?null==(r=f.onDayClick)||r.call(f,t,c,e):e7(m)?null==(n=h.onDayClick)||n.call(h,t,c,e):e8(m)?null==(a=p.onDayClick)||a.call(p,t,c,e):null==(o=m.onDayClick)||o.call(m,t,c,e)},onFocus:function(e){var r;k(t),null==(r=m.onDayFocus)||r.call(m,t,c,e)},onBlur:function(e){var r;x(),null==(r=m.onDayBlur)||r.call(m,t,c,e)},onKeyDown:function(e){var r;switch(e.key){case"ArrowLeft":e.preventDefault(),e.stopPropagation(),"rtl"===m.dir?v():g();break;case"ArrowRight":e.preventDefault(),e.stopPropagation(),"rtl"===m.dir?g():v();break;case"ArrowDown":e.preventDefault(),e.stopPropagation(),w();break;case"ArrowUp":e.preventDefault(),e.stopPropagation(),y();break;case"PageUp":e.preventDefault(),e.stopPropagation(),e.shiftKey?N():M();break;case"PageDown":e.preventDefault(),e.stopPropagation(),e.shiftKey?E():D();break;case"Home":e.preventDefault(),e.stopPropagation(),S();break;case"End":e.preventDefault(),e.stopPropagation(),P()}null==(r=m.onDayKeyDown)||r.call(m,t,c,e)},onKeyUp:function(e){var r;null==(r=m.onDayKeyUp)||r.call(m,t,c,e)},onMouseEnter:function(e){var r;null==(r=m.onDayMouseEnter)||r.call(m,t,c,e)},onMouseLeave:function(e){var r;null==(r=m.onDayMouseLeave)||r.call(m,t,c,e)},onPointerEnter:function(e){var r;null==(r=m.onDayPointerEnter)||r.call(m,t,c,e)},onPointerLeave:function(e){var r;null==(r=m.onDayPointerLeave)||r.call(m,t,c,e)},onTouchCancel:function(e){var r;null==(r=m.onDayTouchCancel)||r.call(m,t,c,e)},onTouchEnd:function(e){var r;null==(r=m.onDayTouchEnd)||r.call(m,t,c,e)},onTouchMove:function(e){var r;null==(r=m.onDayTouchMove)||r.call(m,t,c,e)},onTouchStart:function(e){var r;null==(r=m.onDayTouchStart)||r.call(m,t,c,e)}},C=to(),_=tU(),j=tP(),L=tj(),F=e9(C)?_.selected:e7(C)?j.selected:e8(C)?L.selected:void 0,O=!!(u.onDayClick||"default"!==u.mode),(0,i.useEffect)(function(){var e;c.outside||!d.focusedDay||O&&ep(d.focusedDay,t)&&(null==(e=z.current)||e.focus())},[d.focusedDay,t,z,O,c.outside]),Y=(I=[u.classNames.day],Object.keys(c).forEach(function(e){var t=u.modifiersClassNames[e];if(t)I.push(t);else if(Object.values(l).includes(e)){var r=u.classNames["day_".concat(e)];r&&I.push(r)}}),I).join(" "),W=e5({},u.styles.day),Object.keys(c).forEach(function(e){var t;W=e5(e5({},W),null==(t=u.modifiersStyles)?void 0:t[e])}),H=W,R=!!(c.outside&&!u.showOutsideDays||c.hidden),B=null!=(o=null==(a=u.components)?void 0:a.DayContent)?o:tD,q={style:H,className:Y,children:(0,s.jsx)(B,{date:t,displayMonth:r,activeModifiers:c}),role:"gridcell"},A=d.focusTarget&&ep(d.focusTarget,t)&&!c.outside,Q=d.focusedDay&&ep(d.focusedDay,t),G=e5(e5(e5({},q),((n={disabled:c.disabled,role:"gridcell"})["aria-selected"]=c.selected,n.tabIndex=Q||A?0:-1,n)),T),{isButton:O,isHidden:R,activeModifiers:c,selectedDays:F,buttonProps:G,divProps:q});return V.isHidden?(0,s.jsx)("div",{role:"gridcell"}):V.isButton?(0,s.jsx)(tv,e5({name:"day",ref:z},V.buttonProps)):(0,s.jsx)("div",e5({},V.divProps))}function t0(e){var t=e.number,r=e.dates,n=to(),a=n.onWeekNumberClick,o=n.styles,l=n.classNames,i=n.locale,u=n.labels.labelWeekNumber,d=(0,n.formatters.formatWeekNumber)(Number(t),{locale:i});if(!a)return(0,s.jsx)("span",{className:l.weeknumber,style:o.weeknumber,children:d});var c=u(Number(t),{locale:i});return(0,s.jsx)(tv,{name:"week-number","aria-label":c,className:l.weeknumber,style:o.weeknumber,onClick:function(e){a(t,r,e)},children:d})}function t1(e){var t,r,n,a=to(),o=a.styles,l=a.classNames,i=a.showWeekNumber,u=a.components,d=null!=(t=null==u?void 0:u.Day)?t:tJ,c=null!=(r=null==u?void 0:u.WeekNumber)?r:t0;return i&&(n=(0,s.jsx)("td",{className:l.cell,style:o.cell,children:(0,s.jsx)(c,{number:e.weekNumber,dates:e.dates})})),(0,s.jsxs)("tr",{className:l.row,style:o.row,children:[n,e.dates.map(function(t){return(0,s.jsx)("td",{className:l.cell,style:o.cell,role:"presentation",children:(0,s.jsx)(d,{displayMonth:e.displayMonth,date:t})},Math.trunc((0,m.toDate)(t)/1e3))})]})}function t2(e,t,r){for(var n=(null==r?void 0:r.ISOWeek)?ey(t):ew(t,r),a=(null==r?void 0:r.ISOWeek)?Y(e):I(e,r),o=O(n,a),l=[],s=0;s<=o;s++)l.push((0,g.addDays)(a,s));return l.reduce(function(e,t){var n=(null==r?void 0:r.ISOWeek)?H(t):B(t,r),a=e.find(function(e){return e.weekNumber===n});return a?a.dates.push(t):e.push({weekNumber:n,dates:[t]}),e},[])}function t4(e){var t,r,n,a=to(),o=a.locale,l=a.classNames,i=a.styles,u=a.hideHead,d=a.fixedWeeks,c=a.components,f=a.weekStartsOn,h=a.firstWeekContainsDate,b=a.ISOWeek,v=function(e,t){var r=t2(p(e),eu(e),t);if(null==t?void 0:t.useFixedWeeks){let d,c,f,h;var n,a,o=(c=(d=(0,m.toDate)(e)).getMonth(),d.setFullYear(d.getFullYear(),c+1,0),d.setHours(0,0,0,0),n=d,a=p(e),f=I(n,t),h=I(a,t),Math.round((f-F(f)-(h-F(h)))/6048e5)+1);if(o<6){var l=r[r.length-1],s=l.dates[l.dates.length-1],i=ev(s,6-o),u=t2(ev(s,1),i,t);r.push.apply(r,u)}}return r}(e.displayMonth,{useFixedWeeks:!!d,ISOWeek:b,locale:o,weekStartsOn:f,firstWeekContainsDate:h}),g=null!=(t=null==c?void 0:c.Head)?t:tM,w=null!=(r=null==c?void 0:c.Row)?r:t1,y=null!=(n=null==c?void 0:c.Footer)?n:tx;return(0,s.jsxs)("table",{id:e.id,className:l.table,style:i.table,role:"grid","aria-labelledby":e["aria-labelledby"],children:[!u&&(0,s.jsx)(g,{}),(0,s.jsx)("tbody",{className:l.tbody,style:i.tbody,children:v.map(function(t){return(0,s.jsx)(w,{displayMonth:e.displayMonth,dates:t.dates,weekNumber:t.weekNumber},t.weekNumber)})}),(0,s.jsx)(y,{displayMonth:e.displayMonth})]})}var t3="u">typeof window&&window.document&&window.document.createElement?i.useLayoutEffect:i.useEffect,t5=!1,t6=0;function t7(){return"react-day-picker-".concat(++t6)}function t8(e){var t,r,n,a,o,l,u,d,c=to(),m=c.dir,f=c.classNames,h=c.styles,p=c.components,b=tf().displayMonths,v=(n=null!=(t=c.id?"".concat(c.id,"-").concat(e.displayIndex):void 0)?t:t5?t7():null,o=(a=(0,i.useState)(n))[0],l=a[1],t3(function(){null===o&&l(t7())},[]),(0,i.useEffect)(function(){!1===t5&&(t5=!0)},[]),null!=(r=null!=t?t:o)?r:void 0),g=c.id?"".concat(c.id,"-grid-").concat(e.displayIndex):void 0,w=[f.month],y=h.month,x=0===e.displayIndex,k=e.displayIndex===b.length-1,M=!x&&!k;"rtl"===m&&(k=(u=[x,k])[0],x=u[1]),x&&(w.push(f.caption_start),y=e5(e5({},y),h.caption_start)),k&&(w.push(f.caption_end),y=e5(e5({},y),h.caption_end)),M&&(w.push(f.caption_between),y=e5(e5({},y),h.caption_between));var D=null!=(d=null==p?void 0:p.Caption)?d:ty;return(0,s.jsxs)("div",{className:w.join(" "),style:y,children:[(0,s.jsx)(D,{id:v,displayMonth:e.displayMonth,displayIndex:e.displayIndex}),(0,s.jsx)(t4,{id:g,"aria-labelledby":v,displayMonth:e.displayMonth})]},e.displayIndex)}function t9(e){var t=to(),r=t.classNames,n=t.styles;return(0,s.jsx)("div",{className:r.months,style:n.months,children:e.children})}function re(e){var t,r,n=e.initialProps,a=to(),o=t$(),l=tf(),u=(0,i.useState)(!1),d=u[0],c=u[1];(0,i.useEffect)(function(){a.initialFocus&&o.focusTarget&&(d||(o.focus(o.focusTarget),c(!0)))},[a.initialFocus,d,o.focus,o.focusTarget,o]);var m=[a.classNames.root,a.className];a.numberOfMonths>1&&m.push(a.classNames.multiple_months),a.showWeekNumber&&m.push(a.classNames.with_weeknumber);var f=e5(e5({},a.styles.root),a.style),h=Object.keys(n).filter(function(e){return e.startsWith("data-")}).reduce(function(e,t){var r;return e5(e5({},e),((r={})[t]=n[t],r))},{}),p=null!=(r=null==(t=n.components)?void 0:t.Months)?r:t9;return(0,s.jsx)("div",e5({className:m.join(" "),style:f,dir:a.dir,id:a.id,nonce:n.nonce,title:n.title,lang:n.lang},h,{children:(0,s.jsx)(p,{children:l.displayMonths.map(function(e,t){return(0,s.jsx)(t8,{displayIndex:t,displayMonth:e},t)})})}))}function rt(e){var t=e.children,r=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 a=0,n=Object.getOwnPropertySymbols(e);at.indexOf(n[a])&&Object.prototype.propertyIsEnumerable.call(e,n[a])&&(r[n[a]]=e[n[a]]);return r}(e,["children"]);return(0,s.jsx)(ta,{initialProps:r,children:(0,s.jsx)(tm,{children:(0,s.jsx)(tX,{initialProps:r,children:(0,s.jsx)(tE,{initialProps:r,children:(0,s.jsx)(tC,{initialProps:r,children:(0,s.jsx)(tA,{children:(0,s.jsx)(tV,{children:t})})})})})})})}function rr(e){return(0,s.jsx)(rt,e5({},e,{children:(0,s.jsx)(re,{initialProps:e})}))}let rn=e=>{var t=(0,u.__rest)(e,[]);return i.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},t),i.default.createElement("path",{d:"M10.8284 12.0007L15.7782 16.9504L14.364 18.3646L8 12.0007L14.364 5.63672L15.7782 7.05093L10.8284 12.0007Z"}))},ra=e=>{var t=(0,u.__rest)(e,[]);return i.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},t),i.default.createElement("path",{d:"M13.1717 12.0007L8.22192 7.05093L9.63614 5.63672L16.0001 12.0007L9.63614 18.3646L8.22192 16.9504L13.1717 12.0007Z"}))},ro=e=>{var t=(0,u.__rest)(e,[]);return i.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},t),i.default.createElement("path",{d:"M4.83582 12L11.0429 18.2071L12.4571 16.7929L7.66424 12L12.4571 7.20712L11.0429 5.79291L4.83582 12ZM10.4857 12L16.6928 18.2071L18.107 16.7929L13.3141 12L18.107 7.20712L16.6928 5.79291L10.4857 12Z"}))},rl=e=>{var t=(0,u.__rest)(e,[]);return i.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},t),i.default.createElement("path",{d:"M19.1642 12L12.9571 5.79291L11.5429 7.20712L16.3358 12L11.5429 16.7929L12.9571 18.2071L19.1642 12ZM13.5143 12L7.30722 5.79291L5.89301 7.20712L10.6859 12L5.89301 16.7929L7.30722 18.2071L13.5143 12Z"}))};var rs=e.i(936325),ri=e.i(728889);let ru=e=>{var{onClick:t,icon:r}=e,n=(0,u.__rest)(e,["onClick","icon"]);return i.default.createElement("button",Object.assign({type:"button",className:(0,b.tremorTwMerge)("flex items-center justify-center p-1 h-7 w-7 outline-none focus:ring-2 transition duration-100 border border-tremor-border dark:border-dark-tremor-border hover:bg-tremor-background-muted dark:hover:bg-dark-tremor-background-muted rounded-tremor-small focus:border-tremor-brand-subtle select-none dark:focus:border-dark-tremor-brand-subtle focus:ring-tremor-brand-muted dark:focus:ring-dark-tremor-brand-muted text-tremor-content-subtle dark:text-dark-tremor-content-subtle hover:text-tremor-content dark:hover:text-dark-tremor-content")},n),i.default.createElement(ri.default,{onClick:t,icon:r,variant:"simple",color:"slate",size:"sm"}))};function rd(e){var{mode:t,defaultMonth:r,selected:n,onSelect:a,locale:o,disabled:l,enableYearNavigation:s,classNames:d,weekStartsOn:c=0}=e,m=(0,u.__rest)(e,["mode","defaultMonth","selected","onSelect","locale","disabled","enableYearNavigation","classNames","weekStartsOn"]);return i.default.createElement(rr,Object.assign({showOutsideDays:!0,mode:t,defaultMonth:r,selected:n,onSelect:a,locale:o,disabled:l,weekStartsOn:c,classNames:Object.assign({months:"flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",month:"space-y-4",caption:"flex justify-center pt-2 relative items-center",caption_label:"text-tremor-default text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis font-medium",nav:"space-x-1 flex items-center",nav_button:"flex items-center justify-center p-1 h-7 w-7 outline-none focus:ring-2 transition duration-100 border border-tremor-border dark:border-dark-tremor-border hover:bg-tremor-background-muted dark:hover:bg-dark-tremor-background-muted rounded-tremor-small focus:border-tremor-brand-subtle dark:focus:border-dark-tremor-brand-subtle focus:ring-tremor-brand-muted dark:focus:ring-dark-tremor-brand-muted text-tremor-content-subtle dark:text-dark-tremor-content-subtle hover:text-tremor-content dark:hover:text-dark-tremor-content",nav_button_previous:"absolute left-1",nav_button_next:"absolute right-1",table:"w-full border-collapse space-y-1",head_row:"flex",head_cell:"w-9 font-normal text-center text-tremor-content-subtle dark:text-dark-tremor-content-subtle",row:"flex w-full mt-0.5",cell:"text-center p-0 relative focus-within:relative text-tremor-default text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis",day:"h-9 w-9 p-0 hover:bg-tremor-background-subtle dark:hover:bg-dark-tremor-background-subtle outline-tremor-brand dark:outline-dark-tremor-brand rounded-tremor-default",day_today:"font-bold",day_selected:"aria-selected:bg-tremor-background-emphasis aria-selected:text-tremor-content-inverted dark:aria-selected:bg-dark-tremor-background-emphasis dark:aria-selected:text-dark-tremor-content-inverted ",day_disabled:"text-tremor-content-subtle dark:text-dark-tremor-content-subtle disabled:hover:bg-transparent",day_outside:"text-tremor-content-subtle dark:text-dark-tremor-content-subtle"},d),components:{IconLeft:e=>{var t=(0,u.__rest)(e,[]);return i.default.createElement(rn,Object.assign({className:"h-4 w-4"},t))},IconRight:e=>{var t=(0,u.__rest)(e,[]);return i.default.createElement(ra,Object.assign({className:"h-4 w-4"},t))},Caption:e=>{var t=(0,u.__rest)(e,[]);let{goToMonth:r,nextMonth:n,previousMonth:a,currentMonth:l}=tf();return i.default.createElement("div",{className:"flex justify-between items-center"},i.default.createElement("div",{className:"flex items-center space-x-1"},s&&i.default.createElement(ru,{onClick:()=>l&&r(eg(l,-1)),icon:ro}),i.default.createElement(ru,{onClick:()=>a&&r(a),icon:rn})),i.default.createElement(rs.default,{className:"text-tremor-default tabular-nums capitalize text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis font-medium"},el(t.displayMonth,"LLLL yyy",{locale:o})),i.default.createElement("div",{className:"flex items-center space-x-1"},i.default.createElement(ru,{onClick:()=>n&&r(n),icon:ra}),s&&i.default.createElement(ru,{onClick:()=>l&&r(eg(l,1)),icon:rl})))}}},m))}rd.displayName="DateRangePicker";var rc=e.i(333771),rm=e.i(888288),rf=e.i(429427),rh=e.i(371330),rp=e.i(394487),rb=e.i(992704),rv=e.i(914189),rg=e.i(941444),rw=e.i(835696),ry=e.i(877891),rx=e.i(952744),rk=e.i(605083),rM=e.i(144279),rD=e.i(2788),rN=e.i(402155);let rE=(0,i.createContext)(null);function rS({children:e,node:t}){let[r,n]=(0,i.useState)(null),a=rP(null!=t?t:r);return i.default.createElement(rE.Provider,{value:a},e,null===a&&i.default.createElement(rD.Hidden,{features:rD.HiddenFeatures.Hidden,ref:e=>{var t,r;if(e){for(let a of null!=(r=null==(t=(0,rN.getOwnerDocument)(e))?void 0:t.querySelectorAll("html > *, body > *"))?r:[])if(a!==document.body&&a!==document.head&&a instanceof HTMLElement&&null!=a&&a.contains(e)){n(a);break}}}}))}function rP(e=null){var t;return null!=(t=(0,i.useContext)(rE))?t:e}var rT=e.i(101852),rC=e.i(294316),r_=e.i(401141),rj=((t=rj||{})[t.Forwards=0]="Forwards",t[t.Backwards=1]="Backwards",t);function rL(){let e=(0,i.useRef)(0);return(0,r_.useWindowEvent)(!0,"keydown",t=>{"Tab"===t.key&&(e.current=+!!t.shiftKey)},!0),e}var rF=e.i(83733),rO=e.i(674175),rI=e.i(919751),rY=e.i(233137),rW=e.i(233538),rH=e.i(652265),rR=e.i(397701),rB=e.i(700020),rq=e.i(998348),rA=e.i(635307),rQ=((r=rQ||{})[r.Open=0]="Open",r[r.Closed=1]="Closed",r),rG=((n=rG||{})[n.TogglePopover=0]="TogglePopover",n[n.ClosePopover=1]="ClosePopover",n[n.SetButton=2]="SetButton",n[n.SetButtonId=3]="SetButtonId",n[n.SetPanel=4]="SetPanel",n[n.SetPanelId=5]="SetPanelId",n);let rz={0:e=>({...e,popoverState:(0,rR.match)(e.popoverState,{0:1,1:0}),__demoMode:!1}),1:e=>1===e.popoverState?e:{...e,popoverState:1,__demoMode:!1},2:(e,t)=>e.button===t.button?e:{...e,button:t.button},3:(e,t)=>e.buttonId===t.buttonId?e:{...e,buttonId:t.buttonId},4:(e,t)=>e.panel===t.panel?e:{...e,panel:t.panel},5:(e,t)=>e.panelId===t.panelId?e:{...e,panelId:t.panelId}},rV=(0,i.createContext)(null);function r$(e){let t=(0,i.useContext)(rV);if(null===t){let t=Error(`<${e} /> is missing a parent component.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,r$),t}return t}rV.displayName="PopoverContext";let rK=(0,i.createContext)(null);function rX(e){let t=(0,i.useContext)(rK);if(null===t){let t=Error(`<${e} /> is missing a parent component.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,rX),t}return t}rK.displayName="PopoverAPIContext";let rZ=(0,i.createContext)(null);function rU(){return(0,i.useContext)(rZ)}rZ.displayName="PopoverGroupContext";let rJ=(0,i.createContext)(null);function r0(e,t){return(0,rR.match)(t.type,rz,e,t)}rJ.displayName="PopoverPanelContext";let r1=rB.RenderFeatures.RenderStrategy|rB.RenderFeatures.Static;function r2(e,t){let r=(0,i.useId)(),{id:n=`headlessui-popover-backdrop-${r}`,transition:a=!1,...o}=e,[{popoverState:l},s]=r$("Popover.Backdrop"),[u,d]=(0,i.useState)(null),c=(0,rC.useSyncRefs)(t,d),m=(0,rY.useOpenClosed)(),[f,h]=(0,rF.useTransition)(a,u,null!==m?(m&rY.State.Open)===rY.State.Open:0===l),p=(0,rv.useEvent)(e=>{if((0,rW.isDisabledReactIssue7711)(e.currentTarget))return e.preventDefault();s({type:1})}),b=(0,i.useMemo)(()=>({open:0===l}),[l]),v={ref:c,id:n,"aria-hidden":!0,onClick:p,...(0,rF.transitionDataAttributes)(h)};return(0,rB.useRender)()({ourProps:v,theirProps:o,slot:b,defaultTag:"div",features:r1,visible:f,name:"Popover.Backdrop"})}let r4=rB.RenderFeatures.RenderStrategy|rB.RenderFeatures.Static,r3=(0,rB.forwardRefWithAs)(function(e,t){var r,n,a;let o,{__demoMode:l=!1,...s}=e,u=(0,i.useRef)(null),d=(0,rC.useSyncRefs)(t,(0,rC.optionalRef)(e=>{u.current=e})),c=(0,i.useRef)([]),m=(0,i.useReducer)(r0,{__demoMode:l,popoverState:+!l,buttons:c,button:null,buttonId:null,panel:null,panelId:null,beforePanelSentinel:(0,i.createRef)(),afterPanelSentinel:(0,i.createRef)(),afterButtonSentinel:(0,i.createRef)()}),[{popoverState:f,button:h,buttonId:p,panel:b,panelId:v,beforePanelSentinel:g,afterPanelSentinel:w,afterButtonSentinel:y},x]=m,k=(0,rk.useOwnerDocument)(null!=(r=u.current)?r:h),M=(0,i.useMemo)(()=>{if(!h||!b)return!1;for(let e of document.querySelectorAll("body > *"))if(Number(null==e?void 0:e.contains(h))^Number(null==e?void 0:e.contains(b)))return!0;let e=(0,rH.getFocusableElements)(),t=e.indexOf(h),r=(t+e.length-1)%e.length,n=(t+1)%e.length,a=e[r],o=e[n];return!b.contains(a)&&!b.contains(o)},[h,b]),D=(0,rg.useLatestValue)(p),N=(0,rg.useLatestValue)(v),E=(0,i.useMemo)(()=>({buttonId:D,panelId:N,close:()=>x({type:1})}),[D,N,x]),S=rU(),P=null==S?void 0:S.registerPopover,T=(0,rv.useEvent)(()=>{var e;return null!=(e=null==S?void 0:S.isFocusWithinPopoverGroup())?e:(null==k?void 0:k.activeElement)&&((null==h?void 0:h.contains(k.activeElement))||(null==b?void 0:b.contains(k.activeElement)))});(0,i.useEffect)(()=>null==P?void 0:P(E),[P,E]);let[C,_]=(0,rA.useNestedPortals)(),j=rP(h),L=function({defaultContainers:e=[],portals:t,mainTreeNode:r}={}){let n=(0,rk.useOwnerDocument)(r),a=(0,rv.useEvent)(()=>{var a,o;let l=[];for(let t of e)null!==t&&(t instanceof HTMLElement?l.push(t):"current"in t&&t.current instanceof HTMLElement&&l.push(t.current));if(null!=t&&t.current)for(let e of t.current)l.push(e);for(let e of null!=(a=null==n?void 0:n.querySelectorAll("html > *, body > *"))?a:[])e!==document.body&&e!==document.head&&e instanceof HTMLElement&&"headlessui-portal-root"!==e.id&&(r&&(e.contains(r)||e.contains(null==(o=null==r?void 0:r.getRootNode())?void 0:o.host))||l.some(t=>e.contains(t))||l.push(e));return l});return{resolveContainers:a,contains:(0,rv.useEvent)(e=>a().some(t=>t.contains(e)))}}({mainTreeNode:j,portals:C,defaultContainers:[h,b]});n=null==k?void 0:k.defaultView,a="focus",o=(0,rg.useLatestValue)(e=>{var t,r,n,a,o,l;e.target!==window&&e.target instanceof HTMLElement&&0===f&&(T()||h&&b&&(L.contains(e.target)||null!=(r=null==(t=g.current)?void 0:t.contains)&&r.call(t,e.target)||null!=(a=null==(n=w.current)?void 0:n.contains)&&a.call(n,e.target)||null!=(l=null==(o=y.current)?void 0:o.contains)&&l.call(o,e.target)||x({type:1})))}),(0,i.useEffect)(()=>{function e(e){o.current(e)}return(n=null!=n?n:window).addEventListener(a,e,!0),()=>n.removeEventListener(a,e,!0)},[n,a,!0]),(0,rx.useOutsideClick)(0===f,L.resolveContainers,(e,t)=>{x({type:1}),(0,rH.isFocusableElement)(t,rH.FocusableMode.Loose)||(e.preventDefault(),null==h||h.focus())});let F=(0,rv.useEvent)(e=>{x({type:1});let t=e?e instanceof HTMLElement?e:"current"in e&&e.current instanceof HTMLElement?e.current:h:h;null==t||t.focus()}),O=(0,i.useMemo)(()=>({close:F,isPortalled:M}),[F,M]),I=(0,i.useMemo)(()=>({open:0===f,close:F}),[f,F]),Y=(0,rB.useRender)();return i.default.createElement(rS,{node:j},i.default.createElement(rI.FloatingProvider,null,i.default.createElement(rJ.Provider,{value:null},i.default.createElement(rV.Provider,{value:m},i.default.createElement(rK.Provider,{value:O},i.default.createElement(rO.CloseProvider,{value:F},i.default.createElement(rY.OpenClosedProvider,{value:(0,rR.match)(f,{0:rY.State.Open,1:rY.State.Closed})},i.default.createElement(_,null,Y({ourProps:{ref:d},theirProps:s,slot:I,defaultTag:"div",name:"Popover"})))))))))}),r5=(0,rB.forwardRefWithAs)(function(e,t){let r=(0,i.useId)(),{id:n=`headlessui-popover-button-${r}`,disabled:a=!1,autoFocus:o=!1,...l}=e,[s,u]=r$("Popover.Button"),{isPortalled:d}=rX("Popover.Button"),c=(0,i.useRef)(null),m=`headlessui-focus-sentinel-${(0,i.useId)()}`,f=rU(),h=null==f?void 0:f.closeOthers,p=null!==(0,i.useContext)(rJ);(0,i.useEffect)(()=>{if(!p)return u({type:3,buttonId:n}),()=>{u({type:3,buttonId:null})}},[p,n,u]);let[b]=(0,i.useState)(()=>Symbol()),v=(0,rC.useSyncRefs)(c,t,(0,rI.useFloatingReference)(),(0,rv.useEvent)(e=>{if(!p){if(e)s.buttons.current.push(b);else{let e=s.buttons.current.indexOf(b);-1!==e&&s.buttons.current.splice(e,1)}s.buttons.current.length>1&&console.warn("You are already using a but only 1 is supported."),e&&u({type:2,button:e})}})),g=(0,rC.useSyncRefs)(c,t),w=(0,rk.useOwnerDocument)(c),y=(0,rv.useEvent)(e=>{var t,r,n;if(p){if(1===s.popoverState)return;switch(e.key){case rq.Keys.Space:case rq.Keys.Enter:e.preventDefault(),null==(r=(t=e.target).click)||r.call(t),u({type:1}),null==(n=s.button)||n.focus()}}else switch(e.key){case rq.Keys.Space:case rq.Keys.Enter:e.preventDefault(),e.stopPropagation(),1===s.popoverState&&(null==h||h(s.buttonId)),u({type:0});break;case rq.Keys.Escape:if(0!==s.popoverState)return null==h?void 0:h(s.buttonId);if(!c.current||null!=w&&w.activeElement&&!c.current.contains(w.activeElement))return;e.preventDefault(),e.stopPropagation(),u({type:1})}}),x=(0,rv.useEvent)(e=>{p||e.key===rq.Keys.Space&&e.preventDefault()}),k=(0,rv.useEvent)(e=>{var t,r;(0,rW.isDisabledReactIssue7711)(e.currentTarget)||a||(p?(u({type:1}),null==(t=s.button)||t.focus()):(e.preventDefault(),e.stopPropagation(),1===s.popoverState&&(null==h||h(s.buttonId)),u({type:0}),null==(r=s.button)||r.focus()))}),M=(0,rv.useEvent)(e=>{e.preventDefault(),e.stopPropagation()}),{isFocusVisible:D,focusProps:N}=(0,rf.useFocusRing)({autoFocus:o}),{isHovered:E,hoverProps:S}=(0,rh.useHover)({isDisabled:a}),{pressed:P,pressProps:T}=(0,rp.useActivePress)({disabled:a}),C=0===s.popoverState,_=(0,i.useMemo)(()=>({open:C,active:P||C,disabled:a,hover:E,focus:D,autofocus:o}),[C,E,D,P,a,o]),j=(0,rM.useResolveButtonType)(e,s.button),L=p?(0,rB.mergeProps)({ref:g,type:j,onKeyDown:y,onClick:k,disabled:a||void 0,autoFocus:o},N,S,T):(0,rB.mergeProps)({ref:v,id:s.buttonId,type:j,"aria-expanded":0===s.popoverState,"aria-controls":s.panel?s.panelId:void 0,disabled:a||void 0,autoFocus:o,onKeyDown:y,onKeyUp:x,onClick:k,onMouseDown:M},N,S,T),F=rL(),O=(0,rv.useEvent)(()=>{let e=s.panel;e&&(0,rR.match)(F.current,{[rj.Forwards]:()=>(0,rH.focusIn)(e,rH.Focus.First),[rj.Backwards]:()=>(0,rH.focusIn)(e,rH.Focus.Last)})===rH.FocusResult.Error&&(0,rH.focusIn)((0,rH.getFocusableElements)().filter(e=>"true"!==e.dataset.headlessuiFocusGuard),(0,rR.match)(F.current,{[rj.Forwards]:rH.Focus.Next,[rj.Backwards]:rH.Focus.Previous}),{relativeTo:s.button})}),I=(0,rB.useRender)();return i.default.createElement(i.default.Fragment,null,I({ourProps:L,theirProps:l,slot:_,defaultTag:"button",name:"Popover.Button"}),C&&!p&&d&&i.default.createElement(rD.Hidden,{id:m,ref:s.afterButtonSentinel,features:rD.HiddenFeatures.Focusable,"data-headlessui-focus-guard":!0,as:"button",type:"button",onFocus:O}))}),r6=(0,rB.forwardRefWithAs)(r2),r7=(0,rB.forwardRefWithAs)(r2),r8=(0,rB.forwardRefWithAs)(function(e,t){let r=(0,i.useId)(),{id:n=`headlessui-popover-panel-${r}`,focus:a=!1,anchor:o,portal:l=!1,modal:s=!1,transition:u=!1,...d}=e,[c,m]=r$("Popover.Panel"),{close:f,isPortalled:h}=rX("Popover.Panel"),p=`headlessui-focus-sentinel-before-${r}`,b=`headlessui-focus-sentinel-after-${r}`,v=(0,i.useRef)(null),g=(0,rI.useResolvedAnchor)(o),[w,y]=(0,rI.useFloatingPanel)(g),x=(0,rI.useFloatingPanelProps)();g&&(l=!0);let[k,M]=(0,i.useState)(null),D=(0,rC.useSyncRefs)(v,t,g?w:null,(0,rv.useEvent)(e=>m({type:4,panel:e})),M),N=(0,rk.useOwnerDocument)(v);(0,rw.useIsoMorphicEffect)(()=>(m({type:5,panelId:n}),()=>{m({type:5,panelId:null})}),[n,m]);let E=(0,rY.useOpenClosed)(),[S,P]=(0,rF.useTransition)(u,k,null!==E?(E&rY.State.Open)===rY.State.Open:0===c.popoverState);(0,ry.useOnDisappear)(S,c.button,()=>{m({type:1})});let T=!c.__demoMode&&s&&S;(0,rT.useScrollLock)(T,N);let C=(0,rv.useEvent)(e=>{var t;if(e.key===rq.Keys.Escape){if(0!==c.popoverState||!v.current||null!=N&&N.activeElement&&!v.current.contains(N.activeElement))return;e.preventDefault(),e.stopPropagation(),m({type:1}),null==(t=c.button)||t.focus()}});(0,i.useEffect)(()=>{var t;e.static||1===c.popoverState&&(null==(t=e.unmount)||t)&&m({type:4,panel:null})},[c.popoverState,e.unmount,e.static,m]),(0,i.useEffect)(()=>{if(c.__demoMode||!a||0!==c.popoverState||!v.current)return;let e=null==N?void 0:N.activeElement;v.current.contains(e)||(0,rH.focusIn)(v.current,rH.Focus.First)},[c.__demoMode,a,v.current,c.popoverState]);let _=(0,i.useMemo)(()=>({open:0===c.popoverState,close:f}),[c.popoverState,f]),j=(0,rB.mergeProps)(g?x():{},{ref:D,id:n,onKeyDown:C,onBlur:a&&0===c.popoverState?e=>{var t,r,n,a,o;let l=e.relatedTarget;l&&v.current&&(null!=(t=v.current)&&t.contains(l)||(m({type:1}),(null!=(n=null==(r=c.beforePanelSentinel.current)?void 0:r.contains)&&n.call(r,l)||null!=(o=null==(a=c.afterPanelSentinel.current)?void 0:a.contains)&&o.call(a,l))&&l.focus({preventScroll:!0})))}:void 0,tabIndex:-1,style:{...d.style,...y,"--button-width":(0,rb.useElementSize)(c.button,!0).width},...(0,rF.transitionDataAttributes)(P)}),L=rL(),F=(0,rv.useEvent)(()=>{let e=v.current;e&&(0,rR.match)(L.current,{[rj.Forwards]:()=>{var t;(0,rH.focusIn)(e,rH.Focus.First)===rH.FocusResult.Error&&(null==(t=c.afterPanelSentinel.current)||t.focus())},[rj.Backwards]:()=>{var e;null==(e=c.button)||e.focus({preventScroll:!0})}})}),O=(0,rv.useEvent)(()=>{let e=v.current;e&&(0,rR.match)(L.current,{[rj.Forwards]:()=>{if(!c.button)return;let e=(0,rH.getFocusableElements)(),t=e.indexOf(c.button),r=e.slice(0,t+1),n=[...e.slice(t+1),...r];for(let e of n.slice())if("true"===e.dataset.headlessuiFocusGuard||null!=k&&k.contains(e)){let t=n.indexOf(e);-1!==t&&n.splice(t,1)}(0,rH.focusIn)(n,rH.Focus.First,{sorted:!1})},[rj.Backwards]:()=>{var t;(0,rH.focusIn)(e,rH.Focus.Previous)===rH.FocusResult.Error&&(null==(t=c.button)||t.focus())}})}),I=(0,rB.useRender)();return i.default.createElement(rY.ResetOpenClosedProvider,null,i.default.createElement(rJ.Provider,{value:n},i.default.createElement(rK.Provider,{value:{close:f,isPortalled:h}},i.default.createElement(rA.Portal,{enabled:!!l&&(e.static||S)},S&&h&&i.default.createElement(rD.Hidden,{id:p,ref:c.beforePanelSentinel,features:rD.HiddenFeatures.Focusable,"data-headlessui-focus-guard":!0,as:"button",type:"button",onFocus:F}),I({ourProps:j,theirProps:d,slot:_,defaultTag:"div",features:r4,visible:S,name:"Popover.Panel"}),S&&h&&i.default.createElement(rD.Hidden,{id:b,ref:c.afterPanelSentinel,features:rD.HiddenFeatures.Focusable,"data-headlessui-focus-guard":!0,as:"button",type:"button",onFocus:O})))))}),r9=Object.assign(r3,{Button:r5,Backdrop:r7,Overlay:r6,Panel:r8,Group:(0,rB.forwardRefWithAs)(function(e,t){let r=(0,i.useRef)(null),n=(0,rC.useSyncRefs)(r,t),[a,o]=(0,i.useState)([]),l=(0,rv.useEvent)(e=>{o(t=>{let r=t.indexOf(e);if(-1!==r){let e=t.slice();return e.splice(r,1),e}return t})}),s=(0,rv.useEvent)(e=>(o(t=>[...t,e]),()=>l(e))),u=(0,rv.useEvent)(()=>{var e;let t=(0,rN.getOwnerDocument)(r);if(!t)return!1;let n=t.activeElement;return!!(null!=(e=r.current)&&e.contains(n))||a.some(e=>{var r,a;return(null==(r=t.getElementById(e.buttonId.current))?void 0:r.contains(n))||(null==(a=t.getElementById(e.panelId.current))?void 0:a.contains(n))})}),d=(0,rv.useEvent)(e=>{for(let t of a)t.buttonId.current!==e&&t.close()}),c=(0,i.useMemo)(()=>({registerPopover:s,unregisterPopover:l,isFocusWithinPopoverGroup:u,closeOthers:d}),[s,l,u,d]),m=(0,i.useMemo)(()=>({}),[]),f=(0,rB.useRender)();return i.default.createElement(rS,null,i.default.createElement(rZ.Provider,{value:c},f({ourProps:{ref:n},theirProps:e,slot:m,defaultTag:"div",name:"Popover.Group"})))})});var ne=e.i(854056),nt=e.i(495470);let nr=h(),nn=i.default.forwardRef((e,t)=>{var r,n;let{value:a,defaultValue:o,onValueChange:l,enableSelect:s=!0,minDate:g,maxDate:w,placeholder:y="Select range",selectPlaceholder:x="Select range",disabled:k=!1,locale:M=j,enableClear:E=!0,displayFormat:S,children:P,className:T,enableYearNavigation:C=!1,weekStartsOn:_=0,disabledDates:L}=e,F=(0,u.__rest)(e,["value","defaultValue","onValueChange","enableSelect","minDate","maxDate","placeholder","selectPlaceholder","disabled","locale","enableClear","displayFormat","children","className","enableYearNavigation","weekStartsOn","disabledDates"]),[O,I]=(0,rm.default)(o,a),[Y,W]=(0,i.useState)(!1),[H,R]=(0,i.useState)(!1),B=(0,i.useMemo)(()=>{let e=[];return g&&e.push({before:g}),w&&e.push({after:w}),[...e,...null!=L?L:[]]},[g,w,L]),q=(0,i.useMemo)(()=>{let e=new Map;return P?i.default.Children.forEach(P,t=>{var r;e.set(t.props.value,{text:null!=(r=(0,v.getNodeText)(t))?r:t.props.value,from:t.props.from,to:t.props.to})}):ei.forEach(t=>{e.set(t.value,{text:t.text,from:t.from,to:nr})}),e},[P]),A=(0,i.useMemo)(()=>{if(P)return(0,v.constructValueToNameMapping)(P);let e=new Map;return ei.forEach(t=>e.set(t.value,t.text)),e},[P]),Q=(null==O?void 0:O.selectValue)||"",G=((e,t,r,n)=>{var a;if(r&&(e=null==(a=n.get(r))?void 0:a.from),e)return f(e&&!t?e:D([e,t]))})(null==O?void 0:O.from,g,Q,q),z=((e,t,r,n)=>{var a,o;if(r&&(e=f(null!=(o=null==(a=n.get(r))?void 0:a.to)?o:h())),e)return f(e&&!t?e:N([e,t]))})(null==O?void 0:O.to,w,Q,q),V=G||z?((e,t,r,n)=>{let a=(null==r?void 0:r.code)||"en-US";if(!e&&!t)return"";if(e&&!t)return n?el(e,n):e.toLocaleDateString(a,{year:"numeric",month:"short",day:"numeric"});if(e&&t){if(+(0,m.toDate)(e)==+(0,m.toDate)(t))return n?el(e,n):e.toLocaleDateString(a,{year:"numeric",month:"short",day:"numeric"});if(e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear())return n?`${el(e,n)} - ${el(t,n)}`:`${e.toLocaleDateString(a,{month:"short",day:"numeric"})} - + ${t.getDate()}, ${t.getFullYear()}`;{if(n)return`${el(e,n)} - ${el(t,n)}`;let r={year:"numeric",month:"short",day:"numeric"};return`${e.toLocaleDateString(a,r)} - + ${t.toLocaleDateString(a,r)}`}}return""})(G,z,M,S):y,$=p(null!=(n=null!=(r=null!=z?z:G)?r:w)?n:nr),K=E&&!k;return i.default.createElement("div",Object.assign({ref:t,className:(0,b.tremorTwMerge)("w-full min-w-[10rem] relative flex justify-between text-tremor-default max-w-sm shadow-tremor-input dark:shadow-dark-tremor-input rounded-tremor-default",T)},F),i.default.createElement(r9,{as:"div",className:(0,b.tremorTwMerge)("w-full",s?"rounded-l-tremor-default":"rounded-tremor-default",Y&&"ring-2 ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted z-10")},i.default.createElement("div",{className:"relative w-full"},i.default.createElement(r5,{onFocus:()=>W(!0),onBlur:()=>W(!1),disabled:k,className:(0,b.tremorTwMerge)("w-full outline-none text-left whitespace-nowrap truncate focus:ring-2 transition duration-100 rounded-l-tremor-default flex flex-nowrap border pl-3 py-2","rounded-l-tremor-default border-tremor-border text-tremor-content-emphasis focus:border-tremor-brand-subtle focus:ring-tremor-brand-muted","dark:border-dark-tremor-border dark:text-dark-tremor-content-emphasis dark:focus:border-dark-tremor-brand-subtle dark:focus:ring-dark-tremor-brand-muted",s?"rounded-l-tremor-default":"rounded-tremor-default",K?"pr-8":"pr-4",(0,v.getSelectButtonColors)((0,v.hasValue)(G||z),k))},i.default.createElement(d,{className:(0,b.tremorTwMerge)(es("calendarIcon"),"flex-none shrink-0 h-5 w-5 -ml-0.5 mr-2","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle"),"aria-hidden":"true"}),i.default.createElement("p",{className:"truncate"},V)),K&&G?i.default.createElement("button",{type:"button",className:(0,b.tremorTwMerge)("absolute outline-none inset-y-0 right-0 flex items-center transition duration-100 mr-4"),onClick:e=>{e.preventDefault(),null==l||l({}),I({})}},i.default.createElement(c.default,{className:(0,b.tremorTwMerge)(es("clearIcon"),"flex-none h-4 w-4","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")})):null),i.default.createElement(ne.Transition,{enter:"transition ease duration-100 transform",enterFrom:"opacity-0 -translate-y-4",enterTo:"opacity-100 translate-y-0",leave:"transition ease duration-100 transform",leaveFrom:"opacity-100 translate-y-0",leaveTo:"opacity-0 -translate-y-4"},i.default.createElement(r8,{anchor:"bottom start",focus:!0,className:(0,b.tremorTwMerge)("min-w-min divide-y overflow-y-auto outline-none rounded-tremor-default p-3 border [--anchor-gap:4px]","bg-tremor-background border-tremor-border divide-tremor-border shadow-tremor-dropdown","dark:bg-dark-tremor-background dark:border-dark-tremor-border dark:divide-dark-tremor-border dark:shadow-dark-tremor-dropdown")},i.default.createElement(rd,Object.assign({mode:"range",showOutsideDays:!0,defaultMonth:$,selected:{from:G,to:z},onSelect:e=>{null==l||l({from:null==e?void 0:e.from,to:null==e?void 0:e.to}),I({from:null==e?void 0:e.from,to:null==e?void 0:e.to})},locale:M,disabled:B,enableYearNavigation:C,classNames:{day_range_middle:(0,b.tremorTwMerge)("!rounded-none aria-selected:!bg-tremor-background-subtle aria-selected:dark:!bg-dark-tremor-background-subtle aria-selected:!text-tremor-content aria-selected:dark:!bg-dark-tremor-background-subtle"),day_range_start:"rounded-r-none rounded-l-tremor-small aria-selected:text-tremor-brand-inverted dark:aria-selected:text-dark-tremor-brand-inverted",day_range_end:"rounded-l-none rounded-r-tremor-small aria-selected:text-tremor-brand-inverted dark:aria-selected:text-dark-tremor-brand-inverted"},weekStartsOn:_},e))))),s&&i.default.createElement(nt.Listbox,{as:"div",className:(0,b.tremorTwMerge)("w-48 -ml-px rounded-r-tremor-default",H&&"ring-2 ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted z-10"),value:Q,onChange:e=>{let{from:t,to:r}=q.get(e),n=null!=r?r:nr;null==l||l({from:t,to:n,selectValue:e}),I({from:t,to:n,selectValue:e})},disabled:k},({value:e})=>{var t;return i.default.createElement(i.default.Fragment,null,i.default.createElement(nt.ListboxButton,{onFocus:()=>R(!0),onBlur:()=>R(!1),className:(0,b.tremorTwMerge)("w-full outline-none text-left whitespace-nowrap truncate rounded-r-tremor-default transition duration-100 border px-4 py-2","border-tremor-border text-tremor-content-emphasis focus:border-tremor-brand-subtle","dark:border-dark-tremor-border dark:text-dark-tremor-content-emphasis dark:focus:border-dark-tremor-brand-subtle",(0,v.getSelectButtonColors)((0,v.hasValue)(e),k))},e&&null!=(t=A.get(e))?t:x),i.default.createElement(ne.Transition,{enter:"transition ease duration-100 transform",enterFrom:"opacity-0 -translate-y-4",enterTo:"opacity-100 translate-y-0",leave:"transition ease duration-100 transform",leaveFrom:"opacity-100 translate-y-0",leaveTo:"opacity-0 -translate-y-4"},i.default.createElement(nt.ListboxOptions,{anchor:"bottom end",className:(0,b.tremorTwMerge)("[--anchor-gap:4px] divide-y overflow-y-auto outline-none border min-w-44","shadow-tremor-dropdown bg-tremor-background border-tremor-border divide-tremor-border rounded-tremor-default","dark:shadow-dark-tremor-dropdown dark:bg-dark-tremor-background dark:border-dark-tremor-border dark:divide-dark-tremor-border")},null!=P?P:ei.map(e=>i.default.createElement(rc.default,{key:e.value,value:e.value},e.text)))))}))});nn.displayName="DateRangePicker";var na=e.i(599724);e.s(["default",0,({value:e,onValueChange:t,label:r="Select Time Range",className:n="",showTimeRange:a=!0})=>{let[o,l]=(0,i.useState)(!1),u=(0,i.useRef)(null),d=(0,i.useCallback)(e=>{l(!0),setTimeout(()=>l(!1),1500),t(e),requestIdleCallback(()=>{if(e.from){let r,n={...e},a=new Date(e.from);r=new Date(e.to?e.to:e.from),a.toDateString(),r.toDateString(),a.setHours(0,0,0,0),r.setHours(23,59,59,999),n.from=a,n.to=r,t(n)}},{timeout:100})},[t]),c=(0,i.useCallback)((e,t)=>{if(!e||!t)return"";let r=e=>e.toLocaleString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!0,timeZoneName:"short"});if(e.toDateString()!==t.toDateString())return`${r(e)} - ${r(t)}`;{let r=e.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}),n=e.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",hour12:!0}),a=t.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",hour12:!0,timeZoneName:"short"});return`${r}: ${n} - ${a}`}},[]);return(0,s.jsxs)("div",{className:n,children:[r&&(0,s.jsx)(na.Text,{className:"mb-2",children:r}),(0,s.jsxs)("div",{className:"relative w-fit",children:[(0,s.jsx)("div",{ref:u,children:(0,s.jsx)(nn,{enableSelect:!0,value:e,onValueChange:d,placeholder:"Select date range",enableClear:!1,style:{zIndex:100}})}),o&&(0,s.jsx)("div",{className:"absolute top-1/2 animate-pulse",style:{left:"calc(100% + 8px)",transform:"translateY(-50%)",zIndex:110},children:(0,s.jsxs)("div",{className:"flex items-center gap-1 text-green-600 text-sm font-medium bg-white px-2 py-1 rounded-full border border-green-200 shadow-sm whitespace-nowrap",children:[(0,s.jsx)("div",{className:"w-3 h-3 bg-green-500 text-white rounded-full flex items-center justify-center text-xs",children:"✓"}),(0,s.jsx)("span",{className:"text-xs",children:"Selected"})]})})]}),a&&e.from&&e.to&&(0,s.jsx)(na.Text,{className:"mt-2 text-xs text-gray-500",children:c(e.from,e.to)})]})}],144267)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/0a6c418370a8c183.js b/litellm/proxy/_experimental/out/_next/static/chunks/0a6c418370a8c183.js new file mode 100644 index 00000000000..b3e15e69622 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/0a6c418370a8c183.js @@ -0,0 +1,41 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,486794,(e,t,n)=>{t.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],l=0;l{"use strict";var l=e.r(486794),r={"text/plain":"Text","text/html":"Url",default:"Text"};t.exports=function(e,t){var n,o,a,i,c,s,u,d,p=!1;t||(t={}),a=t.debug||!1;try{if(c=l(),s=document.createRange(),u=document.getSelection(),(d=document.createElement("span")).textContent=e,d.ariaHidden="true",d.style.all="unset",d.style.position="fixed",d.style.top=0,d.style.clip="rect(0, 0, 0, 0)",d.style.whiteSpace="pre",d.style.webkitUserSelect="text",d.style.MozUserSelect="text",d.style.msUserSelect="text",d.style.userSelect="text",d.addEventListener("copy",function(n){if(n.stopPropagation(),t.format)if(n.preventDefault(),void 0===n.clipboardData){a&&console.warn("unable to use e.clipboardData"),a&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var l=r[t.format]||r.default;window.clipboardData.setData(l,e)}else n.clipboardData.clearData(),n.clipboardData.setData(t.format,e);t.onCopy&&(n.preventDefault(),t.onCopy(n.clipboardData))}),document.body.appendChild(d),s.selectNodeContents(d),u.addRange(s),!document.execCommand("copy"))throw Error("copy command was unsuccessful");p=!0}catch(l){a&&console.error("unable to copy using execCommand: ",l),a&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),p=!0}catch(l){a&&console.error("unable to copy using clipboardData: ",l),a&&console.error("falling back to prompt"),n="message"in t?t.message:"Copy to clipboard: #{key}, Enter",o=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C",i=n.replace(/#{\s*key\s*}/g,o),window.prompt(i,e)}}finally{u&&("function"==typeof u.removeRange?u.removeRange(s):u.removeAllRanges()),d&&document.body.removeChild(d),c()}return p}},898586,401361,335771,e=>{"use strict";e.i(247167);var t=e.i(271645),n=e.i(8211),l=e.i(931067);let r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z"}}]},name:"edit",theme:"outlined"};var o=e.i(9583),a=t.forwardRef(function(e,n){return t.createElement(o.default,(0,l.default)({},e,{ref:n,icon:r}))});e.s(["default",0,a],401361);var i=e.i(343794),c=e.i(430073),s=e.i(876556),u=e.i(174428),d=e.i(914949),p=e.i(529681),f=e.i(611935),m=e.i(735049),g=e.i(242064),b=e.i(929447),y=e.i(491816);let v={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 000 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8z"}}]},name:"enter",theme:"outlined"};var h=t.forwardRef(function(e,n){return t.createElement(o.default,(0,l.default)({},e,{ref:n,icon:v}))}),x=e.i(404948),O=e.i(763731),E=e.i(635432),S=e.i(183293),w=e.i(246422);e.i(765846);var j=e.i(896091);let C=(0,w.genStyleHooks)("Typography",e=>{let t,{componentCls:n,titleMarginTop:l}=e;return{[n]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({color:e.colorText,wordBreak:"break-word",lineHeight:e.lineHeight,[`&${n}-secondary`]:{color:e.colorTextDescription},[`&${n}-success`]:{color:e.colorSuccessText},[`&${n}-warning`]:{color:e.colorWarningText},[`&${n}-danger`]:{color:e.colorErrorText,"a&:active, a&:focus":{color:e.colorErrorTextActive},"a&:hover":{color:e.colorErrorTextHover}},[`&${n}-disabled`]:{color:e.colorTextDisabled,cursor:"not-allowed",userSelect:"none"},[` + div&, + p + `]:{marginBottom:"1em"}},(t={},[1,2,3,4,5].forEach(n=>{t[` + h${n}&, + div&-h${n}, + div&-h${n} > textarea, + h${n} + `]=((e,t,n,l)=>{let{titleMarginBottom:r,fontWeightStrong:o}=l;return{marginBottom:r,color:n,fontWeight:o,fontSize:e,lineHeight:t}})(e[`fontSizeHeading${n}`],e[`lineHeightHeading${n}`],e.colorTextHeading,e)}),t)),{[` + & + h1${n}, + & + h2${n}, + & + h3${n}, + & + h4${n}, + & + h5${n} + `]:{marginTop:l},[` + div, + ul, + li, + p, + h1, + h2, + h3, + h4, + h5`]:{[` + + h1, + + h2, + + h3, + + h4, + + h5 + `]:{marginTop:l}}}),{code:{margin:"0 0.2em",paddingInline:"0.4em",paddingBlock:"0.2em 0.1em",fontSize:"85%",fontFamily:e.fontFamilyCode,background:"rgba(150, 150, 150, 0.1)",border:"1px solid rgba(100, 100, 100, 0.2)",borderRadius:3},kbd:{margin:"0 0.2em",paddingInline:"0.4em",paddingBlock:"0.15em 0.1em",fontSize:"90%",fontFamily:e.fontFamilyCode,background:"rgba(150, 150, 150, 0.06)",border:"1px solid rgba(100, 100, 100, 0.2)",borderBottomWidth:2,borderRadius:3},mark:{padding:0,backgroundColor:j.gold[2]},"u, ins":{textDecoration:"underline",textDecorationSkipInk:"auto"},"s, del":{textDecoration:"line-through"},strong:{fontWeight:e.fontWeightStrong},"ul, ol":{marginInline:0,marginBlock:"0 1em",padding:0,li:{marginInline:"20px 0",marginBlock:0,paddingInline:"4px 0",paddingBlock:0}},ul:{listStyleType:"circle",ul:{listStyleType:"disc"}},ol:{listStyleType:"decimal"},"pre, blockquote":{margin:"1em 0"},pre:{padding:"0.4em 0.6em",whiteSpace:"pre-wrap",wordWrap:"break-word",background:"rgba(150, 150, 150, 0.1)",border:"1px solid rgba(100, 100, 100, 0.2)",borderRadius:3,fontFamily:e.fontFamilyCode,code:{display:"inline",margin:0,padding:0,fontSize:"inherit",fontFamily:"inherit",background:"transparent",border:0}},blockquote:{paddingInline:"0.6em 0",paddingBlock:0,borderInlineStart:"4px solid rgba(100, 100, 100, 0.2)",opacity:.85}}),(e=>{let{componentCls:t}=e;return{"a&, a":Object.assign(Object.assign({},(0,S.operationUnit)(e)),{userSelect:"text",[`&[disabled], &${t}-disabled`]:{color:e.colorTextDisabled,cursor:"not-allowed","&:active, &:hover":{color:e.colorTextDisabled},"&:active":{pointerEvents:"none"}}})}})(e)),{[` + ${n}-expand, + ${n}-collapse, + ${n}-edit, + ${n}-copy + `]:Object.assign(Object.assign({},(0,S.operationUnit)(e)),{marginInlineStart:e.marginXXS})}),(e=>{let{componentCls:t,paddingSM:n}=e;return{"&-edit-content":{position:"relative","div&":{insetInlineStart:e.calc(e.paddingSM).mul(-1).equal(),insetBlockStart:e.calc(n).div(-2).add(1).equal(),marginBottom:e.calc(n).div(2).sub(2).equal()},[`${t}-edit-content-confirm`]:{position:"absolute",insetInlineEnd:e.calc(e.marginXS).add(2).equal(),insetBlockEnd:e.marginXS,color:e.colorIcon,fontWeight:"normal",fontSize:e.fontSize,fontStyle:"normal",pointerEvents:"none"},textarea:{margin:"0!important",MozTransition:"none",height:"1em"}}}})(e)),{[`${e.componentCls}-copy-success`]:{[` + &, + &:hover, + &:focus`]:{color:e.colorSuccess}},[`${e.componentCls}-copy-icon-only`]:{marginInlineStart:0}}),{[` + a&-ellipsis, + span&-ellipsis + `]:{display:"inline-block",maxWidth:"100%"},"&-ellipsis-single-line":{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis","a&, span&":{verticalAlign:"bottom"},"> code":{paddingBlock:0,maxWidth:"calc(100% - 1.2em)",display:"inline-block",overflow:"hidden",textOverflow:"ellipsis",verticalAlign:"bottom",boxSizing:"content-box"}},"&-ellipsis-multiple-line":{display:"-webkit-box",overflow:"hidden",WebkitLineClamp:3,WebkitBoxOrient:"vertical"}}),{"&-rtl":{direction:"rtl"}})}},()=>({titleMarginTop:"1.2em",titleMarginBottom:"0.5em"})),k=e=>{let{prefixCls:n,"aria-label":l,className:r,style:o,direction:a,maxLength:c,autoSize:s=!0,value:u,onSave:d,onCancel:p,onEnd:f,component:m,enterIcon:g=t.createElement(h,null)}=e,b=t.useRef(null),y=t.useRef(!1),v=t.useRef(null),[S,w]=t.useState(u);t.useEffect(()=>{w(u)},[u]),t.useEffect(()=>{var e;if(null==(e=b.current)?void 0:e.resizableTextArea){let{textArea:e}=b.current.resizableTextArea;e.focus();let{length:t}=e.value;e.setSelectionRange(t,t)}},[]);let j=()=>{d(S.trim())},[k,R,$]=C(n),T=(0,i.default)(n,`${n}-edit-content`,{[`${n}-rtl`]:"rtl"===a,[`${n}-${m}`]:!!m},r,R,$);return k(t.createElement("div",{className:T,style:o},t.createElement(E.default,{ref:b,maxLength:c,value:S,onChange:({target:e})=>{w(e.value.replace(/[\n\r]/g,""))},onKeyDown:({keyCode:e})=>{y.current||(v.current=e)},onKeyUp:({keyCode:e,ctrlKey:t,altKey:n,metaKey:l,shiftKey:r})=>{v.current!==e||y.current||t||n||l||r||(e===x.default.ENTER?(j(),null==f||f()):e===x.default.ESC&&p())},onCompositionStart:()=>{y.current=!0},onCompositionEnd:()=>{y.current=!1},onBlur:()=>{j()},"aria-label":l,rows:1,autoSize:s}),null!==g?(0,O.cloneElement)(g,{className:`${n}-edit-content-confirm`}):null))};var R=e.i(844343),$=e.i(175066);function T(e,n){return t.useMemo(()=>{let t=!!e;return[t,Object.assign(Object.assign({},n),t&&"object"==typeof e?e:null)]},[e])}var I=function(e,t){var n={};for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&0>t.indexOf(l)&&(n[l]=e[l]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var r=0,l=Object.getOwnPropertySymbols(e);rt.indexOf(l[r])&&Object.prototype.propertyIsEnumerable.call(e,l[r])&&(n[l[r]]=e[l[r]]);return n};let D=t.forwardRef((e,n)=>{let{prefixCls:l,component:r="article",className:o,rootClassName:a,setContentRef:c,children:s,direction:u,style:d}=e,p=I(e,["prefixCls","component","className","rootClassName","setContentRef","children","direction","style"]),{getPrefixCls:m,direction:b,className:y,style:v}=(0,g.useComponentConfig)("typography"),h=c?(0,f.composeRef)(n,c):n,x=m("typography",l),[O,E,S]=C(x),w=(0,i.default)(x,y,{[`${x}-rtl`]:"rtl"===(null!=u?u:b)},o,a,E,S),j=Object.assign(Object.assign({},v),d);return O(t.createElement(r,Object.assign({className:w,style:j,ref:h},p),s))});var P=e.i(121229),B=e.i(190144),M=e.i(739295);function H(e){return!1===e?[!1,!1]:Array.isArray(e)?e:[e]}function z(e,t,n){return!0===e||void 0===e?t:e||n&&t}let A=e=>["string","number"].includes(typeof e),W=({prefixCls:e,copied:n,locale:l,iconOnly:r,tooltips:o,icon:a,tabIndex:c,onCopy:s,loading:u})=>{let d=H(o),p=H(a),{copied:f,copy:m}=null!=l?l:{},g=n?f:m,b=z(d[+!!n],g),v="string"==typeof b?b:g;return t.createElement(y.default,{title:b},t.createElement("button",{type:"button",className:(0,i.default)(`${e}-copy`,{[`${e}-copy-success`]:n,[`${e}-copy-icon-only`]:r}),onClick:s,"aria-label":v,tabIndex:c},n?z(p[1],t.createElement(P.default,null),!0):z(p[0],u?t.createElement(M.default,null):t.createElement(B.default,null),!0)))},L=t.forwardRef(({style:e,children:n},l)=>{let r=t.useRef(null);return t.useImperativeHandle(l,()=>({isExceed:()=>{let e=r.current;return e.scrollHeight>e.clientHeight},getHeight:()=>r.current.clientHeight})),t.createElement("span",{"aria-hidden":!0,ref:r,style:Object.assign({position:"fixed",display:"block",left:0,top:0,pointerEvents:"none",backgroundColor:"rgba(255, 0, 0, 0.65)"},e)},n)});function N(e,t){let n=0,l=[];for(let r=0;rt){let e=t-n;return l.push(String(o).slice(0,e)),l}l.push(o),n=a}return e}let U={display:"-webkit-box",overflow:"hidden",WebkitBoxOrient:"vertical"};function F(e){let{enableMeasure:l,width:r,text:o,children:a,rows:i,expanded:c,miscDeps:d,onEllipsis:p}=e,f=t.useMemo(()=>(0,s.default)(o),[o]),m=t.useMemo(()=>f.reduce((e,t)=>e+(A(t)?String(t).length:1),0),[o]),g=t.useMemo(()=>a(f,!1),[o]),[b,y]=t.useState(null),v=t.useRef(null),h=t.useRef(null),x=t.useRef(null),O=t.useRef(null),E=t.useRef(null),[S,w]=t.useState(!1),[j,C]=t.useState(0),[k,R]=t.useState(0),[$,T]=t.useState(null);(0,u.default)(()=>{l&&r&&m?C(1):C(0)},[r,o,i,l,f]),(0,u.default)(()=>{var e,t,n,l;if(1===j)C(2),T(h.current&&getComputedStyle(h.current).whiteSpace);else if(2===j){let r=!!(null==(e=x.current)?void 0:e.isExceed());C(r?3:4),y(r?[0,m]:null),w(r),R(Math.max((null==(t=x.current)?void 0:t.getHeight())||0,(1===i?0:(null==(n=O.current)?void 0:n.getHeight())||0)+((null==(l=E.current)?void 0:l.getHeight())||0))+1),p(r)}},[j]);let I=b?Math.ceil((b[0]+b[1])/2):0;(0,u.default)(()=>{var e;let[t,n]=b||[0,0];if(t!==n){let l=((null==(e=v.current)?void 0:e.getHeight())||0)>k,r=I;n-t==1&&(r=l?t:n),y(l?[t,r]:[r,n])}},[b,I]);let D=t.useMemo(()=>{if(!l)return a(f,!1);if(3!==j||!b||b[0]!==b[1]){let e=a(f,!1);return[4,0].includes(j)?e:t.createElement("span",{style:Object.assign(Object.assign({},U),{WebkitLineClamp:i})},e)}return a(c?f:N(f,b[0]),S)},[c,j,b,f].concat((0,n.default)(d))),P={width:r,margin:0,padding:0,whiteSpace:"nowrap"===$?"normal":"inherit"};return t.createElement(t.Fragment,null,D,2===j&&t.createElement(t.Fragment,null,t.createElement(L,{style:Object.assign(Object.assign(Object.assign({},P),U),{WebkitLineClamp:i}),ref:x},g),t.createElement(L,{style:Object.assign(Object.assign(Object.assign({},P),U),{WebkitLineClamp:i-1}),ref:O},g),t.createElement(L,{style:Object.assign(Object.assign(Object.assign({},P),U),{WebkitLineClamp:1}),ref:E},a([],!0))),3===j&&b&&b[0]!==b[1]&&t.createElement(L,{style:Object.assign(Object.assign({},P),{top:400}),ref:v},a(N(f,I),!0)),1===j&&t.createElement("span",{style:{whiteSpace:"inherit"},ref:h}))}let q=({enableEllipsis:e,isEllipsis:n,children:l,tooltipProps:r})=>(null==r?void 0:r.title)&&e?t.createElement(y.default,Object.assign({open:!!n&&void 0},r),l):l;var X=function(e,t){var n={};for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&0>t.indexOf(l)&&(n[l]=e[l]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var r=0,l=Object.getOwnPropertySymbols(e);rt.indexOf(l[r])&&Object.prototype.propertyIsEnumerable.call(e,l[r])&&(n[l[r]]=e[l[r]]);return n};let K=["delete","mark","code","underline","strong","keyboard","italic"],V=t.forwardRef((e,l)=>{var r;let o,v,h,{prefixCls:x,className:O,style:E,type:S,disabled:w,children:j,ellipsis:C,editable:I,copyable:P,component:B,title:M}=e,H=X(e,["prefixCls","className","style","type","disabled","children","ellipsis","editable","copyable","component","title"]),{getPrefixCls:z,direction:L}=t.useContext(g.ConfigContext),[N]=(0,b.default)("Text"),U=t.useRef(null),V=t.useRef(null),_=z("typography",x),G=(0,p.default)(H,K),[J,Q]=T(I),[Y,Z]=(0,d.default)(!1,{value:Q.editing}),{triggerType:ee=["icon"]}=Q,et=e=>{var t;e&&(null==(t=Q.onStart)||t.call(Q)),Z(e)},en=(o=(0,t.useRef)(void 0),(0,t.useEffect)(()=>{o.current=Y}),o.current);(0,u.default)(()=>{var e;!Y&&en&&(null==(e=V.current)||e.focus())},[Y]);let el=e=>{null==e||e.preventDefault(),et(!0)},[er,eo]=T(P),{copied:ea,copyLoading:ei,onClick:ec}=(({copyConfig:e,children:n})=>{let[l,r]=t.useState(!1),[o,a]=t.useState(!1),i=t.useRef(null),c=()=>{i.current&&clearTimeout(i.current)},s={};e.format&&(s.format=e.format),t.useEffect(()=>c,[]);let u=(0,$.default)(t=>{var l,o,u,d;return l=void 0,o=void 0,u=void 0,d=function*(){var l;null==t||t.preventDefault(),null==t||t.stopPropagation(),a(!0);try{let o="function"==typeof e.text?yield e.text():e.text;(0,R.default)(o||((e,t=!1)=>t&&null==e?[]:Array.isArray(e)?e:[e])(n,!0).join("")||"",s),a(!1),r(!0),c(),i.current=setTimeout(()=>{r(!1)},3e3),null==(l=e.onCopy)||l.call(e,t)}catch(e){throw a(!1),e}},new(u||(u=Promise))(function(e,t){function n(e){try{a(d.next(e))}catch(e){t(e)}}function r(e){try{a(d.throw(e))}catch(e){t(e)}}function a(t){var l;t.done?e(t.value):((l=t.value)instanceof u?l:new u(function(e){e(l)})).then(n,r)}a((d=d.apply(l,o||[])).next())})});return{copied:l,copyLoading:o,onClick:u}})({copyConfig:eo,children:j}),[es,eu]=t.useState(!1),[ed,ep]=t.useState(!1),[ef,em]=t.useState(!1),[eg,eb]=t.useState(!1),[ey,ev]=t.useState(!0),[eh,ex]=T(C,{expandable:!1,symbol:e=>e?null==N?void 0:N.collapse:null==N?void 0:N.expand}),[eO,eE]=(0,d.default)(ex.defaultExpanded||!1,{value:ex.expanded}),eS=eh&&(!eO||"collapsible"===ex.expandable),{rows:ew=1}=ex,ej=t.useMemo(()=>eS&&(void 0!==ex.suffix||ex.onEllipsis||ex.expandable||J||er),[eS,ex,J,er]);(0,u.default)(()=>{eh&&!ej&&(eu((0,m.isStyleSupport)("webkitLineClamp")),ep((0,m.isStyleSupport)("textOverflow")))},[ej,eh]);let[eC,ek]=t.useState(eS),eR=t.useMemo(()=>!ej&&(1===ew?ed:es),[ej,ed,es]);(0,u.default)(()=>{ek(eR&&eS)},[eR,eS]);let e$=eS&&(eC?eg:ef),eT=eS&&1===ew&&eC,eI=eS&&ew>1&&eC,[eD,eP]=t.useState(0),eB=e=>{var t;em(e),ef!==e&&(null==(t=ex.onEllipsis)||t.call(ex,e))};t.useEffect(()=>{let e=U.current;if(eh&&eC&&e){let t,n,l,r=(t=document.createElement("em"),e.appendChild(t),n=e.getBoundingClientRect(),l=t.getBoundingClientRect(),e.removeChild(t),n.left>l.left||l.right>n.right||n.top>l.top||l.bottom>n.bottom);eg!==r&&eb(r)}},[eh,eC,j,eI,ey,eD]),t.useEffect(()=>{let e=U.current;if("u"{ev(!!e.offsetParent)});return t.observe(e),()=>{t.disconnect()}},[eC,eS]);let eM=(v=ex.tooltip,h=Q.text,(0,t.useMemo)(()=>!0===v?{title:null!=h?h:j}:(0,t.isValidElement)(v)?{title:v}:"object"==typeof v?Object.assign({title:null!=h?h:j},v):{title:v},[v,h,j])),eH=t.useMemo(()=>{if(eh&&!eC)return[Q.text,j,M,eM.title].find(A)},[eh,eC,M,eM.title,e$]);return Y?t.createElement(k,{value:null!=(r=Q.text)?r:"string"==typeof j?j:"",onSave:e=>{var t;null==(t=Q.onChange)||t.call(Q,e),et(!1)},onCancel:()=>{var e;null==(e=Q.onCancel)||e.call(Q),et(!1)},onEnd:Q.onEnd,prefixCls:_,className:O,style:E,direction:L,component:B,maxLength:Q.maxLength,autoSize:Q.autoSize,enterIcon:Q.enterIcon}):t.createElement(c.default,{onResize:({offsetWidth:e})=>{eP(e)},disabled:!eS},r=>t.createElement(q,{tooltipProps:eM,enableEllipsis:eS,isEllipsis:e$},t.createElement(D,Object.assign({className:(0,i.default)({[`${_}-${S}`]:S,[`${_}-disabled`]:w,[`${_}-ellipsis`]:eh,[`${_}-ellipsis-single-line`]:eT,[`${_}-ellipsis-multiple-line`]:eI},O),prefixCls:x,style:Object.assign(Object.assign({},E),{WebkitLineClamp:eI?ew:void 0}),component:B,ref:(0,f.composeRef)(r,U,l),direction:L,onClick:ee.includes("text")?el:void 0,"aria-label":null==eH?void 0:eH.toString(),title:M},G),t.createElement(F,{enableMeasure:eS&&!eC,text:j,rows:ew,width:eD,onEllipsis:eB,expanded:eO,miscDeps:[ea,eO,ei,J,er,N].concat((0,n.default)(K.map(t=>e[t])))},(n,l)=>{let r;return function({mark:e,code:n,underline:l,delete:r,strong:o,keyboard:a,italic:i},c){let s=c;function u(e,n){n&&(s=t.createElement(e,{},s))}return u("strong",o),u("u",l),u("del",r),u("code",n),u("mark",e),u("kbd",a),u("i",i),s}(e,t.createElement(t.Fragment,null,n.length>0&&l&&!eO&&eH?t.createElement("span",{key:"show-content","aria-hidden":!0},n):n,[(r=l)&&!eO&&t.createElement("span",{"aria-hidden":!0,key:"ellipsis"},"..."),ex.suffix,[r&&(()=>{let{expandable:e,symbol:n}=ex;return e?t.createElement("button",{type:"button",key:"expand",className:`${_}-${eO?"collapse":"expand"}`,onClick:e=>{var t,n;eE((t={expanded:!eO}).expanded),null==(n=ex.onExpand)||n.call(ex,e,t)},"aria-label":eO?N.collapse:null==N?void 0:N.expand},"function"==typeof n?n(eO):n):null})(),(()=>{if(!J)return;let{icon:e,tooltip:n,tabIndex:l}=Q,r=(0,s.default)(n)[0]||(null==N?void 0:N.edit),o="string"==typeof r?r:"";return ee.includes("icon")?t.createElement(y.default,{key:"edit",title:!1===n?"":r},t.createElement("button",{type:"button",ref:V,className:`${_}-edit`,onClick:el,"aria-label":o,tabIndex:l},e||t.createElement(a,{role:"button"}))):null})(),er?t.createElement(W,Object.assign({key:"copy"},eo,{prefixCls:_,copied:ea,locale:N,onCopy:ec,loading:ei,iconOnly:null==j})):null]]))}))))});var _=function(e,t){var n={};for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&0>t.indexOf(l)&&(n[l]=e[l]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var r=0,l=Object.getOwnPropertySymbols(e);rt.indexOf(l[r])&&Object.prototype.propertyIsEnumerable.call(e,l[r])&&(n[l[r]]=e[l[r]]);return n};let G=t.forwardRef((e,n)=>{let{ellipsis:l,rel:r,children:o,navigate:a}=e,i=_(e,["ellipsis","rel","children","navigate"]),c=Object.assign(Object.assign({},i),{rel:void 0===r&&"_blank"===i.target?"noopener noreferrer":r});return t.createElement(V,Object.assign({},c,{ref:n,ellipsis:!!l,component:"a"}),o)});var J=function(e,t){var n={};for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&0>t.indexOf(l)&&(n[l]=e[l]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var r=0,l=Object.getOwnPropertySymbols(e);rt.indexOf(l[r])&&Object.prototype.propertyIsEnumerable.call(e,l[r])&&(n[l[r]]=e[l[r]]);return n};let Q=t.forwardRef((e,n)=>{let{children:l}=e,r=J(e,["children"]);return t.createElement(V,Object.assign({ref:n},r,{component:"div"}),l)});var Y=function(e,t){var n={};for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&0>t.indexOf(l)&&(n[l]=e[l]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var r=0,l=Object.getOwnPropertySymbols(e);rt.indexOf(l[r])&&Object.prototype.propertyIsEnumerable.call(e,l[r])&&(n[l[r]]=e[l[r]]);return n};let Z=t.forwardRef((e,n)=>{let{ellipsis:l,children:r}=e,o=Y(e,["ellipsis","children"]),a=t.useMemo(()=>l&&"object"==typeof l?(0,p.default)(l,["expandable","rows"]):l,[l]);return t.createElement(V,Object.assign({ref:n},o,{ellipsis:a,component:"span"}),r)});var ee=function(e,t){var n={};for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&0>t.indexOf(l)&&(n[l]=e[l]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var r=0,l=Object.getOwnPropertySymbols(e);rt.indexOf(l[r])&&Object.prototype.propertyIsEnumerable.call(e,l[r])&&(n[l[r]]=e[l[r]]);return n};let et=[1,2,3,4,5],en=t.forwardRef((e,n)=>{let{level:l=1,children:r}=e,o=ee(e,["level","children"]),a=et.includes(l)?`h${l}`:"h1";return t.createElement(V,Object.assign({ref:n},o,{component:a}),r)});e.s(["default",0,en],335771),D.Text=Z,D.Link=G,D.Title=en,D.Paragraph=Q,e.s(["Typography",0,D],898586)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/0d535cc95398f09e.js b/litellm/proxy/_experimental/out/_next/static/chunks/0d535cc95398f09e.js new file mode 100644 index 00000000000..67dc5347393 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/0d535cc95398f09e.js @@ -0,0 +1,420 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,326373,e=>{"use strict";var t=e.i(21539);e.s(["Dropdown",()=>t.default])},879664,e=>{"use strict";let t=(0,e.i(475254).default)("info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);e.s(["default",()=>t])},798496,e=>{"use strict";var t=e.i(843476),i=e.i(152990),o=e.i(682830),n=e.i(271645),a=e.i(269200),r=e.i(427612),l=e.i(64848),s=e.i(942232),d=e.i(496020),c=e.i(977572),u=e.i(94629),p=e.i(360820),m=e.i(871943);function g({data:e=[],columns:g,isLoading:f=!1,defaultSorting:h=[],pagination:b,onPaginationChange:_,enablePagination:y=!1,onRowClick:x}){let[v,w]=n.default.useState(h),[S]=n.default.useState("onChange"),[j,C]=n.default.useState({}),[$,k]=n.default.useState({}),O=(0,i.useReactTable)({data:e,columns:g,state:{sorting:v,columnSizing:j,columnVisibility:$,...y&&b?{pagination:b}:{}},columnResizeMode:S,onSortingChange:w,onColumnSizingChange:C,onColumnVisibilityChange:k,...y&&_?{onPaginationChange:_}:{},getCoreRowModel:(0,o.getCoreRowModel)(),getSortedRowModel:(0,o.getSortedRowModel)(),...y?{getPaginationRowModel:(0,o.getPaginationRowModel)()}:{},enableSorting:!0,enableColumnResizing:!0,defaultColumn:{minSize:40,maxSize:500}});return(0,t.jsx)("div",{className:"rounded-lg custom-border relative",children:(0,t.jsx)("div",{className:"overflow-x-auto",children:(0,t.jsx)("div",{className:"relative min-w-full",children:(0,t.jsxs)(a.Table,{className:"[&_td]:py-2 [&_th]:py-2",style:{width:O.getTotalSize(),minWidth:"100%",tableLayout:"fixed"},children:[(0,t.jsx)(r.TableHead,{children:O.getHeaderGroups().map(e=>(0,t.jsx)(d.TableRow,{children:e.headers.map(e=>(0,t.jsxs)(l.TableHeaderCell,{className:`py-1 h-8 relative ${"actions"===e.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)] w-[120px] ml-8":""} ${e.column.columnDef.meta?.className||""}`,style:{width:"actions"===e.id?120:e.getSize(),position:"actions"===e.id?"sticky":"relative",right:"actions"===e.id?0:"auto"},onClick:e.column.getCanSort()?e.column.getToggleSortingHandler():void 0,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,i.flexRender)(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)(p.ChevronUpIcon,{className:"h-4 w-4 text-blue-500"}),desc:(0,t.jsx)(m.ChevronDownIcon,{className:"h-4 w-4 text-blue-500"})})[e.column.getIsSorted()]:(0,t.jsx)(u.SwitchVerticalIcon,{className:"h-4 w-4 text-gray-400"})})]}),e.column.getCanResize()&&(0,t.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 ${e.column.getIsResizing()?"bg-blue-500":"hover:bg-blue-200"}`})]},e.id))},e.id))}),(0,t.jsx)(s.TableBody,{children:f?(0,t.jsx)(d.TableRow,{children:(0,t.jsx)(c.TableCell,{colSpan:g.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"🚅 Loading models..."})})})}):O.getRowModel().rows.length>0?O.getRowModel().rows.map(e=>(0,t.jsx)(d.TableRow,{onClick:()=>x?.(e.original),className:x?"cursor-pointer hover:bg-gray-50":"",children:e.getVisibleCells().map(e=>(0,t.jsx)(c.TableCell,{className:`py-0.5 overflow-hidden ${"actions"===e.column.id?"sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)] w-[120px] ml-8":""} ${e.column.columnDef.meta?.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,i.flexRender)(e.column.columnDef.cell,e.getContext())},e.id))},e.id)):(0,t.jsx)(d.TableRow,{children:(0,t.jsx)(c.TableCell,{colSpan:g.length,className:"h-8 text-center",children:(0,t.jsx)("div",{className:"text-center text-gray-500",children:(0,t.jsx)("p",{children:"No models found"})})})})})]})})})})}e.s(["ModelDataTable",()=>g])},339019,865361,e=>{"use strict";var t,i,o=((t={}).AUDIO_SPEECH="audio_speech",t.AUDIO_TRANSCRIPTION="audio_transcription",t.IMAGE_GENERATION="image_generation",t.VIDEO_GENERATION="video_generation",t.CHAT="chat",t.RESPONSES="responses",t.IMAGE_EDITS="image_edits",t.ANTHROPIC_MESSAGES="anthropic_messages",t.EMBEDDING="embedding",t),n=((i={}).IMAGE="image",i.VIDEO="video",i.CHAT="chat",i.RESPONSES="responses",i.IMAGE_EDITS="image_edits",i.ANTHROPIC_MESSAGES="anthropic_messages",i.EMBEDDINGS="embeddings",i.SPEECH="speech",i.TRANSCRIPTION="transcription",i.A2A_AGENTS="a2a_agents",i.MCP="mcp",i.REALTIME="realtime",i.INTERACTIONS="interactions",i);let a={image_generation:"image",video_generation:"video",chat:"chat",responses:"responses",image_edits:"image_edits",anthropic_messages:"anthropic_messages",audio_speech:"speech",audio_transcription:"transcription",embedding:"embeddings"};e.s(["EndpointType",()=>n,"getEndpointType",0,e=>{if(console.log("getEndpointType:",e),Object.values(o).includes(e)){let t=a[e];return console.log("endpointType:",t),t}return"chat"}],865361),e.s(["generateCodeSnippet",0,e=>{let t,{apiKeySource:i,accessToken:o,apiKey:a,inputMessage:r,chatHistory:l,selectedTags:s,selectedVectorStores:d,selectedGuardrails:c,selectedPolicies:u,selectedMCPServers:p,mcpServers:m,mcpServerToolRestrictions:g,selectedVoice:f,endpointType:h,selectedModel:b,selectedSdk:_,proxySettings:y}=e,x="session"===i?o:a,v=window.location.origin,w=y?.LITELLM_UI_API_DOC_BASE_URL;w&&w.trim()?v=w:y?.PROXY_BASE_URL&&(v=y.PROXY_BASE_URL);let S=r||"Your prompt here",j=S.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n"),C=l.filter(e=>!e.isImage).map(({role:e,content:t})=>({role:e,content:t})),$={};s.length>0&&($.tags=s),d.length>0&&($.vector_stores=d),c.length>0&&($.guardrails=c),u.length>0&&($.policies=u);let k=b||"your-model-name",O="azure"===_?`import openai + +client = openai.AzureOpenAI( + api_key="${x||"YOUR_LITELLM_API_KEY"}", + azure_endpoint="${v}", + api_version="2024-02-01" +)`:`import openai + +client = openai.OpenAI( + api_key="${x||"YOUR_LITELLM_API_KEY"}", + base_url="${v}" +)`;switch(h){case n.CHAT:{let e=Object.keys($).length>0,i="";if(e){let e=JSON.stringify({metadata:$},null,2).split("\n").map(e=>" ".repeat(4)+e).join("\n").trim();i=`, + extra_body=${e}`}let o=C.length>0?C:[{role:"user",content:S}];t=` +import base64 + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Example with text only +response = client.chat.completions.create( + model="${k}", + messages=${JSON.stringify(o,null,4)}${i} +) + +print(response) + +# Example with image or PDF (uncomment and provide file path to use) +# base64_file = encode_image("path/to/your/file.jpg") # or .pdf +# response_with_file = client.chat.completions.create( +# model="${k}", +# messages=[ +# { +# "role": "user", +# "content": [ +# { +# "type": "text", +# "text": "${j}" +# }, +# { +# "type": "image_url", +# "image_url": { +# "url": f"data:image/jpeg;base64,{base64_file}" # or data:application/pdf;base64,{base64_file} +# } +# } +# ] +# } +# ]${i} +# ) +# print(response_with_file) +`;break}case n.RESPONSES:{let e=Object.keys($).length>0,i="";if(e){let e=JSON.stringify({metadata:$},null,2).split("\n").map(e=>" ".repeat(4)+e).join("\n").trim();i=`, + extra_body=${e}`}let o=C.length>0?C:[{role:"user",content:S}];t=` +import base64 + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Example with text only +response = client.responses.create( + model="${k}", + input=${JSON.stringify(o,null,4)}${i} +) + +print(response.output_text) + +# Example with image or PDF (uncomment and provide file path to use) +# base64_file = encode_image("path/to/your/file.jpg") # or .pdf +# response_with_file = client.responses.create( +# model="${k}", +# input=[ +# { +# "role": "user", +# "content": [ +# {"type": "input_text", "text": "${j}"}, +# { +# "type": "input_image", +# "image_url": f"data:image/jpeg;base64,{base64_file}", # or data:application/pdf;base64,{base64_file} +# }, +# ], +# } +# ]${i} +# ) +# print(response_with_file.output_text) +`;break}case n.IMAGE:t="azure"===_?` +# NOTE: The Azure SDK does not have a direct equivalent to the multi-modal 'responses.create' method shown for OpenAI. +# This snippet uses 'client.images.generate' and will create a new image based on your prompt. +# It does not use the uploaded image, as 'client.images.generate' does not support image inputs in this context. +import os +import requests +import json +import time +from PIL import Image + +result = client.images.generate( + model="${k}", + prompt="${r}", + n=1 +) + +json_response = json.loads(result.model_dump_json()) + +# Set the directory for the stored image +image_dir = os.path.join(os.curdir, 'images') + +# If the directory doesn't exist, create it +if not os.path.isdir(image_dir): + os.mkdir(image_dir) + +# Initialize the image path +image_filename = f"generated_image_{int(time.time())}.png" +image_path = os.path.join(image_dir, image_filename) + +try: + # Retrieve the generated image + if json_response.get("data") && len(json_response["data"]) > 0 && json_response["data"][0].get("url"): + image_url = json_response["data"][0]["url"] + generated_image = requests.get(image_url).content + with open(image_path, "wb") as image_file: + image_file.write(generated_image) + + print(f"Image saved to {image_path}") + # Display the image + image = Image.open(image_path) + image.show() + else: + print("Could not find image URL in response.") + print("Full response:", json_response) +except Exception as e: + print(f"An error occurred: {e}") + print("Full response:", json_response) +`:` +import base64 +import os +import time +import json +from PIL import Image +import requests + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Helper function to create a file (simplified for this example) +def create_file(image_path): + # In a real implementation, this would upload the file to OpenAI + # For this example, we'll just return a placeholder ID + return f"file_{os.path.basename(image_path).replace('.', '_')}" + +# The prompt entered by the user +prompt = "${j}" + +# Encode images to base64 +base64_image1 = encode_image("body-lotion.png") +base64_image2 = encode_image("soap.png") + +# Create file IDs +file_id1 = create_file("body-lotion.png") +file_id2 = create_file("incense-kit.png") + +response = client.responses.create( + model="${k}", + input=[ + { + "role": "user", + "content": [ + {"type": "input_text", "text": prompt}, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image1}", + }, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image2}", + }, + { + "type": "input_image", + "file_id": file_id1, + }, + { + "type": "input_image", + "file_id": file_id2, + } + ], + } + ], + tools=[{"type": "image_generation"}], +) + +# Process the response +image_generation_calls = [ + output + for output in response.output + if output.type == "image_generation_call" +] + +image_data = [output.result for output in image_generation_calls] + +if image_data: + image_base64 = image_data[0] + image_filename = f"edited_image_{int(time.time())}.png" + with open(image_filename, "wb") as f: + f.write(base64.b64decode(image_base64)) + print(f"Image saved to {image_filename}") +else: + # If no image is generated, there might be a text response with an explanation + text_response = [output.text for output in response.output if hasattr(output, 'text')] + if text_response: + print("No image generated. Model response:") + print("\\n".join(text_response)) + else: + print("No image data found in response.") + print("Full response for debugging:") + print(response) +`;break;case n.IMAGE_EDITS:t="azure"===_?` +import base64 +import os +import time +import json +from PIL import Image +import requests + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# The prompt entered by the user +prompt = "${j}" + +# Encode images to base64 +base64_image1 = encode_image("body-lotion.png") +base64_image2 = encode_image("soap.png") + +# Create file IDs +file_id1 = create_file("body-lotion.png") +file_id2 = create_file("incense-kit.png") + +response = client.responses.create( + model="${k}", + input=[ + { + "role": "user", + "content": [ + {"type": "input_text", "text": prompt}, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image1}", + }, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image2}", + }, + { + "type": "input_image", + "file_id": file_id1, + }, + { + "type": "input_image", + "file_id": file_id2, + } + ], + } + ], + tools=[{"type": "image_generation"}], +) + +# Process the response +image_generation_calls = [ + output + for output in response.output + if output.type == "image_generation_call" +] + +image_data = [output.result for output in image_generation_calls] + +if image_data: + image_base64 = image_data[0] + image_filename = f"edited_image_{int(time.time())}.png" + with open(image_filename, "wb") as f: + f.write(base64.b64decode(image_base64)) + print(f"Image saved to {image_filename}") +else: + # If no image is generated, there might be a text response with an explanation + text_response = [output.text for output in response.output if hasattr(output, 'text')] + if text_response: + print("No image generated. Model response:") + print("\\n".join(text_response)) + else: + print("No image data found in response.") + print("Full response for debugging:") + print(response) +`:` +import base64 +import os +import time + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Helper function to create a file (simplified for this example) +def create_file(image_path): + # In a real implementation, this would upload the file to OpenAI + # For this example, we'll just return a placeholder ID + return f"file_{os.path.basename(image_path).replace('.', '_')}" + +# The prompt entered by the user +prompt = "${j}" + +# Encode images to base64 +base64_image1 = encode_image("body-lotion.png") +base64_image2 = encode_image("soap.png") + +# Create file IDs +file_id1 = create_file("body-lotion.png") +file_id2 = create_file("incense-kit.png") + +response = client.responses.create( + model="${k}", + input=[ + { + "role": "user", + "content": [ + {"type": "input_text", "text": prompt}, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image1}", + }, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image2}", + }, + { + "type": "input_image", + "file_id": file_id1, + }, + { + "type": "input_image", + "file_id": file_id2, + } + ], + } + ], + tools=[{"type": "image_generation"}], +) + +# Process the response +image_generation_calls = [ + output + for output in response.output + if output.type == "image_generation_call" +] + +image_data = [output.result for output in image_generation_calls] + +if image_data: + image_base64 = image_data[0] + image_filename = f"edited_image_{int(time.time())}.png" + with open(image_filename, "wb") as f: + f.write(base64.b64decode(image_base64)) + print(f"Image saved to {image_filename}") +else: + # If no image is generated, there might be a text response with an explanation + text_response = [output.text for output in response.output if hasattr(output, 'text')] + if text_response: + print("No image generated. Model response:") + print("\\n".join(text_response)) + else: + print("No image data found in response.") + print("Full response for debugging:") + print(response) +`;break;case n.EMBEDDINGS:t=` +response = client.embeddings.create( + input="${r||"Your string here"}", + model="${k}", + encoding_format="base64" # or "float" +) + +print(response.data[0].embedding) +`;break;case n.TRANSCRIPTION:t=` +# Open the audio file +audio_file = open("path/to/your/audio/file.mp3", "rb") + +# Make the transcription request +response = client.audio.transcriptions.create( + model="${k}", + file=audio_file${r?`, + prompt="${r.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:""} +) + +print(response.text) +`;break;case n.SPEECH:t=` +# Make the text-to-speech request +response = client.audio.speech.create( + model="${k}", + input="${r||"Your text to convert to speech here"}", + voice="${f}" # Options: alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer +) + +# Save the audio to a file +output_filename = "output_speech.mp3" +response.stream_to_file(output_filename) +print(f"Audio saved to {output_filename}") + +# Optional: Customize response format and speed +# response = client.audio.speech.create( +# model="${k}", +# input="${r||"Your text to convert to speech here"}", +# voice="alloy", +# response_format="mp3", # Options: mp3, opus, aac, flac, wav, pcm +# speed=1.0 # Range: 0.25 to 4.0 +# ) +# response.stream_to_file("output_speech.mp3") +`;break;default:t="\n# Code generation for this endpoint is not implemented yet."}return`${O} +${t}`}],339019)},596239,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let o={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M574 665.4a8.03 8.03 0 00-11.3 0L446.5 781.6c-53.8 53.8-144.6 59.5-204 0-59.5-59.5-53.8-150.2 0-204l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3l-39.8-39.8a8.03 8.03 0 00-11.3 0L191.4 526.5c-84.6 84.6-84.6 221.5 0 306s221.5 84.6 306 0l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3L574 665.4zm258.6-474c-84.6-84.6-221.5-84.6-306 0L410.3 307.6a8.03 8.03 0 000 11.3l39.7 39.7c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c53.8-53.8 144.6-59.5 204 0 59.5 59.5 53.8 150.2 0 204L665.3 562.6a8.03 8.03 0 000 11.3l39.8 39.8c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c84.5-84.6 84.5-221.5 0-306.1zM610.1 372.3a8.03 8.03 0 00-11.3 0L372.3 598.7a8.03 8.03 0 000 11.3l39.6 39.6c3.1 3.1 8.2 3.1 11.3 0l226.4-226.4c3.1-3.1 3.1-8.2 0-11.3l-39.5-39.6z"}}]},name:"link",theme:"outlined"};var n=e.i(9583),a=i.forwardRef(function(e,a){return i.createElement(n.default,(0,t.default)({},e,{ref:a,icon:o}))});e.s(["LinkOutlined",0,a],596239)},652272,209261,e=>{"use strict";var t=e.i(843476),i=e.i(271645),o=e.i(447566),n=e.i(166406),a=e.i(492030),r=e.i(596239);let l=e=>"github"===e.source.source&&e.source.repo?`/plugin marketplace add ${e.source.repo}`:"url"===e.source.source&&e.source.url?`/plugin marketplace add ${e.source.url}`:`/plugin marketplace add ${e.name}`;e.s(["formatInstallCommand",0,l,"getCategoryBadgeColor",0,e=>{if(!e)return"gray";let t=e.toLowerCase();if(t.includes("development")||t.includes("dev"))return"blue";if(t.includes("productivity")||t.includes("workflow"))return"green";if(t.includes("learning")||t.includes("education"))return"purple";if(t.includes("security")||t.includes("safety"))return"red";if(t.includes("data")||t.includes("analytics"))return"orange";else if(t.includes("integration")||t.includes("api"))return"yellow";return"gray"},"isValidEmail",0,e=>!e||/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e),"isValidSemanticVersion",0,e=>!e||/^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(e),"isValidUrl",0,e=>{if(!e)return!0;try{return new URL(e),!0}catch{return!1}},"parseKeywords",0,e=>e&&""!==e.trim()?e.split(",").map(e=>e.trim()).filter(e=>""!==e):[],"validatePluginName",0,e=>!!e&&""!==e.trim()&&/^[a-z0-9-]+$/.test(e)],209261),e.s(["default",0,({skill:e,onBack:s})=>{let d,[c,u]=(0,i.useState)("overview"),[p,m]=(0,i.useState)(null),g=(e,t)=>{navigator.clipboard.writeText(e),m(t),setTimeout(()=>m(null),2e3)},f="github"===(d=e.source).source&&d.repo?`https://github.com/${d.repo}`:"git-subdir"===d.source&&d.url?d.path?`${d.url}/tree/main/${d.path}`:d.url:"url"===d.source&&d.url?d.url:null,h=l(e),b=[...e.category?[{property:"Category",value:e.category}]:[],...e.domain?[{property:"Domain",value:e.domain}]:[],...e.namespace?[{property:"Namespace",value:e.namespace}]:[],...e.version?[{property:"Version",value:e.version}]:[],...e.author?.name?[{property:"Author",value:e.author.name}]:[],...e.created_at?[{property:"Added",value:new Date(e.created_at).toLocaleDateString()}]:[]];return(0,t.jsxs)("div",{style:{padding:"24px 32px 24px 0"},children:[(0,t.jsxs)("div",{onClick:s,style:{display:"inline-flex",alignItems:"center",gap:6,color:"#5f6368",cursor:"pointer",fontSize:14,marginBottom:24},children:[(0,t.jsx)(o.ArrowLeftOutlined,{style:{fontSize:11}}),(0,t.jsx)("span",{children:"Skills"})]}),(0,t.jsxs)("div",{style:{marginBottom:8},children:[(0,t.jsx)("h1",{style:{fontSize:28,fontWeight:400,color:"#202124",margin:0,lineHeight:1.2},children:e.name}),e.description&&(0,t.jsx)("p",{style:{fontSize:14,color:"#5f6368",margin:"8px 0 0 0",lineHeight:1.6},children:e.description})]}),(0,t.jsx)("div",{style:{borderBottom:"1px solid #dadce0",marginBottom:28,marginTop:24},children:(0,t.jsx)("div",{style:{display:"flex",gap:0},children:[{key:"overview",label:"Overview"},{key:"usage",label:"How to Use"}].map(e=>(0,t.jsx)("div",{onClick:()=>u(e.key),style:{padding:"12px 20px",fontSize:14,color:c===e.key?"#1a73e8":"#5f6368",borderBottom:c===e.key?"3px solid #1a73e8":"3px solid transparent",cursor:"pointer",fontWeight:c===e.key?500:400,marginBottom:-1},children:e.label},e.key))})}),"overview"===c&&(0,t.jsxs)("div",{style:{display:"flex",gap:64},children:[(0,t.jsxs)("div",{style:{flex:1,minWidth:0},children:[(0,t.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 4px 0"},children:"Skill Details"}),(0,t.jsx)("p",{style:{fontSize:13,color:"#5f6368",margin:"0 0 16px 0"},children:"Metadata registered with this skill"}),(0,t.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:14},children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{style:{borderBottom:"1px solid #dadce0"},children:[(0,t.jsx)("th",{style:{textAlign:"left",padding:"12px 0",color:"#5f6368",fontWeight:500,width:160},children:"Property"}),(0,t.jsx)("th",{style:{textAlign:"left",padding:"12px 0",color:"#5f6368",fontWeight:500},children:e.name})]})}),(0,t.jsx)("tbody",{children:b.map((e,i)=>(0,t.jsxs)("tr",{style:{borderBottom:"1px solid #f1f3f4"},children:[(0,t.jsx)("td",{style:{padding:"12px 0",color:"#3c4043"},children:e.property}),(0,t.jsx)("td",{style:{padding:"12px 0",color:"#202124"},children:e.value})]},i))})]})]}),(0,t.jsxs)("div",{style:{width:240,flexShrink:0},children:[(0,t.jsxs)("div",{style:{marginBottom:24},children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Status"}),(0,t.jsx)("span",{style:{fontSize:12,padding:"3px 10px",borderRadius:12,backgroundColor:e.enabled?"#e6f4ea":"#f1f3f4",color:e.enabled?"#137333":"#5f6368",fontWeight:500},children:e.enabled?"Public":"Draft"})]}),f&&(0,t.jsxs)("div",{style:{marginBottom:24},children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Source"}),(0,t.jsxs)("a",{href:f,target:"_blank",rel:"noopener noreferrer",style:{fontSize:13,color:"#1a73e8",wordBreak:"break-all",display:"flex",alignItems:"center",gap:4},children:[f.replace("https://",""),(0,t.jsx)(r.LinkOutlined,{style:{fontSize:11,flexShrink:0}})]})]}),e.keywords&&e.keywords.length>0&&(0,t.jsxs)("div",{style:{marginBottom:24},children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:8},children:"Tags"}),(0,t.jsx)("div",{style:{display:"flex",flexWrap:"wrap",gap:6},children:e.keywords.map(e=>(0,t.jsx)("span",{style:{fontSize:12,padding:"4px 12px",borderRadius:16,border:"1px solid #dadce0",color:"#3c4043",backgroundColor:"#fff"},children:e},e))})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Skill ID"}),(0,t.jsx)("div",{style:{fontSize:12,fontFamily:"monospace",color:"#3c4043",wordBreak:"break-all"},children:e.id})]})]})]}),"usage"===c&&(0,t.jsxs)("div",{style:{maxWidth:640},children:[(0,t.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 8px 0"},children:"Using this skill"}),(0,t.jsx)("p",{style:{fontSize:14,color:"#5f6368",margin:"0 0 24px 0",lineHeight:1.6},children:"Once your proxy is set as a marketplace, enable this skill in Claude Code with one command:"}),(0,t.jsxs)("div",{style:{border:"1px solid #dadce0",borderRadius:8,overflow:"hidden",marginBottom:24},children:[(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 16px",backgroundColor:"#f8f9fa",borderBottom:"1px solid #dadce0"},children:[(0,t.jsx)("span",{style:{fontSize:13,color:"#3c4043",fontWeight:500},children:"Run in Claude Code"}),(0,t.jsxs)("button",{onClick:()=>g(h,"install"),style:{display:"flex",alignItems:"center",gap:4,fontSize:12,color:"install"===p?"#137333":"#1a73e8",background:"none",border:"none",cursor:"pointer",padding:0},children:["install"===p?(0,t.jsx)(a.CheckOutlined,{}):(0,t.jsx)(n.CopyOutlined,{}),"install"===p?"Copied":"Copy"]})]}),(0,t.jsx)("pre",{style:{margin:0,padding:"14px 16px",fontSize:14,fontFamily:"monospace",color:"#202124",backgroundColor:"#fff"},children:h})]}),(0,t.jsxs)("p",{style:{fontSize:13,color:"#5f6368",lineHeight:1.6,margin:0},children:["Don't have the marketplace configured yet?"," ",(0,t.jsx)("span",{onClick:()=>u("setup"),style:{color:"#1a73e8",cursor:"pointer"},children:"See one-time setup →"})]})]}),"setup"===c&&(0,t.jsxs)("div",{style:{maxWidth:640},children:[(0,t.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 8px 0"},children:"One-time marketplace setup"}),(0,t.jsxs)("p",{style:{fontSize:14,color:"#5f6368",margin:"0 0 24px 0",lineHeight:1.6},children:["Add this to"," ",(0,t.jsx)("code",{style:{fontSize:13,backgroundColor:"#f1f3f4",padding:"1px 6px",borderRadius:4},children:"~/.claude/settings.json"})," ","to point Claude Code at your proxy:"]}),(0,t.jsxs)("div",{style:{border:"1px solid #dadce0",borderRadius:8,overflow:"hidden"},children:[(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 16px",backgroundColor:"#f8f9fa",borderBottom:"1px solid #dadce0"},children:[(0,t.jsx)("span",{style:{fontSize:13,color:"#3c4043",fontWeight:500},children:"~/.claude/settings.json"}),(0,t.jsxs)("button",{onClick:()=>{g(JSON.stringify({extraKnownMarketplaces:{"my-org":{source:"url",url:`${window.location.origin}/claude-code/marketplace.json`}}},null,2),"settings")},style:{display:"flex",alignItems:"center",gap:4,fontSize:12,color:"settings"===p?"#137333":"#1a73e8",background:"none",border:"none",cursor:"pointer",padding:0},children:["settings"===p?(0,t.jsx)(a.CheckOutlined,{}):(0,t.jsx)(n.CopyOutlined,{}),"settings"===p?"Copied":"Copy"]})]}),(0,t.jsx)("pre",{style:{margin:0,padding:"14px 16px",fontSize:13,fontFamily:"monospace",color:"#202124",backgroundColor:"#fff"},children:JSON.stringify({extraKnownMarketplaces:{"my-org":{source:"url",url:`${window.location.origin}/claude-code/marketplace.json`}}},null,2)})]})]})]})}],652272)},602073,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let 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"};var n=e.i(9583),a=i.forwardRef(function(e,a){return i.createElement(n.default,(0,t.default)({},e,{ref:a,icon:o}))});e.s(["SafetyOutlined",0,a],602073)},818581,(e,t,i)=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0}),Object.defineProperty(i,"useMergedRef",{enumerable:!0,get:function(){return n}});let o=e.r(271645);function n(e,t){let i=(0,o.useRef)(null),n=(0,o.useRef)(null);return(0,o.useCallback)(o=>{if(null===o){let e=i.current;e&&(i.current=null,e());let t=n.current;t&&(n.current=null,t())}else e&&(i.current=a(e,o)),t&&(n.current=a(t,o))},[e,t])}function a(e,t){if("function"!=typeof e)return e.current=t,()=>{e.current=null};{let i=e(t);return"function"==typeof i?i:()=>e(null)}}("function"==typeof i.default||"object"==typeof i.default&&null!==i.default)&&void 0===i.default.__esModule&&(Object.defineProperty(i.default,"__esModule",{value:!0}),Object.assign(i.default,i),t.exports=i.default)},283713,e=>{"use strict";var t=e.i(271645),i=e.i(602869),o=e.i(612256);let n="litellm_selected_worker_id";e.s(["useWorker",0,()=>{let{data:e}=(0,o.useUIConfig)(),a=e?.is_control_plane??!1,r=e?.workers??[],[l,s]=(0,t.useState)(()=>localStorage.getItem(n));(0,t.useEffect)(()=>{if(!l||0===r.length)return;let e=r.find(e=>e.worker_id===l);e&&(0,i.switchToWorkerUrl)(e.url)},[l,r]);let d=r.find(e=>e.worker_id===l)??null,c=(0,t.useCallback)(e=>{let t=r.find(t=>t.worker_id===e);t&&(s(e),localStorage.setItem(n,e),(0,i.switchToWorkerUrl)(t.url))},[r]);return{isControlPlane:a,workers:r,selectedWorkerId:l,selectedWorker:d,selectWorker:c,disconnectFromWorker:(0,t.useCallback)(()=>{s(null),localStorage.removeItem(n),(0,i.switchToWorkerUrl)(null)},[])}}])},295320,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let o={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M704 446H320c-4.4 0-8 3.6-8 8v402c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8V454c0-4.4-3.6-8-8-8zm-328 64h272v117H376V510zm272 290H376V683h272v117z"}},{tag:"path",attrs:{d:"M424 748a32 32 0 1064 0 32 32 0 10-64 0zm0-178a32 32 0 1064 0 32 32 0 10-64 0z"}},{tag:"path",attrs:{d:"M811.4 368.9C765.6 248 648.9 162 512.2 162S258.8 247.9 213 368.8C126.9 391.5 63.5 470.2 64 563.6 64.6 668 145.6 752.9 247.6 762c4.7.4 8.7-3.3 8.7-8v-60.4c0-4-3-7.4-7-7.9-27-3.4-52.5-15.2-72.1-34.5-24-23.5-37.2-55.1-37.2-88.6 0-28 9.1-54.4 26.2-76.4 16.7-21.4 40.2-36.9 66.1-43.7l37.9-10 13.9-36.7c8.6-22.8 20.6-44.2 35.7-63.5 14.9-19.2 32.6-36 52.4-50 41.1-28.9 89.5-44.2 140-44.2s98.9 15.3 140 44.3c19.9 14 37.5 30.8 52.4 50 15.1 19.3 27.1 40.7 35.7 63.5l13.8 36.6 37.8 10c54.2 14.4 92.1 63.7 92.1 120 0 33.6-13.2 65.1-37.2 88.6-19.5 19.2-44.9 31.1-71.9 34.5-4 .5-6.9 3.9-6.9 7.9V754c0 4.7 4.1 8.4 8.8 8 101.7-9.2 182.5-94 183.2-198.2.6-93.4-62.7-172.1-148.6-194.9z"}}]},name:"cloud-server",theme:"outlined"};var n=e.i(9583),a=i.forwardRef(function(e,a){return i.createElement(n.default,(0,t.default)({},e,{ref:a,icon:o}))});e.s(["CloudServerOutlined",0,a],295320)},906579,e=>{"use strict";e.i(247167);var t=e.i(271645),i=e.i(343794),o=e.i(361275),n=e.i(702779),a=e.i(763731),r=e.i(242064);e.i(296059);var l=e.i(915654),s=e.i(694758),d=e.i(183293),c=e.i(403541),u=e.i(246422),p=e.i(838378);let m=new s.Keyframes("antStatusProcessing",{"0%":{transform:"scale(0.8)",opacity:.5},"100%":{transform:"scale(2.4)",opacity:0}}),g=new s.Keyframes("antZoomBadgeIn",{"0%":{transform:"scale(0) translate(50%, -50%)",opacity:0},"100%":{transform:"scale(1) translate(50%, -50%)"}}),f=new s.Keyframes("antZoomBadgeOut",{"0%":{transform:"scale(1) translate(50%, -50%)"},"100%":{transform:"scale(0) translate(50%, -50%)",opacity:0}}),h=new s.Keyframes("antNoWrapperZoomBadgeIn",{"0%":{transform:"scale(0)",opacity:0},"100%":{transform:"scale(1)"}}),b=new s.Keyframes("antNoWrapperZoomBadgeOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0)",opacity:0}}),_=new s.Keyframes("antBadgeLoadingCircle",{"0%":{transformOrigin:"50%"},"100%":{transform:"translate(50%, -50%) rotate(360deg)",transformOrigin:"50%"}}),y=e=>{let{fontHeight:t,lineWidth:i,marginXS:o,colorBorderBg:n}=e,a=e.colorTextLightSolid,r=e.colorError,l=e.colorErrorHover;return(0,p.mergeToken)(e,{badgeFontHeight:t,badgeShadowSize:i,badgeTextColor:a,badgeColor:r,badgeColorHover:l,badgeShadowColor:n,badgeProcessingDuration:"1.2s",badgeRibbonOffset:o,badgeRibbonCornerTransform:"scaleY(0.75)",badgeRibbonCornerFilter:"brightness(75%)"})},x=e=>{let{fontSize:t,lineHeight:i,fontSizeSM:o,lineWidth:n}=e;return{indicatorZIndex:"auto",indicatorHeight:Math.round(t*i)-2*n,indicatorHeightSM:t,dotSize:o/2,textFontSize:o,textFontSizeSM:o,textFontWeight:"normal",statusSize:o/2}},v=(0,u.genStyleHooks)("Badge",e=>(e=>{let{componentCls:t,iconCls:i,antCls:o,badgeShadowSize:n,textFontSize:a,textFontSizeSM:r,statusSize:s,dotSize:u,textFontWeight:p,indicatorHeight:y,indicatorHeightSM:x,marginXS:v,calc:w}=e,S=`${o}-scroll-number`,j=(0,c.genPresetColor)(e,(e,{darkColor:i})=>({[`&${t} ${t}-color-${e}`]:{background:i,[`&:not(${t}-count)`]:{color:i},"a:hover &":{background:i}}}));return{[t]:Object.assign(Object.assign(Object.assign(Object.assign({},(0,d.resetComponent)(e)),{position:"relative",display:"inline-block",width:"fit-content",lineHeight:1,[`${t}-count`]:{display:"inline-flex",justifyContent:"center",zIndex:e.indicatorZIndex,minWidth:y,height:y,color:e.badgeTextColor,fontWeight:p,fontSize:a,lineHeight:(0,l.unit)(y),whiteSpace:"nowrap",textAlign:"center",background:e.badgeColor,borderRadius:w(y).div(2).equal(),boxShadow:`0 0 0 ${(0,l.unit)(n)} ${e.badgeShadowColor}`,transition:`background ${e.motionDurationMid}`,a:{color:e.badgeTextColor},"a:hover":{color:e.badgeTextColor},"a:hover &":{background:e.badgeColorHover}},[`${t}-count-sm`]:{minWidth:x,height:x,fontSize:r,lineHeight:(0,l.unit)(x),borderRadius:w(x).div(2).equal()},[`${t}-multiple-words`]:{padding:`0 ${(0,l.unit)(e.paddingXS)}`,bdi:{unicodeBidi:"plaintext"}},[`${t}-dot`]:{zIndex:e.indicatorZIndex,width:u,minWidth:u,height:u,background:e.badgeColor,borderRadius:"100%",boxShadow:`0 0 0 ${(0,l.unit)(n)} ${e.badgeShadowColor}`},[`${t}-count, ${t}-dot, ${S}-custom-component`]:{position:"absolute",top:0,insetInlineEnd:0,transform:"translate(50%, -50%)",transformOrigin:"100% 0%",[`&${i}-spin`]:{animationName:_,animationDuration:"1s",animationIterationCount:"infinite",animationTimingFunction:"linear"}},[`&${t}-status`]:{lineHeight:"inherit",verticalAlign:"baseline",[`${t}-status-dot`]:{position:"relative",top:-1,display:"inline-block",width:s,height:s,verticalAlign:"middle",borderRadius:"50%"},[`${t}-status-success`]:{backgroundColor:e.colorSuccess},[`${t}-status-processing`]:{overflow:"visible",color:e.colorInfo,backgroundColor:e.colorInfo,borderColor:"currentcolor","&::after":{position:"absolute",top:0,insetInlineStart:0,width:"100%",height:"100%",borderWidth:n,borderStyle:"solid",borderColor:"inherit",borderRadius:"50%",animationName:m,animationDuration:e.badgeProcessingDuration,animationIterationCount:"infinite",animationTimingFunction:"ease-in-out",content:'""'}},[`${t}-status-default`]:{backgroundColor:e.colorTextPlaceholder},[`${t}-status-error`]:{backgroundColor:e.colorError},[`${t}-status-warning`]:{backgroundColor:e.colorWarning},[`${t}-status-text`]:{marginInlineStart:v,color:e.colorText,fontSize:e.fontSize}}}),j),{[`${t}-zoom-appear, ${t}-zoom-enter`]:{animationName:g,animationDuration:e.motionDurationSlow,animationTimingFunction:e.motionEaseOutBack,animationFillMode:"both"},[`${t}-zoom-leave`]:{animationName:f,animationDuration:e.motionDurationSlow,animationTimingFunction:e.motionEaseOutBack,animationFillMode:"both"},[`&${t}-not-a-wrapper`]:{[`${t}-zoom-appear, ${t}-zoom-enter`]:{animationName:h,animationDuration:e.motionDurationSlow,animationTimingFunction:e.motionEaseOutBack},[`${t}-zoom-leave`]:{animationName:b,animationDuration:e.motionDurationSlow,animationTimingFunction:e.motionEaseOutBack},[`&:not(${t}-status)`]:{verticalAlign:"middle"},[`${S}-custom-component, ${t}-count`]:{transform:"none"},[`${S}-custom-component, ${S}`]:{position:"relative",top:"auto",display:"block",transformOrigin:"50% 50%"}},[S]:{overflow:"hidden",transition:`all ${e.motionDurationMid} ${e.motionEaseOutBack}`,[`${S}-only`]:{position:"relative",display:"inline-block",height:y,transition:`all ${e.motionDurationSlow} ${e.motionEaseOutBack}`,WebkitTransformStyle:"preserve-3d",WebkitBackfaceVisibility:"hidden",[`> p${S}-only-unit`]:{height:y,margin:0,WebkitTransformStyle:"preserve-3d",WebkitBackfaceVisibility:"hidden"}},[`${S}-symbol`]:{verticalAlign:"top"}},"&-rtl":{direction:"rtl",[`${t}-count, ${t}-dot, ${S}-custom-component`]:{transform:"translate(-50%, -50%)"}}})}})(y(e)),x),w=(0,u.genStyleHooks)(["Badge","Ribbon"],e=>(e=>{let{antCls:t,badgeFontHeight:i,marginXS:o,badgeRibbonOffset:n,calc:a}=e,r=`${t}-ribbon`,s=`${t}-ribbon-wrapper`,u=(0,c.genPresetColor)(e,(e,{darkColor:t})=>({[`&${r}-color-${e}`]:{background:t,color:t}}));return{[s]:{position:"relative"},[r]:Object.assign(Object.assign(Object.assign(Object.assign({},(0,d.resetComponent)(e)),{position:"absolute",top:o,padding:`0 ${(0,l.unit)(e.paddingXS)}`,color:e.colorPrimary,lineHeight:(0,l.unit)(i),whiteSpace:"nowrap",backgroundColor:e.colorPrimary,borderRadius:e.borderRadiusSM,[`${r}-text`]:{color:e.badgeTextColor},[`${r}-corner`]:{position:"absolute",top:"100%",width:n,height:n,color:"currentcolor",border:`${(0,l.unit)(a(n).div(2).equal())} solid`,transform:e.badgeRibbonCornerTransform,transformOrigin:"top",filter:e.badgeRibbonCornerFilter}}),u),{[`&${r}-placement-end`]:{insetInlineEnd:a(n).mul(-1).equal(),borderEndEndRadius:0,[`${r}-corner`]:{insetInlineEnd:0,borderInlineEndColor:"transparent",borderBlockEndColor:"transparent"}},[`&${r}-placement-start`]:{insetInlineStart:a(n).mul(-1).equal(),borderEndStartRadius:0,[`${r}-corner`]:{insetInlineStart:0,borderBlockEndColor:"transparent",borderInlineStartColor:"transparent"}},"&-rtl":{direction:"rtl"}})}})(y(e)),x),S=e=>{let o,{prefixCls:n,value:a,current:r,offset:l=0}=e;return l&&(o={position:"absolute",top:`${l}00%`,left:0}),t.createElement("span",{style:o,className:(0,i.default)(`${n}-only-unit`,{current:r})},a)},j=e=>{let i,o,{prefixCls:n,count:a,value:r}=e,l=Number(r),s=Math.abs(a),[d,c]=t.useState(l),[u,p]=t.useState(s),m=()=>{c(l),p(s)};if(t.useEffect(()=>{let e=setTimeout(m,1e3);return()=>clearTimeout(e)},[l]),d===l||Number.isNaN(l)||Number.isNaN(d))i=[t.createElement(S,Object.assign({},e,{key:l,current:!0}))],o={transition:"none"};else{i=[];let n=l+10,a=[];for(let e=l;e<=n;e+=1)a.push(e);let r=ue%10===d);i=(r<0?a.slice(0,c+1):a.slice(c)).map((i,o)=>t.createElement(S,Object.assign({},e,{key:i,value:i%10,offset:r<0?o-c:o,current:o===c}))),o={transform:`translateY(${-function(e,t,i){let o=e,n=0;for(;(o+10)%10!==t;)o+=i,n+=i;return n}(d,l,r)}00%)`}}return t.createElement("span",{className:`${n}-only`,style:o,onTransitionEnd:m},i)};var C=function(e,t){var i={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&0>t.indexOf(o)&&(i[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,o=Object.getOwnPropertySymbols(e);nt.indexOf(o[n])&&Object.prototype.propertyIsEnumerable.call(e,o[n])&&(i[o[n]]=e[o[n]]);return i};let $=t.forwardRef((e,o)=>{let{prefixCls:n,count:l,className:s,motionClassName:d,style:c,title:u,show:p,component:m="sup",children:g}=e,f=C(e,["prefixCls","count","className","motionClassName","style","title","show","component","children"]),{getPrefixCls:h}=t.useContext(r.ConfigContext),b=h("scroll-number",n),_=Object.assign(Object.assign({},f),{"data-show":p,style:c,className:(0,i.default)(b,s,d),title:u}),y=l;if(l&&Number(l)%1==0){let e=String(l).split("");y=t.createElement("bdi",null,e.map((i,o)=>t.createElement(j,{prefixCls:b,count:Number(l),value:i,key:e.length-o})))}return((null==c?void 0:c.borderColor)&&(_.style=Object.assign(Object.assign({},c),{boxShadow:`0 0 0 1px ${c.borderColor} inset`})),g)?(0,a.cloneElement)(g,e=>({className:(0,i.default)(`${b}-custom-component`,null==e?void 0:e.className,d)})):t.createElement(m,Object.assign({},_,{ref:o}),y)});var k=function(e,t){var i={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&0>t.indexOf(o)&&(i[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,o=Object.getOwnPropertySymbols(e);nt.indexOf(o[n])&&Object.prototype.propertyIsEnumerable.call(e,o[n])&&(i[o[n]]=e[o[n]]);return i};let O=t.forwardRef((e,l)=>{var s,d,c,u,p;let{prefixCls:m,scrollNumberPrefixCls:g,children:f,status:h,text:b,color:_,count:y=null,overflowCount:x=99,dot:w=!1,size:S="default",title:j,offset:C,style:O,className:E,rootClassName:I,classNames:N,styles:T,showZero:R=!1}=e,z=k(e,["prefixCls","scrollNumberPrefixCls","children","status","text","color","count","overflowCount","dot","size","title","offset","style","className","rootClassName","classNames","styles","showZero"]),{getPrefixCls:A,direction:P,badge:L}=t.useContext(r.ConfigContext),M=A("badge",m),[B,D,H]=v(M),W=y>x?`${x}+`:y,U="0"===W||0===W||"0"===b||0===b,F=null===y||U&&!R,V=(null!=h||null!=_)&&F,G=null!=h||!U,K=w&&!U,q=K?"":W,Y=(0,t.useMemo)(()=>((null==q||""===q)&&(null==b||""===b)||U&&!R)&&!K,[q,U,R,K,b]),Z=(0,t.useRef)(y);Y||(Z.current=y);let J=Z.current,X=(0,t.useRef)(q);Y||(X.current=q);let Q=X.current,ee=(0,t.useRef)(K);Y||(ee.current=K);let et=(0,t.useMemo)(()=>{if(!C)return Object.assign(Object.assign({},null==L?void 0:L.style),O);let e={marginTop:C[1]};return"rtl"===P?e.left=Number.parseInt(C[0],10):e.right=-Number.parseInt(C[0],10),Object.assign(Object.assign(Object.assign({},e),null==L?void 0:L.style),O)},[P,C,O,null==L?void 0:L.style]),ei=null!=j?j:"string"==typeof J||"number"==typeof J?J:void 0,eo=!Y&&(0===b?R:!!b&&!0!==b),en=eo?t.createElement("span",{className:`${M}-status-text`},b):null,ea=J&&"object"==typeof J?(0,a.cloneElement)(J,e=>({style:Object.assign(Object.assign({},et),e.style)})):void 0,er=(0,n.isPresetColor)(_,!1),el=(0,i.default)(null==N?void 0:N.indicator,null==(s=null==L?void 0:L.classNames)?void 0:s.indicator,{[`${M}-status-dot`]:V,[`${M}-status-${h}`]:!!h,[`${M}-color-${_}`]:er}),es={};_&&!er&&(es.color=_,es.background=_);let ed=(0,i.default)(M,{[`${M}-status`]:V,[`${M}-not-a-wrapper`]:!f,[`${M}-rtl`]:"rtl"===P},E,I,null==L?void 0:L.className,null==(d=null==L?void 0:L.classNames)?void 0:d.root,null==N?void 0:N.root,D,H);if(!f&&V&&(b||G||!F)){let e=et.color;return B(t.createElement("span",Object.assign({},z,{className:ed,style:Object.assign(Object.assign(Object.assign({},null==T?void 0:T.root),null==(c=null==L?void 0:L.styles)?void 0:c.root),et)}),t.createElement("span",{className:el,style:Object.assign(Object.assign(Object.assign({},null==T?void 0:T.indicator),null==(u=null==L?void 0:L.styles)?void 0:u.indicator),es)}),eo&&t.createElement("span",{style:{color:e},className:`${M}-status-text`},b)))}return B(t.createElement("span",Object.assign({ref:l},z,{className:ed,style:Object.assign(Object.assign({},null==(p=null==L?void 0:L.styles)?void 0:p.root),null==T?void 0:T.root)}),f,t.createElement(o.default,{visible:!Y,motionName:`${M}-zoom`,motionAppear:!1,motionDeadline:1e3},({className:e})=>{var o,n;let a=A("scroll-number",g),r=ee.current,l=(0,i.default)(null==N?void 0:N.indicator,null==(o=null==L?void 0:L.classNames)?void 0:o.indicator,{[`${M}-dot`]:r,[`${M}-count`]:!r,[`${M}-count-sm`]:"small"===S,[`${M}-multiple-words`]:!r&&Q&&Q.toString().length>1,[`${M}-status-${h}`]:!!h,[`${M}-color-${_}`]:er}),s=Object.assign(Object.assign(Object.assign({},null==T?void 0:T.indicator),null==(n=null==L?void 0:L.styles)?void 0:n.indicator),et);return _&&!er&&((s=s||{}).background=_),t.createElement($,{prefixCls:a,show:!Y,motionClassName:e,className:l,count:Q,title:ei,style:s,key:"scrollNumber"},ea)}),en))});O.Ribbon=e=>{let{className:o,prefixCls:a,style:l,color:s,children:d,text:c,placement:u="end",rootClassName:p}=e,{getPrefixCls:m,direction:g}=t.useContext(r.ConfigContext),f=m("ribbon",a),h=`${f}-wrapper`,[b,_,y]=w(f,h),x=(0,n.isPresetColor)(s,!1),v=(0,i.default)(f,`${f}-placement-${u}`,{[`${f}-rtl`]:"rtl"===g,[`${f}-color-${s}`]:x},o),S={},j={};return s&&!x&&(S.background=s,j.color=s),b(t.createElement("div",{className:(0,i.default)(h,p,_,y)},d,t.createElement("div",{className:(0,i.default)(v,_),style:Object.assign(Object.assign({},S),l)},t.createElement("span",{className:`${f}-text`},c),t.createElement("div",{className:`${f}-corner`,style:j}))))},e.s(["Badge",0,O],906579)},100486,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let o={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M899.6 276.5L705 396.4 518.4 147.5a8.06 8.06 0 00-12.9 0L319 396.4 124.3 276.5c-5.7-3.5-13.1 1.2-12.2 7.9L188.5 865c1.1 7.9 7.9 14 16 14h615.1c8 0 14.9-6 15.9-14l76.4-580.6c.8-6.7-6.5-11.4-12.3-7.9zm-126 534.1H250.3l-53.8-409.4 139.8 86.1L512 252.9l175.7 234.4 139.8-86.1-53.9 409.4zM512 509c-62.1 0-112.6 50.5-112.6 112.6S449.9 734.2 512 734.2s112.6-50.5 112.6-112.6S574.1 509 512 509zm0 160.9c-26.6 0-48.2-21.6-48.2-48.3 0-26.6 21.6-48.3 48.2-48.3s48.2 21.6 48.2 48.3c0 26.6-21.6 48.3-48.2 48.3z"}}]},name:"crown",theme:"outlined"};var n=e.i(9583),a=i.forwardRef(function(e,a){return i.createElement(n.default,(0,t.default)({},e,{ref:a,icon:o}))});e.s(["CrownOutlined",0,a],100486)},275144,e=>{"use strict";var t=e.i(843476),i=e.i(271645),o=e.i(602869);let n=(0,i.createContext)(void 0);e.s(["ThemeProvider",0,({children:e,accessToken:a})=>{let[r,l]=(0,i.useState)(null),[s,d]=(0,i.useState)(null);return(0,i.useEffect)(()=>{(async()=>{try{let e=(0,o.getProxyBaseUrl)(),t=e?`${e}/get/ui_theme_settings`:"/get/ui_theme_settings",i=await fetch(t,{method:"GET",headers:{"Content-Type":"application/json"}});if(i.ok){let e=await i.json();e.values?.logo_url&&l(e.values.logo_url),e.values?.favicon_url&&d(e.values.favicon_url)}}catch(e){console.warn("Failed to load theme settings from backend:",e)}})()},[]),(0,i.useEffect)(()=>{if(s){let e=document.querySelectorAll("link[rel*='icon']");if(e.length>0)e.forEach(e=>{e.href=s});else{let e=document.createElement("link");e.rel="icon",e.href=s,document.head.appendChild(e)}}},[s]),(0,t.jsx)(n.Provider,{value:{logoUrl:r,setLogoUrl:l,faviconUrl:s,setFaviconUrl:d},children:e})},"useTheme",0,()=>{let e=(0,i.useContext)(n);if(!e)throw Error("useTheme must be used within a ThemeProvider");return e}])},371401,e=>{"use strict";var t=e.i(115571),i=e.i(271645);function o(e){let i=t=>{"disableUsageIndicator"===t.key&&e()},o=t=>{let{key:i}=t.detail;"disableUsageIndicator"===i&&e()};return window.addEventListener("storage",i),window.addEventListener(t.LOCAL_STORAGE_EVENT,o),()=>{window.removeEventListener("storage",i),window.removeEventListener(t.LOCAL_STORAGE_EVENT,o)}}function n(){return"true"===(0,t.getLocalStorageItem)("disableUsageIndicator")}function a(){return(0,i.useSyncExternalStore)(o,n)}e.s(["useDisableUsageIndicator",()=>a])},115571,e=>{"use strict";let t="local-storage-change";function i(e){window.dispatchEvent(new CustomEvent(t,{detail:{key:e}}))}function o(e){try{return window.localStorage.getItem(e)}catch(t){return console.warn(`Error reading localStorage key "${e}":`,t),null}}function n(e,t){try{window.localStorage.setItem(e,t)}catch(t){console.warn(`Error setting localStorage key "${e}":`,t)}}function a(e){try{window.localStorage.removeItem(e)}catch(t){console.warn(`Error removing localStorage key "${e}":`,t)}}e.s(["LOCAL_STORAGE_EVENT",0,t,"emitLocalStorageChange",()=>i,"getLocalStorageItem",()=>o,"removeLocalStorageItem",()=>a,"setLocalStorageItem",()=>n])},928685,e=>{"use strict";var t=e.i(38953);e.s(["SearchOutlined",()=>t.default])},62478,e=>{"use strict";var t=e.i(602869);let i=async e=>{if(!e)return null;try{return await (0,t.getProxyUISettings)(e)}catch(e){return console.error("Error fetching proxy settings:",e),null}};e.s(["fetchProxySettings",0,i])},592392,e=>{"use strict";var t=e.i(62478),i=e.i(266027);let o=(0,e.i(243652).createQueryKeys)("proxySettings"),n={PROXY_BASE_URL:"",PROXY_LOGOUT_URL:"",LITELLM_UI_API_DOC_BASE_URL:null};function a(e){let{data:a}=(0,i.useQuery)({queryKey:[...o.all,e],queryFn:()=>(0,t.fetchProxySettings)(e),enabled:!!e});return a??n}e.s(["default",()=>a])}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/0dd021db5f4804b4.js b/litellm/proxy/_experimental/out/_next/static/chunks/0dd021db5f4804b4.js new file mode 100644 index 00000000000..f403e0e0f72 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/0dd021db5f4804b4.js @@ -0,0 +1,23 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,165370,e=>{"use strict";e.i(247167);var t=e.i(271645),n=e.i(931067);let i={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M272.9 512l265.4-339.1c4.1-5.2.4-12.9-6.3-12.9h-77.3c-4.9 0-9.6 2.3-12.6 6.1L186.8 492.3a31.99 31.99 0 000 39.5l255.3 326.1c3 3.9 7.7 6.1 12.6 6.1H532c6.7 0 10.4-7.7 6.3-12.9L272.9 512zm304 0l265.4-339.1c4.1-5.2.4-12.9-6.3-12.9h-77.3c-4.9 0-9.6 2.3-12.6 6.1L490.8 492.3a31.99 31.99 0 000 39.5l255.3 326.1c3 3.9 7.7 6.1 12.6 6.1H836c6.7 0 10.4-7.7 6.3-12.9L576.9 512z"}}]},name:"double-left",theme:"outlined"};var o=e.i(9583),l=t.forwardRef(function(e,l){return t.createElement(o.default,(0,n.default)({},e,{ref:l,icon:i}))});let a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M533.2 492.3L277.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H188c-6.7 0-10.4 7.7-6.3 12.9L447.1 512 181.7 851.1A7.98 7.98 0 00188 864h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5zm304 0L581.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H492c-6.7 0-10.4 7.7-6.3 12.9L751.1 512 485.7 851.1A7.98 7.98 0 00492 864h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5z"}}]},name:"double-right",theme:"outlined"};var r=t.forwardRef(function(e,i){return t.createElement(o.default,(0,n.default)({},e,{ref:i,icon:a}))}),d=e.i(801312),c=e.i(286612),s=e.i(343794),u=e.i(211577),m=e.i(410160),g=e.i(209428),p=e.i(392221),b=e.i(914949),f=e.i(404948),h=e.i(244009);e.i(883110);let v={items_per_page:"条/页",jump_to:"跳至",jump_to_confirm:"确定",page:"页",prev_page:"上一页",next_page:"下一页",prev_5:"向前 5 页",next_5:"向后 5 页",prev_3:"向前 3 页",next_3:"向后 3 页",page_size:"页码"};var $=[10,20,50,100];let y=function(e){var n=e.pageSizeOptions,i=void 0===n?$:n,o=e.locale,l=e.changeSize,a=e.pageSize,r=e.goButton,d=e.quickGo,c=e.rootPrefixCls,s=e.disabled,u=e.buildOptionText,m=e.showSizeChanger,g=e.sizeChangerRender,b=t.default.useState(""),h=(0,p.default)(b,2),v=h[0],y=h[1],S=function(){return!v||Number.isNaN(v)?void 0:Number(v)},C="function"==typeof u?u:function(e){return"".concat(e," ").concat(o.items_per_page)},x=function(e){""!==v&&(e.keyCode===f.default.ENTER||"click"===e.type)&&(y(""),null==d||d(S()))},O="".concat(c,"-options");if(!m&&!d)return null;var k=null,j=null,E=null;return m&&g&&(k=g({disabled:s,size:a,onSizeChange:function(e){null==l||l(Number(e))},"aria-label":o.page_size,className:"".concat(O,"-size-changer"),options:(i.some(function(e){return e.toString()===a.toString()})?i:i.concat([a]).sort(function(e,t){return(Number.isNaN(Number(e))?0:Number(e))-(Number.isNaN(Number(t))?0:Number(t))})).map(function(e){return{label:C(e),value:e}})})),d&&(r&&(E="boolean"==typeof r?t.default.createElement("button",{type:"button",onClick:x,onKeyUp:x,disabled:s,className:"".concat(O,"-quick-jumper-button")},o.jump_to_confirm):t.default.createElement("span",{onClick:x,onKeyUp:x},r)),j=t.default.createElement("div",{className:"".concat(O,"-quick-jumper")},o.jump_to,t.default.createElement("input",{disabled:s,type:"text",value:v,onChange:function(e){y(e.target.value)},onKeyUp:x,onBlur:function(e){r||""===v||(y(""),e.relatedTarget&&(e.relatedTarget.className.indexOf("".concat(c,"-item-link"))>=0||e.relatedTarget.className.indexOf("".concat(c,"-item"))>=0)||null==d||d(S()))},"aria-label":o.page}),o.page,E)),t.default.createElement("li",{className:O},k,j)},S=function(e){var n=e.rootPrefixCls,i=e.page,o=e.active,l=e.className,a=e.showTitle,r=e.onClick,d=e.onKeyPress,c=e.itemRender,m="".concat(n,"-item"),g=(0,s.default)(m,"".concat(m,"-").concat(i),(0,u.default)((0,u.default)({},"".concat(m,"-active"),o),"".concat(m,"-disabled"),!i),l),p=c(i,"page",t.default.createElement("a",{rel:"nofollow"},i));return p?t.default.createElement("li",{title:a?String(i):null,className:g,onClick:function(){r(i)},onKeyDown:function(e){d(e,r,i)},tabIndex:0},p):null};var C=function(e,t,n){return n};function x(){}function O(e){var t=Number(e);return"number"==typeof t&&!Number.isNaN(t)&&isFinite(t)&&Math.floor(t)===t}function k(e,t,n){return Math.floor((n-1)/(void 0===e?t:e))+1}let j=function(e){var i,o,l,a,r=e.prefixCls,d=void 0===r?"rc-pagination":r,c=e.selectPrefixCls,$=e.className,j=e.current,E=e.defaultCurrent,w=e.total,z=void 0===w?0:w,N=e.pageSize,I=e.defaultPageSize,B=e.onChange,M=void 0===B?x:B,P=e.hideOnSinglePage,T=e.align,R=e.showPrevNextJumpers,H=e.showQuickJumper,D=e.showLessItems,L=e.showTitle,W=void 0===L||L,A=e.onShowSizeChange,q=void 0===A?x:A,G=e.locale,_=void 0===G?v:G,F=e.style,X=e.totalBoundaryShowSizeChanger,K=e.disabled,U=e.simple,J=e.showTotal,Q=e.showSizeChanger,V=void 0===Q?z>(void 0===X?50:X):Q,Y=e.sizeChangerRender,Z=e.pageSizeOptions,ee=e.itemRender,et=void 0===ee?C:ee,en=e.jumpPrevIcon,ei=e.jumpNextIcon,eo=e.prevIcon,el=e.nextIcon,ea=t.default.useRef(null),er=(0,b.default)(10,{value:N,defaultValue:void 0===I?10:I}),ed=(0,p.default)(er,2),ec=ed[0],es=ed[1],eu=(0,b.default)(1,{value:j,defaultValue:void 0===E?1:E,postState:function(e){return Math.max(1,Math.min(e,k(void 0,ec,z)))}}),em=(0,p.default)(eu,2),eg=em[0],ep=em[1],eb=t.default.useState(eg),ef=(0,p.default)(eb,2),eh=ef[0],ev=ef[1];(0,t.useEffect)(function(){ev(eg)},[eg]);var e$=Math.max(1,eg-(D?3:5)),ey=Math.min(k(void 0,ec,z),eg+(D?3:5));function eS(n,i){var o=n||t.default.createElement("button",{type:"button","aria-label":i,className:"".concat(d,"-item-link")});return"function"==typeof n&&(o=t.default.createElement(n,(0,g.default)({},e))),o}function eC(e){var t=e.target.value,n=k(void 0,ec,z);return""===t?t:Number.isNaN(Number(t))?eh:t>=n?n:Number(t)}var ex=z>ec&&H;function eO(e){var t=eC(e);switch(t!==eh&&ev(t),e.keyCode){case f.default.ENTER:ek(t);break;case f.default.UP:ek(t-1);break;case f.default.DOWN:ek(t+1)}}function ek(e){if(O(e)&&e!==eg&&O(z)&&z>0&&!K){var t=k(void 0,ec,z),n=e;return e>t?n=t:e<1&&(n=1),n!==eh&&ev(n),ep(n),null==M||M(n,ec),n}return eg}var ej=eg>1,eE=eg2?n-2:0),o=2;oz?z:eg*ec])),eH=null,eD=k(void 0,ec,z);if(P&&z<=ec)return null;var eL=[],eW={rootPrefixCls:d,onClick:ek,onKeyPress:eB,showTitle:W,itemRender:et,page:-1},eA=eg-1>0?eg-1:0,eq=eg+1=2*eK&&3!==eg&&(eL[0]=t.default.cloneElement(eL[0],{className:(0,s.default)("".concat(d,"-item-after-jump-prev"),eL[0].props.className)}),eL.unshift(eP)),eD-eg>=2*eK&&eg!==eD-2){var e2=eL[eL.length-1];eL[eL.length-1]=t.default.cloneElement(e2,{className:(0,s.default)("".concat(d,"-item-before-jump-next"),e2.props.className)}),eL.push(eH)}1!==eZ&&eL.unshift(t.default.createElement(S,(0,n.default)({},eW,{key:1,page:1}))),e0!==eD&&eL.push(t.default.createElement(S,(0,n.default)({},eW,{key:eD,page:eD})))}var e3=(i=et(eA,"prev",eS(eo,"prev page")),t.default.isValidElement(i)?t.default.cloneElement(i,{disabled:!ej}):i);if(e3){var e9=!ej||!eD;e3=t.default.createElement("li",{title:W?_.prev_page:null,onClick:ew,tabIndex:e9?null:0,onKeyDown:function(e){eB(e,ew)},className:(0,s.default)("".concat(d,"-prev"),(0,u.default)({},"".concat(d,"-disabled"),e9)),"aria-disabled":e9},e3)}var e4=(o=et(eq,"next",eS(el,"next page")),t.default.isValidElement(o)?t.default.cloneElement(o,{disabled:!eE}):o);e4&&(U?(l=!eE,a=ej?0:null):a=(l=!eE||!eD)?null:0,e4=t.default.createElement("li",{title:W?_.next_page:null,onClick:ez,tabIndex:a,onKeyDown:function(e){eB(e,ez)},className:(0,s.default)("".concat(d,"-next"),(0,u.default)({},"".concat(d,"-disabled"),l)),"aria-disabled":l},e4));var e6=(0,s.default)(d,$,(0,u.default)((0,u.default)((0,u.default)((0,u.default)((0,u.default)({},"".concat(d,"-start"),"start"===T),"".concat(d,"-center"),"center"===T),"".concat(d,"-end"),"end"===T),"".concat(d,"-simple"),U),"".concat(d,"-disabled"),K));return t.default.createElement("ul",(0,n.default)({className:e6,style:F,ref:ea},eT),eR,e3,U?eX:eL,e4,t.default.createElement(y,{locale:_,rootPrefixCls:d,disabled:K,selectPrefixCls:void 0===c?"rc-select":c,changeSize:function(e){var t=k(e,ec,z),n=eg>t&&0!==t?t:eg;es(e),ev(n),null==q||q(eg,e),ep(n),null==M||M(n,e)},pageSize:ec,pageSizeOptions:Z,quickGo:ex?ek:null,goButton:eF,showSizeChanger:V,sizeChangerRender:Y}))};var E=e.i(727214),w=e.i(242064),z=e.i(517455),N=e.i(150073),I=e.i(408850),B=e.i(327494),M=e.i(104458);e.i(296059);var P=e.i(915654),T=e.i(349942),R=e.i(517458),H=e.i(889943),D=e.i(183293),L=e.i(246422),W=e.i(838378);let A=e=>Object.assign({itemBg:e.colorBgContainer,itemSize:e.controlHeight,itemSizeSM:e.controlHeightSM,itemActiveBg:e.colorBgContainer,itemActiveColor:e.colorPrimary,itemActiveColorHover:e.colorPrimaryHover,itemLinkBg:e.colorBgContainer,itemActiveColorDisabled:e.colorTextDisabled,itemActiveBgDisabled:e.controlItemBgActiveDisabled,itemInputBg:e.colorBgContainer,miniOptionsSizeChangerTop:0},(0,R.initComponentToken)(e)),q=e=>(0,W.mergeToken)(e,{inputOutlineOffset:0,quickJumperInputWidth:e.calc(e.controlHeightLG).mul(1.25).equal(),paginationMiniOptionsMarginInlineStart:e.calc(e.marginXXS).div(2).equal(),paginationMiniQuickJumperInputWidth:e.calc(e.controlHeightLG).mul(1.1).equal(),paginationItemPaddingInline:e.calc(e.marginXXS).mul(1.5).equal(),paginationEllipsisLetterSpacing:e.calc(e.marginXXS).div(2).equal(),paginationSlashMarginInlineStart:e.marginSM,paginationSlashMarginInlineEnd:e.marginSM,paginationEllipsisTextIndent:"0.13em"},(0,R.initInputToken)(e)),G=(0,L.genStyleHooks)("Pagination",e=>{let t=q(e);return[(e=>{let{componentCls:t}=e;return{[t]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},(0,D.resetComponent)(e)),{display:"flex",flexWrap:"wrap",rowGap:e.paddingXS,"&-start":{justifyContent:"start"},"&-center":{justifyContent:"center"},"&-end":{justifyContent:"end"},"ul, ol":{margin:0,padding:0,listStyle:"none"},"&::after":{display:"block",clear:"both",height:0,overflow:"hidden",visibility:"hidden",content:'""'},[`${t}-total-text`]:{display:"inline-block",height:e.itemSize,marginInlineEnd:e.marginXS,lineHeight:(0,P.unit)(e.calc(e.itemSize).sub(2).equal()),verticalAlign:"middle"}}),(e=>{let{componentCls:t}=e;return{[`${t}-item`]:{display:"inline-block",minWidth:e.itemSize,height:e.itemSize,marginInlineEnd:e.marginXS,fontFamily:e.fontFamily,lineHeight:(0,P.unit)(e.calc(e.itemSize).sub(2).equal()),textAlign:"center",verticalAlign:"middle",listStyle:"none",backgroundColor:e.itemBg,border:`${(0,P.unit)(e.lineWidth)} ${e.lineType} transparent`,borderRadius:e.borderRadius,outline:0,cursor:"pointer",userSelect:"none",a:{display:"block",padding:`0 ${(0,P.unit)(e.paginationItemPaddingInline)}`,color:e.colorText,"&:hover":{textDecoration:"none"}},[`&:not(${t}-item-active)`]:{"&:hover":{transition:`all ${e.motionDurationMid}`,backgroundColor:e.colorBgTextHover},"&:active":{backgroundColor:e.colorBgTextActive}},"&-active":{fontWeight:e.fontWeightStrong,backgroundColor:e.itemActiveBg,borderColor:e.colorPrimary,a:{color:e.itemActiveColor},"&:hover":{borderColor:e.colorPrimaryHover},"&:hover a":{color:e.itemActiveColorHover}}}}})(e)),(e=>{let{componentCls:t}=e;return{[`${t}-jump-prev, ${t}-jump-next`]:{outline:0,[`${t}-item-container`]:{position:"relative",[`${t}-item-link-icon`]:{color:e.colorPrimary,fontSize:e.fontSizeSM,opacity:0,transition:`all ${e.motionDurationMid}`,"&-svg":{top:0,insetInlineEnd:0,bottom:0,insetInlineStart:0,margin:"auto"}},[`${t}-item-ellipsis`]:{position:"absolute",top:0,insetInlineEnd:0,bottom:0,insetInlineStart:0,display:"block",margin:"auto",color:e.colorTextDisabled,letterSpacing:e.paginationEllipsisLetterSpacing,textAlign:"center",textIndent:e.paginationEllipsisTextIndent,opacity:1,transition:`all ${e.motionDurationMid}`}},"&:hover":{[`${t}-item-link-icon`]:{opacity:1},[`${t}-item-ellipsis`]:{opacity:0}}},[` + ${t}-prev, + ${t}-jump-prev, + ${t}-jump-next + `]:{marginInlineEnd:e.marginXS},[` + ${t}-prev, + ${t}-next, + ${t}-jump-prev, + ${t}-jump-next + `]:{display:"inline-block",minWidth:e.itemSize,height:e.itemSize,color:e.colorText,fontFamily:e.fontFamily,lineHeight:(0,P.unit)(e.itemSize),textAlign:"center",verticalAlign:"middle",listStyle:"none",borderRadius:e.borderRadius,cursor:"pointer",transition:`all ${e.motionDurationMid}`},[`${t}-prev, ${t}-next`]:{outline:0,button:{color:e.colorText,cursor:"pointer",userSelect:"none"},[`${t}-item-link`]:{display:"block",width:"100%",height:"100%",padding:0,fontSize:e.fontSizeSM,textAlign:"center",backgroundColor:"transparent",border:`${(0,P.unit)(e.lineWidth)} ${e.lineType} transparent`,borderRadius:e.borderRadius,outline:"none",transition:`all ${e.motionDurationMid}`},[`&:hover ${t}-item-link`]:{backgroundColor:e.colorBgTextHover},[`&:active ${t}-item-link`]:{backgroundColor:e.colorBgTextActive},[`&${t}-disabled:hover`]:{[`${t}-item-link`]:{backgroundColor:"transparent"}}},[`${t}-slash`]:{marginInlineEnd:e.paginationSlashMarginInlineEnd,marginInlineStart:e.paginationSlashMarginInlineStart},[`${t}-options`]:{display:"inline-block",marginInlineStart:e.margin,verticalAlign:"middle","&-size-changer":{display:"inline-block",width:"auto"},"&-quick-jumper":{display:"inline-block",height:e.controlHeight,marginInlineStart:e.marginXS,lineHeight:(0,P.unit)(e.controlHeight),verticalAlign:"top",input:Object.assign(Object.assign(Object.assign({},(0,T.genBasicInputStyle)(e)),(0,H.genBaseOutlinedStyle)(e,{borderColor:e.colorBorder,hoverBorderColor:e.colorPrimaryHover,activeBorderColor:e.colorPrimary,activeShadow:e.activeShadow})),{"&[disabled]":Object.assign({},(0,H.genDisabledStyle)(e)),width:e.quickJumperInputWidth,height:e.controlHeight,boxSizing:"border-box",margin:0,marginInlineStart:e.marginXS,marginInlineEnd:e.marginXS})}}}})(e)),(e=>{let{componentCls:t}=e;return{[`&${t}-simple`]:{[`${t}-prev, ${t}-next`]:{height:e.itemSize,lineHeight:(0,P.unit)(e.itemSize),verticalAlign:"top",[`${t}-item-link`]:{height:e.itemSize,backgroundColor:"transparent",border:0,"&:hover":{backgroundColor:e.colorBgTextHover},"&:active":{backgroundColor:e.colorBgTextActive},"&::after":{height:e.itemSize,lineHeight:(0,P.unit)(e.itemSize)}}},[`${t}-simple-pager`]:{display:"inline-flex",alignItems:"center",height:e.itemSize,marginInlineEnd:e.marginXS,input:{boxSizing:"border-box",height:"100%",width:e.quickJumperInputWidth,padding:`0 ${(0,P.unit)(e.paginationItemPaddingInline)}`,textAlign:"center",backgroundColor:e.itemInputBg,border:`${(0,P.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderRadius:e.borderRadius,outline:"none",transition:`border-color ${e.motionDurationMid}`,color:"inherit","&:hover":{borderColor:e.colorPrimary},"&:focus":{borderColor:e.colorPrimaryHover,boxShadow:`${(0,P.unit)(e.inputOutlineOffset)} 0 ${(0,P.unit)(e.controlOutlineWidth)} ${e.controlOutline}`},"&[disabled]":{color:e.colorTextDisabled,backgroundColor:e.colorBgContainerDisabled,borderColor:e.colorBorder,cursor:"not-allowed"}}},[`&${t}-disabled`]:{[`${t}-prev, ${t}-next`]:{[`${t}-item-link`]:{"&:hover, &:active":{backgroundColor:"transparent"}}}},[`&${t}-mini`]:{[`${t}-prev, ${t}-next`]:{height:e.itemSizeSM,lineHeight:(0,P.unit)(e.itemSizeSM),[`${t}-item-link`]:{height:e.itemSizeSM,"&::after":{height:e.itemSizeSM,lineHeight:(0,P.unit)(e.itemSizeSM)}}},[`${t}-simple-pager`]:{height:e.itemSizeSM,input:{width:e.paginationMiniQuickJumperInputWidth}}}}}})(e)),(e=>{let{componentCls:t}=e;return{[`&${t}-mini ${t}-total-text, &${t}-mini ${t}-simple-pager`]:{height:e.itemSizeSM,lineHeight:(0,P.unit)(e.itemSizeSM)},[`&${t}-mini ${t}-item`]:{minWidth:e.itemSizeSM,height:e.itemSizeSM,margin:0,lineHeight:(0,P.unit)(e.calc(e.itemSizeSM).sub(2).equal())},[`&${t}-mini ${t}-prev, &${t}-mini ${t}-next`]:{minWidth:e.itemSizeSM,height:e.itemSizeSM,margin:0,lineHeight:(0,P.unit)(e.itemSizeSM)},[`&${t}-mini:not(${t}-disabled)`]:{[`${t}-prev, ${t}-next`]:{[`&:hover ${t}-item-link`]:{backgroundColor:e.colorBgTextHover},[`&:active ${t}-item-link`]:{backgroundColor:e.colorBgTextActive},[`&${t}-disabled:hover ${t}-item-link`]:{backgroundColor:"transparent"}}},[` + &${t}-mini ${t}-prev ${t}-item-link, + &${t}-mini ${t}-next ${t}-item-link + `]:{backgroundColor:"transparent",borderColor:"transparent","&::after":{height:e.itemSizeSM,lineHeight:(0,P.unit)(e.itemSizeSM)}},[`&${t}-mini ${t}-jump-prev, &${t}-mini ${t}-jump-next`]:{height:e.itemSizeSM,marginInlineEnd:0,lineHeight:(0,P.unit)(e.itemSizeSM)},[`&${t}-mini ${t}-options`]:{marginInlineStart:e.paginationMiniOptionsMarginInlineStart,"&-size-changer":{top:e.miniOptionsSizeChangerTop},"&-quick-jumper":{height:e.itemSizeSM,lineHeight:(0,P.unit)(e.itemSizeSM),input:Object.assign(Object.assign({},(0,T.genInputSmallStyle)(e)),{width:e.paginationMiniQuickJumperInputWidth,height:e.controlHeightSM})}}}})(e)),(e=>{let{componentCls:t}=e;return{[`${t}-disabled`]:{"&, &:hover":{cursor:"not-allowed",[`${t}-item-link`]:{color:e.colorTextDisabled,cursor:"not-allowed"}},"&:focus-visible":{cursor:"not-allowed",[`${t}-item-link`]:{color:e.colorTextDisabled,cursor:"not-allowed"}}},[`&${t}-disabled`]:{cursor:"not-allowed",[`${t}-item`]:{cursor:"not-allowed",backgroundColor:"transparent","&:hover, &:active":{backgroundColor:"transparent"},a:{color:e.colorTextDisabled,backgroundColor:"transparent",border:"none",cursor:"not-allowed"},"&-active":{borderColor:e.colorBorder,backgroundColor:e.itemActiveBgDisabled,"&:hover, &:active":{backgroundColor:e.itemActiveBgDisabled},a:{color:e.itemActiveColorDisabled}}},[`${t}-item-link`]:{color:e.colorTextDisabled,cursor:"not-allowed","&:hover, &:active":{backgroundColor:"transparent"},[`${t}-simple&`]:{backgroundColor:"transparent","&:hover, &:active":{backgroundColor:"transparent"}}},[`${t}-simple-pager`]:{color:e.colorTextDisabled},[`${t}-jump-prev, ${t}-jump-next`]:{[`${t}-item-link-icon`]:{opacity:0},[`${t}-item-ellipsis`]:{opacity:1}}}}})(e)),{[`@media only screen and (max-width: ${e.screenLG}px)`]:{[`${t}-item`]:{"&-after-jump-prev, &-before-jump-next":{display:"none"}}},[`@media only screen and (max-width: ${e.screenSM}px)`]:{[`${t}-options`]:{display:"none"}}}),[`&${e.componentCls}-rtl`]:{direction:"rtl"}}})(t),(e=>{let{componentCls:t}=e;return{[`${t}:not(${t}-disabled)`]:{[`${t}-item`]:Object.assign({},(0,D.genFocusStyle)(e)),[`${t}-jump-prev, ${t}-jump-next`]:{"&:focus-visible":Object.assign({[`${t}-item-link-icon`]:{opacity:1},[`${t}-item-ellipsis`]:{opacity:0}},(0,D.genFocusOutline)(e))},[`${t}-prev, ${t}-next`]:{[`&:focus-visible ${t}-item-link`]:(0,D.genFocusOutline)(e)}}}})(t)]},A),_=(0,L.genSubStyleComponent)(["Pagination","bordered"],e=>(e=>{let{componentCls:t}=e;return{[`${t}${t}-bordered${t}-disabled:not(${t}-mini)`]:{"&, &:hover":{[`${t}-item-link`]:{borderColor:e.colorBorder}},"&:focus-visible":{[`${t}-item-link`]:{borderColor:e.colorBorder}},[`${t}-item, ${t}-item-link`]:{backgroundColor:e.colorBgContainerDisabled,borderColor:e.colorBorder,[`&:hover:not(${t}-item-active)`]:{backgroundColor:e.colorBgContainerDisabled,borderColor:e.colorBorder,a:{color:e.colorTextDisabled}},[`&${t}-item-active`]:{backgroundColor:e.itemActiveBgDisabled}},[`${t}-prev, ${t}-next`]:{"&:hover button":{backgroundColor:e.colorBgContainerDisabled,borderColor:e.colorBorder,color:e.colorTextDisabled},[`${t}-item-link`]:{backgroundColor:e.colorBgContainerDisabled,borderColor:e.colorBorder}}},[`${t}${t}-bordered:not(${t}-mini)`]:{[`${t}-prev, ${t}-next`]:{"&:hover button":{borderColor:e.colorPrimaryHover,backgroundColor:e.itemBg},[`${t}-item-link`]:{backgroundColor:e.itemLinkBg,borderColor:e.colorBorder},[`&:hover ${t}-item-link`]:{borderColor:e.colorPrimary,backgroundColor:e.itemBg,color:e.colorPrimary},[`&${t}-disabled`]:{[`${t}-item-link`]:{borderColor:e.colorBorder,color:e.colorTextDisabled}}},[`${t}-item`]:{backgroundColor:e.itemBg,border:`${(0,P.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,[`&:hover:not(${t}-item-active)`]:{borderColor:e.colorPrimary,backgroundColor:e.itemBg,a:{color:e.colorPrimary}},"&-active":{borderColor:e.colorPrimary}}}}})(q(e)),A);function F(e){return(0,t.useMemo)(()=>"boolean"==typeof e?[e,{}]:e&&"object"==typeof e?[!0,e]:[void 0,void 0],[e])}var X=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};e.s(["default",0,e=>{let{align:n,prefixCls:i,selectPrefixCls:o,className:a,rootClassName:u,style:m,size:g,locale:p,responsive:b,showSizeChanger:f,selectComponentClass:h,pageSizeOptions:v}=e,$=X(e,["align","prefixCls","selectPrefixCls","className","rootClassName","style","size","locale","responsive","showSizeChanger","selectComponentClass","pageSizeOptions"]),{xs:y}=(0,N.default)(b),[,S]=(0,M.useToken)(),{getPrefixCls:C,direction:x,showSizeChanger:O,className:k,style:P}=(0,w.useComponentConfig)("pagination"),T=C("pagination",i),[R,H,D]=G(T),L=(0,z.default)(g),W="small"===L||!!(y&&!L&&b),[A]=(0,I.useLocale)("Pagination",E.default),q=Object.assign(Object.assign({},A),p),[K,U]=F(f),[J,Q]=F(O),V=null!=U?U:Q,Y=h||B.default,Z=t.useMemo(()=>v?v.map(e=>Number(e)):void 0,[v]),ee=t.useMemo(()=>{let e=t.createElement("span",{className:`${T}-item-ellipsis`},"•••"),n=t.createElement("button",{className:`${T}-item-link`,type:"button",tabIndex:-1},"rtl"===x?t.createElement(c.default,null):t.createElement(d.default,null)),i=t.createElement("button",{className:`${T}-item-link`,type:"button",tabIndex:-1},"rtl"===x?t.createElement(d.default,null):t.createElement(c.default,null));return{prevIcon:n,nextIcon:i,jumpPrevIcon:t.createElement("a",{className:`${T}-item-link`},t.createElement("div",{className:`${T}-item-container`},"rtl"===x?t.createElement(r,{className:`${T}-item-link-icon`}):t.createElement(l,{className:`${T}-item-link-icon`}),e)),jumpNextIcon:t.createElement("a",{className:`${T}-item-link`},t.createElement("div",{className:`${T}-item-container`},"rtl"===x?t.createElement(l,{className:`${T}-item-link-icon`}):t.createElement(r,{className:`${T}-item-link-icon`}),e))}},[x,T]),et=C("select",o),en=(0,s.default)({[`${T}-${n}`]:!!n,[`${T}-mini`]:W,[`${T}-rtl`]:"rtl"===x,[`${T}-bordered`]:S.wireframe},k,a,u,H,D),ei=Object.assign(Object.assign({},P),m);return R(t.createElement(t.Fragment,null,S.wireframe&&t.createElement(_,{prefixCls:T}),t.createElement(j,Object.assign({},ee,$,{style:ei,prefixCls:T,selectPrefixCls:et,className:en,locale:q,pageSizeOptions:Z,showSizeChanger:null!=K?K:J,sizeChangerRender:e=>{var n;let{disabled:i,size:o,onSizeChange:l,"aria-label":a,className:r,options:d}=e,{className:c,onChange:u}=V||{},m=null==(n=d.find(e=>String(e.value)===String(o)))?void 0:n.value;return t.createElement(Y,Object.assign({disabled:i,showSearch:!0,popupMatchSelectWidth:!1,getPopupContainer:e=>e.parentNode,"aria-label":a,options:d},V,{value:m,onChange:(e,t)=>{null==l||l(e),null==u||u(e,t)},size:W?"small":"middle",className:(0,s.default)(r,c)}))}}))))}],165370)},175712,e=>{"use strict";e.i(247167);var t=e.i(271645),n=e.i(343794),i=e.i(529681),o=e.i(242064),l=e.i(517455),a=e.i(185793),r=e.i(721369),d=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};let c=e=>{var{prefixCls:i,className:l,hoverable:a=!0}=e,r=d(e,["prefixCls","className","hoverable"]);let{getPrefixCls:c}=t.useContext(o.ConfigContext),s=c("card",i),u=(0,n.default)(`${s}-grid`,l,{[`${s}-grid-hoverable`]:a});return t.createElement("div",Object.assign({},r,{className:u}))};e.i(296059);var s=e.i(915654),u=e.i(183293),m=e.i(246422),g=e.i(838378);let p=(0,m.genStyleHooks)("Card",e=>{let t=(0,g.mergeToken)(e,{cardShadow:e.boxShadowCard,cardHeadPadding:e.padding,cardPaddingBase:e.paddingLG,cardActionsIconSize:e.fontSize});return[(e=>{let{componentCls:t,cardShadow:n,cardHeadPadding:i,colorBorderSecondary:o,boxShadowTertiary:l,bodyPadding:a,extraColor:r}=e;return{[t]:Object.assign(Object.assign({},(0,u.resetComponent)(e)),{position:"relative",background:e.colorBgContainer,borderRadius:e.borderRadiusLG,[`&:not(${t}-bordered)`]:{boxShadow:l},[`${t}-head`]:(e=>{let{antCls:t,componentCls:n,headerHeight:i,headerPadding:o,tabsMarginBottom:l}=e;return Object.assign(Object.assign({display:"flex",justifyContent:"center",flexDirection:"column",minHeight:i,marginBottom:-1,padding:`0 ${(0,s.unit)(o)}`,color:e.colorTextHeading,fontWeight:e.fontWeightStrong,fontSize:e.headerFontSize,background:e.headerBg,borderBottom:`${(0,s.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorderSecondary}`,borderRadius:`${(0,s.unit)(e.borderRadiusLG)} ${(0,s.unit)(e.borderRadiusLG)} 0 0`},(0,u.clearFix)()),{"&-wrapper":{width:"100%",display:"flex",alignItems:"center"},"&-title":Object.assign(Object.assign({display:"inline-block",flex:1},u.textEllipsis),{[` + > ${n}-typography, + > ${n}-typography-edit-content + `]:{insetInlineStart:0,marginTop:0,marginBottom:0}}),[`${t}-tabs-top`]:{clear:"both",marginBottom:l,color:e.colorText,fontWeight:"normal",fontSize:e.fontSize,"&-bar":{borderBottom:`${(0,s.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorderSecondary}`}}})})(e),[`${t}-extra`]:{marginInlineStart:"auto",color:r,fontWeight:"normal",fontSize:e.fontSize},[`${t}-body`]:{padding:a,borderRadius:`0 0 ${(0,s.unit)(e.borderRadiusLG)} ${(0,s.unit)(e.borderRadiusLG)}`},[`${t}-grid`]:(e=>{let{cardPaddingBase:t,colorBorderSecondary:n,cardShadow:i,lineWidth:o}=e;return{width:"33.33%",padding:t,border:0,borderRadius:0,boxShadow:` + ${(0,s.unit)(o)} 0 0 0 ${n}, + 0 ${(0,s.unit)(o)} 0 0 ${n}, + ${(0,s.unit)(o)} ${(0,s.unit)(o)} 0 0 ${n}, + ${(0,s.unit)(o)} 0 0 0 ${n} inset, + 0 ${(0,s.unit)(o)} 0 0 ${n} inset; + `,transition:`all ${e.motionDurationMid}`,"&-hoverable:hover":{position:"relative",zIndex:1,boxShadow:i}}})(e),[`${t}-cover`]:{"> *":{display:"block",width:"100%",borderRadius:`${(0,s.unit)(e.borderRadiusLG)} ${(0,s.unit)(e.borderRadiusLG)} 0 0`}},[`${t}-actions`]:(e=>{let{componentCls:t,iconCls:n,actionsLiMargin:i,cardActionsIconSize:o,colorBorderSecondary:l,actionsBg:a}=e;return Object.assign(Object.assign({margin:0,padding:0,listStyle:"none",background:a,borderTop:`${(0,s.unit)(e.lineWidth)} ${e.lineType} ${l}`,display:"flex",borderRadius:`0 0 ${(0,s.unit)(e.borderRadiusLG)} ${(0,s.unit)(e.borderRadiusLG)}`},(0,u.clearFix)()),{"& > li":{margin:i,color:e.colorTextDescription,textAlign:"center","> span":{position:"relative",display:"block",minWidth:e.calc(e.cardActionsIconSize).mul(2).equal(),fontSize:e.fontSize,lineHeight:e.lineHeight,cursor:"pointer","&:hover":{color:e.colorPrimary,transition:`color ${e.motionDurationMid}`},[`a:not(${t}-btn), > ${n}`]:{display:"inline-block",width:"100%",color:e.colorIcon,lineHeight:(0,s.unit)(e.fontHeight),transition:`color ${e.motionDurationMid}`,"&:hover":{color:e.colorPrimary}},[`> ${n}`]:{fontSize:o,lineHeight:(0,s.unit)(e.calc(o).mul(e.lineHeight).equal())}},"&:not(:last-child)":{borderInlineEnd:`${(0,s.unit)(e.lineWidth)} ${e.lineType} ${l}`}}})})(e),[`${t}-meta`]:Object.assign(Object.assign({margin:`${(0,s.unit)(e.calc(e.marginXXS).mul(-1).equal())} 0`,display:"flex"},(0,u.clearFix)()),{"&-avatar":{paddingInlineEnd:e.padding},"&-detail":{overflow:"hidden",flex:1,"> div:not(:last-child)":{marginBottom:e.marginXS}},"&-title":Object.assign({color:e.colorTextHeading,fontWeight:e.fontWeightStrong,fontSize:e.fontSizeLG},u.textEllipsis),"&-description":{color:e.colorTextDescription}})}),[`${t}-bordered`]:{border:`${(0,s.unit)(e.lineWidth)} ${e.lineType} ${o}`,[`${t}-cover`]:{marginTop:-1,marginInlineStart:-1,marginInlineEnd:-1}},[`${t}-hoverable`]:{cursor:"pointer",transition:`box-shadow ${e.motionDurationMid}, border-color ${e.motionDurationMid}`,"&:hover":{borderColor:"transparent",boxShadow:n}},[`${t}-contain-grid`]:{borderRadius:`${(0,s.unit)(e.borderRadiusLG)} ${(0,s.unit)(e.borderRadiusLG)} 0 0 `,[`${t}-body`]:{display:"flex",flexWrap:"wrap"},[`&:not(${t}-loading) ${t}-body`]:{marginBlockStart:e.calc(e.lineWidth).mul(-1).equal(),marginInlineStart:e.calc(e.lineWidth).mul(-1).equal(),padding:0}},[`${t}-contain-tabs`]:{[`> div${t}-head`]:{minHeight:0,[`${t}-head-title, ${t}-extra`]:{paddingTop:i}}},[`${t}-type-inner`]:(e=>{let{componentCls:t,colorFillAlter:n,headerPadding:i,bodyPadding:o}=e;return{[`${t}-head`]:{padding:`0 ${(0,s.unit)(i)}`,background:n,"&-title":{fontSize:e.fontSize}},[`${t}-body`]:{padding:`${(0,s.unit)(e.padding)} ${(0,s.unit)(o)}`}}})(e),[`${t}-loading`]:(e=>{let{componentCls:t}=e;return{overflow:"hidden",[`${t}-body`]:{userSelect:"none"}}})(e),[`${t}-rtl`]:{direction:"rtl"}}})(t),(e=>{let{componentCls:t,bodyPaddingSM:n,headerPaddingSM:i,headerHeightSM:o,headerFontSizeSM:l}=e;return{[`${t}-small`]:{[`> ${t}-head`]:{minHeight:o,padding:`0 ${(0,s.unit)(i)}`,fontSize:l,[`> ${t}-head-wrapper`]:{[`> ${t}-extra`]:{fontSize:e.fontSize}}},[`> ${t}-body`]:{padding:n}},[`${t}-small${t}-contain-tabs`]:{[`> ${t}-head`]:{[`${t}-head-title, ${t}-extra`]:{paddingTop:0,display:"flex",alignItems:"center"}}}}})(t)]},e=>{var t,n;return{headerBg:"transparent",headerFontSize:e.fontSizeLG,headerFontSizeSM:e.fontSize,headerHeight:e.fontSizeLG*e.lineHeightLG+2*e.padding,headerHeightSM:e.fontSize*e.lineHeight+2*e.paddingXS,actionsBg:e.colorBgContainer,actionsLiMargin:`${e.paddingSM}px 0`,tabsMarginBottom:-e.padding-e.lineWidth,extraColor:e.colorText,bodyPaddingSM:12,headerPaddingSM:12,bodyPadding:null!=(t=e.bodyPadding)?t:e.paddingLG,headerPadding:null!=(n=e.headerPadding)?n:e.paddingLG}});var b=e.i(792812),f=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};let h=e=>{let{actionClasses:n,actions:i=[],actionStyle:o}=e;return t.createElement("ul",{className:n,style:o},i.map((e,n)=>{let o=`action-${n}`;return t.createElement("li",{style:{width:`${100/i.length}%`},key:o},t.createElement("span",null,e))}))},v=t.forwardRef((e,d)=>{let s,{prefixCls:u,className:m,rootClassName:g,style:v,extra:$,headStyle:y={},bodyStyle:S={},title:C,loading:x,bordered:O,variant:k,size:j,type:E,cover:w,actions:z,tabList:N,children:I,activeTabKey:B,defaultActiveTabKey:M,tabBarExtraContent:P,hoverable:T,tabProps:R={},classNames:H,styles:D}=e,L=f(e,["prefixCls","className","rootClassName","style","extra","headStyle","bodyStyle","title","loading","bordered","variant","size","type","cover","actions","tabList","children","activeTabKey","defaultActiveTabKey","tabBarExtraContent","hoverable","tabProps","classNames","styles"]),{getPrefixCls:W,direction:A,card:q}=t.useContext(o.ConfigContext),[G]=(0,b.default)("card",k,O),_=e=>{var t;return(0,n.default)(null==(t=null==q?void 0:q.classNames)?void 0:t[e],null==H?void 0:H[e])},F=e=>{var t;return Object.assign(Object.assign({},null==(t=null==q?void 0:q.styles)?void 0:t[e]),null==D?void 0:D[e])},X=t.useMemo(()=>{let e=!1;return t.Children.forEach(I,t=>{(null==t?void 0:t.type)===c&&(e=!0)}),e},[I]),K=W("card",u),[U,J,Q]=p(K),V=t.createElement(a.default,{loading:!0,active:!0,paragraph:{rows:4},title:!1},I),Y=void 0!==B,Z=Object.assign(Object.assign({},R),{[Y?"activeKey":"defaultActiveKey"]:Y?B:M,tabBarExtraContent:P}),ee=(0,l.default)(j),et=ee&&"default"!==ee?ee:"large",en=N?t.createElement(r.default,Object.assign({size:et},Z,{className:`${K}-head-tabs`,onChange:t=>{var n;null==(n=e.onTabChange)||n.call(e,t)},items:N.map(e=>{var{tab:t}=e;return Object.assign({label:t},f(e,["tab"]))})})):null;if(C||$||en){let e=(0,n.default)(`${K}-head`,_("header")),i=(0,n.default)(`${K}-head-title`,_("title")),o=(0,n.default)(`${K}-extra`,_("extra")),l=Object.assign(Object.assign({},y),F("header"));s=t.createElement("div",{className:e,style:l},t.createElement("div",{className:`${K}-head-wrapper`},C&&t.createElement("div",{className:i,style:F("title")},C),$&&t.createElement("div",{className:o,style:F("extra")},$)),en)}let ei=(0,n.default)(`${K}-cover`,_("cover")),eo=w?t.createElement("div",{className:ei,style:F("cover")},w):null,el=(0,n.default)(`${K}-body`,_("body")),ea=Object.assign(Object.assign({},S),F("body")),er=t.createElement("div",{className:el,style:ea},x?V:I),ed=(0,n.default)(`${K}-actions`,_("actions")),ec=(null==z?void 0:z.length)?t.createElement(h,{actionClasses:ed,actionStyle:F("actions"),actions:z}):null,es=(0,i.default)(L,["onTabChange"]),eu=(0,n.default)(K,null==q?void 0:q.className,{[`${K}-loading`]:x,[`${K}-bordered`]:"borderless"!==G,[`${K}-hoverable`]:T,[`${K}-contain-grid`]:X,[`${K}-contain-tabs`]:null==N?void 0:N.length,[`${K}-${ee}`]:ee,[`${K}-type-${E}`]:!!E,[`${K}-rtl`]:"rtl"===A},m,g,J,Q),em=Object.assign(Object.assign({},null==q?void 0:q.style),v);return U(t.createElement("div",Object.assign({ref:d},es,{className:eu,style:em}),s,eo,er,ec))});var $=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};v.Grid=c,v.Meta=e=>{let{prefixCls:i,className:l,avatar:a,title:r,description:d}=e,c=$(e,["prefixCls","className","avatar","title","description"]),{getPrefixCls:s}=t.useContext(o.ConfigContext),u=s("card",i),m=(0,n.default)(`${u}-meta`,l),g=a?t.createElement("div",{className:`${u}-meta-avatar`},a):null,p=r?t.createElement("div",{className:`${u}-meta-title`},r):null,b=d?t.createElement("div",{className:`${u}-meta-description`},d):null,f=p||b?t.createElement("div",{className:`${u}-meta-detail`},p,b):null;return t.createElement("div",Object.assign({},c,{className:m}),g,f)},e.s(["Card",0,v],175712)},544195,e=>{"use strict";var t=e.i(271645),n=e.i(343794),i=e.i(981444),o=e.i(914949),l=e.i(244009),a=e.i(242064),r=e.i(321883),d=e.i(517455);let c=t.createContext(null),s=c.Provider,u=t.createContext(null),m=u.Provider;e.i(247167);var g=e.i(91874),p=e.i(611935),b=e.i(121872),f=e.i(26905),h=e.i(681216),v=e.i(937328),$=e.i(62139);e.i(296059);var y=e.i(915654),S=e.i(183293),C=e.i(246422),x=e.i(838378);let O=(0,C.genStyleHooks)("Radio",e=>{let{controlOutline:t,controlOutlineWidth:n}=e,i=`0 0 0 ${(0,y.unit)(n)} ${t}`,o=(0,x.mergeToken)(e,{radioFocusShadow:i,radioButtonFocusShadow:i});return[(e=>{let{componentCls:t,antCls:n}=e,i=`${t}-group`;return{[i]:Object.assign(Object.assign({},(0,S.resetComponent)(e)),{display:"inline-block",fontSize:0,[`&${i}-rtl`]:{direction:"rtl"},[`&${i}-block`]:{display:"flex"},[`${n}-badge ${n}-badge-count`]:{zIndex:1},[`> ${n}-badge:not(:first-child) > ${n}-button-wrapper`]:{borderInlineStart:"none"}})}})(o),(e=>{let{componentCls:t,wrapperMarginInlineEnd:n,colorPrimary:i,radioSize:o,motionDurationSlow:l,motionDurationMid:a,motionEaseInOutCirc:r,colorBgContainer:d,colorBorder:c,lineWidth:s,colorBgContainerDisabled:u,colorTextDisabled:m,paddingXS:g,dotColorDisabled:p,lineType:b,radioColor:f,radioBgColor:h,calc:v}=e,$=`${t}-inner`,C=v(o).sub(v(4).mul(2)),x=v(1).mul(o).equal({unit:!0});return{[`${t}-wrapper`]:Object.assign(Object.assign({},(0,S.resetComponent)(e)),{display:"inline-flex",alignItems:"baseline",marginInlineStart:0,marginInlineEnd:n,cursor:"pointer","&:last-child":{marginInlineEnd:0},[`&${t}-wrapper-rtl`]:{direction:"rtl"},"&-disabled":{cursor:"not-allowed",color:e.colorTextDisabled},"&::after":{display:"inline-block",width:0,overflow:"hidden",content:'"\\a0"'},"&-block":{flex:1,justifyContent:"center"},[`${t}-checked::after`]:{position:"absolute",insetBlockStart:0,insetInlineStart:0,width:"100%",height:"100%",border:`${(0,y.unit)(s)} ${b} ${i}`,borderRadius:"50%",visibility:"hidden",opacity:0,content:'""'},[t]:Object.assign(Object.assign({},(0,S.resetComponent)(e)),{position:"relative",display:"inline-block",outline:"none",cursor:"pointer",alignSelf:"center",borderRadius:"50%"}),[`${t}-wrapper:hover &, + &:hover ${$}`]:{borderColor:i},[`${t}-input:focus-visible + ${$}`]:(0,S.genFocusOutline)(e),[`${t}:hover::after, ${t}-wrapper:hover &::after`]:{visibility:"visible"},[`${t}-inner`]:{"&::after":{boxSizing:"border-box",position:"absolute",insetBlockStart:"50%",insetInlineStart:"50%",display:"block",width:x,height:x,marginBlockStart:v(1).mul(o).div(-2).equal({unit:!0}),marginInlineStart:v(1).mul(o).div(-2).equal({unit:!0}),backgroundColor:f,borderBlockStart:0,borderInlineStart:0,borderRadius:x,transform:"scale(0)",opacity:0,transition:`all ${l} ${r}`,content:'""'},boxSizing:"border-box",position:"relative",insetBlockStart:0,insetInlineStart:0,display:"block",width:x,height:x,backgroundColor:d,borderColor:c,borderStyle:"solid",borderWidth:s,borderRadius:"50%",transition:`all ${a}`},[`${t}-input`]:{position:"absolute",inset:0,zIndex:1,cursor:"pointer",opacity:0},[`${t}-checked`]:{[$]:{borderColor:i,backgroundColor:h,"&::after":{transform:`scale(${e.calc(e.dotSize).div(o).equal()})`,opacity:1,transition:`all ${l} ${r}`}}},[`${t}-disabled`]:{cursor:"not-allowed",[$]:{backgroundColor:u,borderColor:c,cursor:"not-allowed","&::after":{backgroundColor:p}},[`${t}-input`]:{cursor:"not-allowed"},[`${t}-disabled + span`]:{color:m,cursor:"not-allowed"},[`&${t}-checked`]:{[$]:{"&::after":{transform:`scale(${v(C).div(o).equal()})`}}}},[`span${t} + *`]:{paddingInlineStart:g,paddingInlineEnd:g}})}})(o),(e=>{let{buttonColor:t,controlHeight:n,componentCls:i,lineWidth:o,lineType:l,colorBorder:a,motionDurationMid:r,buttonPaddingInline:d,fontSize:c,buttonBg:s,fontSizeLG:u,controlHeightLG:m,controlHeightSM:g,paddingXS:p,borderRadius:b,borderRadiusSM:f,borderRadiusLG:h,buttonCheckedBg:v,buttonSolidCheckedColor:$,colorTextDisabled:C,colorBgContainerDisabled:x,buttonCheckedBgDisabled:O,buttonCheckedColorDisabled:k,colorPrimary:j,colorPrimaryHover:E,colorPrimaryActive:w,buttonSolidCheckedBg:z,buttonSolidCheckedHoverBg:N,buttonSolidCheckedActiveBg:I,calc:B}=e;return{[`${i}-button-wrapper`]:{position:"relative",display:"inline-block",height:n,margin:0,paddingInline:d,paddingBlock:0,color:t,fontSize:c,lineHeight:(0,y.unit)(B(n).sub(B(o).mul(2)).equal()),background:s,border:`${(0,y.unit)(o)} ${l} ${a}`,borderBlockStartWidth:B(o).add(.02).equal(),borderInlineEndWidth:o,cursor:"pointer",transition:`color ${r},background ${r},box-shadow ${r}`,a:{color:t},[`> ${i}-button`]:{position:"absolute",insetBlockStart:0,insetInlineStart:0,zIndex:-1,width:"100%",height:"100%"},"&:not(:last-child)":{marginInlineEnd:B(o).mul(-1).equal()},"&:first-child":{borderInlineStart:`${(0,y.unit)(o)} ${l} ${a}`,borderStartStartRadius:b,borderEndStartRadius:b},"&:last-child":{borderStartEndRadius:b,borderEndEndRadius:b},"&:first-child:last-child":{borderRadius:b},[`${i}-group-large &`]:{height:m,fontSize:u,lineHeight:(0,y.unit)(B(m).sub(B(o).mul(2)).equal()),"&:first-child":{borderStartStartRadius:h,borderEndStartRadius:h},"&:last-child":{borderStartEndRadius:h,borderEndEndRadius:h}},[`${i}-group-small &`]:{height:g,paddingInline:B(p).sub(o).equal(),paddingBlock:0,lineHeight:(0,y.unit)(B(g).sub(B(o).mul(2)).equal()),"&:first-child":{borderStartStartRadius:f,borderEndStartRadius:f},"&:last-child":{borderStartEndRadius:f,borderEndEndRadius:f}},"&:hover":{position:"relative",color:j},"&:has(:focus-visible)":(0,S.genFocusOutline)(e),[`${i}-inner, input[type='checkbox'], input[type='radio']`]:{width:0,height:0,opacity:0,pointerEvents:"none"},[`&-checked:not(${i}-button-wrapper-disabled)`]:{zIndex:1,color:j,background:v,borderColor:j,"&::before":{backgroundColor:j},"&:first-child":{borderColor:j},"&:hover":{color:E,borderColor:E,"&::before":{backgroundColor:E}},"&:active":{color:w,borderColor:w,"&::before":{backgroundColor:w}}},[`${i}-group-solid &-checked:not(${i}-button-wrapper-disabled)`]:{color:$,background:z,borderColor:z,"&:hover":{color:$,background:N,borderColor:N},"&:active":{color:$,background:I,borderColor:I}},"&-disabled":{color:C,backgroundColor:x,borderColor:a,cursor:"not-allowed","&:first-child, &:hover":{color:C,backgroundColor:x,borderColor:a}},[`&-disabled${i}-button-wrapper-checked`]:{color:k,backgroundColor:O,borderColor:a,boxShadow:"none"},"&-block":{flex:1,textAlign:"center"}}}})(o)]},e=>{let{wireframe:t,padding:n,marginXS:i,lineWidth:o,fontSizeLG:l,colorText:a,colorBgContainer:r,colorTextDisabled:d,controlItemBgActiveDisabled:c,colorTextLightSolid:s,colorPrimary:u,colorPrimaryHover:m,colorPrimaryActive:g,colorWhite:p}=e;return{radioSize:l,dotSize:t?l-8:l-(4+o)*2,dotColorDisabled:d,buttonSolidCheckedColor:s,buttonSolidCheckedBg:u,buttonSolidCheckedHoverBg:m,buttonSolidCheckedActiveBg:g,buttonBg:r,buttonCheckedBg:r,buttonColor:a,buttonCheckedBgDisabled:c,buttonCheckedColorDisabled:d,buttonPaddingInline:n-o,wrapperMarginInlineEnd:i,radioColor:t?u:p,radioBgColor:t?r:u}},{unitless:{radioSize:!0,dotSize:!0}});var k=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};let j=t.forwardRef((e,i)=>{var o,l;let d=t.useContext(c),s=t.useContext(u),{getPrefixCls:m,direction:y,radio:S}=t.useContext(a.ConfigContext),C=t.useRef(null),x=(0,p.composeRef)(i,C),{isFormItemInput:j}=t.useContext($.FormItemInputContext),{prefixCls:E,className:w,rootClassName:z,children:N,style:I,title:B}=e,M=k(e,["prefixCls","className","rootClassName","children","style","title"]),P=m("radio",E),T="button"===((null==d?void 0:d.optionType)||s),R=T?`${P}-button`:P,H=(0,r.default)(P),[D,L,W]=O(P,H),A=Object.assign({},M),q=t.useContext(v.default);d&&(A.name=d.name,A.onChange=t=>{var n,i;null==(n=e.onChange)||n.call(e,t),null==(i=null==d?void 0:d.onChange)||i.call(d,t)},A.checked=e.value===d.value,A.disabled=null!=(o=A.disabled)?o:d.disabled),A.disabled=null!=(l=A.disabled)?l:q;let G=(0,n.default)(`${R}-wrapper`,{[`${R}-wrapper-checked`]:A.checked,[`${R}-wrapper-disabled`]:A.disabled,[`${R}-wrapper-rtl`]:"rtl"===y,[`${R}-wrapper-in-form-item`]:j,[`${R}-wrapper-block`]:!!(null==d?void 0:d.block)},null==S?void 0:S.className,w,z,L,W,H),[_,F]=(0,h.default)(A.onClick);return D(t.createElement(b.default,{component:"Radio",disabled:A.disabled},t.createElement("label",{className:G,style:Object.assign(Object.assign({},null==S?void 0:S.style),I),onMouseEnter:e.onMouseEnter,onMouseLeave:e.onMouseLeave,title:B,onClick:_},t.createElement(g.default,Object.assign({},A,{className:(0,n.default)(A.className,{[f.TARGET_CLS]:!T}),type:"radio",prefixCls:R,ref:x,onClick:F})),void 0!==N?t.createElement("span",{className:`${R}-label`},N):null)))});var E=e.i(286039);let w=t.forwardRef((e,c)=>{let{getPrefixCls:u,direction:m}=t.useContext(a.ConfigContext),{name:g}=t.useContext($.FormItemInputContext),p=(0,i.default)((0,E.toNamePathStr)(g)),{prefixCls:b,className:f,rootClassName:h,options:v,buttonStyle:y="outline",disabled:S,children:C,size:x,style:k,id:w,optionType:z,name:N=p,defaultValue:I,value:B,block:M=!1,onChange:P,onMouseEnter:T,onMouseLeave:R,onFocus:H,onBlur:D}=e,[L,W]=(0,o.default)(I,{value:B}),A=t.useCallback(t=>{let n=t.target.value;"value"in e||W(n),n!==L&&(null==P||P(t))},[L,W,P]),q=u("radio",b),G=`${q}-group`,_=(0,r.default)(q),[F,X,K]=O(q,_),U=C;v&&v.length>0&&(U=v.map(e=>"string"==typeof e||"number"==typeof e?t.createElement(j,{key:e.toString(),prefixCls:q,disabled:S,value:e,checked:L===e},e):t.createElement(j,{key:`radio-group-value-options-${e.value}`,prefixCls:q,disabled:e.disabled||S,value:e.value,checked:L===e.value,title:e.title,style:e.style,className:e.className,id:e.id,required:e.required},e.label)));let J=(0,d.default)(x),Q=(0,n.default)(G,`${G}-${y}`,{[`${G}-${J}`]:J,[`${G}-rtl`]:"rtl"===m,[`${G}-block`]:M},f,h,X,K,_),V=t.useMemo(()=>({onChange:A,value:L,disabled:S,name:N,optionType:z,block:M}),[A,L,S,N,z,M]);return F(t.createElement("div",Object.assign({},(0,l.default)(e,{aria:!0,data:!0}),{className:Q,style:k,onMouseEnter:T,onMouseLeave:R,onFocus:H,onBlur:D,id:w,ref:c}),t.createElement(s,{value:V},U)))}),z=t.memo(w);var N=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};let I=t.forwardRef((e,n)=>{let{getPrefixCls:i}=t.useContext(a.ConfigContext),{prefixCls:o}=e,l=N(e,["prefixCls"]),r=i("radio",o);return t.createElement(m,{value:"button"},t.createElement(j,Object.assign({prefixCls:r},l,{type:"radio",ref:n})))});j.Button=I,j.Group=z,j.__ANT_RADIO=!0,e.s(["default",0,j],544195)},869216,e=>{"use strict";e.i(247167);var t=e.i(271645),n=e.i(343794),i=e.i(908206),o=e.i(242064),l=e.i(517455),a=e.i(150073);let r={xxl:3,xl:3,lg:3,md:3,sm:2,xs:1},d=t.default.createContext({});var c=e.i(876556),s=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n},u=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};let m=e=>{let{itemPrefixCls:i,component:o,span:l,className:a,style:r,labelStyle:c,contentStyle:s,bordered:u,label:m,content:g,colon:p,type:b,styles:f}=e,{classNames:h}=t.useContext(d),v=Object.assign(Object.assign({},c),null==f?void 0:f.label),$=Object.assign(Object.assign({},s),null==f?void 0:f.content);if(u)return t.createElement(o,{colSpan:l,style:r,className:(0,n.default)(a,{[`${i}-item-${b}`]:"label"===b||"content"===b,[null==h?void 0:h.label]:(null==h?void 0:h.label)&&"label"===b,[null==h?void 0:h.content]:(null==h?void 0:h.content)&&"content"===b})},null!=m&&t.createElement("span",{style:v},m),null!=g&&t.createElement("span",{style:$},g));return t.createElement(o,{colSpan:l,style:r,className:(0,n.default)(`${i}-item`,a)},t.createElement("div",{className:`${i}-item-container`},null!=m&&t.createElement("span",{style:v,className:(0,n.default)(`${i}-item-label`,null==h?void 0:h.label,{[`${i}-item-no-colon`]:!p})},m),null!=g&&t.createElement("span",{style:$,className:(0,n.default)(`${i}-item-content`,null==h?void 0:h.content)},g)))};function g(e,{colon:n,prefixCls:i,bordered:o},{component:l,type:a,showLabel:r,showContent:d,labelStyle:c,contentStyle:s,styles:u}){return e.map(({label:e,children:g,prefixCls:p=i,className:b,style:f,labelStyle:h,contentStyle:v,span:$=1,key:y,styles:S},C)=>"string"==typeof l?t.createElement(m,{key:`${a}-${y||C}`,className:b,style:f,styles:{label:Object.assign(Object.assign(Object.assign(Object.assign({},c),null==u?void 0:u.label),h),null==S?void 0:S.label),content:Object.assign(Object.assign(Object.assign(Object.assign({},s),null==u?void 0:u.content),v),null==S?void 0:S.content)},span:$,colon:n,component:l,itemPrefixCls:p,bordered:o,label:r?e:null,content:d?g:null,type:a}):[t.createElement(m,{key:`label-${y||C}`,className:b,style:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},c),null==u?void 0:u.label),f),h),null==S?void 0:S.label),span:1,colon:n,component:l[0],itemPrefixCls:p,bordered:o,label:e,type:"label"}),t.createElement(m,{key:`content-${y||C}`,className:b,style:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},s),null==u?void 0:u.content),f),v),null==S?void 0:S.content),span:2*$-1,component:l[1],itemPrefixCls:p,bordered:o,content:g,type:"content"})])}let p=e=>{let n=t.useContext(d),{prefixCls:i,vertical:o,row:l,index:a,bordered:r}=e;return o?t.createElement(t.Fragment,null,t.createElement("tr",{key:`label-${a}`,className:`${i}-row`},g(l,e,Object.assign({component:"th",type:"label",showLabel:!0},n))),t.createElement("tr",{key:`content-${a}`,className:`${i}-row`},g(l,e,Object.assign({component:"td",type:"content",showContent:!0},n)))):t.createElement("tr",{key:a,className:`${i}-row`},g(l,e,Object.assign({component:r?["th","td"]:"td",type:"item",showLabel:!0,showContent:!0},n)))};e.i(296059);var b=e.i(915654),f=e.i(183293),h=e.i(246422),v=e.i(838378);let $=(0,h.genStyleHooks)("Descriptions",e=>(e=>{let{componentCls:t,extraColor:n,itemPaddingBottom:i,itemPaddingEnd:o,colonMarginRight:l,colonMarginLeft:a,titleMarginBottom:r}=e;return{[t]:Object.assign(Object.assign(Object.assign({},(0,f.resetComponent)(e)),(e=>{let{componentCls:t,labelBg:n}=e;return{[`&${t}-bordered`]:{[`> ${t}-view`]:{border:`${(0,b.unit)(e.lineWidth)} ${e.lineType} ${e.colorSplit}`,"> table":{tableLayout:"auto"},[`${t}-row`]:{borderBottom:`${(0,b.unit)(e.lineWidth)} ${e.lineType} ${e.colorSplit}`,"&:first-child":{"> th:first-child, > td:first-child":{borderStartStartRadius:e.borderRadiusLG}},"&:last-child":{borderBottom:"none","> th:first-child, > td:first-child":{borderEndStartRadius:e.borderRadiusLG}},[`> ${t}-item-label, > ${t}-item-content`]:{padding:`${(0,b.unit)(e.padding)} ${(0,b.unit)(e.paddingLG)}`,borderInlineEnd:`${(0,b.unit)(e.lineWidth)} ${e.lineType} ${e.colorSplit}`,"&:last-child":{borderInlineEnd:"none"}},[`> ${t}-item-label`]:{color:e.colorTextSecondary,backgroundColor:n,"&::after":{display:"none"}}}},[`&${t}-middle`]:{[`${t}-row`]:{[`> ${t}-item-label, > ${t}-item-content`]:{padding:`${(0,b.unit)(e.paddingSM)} ${(0,b.unit)(e.paddingLG)}`}}},[`&${t}-small`]:{[`${t}-row`]:{[`> ${t}-item-label, > ${t}-item-content`]:{padding:`${(0,b.unit)(e.paddingXS)} ${(0,b.unit)(e.padding)}`}}}}}})(e)),{"&-rtl":{direction:"rtl"},[`${t}-header`]:{display:"flex",alignItems:"center",marginBottom:r},[`${t}-title`]:Object.assign(Object.assign({},f.textEllipsis),{flex:"auto",color:e.titleColor,fontWeight:e.fontWeightStrong,fontSize:e.fontSizeLG,lineHeight:e.lineHeightLG}),[`${t}-extra`]:{marginInlineStart:"auto",color:n,fontSize:e.fontSize},[`${t}-view`]:{width:"100%",borderRadius:e.borderRadiusLG,table:{width:"100%",tableLayout:"fixed",borderCollapse:"collapse"}},[`${t}-row`]:{"> th, > td":{paddingBottom:i,paddingInlineEnd:o},"> th:last-child, > td:last-child":{paddingInlineEnd:0},"&:last-child":{borderBottom:"none","> th, > td":{paddingBottom:0}}},[`${t}-item-label`]:{color:e.labelColor,fontWeight:"normal",fontSize:e.fontSize,lineHeight:e.lineHeight,textAlign:"start","&::after":{content:'":"',position:"relative",top:-.5,marginInline:`${(0,b.unit)(a)} ${(0,b.unit)(l)}`},[`&${t}-item-no-colon::after`]:{content:'""'}},[`${t}-item-no-label`]:{"&::after":{margin:0,content:'""'}},[`${t}-item-content`]:{display:"table-cell",flex:1,color:e.contentColor,fontSize:e.fontSize,lineHeight:e.lineHeight,wordBreak:"break-word",overflowWrap:"break-word"},[`${t}-item`]:{paddingBottom:0,verticalAlign:"top","&-container":{display:"flex",[`${t}-item-label`]:{display:"inline-flex",alignItems:"baseline"},[`${t}-item-content`]:{display:"inline-flex",alignItems:"baseline",minWidth:"1em"}}},"&-middle":{[`${t}-row`]:{"> th, > td":{paddingBottom:e.paddingSM}}},"&-small":{[`${t}-row`]:{"> th, > td":{paddingBottom:e.paddingXS}}}})}})((0,v.mergeToken)(e,{})),e=>({labelBg:e.colorFillAlter,labelColor:e.colorTextTertiary,titleColor:e.colorText,titleMarginBottom:e.fontSizeSM*e.lineHeightSM,itemPaddingBottom:e.padding,itemPaddingEnd:e.padding,colonMarginRight:e.marginXS,colonMarginLeft:e.marginXXS/2,contentColor:e.colorText,extraColor:e.colorText}));var y=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&0>t.indexOf(i)&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,i=Object.getOwnPropertySymbols(e);ot.indexOf(i[o])&&Object.prototype.propertyIsEnumerable.call(e,i[o])&&(n[i[o]]=e[i[o]]);return n};let S=e=>{let m,{prefixCls:g,title:b,extra:f,column:h,colon:v=!0,bordered:S,layout:C,children:x,className:O,rootClassName:k,style:j,size:E,labelStyle:w,contentStyle:z,styles:N,items:I,classNames:B}=e,M=y(e,["prefixCls","title","extra","column","colon","bordered","layout","children","className","rootClassName","style","size","labelStyle","contentStyle","styles","items","classNames"]),{getPrefixCls:P,direction:T,className:R,style:H,classNames:D,styles:L}=(0,o.useComponentConfig)("descriptions"),W=P("descriptions",g),A=(0,a.default)(),q=t.useMemo(()=>{var e;return"number"==typeof h?h:null!=(e=(0,i.matchScreen)(A,Object.assign(Object.assign({},r),h)))?e:3},[A,h]),G=(m=t.useMemo(()=>I||(0,c.default)(x).map(e=>Object.assign(Object.assign({},null==e?void 0:e.props),{key:e.key})),[I,x]),t.useMemo(()=>m.map(e=>{var{span:t}=e,n=s(e,["span"]);return"filled"===t?Object.assign(Object.assign({},n),{filled:!0}):Object.assign(Object.assign({},n),{span:"number"==typeof t?t:(0,i.matchScreen)(A,t)})}),[m,A])),_=(0,l.default)(E),F=((e,n)=>{let[i,o]=(0,t.useMemo)(()=>{let t,i,o,l;return t=[],i=[],o=!1,l=0,n.filter(e=>e).forEach(n=>{let{filled:a}=n,r=u(n,["filled"]);if(a){i.push(r),t.push(i),i=[],l=0;return}let d=e-l;(l+=n.span||1)>=e?(l>e?(o=!0,i.push(Object.assign(Object.assign({},r),{span:d}))):i.push(r),t.push(i),i=[],l=0):i.push(r)}),i.length>0&&t.push(i),[t=t.map(t=>{let n=t.reduce((e,t)=>e+(t.span||1),0);if(n({labelStyle:w,contentStyle:z,styles:{content:Object.assign(Object.assign({},L.content),null==N?void 0:N.content),label:Object.assign(Object.assign({},L.label),null==N?void 0:N.label)},classNames:{label:(0,n.default)(D.label,null==B?void 0:B.label),content:(0,n.default)(D.content,null==B?void 0:B.content)}}),[w,z,N,B,D,L]);return X(t.createElement(d.Provider,{value:J},t.createElement("div",Object.assign({className:(0,n.default)(W,R,D.root,null==B?void 0:B.root,{[`${W}-${_}`]:_&&"default"!==_,[`${W}-bordered`]:!!S,[`${W}-rtl`]:"rtl"===T},O,k,K,U),style:Object.assign(Object.assign(Object.assign(Object.assign({},H),L.root),null==N?void 0:N.root),j)},M),(b||f)&&t.createElement("div",{className:(0,n.default)(`${W}-header`,D.header,null==B?void 0:B.header),style:Object.assign(Object.assign({},L.header),null==N?void 0:N.header)},b&&t.createElement("div",{className:(0,n.default)(`${W}-title`,D.title,null==B?void 0:B.title),style:Object.assign(Object.assign({},L.title),null==N?void 0:N.title)},b),f&&t.createElement("div",{className:(0,n.default)(`${W}-extra`,D.extra,null==B?void 0:B.extra),style:Object.assign(Object.assign({},L.extra),null==N?void 0:N.extra)},f)),t.createElement("div",{className:`${W}-view`},t.createElement("table",null,t.createElement("tbody",null,F.map((e,n)=>t.createElement(p,{key:n,index:n,colon:v,prefixCls:W,vertical:"vertical"===C,bordered:S,row:e}))))))))};S.Item=({children:e})=>e,e.s(["Descriptions",0,S],869216)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/0f4e333632824936.js b/litellm/proxy/_experimental/out/_next/static/chunks/0f4e333632824936.js deleted file mode 100644 index 4af8b60dbe4..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/0f4e333632824936.js +++ /dev/null @@ -1,7 +0,0 @@ -(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,91874,e=>{"use strict";var t=e.i(931067),r=e.i(209428),n=e.i(211577),o=e.i(392221),i=e.i(703923),l=e.i(343794),a=e.i(914949),s=e.i(271645),c=["prefixCls","className","style","checked","disabled","defaultChecked","type","title","onChange"],u=(0,s.forwardRef)(function(e,u){var d=e.prefixCls,p=void 0===d?"rc-checkbox":d,f=e.className,g=e.style,m=e.checked,b=e.disabled,h=e.defaultChecked,v=e.type,y=void 0===v?"checkbox":v,$=e.title,C=e.onChange,k=(0,i.default)(e,c),x=(0,s.useRef)(null),S=(0,s.useRef)(null),O=(0,a.default)(void 0!==h&&h,{value:m}),w=(0,o.default)(O,2),E=w[0],j=w[1];(0,s.useImperativeHandle)(u,function(){return{focus:function(e){var t;null==(t=x.current)||t.focus(e)},blur:function(){var e;null==(e=x.current)||e.blur()},input:x.current,nativeElement:S.current}});var N=(0,l.default)(p,f,(0,n.default)((0,n.default)({},"".concat(p,"-checked"),E),"".concat(p,"-disabled"),b));return s.createElement("span",{className:N,title:$,style:g,ref:S},s.createElement("input",(0,t.default)({},k,{className:"".concat(p,"-input"),ref:x,onChange:function(t){b||("checked"in e||j(t.target.checked),null==C||C({target:(0,r.default)((0,r.default)({},e),{},{type:y,checked:t.target.checked}),stopPropagation:function(){t.stopPropagation()},preventDefault:function(){t.preventDefault()},nativeEvent:t.nativeEvent}))},disabled:b,checked:!!E,type:y})),s.createElement("span",{className:"".concat(p,"-inner")}))});e.s(["default",0,u])},681216,e=>{"use strict";var t=e.i(271645),r=e.i(963188);function n(e){let n=t.default.useRef(null),o=()=>{r.default.cancel(n.current),n.current=null};return[()=>{o(),n.current=(0,r.default)(()=>{n.current=null})},t=>{n.current&&(t.stopPropagation(),o()),null==e||e(t)}]}e.s(["default",()=>n])},421512,236836,e=>{"use strict";let t=e.i(271645).default.createContext(null);e.s(["default",0,t],421512),e.i(296059);var r=e.i(915654),n=e.i(183293),o=e.i(246422),i=e.i(838378);function l(e,t){return(e=>{let{checkboxCls:t}=e,o=`${t}-wrapper`;return[{[`${t}-group`]:Object.assign(Object.assign({},(0,n.resetComponent)(e)),{display:"inline-flex",flexWrap:"wrap",columnGap:e.marginXS,[`> ${e.antCls}-row`]:{flex:1}}),[o]:Object.assign(Object.assign({},(0,n.resetComponent)(e)),{display:"inline-flex",alignItems:"baseline",cursor:"pointer","&:after":{display:"inline-block",width:0,overflow:"hidden",content:"'\\a0'"},[`& + ${o}`]:{marginInlineStart:0},[`&${o}-in-form-item`]:{'input[type="checkbox"]':{width:14,height:14}}}),[t]:Object.assign(Object.assign({},(0,n.resetComponent)(e)),{position:"relative",whiteSpace:"nowrap",lineHeight:1,cursor:"pointer",borderRadius:e.borderRadiusSM,alignSelf:"center",[`${t}-input`]:{position:"absolute",inset:0,zIndex:1,cursor:"pointer",opacity:0,margin:0,[`&:focus-visible + ${t}-inner`]:(0,n.genFocusOutline)(e)},[`${t}-inner`]:{boxSizing:"border-box",display:"block",width:e.checkboxSize,height:e.checkboxSize,direction:"ltr",backgroundColor:e.colorBgContainer,border:`${(0,r.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderRadius:e.borderRadiusSM,borderCollapse:"separate",transition:`all ${e.motionDurationSlow}`,"&:after":{boxSizing:"border-box",position:"absolute",top:"50%",insetInlineStart:"25%",display:"table",width:e.calc(e.checkboxSize).div(14).mul(5).equal(),height:e.calc(e.checkboxSize).div(14).mul(8).equal(),border:`${(0,r.unit)(e.lineWidthBold)} solid ${e.colorWhite}`,borderTop:0,borderInlineStart:0,transform:"rotate(45deg) scale(0) translate(-50%,-50%)",opacity:0,content:'""',transition:`all ${e.motionDurationFast} ${e.motionEaseInBack}, opacity ${e.motionDurationFast}`}},"& + span":{paddingInlineStart:e.paddingXS,paddingInlineEnd:e.paddingXS}})},{[` - ${o}:not(${o}-disabled), - ${t}:not(${t}-disabled) - `]:{[`&:hover ${t}-inner`]:{borderColor:e.colorPrimary}},[`${o}:not(${o}-disabled)`]:{[`&:hover ${t}-checked:not(${t}-disabled) ${t}-inner`]:{backgroundColor:e.colorPrimaryHover,borderColor:"transparent"},[`&:hover ${t}-checked:not(${t}-disabled):after`]:{borderColor:e.colorPrimaryHover}}},{[`${t}-checked`]:{[`${t}-inner`]:{backgroundColor:e.colorPrimary,borderColor:e.colorPrimary,"&:after":{opacity:1,transform:"rotate(45deg) scale(1) translate(-50%,-50%)",transition:`all ${e.motionDurationMid} ${e.motionEaseOutBack} ${e.motionDurationFast}`}}},[` - ${o}-checked:not(${o}-disabled), - ${t}-checked:not(${t}-disabled) - `]:{[`&:hover ${t}-inner`]:{backgroundColor:e.colorPrimaryHover,borderColor:"transparent"}}},{[t]:{"&-indeterminate":{"&":{[`${t}-inner`]:{backgroundColor:`${e.colorBgContainer}`,borderColor:`${e.colorBorder}`,"&:after":{top:"50%",insetInlineStart:"50%",width:e.calc(e.fontSizeLG).div(2).equal(),height:e.calc(e.fontSizeLG).div(2).equal(),backgroundColor:e.colorPrimary,border:0,transform:"translate(-50%, -50%) scale(1)",opacity:1,content:'""'}},[`&:hover ${t}-inner`]:{backgroundColor:`${e.colorBgContainer}`,borderColor:`${e.colorPrimary}`}}}}},{[`${o}-disabled`]:{cursor:"not-allowed"},[`${t}-disabled`]:{[`&, ${t}-input`]:{cursor:"not-allowed",pointerEvents:"none"},[`${t}-inner`]:{background:e.colorBgContainerDisabled,borderColor:e.colorBorder,"&:after":{borderColor:e.colorTextDisabled}},"&:after":{display:"none"},"& + span":{color:e.colorTextDisabled},[`&${t}-indeterminate ${t}-inner::after`]:{background:e.colorTextDisabled}}}]})((0,i.mergeToken)(t,{checkboxCls:`.${e}`,checkboxSize:t.controlInteractiveSize}))}let a=(0,o.genStyleHooks)("Checkbox",(e,{prefixCls:t})=>[l(t,e)]);e.s(["default",0,a,"getStyle",()=>l],236836)},536916,374276,e=>{"use strict";e.i(247167);var t=e.i(271645),r=e.i(343794),n=e.i(91874),o=e.i(611935),i=e.i(121872),l=e.i(26905),a=e.i(242064),s=e.i(937328),c=e.i(321883),u=e.i(62139),d=e.i(421512),p=e.i(236836),f=e.i(681216),g=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=t.forwardRef((e,m)=>{var b;let{prefixCls:h,className:v,rootClassName:y,children:$,indeterminate:C=!1,style:k,onMouseEnter:x,onMouseLeave:S,skipGroup:O=!1,disabled:w}=e,E=g(e,["prefixCls","className","rootClassName","children","indeterminate","style","onMouseEnter","onMouseLeave","skipGroup","disabled"]),{getPrefixCls:j,direction:N,checkbox:I}=t.useContext(a.ConfigContext),P=t.useContext(d.default),{isFormItemInput:D}=t.useContext(u.FormItemInputContext),R=t.useContext(s.default),z=null!=(b=(null==P?void 0:P.disabled)||w)?b:R,A=t.useRef(E.value),M=t.useRef(null),T=(0,o.composeRef)(m,M);t.useEffect(()=>{null==P||P.registerValue(E.value)},[]),t.useEffect(()=>{if(!O)return E.value!==A.current&&(null==P||P.cancelValue(A.current),null==P||P.registerValue(E.value),A.current=E.value),()=>null==P?void 0:P.cancelValue(E.value)},[E.value]),t.useEffect(()=>{var e;(null==(e=M.current)?void 0:e.input)&&(M.current.input.indeterminate=C)},[C]);let W=j("checkbox",h),B=(0,c.default)(W),[F,X,L]=(0,p.default)(W,B),H=Object.assign({},E);P&&!O&&(H.onChange=(...e)=>{E.onChange&&E.onChange.apply(E,e),P.toggleOption&&P.toggleOption({label:$,value:E.value})},H.name=P.name,H.checked=P.value.includes(E.value));let _=(0,r.default)(`${W}-wrapper`,{[`${W}-rtl`]:"rtl"===N,[`${W}-wrapper-checked`]:H.checked,[`${W}-wrapper-disabled`]:z,[`${W}-wrapper-in-form-item`]:D},null==I?void 0:I.className,v,y,L,B,X),q=(0,r.default)({[`${W}-indeterminate`]:C},l.TARGET_CLS,X),[G,V]=(0,f.default)(H.onClick);return F(t.createElement(i.default,{component:"Checkbox",disabled:z},t.createElement("label",{className:_,style:Object.assign(Object.assign({},null==I?void 0:I.style),k),onMouseEnter:x,onMouseLeave:S,onClick:G},t.createElement(n.default,Object.assign({},H,{onClick:V,prefixCls:W,className:q,disabled:z,ref:T})),null!=$&&t.createElement("span",{className:`${W}-label`},$))))});var b=e.i(8211),h=e.i(529681),v=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 y=t.forwardRef((e,n)=>{let{defaultValue:o,children:i,options:l=[],prefixCls:s,className:u,rootClassName:f,style:g,onChange:y}=e,$=v(e,["defaultValue","children","options","prefixCls","className","rootClassName","style","onChange"]),{getPrefixCls:C,direction:k}=t.useContext(a.ConfigContext),[x,S]=t.useState($.value||o||[]),[O,w]=t.useState([]);t.useEffect(()=>{"value"in $&&S($.value||[])},[$.value]);let E=t.useMemo(()=>l.map(e=>"string"==typeof e||"number"==typeof e?{label:e,value:e}:e),[l]),j=e=>{w(t=>t.filter(t=>t!==e))},N=e=>{w(t=>[].concat((0,b.default)(t),[e]))},I=e=>{let t=x.indexOf(e.value),r=(0,b.default)(x);-1===t?r.push(e.value):r.splice(t,1),"value"in $||S(r),null==y||y(r.filter(e=>O.includes(e)).sort((e,t)=>E.findIndex(t=>t.value===e)-E.findIndex(e=>e.value===t)))},P=C("checkbox",s),D=`${P}-group`,R=(0,c.default)(P),[z,A,M]=(0,p.default)(P,R),T=(0,h.default)($,["value","disabled"]),W=l.length?E.map(e=>t.createElement(m,{prefixCls:P,key:e.value.toString(),disabled:"disabled"in e?e.disabled:$.disabled,value:e.value,checked:x.includes(e.value),onChange:e.onChange,className:(0,r.default)(`${D}-item`,e.className),style:e.style,title:e.title,id:e.id,required:e.required},e.label)):i,B=t.useMemo(()=>({toggleOption:I,value:x,disabled:$.disabled,name:$.name,registerValue:N,cancelValue:j}),[I,x,$.disabled,$.name,N,j]),F=(0,r.default)(D,{[`${D}-rtl`]:"rtl"===k},u,f,M,R,A);return z(t.createElement("div",Object.assign({className:F,style:g},T,{ref:n}),t.createElement(d.default.Provider,{value:B},W)))});m.Group=y,m.__ANT_CHECKBOX=!0,e.s(["default",0,m],374276),e.s(["Checkbox",0,m],536916)},309821,e=>{"use strict";e.i(247167);var t=e.i(271645);e.i(262370);var r=e.i(135551),n=e.i(201072),o=e.i(121229),i=e.i(726289),l=e.i(864517),a=e.i(343794),s=e.i(529681),c=e.i(242064),u=e.i(931067),d=e.i(209428),p=e.i(703923),f={percent:0,prefixCls:"rc-progress",strokeColor:"#2db7f5",strokeLinecap:"round",strokeWidth:1,trailColor:"#D9D9D9",trailWidth:1,gapPosition:"bottom"},g=function(){var e=(0,t.useRef)([]),r=(0,t.useRef)(null);return(0,t.useEffect)(function(){var t=Date.now(),n=!1;e.current.forEach(function(e){if(e){n=!0;var o=e.style;o.transitionDuration=".3s, .3s, .3s, .06s",r.current&&t-r.current<100&&(o.transitionDuration="0s, 0s")}}),n&&(r.current=Date.now())}),e.current},m=e.i(410160),b=e.i(392221),h=e.i(654310),v=0,y=(0,h.default)();let $=function(e){var r=t.useState(),n=(0,b.default)(r,2),o=n[0],i=n[1];return t.useEffect(function(){var e;i("rc_progress_".concat((y?(e=v,v+=1):e="TEST_OR_SSR",e)))},[]),e||o};var C=function(e){var r=e.bg,n=e.children;return t.createElement("div",{style:{width:"100%",height:"100%",background:r}},n)};function k(e,t){return Object.keys(e).map(function(r){var n=parseFloat(r),o="".concat(Math.floor(n*t),"%");return"".concat(e[r]," ").concat(o)})}var x=t.forwardRef(function(e,r){var n=e.prefixCls,o=e.color,i=e.gradientId,l=e.radius,a=e.style,s=e.ptg,c=e.strokeLinecap,u=e.strokeWidth,d=e.size,p=e.gapDegree,f=o&&"object"===(0,m.default)(o),g=d/2,b=t.createElement("circle",{className:"".concat(n,"-circle-path"),r:l,cx:g,cy:g,stroke:f?"#FFF":void 0,strokeLinecap:c,strokeWidth:u,opacity:+(0!==s),style:a,ref:r});if(!f)return b;var h="".concat(i,"-conic"),v=k(o,(360-p)/360),y=k(o,1),$="conic-gradient(from ".concat(p?"".concat(180+p/2,"deg"):"0deg",", ").concat(v.join(", "),")"),x="linear-gradient(to ".concat(p?"bottom":"top",", ").concat(y.join(", "),")");return t.createElement(t.Fragment,null,t.createElement("mask",{id:h},b),t.createElement("foreignObject",{x:0,y:0,width:d,height:d,mask:"url(#".concat(h,")")},t.createElement(C,{bg:x},t.createElement(C,{bg:$}))))}),S=function(e,t,r,n,o,i,l,a,s,c){var u=arguments.length>10&&void 0!==arguments[10]?arguments[10]:0,d=(100-n)/100*t;return"round"===s&&100!==n&&(d+=c/2)>=t&&(d=t-.01),{stroke:"string"==typeof a?a:void 0,strokeDasharray:"".concat(t,"px ").concat(e),strokeDashoffset:d+u,transform:"rotate(".concat(o+r/100*360*((360-i)/360)+(0===i?0:({bottom:0,top:180,left:90,right:-90})[l]),"deg)"),transformOrigin:"".concat(50,"px ").concat(50,"px"),transition:"stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s",fillOpacity:0}},O=["id","prefixCls","steps","strokeWidth","trailWidth","gapDegree","gapPosition","trailColor","strokeLinecap","style","className","strokeColor","percent"];function w(e){var t=null!=e?e:[];return Array.isArray(t)?t:[t]}let E=function(e){var r,n,o,i,l=(0,d.default)((0,d.default)({},f),e),s=l.id,c=l.prefixCls,b=l.steps,h=l.strokeWidth,v=l.trailWidth,y=l.gapDegree,C=void 0===y?0:y,k=l.gapPosition,E=l.trailColor,j=l.strokeLinecap,N=l.style,I=l.className,P=l.strokeColor,D=l.percent,R=(0,p.default)(l,O),z=$(s),A="".concat(z,"-gradient"),M=50-h/2,T=2*Math.PI*M,W=C>0?90+C/2:-90,B=(360-C)/360*T,F="object"===(0,m.default)(b)?b:{count:b,gap:2},X=F.count,L=F.gap,H=w(D),_=w(P),q=_.find(function(e){return e&&"object"===(0,m.default)(e)}),G=q&&"object"===(0,m.default)(q)?"butt":j,V=S(T,B,0,100,W,C,k,E,G,h),K=g();return t.createElement("svg",(0,u.default)({className:(0,a.default)("".concat(c,"-circle"),I),viewBox:"0 0 ".concat(100," ").concat(100),style:N,id:s,role:"presentation"},R),!X&&t.createElement("circle",{className:"".concat(c,"-circle-trail"),r:M,cx:50,cy:50,stroke:E,strokeLinecap:G,strokeWidth:v||h,style:V}),X?(r=Math.round(X*(H[0]/100)),n=100/X,o=0,Array(X).fill(null).map(function(e,i){var l=i<=r-1?_[0]:E,a=l&&"object"===(0,m.default)(l)?"url(#".concat(A,")"):void 0,s=S(T,B,o,n,W,C,k,l,"butt",h,L);return o+=(B-s.strokeDashoffset+L)*100/B,t.createElement("circle",{key:i,className:"".concat(c,"-circle-path"),r:M,cx:50,cy:50,stroke:a,strokeWidth:h,opacity:1,style:s,ref:function(e){K[i]=e}})})):(i=0,H.map(function(e,r){var n=_[r]||_[_.length-1],o=S(T,B,i,e,W,C,k,n,G,h);return i+=e,t.createElement(x,{key:r,color:n,ptg:e,radius:M,prefixCls:c,gradientId:A,style:o,strokeLinecap:G,strokeWidth:h,gapDegree:C,ref:function(e){K[r]=e},size:100})}).reverse()))};var j=e.i(491816);e.i(765846);var N=e.i(896091);function I(e){return!e||e<0?0:e>100?100:e}function P({success:e,successPercent:t}){let r=t;return e&&"progress"in e&&(r=e.progress),e&&"percent"in e&&(r=e.percent),r}let D=(e,t,r)=>{var n,o,i,l;let a=-1,s=-1;if("step"===t){let t=r.steps,n=r.strokeWidth;"string"==typeof e||void 0===e?(a="small"===e?2:14,s=null!=n?n:8):"number"==typeof e?[a,s]=[e,e]:[a=14,s=8]=Array.isArray(e)?e:[e.width,e.height],a*=t}else if("line"===t){let t=null==r?void 0:r.strokeWidth;"string"==typeof e||void 0===e?s=t||("small"===e?6:8):"number"==typeof e?[a,s]=[e,e]:[a=-1,s=8]=Array.isArray(e)?e:[e.width,e.height]}else("circle"===t||"dashboard"===t)&&("string"==typeof e||void 0===e?[a,s]="small"===e?[60,60]:[120,120]:"number"==typeof e?[a,s]=[e,e]:Array.isArray(e)&&(a=null!=(o=null!=(n=e[0])?n:e[1])?o:120,s=null!=(l=null!=(i=e[0])?i:e[1])?l:120));return[a,s]},R=e=>{let{prefixCls:r,trailColor:n=null,strokeLinecap:o="round",gapPosition:i,gapDegree:l,width:s=120,type:c,children:u,success:d,size:p=s,steps:f}=e,[g,m]=D(p,"circle"),{strokeWidth:b}=e;void 0===b&&(b=Math.max(3/g*100,6));let h=t.useMemo(()=>l||0===l?l:"dashboard"===c?75:void 0,[l,c]),v=(({percent:e,success:t,successPercent:r})=>{let n=I(P({success:t,successPercent:r}));return[n,I(I(e)-n)]})(e),y="[object Object]"===Object.prototype.toString.call(e.strokeColor),$=(({success:e={},strokeColor:t})=>{let{strokeColor:r}=e;return[r||N.presetPrimaryColors.green,t||null]})({success:d,strokeColor:e.strokeColor}),C=(0,a.default)(`${r}-inner`,{[`${r}-circle-gradient`]:y}),k=t.createElement(E,{steps:f,percent:f?v[1]:v,strokeWidth:b,trailWidth:b,strokeColor:f?$[1]:$,strokeLinecap:o,trailColor:n,prefixCls:r,gapDegree:h,gapPosition:i||"dashboard"===c&&"bottom"||void 0}),x=g<=20,S=t.createElement("div",{className:C,style:{width:g,height:m,fontSize:.15*g+6}},k,!x&&u);return x?t.createElement(j.default,{title:u},S):S};e.i(296059);var z=e.i(694758),A=e.i(915654),M=e.i(183293),T=e.i(246422),W=e.i(838378);let B="--progress-line-stroke-color",F="--progress-percent",X=e=>{let t=e?"100%":"-100%";return new z.Keyframes(`antProgress${e?"RTL":"LTR"}Active`,{"0%":{transform:`translateX(${t}) scaleX(0)`,opacity:.1},"20%":{transform:`translateX(${t}) scaleX(0)`,opacity:.5},to:{transform:"translateX(0) scaleX(1)",opacity:0}})},L=(0,T.genStyleHooks)("Progress",e=>{let t=e.calc(e.marginXXS).div(2).equal(),r=(0,W.mergeToken)(e,{progressStepMarginInlineEnd:t,progressStepMinWidth:t,progressActiveMotionDuration:"2.4s"});return[(e=>{let{componentCls:t,iconCls:r}=e;return{[t]:Object.assign(Object.assign({},(0,M.resetComponent)(e)),{display:"inline-block","&-rtl":{direction:"rtl"},"&-line":{position:"relative",width:"100%",fontSize:e.fontSize},[`${t}-outer`]:{display:"inline-flex",alignItems:"center",width:"100%"},[`${t}-inner`]:{position:"relative",display:"inline-block",width:"100%",flex:1,overflow:"hidden",verticalAlign:"middle",backgroundColor:e.remainingColor,borderRadius:e.lineBorderRadius},[`${t}-inner:not(${t}-circle-gradient)`]:{[`${t}-circle-path`]:{stroke:e.defaultColor}},[`${t}-success-bg, ${t}-bg`]:{position:"relative",background:e.defaultColor,borderRadius:e.lineBorderRadius,transition:`all ${e.motionDurationSlow} ${e.motionEaseInOutCirc}`},[`${t}-layout-bottom`]:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",[`${t}-text`]:{width:"max-content",marginInlineStart:0,marginTop:e.marginXXS}},[`${t}-bg`]:{overflow:"hidden","&::after":{content:'""',background:{_multi_value_:!0,value:["inherit",`var(${B})`]},height:"100%",width:`calc(1 / var(${F}) * 100%)`,display:"block"},[`&${t}-bg-inner`]:{minWidth:"max-content","&::after":{content:"none"},[`${t}-text-inner`]:{color:e.colorWhite,[`&${t}-text-bright`]:{color:"rgba(0, 0, 0, 0.45)"}}}},[`${t}-success-bg`]:{position:"absolute",insetBlockStart:0,insetInlineStart:0,backgroundColor:e.colorSuccess},[`${t}-text`]:{display:"inline-block",marginInlineStart:e.marginXS,color:e.colorText,lineHeight:1,width:"2em",whiteSpace:"nowrap",textAlign:"start",verticalAlign:"middle",wordBreak:"normal",[r]:{fontSize:e.fontSize},[`&${t}-text-outer`]:{width:"max-content"},[`&${t}-text-outer${t}-text-start`]:{width:"max-content",marginInlineStart:0,marginInlineEnd:e.marginXS}},[`${t}-text-inner`]:{display:"flex",justifyContent:"center",alignItems:"center",width:"100%",height:"100%",marginInlineStart:0,padding:`0 ${(0,A.unit)(e.paddingXXS)}`,[`&${t}-text-start`]:{justifyContent:"start"},[`&${t}-text-end`]:{justifyContent:"end"}},[`&${t}-status-active`]:{[`${t}-bg::before`]:{position:"absolute",inset:0,backgroundColor:e.colorBgContainer,borderRadius:e.lineBorderRadius,opacity:0,animationName:X(),animationDuration:e.progressActiveMotionDuration,animationTimingFunction:e.motionEaseOutQuint,animationIterationCount:"infinite",content:'""'}},[`&${t}-rtl${t}-status-active`]:{[`${t}-bg::before`]:{animationName:X(!0)}},[`&${t}-status-exception`]:{[`${t}-bg`]:{backgroundColor:e.colorError},[`${t}-text`]:{color:e.colorError}},[`&${t}-status-exception ${t}-inner:not(${t}-circle-gradient)`]:{[`${t}-circle-path`]:{stroke:e.colorError}},[`&${t}-status-success`]:{[`${t}-bg`]:{backgroundColor:e.colorSuccess},[`${t}-text`]:{color:e.colorSuccess}},[`&${t}-status-success ${t}-inner:not(${t}-circle-gradient)`]:{[`${t}-circle-path`]:{stroke:e.colorSuccess}}})}})(r),(e=>{let{componentCls:t,iconCls:r}=e;return{[t]:{[`${t}-circle-trail`]:{stroke:e.remainingColor},[`&${t}-circle ${t}-inner`]:{position:"relative",lineHeight:1,backgroundColor:"transparent"},[`&${t}-circle ${t}-text`]:{position:"absolute",insetBlockStart:"50%",insetInlineStart:0,width:"100%",margin:0,padding:0,color:e.circleTextColor,fontSize:e.circleTextFontSize,lineHeight:1,whiteSpace:"normal",textAlign:"center",transform:"translateY(-50%)",[r]:{fontSize:e.circleIconFontSize}},[`${t}-circle&-status-exception`]:{[`${t}-text`]:{color:e.colorError}},[`${t}-circle&-status-success`]:{[`${t}-text`]:{color:e.colorSuccess}}},[`${t}-inline-circle`]:{lineHeight:1,[`${t}-inner`]:{verticalAlign:"bottom"}}}})(r),(e=>{let{componentCls:t}=e;return{[t]:{[`${t}-steps`]:{display:"inline-block","&-outer":{display:"flex",flexDirection:"row",alignItems:"center"},"&-item":{flexShrink:0,minWidth:e.progressStepMinWidth,marginInlineEnd:e.progressStepMarginInlineEnd,backgroundColor:e.remainingColor,transition:`all ${e.motionDurationSlow}`,"&-active":{backgroundColor:e.defaultColor}}}}}})(r),(e=>{let{componentCls:t,iconCls:r}=e;return{[t]:{[`${t}-small&-line, ${t}-small&-line ${t}-text ${r}`]:{fontSize:e.fontSizeSM}}}})(r)]},e=>({circleTextColor:e.colorText,defaultColor:e.colorInfo,remainingColor:e.colorFillSecondary,lineBorderRadius:100,circleTextFontSize:"1em",circleIconFontSize:`${e.fontSize/e.fontSizeSM}em`}));var H=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 _=e=>{let{prefixCls:r,direction:n,percent:o,size:i,strokeWidth:l,strokeColor:s,strokeLinecap:c="round",children:u,trailColor:d=null,percentPosition:p,success:f}=e,{align:g,type:m}=p,b=s&&"string"!=typeof s?((e,t)=>{let{from:r=N.presetPrimaryColors.blue,to:n=N.presetPrimaryColors.blue,direction:o="rtl"===t?"to left":"to right"}=e,i=H(e,["from","to","direction"]);if(0!==Object.keys(i).length){let e,t=(e=[],Object.keys(i).forEach(t=>{let r=Number.parseFloat(t.replace(/%/g,""));Number.isNaN(r)||e.push({key:r,value:i[t]})}),(e=e.sort((e,t)=>e.key-t.key)).map(({key:e,value:t})=>`${t} ${e}%`).join(", ")),r=`linear-gradient(${o}, ${t})`;return{background:r,[B]:r}}let l=`linear-gradient(${o}, ${r}, ${n})`;return{background:l,[B]:l}})(s,n):{[B]:s,background:s},h="square"===c||"butt"===c?0:void 0,[v,y]=D(null!=i?i:[-1,l||("small"===i?6:8)],"line",{strokeWidth:l}),$=Object.assign(Object.assign({width:`${I(o)}%`,height:y,borderRadius:h},b),{[F]:I(o)/100}),C=P(e),k={width:`${I(C)}%`,height:y,borderRadius:h,backgroundColor:null==f?void 0:f.strokeColor},x=t.createElement("div",{className:`${r}-inner`,style:{backgroundColor:d||void 0,borderRadius:h}},t.createElement("div",{className:(0,a.default)(`${r}-bg`,`${r}-bg-${m}`),style:$},"inner"===m&&u),void 0!==C&&t.createElement("div",{className:`${r}-success-bg`,style:k})),S="outer"===m&&"start"===g,O="outer"===m&&"end"===g;return"outer"===m&&"center"===g?t.createElement("div",{className:`${r}-layout-bottom`},x,u):t.createElement("div",{className:`${r}-outer`,style:{width:v<0?"100%":v}},S&&u,x,O&&u)},q=e=>{let{size:r,steps:n,rounding:o=Math.round,percent:i=0,strokeWidth:l=8,strokeColor:s,trailColor:c=null,prefixCls:u,children:d}=e,p=o(i/100*n),[f,g]=D(null!=r?r:["small"===r?2:14,l],"step",{steps:n,strokeWidth:l}),m=f/n,b=Array.from({length:n});for(let e=0;et.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 V=["normal","exception","active","success"],K=t.forwardRef((e,u)=>{let d,{prefixCls:p,className:f,rootClassName:g,steps:m,strokeColor:b,percent:h=0,size:v="default",showInfo:y=!0,type:$="line",status:C,format:k,style:x,percentPosition:S={}}=e,O=G(e,["prefixCls","className","rootClassName","steps","strokeColor","percent","size","showInfo","type","status","format","style","percentPosition"]),{align:w="end",type:E="outer"}=S,j=Array.isArray(b)?b[0]:b,N="string"==typeof b||Array.isArray(b)?b:void 0,z=t.useMemo(()=>{if(j){let e="string"==typeof j?j:Object.values(j)[0];return new r.FastColor(e).isLight()}return!1},[b]),A=t.useMemo(()=>{var t,r;let n=P(e);return Number.parseInt(void 0!==n?null==(t=null!=n?n:0)?void 0:t.toString():null==(r=null!=h?h:0)?void 0:r.toString(),10)},[h,e.success,e.successPercent]),M=t.useMemo(()=>!V.includes(C)&&A>=100?"success":C||"normal",[C,A]),{getPrefixCls:T,direction:W,progress:B}=t.useContext(c.ConfigContext),F=T("progress",p),[X,H,K]=L(F),U="line"===$,Q=U&&!m,Y=t.useMemo(()=>{let r;if(!y)return null;let s=P(e),c=k||(e=>`${e}%`),u=U&&z&&"inner"===E;return"inner"===E||k||"exception"!==M&&"success"!==M?r=c(I(h),I(s)):"exception"===M?r=U?t.createElement(i.default,null):t.createElement(l.default,null):"success"===M&&(r=U?t.createElement(n.default,null):t.createElement(o.default,null)),t.createElement("span",{className:(0,a.default)(`${F}-text`,{[`${F}-text-bright`]:u,[`${F}-text-${w}`]:Q,[`${F}-text-${E}`]:Q}),title:"string"==typeof r?r:void 0},r)},[y,h,A,M,$,F,k]);"line"===$?d=m?t.createElement(q,Object.assign({},e,{strokeColor:N,prefixCls:F,steps:"object"==typeof m?m.count:m}),Y):t.createElement(_,Object.assign({},e,{strokeColor:j,prefixCls:F,direction:W,percentPosition:{align:w,type:E}}),Y):("circle"===$||"dashboard"===$)&&(d=t.createElement(R,Object.assign({},e,{strokeColor:j,prefixCls:F,progressStatus:M}),Y));let J=(0,a.default)(F,`${F}-status-${M}`,{[`${F}-${"dashboard"===$&&"circle"||$}`]:"line"!==$,[`${F}-inline-circle`]:"circle"===$&&D(v,"circle")[0]<=20,[`${F}-line`]:Q,[`${F}-line-align-${w}`]:Q,[`${F}-line-position-${E}`]:Q,[`${F}-steps`]:m,[`${F}-show-info`]:y,[`${F}-${v}`]:"string"==typeof v,[`${F}-rtl`]:"rtl"===W},null==B?void 0:B.className,f,g,H,K);return X(t.createElement("div",Object.assign({ref:u,style:Object.assign(Object.assign({},null==B?void 0:B.style),x),className:J,role:"progressbar","aria-valuenow":A,"aria-valuemin":0,"aria-valuemax":100},(0,s.default)(O,["trailColor","strokeWidth","width","gapDegree","gapPosition","strokeLinecap","success","successPercent"])),d))});e.s(["default",0,K],309821)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/0f9a273ed1d8f7f6.js b/litellm/proxy/_experimental/out/_next/static/chunks/0f9a273ed1d8f7f6.js new file mode 100644 index 00000000000..b22d4f4e82d --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/0f9a273ed1d8f7f6.js @@ -0,0 +1,420 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,326373,e=>{"use strict";var t=e.i(21539);e.s(["Dropdown",()=>t.default])},879664,e=>{"use strict";let t=(0,e.i(475254).default)("info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);e.s(["default",()=>t])},596239,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M574 665.4a8.03 8.03 0 00-11.3 0L446.5 781.6c-53.8 53.8-144.6 59.5-204 0-59.5-59.5-53.8-150.2 0-204l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3l-39.8-39.8a8.03 8.03 0 00-11.3 0L191.4 526.5c-84.6 84.6-84.6 221.5 0 306s221.5 84.6 306 0l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3L574 665.4zm258.6-474c-84.6-84.6-221.5-84.6-306 0L410.3 307.6a8.03 8.03 0 000 11.3l39.7 39.7c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c53.8-53.8 144.6-59.5 204 0 59.5 59.5 53.8 150.2 0 204L665.3 562.6a8.03 8.03 0 000 11.3l39.8 39.8c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c84.5-84.6 84.5-221.5 0-306.1zM610.1 372.3a8.03 8.03 0 00-11.3 0L372.3 598.7a8.03 8.03 0 000 11.3l39.6 39.6c3.1 3.1 8.2 3.1 11.3 0l226.4-226.4c3.1-3.1 3.1-8.2 0-11.3l-39.5-39.6z"}}]},name:"link",theme:"outlined"};var r=e.i(9583),o=i.forwardRef(function(e,o){return i.createElement(r.default,(0,t.default)({},e,{ref:o,icon:a}))});e.s(["LinkOutlined",0,o],596239)},652272,209261,e=>{"use strict";var t=e.i(843476),i=e.i(271645),a=e.i(447566),r=e.i(166406),o=e.i(492030),n=e.i(596239);let s=e=>"github"===e.source.source&&e.source.repo?`/plugin marketplace add ${e.source.repo}`:"url"===e.source.source&&e.source.url?`/plugin marketplace add ${e.source.url}`:`/plugin marketplace add ${e.name}`;e.s(["formatInstallCommand",0,s,"getCategoryBadgeColor",0,e=>{if(!e)return"gray";let t=e.toLowerCase();if(t.includes("development")||t.includes("dev"))return"blue";if(t.includes("productivity")||t.includes("workflow"))return"green";if(t.includes("learning")||t.includes("education"))return"purple";if(t.includes("security")||t.includes("safety"))return"red";if(t.includes("data")||t.includes("analytics"))return"orange";else if(t.includes("integration")||t.includes("api"))return"yellow";return"gray"},"isValidEmail",0,e=>!e||/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e),"isValidSemanticVersion",0,e=>!e||/^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(e),"isValidUrl",0,e=>{if(!e)return!0;try{return new URL(e),!0}catch{return!1}},"parseKeywords",0,e=>e&&""!==e.trim()?e.split(",").map(e=>e.trim()).filter(e=>""!==e):[],"validatePluginName",0,e=>!!e&&""!==e.trim()&&/^[a-z0-9-]+$/.test(e)],209261),e.s(["default",0,({skill:e,onBack:l})=>{let p,[d,c]=(0,i.useState)("overview"),[u,g]=(0,i.useState)(null),m=(e,t)=>{navigator.clipboard.writeText(e),g(t),setTimeout(()=>g(null),2e3)},f="github"===(p=e.source).source&&p.repo?`https://github.com/${p.repo}`:"git-subdir"===p.source&&p.url?p.path?`${p.url}/tree/main/${p.path}`:p.url:"url"===p.source&&p.url?p.url:null,_=s(e),h=[...e.category?[{property:"Category",value:e.category}]:[],...e.domain?[{property:"Domain",value:e.domain}]:[],...e.namespace?[{property:"Namespace",value:e.namespace}]:[],...e.version?[{property:"Version",value:e.version}]:[],...e.author?.name?[{property:"Author",value:e.author.name}]:[],...e.created_at?[{property:"Added",value:new Date(e.created_at).toLocaleDateString()}]:[]];return(0,t.jsxs)("div",{style:{padding:"24px 32px 24px 0"},children:[(0,t.jsxs)("div",{onClick:l,style:{display:"inline-flex",alignItems:"center",gap:6,color:"#5f6368",cursor:"pointer",fontSize:14,marginBottom:24},children:[(0,t.jsx)(a.ArrowLeftOutlined,{style:{fontSize:11}}),(0,t.jsx)("span",{children:"Skills"})]}),(0,t.jsxs)("div",{style:{marginBottom:8},children:[(0,t.jsx)("h1",{style:{fontSize:28,fontWeight:400,color:"#202124",margin:0,lineHeight:1.2},children:e.name}),e.description&&(0,t.jsx)("p",{style:{fontSize:14,color:"#5f6368",margin:"8px 0 0 0",lineHeight:1.6},children:e.description})]}),(0,t.jsx)("div",{style:{borderBottom:"1px solid #dadce0",marginBottom:28,marginTop:24},children:(0,t.jsx)("div",{style:{display:"flex",gap:0},children:[{key:"overview",label:"Overview"},{key:"usage",label:"How to Use"}].map(e=>(0,t.jsx)("div",{onClick:()=>c(e.key),style:{padding:"12px 20px",fontSize:14,color:d===e.key?"#1a73e8":"#5f6368",borderBottom:d===e.key?"3px solid #1a73e8":"3px solid transparent",cursor:"pointer",fontWeight:d===e.key?500:400,marginBottom:-1},children:e.label},e.key))})}),"overview"===d&&(0,t.jsxs)("div",{style:{display:"flex",gap:64},children:[(0,t.jsxs)("div",{style:{flex:1,minWidth:0},children:[(0,t.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 4px 0"},children:"Skill Details"}),(0,t.jsx)("p",{style:{fontSize:13,color:"#5f6368",margin:"0 0 16px 0"},children:"Metadata registered with this skill"}),(0,t.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:14},children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{style:{borderBottom:"1px solid #dadce0"},children:[(0,t.jsx)("th",{style:{textAlign:"left",padding:"12px 0",color:"#5f6368",fontWeight:500,width:160},children:"Property"}),(0,t.jsx)("th",{style:{textAlign:"left",padding:"12px 0",color:"#5f6368",fontWeight:500},children:e.name})]})}),(0,t.jsx)("tbody",{children:h.map((e,i)=>(0,t.jsxs)("tr",{style:{borderBottom:"1px solid #f1f3f4"},children:[(0,t.jsx)("td",{style:{padding:"12px 0",color:"#3c4043"},children:e.property}),(0,t.jsx)("td",{style:{padding:"12px 0",color:"#202124"},children:e.value})]},i))})]})]}),(0,t.jsxs)("div",{style:{width:240,flexShrink:0},children:[(0,t.jsxs)("div",{style:{marginBottom:24},children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Status"}),(0,t.jsx)("span",{style:{fontSize:12,padding:"3px 10px",borderRadius:12,backgroundColor:e.enabled?"#e6f4ea":"#f1f3f4",color:e.enabled?"#137333":"#5f6368",fontWeight:500},children:e.enabled?"Public":"Draft"})]}),f&&(0,t.jsxs)("div",{style:{marginBottom:24},children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Source"}),(0,t.jsxs)("a",{href:f,target:"_blank",rel:"noopener noreferrer",style:{fontSize:13,color:"#1a73e8",wordBreak:"break-all",display:"flex",alignItems:"center",gap:4},children:[f.replace("https://",""),(0,t.jsx)(n.LinkOutlined,{style:{fontSize:11,flexShrink:0}})]})]}),e.keywords&&e.keywords.length>0&&(0,t.jsxs)("div",{style:{marginBottom:24},children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:8},children:"Tags"}),(0,t.jsx)("div",{style:{display:"flex",flexWrap:"wrap",gap:6},children:e.keywords.map(e=>(0,t.jsx)("span",{style:{fontSize:12,padding:"4px 12px",borderRadius:16,border:"1px solid #dadce0",color:"#3c4043",backgroundColor:"#fff"},children:e},e))})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{style:{fontSize:12,color:"#5f6368",marginBottom:4},children:"Skill ID"}),(0,t.jsx)("div",{style:{fontSize:12,fontFamily:"monospace",color:"#3c4043",wordBreak:"break-all"},children:e.id})]})]})]}),"usage"===d&&(0,t.jsxs)("div",{style:{maxWidth:640},children:[(0,t.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 8px 0"},children:"Using this skill"}),(0,t.jsx)("p",{style:{fontSize:14,color:"#5f6368",margin:"0 0 24px 0",lineHeight:1.6},children:"Once your proxy is set as a marketplace, enable this skill in Claude Code with one command:"}),(0,t.jsxs)("div",{style:{border:"1px solid #dadce0",borderRadius:8,overflow:"hidden",marginBottom:24},children:[(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 16px",backgroundColor:"#f8f9fa",borderBottom:"1px solid #dadce0"},children:[(0,t.jsx)("span",{style:{fontSize:13,color:"#3c4043",fontWeight:500},children:"Run in Claude Code"}),(0,t.jsxs)("button",{onClick:()=>m(_,"install"),style:{display:"flex",alignItems:"center",gap:4,fontSize:12,color:"install"===u?"#137333":"#1a73e8",background:"none",border:"none",cursor:"pointer",padding:0},children:["install"===u?(0,t.jsx)(o.CheckOutlined,{}):(0,t.jsx)(r.CopyOutlined,{}),"install"===u?"Copied":"Copy"]})]}),(0,t.jsx)("pre",{style:{margin:0,padding:"14px 16px",fontSize:14,fontFamily:"monospace",color:"#202124",backgroundColor:"#fff"},children:_})]}),(0,t.jsxs)("p",{style:{fontSize:13,color:"#5f6368",lineHeight:1.6,margin:0},children:["Don't have the marketplace configured yet?"," ",(0,t.jsx)("span",{onClick:()=>c("setup"),style:{color:"#1a73e8",cursor:"pointer"},children:"See one-time setup →"})]})]}),"setup"===d&&(0,t.jsxs)("div",{style:{maxWidth:640},children:[(0,t.jsx)("h2",{style:{fontSize:18,fontWeight:400,color:"#202124",margin:"0 0 8px 0"},children:"One-time marketplace setup"}),(0,t.jsxs)("p",{style:{fontSize:14,color:"#5f6368",margin:"0 0 24px 0",lineHeight:1.6},children:["Add this to"," ",(0,t.jsx)("code",{style:{fontSize:13,backgroundColor:"#f1f3f4",padding:"1px 6px",borderRadius:4},children:"~/.claude/settings.json"})," ","to point Claude Code at your proxy:"]}),(0,t.jsxs)("div",{style:{border:"1px solid #dadce0",borderRadius:8,overflow:"hidden"},children:[(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 16px",backgroundColor:"#f8f9fa",borderBottom:"1px solid #dadce0"},children:[(0,t.jsx)("span",{style:{fontSize:13,color:"#3c4043",fontWeight:500},children:"~/.claude/settings.json"}),(0,t.jsxs)("button",{onClick:()=>{m(JSON.stringify({extraKnownMarketplaces:{"my-org":{source:"url",url:`${window.location.origin}/claude-code/marketplace.json`}}},null,2),"settings")},style:{display:"flex",alignItems:"center",gap:4,fontSize:12,color:"settings"===u?"#137333":"#1a73e8",background:"none",border:"none",cursor:"pointer",padding:0},children:["settings"===u?(0,t.jsx)(o.CheckOutlined,{}):(0,t.jsx)(r.CopyOutlined,{}),"settings"===u?"Copied":"Copy"]})]}),(0,t.jsx)("pre",{style:{margin:0,padding:"14px 16px",fontSize:13,fontFamily:"monospace",color:"#202124",backgroundColor:"#fff"},children:JSON.stringify({extraKnownMarketplaces:{"my-org":{source:"url",url:`${window.location.origin}/claude-code/marketplace.json`}}},null,2)})]})]})]})}],652272)},275144,e=>{"use strict";var t=e.i(843476),i=e.i(271645),a=e.i(602869);let r=(0,i.createContext)(void 0);e.s(["ThemeProvider",0,({children:e,accessToken:o})=>{let[n,s]=(0,i.useState)(null),[l,p]=(0,i.useState)(null);return(0,i.useEffect)(()=>{(async()=>{try{let e=(0,a.getProxyBaseUrl)(),t=e?`${e}/get/ui_theme_settings`:"/get/ui_theme_settings",i=await fetch(t,{method:"GET",headers:{"Content-Type":"application/json"}});if(i.ok){let e=await i.json();e.values?.logo_url&&s(e.values.logo_url),e.values?.favicon_url&&p(e.values.favicon_url)}}catch(e){console.warn("Failed to load theme settings from backend:",e)}})()},[]),(0,i.useEffect)(()=>{if(l){let e=document.querySelectorAll("link[rel*='icon']");if(e.length>0)e.forEach(e=>{e.href=l});else{let e=document.createElement("link");e.rel="icon",e.href=l,document.head.appendChild(e)}}},[l]),(0,t.jsx)(r.Provider,{value:{logoUrl:n,setLogoUrl:s,faviconUrl:l,setFaviconUrl:p},children:e})},"useTheme",0,()=>{let e=(0,i.useContext)(r);if(!e)throw Error("useTheme must be used within a ThemeProvider");return e}])},371401,e=>{"use strict";var t=e.i(115571),i=e.i(271645);function a(e){let i=t=>{"disableUsageIndicator"===t.key&&e()},a=t=>{let{key:i}=t.detail;"disableUsageIndicator"===i&&e()};return window.addEventListener("storage",i),window.addEventListener(t.LOCAL_STORAGE_EVENT,a),()=>{window.removeEventListener("storage",i),window.removeEventListener(t.LOCAL_STORAGE_EVENT,a)}}function r(){return"true"===(0,t.getLocalStorageItem)("disableUsageIndicator")}function o(){return(0,i.useSyncExternalStore)(a,r)}e.s(["useDisableUsageIndicator",()=>o])},115571,e=>{"use strict";let t="local-storage-change";function i(e){window.dispatchEvent(new CustomEvent(t,{detail:{key:e}}))}function a(e){try{return window.localStorage.getItem(e)}catch(t){return console.warn(`Error reading localStorage key "${e}":`,t),null}}function r(e,t){try{window.localStorage.setItem(e,t)}catch(t){console.warn(`Error setting localStorage key "${e}":`,t)}}function o(e){try{window.localStorage.removeItem(e)}catch(t){console.warn(`Error removing localStorage key "${e}":`,t)}}e.s(["LOCAL_STORAGE_EVENT",0,t,"emitLocalStorageChange",()=>i,"getLocalStorageItem",()=>a,"removeLocalStorageItem",()=>o,"setLocalStorageItem",()=>r])},928685,e=>{"use strict";var t=e.i(38953);e.s(["SearchOutlined",()=>t.default])},62478,e=>{"use strict";var t=e.i(602869);let i=async e=>{if(!e)return null;try{return await (0,t.getProxyUISettings)(e)}catch(e){return console.error("Error fetching proxy settings:",e),null}};e.s(["fetchProxySettings",0,i])},592392,e=>{"use strict";var t=e.i(62478),i=e.i(266027);let a=(0,e.i(243652).createQueryKeys)("proxySettings"),r={PROXY_BASE_URL:"",PROXY_LOGOUT_URL:"",LITELLM_UI_API_DOC_BASE_URL:null};function o(e){let{data:o}=(0,i.useQuery)({queryKey:[...a.all,e],queryFn:()=>(0,t.fetchProxySettings)(e),enabled:!!e});return o??r}e.s(["default",()=>o])},602073,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let a={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"};var r=e.i(9583),o=i.forwardRef(function(e,o){return i.createElement(r.default,(0,t.default)({},e,{ref:o,icon:a}))});e.s(["SafetyOutlined",0,o],602073)},818581,(e,t,i)=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0}),Object.defineProperty(i,"useMergedRef",{enumerable:!0,get:function(){return r}});let a=e.r(271645);function r(e,t){let i=(0,a.useRef)(null),r=(0,a.useRef)(null);return(0,a.useCallback)(a=>{if(null===a){let e=i.current;e&&(i.current=null,e());let t=r.current;t&&(r.current=null,t())}else e&&(i.current=o(e,a)),t&&(r.current=o(t,a))},[e,t])}function o(e,t){if("function"!=typeof e)return e.current=t,()=>{e.current=null};{let i=e(t);return"function"==typeof i?i:()=>e(null)}}("function"==typeof i.default||"object"==typeof i.default&&null!==i.default)&&void 0===i.default.__esModule&&(Object.defineProperty(i.default,"__esModule",{value:!0}),Object.assign(i.default,i),t.exports=i.default)},283713,e=>{"use strict";var t=e.i(271645),i=e.i(602869),a=e.i(612256);let r="litellm_selected_worker_id";e.s(["useWorker",0,()=>{let{data:e}=(0,a.useUIConfig)(),o=e?.is_control_plane??!1,n=e?.workers??[],[s,l]=(0,t.useState)(()=>localStorage.getItem(r));(0,t.useEffect)(()=>{if(!s||0===n.length)return;let e=n.find(e=>e.worker_id===s);e&&(0,i.switchToWorkerUrl)(e.url)},[s,n]);let p=n.find(e=>e.worker_id===s)??null,d=(0,t.useCallback)(e=>{let t=n.find(t=>t.worker_id===e);t&&(l(e),localStorage.setItem(r,e),(0,i.switchToWorkerUrl)(t.url))},[n]);return{isControlPlane:o,workers:n,selectedWorkerId:s,selectedWorker:p,selectWorker:d,disconnectFromWorker:(0,t.useCallback)(()=>{l(null),localStorage.removeItem(r),(0,i.switchToWorkerUrl)(null)},[])}}])},295320,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M704 446H320c-4.4 0-8 3.6-8 8v402c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8V454c0-4.4-3.6-8-8-8zm-328 64h272v117H376V510zm272 290H376V683h272v117z"}},{tag:"path",attrs:{d:"M424 748a32 32 0 1064 0 32 32 0 10-64 0zm0-178a32 32 0 1064 0 32 32 0 10-64 0z"}},{tag:"path",attrs:{d:"M811.4 368.9C765.6 248 648.9 162 512.2 162S258.8 247.9 213 368.8C126.9 391.5 63.5 470.2 64 563.6 64.6 668 145.6 752.9 247.6 762c4.7.4 8.7-3.3 8.7-8v-60.4c0-4-3-7.4-7-7.9-27-3.4-52.5-15.2-72.1-34.5-24-23.5-37.2-55.1-37.2-88.6 0-28 9.1-54.4 26.2-76.4 16.7-21.4 40.2-36.9 66.1-43.7l37.9-10 13.9-36.7c8.6-22.8 20.6-44.2 35.7-63.5 14.9-19.2 32.6-36 52.4-50 41.1-28.9 89.5-44.2 140-44.2s98.9 15.3 140 44.3c19.9 14 37.5 30.8 52.4 50 15.1 19.3 27.1 40.7 35.7 63.5l13.8 36.6 37.8 10c54.2 14.4 92.1 63.7 92.1 120 0 33.6-13.2 65.1-37.2 88.6-19.5 19.2-44.9 31.1-71.9 34.5-4 .5-6.9 3.9-6.9 7.9V754c0 4.7 4.1 8.4 8.8 8 101.7-9.2 182.5-94 183.2-198.2.6-93.4-62.7-172.1-148.6-194.9z"}}]},name:"cloud-server",theme:"outlined"};var r=e.i(9583),o=i.forwardRef(function(e,o){return i.createElement(r.default,(0,t.default)({},e,{ref:o,icon:a}))});e.s(["CloudServerOutlined",0,o],295320)},339019,865361,e=>{"use strict";var t,i,a=((t={}).AUDIO_SPEECH="audio_speech",t.AUDIO_TRANSCRIPTION="audio_transcription",t.IMAGE_GENERATION="image_generation",t.VIDEO_GENERATION="video_generation",t.CHAT="chat",t.RESPONSES="responses",t.IMAGE_EDITS="image_edits",t.ANTHROPIC_MESSAGES="anthropic_messages",t.EMBEDDING="embedding",t),r=((i={}).IMAGE="image",i.VIDEO="video",i.CHAT="chat",i.RESPONSES="responses",i.IMAGE_EDITS="image_edits",i.ANTHROPIC_MESSAGES="anthropic_messages",i.EMBEDDINGS="embeddings",i.SPEECH="speech",i.TRANSCRIPTION="transcription",i.A2A_AGENTS="a2a_agents",i.MCP="mcp",i.REALTIME="realtime",i.INTERACTIONS="interactions",i);let o={image_generation:"image",video_generation:"video",chat:"chat",responses:"responses",image_edits:"image_edits",anthropic_messages:"anthropic_messages",audio_speech:"speech",audio_transcription:"transcription",embedding:"embeddings"};e.s(["EndpointType",()=>r,"getEndpointType",0,e=>{if(console.log("getEndpointType:",e),Object.values(a).includes(e)){let t=o[e];return console.log("endpointType:",t),t}return"chat"}],865361),e.s(["generateCodeSnippet",0,e=>{let t,{apiKeySource:i,accessToken:a,apiKey:o,inputMessage:n,chatHistory:s,selectedTags:l,selectedVectorStores:p,selectedGuardrails:d,selectedPolicies:c,selectedMCPServers:u,mcpServers:g,mcpServerToolRestrictions:m,selectedVoice:f,endpointType:_,selectedModel:h,selectedSdk:y,proxySettings:x}=e,b="session"===i?a:o,v=window.location.origin,S=x?.LITELLM_UI_API_DOC_BASE_URL;S&&S.trim()?v=S:x?.PROXY_BASE_URL&&(v=x.PROXY_BASE_URL);let w=n||"Your prompt here",j=w.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n"),E=s.filter(e=>!e.isImage).map(({role:e,content:t})=>({role:e,content:t})),k={};l.length>0&&(k.tags=l),p.length>0&&(k.vector_stores=p),d.length>0&&(k.guardrails=d),c.length>0&&(k.policies=c);let I=h||"your-model-name",C="azure"===y?`import openai + +client = openai.AzureOpenAI( + api_key="${b||"YOUR_LITELLM_API_KEY"}", + azure_endpoint="${v}", + api_version="2024-02-01" +)`:`import openai + +client = openai.OpenAI( + api_key="${b||"YOUR_LITELLM_API_KEY"}", + base_url="${v}" +)`;switch(_){case r.CHAT:{let e=Object.keys(k).length>0,i="";if(e){let e=JSON.stringify({metadata:k},null,2).split("\n").map(e=>" ".repeat(4)+e).join("\n").trim();i=`, + extra_body=${e}`}let a=E.length>0?E:[{role:"user",content:w}];t=` +import base64 + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Example with text only +response = client.chat.completions.create( + model="${I}", + messages=${JSON.stringify(a,null,4)}${i} +) + +print(response) + +# Example with image or PDF (uncomment and provide file path to use) +# base64_file = encode_image("path/to/your/file.jpg") # or .pdf +# response_with_file = client.chat.completions.create( +# model="${I}", +# messages=[ +# { +# "role": "user", +# "content": [ +# { +# "type": "text", +# "text": "${j}" +# }, +# { +# "type": "image_url", +# "image_url": { +# "url": f"data:image/jpeg;base64,{base64_file}" # or data:application/pdf;base64,{base64_file} +# } +# } +# ] +# } +# ]${i} +# ) +# print(response_with_file) +`;break}case r.RESPONSES:{let e=Object.keys(k).length>0,i="";if(e){let e=JSON.stringify({metadata:k},null,2).split("\n").map(e=>" ".repeat(4)+e).join("\n").trim();i=`, + extra_body=${e}`}let a=E.length>0?E:[{role:"user",content:w}];t=` +import base64 + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Example with text only +response = client.responses.create( + model="${I}", + input=${JSON.stringify(a,null,4)}${i} +) + +print(response.output_text) + +# Example with image or PDF (uncomment and provide file path to use) +# base64_file = encode_image("path/to/your/file.jpg") # or .pdf +# response_with_file = client.responses.create( +# model="${I}", +# input=[ +# { +# "role": "user", +# "content": [ +# {"type": "input_text", "text": "${j}"}, +# { +# "type": "input_image", +# "image_url": f"data:image/jpeg;base64,{base64_file}", # or data:application/pdf;base64,{base64_file} +# }, +# ], +# } +# ]${i} +# ) +# print(response_with_file.output_text) +`;break}case r.IMAGE:t="azure"===y?` +# NOTE: The Azure SDK does not have a direct equivalent to the multi-modal 'responses.create' method shown for OpenAI. +# This snippet uses 'client.images.generate' and will create a new image based on your prompt. +# It does not use the uploaded image, as 'client.images.generate' does not support image inputs in this context. +import os +import requests +import json +import time +from PIL import Image + +result = client.images.generate( + model="${I}", + prompt="${n}", + n=1 +) + +json_response = json.loads(result.model_dump_json()) + +# Set the directory for the stored image +image_dir = os.path.join(os.curdir, 'images') + +# If the directory doesn't exist, create it +if not os.path.isdir(image_dir): + os.mkdir(image_dir) + +# Initialize the image path +image_filename = f"generated_image_{int(time.time())}.png" +image_path = os.path.join(image_dir, image_filename) + +try: + # Retrieve the generated image + if json_response.get("data") && len(json_response["data"]) > 0 && json_response["data"][0].get("url"): + image_url = json_response["data"][0]["url"] + generated_image = requests.get(image_url).content + with open(image_path, "wb") as image_file: + image_file.write(generated_image) + + print(f"Image saved to {image_path}") + # Display the image + image = Image.open(image_path) + image.show() + else: + print("Could not find image URL in response.") + print("Full response:", json_response) +except Exception as e: + print(f"An error occurred: {e}") + print("Full response:", json_response) +`:` +import base64 +import os +import time +import json +from PIL import Image +import requests + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Helper function to create a file (simplified for this example) +def create_file(image_path): + # In a real implementation, this would upload the file to OpenAI + # For this example, we'll just return a placeholder ID + return f"file_{os.path.basename(image_path).replace('.', '_')}" + +# The prompt entered by the user +prompt = "${j}" + +# Encode images to base64 +base64_image1 = encode_image("body-lotion.png") +base64_image2 = encode_image("soap.png") + +# Create file IDs +file_id1 = create_file("body-lotion.png") +file_id2 = create_file("incense-kit.png") + +response = client.responses.create( + model="${I}", + input=[ + { + "role": "user", + "content": [ + {"type": "input_text", "text": prompt}, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image1}", + }, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image2}", + }, + { + "type": "input_image", + "file_id": file_id1, + }, + { + "type": "input_image", + "file_id": file_id2, + } + ], + } + ], + tools=[{"type": "image_generation"}], +) + +# Process the response +image_generation_calls = [ + output + for output in response.output + if output.type == "image_generation_call" +] + +image_data = [output.result for output in image_generation_calls] + +if image_data: + image_base64 = image_data[0] + image_filename = f"edited_image_{int(time.time())}.png" + with open(image_filename, "wb") as f: + f.write(base64.b64decode(image_base64)) + print(f"Image saved to {image_filename}") +else: + # If no image is generated, there might be a text response with an explanation + text_response = [output.text for output in response.output if hasattr(output, 'text')] + if text_response: + print("No image generated. Model response:") + print("\\n".join(text_response)) + else: + print("No image data found in response.") + print("Full response for debugging:") + print(response) +`;break;case r.IMAGE_EDITS:t="azure"===y?` +import base64 +import os +import time +import json +from PIL import Image +import requests + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# The prompt entered by the user +prompt = "${j}" + +# Encode images to base64 +base64_image1 = encode_image("body-lotion.png") +base64_image2 = encode_image("soap.png") + +# Create file IDs +file_id1 = create_file("body-lotion.png") +file_id2 = create_file("incense-kit.png") + +response = client.responses.create( + model="${I}", + input=[ + { + "role": "user", + "content": [ + {"type": "input_text", "text": prompt}, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image1}", + }, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image2}", + }, + { + "type": "input_image", + "file_id": file_id1, + }, + { + "type": "input_image", + "file_id": file_id2, + } + ], + } + ], + tools=[{"type": "image_generation"}], +) + +# Process the response +image_generation_calls = [ + output + for output in response.output + if output.type == "image_generation_call" +] + +image_data = [output.result for output in image_generation_calls] + +if image_data: + image_base64 = image_data[0] + image_filename = f"edited_image_{int(time.time())}.png" + with open(image_filename, "wb") as f: + f.write(base64.b64decode(image_base64)) + print(f"Image saved to {image_filename}") +else: + # If no image is generated, there might be a text response with an explanation + text_response = [output.text for output in response.output if hasattr(output, 'text')] + if text_response: + print("No image generated. Model response:") + print("\\n".join(text_response)) + else: + print("No image data found in response.") + print("Full response for debugging:") + print(response) +`:` +import base64 +import os +import time + +# Helper function to encode images to base64 +def encode_image(image_path): + with open(image_path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode('utf-8') + +# Helper function to create a file (simplified for this example) +def create_file(image_path): + # In a real implementation, this would upload the file to OpenAI + # For this example, we'll just return a placeholder ID + return f"file_{os.path.basename(image_path).replace('.', '_')}" + +# The prompt entered by the user +prompt = "${j}" + +# Encode images to base64 +base64_image1 = encode_image("body-lotion.png") +base64_image2 = encode_image("soap.png") + +# Create file IDs +file_id1 = create_file("body-lotion.png") +file_id2 = create_file("incense-kit.png") + +response = client.responses.create( + model="${I}", + input=[ + { + "role": "user", + "content": [ + {"type": "input_text", "text": prompt}, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image1}", + }, + { + "type": "input_image", + "image_url": f"data:image/jpeg;base64,{base64_image2}", + }, + { + "type": "input_image", + "file_id": file_id1, + }, + { + "type": "input_image", + "file_id": file_id2, + } + ], + } + ], + tools=[{"type": "image_generation"}], +) + +# Process the response +image_generation_calls = [ + output + for output in response.output + if output.type == "image_generation_call" +] + +image_data = [output.result for output in image_generation_calls] + +if image_data: + image_base64 = image_data[0] + image_filename = f"edited_image_{int(time.time())}.png" + with open(image_filename, "wb") as f: + f.write(base64.b64decode(image_base64)) + print(f"Image saved to {image_filename}") +else: + # If no image is generated, there might be a text response with an explanation + text_response = [output.text for output in response.output if hasattr(output, 'text')] + if text_response: + print("No image generated. Model response:") + print("\\n".join(text_response)) + else: + print("No image data found in response.") + print("Full response for debugging:") + print(response) +`;break;case r.EMBEDDINGS:t=` +response = client.embeddings.create( + input="${n||"Your string here"}", + model="${I}", + encoding_format="base64" # or "float" +) + +print(response.data[0].embedding) +`;break;case r.TRANSCRIPTION:t=` +# Open the audio file +audio_file = open("path/to/your/audio/file.mp3", "rb") + +# Make the transcription request +response = client.audio.transcriptions.create( + model="${I}", + file=audio_file${n?`, + prompt="${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:""} +) + +print(response.text) +`;break;case r.SPEECH:t=` +# Make the text-to-speech request +response = client.audio.speech.create( + model="${I}", + input="${n||"Your text to convert to speech here"}", + voice="${f}" # Options: alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer +) + +# Save the audio to a file +output_filename = "output_speech.mp3" +response.stream_to_file(output_filename) +print(f"Audio saved to {output_filename}") + +# Optional: Customize response format and speed +# response = client.audio.speech.create( +# model="${I}", +# input="${n||"Your text to convert to speech here"}", +# voice="alloy", +# response_format="mp3", # Options: mp3, opus, aac, flac, wav, pcm +# speed=1.0 # Range: 0.25 to 4.0 +# ) +# response.stream_to_file("output_speech.mp3") +`;break;default:t="\n# Code generation for this endpoint is not implemented yet."}return`${C} +${t}`}],339019)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/101fb167bf3e83b1.js b/litellm/proxy/_experimental/out/_next/static/chunks/101fb167bf3e83b1.js new file mode 100644 index 00000000000..a820ce54256 --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/101fb167bf3e83b1.js @@ -0,0 +1 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,728889,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(829087),l=e.i(480731),o=e.i(444755),n=e.i(673706),s=e.i(95779);let i={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"}},d={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"}},u={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:""}},c=(0,n.makeClassName)("Icon"),m=t.default.forwardRef((e,m)=>{let{icon:f,variant:g="simple",tooltip:h,size:b=l.Sizes.SM,color:p,className:v}=e,w=(0,r.__rest)(e,["icon","variant","tooltip","size","color","className"]),x=((e,r)=>{switch(e){case"simple":return{textColor:r?(0,n.getColorClassNames)(r,s.colorPalette.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:"",borderColor:"",ringColor:""};case"light":return{textColor:r?(0,n.getColorClassNames)(r,s.colorPalette.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:r?(0,o.tremorTwMerge)((0,n.getColorClassNames)(r,s.colorPalette.background).bgColor,"bg-opacity-20"):"bg-tremor-brand-muted dark:bg-dark-tremor-brand-muted",borderColor:"",ringColor:""};case"shadow":return{textColor:r?(0,n.getColorClassNames)(r,s.colorPalette.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:r?(0,o.tremorTwMerge)((0,n.getColorClassNames)(r,s.colorPalette.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:r?(0,n.getColorClassNames)(r,s.colorPalette.text).textColor:"text-tremor-brand-inverted dark:text-dark-tremor-brand-inverted",bgColor:r?(0,o.tremorTwMerge)((0,n.getColorClassNames)(r,s.colorPalette.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:r?(0,n.getColorClassNames)(r,s.colorPalette.text).textColor:"text-tremor-brand dark:text-dark-tremor-brand",bgColor:r?(0,o.tremorTwMerge)((0,n.getColorClassNames)(r,s.colorPalette.background).bgColor,"bg-opacity-20"):"bg-tremor-background dark:bg-dark-tremor-background",borderColor:r?(0,n.getColorClassNames)(r,s.colorPalette.ring).borderColor:"border-tremor-brand-subtle dark:border-dark-tremor-brand-subtle",ringColor:r?(0,o.tremorTwMerge)((0,n.getColorClassNames)(r,s.colorPalette.ring).ringColor,"ring-opacity-40"):"ring-tremor-brand-muted dark:ring-dark-tremor-brand-muted"}}})(g,p),{tooltipProps:k,getReferenceProps:C}=(0,a.useTooltip)();return t.default.createElement("span",Object.assign({ref:(0,n.mergeRefs)([m,k.refs.setReference]),className:(0,o.tremorTwMerge)(c("root"),"inline-flex shrink-0 items-center justify-center",x.bgColor,x.textColor,x.borderColor,x.ringColor,u[g].rounded,u[g].border,u[g].shadow,u[g].ring,i[b].paddingX,i[b].paddingY,v)},C,w),t.default.createElement(a.default,Object.assign({text:h},k)),t.default.createElement(f,{className:(0,o.tremorTwMerge)(c("icon"),"shrink-0",d[b].height,d[b].width)}))});m.displayName="Icon",e.s(["default",()=>m],728889)},752978,e=>{"use strict";var r=e.i(728889);e.s(["Icon",()=>r.default])},591935,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),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.s(["PencilAltIcon",0,t],591935)},360820,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 15l7-7 7 7"}))});e.s(["ChevronUpIcon",0,t],360820)},871943,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"}))});e.s(["ChevronDownIcon",0,t],871943)},269200,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(444755);let l=(0,e.i(673706).makeClassName)("Table"),o=t.default.forwardRef((e,o)=>{let{children:n,className:s}=e,i=(0,r.__rest)(e,["children","className"]);return t.default.createElement("div",{className:(0,a.tremorTwMerge)(l("root"),"overflow-auto",s)},t.default.createElement("table",Object.assign({ref:o,className:(0,a.tremorTwMerge)(l("table"),"w-full text-tremor-default","text-tremor-content","dark:text-dark-tremor-content")},i),n))});o.displayName="Table",e.s(["Table",()=>o],269200)},427612,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(444755);let l=(0,e.i(673706).makeClassName)("TableHead"),o=t.default.forwardRef((e,o)=>{let{children:n,className:s}=e,i=(0,r.__rest)(e,["children","className"]);return t.default.createElement(t.default.Fragment,null,t.default.createElement("thead",Object.assign({ref:o,className:(0,a.tremorTwMerge)(l("root"),"text-left","text-tremor-content","dark:text-dark-tremor-content",s)},i),n))});o.displayName="TableHead",e.s(["TableHead",()=>o],427612)},64848,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(444755);let l=(0,e.i(673706).makeClassName)("TableHeaderCell"),o=t.default.forwardRef((e,o)=>{let{children:n,className:s}=e,i=(0,r.__rest)(e,["children","className"]);return t.default.createElement(t.default.Fragment,null,t.default.createElement("th",Object.assign({ref:o,className:(0,a.tremorTwMerge)(l("root"),"whitespace-nowrap text-left font-semibold top-0 px-4 py-3.5","text-tremor-content-strong","dark:text-dark-tremor-content-strong",s)},i),n))});o.displayName="TableHeaderCell",e.s(["TableHeaderCell",()=>o],64848)},942232,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(444755);let l=(0,e.i(673706).makeClassName)("TableBody"),o=t.default.forwardRef((e,o)=>{let{children:n,className:s}=e,i=(0,r.__rest)(e,["children","className"]);return t.default.createElement(t.default.Fragment,null,t.default.createElement("tbody",Object.assign({ref:o,className:(0,a.tremorTwMerge)(l("root"),"align-top divide-y","divide-tremor-border","dark:divide-dark-tremor-border",s)},i),n))});o.displayName="TableBody",e.s(["TableBody",()=>o],942232)},496020,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(444755);let l=(0,e.i(673706).makeClassName)("TableRow"),o=t.default.forwardRef((e,o)=>{let{children:n,className:s}=e,i=(0,r.__rest)(e,["children","className"]);return t.default.createElement(t.default.Fragment,null,t.default.createElement("tr",Object.assign({ref:o,className:(0,a.tremorTwMerge)(l("row"),s)},i),n))});o.displayName="TableRow",e.s(["TableRow",()=>o],496020)},977572,e=>{"use strict";var r=e.i(290571),t=e.i(271645),a=e.i(444755);let l=(0,e.i(673706).makeClassName)("TableCell"),o=t.default.forwardRef((e,o)=>{let{children:n,className:s}=e,i=(0,r.__rest)(e,["children","className"]);return t.default.createElement(t.default.Fragment,null,t.default.createElement("td",Object.assign({ref:o,className:(0,a.tremorTwMerge)(l("root"),"align-middle whitespace-nowrap text-left p-4",s)},i),n))});o.displayName="TableCell",e.s(["TableCell",()=>o],977572)},68155,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),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.s(["TrashIcon",0,t],68155)},278587,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),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.s(["RefreshIcon",0,t],278587)},118366,e=>{"use strict";var r=e.i(991124);e.s(["CopyIcon",()=>r.default])},678784,678745,e=>{"use strict";let r=(0,e.i(475254).default)("check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);e.s(["default",()=>r],678745),e.s(["CheckIcon",()=>r],678784)},991124,e=>{"use strict";let r=(0,e.i(475254).default)("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"}]]);e.s(["default",()=>r])},54943,e=>{"use strict";let r=(0,e.i(475254).default)("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]);e.s(["default",()=>r])},166406,e=>{"use strict";var r=e.i(190144);e.s(["CopyOutlined",()=>r.default])},94629,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"}))});e.s(["SwitchVerticalIcon",0,t],94629)},646563,e=>{"use strict";var r=e.i(959013);e.s(["PlusOutlined",()=>r.default])},597440,e=>{"use strict";e.i(247167);var r=e.i(931067),t=e.i(271645);let a={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"}}]},name:"delete",theme:"outlined"};var l=e.i(9583),o=t.forwardRef(function(e,o){return t.createElement(l.default,(0,r.default)({},e,{ref:o,icon:a}))});e.s(["default",0,o],597440)},955135,e=>{"use strict";var r=e.i(597440);e.s(["DeleteOutlined",()=>r.default])},127952,e=>{"use strict";var r=e.i(843476),t=e.i(560445),a=e.i(175712),l=e.i(869216),o=e.i(311451),n=e.i(212931),s=e.i(898586),i=e.i(368869),d=e.i(270377),u=e.i(271645);function c({isOpen:e,title:c,alertMessage:m,message:f,resourceInformationTitle:g,resourceInformation:h,onCancel:b,onOk:p,confirmLoading:v,requiredConfirmation:w}){let{Title:x,Text:k}=s.Typography,{token:C}=i.theme.useToken(),[y,E]=(0,u.useState)("");return(0,u.useEffect)(()=>{e&&E("")},[e]),(0,r.jsx)(n.Modal,{title:c,open:e,onOk:p,onCancel:b,confirmLoading:v,okText:v?"Deleting...":"Delete",cancelText:"Cancel",okButtonProps:{danger:!0,disabled:!!w&&y!==w||v},cancelButtonProps:{disabled:v},children:(0,r.jsxs)("div",{className:"space-y-4",children:[m&&(0,r.jsx)(t.Alert,{message:m,type:"warning"}),(0,r.jsx)(a.Card,{title:g,className:"mt-4",styles:{body:{padding:"16px"},header:{backgroundColor:C.colorErrorBg,borderColor:C.colorErrorBorder}},style:{backgroundColor:C.colorErrorBg,borderColor:C.colorErrorBorder},children:(0,r.jsx)(l.Descriptions,{column:1,size:"small",children:h&&h.map(({label:e,value:t,...a})=>(0,r.jsx)(l.Descriptions.Item,{label:(0,r.jsx)("span",{className:"font-semibold",children:e}),children:(0,r.jsx)(k,{...a,children:t??"-"})},e))})}),(0,r.jsx)("div",{children:(0,r.jsx)(k,{children:f})}),w&&(0,r.jsxs)("div",{className:"mb-6 mt-4 pt-4 border-t border-gray-200 dark:border-gray-700",children:[(0,r.jsxs)(k,{className:"block text-base font-medium text-gray-700 dark:text-gray-300 mb-2",children:[(0,r.jsx)(k,{children:"Type "}),(0,r.jsx)(k,{strong:!0,type:"danger",children:w}),(0,r.jsx)(k,{children:" to confirm deletion:"})]}),(0,r.jsx)(o.Input,{value:y,onChange:e=>E(e.target.value),placeholder:w,className:"rounded-md",prefix:(0,r.jsx)(d.ExclamationCircleOutlined,{style:{color:C.colorError}}),autoFocus:!0})]})]})})}e.s(["default",()=>c])},270377,e=>{"use strict";e.i(247167);var r=e.i(931067),t=e.i(271645);let 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"};var l=e.i(9583),o=t.forwardRef(function(e,o){return t.createElement(l.default,(0,r.default)({},e,{ref:o,icon:a}))});e.s(["ExclamationCircleOutlined",0,o],270377)},368869,e=>{"use strict";e.i(296059);var r=e.i(868297),t=e.i(732961),a=e.i(289882),l=e.i(170517),o=e.i(628882),n=e.i(320890),s=e.i(104458),i=e.i(722319),d=e.i(8398),u=e.i(279728);e.i(765846);var c=e.i(602716),m=e.i(328052);e.i(262370);var f=e.i(135551);let g=(e,r)=>new f.FastColor(e).setA(r).toRgbString(),h=(e,r)=>new f.FastColor(e).lighten(r).toHexString(),b=e=>{let r=(0,c.generate)(e,{theme:"dark"});return{1:r[0],2:r[1],3:r[2],4:r[3],5:r[6],6:r[5],7:r[4],8:r[6],9:r[5],10:r[4]}},p=(e,r)=>{let t=e||"#000",a=r||"#fff";return{colorBgBase:t,colorTextBase:a,colorText:g(a,.85),colorTextSecondary:g(a,.65),colorTextTertiary:g(a,.45),colorTextQuaternary:g(a,.25),colorFill:g(a,.18),colorFillSecondary:g(a,.12),colorFillTertiary:g(a,.08),colorFillQuaternary:g(a,.04),colorBgSolid:g(a,.95),colorBgSolidHover:g(a,1),colorBgSolidActive:g(a,.9),colorBgElevated:h(t,12),colorBgContainer:h(t,8),colorBgLayout:h(t,0),colorBgSpotlight:h(t,26),colorBgBlur:g(a,.04),colorBorder:h(t,26),colorBorderSecondary:h(t,19)}},v={defaultSeed:n.defaultConfig.token,useToken:function(){let[e,r,t]=(0,s.useToken)();return{theme:e,token:r,hashId:t}},defaultAlgorithm:i.default,darkAlgorithm:(e,r)=>{let t=Object.keys(l.defaultPresetColors).map(r=>{let t=(0,c.generate)(e[r],{theme:"dark"});return Array.from({length:10},()=>1).reduce((e,a,l)=>(e[`${r}-${l+1}`]=t[l],e[`${r}${l+1}`]=t[l],e),{})}).reduce((e,r)=>e=Object.assign(Object.assign({},e),r),{}),a=null!=r?r:(0,i.default)(e),o=(0,m.default)(e,{generateColorPalettes:b,generateNeutralColorPalettes:p});return Object.assign(Object.assign(Object.assign(Object.assign({},a),t),o),{colorPrimaryBg:o.colorPrimaryBorder,colorPrimaryBgHover:o.colorPrimaryBorderHover})},compactAlgorithm:(e,r)=>{let t=null!=r?r:(0,i.default)(e),a=t.fontSizeSM,l=t.controlHeight-4;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},t),function(e){let{sizeUnit:r,sizeStep:t}=e,a=t-2;return{sizeXXL:r*(a+10),sizeXL:r*(a+6),sizeLG:r*(a+2),sizeMD:r*(a+2),sizeMS:r*(a+1),size:r*a,sizeSM:r*a,sizeXS:r*(a-1),sizeXXS:r*(a-1)}}(null!=r?r:e)),(0,u.default)(a)),{controlHeight:l}),(0,d.default)(Object.assign(Object.assign({},t),{controlHeight:l})))},getDesignToken:e=>{let n=(null==e?void 0:e.algorithm)?(0,r.createTheme)(e.algorithm):a.default,s=Object.assign(Object.assign({},l.default),null==e?void 0:e.token);return(0,t.getComputedToken)(s,{override:null==e?void 0:e.token},n,o.default)},defaultConfig:n.defaultConfig,_internalContext:n.DesignTokenContext};e.s(["theme",0,v],368869)},530212,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10 19l-7-7m0 0l7-7m-7 7h18"}))});e.s(["ArrowLeftIcon",0,t],530212)},367240,555436,e=>{"use strict";let r=(0,e.i(475254).default)("rotate-ccw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);e.s(["RotateCcw",()=>r],367240);var t=e.i(54943);e.s(["Search",()=>t.default],555436)},655913,38419,78334,284614,e=>{"use strict";var r=e.i(843476),t=e.i(115504),a=e.i(311451),l=e.i(374009),o=e.i(271645);e.s(["FilterInput",0,({placeholder:e,value:n,onChange:s,icon:i,className:d})=>{let[u,c]=(0,o.useState)(n);(0,o.useEffect)(()=>{c(n)},[n]);let m=(0,o.useMemo)(()=>(0,l.default)(e=>s(e),300),[s]);(0,o.useEffect)(()=>()=>{m.cancel()},[m]);let f=(0,o.useCallback)(e=>{let r=e.target.value;c(r),m(r)},[m]);return(0,r.jsx)(a.Input,{placeholder:e,value:u,onChange:f,prefix:i?(0,r.jsx)(i,{size:16,className:"text-gray-500"}):void 0,className:(0,t.cx)("w-64",d)})}],655913);var n=e.i(906579),s=e.i(464571),i=e.i(475254);let d=(0,i.default)("funnel",[["path",{d:"M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z",key:"sc7q7i"}]]);e.s(["FiltersButton",0,({onClick:e,active:t,hasActiveFilters:a,label:l="Filters"})=>(0,r.jsx)(n.Badge,{color:"blue",dot:a,children:(0,r.jsx)(s.Button,{type:"default",onClick:e,icon:(0,r.jsx)(d,{size:16}),className:t?"bg-gray-100":"",children:l})})],38419);var u=e.i(367240);e.s(["ResetFiltersButton",0,({onClick:e,label:t="Reset Filters"})=>(0,r.jsx)(s.Button,{type:"default",onClick:e,icon:(0,r.jsx)(u.RotateCcw,{size:16}),children:t})],78334);let c=(0,i.default)("user",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]);e.s(["User",()=>c],284614)},888288,e=>{"use strict";var r=e.i(271645);let t=(e,t)=>{let a=void 0!==t,[l,o]=(0,r.useState)(e);return[a?t:l,e=>{a||o(e)}]};e.s(["default",()=>t])},757440,e=>{"use strict";var r=e.i(290571),t=e.i(271645);let a=e=>{var a=(0,r.__rest)(e,[]);return t.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},a),t.default.createElement("path",{d:"M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z"}))};e.s(["default",()=>a])},446428,854056,e=>{"use strict";let r;var t=e.i(290571),a=e.i(271645);let l=e=>{var r=(0,t.__rest)(e,[]);return a.default.createElement("svg",Object.assign({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor"},r),a.default.createElement("path",{d:"M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 10.5858L9.17157 7.75736L7.75736 9.17157L10.5858 12L7.75736 14.8284L9.17157 16.2426L12 13.4142L14.8284 16.2426L16.2426 14.8284L13.4142 12L16.2426 9.17157L14.8284 7.75736L12 10.5858Z"}))};e.s(["default",()=>l],446428);var o=e.i(746725),n=e.i(914189),s=e.i(553521),i=e.i(835696),d=e.i(941444),u=e.i(178677),c=e.i(294316),m=e.i(83733),f=e.i(233137),g=e.i(732607),h=e.i(397701),b=e.i(700020);function p(e){var r;return!!(e.enter||e.enterFrom||e.enterTo||e.leave||e.leaveFrom||e.leaveTo)||(null!=(r=e.as)?r:y)!==a.Fragment||1===a.default.Children.count(e.children)}let v=(0,a.createContext)(null);v.displayName="TransitionContext";var w=((r=w||{}).Visible="visible",r.Hidden="hidden",r);let x=(0,a.createContext)(null);function k(e){return"children"in e?k(e.children):e.current.filter(({el:e})=>null!==e.current).filter(({state:e})=>"visible"===e).length>0}function C(e,r){let t=(0,d.useLatestValue)(e),l=(0,a.useRef)([]),i=(0,s.useIsMounted)(),u=(0,o.useDisposables)(),c=(0,n.useEvent)((e,r=b.RenderStrategy.Hidden)=>{let a=l.current.findIndex(({el:r})=>r===e);-1!==a&&((0,h.match)(r,{[b.RenderStrategy.Unmount](){l.current.splice(a,1)},[b.RenderStrategy.Hidden](){l.current[a].state="hidden"}}),u.microTask(()=>{var e;!k(l)&&i.current&&(null==(e=t.current)||e.call(t))}))}),m=(0,n.useEvent)(e=>{let r=l.current.find(({el:r})=>r===e);return r?"visible"!==r.state&&(r.state="visible"):l.current.push({el:e,state:"visible"}),()=>c(e,b.RenderStrategy.Unmount)}),f=(0,a.useRef)([]),g=(0,a.useRef)(Promise.resolve()),p=(0,a.useRef)({enter:[],leave:[]}),v=(0,n.useEvent)((e,t,a)=>{f.current.splice(0),r&&(r.chains.current[t]=r.chains.current[t].filter(([r])=>r!==e)),null==r||r.chains.current[t].push([e,new Promise(e=>{f.current.push(e)})]),null==r||r.chains.current[t].push([e,new Promise(e=>{Promise.all(p.current[t].map(([e,r])=>r)).then(()=>e())})]),"enter"===t?g.current=g.current.then(()=>null==r?void 0:r.wait.current).then(()=>a(t)):a(t)}),w=(0,n.useEvent)((e,r,t)=>{Promise.all(p.current[r].splice(0).map(([e,r])=>r)).then(()=>{var e;null==(e=f.current.shift())||e()}).then(()=>t(r))});return(0,a.useMemo)(()=>({children:l,register:m,unregister:c,onStart:v,onStop:w,wait:g,chains:p}),[m,c,l,v,w,p,g])}x.displayName="NestingContext";let y=a.Fragment,E=b.RenderFeatures.RenderStrategy,T=(0,b.forwardRefWithAs)(function(e,r){let{show:t,appear:l=!1,unmount:o=!0,...s}=e,d=(0,a.useRef)(null),m=p(e),g=(0,c.useSyncRefs)(...m?[d,r]:null===r?[]:[r]);(0,u.useServerHandoffComplete)();let h=(0,f.useOpenClosed)();if(void 0===t&&null!==h&&(t=(h&f.State.Open)===f.State.Open),void 0===t)throw Error("A is used but it is missing a `show={true | false}` prop.");let[w,y]=(0,a.useState)(t?"visible":"hidden"),T=C(()=>{t||y("hidden")}),[M,j]=(0,a.useState)(!0),R=(0,a.useRef)([t]);(0,i.useIsoMorphicEffect)(()=>{!1!==M&&R.current[R.current.length-1]!==t&&(R.current.push(t),j(!1))},[R,t]);let S=(0,a.useMemo)(()=>({show:t,appear:l,initial:M}),[t,l,M]);(0,i.useIsoMorphicEffect)(()=>{t?y("visible"):k(T)||null===d.current||y("hidden")},[t,T]);let O={unmount:o},L=(0,n.useEvent)(()=>{var r;M&&j(!1),null==(r=e.beforeEnter)||r.call(e)}),B=(0,n.useEvent)(()=>{var r;M&&j(!1),null==(r=e.beforeLeave)||r.call(e)}),P=(0,b.useRender)();return a.default.createElement(x.Provider,{value:T},a.default.createElement(v.Provider,{value:S},P({ourProps:{...O,as:a.Fragment,children:a.default.createElement(N,{ref:g,...O,...s,beforeEnter:L,beforeLeave:B})},theirProps:{},defaultTag:a.Fragment,features:E,visible:"visible"===w,name:"Transition"})))}),N=(0,b.forwardRefWithAs)(function(e,r){var t,l;let{transition:o=!0,beforeEnter:s,afterEnter:d,beforeLeave:w,afterLeave:T,enter:N,enterFrom:M,enterTo:j,entered:R,leave:S,leaveFrom:O,leaveTo:L,...B}=e,[P,F]=(0,a.useState)(null),H=(0,a.useRef)(null),z=p(e),I=(0,c.useSyncRefs)(...z?[H,r,F]:null===r?[]:[r]),A=null==(t=B.unmount)||t?b.RenderStrategy.Unmount:b.RenderStrategy.Hidden,{show:_,appear:V,initial:D}=function(){let e=(0,a.useContext)(v);if(null===e)throw Error("A is used but it is missing a parent or .");return e}(),[X,W]=(0,a.useState)(_?"visible":"hidden"),U=function(){let e=(0,a.useContext)(x);if(null===e)throw Error("A is used but it is missing a parent or .");return e}(),{register:Y,unregister:q}=U;(0,i.useIsoMorphicEffect)(()=>Y(H),[Y,H]),(0,i.useIsoMorphicEffect)(()=>{if(A===b.RenderStrategy.Hidden&&H.current)return _&&"visible"!==X?void W("visible"):(0,h.match)(X,{hidden:()=>q(H),visible:()=>Y(H)})},[X,H,Y,q,_,A]);let $=(0,u.useServerHandoffComplete)();(0,i.useIsoMorphicEffect)(()=>{if(z&&$&&"visible"===X&&null===H.current)throw Error("Did you forget to passthrough the `ref` to the actual DOM node?")},[H,X,$,z]);let Z=D&&!V,K=V&&_&&D,Q=(0,a.useRef)(!1),G=C(()=>{Q.current||(W("hidden"),q(H))},U),J=(0,n.useEvent)(e=>{Q.current=!0,G.onStart(H,e?"enter":"leave",e=>{"enter"===e?null==s||s():"leave"===e&&(null==w||w())})}),ee=(0,n.useEvent)(e=>{let r=e?"enter":"leave";Q.current=!1,G.onStop(H,r,e=>{"enter"===e?null==d||d():"leave"===e&&(null==T||T())}),"leave"!==r||k(G)||(W("hidden"),q(H))});(0,a.useEffect)(()=>{z&&o||(J(_),ee(_))},[_,z,o]);let er=!(!o||!z||!$||Z),[,et]=(0,m.useTransition)(er,P,_,{start:J,end:ee}),ea=(0,b.compact)({ref:I,className:(null==(l=(0,g.classNames)(B.className,K&&N,K&&M,et.enter&&N,et.enter&&et.closed&&M,et.enter&&!et.closed&&j,et.leave&&S,et.leave&&!et.closed&&O,et.leave&&et.closed&&L,!et.transition&&_&&R))?void 0:l.trim())||void 0,...(0,m.transitionDataAttributes)(et)}),el=0;"visible"===X&&(el|=f.State.Open),"hidden"===X&&(el|=f.State.Closed),et.enter&&(el|=f.State.Opening),et.leave&&(el|=f.State.Closing);let eo=(0,b.useRender)();return a.default.createElement(x.Provider,{value:G},a.default.createElement(f.OpenClosedProvider,{value:el},eo({ourProps:ea,theirProps:B,defaultTag:y,features:E,visible:"visible"===X,name:"Transition.Child"})))}),M=(0,b.forwardRefWithAs)(function(e,r){let t=null!==(0,a.useContext)(v),l=null!==(0,f.useOpenClosed)();return a.default.createElement(a.default.Fragment,null,!t&&l?a.default.createElement(T,{ref:r,...e}):a.default.createElement(N,{ref:r,...e}))}),j=Object.assign(T,{Child:M,Root:T});e.s(["Transition",()=>j],854056)},206929,e=>{"use strict";var r=e.i(290571),t=e.i(757440),a=e.i(271645),l=e.i(446428),o=e.i(444755),n=e.i(673706),s=e.i(103471),i=e.i(495470),d=e.i(854056),u=e.i(888288);let c=(0,n.makeClassName)("Select"),m=a.default.forwardRef((e,n)=>{let{defaultValue:m="",value:f,onValueChange:g,placeholder:h="Select...",disabled:b=!1,icon:p,enableClear:v=!1,required:w,children:x,name:k,error:C=!1,errorMessage:y,className:E,id:T}=e,N=(0,r.__rest)(e,["defaultValue","value","onValueChange","placeholder","disabled","icon","enableClear","required","children","name","error","errorMessage","className","id"]),M=(0,a.useRef)(null),j=a.Children.toArray(x),[R,S]=(0,u.default)(m,f),O=(0,a.useMemo)(()=>{let e=a.default.Children.toArray(x).filter(a.isValidElement);return(0,s.constructValueToNameMapping)(e)},[x]);return a.default.createElement("div",{className:(0,o.tremorTwMerge)("w-full min-w-[10rem] text-tremor-default",E)},a.default.createElement("div",{className:"relative"},a.default.createElement("select",{title:"select-hidden",required:w,className:(0,o.tremorTwMerge)("h-full w-full absolute left-0 top-0 -z-10 opacity-0"),value:R,onChange:e=>{e.preventDefault()},name:k,disabled:b,id:T,onFocus:()=>{let e=M.current;e&&e.focus()}},a.default.createElement("option",{className:"hidden",value:"",disabled:!0,hidden:!0},h),j.map(e=>{let r=e.props.value,t=e.props.children;return a.default.createElement("option",{className:"hidden",key:r,value:r},t)})),a.default.createElement(i.Listbox,Object.assign({as:"div",ref:n,defaultValue:R,value:R,onChange:e=>{null==g||g(e),S(e)},disabled:b,id:T},N),({value:e})=>{var r;return a.default.createElement(a.default.Fragment,null,a.default.createElement(i.ListboxButton,{ref:M,className:(0,o.tremorTwMerge)("w-full outline-none text-left whitespace-nowrap truncate rounded-tremor-default focus:ring-2 transition duration-100 border pr-8 py-2","border-tremor-border shadow-tremor-input focus:border-tremor-brand-subtle focus:ring-tremor-brand-muted","dark:border-dark-tremor-border dark:shadow-dark-tremor-input dark:focus:border-dark-tremor-brand-subtle dark:focus:ring-dark-tremor-brand-muted",p?"pl-10":"pl-3",(0,s.getSelectButtonColors)((0,s.hasValue)(e),b,C))},p&&a.default.createElement("span",{className:(0,o.tremorTwMerge)("absolute inset-y-0 left-0 flex items-center ml-px pl-2.5")},a.default.createElement(p,{className:(0,o.tremorTwMerge)(c("Icon"),"flex-none h-5 w-5","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")})),a.default.createElement("span",{className:"w-[90%] block truncate"},e&&null!=(r=O.get(e))?r:h),a.default.createElement("span",{className:(0,o.tremorTwMerge)("absolute inset-y-0 right-0 flex items-center mr-3")},a.default.createElement(t.default,{className:(0,o.tremorTwMerge)(c("arrowDownIcon"),"flex-none h-5 w-5","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")}))),v&&R?a.default.createElement("button",{type:"button",className:(0,o.tremorTwMerge)("absolute inset-y-0 right-0 flex items-center mr-8"),onClick:e=>{e.preventDefault(),S(""),null==g||g("")}},a.default.createElement(l.default,{className:(0,o.tremorTwMerge)(c("clearIcon"),"flex-none h-4 w-4","text-tremor-content-subtle","dark:text-dark-tremor-content-subtle")})):null,a.default.createElement(d.Transition,{enter:"transition ease duration-100 transform",enterFrom:"opacity-0 -translate-y-4",enterTo:"opacity-100 translate-y-0",leave:"transition ease duration-100 transform",leaveFrom:"opacity-100 translate-y-0",leaveTo:"opacity-0 -translate-y-4"},a.default.createElement(i.ListboxOptions,{anchor:"bottom start",className:(0,o.tremorTwMerge)("z-10 w-[var(--button-width)] divide-y overflow-y-auto outline-none rounded-tremor-default max-h-[228px] border [--anchor-gap:4px]","bg-tremor-background border-tremor-border divide-tremor-border shadow-tremor-dropdown","dark:bg-dark-tremor-background dark:border-dark-tremor-border dark:divide-dark-tremor-border dark:shadow-dark-tremor-dropdown")},x)))})),C&&y?a.default.createElement("p",{className:(0,o.tremorTwMerge)("errorMessage","text-sm text-rose-500 mt-1")},y):null)});m.displayName="Select",e.s(["Select",()=>m],206929)},502275,e=>{"use strict";var r=e.i(271645);let t=r.forwardRef(function(e,t){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:t},e),r.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"}))});e.s(["InformationCircleIcon",0,t],502275)},114600,e=>{"use strict";var r=e.i(290571),t=e.i(444755),a=e.i(673706),l=e.i(271645);let o=(0,a.makeClassName)("Divider"),n=l.default.forwardRef((e,a)=>{let{className:n,children:s}=e,i=(0,r.__rest)(e,["className","children"]);return l.default.createElement("div",Object.assign({ref:a,className:(0,t.tremorTwMerge)(o("root"),"w-full mx-auto my-6 flex justify-between gap-3 items-center text-tremor-default","text-tremor-content","dark:text-dark-tremor-content",n)},i),s?l.default.createElement(l.default.Fragment,null,l.default.createElement("div",{className:(0,t.tremorTwMerge)("w-full h-[1px] bg-tremor-border dark:bg-dark-tremor-border")}),l.default.createElement("div",{className:(0,t.tremorTwMerge)("text-inherit whitespace-nowrap")},s),l.default.createElement("div",{className:(0,t.tremorTwMerge)("w-full h-[1px] bg-tremor-border dark:bg-dark-tremor-border")})):l.default.createElement("div",{className:(0,t.tremorTwMerge)("w-full h-[1px] bg-tremor-border dark:bg-dark-tremor-border")}))});n.displayName="Divider",e.s(["Divider",()=>n],114600)},78085,e=>{"use strict";var r=e.i(290571),t=e.i(103471),a=e.i(888288),l=e.i(271645),o=e.i(444755),n=e.i(673706);let s=(0,n.makeClassName)("Textarea"),i=l.default.forwardRef((e,i)=>{let{value:d,defaultValue:u="",placeholder:c="Type...",error:m=!1,errorMessage:f,disabled:g=!1,className:h,onChange:b,onValueChange:p,autoHeight:v=!1}=e,w=(0,r.__rest)(e,["value","defaultValue","placeholder","error","errorMessage","disabled","className","onChange","onValueChange","autoHeight"]),[x,k]=(0,a.default)(u,d),C=(0,l.useRef)(null),y=(0,t.hasValue)(x);return(0,l.useEffect)(()=>{let e=C.current;if(v&&e){e.style.height="60px";let r=e.scrollHeight;e.style.height=r+"px"}},[v,C,x]),l.default.createElement(l.default.Fragment,null,l.default.createElement("textarea",Object.assign({ref:(0,n.mergeRefs)([C,i]),value:x,placeholder:c,disabled:g,className:(0,o.tremorTwMerge)(s("Textarea"),"w-full flex items-center outline-none rounded-tremor-default px-3 py-2 text-tremor-default focus:ring-2 transition duration-100 border","shadow-tremor-input focus:border-tremor-brand-subtle focus:ring-tremor-brand-muted","dark:shadow-dark-tremor-input focus:dark:border-dark-tremor-brand-subtle focus:dark:ring-dark-tremor-brand-muted",(0,t.getSelectButtonColors)(y,g,m),g?"placeholder:text-tremor-content-subtle dark:placeholder:text-dark-tremor-content-subtle":"placeholder:text-tremor-content dark:placeholder:text-dark-tremor-content",h),"data-testid":"text-area",onChange:e=>{null==b||b(e),k(e.target.value),null==p||p(e.target.value)}},w)),m&&f?l.default.createElement("p",{className:(0,o.tremorTwMerge)(s("errorMessage"),"text-sm text-red-500 mt-1")},f):null)});i.displayName="Textarea",e.s(["Textarea",()=>i],78085)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/10376d0955336027.js b/litellm/proxy/_experimental/out/_next/static/chunks/10376d0955336027.js deleted file mode 100644 index 55ce00c27b0..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/10376d0955336027.js +++ /dev/null @@ -1,12 +0,0 @@ -(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,295320,e=>{"use strict";e.i(247167);var t=e.i(931067),i=e.i(271645);let r={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M704 446H320c-4.4 0-8 3.6-8 8v402c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8V454c0-4.4-3.6-8-8-8zm-328 64h272v117H376V510zm272 290H376V683h272v117z"}},{tag:"path",attrs:{d:"M424 748a32 32 0 1064 0 32 32 0 10-64 0zm0-178a32 32 0 1064 0 32 32 0 10-64 0z"}},{tag:"path",attrs:{d:"M811.4 368.9C765.6 248 648.9 162 512.2 162S258.8 247.9 213 368.8C126.9 391.5 63.5 470.2 64 563.6 64.6 668 145.6 752.9 247.6 762c4.7.4 8.7-3.3 8.7-8v-60.4c0-4-3-7.4-7-7.9-27-3.4-52.5-15.2-72.1-34.5-24-23.5-37.2-55.1-37.2-88.6 0-28 9.1-54.4 26.2-76.4 16.7-21.4 40.2-36.9 66.1-43.7l37.9-10 13.9-36.7c8.6-22.8 20.6-44.2 35.7-63.5 14.9-19.2 32.6-36 52.4-50 41.1-28.9 89.5-44.2 140-44.2s98.9 15.3 140 44.3c19.9 14 37.5 30.8 52.4 50 15.1 19.3 27.1 40.7 35.7 63.5l13.8 36.6 37.8 10c54.2 14.4 92.1 63.7 92.1 120 0 33.6-13.2 65.1-37.2 88.6-19.5 19.2-44.9 31.1-71.9 34.5-4 .5-6.9 3.9-6.9 7.9V754c0 4.7 4.1 8.4 8.8 8 101.7-9.2 182.5-94 183.2-198.2.6-93.4-62.7-172.1-148.6-194.9z"}}]},name:"cloud-server",theme:"outlined"};var n=e.i(9583),a=i.forwardRef(function(e,a){return i.createElement(n.default,(0,t.default)({},e,{ref:a,icon:r}))});e.s(["CloudServerOutlined",0,a],295320)},283713,e=>{"use strict";var t=e.i(271645),i=e.i(602869),r=e.i(612256);let n="litellm_selected_worker_id";e.s(["useWorker",0,()=>{let{data:e}=(0,r.useUIConfig)(),a=e?.is_control_plane??!1,o=e?.workers??[],[l,s]=(0,t.useState)(()=>localStorage.getItem(n));(0,t.useEffect)(()=>{if(!l||0===o.length)return;let e=o.find(e=>e.worker_id===l);e&&(0,i.switchToWorkerUrl)(e.url)},[l,o]);let c=o.find(e=>e.worker_id===l)??null,d=(0,t.useCallback)(e=>{let t=o.find(t=>t.worker_id===e);t&&(s(e),localStorage.setItem(n,e),(0,i.switchToWorkerUrl)(t.url))},[o]);return{isControlPlane:a,workers:o,selectedWorkerId:l,selectedWorker:c,selectWorker:d,disconnectFromWorker:(0,t.useCallback)(()=>{s(null),localStorage.removeItem(n),(0,i.switchToWorkerUrl)(null)},[])}}])},954616,e=>{"use strict";var t=e.i(271645),i=e.i(114272),r=e.i(540143),n=e.i(915823),a=e.i(619273),o=class extends n.Subscribable{#e;#t=void 0;#i;#r;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#n()}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,a.shallowEqualObjects)(this.options,t)||this.#e.getMutationCache().notify({type:"observerOptionsUpdated",mutation:this.#i,observer:this}),t?.mutationKey&&this.options.mutationKey&&(0,a.hashKey)(t.mutationKey)!==(0,a.hashKey)(this.options.mutationKey)?this.reset():this.#i?.state.status==="pending"&&this.#i.setOptions(this.options)}onUnsubscribe(){this.hasListeners()||this.#i?.removeObserver(this)}onMutationUpdate(e){this.#n(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#i?.removeObserver(this),this.#i=void 0,this.#n(),this.#a()}mutate(e,t){return this.#r=t,this.#i?.removeObserver(this),this.#i=this.#e.getMutationCache().build(this.#e,this.options),this.#i.addObserver(this),this.#i.execute(e)}#n(){let e=this.#i?.state??(0,i.getDefaultState)();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){r.notifyManager.batch(()=>{if(this.#r&&this.hasListeners()){let t=this.#t.variables,i=this.#t.context,r={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type==="success"){try{this.#r.onSuccess?.(e.data,t,i,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(e.data,null,t,i,r)}catch(e){Promise.reject(e)}}else if(e?.type==="error"){try{this.#r.onError?.(e.error,t,i,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(void 0,e.error,t,i,r)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#t)})})}},l=e.i(912598);function s(e,i){let n=(0,l.useQueryClient)(i),[s]=t.useState(()=>new o(n,e));t.useEffect(()=>{s.setOptions(e)},[s,e]);let c=t.useSyncExternalStore(t.useCallback(e=>s.subscribe(r.notifyManager.batchCalls(e)),[s]),()=>s.getCurrentResult(),()=>s.getCurrentResult()),d=t.useCallback((e,t)=>{s.mutate(e,t).catch(a.noop)},[s]);if(c.error&&(0,a.shouldThrowError)(s.options.throwOnError,[c.error]))throw c.error;return{...c,mutate:d,mutateAsync:c.mutate}}e.s(["useMutation",()=>s],954616)},175712,e=>{"use strict";e.i(247167);var t=e.i(271645),i=e.i(343794),r=e.i(529681),n=e.i(242064),a=e.i(517455),o=e.i(185793),l=e.i(721369),s=function(e,t){var i={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(i[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(e);nt.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(e,r[n])&&(i[r[n]]=e[r[n]]);return i};let c=e=>{var{prefixCls:r,className:a,hoverable:o=!0}=e,l=s(e,["prefixCls","className","hoverable"]);let{getPrefixCls:c}=t.useContext(n.ConfigContext),d=c("card",r),u=(0,i.default)(`${d}-grid`,a,{[`${d}-grid-hoverable`]:o});return t.createElement("div",Object.assign({},l,{className:u}))};e.i(296059);var d=e.i(915654),u=e.i(183293),m=e.i(246422),p=e.i(838378);let g=(0,m.genStyleHooks)("Card",e=>{let t=(0,p.mergeToken)(e,{cardShadow:e.boxShadowCard,cardHeadPadding:e.padding,cardPaddingBase:e.paddingLG,cardActionsIconSize:e.fontSize});return[(e=>{let{componentCls:t,cardShadow:i,cardHeadPadding:r,colorBorderSecondary:n,boxShadowTertiary:a,bodyPadding:o,extraColor:l}=e;return{[t]:Object.assign(Object.assign({},(0,u.resetComponent)(e)),{position:"relative",background:e.colorBgContainer,borderRadius:e.borderRadiusLG,[`&:not(${t}-bordered)`]:{boxShadow:a},[`${t}-head`]:(e=>{let{antCls:t,componentCls:i,headerHeight:r,headerPadding:n,tabsMarginBottom:a}=e;return Object.assign(Object.assign({display:"flex",justifyContent:"center",flexDirection:"column",minHeight:r,marginBottom:-1,padding:`0 ${(0,d.unit)(n)}`,color:e.colorTextHeading,fontWeight:e.fontWeightStrong,fontSize:e.headerFontSize,background:e.headerBg,borderBottom:`${(0,d.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorderSecondary}`,borderRadius:`${(0,d.unit)(e.borderRadiusLG)} ${(0,d.unit)(e.borderRadiusLG)} 0 0`},(0,u.clearFix)()),{"&-wrapper":{width:"100%",display:"flex",alignItems:"center"},"&-title":Object.assign(Object.assign({display:"inline-block",flex:1},u.textEllipsis),{[` - > ${i}-typography, - > ${i}-typography-edit-content - `]:{insetInlineStart:0,marginTop:0,marginBottom:0}}),[`${t}-tabs-top`]:{clear:"both",marginBottom:a,color:e.colorText,fontWeight:"normal",fontSize:e.fontSize,"&-bar":{borderBottom:`${(0,d.unit)(e.lineWidth)} ${e.lineType} ${e.colorBorderSecondary}`}}})})(e),[`${t}-extra`]:{marginInlineStart:"auto",color:l,fontWeight:"normal",fontSize:e.fontSize},[`${t}-body`]:{padding:o,borderRadius:`0 0 ${(0,d.unit)(e.borderRadiusLG)} ${(0,d.unit)(e.borderRadiusLG)}`},[`${t}-grid`]:(e=>{let{cardPaddingBase:t,colorBorderSecondary:i,cardShadow:r,lineWidth:n}=e;return{width:"33.33%",padding:t,border:0,borderRadius:0,boxShadow:` - ${(0,d.unit)(n)} 0 0 0 ${i}, - 0 ${(0,d.unit)(n)} 0 0 ${i}, - ${(0,d.unit)(n)} ${(0,d.unit)(n)} 0 0 ${i}, - ${(0,d.unit)(n)} 0 0 0 ${i} inset, - 0 ${(0,d.unit)(n)} 0 0 ${i} inset; - `,transition:`all ${e.motionDurationMid}`,"&-hoverable:hover":{position:"relative",zIndex:1,boxShadow:r}}})(e),[`${t}-cover`]:{"> *":{display:"block",width:"100%",borderRadius:`${(0,d.unit)(e.borderRadiusLG)} ${(0,d.unit)(e.borderRadiusLG)} 0 0`}},[`${t}-actions`]:(e=>{let{componentCls:t,iconCls:i,actionsLiMargin:r,cardActionsIconSize:n,colorBorderSecondary:a,actionsBg:o}=e;return Object.assign(Object.assign({margin:0,padding:0,listStyle:"none",background:o,borderTop:`${(0,d.unit)(e.lineWidth)} ${e.lineType} ${a}`,display:"flex",borderRadius:`0 0 ${(0,d.unit)(e.borderRadiusLG)} ${(0,d.unit)(e.borderRadiusLG)}`},(0,u.clearFix)()),{"& > li":{margin:r,color:e.colorTextDescription,textAlign:"center","> span":{position:"relative",display:"block",minWidth:e.calc(e.cardActionsIconSize).mul(2).equal(),fontSize:e.fontSize,lineHeight:e.lineHeight,cursor:"pointer","&:hover":{color:e.colorPrimary,transition:`color ${e.motionDurationMid}`},[`a:not(${t}-btn), > ${i}`]:{display:"inline-block",width:"100%",color:e.colorIcon,lineHeight:(0,d.unit)(e.fontHeight),transition:`color ${e.motionDurationMid}`,"&:hover":{color:e.colorPrimary}},[`> ${i}`]:{fontSize:n,lineHeight:(0,d.unit)(e.calc(n).mul(e.lineHeight).equal())}},"&:not(:last-child)":{borderInlineEnd:`${(0,d.unit)(e.lineWidth)} ${e.lineType} ${a}`}}})})(e),[`${t}-meta`]:Object.assign(Object.assign({margin:`${(0,d.unit)(e.calc(e.marginXXS).mul(-1).equal())} 0`,display:"flex"},(0,u.clearFix)()),{"&-avatar":{paddingInlineEnd:e.padding},"&-detail":{overflow:"hidden",flex:1,"> div:not(:last-child)":{marginBottom:e.marginXS}},"&-title":Object.assign({color:e.colorTextHeading,fontWeight:e.fontWeightStrong,fontSize:e.fontSizeLG},u.textEllipsis),"&-description":{color:e.colorTextDescription}})}),[`${t}-bordered`]:{border:`${(0,d.unit)(e.lineWidth)} ${e.lineType} ${n}`,[`${t}-cover`]:{marginTop:-1,marginInlineStart:-1,marginInlineEnd:-1}},[`${t}-hoverable`]:{cursor:"pointer",transition:`box-shadow ${e.motionDurationMid}, border-color ${e.motionDurationMid}`,"&:hover":{borderColor:"transparent",boxShadow:i}},[`${t}-contain-grid`]:{borderRadius:`${(0,d.unit)(e.borderRadiusLG)} ${(0,d.unit)(e.borderRadiusLG)} 0 0 `,[`${t}-body`]:{display:"flex",flexWrap:"wrap"},[`&:not(${t}-loading) ${t}-body`]:{marginBlockStart:e.calc(e.lineWidth).mul(-1).equal(),marginInlineStart:e.calc(e.lineWidth).mul(-1).equal(),padding:0}},[`${t}-contain-tabs`]:{[`> div${t}-head`]:{minHeight:0,[`${t}-head-title, ${t}-extra`]:{paddingTop:r}}},[`${t}-type-inner`]:(e=>{let{componentCls:t,colorFillAlter:i,headerPadding:r,bodyPadding:n}=e;return{[`${t}-head`]:{padding:`0 ${(0,d.unit)(r)}`,background:i,"&-title":{fontSize:e.fontSize}},[`${t}-body`]:{padding:`${(0,d.unit)(e.padding)} ${(0,d.unit)(n)}`}}})(e),[`${t}-loading`]:(e=>{let{componentCls:t}=e;return{overflow:"hidden",[`${t}-body`]:{userSelect:"none"}}})(e),[`${t}-rtl`]:{direction:"rtl"}}})(t),(e=>{let{componentCls:t,bodyPaddingSM:i,headerPaddingSM:r,headerHeightSM:n,headerFontSizeSM:a}=e;return{[`${t}-small`]:{[`> ${t}-head`]:{minHeight:n,padding:`0 ${(0,d.unit)(r)}`,fontSize:a,[`> ${t}-head-wrapper`]:{[`> ${t}-extra`]:{fontSize:e.fontSize}}},[`> ${t}-body`]:{padding:i}},[`${t}-small${t}-contain-tabs`]:{[`> ${t}-head`]:{[`${t}-head-title, ${t}-extra`]:{paddingTop:0,display:"flex",alignItems:"center"}}}}})(t)]},e=>{var t,i;return{headerBg:"transparent",headerFontSize:e.fontSizeLG,headerFontSizeSM:e.fontSize,headerHeight:e.fontSizeLG*e.lineHeightLG+2*e.padding,headerHeightSM:e.fontSize*e.lineHeight+2*e.paddingXS,actionsBg:e.colorBgContainer,actionsLiMargin:`${e.paddingSM}px 0`,tabsMarginBottom:-e.padding-e.lineWidth,extraColor:e.colorText,bodyPaddingSM:12,headerPaddingSM:12,bodyPadding:null!=(t=e.bodyPadding)?t:e.paddingLG,headerPadding:null!=(i=e.headerPadding)?i:e.paddingLG}});var h=e.i(792812),f=function(e,t){var i={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(i[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(e);nt.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(e,r[n])&&(i[r[n]]=e[r[n]]);return i};let b=e=>{let{actionClasses:i,actions:r=[],actionStyle:n}=e;return t.createElement("ul",{className:i,style:n},r.map((e,i)=>{let n=`action-${i}`;return t.createElement("li",{style:{width:`${100/r.length}%`},key:n},t.createElement("span",null,e))}))},y=t.forwardRef((e,s)=>{let d,{prefixCls:u,className:m,rootClassName:p,style:y,extra:v,headStyle:x={},bodyStyle:$={},title:S,loading:j,bordered:w,variant:O,size:C,type:E,cover:I,actions:N,tabList:k,children:z,activeTabKey:L,defaultActiveTabKey:M,tabBarExtraContent:R,hoverable:P,tabProps:T={},classNames:_,styles:G}=e,B=f(e,["prefixCls","className","rootClassName","style","extra","headStyle","bodyStyle","title","loading","bordered","variant","size","type","cover","actions","tabList","children","activeTabKey","defaultActiveTabKey","tabBarExtraContent","hoverable","tabProps","classNames","styles"]),{getPrefixCls:A,direction:H,card:U}=t.useContext(n.ConfigContext),[W]=(0,h.default)("card",O,w),D=e=>{var t;return(0,i.default)(null==(t=null==U?void 0:U.classNames)?void 0:t[e],null==_?void 0:_[e])},F=e=>{var t;return Object.assign(Object.assign({},null==(t=null==U?void 0:U.styles)?void 0:t[e]),null==G?void 0:G[e])},K=t.useMemo(()=>{let e=!1;return t.Children.forEach(z,t=>{(null==t?void 0:t.type)===c&&(e=!0)}),e},[z]),q=A("card",u),[V,X,J]=g(q),Q=t.createElement(o.default,{loading:!0,active:!0,paragraph:{rows:4},title:!1},z),Y=void 0!==L,Z=Object.assign(Object.assign({},T),{[Y?"activeKey":"defaultActiveKey"]:Y?L:M,tabBarExtraContent:R}),ee=(0,a.default)(C),et=ee&&"default"!==ee?ee:"large",ei=k?t.createElement(l.default,Object.assign({size:et},Z,{className:`${q}-head-tabs`,onChange:t=>{var i;null==(i=e.onTabChange)||i.call(e,t)},items:k.map(e=>{var{tab:t}=e;return Object.assign({label:t},f(e,["tab"]))})})):null;if(S||v||ei){let e=(0,i.default)(`${q}-head`,D("header")),r=(0,i.default)(`${q}-head-title`,D("title")),n=(0,i.default)(`${q}-extra`,D("extra")),a=Object.assign(Object.assign({},x),F("header"));d=t.createElement("div",{className:e,style:a},t.createElement("div",{className:`${q}-head-wrapper`},S&&t.createElement("div",{className:r,style:F("title")},S),v&&t.createElement("div",{className:n,style:F("extra")},v)),ei)}let er=(0,i.default)(`${q}-cover`,D("cover")),en=I?t.createElement("div",{className:er,style:F("cover")},I):null,ea=(0,i.default)(`${q}-body`,D("body")),eo=Object.assign(Object.assign({},$),F("body")),el=t.createElement("div",{className:ea,style:eo},j?Q:z),es=(0,i.default)(`${q}-actions`,D("actions")),ec=(null==N?void 0:N.length)?t.createElement(b,{actionClasses:es,actionStyle:F("actions"),actions:N}):null,ed=(0,r.default)(B,["onTabChange"]),eu=(0,i.default)(q,null==U?void 0:U.className,{[`${q}-loading`]:j,[`${q}-bordered`]:"borderless"!==W,[`${q}-hoverable`]:P,[`${q}-contain-grid`]:K,[`${q}-contain-tabs`]:null==k?void 0:k.length,[`${q}-${ee}`]:ee,[`${q}-type-${E}`]:!!E,[`${q}-rtl`]:"rtl"===H},m,p,X,J),em=Object.assign(Object.assign({},null==U?void 0:U.style),y);return V(t.createElement("div",Object.assign({ref:s},ed,{className:eu,style:em}),d,en,el,ec))});var v=function(e,t){var i={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(i[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(e);nt.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(e,r[n])&&(i[r[n]]=e[r[n]]);return i};y.Grid=c,y.Meta=e=>{let{prefixCls:r,className:a,avatar:o,title:l,description:s}=e,c=v(e,["prefixCls","className","avatar","title","description"]),{getPrefixCls:d}=t.useContext(n.ConfigContext),u=d("card",r),m=(0,i.default)(`${u}-meta`,a),p=o?t.createElement("div",{className:`${u}-meta-avatar`},o):null,g=l?t.createElement("div",{className:`${u}-meta-title`},l):null,h=s?t.createElement("div",{className:`${u}-meta-description`},s):null,f=g||h?t.createElement("div",{className:`${u}-meta-detail`},g,h):null;return t.createElement("div",Object.assign({},c,{className:m}),p,f)},e.s(["Card",0,y],175712)},770914,908286,38243,e=>{"use strict";e.i(247167);var t=e.i(271645),i=e.i(343794),r=e.i(876556);function n(e){return["small","middle","large"].includes(e)}function a(e){return!!e&&"number"==typeof e&&!Number.isNaN(e)}e.s(["isPresetSize",()=>n,"isValidGapNumber",()=>a],908286);var o=e.i(242064),l=e.i(249616),s=e.i(372409),c=e.i(246422);let d=(0,c.genStyleHooks)(["Space","Addon"],e=>[(e=>{let{componentCls:t,borderRadius:i,paddingSM:r,colorBorder:n,paddingXS:a,fontSizeLG:o,fontSizeSM:l,borderRadiusLG:c,borderRadiusSM:d,colorBgContainerDisabled:u,lineWidth:m}=e;return{[t]:[{display:"inline-flex",alignItems:"center",gap:0,paddingInline:r,margin:0,background:u,borderWidth:m,borderStyle:"solid",borderColor:n,borderRadius:i,"&-large":{fontSize:o,borderRadius:c},"&-small":{paddingInline:a,borderRadius:d,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,s.genCompactItemStyle)(e,{focus:!1})]}})(e)]);var u=function(e,t){var i={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(i[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(e);nt.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(e,r[n])&&(i[r[n]]=e[r[n]]);return i};let m=t.default.forwardRef((e,r)=>{let{className:n,children:a,style:s,prefixCls:c}=e,m=u(e,["className","children","style","prefixCls"]),{getPrefixCls:p,direction:g}=t.default.useContext(o.ConfigContext),h=p("space-addon",c),[f,b,y]=d(h),{compactItemClassnames:v,compactSize:x}=(0,l.useCompactItemContext)(h,g),$=(0,i.default)(h,b,v,y,{[`${h}-${x}`]:x},n);return f(t.default.createElement("div",Object.assign({ref:r,className:$,style:s},m),a))}),p=t.default.createContext({latestIndex:0}),g=p.Provider,h=({className:e,index:i,children:r,split:n,style:a})=>{let{latestIndex:o}=t.useContext(p);return null==r?null:t.createElement(t.Fragment,null,t.createElement("div",{className:e,style:a},r),i{let t=(0,f.mergeToken)(e,{spaceGapSmallSize:e.paddingXS,spaceGapMiddleSize:e.padding,spaceGapLargeSize:e.paddingLG});return[(e=>{let{componentCls:t,antCls:i}=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"}},[`${t}-item:empty`]:{display:"none"},[`${t}-item > ${i}-badge-not-a-wrapper:only-child`]:{display:"block"}}}})(t),(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}}}})(t)]},()=>({}),{resetStyle:!1});var y=function(e,t){var i={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(i[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(e);nt.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(e,r[n])&&(i[r[n]]=e[r[n]]);return i};let v=t.forwardRef((e,l)=>{var s;let{getPrefixCls:c,direction:d,size:u,className:m,style:p,classNames:f,styles:v}=(0,o.useComponentConfig)("space"),{size:x=null!=u?u:"small",align:$,className:S,rootClassName:j,children:w,direction:O="horizontal",prefixCls:C,split:E,style:I,wrap:N=!1,classNames:k,styles:z}=e,L=y(e,["size","align","className","rootClassName","children","direction","prefixCls","split","style","wrap","classNames","styles"]),[M,R]=Array.isArray(x)?x:[x,x],P=n(R),T=n(M),_=a(R),G=a(M),B=(0,r.default)(w,{keepEmpty:!0}),A=void 0===$&&"horizontal"===O?"center":$,H=c("space",C),[U,W,D]=b(H),F=(0,i.default)(H,m,W,`${H}-${O}`,{[`${H}-rtl`]:"rtl"===d,[`${H}-align-${A}`]:A,[`${H}-gap-row-${R}`]:P,[`${H}-gap-col-${M}`]:T},S,j,D),K=(0,i.default)(`${H}-item`,null!=(s=null==k?void 0:k.item)?s:f.item),q=Object.assign(Object.assign({},v.item),null==z?void 0:z.item),V=B.map((e,i)=>{let r=(null==e?void 0:e.key)||`${K}-${i}`;return t.createElement(h,{className:K,key:r,index:i,split:E,style:q},e)}),X=t.useMemo(()=>({latestIndex:B.reduce((e,t,i)=>null!=t?i:e,0)}),[B]);if(0===B.length)return null;let J={};return N&&(J.flexWrap="wrap"),!T&&G&&(J.columnGap=M),!P&&_&&(J.rowGap=R),U(t.createElement("div",Object.assign({ref:l,className:F,style:Object.assign(Object.assign(Object.assign({},J),p),I)},L),t.createElement(g,{value:X},V)))});v.Compact=l.default,v.Addon=m,e.s(["default",0,v],38243),e.s(["Space",0,v],770914)},560445,e=>{"use strict";e.i(247167);var t=e.i(271645),i=e.i(201072),r=e.i(726289),n=e.i(864517),a=e.i(562901),o=e.i(779573),l=e.i(343794),s=e.i(361275),c=e.i(244009),d=e.i(611935),u=e.i(763731),m=e.i(242064);e.i(296059);var p=e.i(915654),g=e.i(183293),h=e.i(246422);let f=(e,t,i,r,n)=>({background:e,border:`${(0,p.unit)(r.lineWidth)} ${r.lineType} ${t}`,[`${n}-icon`]:{color:i}}),b=(0,h.genStyleHooks)("Alert",e=>[(e=>{let{componentCls:t,motionDurationSlow:i,marginXS:r,marginSM:n,fontSize:a,fontSizeLG:o,lineHeight:l,borderRadiusLG:s,motionEaseInOutCirc:c,withDescriptionIconSize:d,colorText:u,colorTextHeading:m,withDescriptionPadding:p,defaultPadding:h}=e;return{[t]:Object.assign(Object.assign({},(0,g.resetComponent)(e)),{position:"relative",display:"flex",alignItems:"center",padding:h,wordWrap:"break-word",borderRadius:s,[`&${t}-rtl`]:{direction:"rtl"},[`${t}-content`]:{flex:1,minWidth:0},[`${t}-icon`]:{marginInlineEnd:r,lineHeight:0},"&-description":{display:"none",fontSize:a,lineHeight:l},"&-message":{color:m},[`&${t}-motion-leave`]:{overflow:"hidden",opacity:1,transition:`max-height ${i} ${c}, opacity ${i} ${c}, - padding-top ${i} ${c}, padding-bottom ${i} ${c}, - margin-bottom ${i} ${c}`},[`&${t}-motion-leave-active`]:{maxHeight:0,marginBottom:"0 !important",paddingTop:0,paddingBottom:0,opacity:0}}),[`${t}-with-description`]:{alignItems:"flex-start",padding:p,[`${t}-icon`]:{marginInlineEnd:n,fontSize:d,lineHeight:0},[`${t}-message`]:{display:"block",marginBottom:r,color:m,fontSize:o},[`${t}-description`]:{display:"block",color:u}},[`${t}-banner`]:{marginBottom:0,border:"0 !important",borderRadius:0}}})(e),(e=>{let{componentCls:t,colorSuccess:i,colorSuccessBorder:r,colorSuccessBg:n,colorWarning:a,colorWarningBorder:o,colorWarningBg:l,colorError:s,colorErrorBorder:c,colorErrorBg:d,colorInfo:u,colorInfoBorder:m,colorInfoBg:p}=e;return{[t]:{"&-success":f(n,r,i,e,t),"&-info":f(p,m,u,e,t),"&-warning":f(l,o,a,e,t),"&-error":Object.assign(Object.assign({},f(d,c,s,e,t)),{[`${t}-description > pre`]:{margin:0,padding:0}})}}})(e),(e=>{let{componentCls:t,iconCls:i,motionDurationMid:r,marginXS:n,fontSizeIcon:a,colorIcon:o,colorIconHover:l}=e;return{[t]:{"&-action":{marginInlineStart:n},[`${t}-close-icon`]:{marginInlineStart:n,padding:0,overflow:"hidden",fontSize:a,lineHeight:(0,p.unit)(a),backgroundColor:"transparent",border:"none",outline:"none",cursor:"pointer",[`${i}-close`]:{color:o,transition:`color ${r}`,"&:hover":{color:l}}},"&-close-text":{color:o,transition:`color ${r}`,"&:hover":{color:l}}}}})(e)],e=>({withDescriptionIconSize:e.fontSizeHeading3,defaultPadding:`${e.paddingContentVerticalSM}px 12px`,withDescriptionPadding:`${e.paddingMD}px ${e.paddingContentHorizontalLG}px`}));var y=function(e,t){var i={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(i[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var n=0,r=Object.getOwnPropertySymbols(e);nt.indexOf(r[n])&&Object.prototype.propertyIsEnumerable.call(e,r[n])&&(i[r[n]]=e[r[n]]);return i};let v={success:i.default,info:o.default,error:r.default,warning:a.default},x=e=>{let{icon:i,prefixCls:r,type:n}=e,a=v[n]||null;return i?(0,u.replaceElement)(i,t.createElement("span",{className:`${r}-icon`},i),()=>({className:(0,l.default)(`${r}-icon`,i.props.className)})):t.createElement(a,{className:`${r}-icon`})},$=e=>{let{isClosable:i,prefixCls:r,closeIcon:a,handleClose:o,ariaProps:l}=e,s=!0===a||void 0===a?t.createElement(n.default,null):a;return i?t.createElement("button",Object.assign({type:"button",onClick:o,className:`${r}-close-icon`,tabIndex:0},l),s):null},S=t.forwardRef((e,i)=>{let{description:r,prefixCls:n,message:a,banner:o,className:u,rootClassName:p,style:g,onMouseEnter:h,onMouseLeave:f,onClick:v,afterClose:S,showIcon:j,closable:w,closeText:O,closeIcon:C,action:E,id:I}=e,N=y(e,["description","prefixCls","message","banner","className","rootClassName","style","onMouseEnter","onMouseLeave","onClick","afterClose","showIcon","closable","closeText","closeIcon","action","id"]),[k,z]=t.useState(!1),L=t.useRef(null);t.useImperativeHandle(i,()=>({nativeElement:L.current}));let{getPrefixCls:M,direction:R,closable:P,closeIcon:T,className:_,style:G}=(0,m.useComponentConfig)("alert"),B=M("alert",n),[A,H,U]=b(B),W=t=>{var i;z(!0),null==(i=e.onClose)||i.call(e,t)},D=t.useMemo(()=>void 0!==e.type?e.type:o?"warning":"info",[e.type,o]),F=t.useMemo(()=>"object"==typeof w&&!!w.closeIcon||!!O||("boolean"==typeof w?w:!1!==C&&null!=C||!!P),[O,C,w,P]),K=!!o&&void 0===j||j,q=(0,l.default)(B,`${B}-${D}`,{[`${B}-with-description`]:!!r,[`${B}-no-icon`]:!K,[`${B}-banner`]:!!o,[`${B}-rtl`]:"rtl"===R},_,u,p,U,H),V=(0,c.default)(N,{aria:!0,data:!0}),X=t.useMemo(()=>"object"==typeof w&&w.closeIcon?w.closeIcon:O||(void 0!==C?C:"object"==typeof P&&P.closeIcon?P.closeIcon:T),[C,w,P,O,T]),J=t.useMemo(()=>{let e=null!=w?w:P;if("object"==typeof e){let{closeIcon:t}=e;return y(e,["closeIcon"])}return{}},[w,P]);return A(t.createElement(s.default,{visible:!k,motionName:`${B}-motion`,motionAppear:!1,motionEnter:!1,onLeaveStart:e=>({maxHeight:e.offsetHeight}),onLeaveEnd:S},({className:i,style:n},o)=>t.createElement("div",Object.assign({id:I,ref:(0,d.composeRef)(L,o),"data-show":!k,className:(0,l.default)(q,i),style:Object.assign(Object.assign(Object.assign({},G),g),n),onMouseEnter:h,onMouseLeave:f,onClick:v,role:"alert"},V),K?t.createElement(x,{description:r,icon:e.icon,prefixCls:B,type:D}):null,t.createElement("div",{className:`${B}-content`},a?t.createElement("div",{className:`${B}-message`},a):null,r?t.createElement("div",{className:`${B}-description`},r):null),E?t.createElement("div",{className:`${B}-action`},E):null,t.createElement($,{isClosable:F,prefixCls:B,closeIcon:X,handleClose:W,ariaProps:J}))))});var j=e.i(278409),w=e.i(233848),O=e.i(487806),C=e.i(479671),E=e.i(480002),I=e.i(868917);let N=function(e){function i(){var e,t,r;return(0,j.default)(this,i),t=i,r=arguments,t=(0,O.default)(t),(e=(0,E.default)(this,(0,C.default)()?Reflect.construct(t,r||[],(0,O.default)(this).constructor):t.apply(this,r))).state={error:void 0,info:{componentStack:""}},e}return(0,I.default)(i,e),(0,w.default)(i,[{key:"componentDidCatch",value:function(e,t){this.setState({error:e,info:t})}},{key:"render",value:function(){let{message:e,description:i,id:r,children:n}=this.props,{error:a,info:o}=this.state,l=(null==o?void 0:o.componentStack)||null,s=void 0===e?(a||"").toString():e;return a?t.createElement(S,{id:r,type:"error",message:s,description:t.createElement("pre",{style:{fontSize:"0.9em",overflowX:"auto"}},void 0===i?l:i)}):n}}])}(t.Component);S.ErrorBoundary=N,e.s(["Alert",0,S],560445)},936578,571303,e=>{"use strict";var t=e.i(843476),i=e.i(115504),r=e.i(271645);function n({className:e="",...n}){var a,o;let l=(0,r.useId)();return a=()=>{let e=document.getAnimations().filter(e=>e instanceof CSSAnimation&&"spin"===e.animationName),t=e.find(e=>e.effect.target?.getAttribute("data-spinner-id")===l),i=e.find(e=>e.effect instanceof KeyframeEffect&&e.effect.target?.getAttribute("data-spinner-id")!==l);t&&i&&(t.currentTime=i.currentTime)},o=[l],(0,r.useLayoutEffect)(a,o),(0,t.jsxs)("svg",{"data-spinner-id":l,className:(0,i.cx)("pointer-events-none size-12 animate-spin text-current",e),fill:"none",viewBox:"0 0 24 24",...n,children:[(0,t.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),(0,t.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})}function a(){return(0,t.jsxs)("div",{className:(0,i.cx)("h-screen","flex items-center justify-center gap-4"),children:[(0,t.jsx)("div",{className:"text-lg font-medium py-2 pr-4 border-r border-r-gray-200",children:"🚅 LiteLLM"}),(0,t.jsxs)("div",{className:"flex items-center justify-center gap-2",children:[(0,t.jsx)(n,{className:"size-4"}),(0,t.jsx)("span",{className:"text-gray-600 text-sm",children:"Loading..."})]})]})}e.s(["UiLoadingSpinner",()=>n],571303),e.s(["default",()=>a],936578)},594542,e=>{"use strict";var t=e.i(843476),i=e.i(954616),r=e.i(602869),n=e.i(612256),a=e.i(936578),o=e.i(268004),l=e.i(161281),s=e.i(321836),c=e.i(827252),d=e.i(295320),u=e.i(560445),m=e.i(464571),p=e.i(175712),g=e.i(808613),h=e.i(311451),f=e.i(282786),b=e.i(199133),y=e.i(770914),v=e.i(898586),x=e.i(618566),$=e.i(271645),S=e.i(283713);function j(){let[e,j]=(0,$.useState)(""),[w,O]=(0,$.useState)(""),[C,E]=(0,$.useState)(!0),{data:I,isLoading:N}=(0,n.useUIConfig)(),k=(0,i.useMutation)({mutationFn:async({username:e,password:t,useV3:i})=>await (0,r.loginCall)(e,t,i)}),z=(0,x.useRouter)(),{workers:L,selectWorker:M}=(0,S.useWorker)(),[R,P]=(0,$.useState)(null);(0,$.useEffect)(()=>{let e=new URLSearchParams(window.location.search).get("worker");e&&P(e)},[]),(0,$.useEffect)(()=>{if(N)return;if(I&&I.admin_ui_disabled)return void E(!1);let e=new URLSearchParams(window.location.search),t=e.get("code"),i=t&&/^[a-zA-Z0-9._~+/=-]+$/.test(t)?t:null;if(i){let t=localStorage.getItem("litellm_worker_url"),n=t&&/^https?:\/\/.+/.test(t)?t:null;(0,r.exchangeLoginCode)(i,n).then(()=>{e.delete("code");let t=e.toString();window.history.replaceState(null,"",window.location.pathname+(t?`?${t}`:"")),z.replace("/ui/?login=success")});return}if(e.has("worker")&&I?.is_control_plane){(0,o.clearTokenCookies)(),E(!1);return}let n=(0,o.getCookieFromDocument)("token");if(n&&!(0,l.isJwtExpired)(n)){let e=(0,s.consumeReturnUrl)();e?z.replace(e):z.replace("/ui");return}if(I&&I.auto_redirect_to_sso){let e=(0,s.getReturnUrl)(),t=`${(0,r.getProxyBaseUrl)()}/sso/key/generate`;e&&(0,s.isValidReturnUrl)(e)&&(t+=`?redirect_to=${encodeURIComponent(e)}`),z.push(t);return}E(!1)},[N,z,I]);let T=k.error instanceof Error?k.error.message:null,_=k.isPending,{Title:G,Text:B,Paragraph:A}=v.Typography;return N||C?(0,t.jsx)(a.default,{}):I&&I.admin_ui_disabled?(0,t.jsx)("div",{className:"min-h-screen flex items-center justify-center bg-gray-50",children:(0,t.jsx)(p.Card,{className:"w-full max-w-lg shadow-md",children:(0,t.jsxs)(y.Space,{direction:"vertical",size:"middle",className:"w-full",children:[(0,t.jsx)("div",{className:"text-center",children:(0,t.jsx)(G,{level:2,children:"🚅 LiteLLM"})}),(0,t.jsx)(u.Alert,{message:"Admin UI Disabled",description:(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(A,{className:"text-sm",children:"The Admin UI has been disabled by the administrator. To re-enable it, please update the following environment variable:"}),(0,t.jsx)(A,{className:"text-sm",children:(0,t.jsx)("code",{className:"bg-gray-100 px-1 py-0.5 rounded text-xs",children:"DISABLE_ADMIN_UI=False"})})]}),type:"warning",showIcon:!0})]})})}):(0,t.jsx)("div",{className:"min-h-screen flex items-center justify-center bg-gray-50",children:(0,t.jsxs)(p.Card,{className:"w-full max-w-lg shadow-md",children:[(0,t.jsxs)(y.Space,{direction:"vertical",size:"middle",className:"w-full",children:[(0,t.jsx)("div",{className:"text-center",children:(0,t.jsx)(G,{level:2,children:"🚅 LiteLLM"})}),(0,t.jsxs)("div",{className:"text-center",children:[(0,t.jsx)(G,{level:3,children:"Login"}),(0,t.jsx)(B,{type:"secondary",children:"Access your LiteLLM Admin UI."})]}),(0,t.jsx)(u.Alert,{message:"Default Credentials",description:(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(A,{className:"text-sm",children:["By default, Username is ",(0,t.jsx)("code",{className:"bg-gray-100 px-1 py-0.5 rounded text-xs",children:"admin"})," and Password is your set LiteLLM Proxy",(0,t.jsx)("code",{className:"bg-gray-100 px-1 py-0.5 rounded text-xs",children:"MASTER_KEY"}),"."]}),(0,t.jsxs)(A,{className:"text-sm",children:["Need to set UI credentials or SSO?"," ",(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/ui",target:"_blank",rel:"noopener noreferrer",children:"Check the documentation"}),"."]})]}),type:"info",icon:(0,t.jsx)(c.InfoCircleOutlined,{}),showIcon:!0}),T&&(0,t.jsx)(u.Alert,{message:T,type:"error",showIcon:!0}),(0,t.jsxs)(g.Form,{onFinish:()=>{let t=L.find(e=>e.worker_id===R);t&&(0,r.switchToWorkerUrl)(t.url),k.mutate({username:e,password:w,useV3:!!t},{onSuccess:e=>{if(t)M(t.worker_id),z.push("/ui/?login=success");else{let t=(0,s.consumeReturnUrl)();t?z.push(t):z.push(e.redirect_url)}},onError:()=>{t&&(0,r.switchToWorkerUrl)(null)}})},layout:"vertical",requiredMark:!1,children:[I?.is_control_plane&&L.length>0&&(0,t.jsx)(g.Form.Item,{label:"Worker",style:{marginBottom:16},children:(0,t.jsx)(b.Select,{value:R||void 0,onChange:e=>P(e),placeholder:"Choose a worker to connect to",size:"large",suffixIcon:(0,t.jsx)(d.CloudServerOutlined,{}),options:L.map(e=>({label:e.name,value:e.worker_id}))})}),(0,t.jsx)(g.Form.Item,{label:"Username",name:"username",rules:[{required:!0,message:"Please enter your username"}],children:(0,t.jsx)(h.Input,{placeholder:"Enter your username",autoComplete:"username",value:e,onChange:e=>j(e.target.value),disabled:_,size:"large",className:"rounded-md border-gray-300"})}),(0,t.jsx)(g.Form.Item,{label:"Password",name:"password",rules:[{required:!0,message:"Please enter your password"}],children:(0,t.jsx)(h.Input.Password,{placeholder:"Enter your password",autoComplete:"current-password",value:w,onChange:e=>O(e.target.value),disabled:_,size:"large"})}),(0,t.jsx)(g.Form.Item,{children:(0,t.jsx)(m.Button,{type:"primary",htmlType:"submit",loading:_,disabled:_,block:!0,size:"large",children:_?"Logging in...":"Login"})}),(0,t.jsx)(g.Form.Item,{children:I?.sso_configured?(0,t.jsx)(m.Button,{disabled:_||!!R&&0===L.length,onClick:()=>{let e=L.find(e=>e.worker_id===R);e&&(localStorage.setItem("litellm_selected_worker_id",R),(0,r.switchToWorkerUrl)(e.url));let t=e?.url??(0,r.getProxyBaseUrl)(),i=encodeURIComponent(window.location.origin+"/ui/login");z.push(`${t}/sso/key/generate?return_to=${i}`)},block:!0,size:"large",children:"Login with SSO"}):(0,t.jsx)(f.Popover,{content:"Please configure SSO to log in with SSO.",trigger:"hover",children:(0,t.jsx)(m.Button,{disabled:!0,block:!0,size:"large",children:"Login with SSO"})})})]})]}),I?.sso_configured&&(0,t.jsx)(u.Alert,{type:"info",showIcon:!0,closable:!0,message:(0,t.jsxs)(B,{children:["Single Sign-On (SSO) is enabled. LiteLLM no longer automatically redirects to the SSO login flow upon loading this page. To re-enable auto-redirect-to-SSO, set"," ",(0,t.jsx)(B,{code:!0,children:"AUTO_REDIRECT_UI_LOGIN_TO_SSO=true"})," in your environment configuration."]})})]})})}e.s(["default",0,function(){return(0,t.jsx)(j,{})}],594542)}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/10757c2146f43db4.js b/litellm/proxy/_experimental/out/_next/static/chunks/10757c2146f43db4.js deleted file mode 100644 index 3b6538f90e1..00000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/10757c2146f43db4.js +++ /dev/null @@ -1,100 +0,0 @@ -(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,127952,869216,368869,e=>{"use strict";var t=e.i(843476),n=e.i(560445),r=e.i(175712);e.i(247167);var l=e.i(271645),a=e.i(343794),o=e.i(908206),i=e.i(242064),s=e.i(517455),d=e.i(150073);let c={xxl:3,xl:3,lg:3,md:3,sm:2,xs:1},u=l.default.createContext({});var f=e.i(876556),m=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var l=0,r=Object.getOwnPropertySymbols(e);lt.indexOf(r[l])&&Object.prototype.propertyIsEnumerable.call(e,r[l])&&(n[r[l]]=e[r[l]]);return n},p=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var l=0,r=Object.getOwnPropertySymbols(e);lt.indexOf(r[l])&&Object.prototype.propertyIsEnumerable.call(e,r[l])&&(n[r[l]]=e[r[l]]);return n};let g=e=>{let{itemPrefixCls:t,component:n,span:r,className:o,style:i,labelStyle:s,contentStyle:d,bordered:c,label:f,content:m,colon:p,type:g,styles:h}=e,{classNames:x}=l.useContext(u),v=Object.assign(Object.assign({},s),null==h?void 0:h.label),b=Object.assign(Object.assign({},d),null==h?void 0:h.content);if(c)return l.createElement(n,{colSpan:r,style:i,className:(0,a.default)(o,{[`${t}-item-${g}`]:"label"===g||"content"===g,[null==x?void 0:x.label]:(null==x?void 0:x.label)&&"label"===g,[null==x?void 0:x.content]:(null==x?void 0:x.content)&&"content"===g})},null!=f&&l.createElement("span",{style:v},f),null!=m&&l.createElement("span",{style:b},m));return l.createElement(n,{colSpan:r,style:i,className:(0,a.default)(`${t}-item`,o)},l.createElement("div",{className:`${t}-item-container`},null!=f&&l.createElement("span",{style:v,className:(0,a.default)(`${t}-item-label`,null==x?void 0:x.label,{[`${t}-item-no-colon`]:!p})},f),null!=m&&l.createElement("span",{style:b,className:(0,a.default)(`${t}-item-content`,null==x?void 0:x.content)},m)))};function h(e,{colon:t,prefixCls:n,bordered:r},{component:a,type:o,showLabel:i,showContent:s,labelStyle:d,contentStyle:c,styles:u}){return e.map(({label:e,children:f,prefixCls:m=n,className:p,style:h,labelStyle:x,contentStyle:v,span:b=1,key:y,styles:w},j)=>"string"==typeof a?l.createElement(g,{key:`${o}-${y||j}`,className:p,style:h,styles:{label:Object.assign(Object.assign(Object.assign(Object.assign({},d),null==u?void 0:u.label),x),null==w?void 0:w.label),content:Object.assign(Object.assign(Object.assign(Object.assign({},c),null==u?void 0:u.content),v),null==w?void 0:w.content)},span:b,colon:t,component:a,itemPrefixCls:m,bordered:r,label:i?e:null,content:s?f:null,type:o}):[l.createElement(g,{key:`label-${y||j}`,className:p,style:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},d),null==u?void 0:u.label),h),x),null==w?void 0:w.label),span:1,colon:t,component:a[0],itemPrefixCls:m,bordered:r,label:e,type:"label"}),l.createElement(g,{key:`content-${y||j}`,className:p,style:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},c),null==u?void 0:u.content),h),v),null==w?void 0:w.content),span:2*b-1,component:a[1],itemPrefixCls:m,bordered:r,content:f,type:"content"})])}let x=e=>{let t=l.useContext(u),{prefixCls:n,vertical:r,row:a,index:o,bordered:i}=e;return r?l.createElement(l.Fragment,null,l.createElement("tr",{key:`label-${o}`,className:`${n}-row`},h(a,e,Object.assign({component:"th",type:"label",showLabel:!0},t))),l.createElement("tr",{key:`content-${o}`,className:`${n}-row`},h(a,e,Object.assign({component:"td",type:"content",showContent:!0},t)))):l.createElement("tr",{key:o,className:`${n}-row`},h(a,e,Object.assign({component:i?["th","td"]:"td",type:"item",showLabel:!0,showContent:!0},t)))};e.i(296059);var v=e.i(915654),b=e.i(183293),y=e.i(246422),w=e.i(838378);let j=(0,y.genStyleHooks)("Descriptions",e=>(e=>{let{componentCls:t,extraColor:n,itemPaddingBottom:r,itemPaddingEnd:l,colonMarginRight:a,colonMarginLeft:o,titleMarginBottom:i}=e;return{[t]:Object.assign(Object.assign(Object.assign({},(0,b.resetComponent)(e)),(e=>{let{componentCls:t,labelBg:n}=e;return{[`&${t}-bordered`]:{[`> ${t}-view`]:{border:`${(0,v.unit)(e.lineWidth)} ${e.lineType} ${e.colorSplit}`,"> table":{tableLayout:"auto"},[`${t}-row`]:{borderBottom:`${(0,v.unit)(e.lineWidth)} ${e.lineType} ${e.colorSplit}`,"&:first-child":{"> th:first-child, > td:first-child":{borderStartStartRadius:e.borderRadiusLG}},"&:last-child":{borderBottom:"none","> th:first-child, > td:first-child":{borderEndStartRadius:e.borderRadiusLG}},[`> ${t}-item-label, > ${t}-item-content`]:{padding:`${(0,v.unit)(e.padding)} ${(0,v.unit)(e.paddingLG)}`,borderInlineEnd:`${(0,v.unit)(e.lineWidth)} ${e.lineType} ${e.colorSplit}`,"&:last-child":{borderInlineEnd:"none"}},[`> ${t}-item-label`]:{color:e.colorTextSecondary,backgroundColor:n,"&::after":{display:"none"}}}},[`&${t}-middle`]:{[`${t}-row`]:{[`> ${t}-item-label, > ${t}-item-content`]:{padding:`${(0,v.unit)(e.paddingSM)} ${(0,v.unit)(e.paddingLG)}`}}},[`&${t}-small`]:{[`${t}-row`]:{[`> ${t}-item-label, > ${t}-item-content`]:{padding:`${(0,v.unit)(e.paddingXS)} ${(0,v.unit)(e.padding)}`}}}}}})(e)),{"&-rtl":{direction:"rtl"},[`${t}-header`]:{display:"flex",alignItems:"center",marginBottom:i},[`${t}-title`]:Object.assign(Object.assign({},b.textEllipsis),{flex:"auto",color:e.titleColor,fontWeight:e.fontWeightStrong,fontSize:e.fontSizeLG,lineHeight:e.lineHeightLG}),[`${t}-extra`]:{marginInlineStart:"auto",color:n,fontSize:e.fontSize},[`${t}-view`]:{width:"100%",borderRadius:e.borderRadiusLG,table:{width:"100%",tableLayout:"fixed",borderCollapse:"collapse"}},[`${t}-row`]:{"> th, > td":{paddingBottom:r,paddingInlineEnd:l},"> th:last-child, > td:last-child":{paddingInlineEnd:0},"&:last-child":{borderBottom:"none","> th, > td":{paddingBottom:0}}},[`${t}-item-label`]:{color:e.labelColor,fontWeight:"normal",fontSize:e.fontSize,lineHeight:e.lineHeight,textAlign:"start","&::after":{content:'":"',position:"relative",top:-.5,marginInline:`${(0,v.unit)(o)} ${(0,v.unit)(a)}`},[`&${t}-item-no-colon::after`]:{content:'""'}},[`${t}-item-no-label`]:{"&::after":{margin:0,content:'""'}},[`${t}-item-content`]:{display:"table-cell",flex:1,color:e.contentColor,fontSize:e.fontSize,lineHeight:e.lineHeight,wordBreak:"break-word",overflowWrap:"break-word"},[`${t}-item`]:{paddingBottom:0,verticalAlign:"top","&-container":{display:"flex",[`${t}-item-label`]:{display:"inline-flex",alignItems:"baseline"},[`${t}-item-content`]:{display:"inline-flex",alignItems:"baseline",minWidth:"1em"}}},"&-middle":{[`${t}-row`]:{"> th, > td":{paddingBottom:e.paddingSM}}},"&-small":{[`${t}-row`]:{"> th, > td":{paddingBottom:e.paddingXS}}}})}})((0,w.mergeToken)(e,{})),e=>({labelBg:e.colorFillAlter,labelColor:e.colorTextTertiary,titleColor:e.colorText,titleMarginBottom:e.fontSizeSM*e.lineHeightSM,itemPaddingBottom:e.padding,itemPaddingEnd:e.padding,colonMarginRight:e.marginXS,colonMarginLeft:e.marginXXS/2,contentColor:e.colorText,extraColor:e.colorText}));var k=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var l=0,r=Object.getOwnPropertySymbols(e);lt.indexOf(r[l])&&Object.prototype.propertyIsEnumerable.call(e,r[l])&&(n[r[l]]=e[r[l]]);return n};let C=e=>{let t,{prefixCls:n,title:r,extra:g,column:h,colon:v=!0,bordered:b,layout:y,children:w,className:C,rootClassName:S,style:N,size:E,labelStyle:_,contentStyle:O,styles:$,items:T,classNames:I}=e,P=k(e,["prefixCls","title","extra","column","colon","bordered","layout","children","className","rootClassName","style","size","labelStyle","contentStyle","styles","items","classNames"]),{getPrefixCls:M,direction:R,className:L,style:D,classNames:A,styles:K}=(0,i.useComponentConfig)("descriptions"),B=M("descriptions",n),F=(0,d.default)(),z=l.useMemo(()=>{var e;return"number"==typeof h?h:null!=(e=(0,o.matchScreen)(F,Object.assign(Object.assign({},c),h)))?e:3},[F,h]),H=(t=l.useMemo(()=>T||(0,f.default)(w).map(e=>Object.assign(Object.assign({},null==e?void 0:e.props),{key:e.key})),[T,w]),l.useMemo(()=>t.map(e=>{var{span:t}=e,n=m(e,["span"]);return"filled"===t?Object.assign(Object.assign({},n),{filled:!0}):Object.assign(Object.assign({},n),{span:"number"==typeof t?t:(0,o.matchScreen)(F,t)})}),[t,F])),V=(0,s.default)(E),W=((e,t)=>{let[n,r]=(0,l.useMemo)(()=>{let n,r,l,a;return n=[],r=[],l=!1,a=0,t.filter(e=>e).forEach(t=>{let{filled:o}=t,i=p(t,["filled"]);if(o){r.push(i),n.push(r),r=[],a=0;return}let s=e-a;(a+=t.span||1)>=e?(a>e?(l=!0,r.push(Object.assign(Object.assign({},i),{span:s}))):r.push(i),n.push(r),r=[],a=0):r.push(i)}),r.length>0&&n.push(r),[n=n.map(t=>{let n=t.reduce((e,t)=>e+(t.span||1),0);if(n({labelStyle:_,contentStyle:O,styles:{content:Object.assign(Object.assign({},K.content),null==$?void 0:$.content),label:Object.assign(Object.assign({},K.label),null==$?void 0:$.label)},classNames:{label:(0,a.default)(A.label,null==I?void 0:I.label),content:(0,a.default)(A.content,null==I?void 0:I.content)}}),[_,O,$,I,A,K]);return U(l.createElement(u.Provider,{value:X},l.createElement("div",Object.assign({className:(0,a.default)(B,L,A.root,null==I?void 0:I.root,{[`${B}-${V}`]:V&&"default"!==V,[`${B}-bordered`]:!!b,[`${B}-rtl`]:"rtl"===R},C,S,q,G),style:Object.assign(Object.assign(Object.assign(Object.assign({},D),K.root),null==$?void 0:$.root),N)},P),(r||g)&&l.createElement("div",{className:(0,a.default)(`${B}-header`,A.header,null==I?void 0:I.header),style:Object.assign(Object.assign({},K.header),null==$?void 0:$.header)},r&&l.createElement("div",{className:(0,a.default)(`${B}-title`,A.title,null==I?void 0:I.title),style:Object.assign(Object.assign({},K.title),null==$?void 0:$.title)},r),g&&l.createElement("div",{className:(0,a.default)(`${B}-extra`,A.extra,null==I?void 0:I.extra),style:Object.assign(Object.assign({},K.extra),null==$?void 0:$.extra)},g)),l.createElement("div",{className:`${B}-view`},l.createElement("table",null,l.createElement("tbody",null,W.map((e,t)=>l.createElement(x,{key:t,index:t,colon:v,prefixCls:B,vertical:"vertical"===y,bordered:b,row:e}))))))))};C.Item=({children:e})=>e,e.s(["Descriptions",0,C],869216);var S=e.i(311451),N=e.i(212931),E=e.i(898586),_=e.i(868297),O=e.i(732961),$=e.i(289882),T=e.i(170517),I=e.i(628882),P=e.i(320890),M=e.i(104458),R=e.i(722319),L=e.i(8398),D=e.i(279728);e.i(765846);var A=e.i(602716),K=e.i(328052);e.i(262370);var B=e.i(135551);let F=(e,t)=>new B.FastColor(e).setA(t).toRgbString(),z=(e,t)=>new B.FastColor(e).lighten(t).toHexString(),H=e=>{let t=(0,A.generate)(e,{theme:"dark"});return{1:t[0],2:t[1],3:t[2],4:t[3],5:t[6],6:t[5],7:t[4],8:t[6],9:t[5],10:t[4]}},V=(e,t)=>{let n=e||"#000",r=t||"#fff";return{colorBgBase:n,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:z(n,12),colorBgContainer:z(n,8),colorBgLayout:z(n,0),colorBgSpotlight:z(n,26),colorBgBlur:F(r,.04),colorBorder:z(n,26),colorBorderSecondary:z(n,19)}},W={defaultSeed:P.defaultConfig.token,useToken:function(){let[e,t,n]=(0,M.useToken)();return{theme:e,token:t,hashId:n}},defaultAlgorithm:R.default,darkAlgorithm:(e,t)=>{let n=Object.keys(T.defaultPresetColors).map(t=>{let n=(0,A.generate)(e[t],{theme:"dark"});return Array.from({length:10},()=>1).reduce((e,r,l)=>(e[`${t}-${l+1}`]=n[l],e[`${t}${l+1}`]=n[l],e),{})}).reduce((e,t)=>e=Object.assign(Object.assign({},e),t),{}),r=null!=t?t:(0,R.default)(e),l=(0,K.default)(e,{generateColorPalettes:H,generateNeutralColorPalettes:V});return Object.assign(Object.assign(Object.assign(Object.assign({},r),n),l),{colorPrimaryBg:l.colorPrimaryBorder,colorPrimaryBgHover:l.colorPrimaryBorderHover})},compactAlgorithm:(e,t)=>{let n=null!=t?t:(0,R.default)(e),r=n.fontSizeSM,l=n.controlHeight-4;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},n),function(e){let{sizeUnit:t,sizeStep:n}=e,r=n-2;return{sizeXXL:t*(r+10),sizeXL:t*(r+6),sizeLG:t*(r+2),sizeMD:t*(r+2),sizeMS:t*(r+1),size:t*r,sizeSM:t*r,sizeXS:t*(r-1),sizeXXS:t*(r-1)}}(null!=t?t:e)),(0,D.default)(r)),{controlHeight:l}),(0,L.default)(Object.assign(Object.assign({},n),{controlHeight:l})))},getDesignToken:e=>{let t=(null==e?void 0:e.algorithm)?(0,_.createTheme)(e.algorithm):$.default,n=Object.assign(Object.assign({},T.default),null==e?void 0:e.token);return(0,O.getComputedToken)(n,{override:null==e?void 0:e.token},t,I.default)},defaultConfig:P.defaultConfig,_internalContext:P.DesignTokenContext};e.s(["theme",0,W],368869);var U=e.i(270377);function q({isOpen:e,title:a,alertMessage:o,message:i,resourceInformationTitle:s,resourceInformation:d,onCancel:c,onOk:u,confirmLoading:f,requiredConfirmation:m}){let{Title:p,Text:g}=E.Typography,{token:h}=W.useToken(),[x,v]=(0,l.useState)("");return(0,l.useEffect)(()=>{e&&v("")},[e]),(0,t.jsx)(N.Modal,{title:a,open:e,onOk:u,onCancel:c,confirmLoading:f,okText:f?"Deleting...":"Delete",cancelText:"Cancel",okButtonProps:{danger:!0,disabled:!!m&&x!==m||f},cancelButtonProps:{disabled:f},children:(0,t.jsxs)("div",{className:"space-y-4",children:[o&&(0,t.jsx)(n.Alert,{message:o,type:"warning"}),(0,t.jsx)(r.Card,{title:s,className:"mt-4",styles:{body:{padding:"16px"},header:{backgroundColor:h.colorErrorBg,borderColor:h.colorErrorBorder}},style:{backgroundColor:h.colorErrorBg,borderColor:h.colorErrorBorder},children:(0,t.jsx)(C,{column:1,size:"small",children:d&&d.map(({label:e,value:n,...r})=>(0,t.jsx)(C.Item,{label:(0,t.jsx)("span",{className:"font-semibold",children:e}),children:(0,t.jsx)(g,{...r,children:n??"-"})},e))})}),(0,t.jsx)("div",{children:(0,t.jsx)(g,{children:i})}),m&&(0,t.jsxs)("div",{className:"mb-6 mt-4 pt-4 border-t border-gray-200 dark:border-gray-700",children:[(0,t.jsxs)(g,{className:"block text-base font-medium text-gray-700 dark:text-gray-300 mb-2",children:[(0,t.jsx)(g,{children:"Type "}),(0,t.jsx)(g,{strong:!0,type:"danger",children:m}),(0,t.jsx)(g,{children:" to confirm deletion:"})]}),(0,t.jsx)(S.Input,{value:x,onChange:e=>v(e.target.value),placeholder:m,className:"rounded-md",prefix:(0,t.jsx)(U.ExclamationCircleOutlined,{style:{color:h.colorError}}),autoFocus:!0})]})]})})}e.s(["default",()=>q],127952)},950724,(e,t,n)=>{t.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},100236,(e,t,n)=>{t.exports=e.g&&e.g.Object===Object&&e.g},139088,(e,t,n)=>{var r=e.r(100236),l="object"==typeof self&&self&&self.Object===Object&&self;t.exports=r||l||Function("return this")()},631926,(e,t,n)=>{var r=e.r(139088);t.exports=function(){return r.Date.now()}},748891,(e,t,n)=>{var r=/\s/;t.exports=function(e){for(var t=e.length;t--&&r.test(e.charAt(t)););return t}},830364,(e,t,n)=>{var r=e.r(748891),l=/^\s+/;t.exports=function(e){return e?e.slice(0,r(e)+1).replace(l,""):e}},630353,(e,t,n)=>{t.exports=e.r(139088).Symbol},243436,(e,t,n)=>{var r=e.r(630353),l=Object.prototype,a=l.hasOwnProperty,o=l.toString,i=r?r.toStringTag:void 0;t.exports=function(e){var t=a.call(e,i),n=e[i];try{e[i]=void 0;var r=!0}catch(e){}var l=o.call(e);return r&&(t?e[i]=n:delete e[i]),l}},223243,(e,t,n)=>{var r=Object.prototype.toString;t.exports=function(e){return r.call(e)}},377684,(e,t,n)=>{var r=e.r(630353),l=e.r(243436),a=e.r(223243),o=r?r.toStringTag:void 0;t.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":o&&o in Object(e)?l(e):a(e)}},877289,(e,t,n)=>{t.exports=function(e){return null!=e&&"object"==typeof e}},361884,(e,t,n)=>{var r=e.r(377684),l=e.r(877289);t.exports=function(e){return"symbol"==typeof e||l(e)&&"[object Symbol]"==r(e)}},773759,(e,t,n)=>{var r=e.r(830364),l=e.r(950724),a=e.r(361884),o=0/0,i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,d=/^0o[0-7]+$/i,c=parseInt;t.exports=function(e){if("number"==typeof e)return e;if(a(e))return o;if(l(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=l(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var n=s.test(e);return n||d.test(e)?c(e.slice(2),n?2:8):i.test(e)?o:+e}},374009,(e,t,n)=>{var r=e.r(950724),l=e.r(631926),a=e.r(773759),o=Math.max,i=Math.min;t.exports=function(e,t,n){var s,d,c,u,f,m,p=0,g=!1,h=!1,x=!0;if("function"!=typeof e)throw TypeError("Expected a function");function v(t){var n=s,r=d;return s=d=void 0,p=t,u=e.apply(r,n)}function b(e){var n=e-m,r=e-p;return void 0===m||n>=t||n<0||h&&r>=c}function y(){var e,n,r,a=l();if(b(a))return w(a);f=setTimeout(y,(e=a-m,n=a-p,r=t-e,h?i(r,c-n):r))}function w(e){return(f=void 0,x&&s)?v(e):(s=d=void 0,u)}function j(){var e,n=l(),r=b(n);if(s=arguments,d=this,m=n,r){if(void 0===f)return p=e=m,f=setTimeout(y,t),g?v(e):u;if(h)return clearTimeout(f),f=setTimeout(y,t),v(m)}return void 0===f&&(f=setTimeout(y,t)),u}return t=a(t)||0,r(n)&&(g=!!n.leading,c=(h="maxWait"in n)?o(a(n.maxWait)||0,t):c,x="trailing"in n?!!n.trailing:x),j.cancel=function(){void 0!==f&&clearTimeout(f),p=0,s=m=d=f=void 0},j.flush=function(){return void 0===f?u:w(l())},j}},436289,503269,214520,814379,992704,684653,877891,401141,952744,605083,101852,249578,571616,e=>{"use strict";var t=e.i(271645);function n(e,t){return null!==e&&null!==t&&"object"==typeof e&&"object"==typeof t&&"id"in e&&"id"in t?e.id===t.id:e===t}function r(e=n){return(0,t.useCallback)((t,n)=>"string"==typeof e?(null==t?void 0:t[e])===(null==n?void 0:n[e]):e(t,n),[e])}e.s(["useByComparator",()=>r],436289);var l=e.i(914189);function a(e,n,r){let[a,o]=(0,t.useState)(r),i=void 0!==e,s=(0,t.useRef)(i),d=(0,t.useRef)(!1),c=(0,t.useRef)(!1);return!i||s.current||d.current?i||!s.current||c.current||(c.current=!0,s.current=i,console.error("A component is changing from controlled to uncontrolled. This may be caused by the value changing from a defined value to undefined, which should not happen.")):(d.current=!0,s.current=i,console.error("A component is changing from uncontrolled to controlled. This may be caused by the value changing from undefined to a defined value, which should not happen.")),[i?e:a,(0,l.useEvent)(e=>(i||o(e),null==n?void 0:n(e)))]}function o(e){let[n]=(0,t.useState)(e);return n}e.s(["useControllable",()=>a],503269),e.s(["useDefaultValue",()=>o],214520);var i=e.i(835696);function s(e,n){let r=(0,t.useRef)({left:0,top:0});if((0,i.useIsoMorphicEffect)(()=>{if(!n)return;let e=n.getBoundingClientRect();e&&(r.current=e)},[e,n]),null==n||!e||n===document.activeElement)return!1;let l=n.getBoundingClientRect();return l.top!==r.current.top||l.left!==r.current.left}function d(e,n=!1){let[r,l]=(0,t.useReducer)(()=>({}),{}),a=(0,t.useMemo)(()=>(function(e){if(null===e)return{width:0,height:0};let{width:t,height:n}=e.getBoundingClientRect();return{width:t,height:n}})(e),[e,r]);return(0,i.useIsoMorphicEffect)(()=>{if(!e)return;let t=new ResizeObserver(l);return t.observe(e),()=>{t.disconnect()}},[e]),n?{width:`${a.width}px`,height:`${a.height}px`}:a}e.s(["useDidElementMove",()=>s],814379),e.s(["useElementSize",()=>d],992704);var c=e.i(544508),u=e.i(402155);class f extends Map{constructor(e){super(),this.factory=e}get(e){let t=super.get(e);return void 0===t&&(t=this.factory(e),this.set(e,t)),t}}function m(e,t){let n=e(),r=new Set;return{getSnapshot:()=>n,subscribe:e=>(r.add(e),()=>r.delete(e)),dispatch(e,...l){let a=t[e].call(n,...l);a&&(n=a,r.forEach(e=>e()))}}}function p(e){return(0,t.useSyncExternalStore)(e.subscribe,e.getSnapshot,e.getSnapshot)}let g=new f(()=>m(()=>[],{ADD(e){return this.includes(e)?this:[...this,e]},REMOVE(e){let t=this.indexOf(e);if(-1===t)return this;let n=this.slice();return n.splice(t,1),n}}));function h(e,n){let r=g.get(n),l=(0,t.useId)(),a=p(r);if((0,i.useIsoMorphicEffect)(()=>{if(e)return r.dispatch("ADD",l),()=>r.dispatch("REMOVE",l)},[r,e]),!e)return!1;let o=a.indexOf(l),s=a.length;return -1===o&&(o=s,s+=1),o===s-1}let x=new Map,v=new Map;function b(e){var t;let n=null!=(t=v.get(e))?t:0;return v.set(e,n+1),0!==n||(x.set(e,{"aria-hidden":e.getAttribute("aria-hidden"),inert:e.inert}),e.setAttribute("aria-hidden","true"),e.inert=!0),()=>(function(e){var t;let n=null!=(t=v.get(e))?t:1;if(1===n?v.delete(e):v.set(e,n-1),1!==n)return;let r=x.get(e);r&&(null===r["aria-hidden"]?e.removeAttribute("aria-hidden"):e.setAttribute("aria-hidden",r["aria-hidden"]),e.inert=r.inert,x.delete(e))})(e)}function y(e,{allowed:t,disallowed:n}={}){let r=h(e,"inert-others");(0,i.useIsoMorphicEffect)(()=>{var e,l;if(!r)return;let a=(0,c.disposables)();for(let t of null!=(e=null==n?void 0:n())?e:[])t&&a.add(b(t));let o=null!=(l=null==t?void 0:t())?l:[];for(let e of o){if(!e)continue;let t=(0,u.getOwnerDocument)(e);if(!t)continue;let n=e.parentElement;for(;n&&n!==t.body;){for(let e of n.children)o.some(t=>e.contains(t))||a.add(b(e));n=n.parentElement}}return a.dispose},[r,t,n])}e.s(["useInertOthers",()=>y],684653);var w=e.i(941444);function j(e,n,r){let l=(0,w.useLatestValue)(e=>{let t=e.getBoundingClientRect();0===t.x&&0===t.y&&0===t.width&&0===t.height&&r()});(0,t.useEffect)(()=>{if(!e)return;let t=null===n?null:n instanceof HTMLElement?n:n.current;if(!t)return;let r=(0,c.disposables)();if("u">typeof ResizeObserver){let e=new ResizeObserver(()=>l.current(t));e.observe(t),r.add(()=>e.disconnect())}if("u">typeof IntersectionObserver){let e=new IntersectionObserver(()=>l.current(t));e.observe(t),r.add(()=>e.disconnect())}return()=>r.dispose()},[n,l,e])}e.s(["useOnDisappear",()=>j],877891);var k=e.i(652265);function C(){return/iPhone/gi.test(window.navigator.platform)||/Mac/gi.test(window.navigator.platform)&&window.navigator.maxTouchPoints>0}function S(e,n,r,l){let a=(0,w.useLatestValue)(r);(0,t.useEffect)(()=>{if(e)return document.addEventListener(n,t,l),()=>document.removeEventListener(n,t,l);function t(e){a.current(e)}},[e,n,l])}function N(e,n,r,l){let a=(0,w.useLatestValue)(r);(0,t.useEffect)(()=>{if(e)return window.addEventListener(n,t,l),()=>window.removeEventListener(n,t,l);function t(e){a.current(e)}},[e,n,l])}function E(e,n,r){let l=h(e,"outside-click"),a=(0,w.useLatestValue)(r),o=(0,t.useCallback)(function(e,t){if(e.defaultPrevented)return;let r=t(e);if(null!==r&&r.getRootNode().contains(r)&&r.isConnected){for(let t of function e(t){return"function"==typeof t?e(t()):Array.isArray(t)||t instanceof Set?t:[t]}(n))if(null!==t&&(t.contains(r)||e.composed&&e.composedPath().includes(t)))return;return(0,k.isFocusableElement)(r,k.FocusableMode.Loose)||-1===r.tabIndex||e.preventDefault(),a.current(e,r)}},[a,n]),i=(0,t.useRef)(null);S(l,"pointerdown",e=>{var t,n;i.current=(null==(n=null==(t=e.composedPath)?void 0:t.call(e))?void 0:n[0])||e.target},!0),S(l,"mousedown",e=>{var t,n;i.current=(null==(n=null==(t=e.composedPath)?void 0:t.call(e))?void 0:n[0])||e.target},!0),S(l,"click",e=>{C()||/Android/gi.test(window.navigator.userAgent)||i.current&&(o(e,()=>i.current),i.current=null)},!0);let s=(0,t.useRef)({x:0,y:0});S(l,"touchstart",e=>{s.current.x=e.touches[0].clientX,s.current.y=e.touches[0].clientY},!0),S(l,"touchend",e=>{let t={x:e.changedTouches[0].clientX,y:e.changedTouches[0].clientY};if(!(Math.abs(t.x-s.current.x)>=30||Math.abs(t.y-s.current.y)>=30))return o(e,()=>e.target instanceof HTMLElement?e.target:null)},!0),N(l,"blur",e=>o(e,()=>window.document.activeElement instanceof HTMLIFrameElement?window.document.activeElement:null),!0)}function _(...e){return(0,t.useMemo)(()=>(0,u.getOwnerDocument)(...e),[...e])}e.s(["useWindowEvent",()=>N],401141),e.s(["useOutsideClick",()=>E],952744),e.s(["useOwnerDocument",()=>_],605083);let O=m(()=>new Map,{PUSH(e,t){var n;let r=null!=(n=this.get(e))?n:{doc:e,count:0,d:(0,c.disposables)(),meta:new Set};return r.count++,r.meta.add(t),this.set(e,r),this},POP(e,t){let n=this.get(e);return n&&(n.count--,n.meta.delete(t)),this},SCROLL_PREVENT({doc:e,d:t,meta:n}){let r,l={doc:e,d:t,meta:function(e){let t={};for(let n of e)Object.assign(t,n(t));return t}(n)},a=[C()?{before({doc:e,d:t,meta:n}){function r(e){return n.containers.flatMap(e=>e()).some(t=>t.contains(e))}t.microTask(()=>{var n;if("auto"!==window.getComputedStyle(e.documentElement).scrollBehavior){let n=(0,c.disposables)();n.style(e.documentElement,"scrollBehavior","auto"),t.add(()=>t.microTask(()=>n.dispose()))}let l=null!=(n=window.scrollY)?n:window.pageYOffset,a=null;t.addEventListener(e,"click",t=>{if(t.target instanceof HTMLElement)try{let n=t.target.closest("a");if(!n)return;let{hash:l}=new URL(n.href),o=e.querySelector(l);o&&!r(o)&&(a=o)}catch{}},!0),t.addEventListener(e,"touchstart",e=>{if(e.target instanceof HTMLElement)if(r(e.target)){let n=e.target;for(;n.parentElement&&r(n.parentElement);)n=n.parentElement;t.style(n,"overscrollBehavior","contain")}else t.style(e.target,"touchAction","none")}),t.addEventListener(e,"touchmove",e=>{if(e.target instanceof HTMLElement&&"INPUT"!==e.target.tagName)if(r(e.target)){let t=e.target;for(;t.parentElement&&""!==t.dataset.headlessuiPortal&&!(t.scrollHeight>t.clientHeight||t.scrollWidth>t.clientWidth);)t=t.parentElement;""===t.dataset.headlessuiPortal&&e.preventDefault()}else e.preventDefault()},{passive:!1}),t.add(()=>{var e;l!==(null!=(e=window.scrollY)?e:window.pageYOffset)&&window.scrollTo(0,l),a&&a.isConnected&&(a.scrollIntoView({block:"nearest"}),a=null)})})}}:{},{before({doc:e}){var t;let n=e.documentElement;r=Math.max(0,(null!=(t=e.defaultView)?t:window).innerWidth-n.clientWidth)},after({doc:e,d:t}){let n=e.documentElement,l=Math.max(0,n.clientWidth-n.offsetWidth),a=Math.max(0,r-l);t.style(n,"paddingRight",`${a}px`)}},{before({doc:e,d:t}){t.style(e.documentElement,"overflow","hidden")}}];a.forEach(({before:e})=>null==e?void 0:e(l)),a.forEach(({after:e})=>null==e?void 0:e(l))},SCROLL_ALLOW({d:e}){e.dispose()},TEARDOWN({doc:e}){this.delete(e)}});function $(e,t,n=()=>[document.body]){!function(e,t,n=()=>({containers:[]})){let r=p(O),l=t?r.get(t):void 0;l&&l.count,(0,i.useIsoMorphicEffect)(()=>{if(!(!t||!e))return O.dispatch("PUSH",t,n),()=>O.dispatch("POP",t,n)},[e,t])}(h(e,"scroll-lock"),t,e=>{var t;return{containers:[...null!=(t=e.containers)?t:[],n]}})}O.subscribe(()=>{let e=O.getSnapshot(),t=new Map;for(let[n]of e)t.set(n,n.documentElement.style.overflow);for(let n of e.values()){let e="hidden"===t.get(n.doc),r=0!==n.count;(r&&!e||!r&&e)&&O.dispatch(n.count>0?"SCROLL_PREVENT":"SCROLL_ALLOW",n),0===n.count&&O.dispatch("TEARDOWN",n)}}),e.s(["useScrollLock",()=>$],101852);let T=/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;function I(e){var t,n;let r=null!=(t=e.innerText)?t:"",l=e.cloneNode(!0);if(!(l instanceof HTMLElement))return r;let a=!1;for(let e of l.querySelectorAll('[hidden],[aria-hidden],[role="img"]'))e.remove(),a=!0;let o=a?null!=(n=l.innerText)?n:"":r;return T.test(o)&&(o=o.replace(T,"")),o}function P(e){let n=(0,t.useRef)(""),r=(0,t.useRef)("");return(0,l.useEvent)(()=>{let t=e.current;if(!t)return"";let l=t.innerText;if(n.current===l)return r.current;let a=(function(e){let t=e.getAttribute("aria-label");if("string"==typeof t)return t.trim();let n=e.getAttribute("aria-labelledby");if(n){let e=n.split(" ").map(e=>{let t=document.getElementById(e);if(t){let e=t.getAttribute("aria-label");return"string"==typeof e?e.trim():I(t).trim()}return null}).filter(Boolean);if(e.length>0)return e.join(", ")}return I(e).trim()})(t).trim().toLowerCase();return n.current=l,r.current=a,a})}function M(e){return[e.screenX,e.screenY]}function R(){let e=(0,t.useRef)([-1,-1]);return{wasMoved(t){let n=M(t);return(e.current[0]!==n[0]||e.current[1]!==n[1])&&(e.current=n,!0)},update(t){e.current=M(t)}}}e.s(["useTextValue",()=>P],249578),e.s(["useTrackedPointer",()=>R],571616)},83733,e=>{"use strict";let t;var n,r,l=e.i(247167),a=e.i(271645),o=e.i(544508),i=e.i(746725),s=e.i(835696);void 0!==l.default&&"u">typeof globalThis&&"u">typeof Element&&(null==(n=null==l.default?void 0:l.default.env)?void 0:n.NODE_ENV)==="test"&&void 0===(null==(r=null==Element?void 0:Element.prototype)?void 0:r.getAnimations)&&(Element.prototype.getAnimations=function(){return console.warn(["Headless UI has polyfilled `Element.prototype.getAnimations` for your tests.","Please install a proper polyfill e.g. `jsdom-testing-mocks`, to silence these warnings.","","Example usage:","```js","import { mockAnimationsApi } from 'jsdom-testing-mocks'","mockAnimationsApi()","```"].join(` -`)),[]});var d=((t=d||{})[t.None=0]="None",t[t.Closed=1]="Closed",t[t.Enter=2]="Enter",t[t.Leave=4]="Leave",t);function c(e){let t={};for(let n in e)!0===e[n]&&(t[`data-${n}`]="");return t}function u(e,t,n,r){let[l,d]=(0,a.useState)(n),{hasFlag:c,addFlag:u,removeFlag:f}=function(e=0){let[t,n]=(0,a.useState)(e),r=(0,a.useCallback)(e=>n(e),[t]),l=(0,a.useCallback)(e=>n(t=>t|e),[t]),o=(0,a.useCallback)(e=>(t&e)===e,[t]);return{flags:t,setFlag:r,addFlag:l,hasFlag:o,removeFlag:(0,a.useCallback)(e=>n(t=>t&~e),[n]),toggleFlag:(0,a.useCallback)(e=>n(t=>t^e),[n])}}(e&&l?3:0),m=(0,a.useRef)(!1),p=(0,a.useRef)(!1),g=(0,i.useDisposables)();return(0,s.useIsoMorphicEffect)(()=>{var l;if(e){if(n&&d(!0),!t){n&&u(3);return}return null==(l=null==r?void 0:r.start)||l.call(r,n),function(e,{prepare:t,run:n,done:r,inFlight:l}){let a=(0,o.disposables)();return function(e,{inFlight:t,prepare:n}){if(null!=t&&t.current)return n();let r=e.style.transition;e.style.transition="none",n(),e.offsetHeight,e.style.transition=r}(e,{prepare:t,inFlight:l}),a.nextFrame(()=>{n(),a.requestAnimationFrame(()=>{a.add(function(e,t){var n,r;let l=(0,o.disposables)();if(!e)return l.dispose;let a=!1;l.add(()=>{a=!0});let i=null!=(r=null==(n=e.getAnimations)?void 0:n.call(e).filter(e=>e instanceof CSSTransition))?r:[];return 0===i.length?t():Promise.allSettled(i.map(e=>e.finished)).then(()=>{a||t()}),l.dispose}(e,r))})}),a.dispose}(t,{inFlight:m,prepare(){p.current?p.current=!1:p.current=m.current,m.current=!0,p.current||(n?(u(3),f(4)):(u(4),f(2)))},run(){p.current?n?(f(3),u(4)):(f(4),u(3)):n?f(1):u(1)},done(){var e;p.current&&"function"==typeof t.getAnimations&&t.getAnimations().length>0||(m.current=!1,f(7),n||d(!1),null==(e=null==r?void 0:r.end)||e.call(r,n))}})}},[e,n,t,g]),e?[l,{closed:c(1),enter:c(2),leave:c(4),transition:c(2)||c(4)}]:[n,{closed:void 0,enter:void 0,leave:void 0,transition:void 0}]}e.s(["transitionDataAttributes",()=>c,"useTransition",()=>u],83733)},601893,919751,694421,140721,904016,942803,e=>{"use strict";var t=e.i(271645);let n=(0,t.createContext)(void 0);function r(){return(0,t.useContext)(n)}e.s(["useDisabled",()=>r],601893);var l=e.i(953760),a=e.i(174080),o="u">typeof document?t.useLayoutEffect:function(){};function i(e,t){let n,r,l;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(!i(e[r],t[r]))return!1;return!0}if((n=(l=Object.keys(e)).length)!==Object.keys(t).length)return!1;for(r=n;0!=r--;)if(!({}).hasOwnProperty.call(t,l[r]))return!1;for(r=n;0!=r--;){let n=l[r];if(("_owner"!==n||!e.$$typeof)&&!i(e[n],t[n]))return!1}return!0}return e!=e&&t!=t}function s(e){return"u"{n.current=e}),n}let u=(e,t)=>({...(0,l.offset)(e),options:[e,t]});e.i(247167);var f=e.i(229315),m=e.i(343084);e.i(397126);let p={...t},g=p.useInsertionEffect||(e=>e());function h(e){let n=t.useRef(()=>{});return g(()=>{n.current=e}),t.useCallback(function(){for(var e=arguments.length,t=Array(e),r=0;rtypeof document?t.useLayoutEffect:t.useEffect;let v=!1,b=0,y=()=>"floating-ui-"+Math.random().toString(36).slice(2,6)+b++,w=p.useId||function(){let[e,n]=t.useState(()=>v?y():void 0);return x(()=>{null==e&&n(y())},[]),t.useEffect(()=>{v=!0},[]),e},j=t.createContext(null),k=t.createContext(null),C="active",S="selected";function N(e,t,n){let r=new Map,l="item"===n,a=e;if(l&&e){let{[C]:t,[S]:n,...r}=e;a=r}return{..."floating"===n&&{tabIndex:-1,"data-floating-ui-focusable":""},...a,...t.map(t=>{let r=t?t[n]:null;return"function"==typeof r?e?r(e):null:r}).concat(e).reduce((e,t)=>(t&&Object.entries(t).forEach(t=>{let[n,a]=t;if(!(l&&[C,S].includes(n)))if(0===n.indexOf("on")){if(r.has(n)||r.set(n,[]),"function"==typeof a){var o;null==(o=r.get(n))||o.push(a),e[n]=function(){for(var e,t=arguments.length,l=Array(t),a=0;ae(...l)).find(e=>void 0!==e)}}}else e[n]=a}),e),{})}}function E(e,t){return{...e,rects:{...e.rects,floating:{...e.rects.floating,height:t}}}}var _=e.i(746725),O=e.i(914189),$=e.i(835696);let T=(0,t.createContext)({styles:void 0,setReference:()=>{},setFloating:()=>{},getReferenceProps:()=>({}),getFloatingProps:()=>({}),slot:{}});T.displayName="FloatingContext";let I=(0,t.createContext)(null);function P(e){return(0,t.useMemo)(()=>e?"string"==typeof e?{to:e}:e:null,[e])}function M(){return(0,t.useContext)(T).setReference}function R(){return(0,t.useContext)(T).getReferenceProps}function L(){let{getFloatingProps:e,slot:n}=(0,t.useContext)(T);return(0,t.useCallback)((...t)=>Object.assign({},e(...t),{"data-anchor":n.anchor}),[e,n])}function D(e=null){!1===e&&(e=null),"string"==typeof e&&(e={to:e});let n=(0,t.useContext)(I),r=(0,t.useMemo)(()=>e,[JSON.stringify(e,(e,t)=>{var n;return null!=(n=null==t?void 0:t.outerHTML)?n:t})]);(0,$.useIsoMorphicEffect)(()=>{null==n||n(null!=r?r:null)},[n,r]);let l=(0,t.useContext)(T);return(0,t.useMemo)(()=>[l.setFloating,e?l.styles:{}],[l.setFloating,e,l.styles])}function A({children:e,enabled:n=!0}){var r,p,g,v,b,y,C;let S,_,P,M,R,L,D,A,B,F,z,H,V,W,U,q,[G,X]=(0,t.useState)(null),[Q,Y]=(0,t.useState)(0),J=(0,t.useRef)(null),[Z,ee]=(0,t.useState)(null);p=Z,(0,$.useIsoMorphicEffect)(()=>{if(!p)return;let e=new MutationObserver(()=>{let e=window.getComputedStyle(p).maxHeight,t=parseFloat(e);if(isNaN(t))return;let n=parseInt(e);isNaN(n)||t!==n&&(p.style.maxHeight=`${Math.ceil(t)}px`)});return e.observe(p,{attributes:!0,attributeFilter:["style"]}),()=>{e.disconnect()}},[p]);let et=n&&null!==G&&null!==Z,{to:en="bottom",gap:er=0,offset:el=0,padding:ea=0,inner:eo}=(g=G,v=Z,S=K(null!=(b=null==g?void 0:g.gap)?b:"var(--anchor-gap, 0)",v),_=K(null!=(y=null==g?void 0:g.offset)?y:"var(--anchor-offset, 0)",v),P=K(null!=(C=null==g?void 0:g.padding)?C:"var(--anchor-padding, 0)",v),{...g,gap:S,offset:_,padding:P}),[ei,es="center"]=en.split(" ");(0,$.useIsoMorphicEffect)(()=>{et&&Y(0)},[et]);let{refs:ed,floatingStyles:ec,context:eu}=function(e){void 0===e&&(e={});let{nodeId:n}=e,r=function(e){var n;let{open:r=!1,onOpenChange:l,elements:a}=e,o=w(),i=t.useRef({}),[s]=t.useState(()=>{let e;return e=new Map,{emit(t,n){var r;null==(r=e.get(t))||r.forEach(e=>e(n))},on(t,n){e.set(t,[...e.get(t)||[],n])},off(t,n){var r;e.set(t,(null==(r=e.get(t))?void 0:r.filter(e=>e!==n))||[])}}}),d=null!=((null==(n=t.useContext(j))?void 0:n.id)||null),[c,u]=t.useState(a.reference),f=h((e,t,n)=>{i.current.openEvent=e?t:void 0,s.emit("openchange",{open:e,event:t,reason:n,nested:d}),null==l||l(e,t,n)}),m=t.useMemo(()=>({setPositionReference:u}),[]),p=t.useMemo(()=>({reference:c||a.reference||null,floating:a.floating||null,domReference:a.reference}),[c,a.reference,a.floating]);return t.useMemo(()=>({dataRef:i,open:r,onOpenChange:f,elements:p,events:s,floatingId:o,refs:m}),[r,f,p,s,o,m])}({...e,elements:{reference:null,floating:null,...e.elements}}),u=e.rootContext||r,m=u.elements,[p,g]=t.useState(null),[v,b]=t.useState(null),y=(null==m?void 0:m.domReference)||p,C=t.useRef(null),S=t.useContext(k);x(()=>{y&&(C.current=y)},[y]);let N=function(e){void 0===e&&(e={});let{placement:n="bottom",strategy:r="absolute",middleware:u=[],platform:f,elements:{reference:m,floating:p}={},transform:g=!0,whileElementsMounted:h,open:x}=e,[v,b]=t.useState({x:0,y:0,strategy:r,placement:n,middlewareData:{},isPositioned:!1}),[y,w]=t.useState(u);i(y,u)||w(u);let[j,k]=t.useState(null),[C,S]=t.useState(null),N=t.useCallback(e=>{e!==$.current&&($.current=e,k(e))},[]),E=t.useCallback(e=>{e!==T.current&&(T.current=e,S(e))},[]),_=m||j,O=p||C,$=t.useRef(null),T=t.useRef(null),I=t.useRef(v),P=null!=h,M=c(h),R=c(f),L=c(x),D=t.useCallback(()=>{if(!$.current||!T.current)return;let e={placement:n,strategy:r,middleware:y};R.current&&(e.platform=R.current),(0,l.computePosition)($.current,T.current,e).then(e=>{let t={...e,isPositioned:!1!==L.current};A.current&&!i(I.current,t)&&(I.current=t,a.flushSync(()=>{b(t)}))})},[y,n,r,R,L]);o(()=>{!1===x&&I.current.isPositioned&&(I.current.isPositioned=!1,b(e=>({...e,isPositioned:!1})))},[x]);let A=t.useRef(!1);o(()=>(A.current=!0,()=>{A.current=!1}),[]),o(()=>{if(_&&($.current=_),O&&(T.current=O),_&&O){if(M.current)return M.current(_,O,D);D()}},[_,O,D,M,P]);let K=t.useMemo(()=>({reference:$,floating:T,setReference:N,setFloating:E}),[N,E]),B=t.useMemo(()=>({reference:_,floating:O}),[_,O]),F=t.useMemo(()=>{let e={position:r,left:0,top:0};if(!B.floating)return e;let t=d(B.floating,v.x),n=d(B.floating,v.y);return g?{...e,transform:"translate("+t+"px, "+n+"px)",...s(B.floating)>=1.5&&{willChange:"transform"}}:{position:r,left:t,top:n}},[r,g,B.floating,v.x,v.y]);return t.useMemo(()=>({...v,update:D,refs:K,elements:B,floatingStyles:F}),[v,D,K,B,F])}({...e,elements:{...m,...v&&{reference:v}}}),E=t.useCallback(e=>{let t=(0,f.isElement)(e)?{getBoundingClientRect:()=>e.getBoundingClientRect(),contextElement:e}:e;b(t),N.refs.setReference(t)},[N.refs]),_=t.useCallback(e=>{((0,f.isElement)(e)||null===e)&&(C.current=e,g(e)),((0,f.isElement)(N.refs.reference.current)||null===N.refs.reference.current||null!==e&&!(0,f.isElement)(e))&&N.refs.setReference(e)},[N.refs]),O=t.useMemo(()=>({...N.refs,setReference:_,setPositionReference:E,domReference:C}),[N.refs,_,E]),$=t.useMemo(()=>({...N.elements,domReference:y}),[N.elements,y]),T=t.useMemo(()=>({...N,...u,refs:O,elements:$,nodeId:n}),[N,O,$,n,u]);return x(()=>{u.dataRef.current.floatingContext=T;let e=null==S?void 0:S.nodesRef.current.find(e=>e.id===n);e&&(e.context=T)}),t.useMemo(()=>({...N,context:T,refs:O,elements:$}),[N,O,$,T])}({open:et,placement:"selection"===ei?"center"===es?"bottom":`bottom-${es}`:"center"===es?`${ei}`:`${ei}-${es}`,strategy:"absolute",transform:!1,middleware:[u({mainAxis:"selection"===ei?0:er,crossAxis:el}),(M={padding:ea},{...(0,l.shift)(M),options:[M,R]}),"selection"!==ei&&(L={padding:ea},{...(0,l.flip)(L),options:[L,D]}),"selection"===ei&&eo?{name:"inner",options:A={...eo,padding:ea,overflowRef:J,offset:Q,minItemsVisible:4,referenceOverflowThreshold:ea,onFallbackChange(e){var t,n;if(!e)return;let r=eu.elements.floating;if(!r)return;let l=parseFloat(getComputedStyle(r).scrollPaddingBottom)||0,a=Math.min(4,r.childElementCount),o=0,i=0;for(let e of null!=(n=null==(t=eu.elements.floating)?void 0:t.childNodes)?n:[])if(e instanceof HTMLElement){let t=e.offsetTop,n=t+e.clientHeight+l,s=r.scrollTop,d=s+r.clientHeight;if(t>=s&&n<=d)a--;else{i=Math.max(0,Math.min(n,d)-Math.max(t,s)),o=e.clientHeight;break}}a>=1&&Y(e=>{let t=o*a-i+l;return e>=t?e:t})}},async fn(e){let{listRef:t,overflowRef:n,onFallbackChange:r,offset:o=0,index:i=0,minItemsVisible:s=4,referenceOverflowThreshold:d=0,scrollRef:c,...f}=(0,m.evaluate)(A,e),{rects:p,elements:{floating:g}}=e,h=t.current[i],x=(null==c?void 0:c.current)||g,v=g.clientTop||x.clientTop,b=0!==g.clientTop,y=0!==x.clientTop,w=g===x;if(!h)return{};let j={...e,...await u(-h.offsetTop-g.clientTop-p.reference.height/2-h.offsetHeight/2-o).fn(e)},k=await (0,l.detectOverflow)(E(j,x.scrollHeight+v+g.clientTop),f),C=await (0,l.detectOverflow)(j,{...f,elementContext:"reference"}),S=(0,m.max)(0,k.top),N=j.y+S,_=(x.scrollHeight>x.clientHeight?e=>e:m.round)((0,m.max)(0,x.scrollHeight+(b&&w||y?2*v:0)-S-(0,m.max)(0,k.bottom)));if(x.style.maxHeight=_+"px",x.scrollTop=S,r){let e=x.offsetHeight=-d||C.bottom>=-d;a.flushSync(()=>r(e))}return n&&(n.current=await (0,l.detectOverflow)(E({...j,y:N},x.offsetHeight+v+g.clientTop),f)),{y:N}}}:null,(B={padding:ea,apply({availableWidth:e,availableHeight:t,elements:n}){Object.assign(n.floating.style,{overflow:"auto",maxWidth:`${e}px`,maxHeight:`min(var(--anchor-max-height, 100vh), ${t}px)`})}},{...(0,l.size)(B),options:[B,F]})].filter(Boolean),whileElementsMounted:l.autoUpdate}),[ef=ei,em=es]=eu.placement.split("-");"selection"===ei&&(ef="selection");let ep=(0,t.useMemo)(()=>({anchor:[ef,em].filter(Boolean).join(" ")}),[ef,em]),{getReferenceProps:eg,getFloatingProps:eh}=(z=(r=[function(e,n){let{open:r,elements:l}=e,{enabled:o=!0,overflowRef:i,scrollRef:s,onChange:d}=n,c=h(d),u=t.useRef(!1),f=t.useRef(null),m=t.useRef(null);t.useEffect(()=>{if(!o)return;function e(e){if(e.ctrlKey||!t||null==i.current)return;let n=e.deltaY,r=i.current.top>=-.5,l=i.current.bottom>=-.5,o=t.scrollHeight-t.clientHeight,s=n<0?-1:1,d=n<0?"max":"min";if(!(t.scrollHeight<=t.clientHeight))if(!r&&n>0||!l&&n<0)e.preventDefault(),a.flushSync(()=>{c(e=>e+Math[d](n,o*s))});else{let e;/firefox/i.test((e=navigator.userAgentData)&&Array.isArray(e.brands)?e.brands.map(e=>{let{brand:t,version:n}=e;return t+"/"+n}).join(" "):navigator.userAgent)&&(t.scrollTop+=n)}}let t=(null==s?void 0:s.current)||l.floating;if(r&&t)return t.addEventListener("wheel",e),requestAnimationFrame(()=>{f.current=t.scrollTop,null!=i.current&&(m.current={...i.current})}),()=>{f.current=null,m.current=null,t.removeEventListener("wheel",e)}},[o,r,l.floating,i,s,c]);let p=t.useMemo(()=>({onKeyDown(){u.current=!0},onWheel(){u.current=!1},onPointerMove(){u.current=!1},onScroll(){let e=(null==s?void 0:s.current)||l.floating;if(i.current&&e&&u.current){if(null!==f.current){let t=e.scrollTop-f.current;(i.current.bottom<-.5&&t<-1||i.current.top<-.5&&t>1)&&a.flushSync(()=>c(e=>e+t))}requestAnimationFrame(()=>{f.current=e.scrollTop})}}}),[l.floating,c,i,s]);return t.useMemo(()=>o?{floating:p}:{},[o,p])}(eu,{overflowRef:J,onChange:Y})]).map(e=>null==e?void 0:e.reference),H=r.map(e=>null==e?void 0:e.floating),V=r.map(e=>null==e?void 0:e.item),W=t.useCallback(e=>N(e,r,"reference"),z),U=t.useCallback(e=>N(e,r,"floating"),H),q=t.useCallback(e=>N(e,r,"item"),V),t.useMemo(()=>({getReferenceProps:W,getFloatingProps:U,getItemProps:q}),[W,U,q])),ex=(0,O.useEvent)(e=>{ee(e),ed.setFloating(e)});return t.createElement(I.Provider,{value:X},t.createElement(T.Provider,{value:{setFloating:ex,setReference:ed.setReference,styles:ec,getReferenceProps:eg,getFloatingProps:eh,slot:ep}},e))}function K(e,n,r){let l=(0,_.useDisposables)(),a=(0,O.useEvent)((e,t)=>{if(null==e)return[r,null];if("number"==typeof e)return[e,null];if("string"==typeof e){if(!t)return[r,null];let n=B(e,t);return[n,r=>{let a=function e(t){let n=/var\((.*)\)/.exec(t);if(n){let t=n[1].indexOf(",");if(-1===t)return[n[1]];let r=n[1].slice(0,t).trim(),l=n[1].slice(t+1).trim();return l?[r,...e(l)]:[r]}return[]}(e);{let o=a.map(e=>window.getComputedStyle(t).getPropertyValue(e));l.requestAnimationFrame(function i(){l.nextFrame(i);let s=!1;for(let[e,n]of a.entries()){let r=window.getComputedStyle(t).getPropertyValue(n);if(o[e]!==r){o[e]=r,s=!0;break}}if(!s)return;let d=B(e,t);n!==d&&(r(d),n=d)})}return l.dispose}]}return[r,null]}),o=(0,t.useMemo)(()=>a(e,n)[0],[e,n]),[i=o,s]=(0,t.useState)();return(0,$.useIsoMorphicEffect)(()=>{let[t,r]=a(e,n);if(s(t),r)return r(s)},[e,n]),i}function B(e,t){let n=document.createElement("div");t.appendChild(n),n.style.setProperty("margin-top","0px","important"),n.style.setProperty("margin-top",e,"important");let r=parseFloat(window.getComputedStyle(n).marginTop)||0;return t.removeChild(n),r}function F(e={},t=null,n=[]){for(let[r,l]of Object.entries(e))!function e(t,n,r){if(Array.isArray(r))for(let[l,a]of r.entries())e(t,z(n,l.toString()),a);else r instanceof Date?t.push([n,r.toISOString()]):"boolean"==typeof r?t.push([n,r?"1":"0"]):"string"==typeof r?t.push([n,r]):"number"==typeof r?t.push([n,`${r}`]):null==r?t.push([n,""]):F(r,n,t)}(n,z(t,r),l);return n}function z(e,t){return e?e+"["+t+"]":t}function H(e){var t,n;let r=null!=(t=null==e?void 0:e.form)?t:e.closest("form");if(r){for(let t of r.elements)if(t!==e&&("INPUT"===t.tagName&&"submit"===t.type||"BUTTON"===t.tagName&&"submit"===t.type||"INPUT"===t.nodeName&&"image"===t.type))return void t.click();null==(n=r.requestSubmit)||n.call(r)}}I.displayName="PlacementContext",e.s(["FloatingProvider",()=>A,"useFloatingPanel",()=>D,"useFloatingPanelProps",()=>L,"useFloatingReference",()=>M,"useFloatingReferenceProps",()=>R,"useResolvedAnchor",()=>P],919751),e.s(["attemptSubmit",()=>H,"objectToFormEntries",()=>F],694421);var V=e.i(700020),W=e.i(2788);let U=(0,t.createContext)(null);function q({children:e}){let n=(0,t.useContext)(U);if(!n)return t.default.createElement(t.default.Fragment,null,e);let{target:r}=n;return r?(0,a.createPortal)(t.default.createElement(t.default.Fragment,null,e),r):null}function G({data:e,form:n,disabled:r,onReset:l,overrides:a}){let[o,i]=(0,t.useState)(null),s=(0,_.useDisposables)();return(0,t.useEffect)(()=>{if(l&&o)return s.addEventListener(o,"reset",l)},[o,n,l]),t.default.createElement(q,null,t.default.createElement(X,{setForm:i,formId:n}),F(e).map(([e,l])=>t.default.createElement(W.Hidden,{features:W.HiddenFeatures.Hidden,...(0,V.compact)({key:e,as:"input",type:"hidden",hidden:!0,readOnly:!0,form:n,disabled:r,name:e,value:l,...a})})))}function X({setForm:e,formId:n}){return(0,t.useEffect)(()=>{if(n){let t=document.getElementById(n);t&&e(t)}},[e,n]),n?null:t.default.createElement(W.Hidden,{features:W.HiddenFeatures.Hidden,as:"input",type:"hidden",hidden:!0,readOnly:!0,ref:t=>{if(!t)return;let n=t.closest("form");n&&e(n)}})}function Q(e,n){let[r,l]=(0,t.useState)(n);return e||r===n||l(n),e?r:n}e.s(["FormFields",()=>G],140721),e.s(["useFrozenData",()=>Q],904016);let Y=(0,t.createContext)(void 0);function J(){return(0,t.useContext)(Y)}e.s(["useProvidedId",()=>J],942803)},233137,233538,e=>{"use strict";let t;var n=e.i(271645);let r=(0,n.createContext)(null);r.displayName="OpenClosedContext";var l=((t=l||{})[t.Open=1]="Open",t[t.Closed=2]="Closed",t[t.Closing=4]="Closing",t[t.Opening=8]="Opening",t);function a(){return(0,n.useContext)(r)}function o({value:e,children:t}){return n.default.createElement(r.Provider,{value:e},t)}function i({children:e}){return n.default.createElement(r.Provider,{value:null},e)}function s(e){let t=e.parentElement,n=null;for(;t&&!(t instanceof HTMLFieldSetElement);)t instanceof HTMLLegendElement&&(n=t),t=t.parentElement;let r=(null==t?void 0:t.getAttribute("disabled"))==="";return!(r&&function(e){if(!e)return!1;let t=e.previousElementSibling;for(;null!==t;){if(t instanceof HTMLLegendElement)return!1;t=t.previousElementSibling}return!0}(n))&&r}e.s(["OpenClosedProvider",()=>o,"ResetOpenClosedProvider",()=>i,"State",()=>l,"useOpenClosed",()=>a],233137),e.s(["isDisabledReactIssue7711",()=>s],233538)},35983,35889,722678,178677,635307,495470,333771,e=>{"use strict";let t,n,r,l,a;var o=e.i(290571),i=e.i(271645),s=e.i(429427),d=e.i(371330),c=e.i(174080),u=e.i(394487),f=e.i(436289),m=e.i(503269),p=e.i(214520),g=e.i(814379),h=e.i(746725),x=e.i(992704),v=e.i(914189),b=e.i(684653),y=e.i(835696),w=e.i(941444),j=e.i(877891),k=e.i(952744),C=e.i(605083),S=e.i(144279),N=e.i(101852),E=e.i(294316),_=e.i(249578),O=e.i(571616),$=e.i(83733),T=e.i(601893),I=e.i(919751),P=e.i(140721),M=e.i(904016),R=e.i(942803),L=e.i(233137),D=e.i(233538),A=((t=A||{})[t.First=0]="First",t[t.Previous=1]="Previous",t[t.Next=2]="Next",t[t.Last=3]="Last",t[t.Specific=4]="Specific",t[t.Nothing=5]="Nothing",t);function K(e,t){let n=t.resolveItems();if(n.length<=0)return null;let r=t.resolveActiveIndex(),l=null!=r?r:-1;switch(e.focus){case 0:for(let e=0;e=0;--e)if(!t.resolveDisabled(n[e],e,n))return e;return r;case 2:for(let e=l+1;e=0;--e)if(!t.resolveDisabled(n[e],e,n))return e;return r;case 4:for(let r=0;r0?e.join(" "):void 0,(0,i.useMemo)(()=>function(e){let n=(0,v.useEvent)(e=>(t(t=>[...t,e]),()=>t(t=>{let n=t.slice(),r=n.indexOf(e);return -1!==r&&n.splice(r,1),n}))),r=(0,i.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 i.default.createElement(U.Provider,{value:r},e.children)},[t])]}U.displayName="DescriptionContext";let X=Object.assign((0,W.forwardRefWithAs)(function(e,t){let n=(0,i.useId)(),r=(0,T.useDisabled)(),{id:l=`headlessui-description-${n}`,...a}=e,o=function e(){let t=(0,i.useContext)(U);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}(),s=(0,E.useSyncRefs)(t);(0,y.useIsoMorphicEffect)(()=>o.register(l),[l,o.register]);let d=r||!1,c=(0,i.useMemo)(()=>({...o.slot,disabled:d}),[o.slot,d]),u={ref:s,...o.props,id:l};return(0,W.useRender)()({ourProps:u,theirProps:a,slot:c,defaultTag:"p",name:o.name||"Description"})}),{});e.s(["Description",()=>X,"useDescribedBy",()=>q,"useDescriptions",()=>G],35889);var Q=e.i(998348);let Y=(0,i.createContext)(null);function J(e){var t,n,r;let l=null!=(n=null==(t=(0,i.useContext)(Y))?void 0:t.value)?n:void 0;return(null!=(r=null==e?void 0:e.length)?r:0)>0?[l,...e].filter(Boolean).join(" "):l}function Z({inherit:e=!1}={}){let t=J(),[n,r]=(0,i.useState)([]),l=e?[t,...n].filter(Boolean):n;return[l.length>0?l.join(" "):void 0,(0,i.useMemo)(()=>function(e){let t=(0,v.useEvent)(e=>(r(t=>[...t,e]),()=>r(t=>{let n=t.slice(),r=n.indexOf(e);return -1!==r&&n.splice(r,1),n}))),n=(0,i.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 i.default.createElement(Y.Provider,{value:n},e.children)},[r])]}Y.displayName="LabelContext";let ee=Object.assign((0,W.forwardRefWithAs)(function(e,t){var n;let r=(0,i.useId)(),l=function e(){let t=(0,i.useContext)(Y);if(null===t){let t=Error("You used a