diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3073a664cd5..09f56c1a34d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ -/model_prices_and_context_window.json @mateo-berri @ryan-crabbe-berri @kerry-berri @joshua-berri +/litellm/data/model_prices_and_context_window.json @mateo-berri @ryan-crabbe-berri @kerry-berri @joshua-berri /litellm/model_prices_and_context_window_backup.json @mateo-berri @ryan-crabbe-berri @kerry-berri @joshua-berri /litellm/scripts/ci_cd/cost_map_pins.json @mateo-berri @ryan-crabbe-berri @kerry-berri @joshua-berri /litellm/deploy/helm/ @yassin-berriai diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 02beeb9fac1..6c1ec42f3ef 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -276,7 +276,7 @@ When the provider reports its own usage or spend numbers, compare the proxy's nu Provider work (a new provider, a new parameter, a new usage or cost field) is the most common kind of contribution, and it is where PRs get reworked most often. Follow these rules -**Preserve zero prices.** In [`model_prices_and_context_window.json`](../model_prices_and_context_window.json), an explicit `0.0` means that the priced operation is free. A missing field or `null` means no rate is specified, so the relevant calculator may use a fallback. For example, when no batch input rate is configured, batch cache writes use `cache_creation_input_token_cost` if set, otherwise the regular input rate, then apply the batch discount. A zero ordinary input rate does not make separately priced cache reads or writes free. Test `rate is None` before substituting a fallback, since `row.get("cache_creation_input_token_cost") or fallback` would discard a valid zero. Speech keeps character pricing ahead of token pricing even when the character rate is zero. If neither rate is configured, speech cost calculation raises an error. Its model lookup preserves unset rates instead of treating compatibility defaults as explicit zero prices. Perplexity keeps a configured legacy search rate ahead of the current search rate, including zero. When registering custom prices, `None` leaves an existing rate unchanged and `0.0` overrides it +**Preserve zero prices.** In [`litellm/data/model_prices_and_context_window.json`](../litellm/data/model_prices_and_context_window.json), an explicit `0.0` means that the priced operation is free. A missing field or `null` means no rate is specified, so the relevant calculator may use a fallback. For example, when no batch input rate is configured, batch cache writes use `cache_creation_input_token_cost` if set, otherwise the regular input rate, then apply the batch discount. A zero ordinary input rate does not make separately priced cache reads or writes free. Test `rate is None` before substituting a fallback, since `row.get("cache_creation_input_token_cost") or fallback` would discard a valid zero. Speech keeps character pricing ahead of token pricing even when the character rate is zero. If neither rate is configured, speech cost calculation raises an error. Its model lookup preserves unset rates instead of treating compatibility defaults as explicit zero prices. Perplexity keeps a configured legacy search rate ahead of the current search rate, including zero. When registering custom prices, `None` leaves an existing rate unchanged and `0.0` overrides it **Find the existing machinery before you add plumbing.** LiteLLM already has generic paths that move data between the endpoints, the provider transformations, and cost tracking. A second, hand-rolled path for the same data is a common reason a provider PR gets rewritten before merge. If you cannot find a mechanism for what you need, say so in the PR or ask in [#pr-review on Slack](https://join.slack.com/t/litellmossslack/shared_invite/zt-3o7nkuyfr-p_kbNJj8taRfXGgQI1~YyA) before you build one diff --git a/.github/prompts/duplicate-issue-check.md b/.github/prompts/duplicate-issue-check.md index c2006943fa5..6fcb74eaa19 100644 --- a/.github/prompts/duplicate-issue-check.md +++ b/.github/prompts/duplicate-issue-check.md @@ -27,7 +27,7 @@ Call it a duplicate only when one fix closes both: the same root cause in the sa These are NOT duplicates: -- two requests to add different models to `model_prices_and_context_window.json` (the same model under two names IS a duplicate) +- two requests to add different models to `litellm/data/model_prices_and_context_window.json` (the same model under two names IS a duplicate) - two bugs in the same file or the same request path with different root causes, such as "this request should not be routed here at all" versus "the translation this route performs drops a field" - the same symptom on a different provider, endpoint, or model, unless the broken code is plainly shared - the same general area ("spend tracking is wrong", "streaming is broken") with different root causes diff --git a/.github/prompts/issue-classifier.md b/.github/prompts/issue-classifier.md index 6e447fbabc8..9bbcbdfb97e 100644 --- a/.github/prompts/issue-classifier.md +++ b/.github/prompts/issue-classifier.md @@ -8,7 +8,7 @@ Answer with one JSON object matching the schema you were given. Every field is r Pick the domain whose code would change to fix the issue. The symptom decides, not the file the reporter guesses at. A path belongs to exactly one domain. -- `cost-map`: a model is missing, priced wrong, or has a stale capability flag or context limit. No code change, only `model_prices_and_context_window.json`. +- `cost-map`: a model is missing, priced wrong, or has a stale capability flag or context limit. No code change, only `litellm/data/model_prices_and_context_window.json`. - `llm-translation`: a specific provider returns the wrong shape, drops a param, breaks on streaming, tools, images or reasoning, or maps an error badly. Also every bridge between API shapes: Responses to Chat, Messages to Chat, batches, files, images, audio, realtime. Prompt caching lives here, not in caching: it is a per-provider header translation. - `routing`: the wrong deployment was picked, a fallback did not fire or fired wrongly, retries or cooldowns misbehave, a model group alias resolves wrong, the auto router chose badly. Router-level tpm/rpm used to pick a deployment is routing. - `caching`: a response was served from cache when it should not have been, or not cached when it should; Redis or semantic cache misconfigured; cache keys collide across keys or users. Response cache only: `cache_hit` in the logs means this, a provider's prompt cache is llm-translation. diff --git a/.github/root-entries-allowlist.json b/.github/root-entries-allowlist.json index 0da8175435e..776259c4bae 100644 --- a/.github/root-entries-allowlist.json +++ b/.github/root-entries-allowlist.json @@ -6,9 +6,6 @@ "Makefile": "Root entry points for workspace development and testing.", "README.md": "Repository overview consumed by hosting and package builds.", "litellm": "Python SDK and consolidated project sources.", - "model_prices_and_context_window.json": "Published model metadata consumed by the SDK and external readers.", - "policy_templates.json": "Published policy templates retained at their existing root URL.", - "provider_endpoints_support.json": "Published provider endpoint metadata retained at its existing root URL.", "pyproject.toml": "Root Python package manifest and workspace configuration.", "tests": "Repository-wide test suites and test infrastructure.", "uv.lock": "Locked dependency graph for the root Python workspace." diff --git a/.github/scripts/ci/classify_changes.sh b/.github/scripts/ci/classify_changes.sh index f78c76bda77..e29f5b7a616 100755 --- a/.github/scripts/ci/classify_changes.sh +++ b/.github/scripts/ci/classify_changes.sh @@ -33,7 +33,7 @@ while IFS= read -r file || [ -n "$file" ]; do *) has_backend=true ;; esac case "$file" in - model_prices_and_context_window.json | litellm/model_prices_and_context_window_backup.json) + litellm/data/model_prices_and_context_window.json | litellm/model_prices_and_context_window_backup.json) has_cost_map=true ;; tests/unit/proxy/*) : ;; *) outside_cost_map_set=true ;; diff --git a/.github/scripts/smoke_test_native_wheel.py b/.github/scripts/smoke_test_native_wheel.py index af4054ea92e..e98666abc9c 100644 --- a/.github/scripts/smoke_test_native_wheel.py +++ b/.github/scripts/smoke_test_native_wheel.py @@ -7,7 +7,7 @@ import zipfile from pathlib import Path from typing import Final -COST_MAP: Final = Path(__file__).resolve().parents[2] / "model_prices_and_context_window.json" +COST_MAP: Final = Path(__file__).resolve().parents[2] / "litellm/data/model_prices_and_context_window.json" CHILD_SCRIPT: Final = """ from importlib.util import module_from_spec, spec_from_file_location diff --git a/.github/scripts/verify_linux_native_wheel.py b/.github/scripts/verify_linux_native_wheel.py index 610f55a36b9..2518b2a5220 100644 --- a/.github/scripts/verify_linux_native_wheel.py +++ b/.github/scripts/verify_linux_native_wheel.py @@ -140,6 +140,9 @@ def main( "litellm/scripts/", "litellm/runtime/", "litellm/schema.prisma", + "litellm/data/model_prices_and_context_window.json", + "litellm/data/policy_templates.json", + "litellm/data/provider_endpoints_support.json", ) ) or any(part.endswith(".dSYM") for part in PurePosixPath(member.filename).parts) diff --git a/.github/workflows/cost-map-guard.yml b/.github/workflows/cost-map-guard.yml index 90c8d5a3f9e..655743b5fa2 100644 --- a/.github/workflows/cost-map-guard.yml +++ b/.github/workflows/cost-map-guard.yml @@ -64,7 +64,7 @@ jobs: MERGE_BASE: ${{ steps.revisions.outputs.merge_base }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | - if git diff --quiet "$MERGE_BASE" "$HEAD_SHA" -- model_prices_and_context_window.json; then + if git diff --quiet "$MERGE_BASE" "$HEAD_SHA" -- litellm/data/model_prices_and_context_window.json; then echo "cost_map=false" >> "$GITHUB_OUTPUT" else echo "cost_map=true" >> "$GITHUB_OUTPUT" @@ -76,6 +76,6 @@ jobs: env: HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | - git show "${HEAD_SHA}:model_prices_and_context_window.json" > "$RUNNER_TEMP/model_prices_and_context_window.json" + git show "${HEAD_SHA}:litellm/data/model_prices_and_context_window.json" > "$RUNNER_TEMP/model_prices_and_context_window.json" cargo run --locked --quiet --manifest-path litellm/rust/Cargo.toml -p litellm-model-catalog --bin check-registry \ -- "$RUNNER_TEMP/model_prices_and_context_window.json" diff --git a/.github/workflows/cost-map-pins-recheck.yml b/.github/workflows/cost-map-pins-recheck.yml index 34482a842ee..50beb56a5d2 100644 --- a/.github/workflows/cost-map-pins-recheck.yml +++ b/.github/workflows/cost-map-pins-recheck.yml @@ -6,7 +6,7 @@ on: - main - "litellm_**" paths: - - model_prices_and_context_window.json + - litellm/data/model_prices_and_context_window.json - litellm/model_prices_and_context_window_backup.json - litellm/scripts/ci_cd/cost_map_pins.json @@ -28,7 +28,7 @@ jobs: BEFORE_SHA: ${{ github.event.before }} AFTER_SHA: ${{ github.event.after }} FORCED: ${{ github.event.forced }} - COST_MAP_PATHS: '["model_prices_and_context_window.json", "litellm/model_prices_and_context_window_backup.json", "litellm/scripts/ci_cd/cost_map_pins.json"]' + COST_MAP_PATHS: '["litellm/data/model_prices_and_context_window.json", "litellm/model_prices_and_context_window_backup.json", "litellm/scripts/ci_cd/cost_map_pins.json"]' PINS_PATHS: '["litellm/scripts/ci_cd/cost_map_pins.json"]' run: | if [[ "$BEFORE_SHA" =~ ^0+$ || "$FORCED" == true ]] \ diff --git a/.github/workflows/test-rust.yml b/.github/workflows/test-rust.yml index 74a6957aba4..e79c03b275a 100644 --- a/.github/workflows/test-rust.yml +++ b/.github/workflows/test-rust.yml @@ -4,7 +4,7 @@ on: push: paths: - "litellm/rust/**" - - "model_prices_and_context_window.json" + - "litellm/data/model_prices_and_context_window.json" - "litellm/rust_bridge/**" - "litellm/scripts/generate_trace_types.py" - "litellm/scripts/trace_codegen/**" @@ -39,7 +39,7 @@ on: - "litellm_**" paths: - "litellm/rust/**" - - "model_prices_and_context_window.json" + - "litellm/data/model_prices_and_context_window.json" - "litellm/rust_bridge/**" - "litellm/scripts/generate_trace_types.py" - "litellm/scripts/trace_codegen/**" diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml index 53ef8dd1e91..f67b92fb2d2 100644 --- a/.github/workflows/test-unit.yml +++ b/.github/workflows/test-unit.yml @@ -45,7 +45,7 @@ jobs: id: rust-bridge-key if: steps.changes.outputs.decision != 'skip' env: - RUST_BRIDGE_CACHE_KEY: ${{ runner.os }}-rust-bridge-editable-${{ hashFiles('litellm/rust/Cargo.lock', 'litellm/rust/Cargo.toml', 'litellm/rust/crates/**', 'model_prices_and_context_window.json', 'pyproject.toml', 'litellm/packaging/litellm-proxy/pyproject.toml') }} + RUST_BRIDGE_CACHE_KEY: ${{ runner.os }}-rust-bridge-editable-${{ hashFiles('litellm/rust/Cargo.lock', 'litellm/rust/Cargo.toml', 'litellm/rust/crates/**', 'litellm/data/model_prices_and_context_window.json', 'pyproject.toml', 'litellm/packaging/litellm-proxy/pyproject.toml') }} run: echo "key=$RUST_BRIDGE_CACHE_KEY" >> "$GITHUB_OUTPUT" - name: Set up Python @@ -1032,7 +1032,7 @@ jobs: env: RUST_BRIDGE_ARTIFACT: ${{ needs.rust-bridge.outputs.artifact }} run: | - diff -u model_prices_and_context_window.json litellm/model_prices_and_context_window_backup.json + diff -u litellm/data/model_prices_and_context_window.json litellm/model_prices_and_context_window_backup.json if [ -z "$RUST_BRIDGE_ARTIFACT" ]; then .github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra switchyard --extra saml --extra extra_proxy --extra proxy-runtime --extra utils else diff --git a/litellm/__init__.py b/litellm/__init__.py index 8a73f3447b8..b1a88b3b47d 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -408,7 +408,7 @@ aclient_session: Optional[Union[httpx.AsyncClient, DefaultAsyncHttpxClient]] = N model_fallbacks: Optional[List] = None # Deprecated for 'litellm.fallbacks' model_cost_map_url: str = os.getenv( "LITELLM_MODEL_COST_MAP_URL", - "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json", + "https://raw.githubusercontent.com/BerriAI/litellm/main/litellm/data/model_prices_and_context_window.json", ) blog_posts_url: str = os.getenv( "LITELLM_BLOG_POSTS_URL", diff --git a/model_prices_and_context_window.json b/litellm/data/model_prices_and_context_window.json similarity index 100% rename from model_prices_and_context_window.json rename to litellm/data/model_prices_and_context_window.json diff --git a/policy_templates.json b/litellm/data/policy_templates.json similarity index 100% rename from policy_templates.json rename to litellm/data/policy_templates.json diff --git a/provider_endpoints_support.json b/litellm/data/provider_endpoints_support.json similarity index 100% rename from provider_endpoints_support.json rename to litellm/data/provider_endpoints_support.json diff --git a/litellm/litellm_core_utils/get_model_cost_map.py b/litellm/litellm_core_utils/get_model_cost_map.py index 80393a72631..52297939aaf 100644 --- a/litellm/litellm_core_utils/get_model_cost_map.py +++ b/litellm/litellm_core_utils/get_model_cost_map.py @@ -1,5 +1,5 @@ """ -Pulls the cost + context window + provider route for known models from https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json +Pulls the cost + context window + provider route for known models from https://github.com/BerriAI/litellm/blob/main/litellm/data/model_prices_and_context_window.json This can be disabled by setting the LITELLM_LOCAL_MODEL_COST_MAP environment variable to True. The ``lite`` and ``litellm-proxy`` CLI entry points also use the bundled map without fetching. diff --git a/litellm/llms/vertex_ai/common_utils.py b/litellm/llms/vertex_ai/common_utils.py index d0de71e0305..71a6c616e37 100644 --- a/litellm/llms/vertex_ai/common_utils.py +++ b/litellm/llms/vertex_ai/common_utils.py @@ -351,7 +351,7 @@ def get_supports_system_message( supports_system_message = True except Exception as e: verbose_logger.warning( - "Unable to identify if system message supported. Defaulting to 'False'. Received error message - %s\nAdd it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json", + "Unable to identify if system message supported. Defaulting to 'False'. Received error message - %s\nAdd it here - https://github.com/BerriAI/litellm/blob/main/litellm/data/model_prices_and_context_window.json", e, ) supports_system_message = False diff --git a/litellm/packaging/litellm-core/pyproject.toml b/litellm/packaging/litellm-core/pyproject.toml index 2b45c2357e1..fd14573b834 100644 --- a/litellm/packaging/litellm-core/pyproject.toml +++ b/litellm/packaging/litellm-core/pyproject.toml @@ -56,7 +56,7 @@ editable-profile = "dev" include = [ { path = "litellm/rust/rust-toolchain.toml", format = "sdist" }, { path = "litellm/rust/.cargo/config.toml", format = "sdist" }, - { path = "model_prices_and_context_window.json", format = "sdist" }, + { path = "litellm/data/model_prices_and_context_window.json", format = "sdist" }, "litellm/router_strategy/complexity_router/artifacts/*.json", "litellm/router_strategy/complexity_router/fuse_presets.json", "litellm/proxy/model_insights_tasks.json", @@ -66,6 +66,9 @@ include = [ "litellm/proxy/common_utils/codex_bedrock_runtime_models_0.166.0.json", ] exclude = [ + { path = "litellm/data/model_prices_and_context_window.json", format = "wheel" }, + "litellm/data/policy_templates.json", + "litellm/data/provider_endpoints_support.json", "litellm/scripts", "litellm/scripts/**", "litellm/runtime", diff --git a/litellm/packaging/litellm-proxy/pyproject.toml b/litellm/packaging/litellm-proxy/pyproject.toml index 4b9de6f848e..35a9bbf8794 100644 --- a/litellm/packaging/litellm-proxy/pyproject.toml +++ b/litellm/packaging/litellm-proxy/pyproject.toml @@ -18,5 +18,5 @@ editable-profile = "dev" include = [ { path = "litellm/rust/rust-toolchain.toml", format = "sdist" }, { path = "litellm/rust/.cargo/config.toml", format = "sdist" }, - { path = "model_prices_and_context_window.json", format = "sdist" }, + { path = "litellm/data/model_prices_and_context_window.json", format = "sdist" }, ] diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/3yrgf44a9g52e.js b/litellm/proxy/_experimental/out/_next/static/chunks/3yrgf44a9g52e.js index 3d4d5454b73..feb4f6f9d1b 100644 --- a/litellm/proxy/_experimental/out/_next/static/chunks/3yrgf44a9g52e.js +++ b/litellm/proxy/_experimental/out/_next/static/chunks/3yrgf44a9g52e.js @@ -1,4 +1,4 @@ -(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,664307,e=>{"use strict";var t=e.i(843476),s=e.i(271645),a=e.i(16715),l=e.i(438847),r=e.i(912598),i=e.i(135214),n=e.i(785242),o=e.i(292639),d=e.i(802954),c=e.i(708347),u=e.i(707728),m=e.i(218842),h=e.i(972520),p=e.i(283086),f=e.i(37727),x=e.i(735450),_=e.i(782066),g=e.i(519455);let j="hideDecisionModelsBanner",v=()=>{let[e,a]=(0,s.useState)(()=>"true"===localStorage.getItem(j));return e?null:(0,t.jsxs)("div",{className:"mb-4 flex items-center gap-4 rounded-lg border bg-muted/40 px-4 py-3",children:[(0,t.jsx)("div",{className:"flex size-10 shrink-0 items-center justify-center rounded-full border bg-background",children:(0,t.jsx)(p.f,{className:"size-4 text-muted-foreground"})}),(0,t.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,t.jsx)("h4",{className:"m-0 text-sm font-semibold text-foreground",children:"Decision models are now supported"}),(0,t.jsxs)("p",{className:"m-0 mt-0.5 text-xs text-muted-foreground",children:["Call them at ",(0,t.jsx)("code",{children:"/v1/decisions"})," or ",(0,t.jsx)("code",{children:"/v1/systemone"}),", or try them in the Decisions playground."," ",(0,t.jsx)("a",{href:x.O,target:"_blank",rel:"noopener noreferrer",className:"underline",children:"How to call them"})]})]}),(0,t.jsx)(g.K,{variant:"outline",className:"shrink-0",nativeButton:!1,role:"link",render:(0,t.jsx)("a",{href:x.Z,target:"_blank",rel:"noopener noreferrer"}),children:"Supported providers"}),(0,t.jsxs)(g.K,{className:"shrink-0",nativeButton:!1,role:"link",render:(0,t.jsx)("a",{href:(0,_.B)(x.B)}),children:["Try decision models",(0,t.jsx)(h.f,{})]}),(0,t.jsx)(g.K,{type:"button",variant:"ghost",size:"icon-sm",onClick:()=>{a(!0),localStorage.setItem(j,"true")},className:"shrink-0","aria-label":"Dismiss banner",children:(0,t.jsx)(f.X,{})})]})};var b=e.i(368670),y=e.i(625901);let N=/^output_cost_per_second_(.+)$/,k=e=>null==e?null:(1e6*Number(e)).toFixed(2),w=(e,t)=>e?.data?{data:e.data.map(e=>{var s,a;let l,r,i;return s=e,a=t,r=(l=JSON.parse(JSON.stringify(s))).litellm_params,i=l.model_info,{...l,provider:((e,t,s)=>{if(!e)return"-";if(t)return t;let a=e.split("/");return 1===a.length?s(e):a[0]})(r.model,r.custom_llm_provider,a),input_cost:k(i?.input_cost_per_token),output_cost:k(i?.output_cost_per_token),output_cost_per_second:r.output_cost_per_second??i?.output_cost_per_second??null,output_cost_per_second_tiers:Object.entries(i??{}).flatMap(([e,t])=>{let s=N.exec(e)?.[1];return void 0!==s&&"number"==typeof t?[{resolution:s,cost:t}]:[]}),litellm_model_name:r.model,max_tokens:i?.max_tokens,max_input_tokens:i?.max_input_tokens,api_base:r.api_base,cleanedLitellmParams:Object.fromEntries(Object.entries(r).filter(([e])=>"model"!==e&&"api_base"!==e))}})}:{data:[]},C=s.forwardRef(function(e,t){return s.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),s.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"}))});var S=e.i(278587),M=e.i(68155),E=e.i(515288),T=e.i(677572),A=e.i(746798),P=e.i(822315),I=e.i(895751);P.default.extend(I.default);let z=e=>e&&"function"==typeof e.format?"function"==typeof e.isUTC&&e.isUTC()?e.toISOString():P.default.utc(e.format("YYYY-MM-DDTHH:mm:ss")).toISOString():null,O=e=>{if(!e)return null;let t=P.default.utc(e);return t.isValid()?t:null},L="ptu_count",R="cost_per_ptu_per_hour",q="ptu_effective_from",F="ptu_effective_to",K=e=>null!=e&&""!==e,D=e=>{if(!K(e))return!0;let t=Number(e);return Number.isInteger(t)&&t>0&&t<=1e6},V=[{validator:(e,t)=>D(t)?Promise.resolve():Promise.reject(Error(`PTU Count must be a whole number between 1 and ${1e6.toLocaleString()}`))}],U=e=>{if(!K(e))return!0;let t=Number(e);return Number.isFinite(t)&&t>=0&&t<=1e6},B=[{validator:(e,t)=>U(t)?Promise.resolve():Promise.reject(Error(`Cost per PTU / Hour must be between 0 and ${1e6.toLocaleString()}`))}],$=e=>({getFieldValue:t})=>({validator:(s,a)=>K(a)===K(t(e))?Promise.resolve():Promise.reject(Error("PTU Count and Cost per PTU / Hour must be set together"))}),G=e=>{let t=Number(e?.valueOf?.());return Number.isFinite(t)?t:new Date(String(e)).getTime()},H=(e,t)=>{if(!K(e)||!K(t))return!0;let s=G(e),a=G(t);return Number.isNaN(s)||Number.isNaN(a)||a>s},W=(e,t)=>({getFieldValue:s})=>({validator:(a,l)=>{let r=s(e);return H("start"===t?l:r,"start"===t?r:l)?Promise.resolve():Promise.reject(Error("PTU Effective To must be after PTU Effective From"))}}),J=[L,R,"ptu_effective_from","ptu_effective_to"],Y=e=>null!=e&&""!==e?Number(e):null,X=()=>{let{data:e}=(0,o.f)(),t=e?.values?.enable_ptu_cost_attribution===!0;return(0,o.f)(t?{staleTime:3e4,refetchInterval:3e4}:void 0),t};var Q=e.i(871689),Z=e.i(678784),ee=e.i(118366),et=e.i(952571),es=e.i(500330);let ea=e=>"string"==typeof e&&/\*{2,}/.test(e),el=e=>Object.fromEntries(Object.entries(e).filter(([,e])=>!ea(e))),er=new Set(["api_base","custom_llm_provider","organization","tpm","rpm","max_retries","timeout","stream_timeout","model","input_cost_per_token","output_cost_per_token","cache_read_input_token_cost","cache_creation_input_token_cost","cache_creation_input_token_cost_above_1hr","litellm_credential_name","cache_control_injection_points","vector_store_ids","guardrails","tags"]),ei=e=>Object.fromEntries(Object.entries(e).filter(([e,t])=>!er.has(e)&&!ea(t))),en=e=>{try{let t=JSON.parse(e?.trim()||"{}");return null===t||"object"!=typeof t||Array.isArray(t)?null:t}catch{return null}};var eo=e.i(122550),ed=e.i(101048),ec=e.i(832724),eu=e.i(164668),em=e.i(602869),eh=e.i(776639);let ep=({accessToken:e,targets:a,jevRequest:l,onTestComplete:r})=>{let[i,n]=s.default.useState(()=>a.map(()=>({status:"pending"}))),[o,d]=s.default.useState({status:"pending"});return(s.default.useEffect(()=>{let t=!1,s=async()=>{if(!l)return;let s=await (0,em.b)(e,l);if(t)return;if("error"===s.status)return void d(s);let a=s.result.routing_decision;d("jev_classifier"===a.cause?{status:"success"}:{status:"error",error:`OSS classifier was not reached successfully (routing cause: ${a.cause??"unknown"})`})};return(async()=>{await Promise.all([s(),...a.map(async(s,a)=>{let l=s.requestParams?await (0,em.EA)(e,s.modelGroup,s.mode,s.requestParams):await (0,em.EA)(e,s.modelGroup,s.mode);if(t)return;let r="error"===l.status?{status:"error",error:l.error.split("stack trace:")[0].trim().replace(/^litellm\.(.*?)Error: /,"")}:l;n(e=>e.map((e,t)=>t===a?r:e))})]),!t&&r&&r()})(),()=>{t=!0}},[]),0!==a.length||l)?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)("p",{className:"mb-2 text-sm text-muted-foreground",children:"Test Connection sends a minimal request to every configured tier, classifier, default, and embedding model. The classifier probe includes its reasoning effort override."}),l&&(0,t.jsxs)("div",{role:"status","aria-label":"OSS classifier connection",className:"rounded-lg border p-3 text-sm",children:[(0,t.jsx)("strong",{children:"OSS Classifier"}),(0,t.jsxs)("p",{children:["pending"===o.status&&"Testing OSS classification","success"===o.status&&"OSS classification succeeded","error"===o.status&&o.error]})]}),a.map((e,s)=>{let a=i[s]??{status:"pending"};return(0,t.jsxs)("div",{"data-testid":"auto-router-test-row",className:"flex items-start gap-3 rounded-lg border p-3",children:[(0,t.jsxs)("div",{className:"pt-0.5",children:["pending"===a.status&&(0,t.jsx)(eu.f,{className:"size-5 animate-spin text-muted-foreground","data-testid":"test-status-pending"}),"success"===a.status&&(0,t.jsx)(ed.f,{className:"size-5 text-primary","data-testid":"test-status-success"}),"error"===a.status&&(0,t.jsx)(ec.f,{className:"size-5 text-destructive","data-testid":"test-status-error"})]}),(0,t.jsxs)("div",{className:"min-w-0 flex-1 text-sm",children:[(0,t.jsx)("span",{className:"font-medium",children:e.labels.join(", ")})," ",(0,t.jsxs)("span",{className:"text-muted-foreground",children:["->"," ",e.modelGroup,"embedding"===e.mode?" (embedding)":""]}),"error"===a.status&&(0,t.jsx)("p",{className:"mt-1 text-xs text-destructive","data-testid":"test-error-message",children:a.error})]})]},`${e.labels.join("-")}-${e.modelGroup}-${e.mode}`)})]}):(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"No complexity tiers are configured yet, so there is nothing to test."})};function ef({open:e,onClose:s,testId:a,...l}){return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&s(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[700px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Connection Test Results"})}),e&&(0,t.jsx)(ep,{...l},a),(0,t.jsx)(eh.c,{children:(0,t.jsx)(g.K,{variant:"outline",onClick:s,children:"Close"})})]})})}var ex=e.i(411382),e_=e.i(282492),eg=e.i(240192),ej=e.i(54105),ev=e.i(138620),eb=e.i(996389);let ey="What is 2 plus 2?",eN=({prompt:e,config:t,defaultModel:s,routerName:a,teamId:l})=>({prompt:e,complexity_router_config:t,...s?{default_model:s}:{},...a?.trim()?{router_name:a.trim()}:{},...l?{team_id:l}:{}});var ek=e.i(869255);let ew=({tiers:e,semanticMatchingEnabled:t,embeddingModel:s,defaultModel:a,classifier:l})=>{let r=e.reduce((e,[t,s])=>s.reduce((e,s)=>{let a=s?.trim();return a?{...e,[a]:[...e[a]??[],t]}:e},e),{}),i=a?.trim(),n=Object.entries(!i||i in r?r:{...r,[i]:["Default"]}).map(([e,t])=>({labels:t,modelGroup:e,mode:"chat"})),o=t&&s?.trim()?[{labels:["Embedding"],modelGroup:s.trim(),mode:"embedding"}]:[],d=l?.model.trim();return[...n,...o,...d?[{labels:["Classifier"],modelGroup:d,mode:"chat",...l?.reasoningEffort&&{requestParams:{reasoning_effort:l.reasoningEffort}}}]:[]]},eC=(e,t)=>e.model?.startsWith(t)===!0,eS=[{kind:"complexity",label:"Complexity",configKey:"complexity_router_config",defaultModelKey:"complexity_router_default_model",hasEditor:!0,matches:e=>eC(e,"auto_router/complexity_router")||null!=e.complexity_router_config},{kind:"adaptive",label:"Adaptive",configKey:"adaptive_router_config",defaultModelKey:"adaptive_router_default_model",hasEditor:!1,matches:e=>eC(e,"auto_router/adaptive_router")},{kind:"quality",label:"Quality",configKey:"quality_router_config",defaultModelKey:"quality_router_default_model",hasEditor:!1,matches:e=>eC(e,"auto_router/quality_router")},{kind:"semantic",label:"Semantic",configKey:"auto_router_config",defaultModelKey:"auto_router_default_model",hasEditor:!0,matches:()=>!0}],eM=e=>eS.find(t=>t.matches(e??{})),eE=e=>"complexity"===eM(e).kind,eT=e=>e?.model?.startsWith("auto_router/")===!0||e?.complexity_router_config!=null||e?.auto_router_config!=null;var eA=e.i(127952),eP=e.i(266027),eI=e.i(552546),ez=e.i(110204);function eO({value:e,onChange:a,modelInfo:l,deployments:r}){let i=s.default.useId(),{data:n}=(0,b.X)(!0,!0),o=s.default.useMemo(()=>(0,x.F)(n),[n]),d=l.filter(e=>(0,x._)(e.mode)||(r??[]).some(t=>t.model_name===e.model_group&&(0,x.r)(o,t.litellm_params?.custom_llm_provider??t.litellm_params?.model?.split("/")[0],[t.litellm_params?.model??"",t.litellm_params?.base_model??""])));return(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{htmlFor:i,children:"Decision model"}),(0,t.jsx)(eI.f,{inputId:i,"aria-label":"Decision model",options:d.map(e=>({value:e.model_group,label:e.model_group})),value:e.jev_classifier_config?.deployment_name??"",placeholder:"Select the decision model",allowClear:!1,onValueChange:t=>{t&&a({...e,jev_classifier_config:{...e.jev_classifier_config??(0,eb.c)(),deployment_name:t}})}})]})}var eL=e.i(372339),eR=e.i(100372),eq=e.i(131688),eF=e.i(961540),eK=e.i(772325);let eD={auto_router_name:ej.z.string().min(1,"Auto router name is required"),model_access_group:eK.z.array(ej.z.string())},eV={...eD,auto_router_default_model:ej.z.string().nullable().transform(e=>e??""),auto_router_embedding_model:ej.z.string().nullable().transform(e=>e??"")},eU={...eD,auto_router_default_model:ej.z.string().nullable().pipe(ej.z.string({error:"Default model is required"}).min(1,"Default model is required")),auto_router_embedding_model:ej.z.string().nullable().pipe(ej.z.string({error:"Embedding model is required"}).min(1,"Embedding model is required"))},eB=ex.z.object(eV),e$=ex.z.object(eU),eG={auto_router_name:"",auto_router_default_model:null,auto_router_embedding_model:null,model_access_group:[]};var eH=e.i(417385),eW=e.i(547756),eJ=e.i(542450),eY=e.i(182668),eX=e.i(793479),eQ=e.i(571303),eZ=e.i(991326),e0=e.i(131792);let e1=({id:e,value:a,onChange:l,options:r,ariaInvalid:i,ariaDescribedBy:n})=>{let o=(0,e0.d)(),[d,c]=(0,s.useState)(""),u=a??[],m=d.trim(),h=m&&!r.includes(m)?[...r,m]:r,p=e=>{l(Array.from(new Set(e))),c("")};return(0,t.jsxs)(e0.x,{multiple:!0,autoHighlight:!0,items:h,value:u,onValueChange:p,inputValue:d,onInputValueChange:e=>{e.includes(",")?p([...u,...e.split(",").map(e=>e.trim()).filter(Boolean)]):c(e)},children:[(0,t.jsx)(e0.V,{render:(0,t.jsx)("div",{ref:o}),children:(0,t.jsx)(e0.l,{children:s=>(0,t.jsxs)(t.Fragment,{children:[s.map(e=>(0,t.jsx)(e0.Q,{"aria-label":e,children:e},e)),(0,t.jsx)(e0.z,{id:e,"aria-invalid":i,"aria-describedby":n,placeholder:"Select existing groups or type to create new ones"})]})})}),(0,t.jsxs)(e0.R,{anchor:o,children:[(0,t.jsx)(e0.S,{children:"No access groups found"}),(0,t.jsx)(e0.k,{children:e=>(0,t.jsx)(e0.T,{value:e,children:e},e)})]})]})},e2=({id:e,value:s,onChange:a,choices:l,placeholder:r,ariaInvalid:i,ariaDescribedBy:n})=>{let o=s?l.find(e=>e.value===s)??{value:s,label:s}:null;return(0,t.jsxs)(e0.x,{items:l,value:o,onValueChange:e=>a(e?.value??null),itemToStringLabel:e=>e.label,isItemEqualToValue:(e,t)=>e.value===t.value,children:[(0,t.jsx)(e0.c,{id:e,"aria-invalid":i,"aria-describedby":n,placeholder:r,className:"w-full",showClear:null!=s&&""!==s}),(0,t.jsxs)(e0.R,{children:[(0,t.jsx)(e0.S,{children:"No models found"}),(0,t.jsx)(e0.k,{children:e=>(0,t.jsx)(e0.T,{value:e,children:e.label},e.value)})]})]})};var e4=e.i(695411),e5=e.i(664659),e6=e.i(359360),e3=e.i(107233),e7=e.i(727612),e8=e.i(487486),e9=e.i(204258),te=e.i(772436),tt=e.i(624687);let ts=({value:e,onChange:a})=>{let[l,r]=(0,s.useState)(""),i=t=>{let s=Array.from(new Set([...e,...t.split("\n").map(e=>e.trim()).filter(e=>""!==e)]));s.length>e.length&&a(s),r("")};return(0,t.jsxs)("div",{className:"flex min-h-9 w-full flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2.5 py-1.5 shadow-xs transition-[color,box-shadow] focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 dark:bg-input/30",children:[e.map(s=>(0,t.jsxs)(e8.f,{variant:"secondary",className:"max-w-full gap-1 pr-1",children:[(0,t.jsx)("span",{className:"truncate",children:s}),(0,t.jsx)("button",{type:"button","aria-label":`Remove ${s}`,className:"rounded-full p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",onClick:()=>a(e.filter(e=>e!==s)),children:(0,t.jsx)(f.X,{className:"size-3"})})]},s)),(0,t.jsx)("input",{"aria-label":"Example Utterances",value:l,onChange:e=>r(e.target.value),onBlur:()=>l.trim()&&i(l),onKeyDown:t=>{"Enter"===t.key&&l.trim()?(t.preventDefault(),i(l)):"Backspace"===t.key&&""===l&&e.length>0&&a(e.slice(0,-1))},onPaste:e=>{let t=e.clipboardData.getData("text");t.includes("\n")&&(e.preventDefault(),i(t))},placeholder:0===e.length?"Type an utterance and press Enter...":void 0,className:"min-w-48 flex-1 bg-transparent py-0.5 text-sm outline-none placeholder:text-muted-foreground"})]})},ta=({content:e})=>(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("button",{type:"button","aria-label":e,className:"inline-flex rounded-sm text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"}),children:(0,t.jsx)(e6.f,{className:"size-4"})}),(0,t.jsx)(A.Y,{children:e})]}),tl=({modelInfo:e,value:a,onChange:l})=>{let[r,i]=(0,s.useState)([]),[n,o]=(0,s.useState)(!1),[d,c]=(0,s.useState)([]);(0,s.useEffect)(()=>{let e=a?.routes;if(e){let t=[];i(s=>e.map((e,a)=>{let l=s[a],r=l?.id||e.id||`route-${a}-${Date.now()}`;return t.push(r),{id:r,model:e.name||e.model||null,utterances:e.utterances||[],description:e.description||"",score_threshold:e.score_threshold??.5}})),c(t)}else i([]),c([])},[a]);let u=e=>{l?.({routes:e.map(e=>({name:e.model,utterances:e.utterances,description:e.description,score_threshold:e.score_threshold}))})},m=(e,t,s)=>{let a=r.map(a=>a.id===e?{...a,[t]:s}:a);i(a),u(a)},h=e.map(e=>({value:e.model_group,label:e.model_group})),p={routes:r.map(e=>({name:e.model,utterances:e.utterances,description:e.description,score_threshold:e.score_threshold}))};return(0,t.jsx)(A.g,{children:(0,t.jsxs)("div",{className:"w-full space-y-6",children:[(0,t.jsxs)("div",{className:"flex w-full flex-wrap items-center justify-between gap-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold",children:"Routes Configuration"}),(0,t.jsx)(ta,{content:"Configure routing logic to automatically select the best model based on user input patterns"})]}),(0,t.jsxs)(g.K,{type:"button",onClick:()=>{let e=`route-${Date.now()}`,t=[...r,{id:e,model:null,utterances:[],description:"",score_threshold:.5}];i(t),u(t),c(t=>[...t,e])},children:[(0,t.jsx)(e3.f,{"data-icon":"inline-start"}),"Add Route"]})]}),0===r.length?(0,t.jsx)(E.N,{children:(0,t.jsx)(E.O,{className:"py-8 text-center text-muted-foreground",children:'No routes configured. Click "Add Route" to get started.'})}):(0,t.jsx)("div",{className:"space-y-3",children:r.map((e,s)=>{let a=d.includes(e.id);return(0,t.jsxs)(e9.Y,{open:a,onOpenChange:t=>c(s=>t?[...s,e.id]:s.filter(t=>t!==e.id)),className:"overflow-hidden rounded-xl border bg-card shadow-xs",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 px-4 py-3",children:[(0,t.jsxs)(e9.v,{render:(0,t.jsx)("button",{type:"button",className:"flex min-w-0 flex-1 items-center gap-2 text-left"}),children:[(0,t.jsx)(e5.f,{className:`size-4 shrink-0 text-muted-foreground transition-transform ${a?"rotate-180":""}`}),(0,t.jsxs)("span",{className:"truncate text-base font-medium",children:["Route ",s+1,": ",e.model||"Unnamed"]})]}),(0,t.jsx)(g.K,{type:"button","aria-label":"delete",variant:"ghost",size:"icon-sm",onClick:()=>{var t;let s;return t=e.id,void(i(s=r.filter(e=>e.id!==t)),u(s),c(e=>e.filter(e=>e!==t)))},children:(0,t.jsx)(e7.f,{className:"text-destructive"})})]}),(0,t.jsxs)(e9.C,{children:[(0,t.jsx)(te.f,{}),(0,t.jsxs)("div",{className:"space-y-4 p-4",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{children:"Model"}),(0,t.jsx)(eI.f,{value:e.model,onValueChange:t=>m(e.id,"model",t),placeholder:"Select model",options:h})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{htmlFor:`${e.id}-description`,children:"Description"}),(0,t.jsx)(tt.f,{id:`${e.id}-description`,value:e.description,onChange:t=>m(e.id,"description",t.target.value),placeholder:"Describe when this route should be used...",rows:2})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(ez.f,{htmlFor:`${e.id}-threshold`,children:"Score Threshold"}),(0,t.jsx)(ta,{content:"Minimum similarity score to route to this model (0-1)"})]}),(0,t.jsx)(eX.f,{id:`${e.id}-threshold`,type:"number",value:e.score_threshold,onChange:t=>m(e.id,"score_threshold",Number(t.target.value)||0),min:0,max:1,step:.1,placeholder:"0.5"})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(ez.f,{children:"Example Utterances"}),(0,t.jsx)(ta,{content:"Training examples for this route. Type an utterance and press Enter to add it."})]}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground",children:"Type an utterance and press Enter to add it. You can also paste multiple lines."}),(0,t.jsx)(ts,{value:e.utterances,onChange:t=>m(e.id,"utterances",t)})]})]})]})]},e.id)})}),(0,t.jsx)(te.f,{}),(0,t.jsxs)("div",{className:"flex w-full items-center justify-between gap-3",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold",children:"JSON Preview"}),(0,t.jsx)(g.K,{type:"button",variant:"link",onClick:()=>o(e=>!e),children:n?"Hide":"Show"})]}),n&&(0,t.jsx)(E.N,{className:"bg-muted/40",children:(0,t.jsx)(E.O,{children:(0,t.jsx)("pre",{className:"max-h-64 w-full overflow-auto text-sm",children:JSON.stringify(p,null,2)})})})]})})};var tr=e.i(257e3),ti=e.i(848573),tn=e.i(304720),to=e.i(670264),td=e.i(430597),tc=e.i(568142),tu=e.i(731417);let tm=e=>({tiers:e.tiers,enableNonReasoningTier:e.enable_non_reasoning_tier,customTierSet:e.custom_tier_set,defaultModel:e.default_model,planModeMinTier:e.plan_mode_min_tier,classificationPrompt:e.classification_prompt,classificationExamples:e.classification_examples,heuristicFirstMaxTier:e.heuristic_first_max_tier,hybridBoundaryMargin:e.hybrid_boundary_margin,classificationMode:e.classification_mode,tierLabels:e.tier_labels,classifierType:e.classifier_type,localHeuristic:e.local_heuristic,jevClassifierConfig:e.jev_classifier_config,heuristicV2SuccessThreshold:e.heuristic_v2_success_threshold,capabilityClassifierConfig:e.capability_classifier_config,llmV2Config:e.llm_v2_config,classifierLlmConfig:e.classifier_llm_config,classifierContextWindowSize:e.classifier_context_window_size,classifierContextBudgetChars:e.classifier_context_budget_chars,classifierContextPerTurnChars:e.classifier_context_per_turn_chars,classifierContextIncludeAssistantTurns:e.classifier_context_include_assistant_turns,classifierFallback:e.classifier_fallback,sessionAffinity:e.session_affinity??tu.K,sessionAffinityTtlSeconds:e.session_affinity_ttl_seconds,modalityRouting:e.modality_routing??!1,modalityPinOverride:e.modality_pin_override??!1,deploymentAffinity:e.deployment_affinity??tu.$,adaptive:e.adaptive??!1,adaptiveWeights:e.adaptive_weights??tu.l,tierDistancePenalty:e.tier_distance_penalty??tu.B,adaptiveEligible:e.adaptive_eligible??"all",returnRawModelName:e.return_raw_model_name??!1,tierBoundaries:e.tier_boundaries,tokenThresholds:e.token_thresholds,dimensionWeights:e.dimension_weights,customDimensions:e.custom_dimensions,reasoningOverrideMinScore:e.reasoning_override_min_score,tierModelParams:e.tier_model_params,enableContextWindowEscalation:e.enable_context_window_escalation,contextWindowEscalationBuffer:e.context_window_escalation_buffer,cacheAwareRouting:e.cache_aware_routing,cacheAwareRoutingOutputTokens:e.cache_aware_routing_output_tokens,cacheAwareRoutingTimeoutMs:e.cache_aware_routing_timeout_ms,stallEscalationEnabled:e.stall_escalation_enabled,stallEscalationWindow:e.stall_escalation_window,stallEscalationRepeatThreshold:e.stall_escalation_repeat_threshold,codeKeywords:e.code_keywords,reasoningKeywords:e.reasoning_keywords,technicalKeywords:e.technical_keywords,simpleKeywords:e.simple_keywords,planModePatterns:e.plan_mode_patterns,routeHousekeepingToCheapestTier:e.route_housekeeping_to_cheapest_tier,housekeepingPatterns:e.housekeeping_patterns,reminderMarkers:e.reminder_markers,maxTokensFromTierModel:e.max_tokens_from_tier_model,classifierPluginTimeoutMs:e.classifier_plugin_timeout_ms});var th=e.i(233820);let tp=e=>"object"==typeof e&&null!==e&&"open"in e&&"close"in e&&"string"==typeof e.open&&"string"==typeof e.close,tf=e=>Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0,tx=(e,t)=>{let s=(0,eb.E)(e),a=(0,ti.Q)(e.tiers,e.enable_non_reasoning_tier),{tiers:l,enable_non_reasoning_tier:r}=a,i=(0,ti.y)(e),n={...a,custom_tier_set:i};return{tiers:l,enable_non_reasoning_tier:r,custom_tier_set:i,tier_model_params:(0,tr.K)((0,ek.q)(e.tiers,e.tier_model_configs),(0,tr.X)(n)),default_model:((e,t,s)=>{if("string"==typeof e&&e.trim())return e;let a=(0,tr.H)(s),l=t?.trim();return l&&l!==a?l:void 0})(e.default_model,t,n),plan_mode_min_tier:(0,ti.i)(e.plan_mode_min_tier,i),tier_labels:(0,ti.W)(e.tier_labels),...s,local_heuristic:"heuristic"===e.local_heuristic||"heuristic_v2"===e.local_heuristic?e.local_heuristic:void 0,heuristic_v2_success_threshold:"number"==typeof e.heuristic_v2_success_threshold?e.heuristic_v2_success_threshold:void 0,capability_classifier_config:eF.h.safeParse(e.capability_classifier_config).data,llm_v2_config:eF.S.safeParse(e.llm_v2_config).data,classifier_llm_config:"jev"===s.classifier_type?void 0:e.classifier_llm_config,classifier_context_window_size:"number"==typeof e.classifier_context_window_size?e.classifier_context_window_size:void 0,classifier_context_budget_chars:"number"==typeof e.classifier_context_budget_chars?e.classifier_context_budget_chars:void 0,classifier_context_per_turn_chars:"number"==typeof e.classifier_context_per_turn_chars?e.classifier_context_per_turn_chars:void 0,classifier_context_include_assistant_turns:"boolean"==typeof e.classifier_context_include_assistant_turns?e.classifier_context_include_assistant_turns:void 0,classifier_fallback:"default_model"===e.classifier_fallback||"heuristic"===e.classifier_fallback?e.classifier_fallback:void 0,classification_prompt:"string"==typeof e.classification_prompt&&""!==e.classification_prompt.trim()?e.classification_prompt:void 0,classification_examples:"string"==typeof e.classification_examples&&""!==e.classification_examples.trim()?e.classification_examples:void 0,heuristic_first_max_tier:"string"==typeof e.heuristic_first_max_tier&&""!==e.heuristic_first_max_tier.trim()?e.heuristic_first_max_tier:void 0,hybrid_boundary_margin:"number"==typeof e.hybrid_boundary_margin?e.hybrid_boundary_margin:void 0,classification_mode:"user_turn"===e.classification_mode||"every_request"===e.classification_mode?e.classification_mode:void 0,tier_boundaries:(0,th.E)(e.tier_boundaries),token_thresholds:(0,th.F)(e.token_thresholds),dimension_weights:(0,th.A)(e.dimension_weights),custom_dimensions:(0,tc.f)(e.custom_dimensions),reasoning_override_min_score:(0,th.m)(e.reasoning_override_min_score),session_affinity:"boolean"==typeof e.session_affinity?e.session_affinity:tu.K,session_affinity_ttl_seconds:"number"==typeof e.session_affinity_ttl_seconds&&Number.isFinite(e.session_affinity_ttl_seconds)?e.session_affinity_ttl_seconds:void 0,modality_routing:"boolean"==typeof e.modality_routing&&e.modality_routing,modality_pin_override:"boolean"==typeof e.modality_pin_override&&e.modality_pin_override,deployment_affinity:"boolean"==typeof e.deployment_affinity?e.deployment_affinity:tu.$,adaptive:e.adaptive||!1,adaptive_weights:e.adaptive_weights,tier_distance_penalty:e.tier_distance_penalty,adaptive_eligible:e.adaptive_eligible||"all",return_raw_model_name:e.return_raw_model_name||!1,enable_context_window_escalation:"boolean"==typeof e.enable_context_window_escalation?e.enable_context_window_escalation:void 0,context_window_escalation_buffer:"number"==typeof e.context_window_escalation_buffer?e.context_window_escalation_buffer:void 0,cache_aware_routing:"boolean"==typeof e.cache_aware_routing?e.cache_aware_routing:void 0,cache_aware_routing_output_tokens:"number"==typeof e.cache_aware_routing_output_tokens?e.cache_aware_routing_output_tokens:void 0,cache_aware_routing_timeout_ms:"number"==typeof e.cache_aware_routing_timeout_ms?e.cache_aware_routing_timeout_ms:void 0,stall_escalation_enabled:!0===e.stall_escalation_enabled||void 0,stall_escalation_window:"number"==typeof e.stall_escalation_window?e.stall_escalation_window:void 0,stall_escalation_repeat_threshold:"number"==typeof e.stall_escalation_repeat_threshold?e.stall_escalation_repeat_threshold:void 0,code_keywords:tf(e.code_keywords),reasoning_keywords:tf(e.reasoning_keywords),technical_keywords:tf(e.technical_keywords),simple_keywords:tf(e.simple_keywords),plan_mode_patterns:tf(e.plan_mode_patterns),route_housekeeping_to_cheapest_tier:"boolean"==typeof e.route_housekeeping_to_cheapest_tier?e.route_housekeeping_to_cheapest_tier:void 0,housekeeping_patterns:tf(e.housekeeping_patterns),reminder_markers:Array.isArray(e.reminder_markers)?e.reminder_markers.filter(tp):void 0,max_tokens_from_tier_model:"boolean"==typeof e.max_tokens_from_tier_model||"clamp"===e.max_tokens_from_tier_model?e.max_tokens_from_tier_model:void 0,classifier_plugin_timeout_ms:"number"==typeof e.classifier_plugin_timeout_ms&&Number.isFinite(e.classifier_plugin_timeout_ms)?e.classifier_plugin_timeout_ms:void 0}},t_=new Set(["tiers","enable_non_reasoning_tier","tier_definitions","fallback_tier","tier_model_configs","default_model","plan_mode_min_tier","tier_labels","classifier_type","local_heuristic","capability_classifier_config","llm_v2_config","classifier_llm_config","jev_classifier_config","opensource_classifier_config","classifier_context_window_size","classifier_context_budget_chars","classifier_context_include_assistant_turns","classifier_fallback","classification_prompt","classification_examples","heuristic_first_max_tier","hybrid_boundary_margin","heuristic_v2_success_threshold","classification_mode","session_affinity","session_affinity_ttl_seconds","modality_routing","modality_pin_override","deployment_affinity","adaptive","adaptive_weights","tier_distance_penalty","adaptive_eligible","return_raw_model_name","tier_boundaries","token_thresholds","dimension_weights","custom_dimensions","reasoning_override_min_score","enable_context_window_escalation","context_window_escalation_buffer","cache_aware_routing","cache_aware_routing_output_tokens","cache_aware_routing_timeout_ms","stall_escalation_enabled","stall_escalation_window","stall_escalation_repeat_threshold","code_keywords","reasoning_keywords","technical_keywords","simple_keywords","plan_mode_patterns","route_housekeeping_to_cheapest_tier","housekeeping_patterns","reminder_markers","max_tokens_from_tier_model","classifier_plugin_timeout_ms"]),tg=new Set(["keyword_tier_rules","escalation_keywords","semantic_keyword_matching","embedding_model","match_threshold"]),tj=["route_housekeeping_to_cheapest_tier","reminder_markers","max_tokens_from_tier_model"],tv=(e,t,s,a)=>{let l,r="object"!=typeof(l="string"==typeof e?JSON.parse(e):e)||null===l||Array.isArray(l)?{}:l,i=tx(r,void 0),n=new Set(tj.filter(e=>e in r&&JSON.stringify(t[e])===JSON.stringify(i[e]))),o=e=>!n.has(e)&&("classifier_context_per_turn_chars"===e?!(0,eq.h)((0,tu.t)(t))||Object.prototype.hasOwnProperty.call(t,e):!!(t_.has(e)||"escalation_keywords"===e&&(0,eF.K)((0,tu.t)(t))||void 0!==a&&tg.has(e))||void 0!==s&&"custom_technical_keywords"===e),d=t.custom_tier_set?tr.I:[],c=Object.fromEntries(Object.entries(r).filter(([e])=>!o(e)&&!d.includes(e))),u={...tm(t),customTechnicalKeywords:s??[],keywordTierRules:a?.keywordTierRules??[],semanticMatchingEnabled:a?.semanticMatchingEnabled??!1,embeddingModel:a?.embeddingModel,matchThreshold:a?.matchThreshold??tn.h,escalationKeywords:a?.escalationKeywords??[]},m=(0,ti.j)(u),h=[...void 0===a?[...tg].filter(e=>!o(e)):[],...void 0===s?["custom_technical_keywords"]:[],...n];return{...c,...Object.fromEntries(Object.entries(m).filter(([e])=>!h.includes(e)))}},tb=({value:e,onChange:s,children:a,modelInfo:l,accessToken:r,userRole:n,isVisible:o})=>{let{userId:d}=(0,i.f)(),c=!!e.jev_classifier_config?.deployment_name,{data:u}=(0,eP.f)({queryKey:(0,y.Z)(d??"",n),queryFn:()=>(0,y.G)(r,d??"",n),enabled:!!(o&&r&&c)});return(0,t.jsx)(eR.U,{value:e,onChange:s,decisionModel:c?(0,t.jsx)(eO,{value:e,onChange:s,modelInfo:l,deployments:u}):void 0,children:a})},ty=({isVisible:e,onCancel:a,onSuccess:l,modelData:r,accessToken:i,userRole:n,isMemberManaged:o=!1})=>{let[d,c]=(0,s.useState)(!1),[u,m]=(0,s.useState)([]),[h,p]=(0,s.useState)([]),[f,x]=(0,s.useState)(!1),[_,j]=(0,s.useState)(!1),[v,b]=(0,s.useState)(null),[y,N]=(0,s.useState)([]),[k,w]=(0,s.useState)([]),[C,S]=(0,s.useState)([]),[M,E]=(0,s.useState)(!1),[T,P]=(0,s.useState)(void 0),[I,z]=(0,s.useState)(tn.h),[O,L]=(0,s.useState)(to.p),[R,q]=(0,s.useState)({tiers:{SIMPLE:[],MEDIUM:[],COMPLEX:[],REASONING:[]},classifier_type:"heuristic"}),F=eE(r?.litellm_params),K=(0,eL.v)(i,{saved_model_id:r?.model_info?.id,team_id:r?.model_info?.team_id,complexity_router_config:tv(r?.litellm_params?.complexity_router_config,R,y,{keywordTierRules:k,escalationKeywords:C,semanticMatchingEnabled:M,embeddingModel:T,matchThreshold:I})},e&&F),D=(0,s.useMemo)(()=>F?eB:e$,[F]),V=(0,eZ.f)(D,{defaultValues:eG}),U=(F?(R.custom_tier_set?(0,tr.O)(R.custom_tier_set)??(0,ti.k)((0,tr.X)(R)):(Object.values(R.tiers).every(e=>0===e.length)?"Please select at least one model for a complexity tier":null)??(0,ti.w)(R.tier_labels))??(0,ti.C)(R.plan_mode_min_tier,(0,tr.X)(R))??(0,ti.f)(k,(0,tr.X)(R))??(0,ti.b)(R)??(0,ti.e)(R.heuristic_v2_success_threshold)??(0,eF.J)(R)??("decides"===(0,tu.H)(R)?(0,tc.R)(R.custom_dimensions):null):null)??K.saveBlockedReason;(0,s.useEffect)(()=>{e&&r&&B()},[e,r]),(0,s.useEffect)(()=>{let t=!0,s=async()=>{if(i)try{let e=await (0,em.SL)(i,"","",!1,null,!0,!0);m(e.data.map(e=>e.id))}catch(e){console.error("Error fetching model access groups:",e)}},a=async()=>{if(i){p([]);try{let e=o?await (0,e4.a)(i,r?.model_info?.team_id):await (0,e4.X)(i);t&&p(e)}catch(e){console.error("Error fetching model info:",e)}}};return e&&(s(),a()),()=>{t=!1}},[e,i,o,r?.model_info?.team_id]);let B=()=>{j(!1);try{if(F){let e=r.litellm_params?.complexity_router_config||{};"string"==typeof e&&(e=JSON.parse(e));let t=tx(e,r.litellm_params?.complexity_router_default_model);q(t),N(Array.isArray(e.custom_technical_keywords)?e.custom_technical_keywords:[]),w((0,td.f)(e.keyword_tier_rules)),S(Array.isArray(e.escalation_keywords)?e.escalation_keywords.filter(e=>"string"==typeof e):[]),E(!0===e.semantic_keyword_matching),P("string"==typeof e.embedding_model?e.embedding_model:void 0),z("number"==typeof e.match_threshold?e.match_threshold:tn.h),L((0,to.a)({auto_router_routing_compression:r.litellm_params?.auto_router_routing_compression,auto_router_model_compression:r.litellm_params?.auto_router_model_compression})),V.reset({...eG,auto_router_name:r.model_name,model_access_group:r.model_info?.access_groups||[]});return}let e=null;r.litellm_params?.auto_router_config&&(e="string"==typeof r.litellm_params.auto_router_config?JSON.parse(r.litellm_params.auto_router_config):r.litellm_params.auto_router_config),b(e);let t={auto_router_name:r.model_name,auto_router_default_model:r.litellm_params?.auto_router_default_model||null,auto_router_embedding_model:r.litellm_params?.auto_router_embedding_model||null,model_access_group:r.model_info?.access_groups||[]};V.reset(t)}catch(e){console.error("Error parsing auto router config:",e),eH.f.fromError("Error loading auto router configuration")}},$=async e=>{if(K.saveBlockedReason)return void eH.f.fromError(K.saveBlockedReason);if(F){let{tiers:t,custom_tier_set:s,classifier_llm_config:n}=R,d=(0,tr.X)(R),c=Object.values(t).every(e=>0===e.length),u=s?(0,tr.O)(s)??(0,ti.k)(d):c&&"Please select at least one model for a complexity tier";if(u){x(!0),eH.f.fromError(u);return}let m=(0,ti.b)(R)??(0,ti.e)(R.heuristic_v2_success_threshold)??(0,ti._)(R.reminder_markers)??(0,ti.r)(R.classifier_type,R.classifier_plugin_timeout_ms)??(0,eF.J)(R)??("decides"===(0,tu.H)(R)?(0,tc.R)(R.custom_dimensions):null);if(m){x(!0),eH.f.fromError(m);return}let p=(0,ti.I)(R,h);if(p){x(!0),eH.f.fromError(p);return}let f=(0,ti.f)(k,d);if(f){x(!0),eH.f.fromError(f);return}let _=(0,ti.q)({semanticMatchingEnabled:M,embeddingModel:T,keywordTierRules:k});if(_){x(!0),eH.f.fromError(_);return}let g=(0,tr.H)(R,R.default_model);if(!g){x(!0),eH.f.fromError("Add a model to the Simple or Medium tier, or pin a default model, so requests have somewhere to route.");return}let j=tv(r.litellm_params?.complexity_router_config,R,y,{keywordTierRules:k,escalationKeywords:C,semanticMatchingEnabled:M,embeddingModel:T,matchThreshold:I}),v=await (0,em.Ms)(i,j,r?.model_info?.team_id),b=(0,ti.c)(v);if(b){x(!0),eH.f.fromError(b);return}let N={...r.litellm_params,complexity_router_config:j,complexity_router_default_model:g,...o?{}:(0,to.I)(O,r.litellm_params??{})},w={...r.model_info,access_groups:e.model_access_group||[]};await (0,em.Gp)(i,o?{litellm_params:{complexity_router_config:j,complexity_router_default_model:g}}:{model_name:e.auto_router_name,litellm_params:N,model_info:w},r.model_info.id),eH.f.success("Auto router configuration updated successfully"),l({...r,model_name:e.auto_router_name,litellm_params:N,model_info:w}),a();return}let t={...r.litellm_params,auto_router_config:function(e){if(e?.routes?.some(e=>!(e.name??e.model)))throw Error("Please select a model for every route");return JSON.stringify(e)}(v),auto_router_default_model:e.auto_router_default_model,auto_router_embedding_model:e.auto_router_embedding_model||void 0},s={...r.model_info,access_groups:e.model_access_group||[]},n={model_name:e.auto_router_name,litellm_params:t,model_info:s};await (0,em.Gp)(i,n,r.model_info.id);let d={...r,model_name:e.auto_router_name,litellm_params:t,model_info:s};eH.f.success("Auto router configuration updated successfully"),l(d),a()},G=async()=>{try{c(!0),await V.handleSubmit($,()=>{eH.f.fromError("Failed to update auto router configuration")})()}catch(e){console.error("Error updating auto router:",e),eH.f.fromError(e)}finally{c(!1)}},H=[...h.map(e=>({value:e.model_group,label:e.model_group})),{value:"custom",label:"Enter custom model name"}],W=(0,t.jsx)(eY.f,{control:V.control,name:"auto_router_name",label:"Auto Router Name",children:({ref:e,...s})=>(0,t.jsx)(eX.f,{...s,ref:e,readOnly:o,placeholder:"e.g., auto_router_1, smart_routing"})});return(0,t.jsx)(eL.R.Provider,{value:K,children:(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&a(),children:(0,t.jsx)(eh.d,{className:"max-h-[90vh] overflow-y-auto sm:max-w-4xl",children:(0,t.jsxs)(A.g,{children:[(0,t.jsxs)(eh.s,{children:[(0,t.jsx)(eh.F,{children:"Edit Auto Router Configuration"}),(0,t.jsx)(eh.C,{children:"Edit the auto router configuration including routing logic, default models, and access settings."})]}),(0,t.jsx)("form",{onSubmit:e=>e.preventDefault(),noValidate:!0,children:(0,t.jsxs)(eJ.e,{children:[W,F?(0,t.jsx)("div",{className:"w-full",children:(0,t.jsx)(tb,{value:R,onChange:q,modelInfo:h,accessToken:i,userRole:n,isVisible:e,children:(0,t.jsx)(tu.U,{editingTiers:_,onEditingTiersChange:j,showValidationErrors:f,modelInfo:h,value:R,onChange:e=>{q(e)},customTechnicalKeywords:y,onCustomTechnicalKeywordsChange:N,keywordTierRules:k,onKeywordTierRulesChange:w,keywordRulesError:(0,ti.f)(k,(0,tr.X)(R)),semanticMatchingEnabled:M,onSemanticMatchingEnabledChange:E,embeddingModel:T,onEmbeddingModelChange:P,matchThreshold:I,onMatchThresholdChange:z,escalationKeywords:C,onEscalationKeywordsChange:S,autoRouterCompression:O,onAutoRouterCompressionChange:o?void 0:L})})}):(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"w-full",children:(0,t.jsx)(tl,{modelInfo:h,value:v,onChange:e=>{b(e)}})}),(0,t.jsx)(eY.f,{control:V.control,name:"auto_router_default_model",label:"Default Model",children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e2,{id:e,value:s,onChange:a,choices:H,placeholder:"Select a default model",ariaInvalid:l,ariaDescribedBy:r})}),(0,t.jsx)(eY.f,{control:V.control,name:"auto_router_embedding_model",label:"Embedding Model",children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e2,{id:e,value:s,onChange:a,choices:H,placeholder:"Select an embedding model",ariaInvalid:l,ariaDescribedBy:r})})]}),"Admin"===n&&!o&&(0,t.jsx)(eY.f,{control:V.control,name:"model_access_group",label:(0,eW.q)("Model Access Groups","Control who can access this auto router"),children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e1,{id:e,value:s,onChange:a,options:u,ariaInvalid:l,ariaDescribedBy:r})})]})}),(0,t.jsxs)(eh.c,{children:[(0,t.jsx)(g.K,{variant:"outline",onClick:a,children:"Cancel"}),null===U?(0,t.jsxs)(g.K,{disabled:d,onClick:G,children:[d&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Save Changes"]}):(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)(g.K,{disabled:!0,onClick:G,children:"Save Changes"})}),(0,t.jsx)(A.Y,{children:U})]})]})]})})})})},tN=ex.z.object({credential_name:ej.z.string().min(1,"Credential name is required")}),tk=({isVisible:e,onCancel:a,onAddCredential:l,existingCredential:r,setIsCredentialModalOpen:i})=>{let n,o=s.default.useId(),d="object"==typeof(n=r?.credential_values)&&null!==n?n:{},c=(0,eZ.f)(tN,{defaultValues:{credential_name:r?.credential_name??""}}),u=()=>{a(),c.reset()};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&u(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[600px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Reuse Credentials"})}),(0,t.jsx)(A.g,{children:(0,t.jsx)("form",{onSubmit:c.handleSubmit(e=>{l({...d,...e}),c.reset(),i(!1)}),noValidate:!0,children:(0,t.jsxs)(eJ.e,{children:[(0,t.jsx)(eY.f,{control:c.control,name:"credential_name",label:"Credential Name:",children:({ref:e,...s})=>(0,t.jsx)(eX.f,{...s,ref:e,placeholder:"Enter a friendly name for these credentials"})}),Object.entries(d).map(([e,s])=>(0,t.jsxs)(eJ.N,{children:[(0,t.jsx)(eJ.u,{htmlFor:`${o}-${e}`,children:e}),(0,t.jsx)(eX.f,{id:`${o}-${e}`,value:String(s),placeholder:`Enter ${e}`,disabled:!0,readOnly:!0})]},e)),(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/issues",className:"text-sm text-primary underline-offset-4 hover:underline",children:"Need Help?"})}),(0,t.jsx)(A.Y,{children:"Get help on our github"})]}),(0,t.jsxs)("div",{className:"flex gap-2.5",children:[(0,t.jsx)(g.K,{type:"button",variant:"outline",onClick:u,children:"Cancel"}),(0,t.jsx)(g.K,{type:"submit",children:"Reuse Credentials"})]})]})]})})})]})})};var tw=e.i(492688),tC=e.i(196631);function tS({credentialName:e,label:s,icon:a,className:l}){let r=s??e;return(0,t.jsxs)("span",{className:(0,tC.c)("flex min-w-0 flex-col gap-0.5",l),title:e,children:[(0,t.jsxs)("span",{className:"flex min-w-0 items-center gap-1.5",children:[a,(0,t.jsx)("span",{className:"truncate",children:r})]}),r!==e&&(0,t.jsx)("span",{className:"truncate font-mono text-xs font-normal text-muted-foreground",children:e})]})}function tM({credentialName:e,credentials:s}){return e?(0,t.jsx)(tS,{credentialName:e,label:(0,tw.N)(s).get(e)}):(0,t.jsx)(t.Fragment,{children:"Manual"})}function tE({credentialName:e,credentials:s}){let a=e?(0,tw.N)(s).get(e):void 0;return e&&void 0!==a&&a!==e?(0,t.jsx)("p",{className:"mt-1 truncate font-mono text-xs text-muted-foreground",children:e}):null}var tT=e.i(174553);function tA({overrides:e}){return void 0===e?null:0===e.length?(0,t.jsx)("p",{className:"mt-2 text-xs text-muted-foreground",children:"Follows the model cost map"}):(0,t.jsxs)("p",{className:"mt-2 text-xs text-muted-foreground",children:[(0,t.jsx)(e8.f,{variant:"outline",className:"mr-1",children:"Custom pricing"}),"Overrides the model cost map for ",e.join(", ")]})}function tP({model:e}){let s=e.output_cost_per_second,a=null!=s,l=null!=e.input_cost&&(!a||Number(e.input_cost)>0),r=null!=e.output_cost&&(!a||Number(e.output_cost)>0);return l||r||a?(0,t.jsxs)("div",{className:"mt-2",children:[l&&(0,t.jsxs)("p",{className:"text-sm",children:["Input: $",e.input_cost,"/1M tokens"]}),r&&(0,t.jsxs)("p",{className:"text-sm",children:["Output: $",e.output_cost,"/1M tokens"]}),a&&(0,t.jsxs)("p",{className:"text-sm",children:["Output: ",(0,es.b)(s)]}),(e.output_cost_per_second_tiers??[]).map(({resolution:e,cost:s})=>(0,t.jsxs)("p",{className:"text-sm",children:["Output (",e,"): ",(0,es.b)(s)]},e)),(0,t.jsx)(tA,{overrides:e.model_info?.pricing_overrides})]}):(0,t.jsx)("p",{className:"mt-2 text-sm text-muted-foreground",children:"-"})}var tI=e.i(89128),tz=e.i(204290),tO=e.i(929592),tL=e.i(450240);let tR=ex.z.object({api_key:ej.z.string().min(1,"Enter a new API key")}),tq={api_key:""};function tF({open:e,onCancel:a,accessToken:l,modelId:r,onUpdated:i}){let n=(0,eZ.f)(tR,{defaultValues:tq}),[o,d]=(0,s.useState)(!1),c=()=>{n.reset(tq),a()},u=async e=>{let t=e.api_key?.trim();if(!t)return void eH.f.fromError("Enter a new API key");d(!0);try{await (0,em.Gp)(l,{litellm_params:{api_key:t},model_info:{id:r}},r),eH.f.success("API key updated"),n.reset(tq),i(),a()}catch(e){console.error("Error updating API key:",e),eH.f.fromError("Failed to update API key")}finally{d(!1)}};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&c(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[520px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Update API Key"})}),(0,t.jsx)("span",{className:"block mb-4 text-sm text-muted-foreground",children:"Update this model's API key. Only the new key is sent; the rest of the deployment configuration is left untouched."}),(0,t.jsxs)(tz.f,{variant:"warning",className:"mb-4",children:[(0,t.jsx)(tI.f,{}),(0,t.jsx)(tO.s,{children:"Only the API key is rotated here. Models that authenticate with an Azure AD token, AWS credentials, or a Vertex service-account JSON aren't supported yet; update those from the model's LiteLLM Params for now."})]}),(0,t.jsxs)("form",{onSubmit:n.handleSubmit(u),children:[(0,t.jsx)(eJ.e,{children:(0,t.jsx)(eY.f,{control:n.control,name:"api_key",label:"New API Key",children:({ref:e,...s})=>(0,t.jsx)(tL.f,{...s,ref:e,placeholder:"Enter the new API key",autoComplete:"new-password"})})}),(0,t.jsxs)("div",{className:"flex justify-end items-center mt-4 gap-2.5",children:[(0,t.jsx)(g.K,{type:"button",variant:"outline",onClick:c,children:"Cancel"}),(0,t.jsxs)(g.K,{type:"submit",disabled:o,children:[o&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Update API Key"]})]})]})]})})}var tK=e.i(972165),tD=e.i(653145),tV=e.i(488826),tU=e.i(978056),tB=e.i(158321),t$=e.i(563458),tG=e.i(213056),tH=e.i(421436),tW=e.i(418276),tJ=e.i(967489),tY=e.i(699375),tX=e.i(299023),tQ=e.i(435451);let tZ="Cache Control Injection Points",t0="Tell litellm where to inject cache control checkpoints. You can specify either by role (to apply to all messages of that role) or by specific message index.",t1={location:"message"},t2=[{value:"message",label:"Message"}],t4=[{value:"user",label:"User"},{value:"system",label:"System"},{value:"assistant",label:"Assistant"}],t5=({label:e,hint:s})=>(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)(ez.f,{children:e}),(0,t.jsx)(A.g,{children:(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("button",{type:"button","aria-label":`${e} help`,className:"ml-1 inline-flex cursor-help items-center rounded-sm text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"}),children:(0,t.jsx)(e6.f,{"aria-hidden":!0,className:"size-4"})}),(0,t.jsx)(A.Y,{className:"max-w-xs whitespace-normal",children:s})]})})]}),t6=({value:e,onChange:s})=>{let a=e??[],l=(e,t)=>s?.(a.map((s,a)=>a===e?t:s));return(0,t.jsxs)("div",{className:"ml-6 border-l-2 border-border pl-4",children:[(0,t.jsx)("p",{className:"mb-4 block text-sm text-muted-foreground",children:"Providers like Anthropic, Bedrock API require users to specify where to inject cache control checkpoints, litellm can automatically add them for you as a cost saving feature."}),a.map((e,r)=>(0,t.jsxs)("div",{className:"mb-4 flex items-end gap-4",children:[(0,t.jsxs)("div",{className:"w-[180px] space-y-1",children:[(0,t.jsx)(ez.f,{children:"Type"}),(0,t.jsxs)(tJ.d,{items:t2,value:e.location,disabled:!0,children:[(0,t.jsx)(tJ.P,{className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:t2.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})]}),(0,t.jsxs)("div",{className:"w-[180px] space-y-1",children:[(0,t.jsx)(t5,{label:"Role",hint:"LiteLLM will mark all messages of this role as cacheable"}),(0,t.jsxs)(tJ.d,{items:t4,value:e.role??null,onValueChange:t=>l(r,{...e,role:t??void 0}),children:[(0,t.jsx)(tJ.P,{className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Select a role"})}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:null,children:"None"}),t4.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))]})]})]}),(0,t.jsxs)("div",{className:"w-[180px] space-y-1",children:[(0,t.jsx)(t5,{label:"Index",hint:"(Optional) If set litellm will mark the message at this index as cacheable"}),(0,t.jsx)(tQ.f,{type:"number",placeholder:"Optional",step:1,value:e.index??"",onChange:t=>l(r,{...e,index:""===t.target.value?void 0:t.target.value})})]}),a.length>1&&(0,t.jsx)(g.K,{type:"button",variant:"ghost",size:"icon","aria-label":`Remove injection point ${r+1}`,className:"text-destructive",onClick:()=>s?.(a.filter((e,t)=>t!==r)),children:(0,t.jsx)(tX.f,{className:"size-4"})})]},r)),(0,t.jsxs)(g.K,{type:"button",variant:"outline",className:"w-full border-dashed",onClick:()=>s?.([...a,t1]),children:[(0,t.jsx)(e3.f,{className:"mr-2 size-4"}),"Add Injection Point"]})]})},t3=({id:e,value:s,onChange:a,onBlur:l,teams:r})=>{let i=(r??[]).map(e=>({value:e.team_id,label:e.team_alias?`${e.team_alias} (${e.team_id})`:e.team_id}));return(0,t.jsxs)(tJ.d,{items:i,value:s||null,onValueChange:e=>a(e??""),children:[(0,t.jsx)(tJ.P,{id:e,className:"w-full",onBlur:l,children:(0,t.jsx)(tJ.U,{placeholder:"Select a team"})}),(0,t.jsx)(tJ.r,{children:i.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})};var t7=e.i(916940);let t8=[{name:L,label:"PTU Count",input:"number",placeholder:"e.g. 15",isCount:!0},{name:R,label:"Cost per PTU / Hour (USD)",input:"number",placeholder:"e.g. 2.00"},{name:q,label:"PTU Effective From (UTC)",input:"datetime"},{name:F,label:"PTU Effective To (UTC)",input:"datetime"}],t9=["input_cost","output_cost","cache_read_cost","cache_write_cost","cache_write_cost_1h"],se={input_cost:"input_cost_per_token",output_cost:"output_cost_per_token",cache_read_cost:"cache_read_input_token_cost",cache_write_cost:"cache_creation_input_token_cost",cache_write_cost_1h:"cache_creation_input_token_cost_above_1hr"},st=tV.z.union([ej.z.string(),tU.z.number(),tB.z.null()]).optional(),ss=ej.z.string().optional(),sa=e=>null==e||""===String(e).trim(),sl=st.refine(e=>sa(e)||Number.isFinite(Number(e))&&Number(e)>=0,"Enter a price of 0 or more").transform(e=>sa(e)?null:Number(e)/1e6),sr={model_name:ss,litellm_model_name:ss,api_base:ss,custom_llm_provider:ss,organization:ss,tpm:st,rpm:st,max_retries:st,timeout:st,stream_timeout:st,input_cost:sl,output_cost:sl,cache_read_cost:sl,cache_write_cost:sl,cache_write_cost_1h:sl,ptu_count:st,cost_per_ptu_per_hour:st,ptu_effective_from:t$.z.custom().nullish(),ptu_effective_to:t$.z.custom().nullish(),cache_control:tG.z.boolean().optional(),cache_control_injection_points:eK.z.array(t$.z.custom()).optional(),model_access_group:eK.z.array(ej.z.string()).optional(),guardrails:eK.z.array(ej.z.string()).optional(),vector_store_ids:eK.z.array(ej.z.string()).optional(),tags:eK.z.array(ej.z.string()).optional(),health_check_model:ej.z.string().nullish(),litellm_credential_name:ej.z.string().nullish(),litellm_extra_params:ss,model_info:ss,team_id:ss},si=(...e)=>{let t=e.find(e=>null!=e);return null==t?null:1e6*t},sn=(e,t)=>({model_name:e.model_name,litellm_model_name:e.litellm_model_name,api_base:e.litellm_params.api_base,custom_llm_provider:e.litellm_params.custom_llm_provider,organization:e.litellm_params.organization,tpm:e.litellm_params.tpm,rpm:e.litellm_params.rpm,max_retries:e.litellm_params.max_retries,timeout:e.litellm_params.timeout,stream_timeout:e.litellm_params.stream_timeout,input_cost:si(e.litellm_params.input_cost_per_token,e.model_info?.input_cost_per_token),output_cost:si(e.litellm_params?.output_cost_per_token,e.model_info?.output_cost_per_token),ptu_count:e.model_info?.ptu_count??null,cost_per_ptu_per_hour:e.model_info?.cost_per_ptu_per_hour??null,ptu_effective_from:O(e.model_info?.ptu_effective_from),ptu_effective_to:O(e.model_info?.ptu_effective_to),cache_read_cost:si(e.litellm_params?.cache_read_input_token_cost,e.model_info?.cache_read_input_token_cost),cache_write_cost:si(e.litellm_params?.cache_creation_input_token_cost,e.model_info?.cache_creation_input_token_cost),cache_write_cost_1h:si(e.litellm_params?.cache_creation_input_token_cost_above_1hr,e.model_info?.cache_creation_input_token_cost_above_1hr),cache_control:!!e.litellm_params?.cache_control_injection_points,cache_control_injection_points:e.litellm_params?.cache_control_injection_points||[],model_access_group:Array.isArray(e.model_info?.access_groups)?e.model_info.access_groups:[],guardrails:Array.isArray(e.litellm_params?.guardrails)?e.litellm_params.guardrails:[],vector_store_ids:Array.isArray(e.litellm_params?.vector_store_ids)&&e.litellm_params.vector_store_ids.length>0?e.litellm_params.vector_store_ids:void 0,tags:Array.isArray(e.litellm_params?.tags)?e.litellm_params.tags:[],...t?{health_check_model:e.model_info?.health_check_model}:{},litellm_credential_name:e.litellm_params?.litellm_credential_name??null,litellm_extra_params:JSON.stringify(ei(e.litellm_params??{}),null,2),team_id:e.model_info?.team_id??void 0}),so=({children:e})=>(0,t.jsx)("div",{className:"mt-1 rounded-sm bg-muted p-2",children:e}),sd="text-sm font-medium text-foreground",sc=({htmlFor:e,children:s})=>void 0===e?(0,t.jsx)("p",{className:sd,children:s}):(0,t.jsx)("label",{htmlFor:e,className:sd,children:s}),su=({text:e})=>(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)(e6.f,{className:"ml-1 inline size-3.5 shrink-0 cursor-help text-muted-foreground"})}),(0,t.jsx)(A.Y,{className:"max-w-xs",children:e})]}),sm=({text:e,href:s})=>(0,t.jsx)("a",{href:s,target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,t.jsx)(su,{text:e})}),sh=({values:e,emptyLabel:s})=>e?Array.isArray(e)?0===e.length?(0,t.jsx)(t.Fragment,{children:s}):(0,t.jsx)("div",{className:"flex flex-wrap gap-1",children:e.map((e,s)=>(0,t.jsx)(e8.f,{variant:"secondary",children:e},s))}):(0,t.jsx)(t.Fragment,{children:String(e)}):(0,t.jsx)(t.Fragment,{children:"Not Set"}),sp=({localModelData:e,modelData:a,teamAlias:l,accessToken:r,isEditing:i,isSaving:n,isWildcardModel:o,ptuCostAttributionEnabled:d,showCacheControl:c,setShowCacheControl:u,onCancel:m,onSubmit:h,modelAccessGroups:p,guardrailsList:f,tagsList:x,credentialsList:_,healthCheckModelOptions:j,teams:v})=>{let b=s.useRef(new Set),y=s.useCallback(e=>b.current.has(e),[]),N=(0,tD.G)({resolver:(e,t,s)=>(0,tK.f)(ex.z.object(sr).superRefine((e,t)=>{let s=(e,s)=>t.addIssue({code:"custom",path:[e],message:s});if(null===en(e.litellm_extra_params)&&s("litellm_extra_params","Please enter a valid JSON object"),d){if(D(e.ptu_count)||s("ptu_count",`PTU Count must be a whole number between 1 and ${1e6.toLocaleString()}`),U(e.cost_per_ptu_per_hour)||s("cost_per_ptu_per_hour",`Cost per PTU / Hour must be between 0 and ${1e6.toLocaleString()}`),K(e.ptu_count)!==K(e.cost_per_ptu_per_hour)){let e="PTU Count and Cost per PTU / Hour must be set together";s("ptu_count",e),s("cost_per_ptu_per_hour",e)}if(K(e.ptu_count)&&!K(e.ptu_effective_from)&&s("ptu_effective_from","PTU Effective From is required when PTU Count is set"),!H(e.ptu_effective_from,e.ptu_effective_to)){let e="PTU Effective To must be after PTU Effective From";s("ptu_effective_from",e),s("ptu_effective_to",e)}for(let t of t9){let a=e[t];y(t)&&K(e.ptu_count)&&K(a)&&0!==Number(a)&&s(t,"A PTU deployment bills by reserved capacity, so this cost must be 0 or blank")}}}))(e,t,s),defaultValues:sn(e,o)}),k=(e,s,a,l)=>(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:s}),i?(0,t.jsx)(eY.f,{control:N.control,name:e,children:({value:e,...s})=>(0,t.jsx)(eX.f,{...s,value:e??"",placeholder:a})}):(0,t.jsx)(so,{children:l||"Not Set"})]}),w=(e,s,a,l)=>(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:s}),i?(0,t.jsx)(eY.f,{control:N.control,name:e,children:({value:e,...s})=>(0,t.jsx)(tQ.f,{...s,value:e??"",placeholder:a})}):(0,t.jsx)(so,{children:l||"Not Set"})]}),C=(s,a,l,r)=>{let n,o;return i?(0,t.jsx)(eY.f,{control:N.control,name:s,label:a,description:r,children:({value:e,onChange:a,...r})=>(0,t.jsx)(tQ.f,{...r,value:e??"",placeholder:l,onChange:e=>{b.current=new Set([...b.current,s]),a(e)}})}):(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:a}),(0,t.jsx)(so,{children:(n=se[s],null!=(o=e?.litellm_params?.[n]??e?.model_info?.[n])?(1e6*Number(o)).toFixed(4):"Not Set")})]})},S=(e,s,a)=>(0,t.jsx)(eY.f,{control:N.control,name:e,children:({id:e,value:l,onChange:r})=>(0,t.jsx)(tH.f,{id:e,value:l??[],onValueChange:r,options:s,placeholder:a,tokenSeparators:[","]})});return(0,t.jsx)(A.g,{children:(0,t.jsx)("form",{onSubmit:e=>N.handleSubmit(async e=>{await h(e,y)})(e),children:(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("div",{className:"space-y-4",children:[k("model_name","Model Name","Enter model name",e.model_name),k("litellm_model_name","LiteLLM Model Name","Enter LiteLLM model name",e.litellm_model_name),C("input_cost","Input Cost (per 1M tokens)","Enter input cost"),C("output_cost","Output Cost (per 1M tokens)","Enter output cost"),d&&t8.map(s=>(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{htmlFor:s.name,children:s.label}),i?(0,t.jsx)(eY.f,{control:N.control,name:s.name,children:({value:e,onChange:a,...l})=>"number"===s.input?(0,t.jsx)(tQ.f,{...l,id:s.name,onChange:a,value:e??"",placeholder:s.placeholder,step:s.isCount?1:void 0,min:+!!s.isCount}):(0,t.jsx)(tW.f,{...l,id:s.name,value:e,onChange:a})}):(0,t.jsx)(so,{children:("datetime"===s.input?(e=>{if(!e)return null;let t=P.default.utc(e);return t.isValid()?`${t.format("YYYY-MM-DD HH:mm:ss")} UTC`:String(e)})(e?.model_info?.[s.name]):e?.model_info?.[s.name])??"Not Set"})]},s.name)),C("cache_read_cost","Cache Read Cost (per 1M tokens)","Defaults to Input Cost if blank","If left blank on save, defaults to Input Cost."),C("cache_write_cost","Cache Write Cost (per 1M tokens)","Defaults to Input Cost if blank","If left blank on save, defaults to Input Cost (backend falls back to input_cost_per_token)."),C("cache_write_cost_1h","Cache Write Cost (1 hour, per 1M tokens)","Defaults to the cost map 1 hour rate, else Cache Write Cost","Rate for prompt cache writes with a 1 hour TTL. If left blank on save, known models use their cost map 1 hour rate, otherwise Cache Write Cost."),k("api_base","API Base","Enter API base",e.litellm_params?.api_base),k("custom_llm_provider","Custom LLM Provider","Enter custom LLM provider",e.litellm_params?.custom_llm_provider),k("organization","Organization","Enter organization",e.litellm_params?.organization),w("tpm","TPM (Tokens per Minute)","Enter TPM",e.litellm_params?.tpm),w("rpm","RPM (Requests per Minute)","Enter RPM",e.litellm_params?.rpm),w("max_retries","Max Retries","Enter max retries",e.litellm_params?.max_retries),w("timeout","Timeout (seconds)","Enter timeout",e.litellm_params?.timeout),w("stream_timeout","Stream Timeout (seconds)","Enter stream timeout",e.litellm_params?.stream_timeout),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Model Access Groups"}),i?S("model_access_group",(p??[]).map(e=>({value:e,label:e})),"Select existing groups or type to create new ones"):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.model_info?.access_groups,emptyLabel:"No groups assigned"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(sc,{children:["Guardrails",(0,t.jsx)(sm,{text:"Apply safety guardrails to this model to filter content or enforce policies",href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start"})]}),i?S("guardrails",f.map(e=>({value:e,label:e})),"Select existing guardrails or type to create new ones"):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.litellm_params?.guardrails,emptyLabel:"No guardrails assigned"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(sc,{children:["Attached Knowledge Bases (RAG)",(0,t.jsx)(sm,{text:"Vector stores used for RAG. Every request to this model will automatically retrieve context from these knowledge bases.",href:"https://docs.litellm.ai/docs/completion/knowledgebase"})]}),i?(0,t.jsx)(eY.f,{control:N.control,name:"vector_store_ids",children:({value:e,onChange:s})=>(0,t.jsx)(t7.f,{value:e,onChange:s,accessToken:r||"",placeholder:"Select knowledge bases (optional)"})}):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.litellm_params?.vector_store_ids,emptyLabel:"No knowledge bases attached"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Tags"}),i?S("tags",Object.values(x).map(e=>({value:e.name,label:e.name})),"Select existing tags or type to create new ones"):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.litellm_params?.tags,emptyLabel:"No tags assigned"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Existing Credentials"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"litellm_credential_name",children:({id:e,value:s,onChange:a})=>(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(eI.f,{inputId:e,placeholder:"Select or search for existing credentials",options:(0,tw.H)(_),value:s??"",allowClear:!1,onValueChange:e=>{null!==e&&a(""===e?null:e)}}),(0,t.jsx)(tE,{credentialName:s,credentials:_})]})}):(0,t.jsx)(so,{children:(0,t.jsx)(tM,{credentialName:e.litellm_params?.litellm_credential_name,credentials:_})})]}),o&&(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Health Check Model"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"health_check_model",children:({id:e,value:s,onChange:a,onBlur:l})=>(0,t.jsxs)(tJ.d,{items:j,value:s??null,onValueChange:a,children:[(0,t.jsx)(tJ.P,{id:e,className:"w-full",onBlur:l,children:(0,t.jsx)(tJ.U,{placeholder:"Select existing health check model"})}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:null,children:"None"}),j.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))]})]})}):(0,t.jsx)(so,{children:e.model_info?.health_check_model||"Not Set"})]}),i?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(eY.f,{control:N.control,name:"cache_control",label:(0,t.jsxs)(t.Fragment,{children:[tZ,(0,t.jsx)(su,{text:t0})]}),orientation:"horizontal",children:({id:e,value:s,onChange:a,onBlur:l})=>(0,t.jsx)(tY.f,{id:e,onBlur:l,checked:!!s,onCheckedChange:e=>{a(e),u(e)}})}),c&&(0,t.jsx)(eY.f,{control:N.control,name:"cache_control_injection_points",children:({value:e,onChange:s})=>(0,t.jsx)(t6,{value:e??[],onChange:s})})]}):(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Cache Control"}),(0,t.jsx)(so,{children:e.litellm_params?.cache_control_injection_points?(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{children:"Enabled"}),(0,t.jsx)("div",{className:"mt-2",children:e.litellm_params.cache_control_injection_points.map((e,s)=>(0,t.jsxs)("div",{className:"mb-1 text-sm text-muted-foreground",children:["Location: ",e.location,",",e.role&&(0,t.jsxs)("span",{children:[" Role: ",e.role]}),void 0!==e.index&&(0,t.jsxs)("span",{children:[" Index: ",e.index]})]},s))})]}):"Disabled"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Model Info"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"model_info",children:({value:e,...s})=>(0,t.jsx)(tt.f,{...s,rows:4,placeholder:'{"gpt-4": 100, "claude-v1": 200}',defaultValue:JSON.stringify(a.model_info,null,2)})}):(0,t.jsx)(so,{children:(0,t.jsx)("pre",{className:"mt-1 overflow-auto rounded-sm bg-muted p-2 text-xs",children:JSON.stringify(e.model_info,null,2)})})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(sc,{children:["LiteLLM Params",(0,t.jsx)(sm,{text:"Additional parameters for model requests. Settings with dedicated fields above are edited there. Remove a key here to delete its saved value.",href:"https://docs.litellm.ai/docs/completion/input"})]}),i?(0,t.jsx)(eY.f,{control:N.control,name:"litellm_extra_params",children:({value:e,...s})=>(0,t.jsx)(tt.f,{...s,"aria-label":"LiteLLM Params",value:e??"",rows:4,placeholder:'{\n "drop_params": true\n}'})}):(0,t.jsx)(so,{children:(0,t.jsx)("pre",{className:"mt-1 overflow-auto rounded-sm bg-muted p-2 text-xs",children:JSON.stringify(e.litellm_params,null,2)})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Team"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"team_id",children:({id:e,value:s,onChange:a,onBlur:l})=>(0,t.jsx)(t3,{id:e,value:s,onChange:a,onBlur:l,teams:v})}):(0,t.jsx)(so,{children:l?`${l} (${e.model_info?.team_id})`:e.model_info?.team_id||"Not Set"})]})]}),i&&(0,t.jsxs)("div",{className:"mt-6 flex justify-end gap-2",children:[(0,t.jsx)(g.K,{type:"submit",variant:"secondary",onClick:()=>{N.reset(sn(e,o)),b.current=new Set,m()},disabled:n,children:"Cancel"}),(0,t.jsxs)(g.K,{type:"submit",disabled:n,"aria-busy":n,children:[n&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Save Changes"]})]})]})})})},sf=e=>e?.model_info?.team_public_model_name?e.model_info.team_public_model_name:e?.model_name||"-";var sx=e.i(768371);function s_({data:e,isError:s,isPending:a,apiErrorMessage:l}){let r=void 0!==e&&!s,i=r&&null!==e.error,n=r&&null===e.error&&0===e.pod_ips.length,o=r&&null===e.error&&e.pod_ips.length>0,d=r&&!i?e.pod_count:null;return(0,t.jsxs)(t.Fragment,{children:[null!==d&&d>0&&(0,t.jsxs)("p",{className:"mt-4 text-sm",children:[d," ready pods"]}),a&&(0,t.jsx)("p",{className:"mt-4 text-sm text-muted-foreground",role:"status",children:"Loading Kubernetes pods"}),s&&(0,t.jsx)("p",{className:"mt-4 text-sm text-destructive",role:"alert",children:l}),e&&i&&(0,t.jsx)("p",{className:"mt-4 text-sm text-destructive",role:"alert",children:e.error}),e&&n&&(0,t.jsx)("p",{className:"mt-4 text-sm text-muted-foreground",children:"No ready pods"}),e&&o&&(0,t.jsx)("ul",{"aria-label":"Ready Kubernetes pod IPs",className:"mt-3 space-y-1 font-mono text-sm",children:e.pod_ips.map(e=>(0,t.jsx)("li",{children:e},e))})]})}function sg({modelId:e}){let{data:s,error:a,isError:l,isPending:r,refetch:i}=sx.q.useQuery("get","/model/{model_id}/kubernetes_pods",{params:{path:{model_id:e}}},{refetchInterval:1e4}),n=a instanceof Error?a.message:JSON.stringify(a)??"Failed to load Kubernetes pods";return(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsxs)("div",{className:"flex items-start justify-between gap-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Kubernetes pods"}),s&&(0,t.jsx)("p",{className:"mt-1 text-sm text-muted-foreground",children:null===s.port?s.service_host:`${s.service_host}:${s.port}`})]}),(0,t.jsx)(g.K,{type:"button",variant:"outline",onClick:()=>void i(),children:"Refresh"})]}),(0,t.jsx)(s_,{data:s,isError:l,isPending:r,apiErrorMessage:n})]})}function sj({modelId:e,onClose:a,accessToken:l,userID:i,userRole:o,isViewOnly:d,onModelUpdate:m,modelAccessGroups:h}){let p,f=(0,r.d)(),[x,_]=(0,s.useState)(null),[j,v]=(0,s.useState)(!1),[N,k]=(0,s.useState)(!1),[P,I]=(0,s.useState)(!1),[O,L]=(0,s.useState)(!1),[R,q]=(0,s.useState)(!1),[F,K]=(0,s.useState)(!1),[D,V]=(0,s.useState)(null),[U,B]=(0,s.useState)(!1),[$,G]=(0,s.useState)({}),[H,W]=(0,s.useState)(!1),[ea,er]=(0,s.useState)(!1),[ed,ec]=(0,s.useState)(0),[eu,ef]=(0,s.useState)([]),[eN,eC]=(0,s.useState)([]),[eS,eP]=(0,s.useState)({}),[eI,ez]=(0,s.useState)([]),{data:eO,isLoading:eL}=(0,y.e)(1,50,void 0,e,void 0,void 0,void 0,!1,void 0,void 0,!1,void 0,{useStoredParams:!0}),{data:eR}=(0,b.X)(),{data:eq}=(0,y.x)(),{data:eF}=(0,n.n)(),eK=X(),eD=e=>null!=eR&&"object"==typeof eR&&e in eR?eR[e].litellm_provider:"openai",eV=(0,s.useMemo)(()=>eO?.data&&0!==eO.data.length&&w(eO,eD).data[0]||null,[eO,eR]),eU=e=>eF?.find(t=>t.team_id===e)?.team_alias||null,eB=eU(eV?.model_info?.team_id),e$=Object.entries(eV?.model_info??{}).flatMap(e=>"team_id"===e[0]&&eB?[e,["team_alias",eB]]:[e]),eG=eV&&{...eV,model_info:Object.fromEntries(e$)},eW="Admin"===o,eJ={userRole:o,userID:i,isViewOnly:d},eY={teamId:eV?.model_info?.team_id,isDbModel:eV?.model_info?.db_model===!0,createdBy:eV?.model_info?.created_by,model:eV?.litellm_params?.model},eX=(0,u.d)(eJ,eF??null,eY),eQ=(0,u.F)(eJ,eF??null,eY),eZ=(0,s.useMemo)(()=>(0,c.d)(eF??null,o,i),[eF,o,i]),e0=eT(p=eV?.litellm_params)&&eM(p).hasEditor,e1=eT(eV?.litellm_params),e2=e1?"Delete Auto-Router":"Delete Model",e4=eE(eV?.litellm_params),e5=eV?.litellm_params?.litellm_credential_name!=null&&eV?.litellm_params?.litellm_credential_name!=void 0,e6=x?.model_info?.id!==eV?.model_info?.id;(0,s.useEffect)(()=>{if(eV&&(!x||e6)){let e=eV;e.litellm_model_name||(e={...e,litellm_model_name:e?.litellm_params?.litellm_model_name??e?.litellm_params?.model??e?.model_info?.key??null}),_(e),B(!!e?.litellm_params?.cache_control_injection_points)}},[eV,x,e6]),(0,s.useEffect)(()=>{let t=async()=>{if(l)try{let e=(await (0,em.gx)(l)).guardrails.map(e=>e.guardrail_name);eC(e)}catch(e){console.error("Failed to fetch guardrails:",e)}},s=async()=>{if(l)try{let e=await (0,em.M3)(l);eP(e)}catch(e){console.error("Failed to fetch tags:",e)}},a=async()=>{if(l)try{let e=await (0,em.lg)(l);ez(e.credentials||[])}catch(e){console.error("Failed to fetch credentials:",e)}};(async()=>{if(!l||e5)return;let t=await (0,em.lm)(l,null,e);V({credential_name:t.credential_name,credential_values:t.credential_values,credential_info:t.credential_info})})(),t(),s(),a()},[l,e]);let e3=async t=>{if(!l)return;let s={credential_name:t.credential_name,model_id:e,credential_info:{custom_llm_provider:x.litellm_params?.custom_llm_provider}};eH.f.info("Storing credential.."),await (0,em.E6)(l,s),eH.f.success("Credential stored successfully")},e7=async(t,s)=>{try{let r;if(!l)return;q(!0);let i=en(t.litellm_extra_params);if(null===i)return void eH.f.fromError("LiteLLM Params must be a valid JSON object");let n={...ei(i),model:t.litellm_model_name,api_base:t.api_base,custom_llm_provider:t.custom_llm_provider,organization:t.organization,tpm:t.tpm,rpm:t.rpm,max_retries:t.max_retries,timeout:t.timeout,stream_timeout:t.stream_timeout,tags:t.tags};if(s("input_cost")&&(n.input_cost_per_token=t.input_cost),s("output_cost")&&(n.output_cost_per_token=t.output_cost),s("cache_read_cost"))n.cache_read_input_token_cost=t.cache_read_cost;else if(s("input_cost")){let e=t.cache_read_cost??t.input_cost;null!==e&&(n.cache_read_input_token_cost=e)}s("cache_write_cost")&&(n.cache_creation_input_token_cost=t.cache_write_cost),s("cache_write_cost_1h")&&(n.cache_creation_input_token_cost_above_1hr=t.cache_write_cost_1h);let o=x?.litellm_params?.litellm_credential_name??null,d=t.litellm_credential_name??null;d!==o?n.litellm_credential_name=d:delete n.litellm_credential_name,t.guardrails&&(n.guardrails=t.guardrails),(t.vector_store_ids?.length??0)>0?n.vector_store_ids=t.vector_store_ids:void 0!==t.vector_store_ids?n.vector_store_ids=[]:delete n.vector_store_ids;let c=!!x?.litellm_params?.cache_control_injection_points;t.cache_control&&(t.cache_control_injection_points?.length??0)>0?n.cache_control_injection_points=t.cache_control_injection_points:c?n.cache_control_injection_points=null:delete n.cache_control_injection_points;try{var a;r=t.model_info?JSON.parse(t.model_info):eV?.model_info,t.model_access_group&&(r={...r,access_groups:t.model_access_group}),void 0!==t.health_check_model&&(r={...r,health_check_model:t.health_check_model}),t.team_id&&(r={...r,team_id:t.team_id}),a=r,r=eK?{...a,ptu_count:Y(t.ptu_count),cost_per_ptu_per_hour:Y(t.cost_per_ptu_per_hour),ptu_effective_from:z(t.ptu_effective_from),ptu_effective_to:z(t.ptu_effective_to)}:Object.fromEntries(Object.entries(a).filter(([e])=>!J.includes(e)))}catch(e){eH.f.fromError("Invalid JSON in Model Info");return}let u=Object.keys(ei(x?.litellm_params??{})).filter(e=>!Object.prototype.hasOwnProperty.call(i,e)),h=el(n),p=Object.fromEntries(Object.entries({...x?.litellm_params,...h}).filter(([e])=>"litellm_credential_name"!==e&&!u.includes(e))),f={model_name:t.model_name,litellm_params:h,...u.length>0&&{litellm_params_to_remove:u},model_info:r};await (0,em.Gp)(l,f,e);let g={...x,model_name:t.model_name,litellm_model_name:t.litellm_model_name,litellm_params:null===d?p:{...p,litellm_credential_name:d},model_info:r};_(g),m&&m(g),eH.f.success("Model settings updated successfully"),K(!1)}catch(e){console.error("Error updating model:",e),eH.f.fromError("Failed to update model settings")}finally{q(!1)}};if(eL)return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)(g.K,{variant:"ghost",onClick:a,className:"mb-4",children:[(0,t.jsx)(Q.f,{className:"size-4"}),"Back to Models"]}),(0,t.jsx)("p",{className:"text-sm",children:"Loading..."})]});if(!eV)return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)(g.K,{variant:"ghost",onClick:a,className:"mb-4",children:[(0,t.jsx)(Q.f,{className:"size-4"}),"Back to Models"]}),(0,t.jsx)("p",{className:"text-sm",children:"Model not found"})]});let e8=async()=>{if(l){if(e4){let e=(e=>{let t=e?.litellm_params?.complexity_router_config,s={};if("string"==typeof t)try{s=JSON.parse(t)}catch{s={}}else t&&(s=t);let a=s.tiers&&"object"==typeof s.tiers?Object.entries(s.tiers).map(([e,t])=>[e,(0,ek.I)(t)]):[],l=e?.litellm_params?.complexity_router_default_model||void 0;return ew({tiers:a,semanticMatchingEnabled:!!s.semantic_keyword_matching,embeddingModel:s.embedding_model,defaultModel:l})})(x??eV);return 0===e.length?void eH.f.warning("No complexity tiers are configured yet, so there is nothing to test."):(ef(e),ec(e=>e+1),void er(!0))}try{eH.f.info("Testing connection...");let e=await (0,em.ym)(l,{custom_llm_provider:x.litellm_params.custom_llm_provider,litellm_credential_name:x.litellm_params.litellm_credential_name,model:x.litellm_model_name},{id:x.model_info?.id});if("success"===e.status)eH.f.success("Connection test successful!");else throw Error(e?.result?.error||e?.message||"Unknown error")}catch(e){e instanceof Error?eH.f.error("Error testing connection: "+(0,eo.I)(e.message,100)):eH.f.error("Error testing connection: "+String(e))}}},e9=async()=>{try{if(k(!0),!l)return;await (0,em.o2)(l,e),eH.f.success("Model deleted successfully"),m&&m({deleted:!0,model_info:{id:e}}),a()}catch(e){console.error("Error deleting the model:",e),eH.f.fromError("Failed to delete model")}finally{k(!1),v(!1)}},te=async(e,t)=>{await (0,es.W)(e)&&(G(e=>({...e,[t]:!0})),setTimeout(()=>{G(e=>({...e,[t]:!1}))},2e3))},tt=eV.litellm_model_name.includes("*"),ts=eV.litellm_model_name.split("/")[0],ta=eq?.data?.filter(e=>e.providers?.includes(ts)&&e.model_group!==eV.litellm_model_name).map(e=>({value:e.model_group,label:e.model_group}))||[];return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-6",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)(g.K,{variant:"ghost",onClick:a,className:"mb-4",children:[(0,t.jsx)(Q.f,{className:"size-4"}),"Back to Models"]}),(0,t.jsxs)("h2",{className:"text-xl font-semibold",children:["Public Model Name: ",sf(eV)]}),(0,t.jsxs)("div",{className:"flex items-center cursor-pointer",children:[(0,t.jsx)("span",{className:"text-sm text-muted-foreground font-mono",children:eV.model_info.id}),(0,t.jsx)(g.K,{variant:"ghost",size:"icon-xs","aria-label":"Copy model ID",onClick:()=>te(eV.model_info.id,"model-id"),className:`left-2 z-raised transition-all duration-200 ${$["model-id"]?"text-success bg-success/10 border-success/20":"text-muted-foreground hover:text-foreground hover:bg-muted"}`,children:$["model-id"]?(0,t.jsx)(Z.f,{size:12}):(0,t.jsx)(ee.f,{size:12})})]})]}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(!e1||e4)&&(0,t.jsxs)(g.K,{variant:"outline",onClick:e8,className:"flex items-center gap-2","data-testid":"test-connection-button",children:[(0,t.jsx)(S.f,{className:"h-4 w-4"}),"Test Connection"]}),!e1&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(g.K,{variant:"outline",onClick:()=>L(!0),className:"flex items-center",disabled:!eX,"data-testid":"update-api-key-button",children:[(0,t.jsx)(C,{className:"h-4 w-4"}),"Update API Key"]}),(0,t.jsxs)(g.K,{variant:"outline",onClick:()=>I(!0),className:"flex items-center",disabled:!eW,"data-testid":"reuse-credentials-button",children:[(0,t.jsx)(C,{className:"h-4 w-4"}),"Re-use Credentials"]})]}),(0,t.jsxs)(g.K,{variant:"destructive",onClick:()=>v(!0),className:"flex items-center",disabled:!eX,"data-testid":"delete-model-button",children:[(0,t.jsx)(M.f,{className:"h-4 w-4"}),e2]})]})]}),(0,t.jsxs)(T.i,{defaultValue:"overview",children:[(0,t.jsxs)(T.U,{variant:"line",className:"mb-6 h-auto w-full justify-start rounded-none border-b p-0",children:[(0,t.jsx)(T.k,{value:"overview",className:"flex-none rounded-none px-4 py-2",children:"Overview"}),(0,t.jsx)(T.k,{value:"raw",className:"flex-none rounded-none px-4 py-2",children:"Raw JSON"})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(T.S,{value:"overview",keepMounted:!0,children:[(0,t.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mb-6",children:[(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsx)("p",{className:"text-sm",children:"Provider"}),(0,t.jsxs)("div",{className:"mt-2 flex items-center space-x-2",children:[eV.provider&&(0,t.jsx)(tT.f,{provider:eV.provider,className:"w-4 h-4"}),(0,t.jsx)("h3",{className:"text-lg font-medium",children:eV.provider||"Not Set"})]})]}),(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsx)("p",{className:"text-sm",children:"LiteLLM Model"}),(0,t.jsx)("div",{className:"mt-2 overflow-hidden",children:(0,t.jsx)(A.x,{content:eV.litellm_model_name||"Not Set",className:"w-full min-w-0",children:(0,t.jsx)("div",{className:"break-all text-sm font-medium leading-relaxed cursor-pointer",children:eV.litellm_model_name||"Not Set"})})})]}),(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsx)("p",{className:"text-sm",children:"Pricing"}),(0,t.jsx)(tP,{model:eV})]})]}),(0,t.jsxs)("div",{className:"mb-6 text-sm text-muted-foreground flex items-center gap-x-6",children:[(0,t.jsxs)("div",{className:"flex items-center gap-x-2",children:[(0,t.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})}),"Created At"," ",eV.model_info.created_at?new Date(eV.model_info.created_at).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}):"Not Set"]}),(0,t.jsxs)("div",{className:"flex items-center gap-x-2",children:[(0,t.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"})}),"Created By ",eV.model_info.created_by||"Not Set"]})]}),eV?.litellm_params?.kubernetes_pod_discovery===!0&&(0,c.v)(o??"")&&(0,t.jsx)("div",{className:"mb-6",children:(0,t.jsx)(sg,{modelId:e})}),(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Model Settings"}),(0,t.jsxs)("div",{className:"flex gap-2",children:[e0&&eQ&&!F&&(0,t.jsx)(g.K,{onClick:()=>W(!0),className:"flex items-center",children:"Edit Auto Router"}),eX?!F&&(0,t.jsx)(g.K,{onClick:()=>K(!0),className:"flex items-center",children:"Edit Settings"}):(0,t.jsx)(A.x,{content:"Only DB models can be edited. You must be an admin or the creator of the model to edit it.",children:(0,t.jsx)(et.f,{className:"size-4 text-muted-foreground"})})]})]}),x?(0,t.jsx)(sp,{localModelData:x,modelData:eV,teamAlias:eU(x.model_info?.team_id),accessToken:l,isEditing:F,isSaving:R,isWildcardModel:tt,ptuCostAttributionEnabled:eK,showCacheControl:U,setShowCacheControl:B,onCancel:()=>K(!1),onSubmit:e7,modelAccessGroups:h,guardrailsList:eN,tagsList:eS,credentialsList:eI,healthCheckModelOptions:ta,teams:eZ},x.model_info?.id):(0,t.jsx)("p",{className:"text-sm",children:"Loading..."})]})]}),(0,t.jsx)(T.S,{value:"raw",keepMounted:!0,children:(0,t.jsx)(E.N,{className:"block p-6",children:(0,t.jsx)("pre",{className:"bg-muted p-4 rounded-sm text-xs overflow-auto",children:JSON.stringify(eG,null,2)})})})]})]}),(0,t.jsx)(eA.f,{isOpen:j,title:e2,alertMessage:"This action cannot be undone.",message:`Are you sure you want to delete this ${e1?"auto-router":"model"}?`,resourceInformationTitle:"Model Information",resourceInformation:[{label:"Model Name",value:eV?.model_name||"Not Set"},{label:"LiteLLM Model Name",value:eV?.litellm_model_name||"Not Set"},{label:"Provider",value:eV?.provider||"Not Set"},{label:"Created By",value:eV?.model_info?.created_by||"Not Set"}],onCancel:()=>v(!1),onOk:e9,confirmLoading:N}),P&&!e5?(0,t.jsx)(tk,{isVisible:P,onCancel:()=>I(!1),onAddCredential:e3,existingCredential:D,setIsCredentialModalOpen:I}):(0,t.jsx)(eh.N,{open:P,onOpenChange:e=>!e&&I(!1),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Using Existing Credential"})}),(0,t.jsx)(tS,{className:"text-sm",credentialName:eV.litellm_params.litellm_credential_name??"",label:(0,tw.N)(eI).get(eV.litellm_params.litellm_credential_name??"")}),(0,t.jsx)(eh.c,{children:(0,t.jsx)(g.K,{variant:"outline",onClick:()=>I(!1),children:"Cancel"})})]})}),O&&l&&(0,t.jsx)(tF,{open:O,onCancel:()=>L(!1),accessToken:l,modelId:e,onUpdated:()=>{f.invalidateQueries({queryKey:["models","list"]})}}),(0,t.jsx)(ty,{isVisible:H,onCancel:()=>W(!1),onSuccess:e=>{_(e),m&&m(e)},modelData:x||eV,accessToken:l||"",userRole:o||"",isMemberManaged:!eX}),(0,t.jsx)(eh.N,{open:ea,onOpenChange:e=>!e&&er(!1),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[700px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Connection Test Results"})}),ea&&l&&(0,t.jsx)(ep,{accessToken:l,targets:eu,jevRequest:((e,t,s)=>{if(!t)return;let a="string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return}})():e,l=ex.z.object({classifier_type:e_.z.enum(["jev","oss_classifier"]),tiers:eg.z.record(ej.z.string(),ev.z.unknown()),jev_classifier_config:eb.j.optional(),opensource_classifier_config:eb.j.optional()}).loose().safeParse(a);if(!l.success)return;let{jev_classifier_config:r,opensource_classifier_config:i,...n}=l.data,o=(0,eb.E)({...n,jev_classifier_config:r,opensource_classifier_config:i});return{prompt:ey,complexity_router_config:{...n,classifier_type:"oss_classifier",opensource_classifier_config:(0,eb.L)(o.jev_classifier_config)},saved_model_id:t,...s&&{team_id:s}}})((x??eV)?.litellm_params?.complexity_router_config,(x??eV)?.model_info?.id,(x??eV)?.model_info?.team_id)},ed),(0,t.jsx)(eh.c,{children:(0,t.jsx)(g.K,{variant:"outline",onClick:()=>er(!1),children:"Close"})})]})})]})}var sv=e.i(56567);function sb(){let[{model:e,team:t},a]=(0,l.i)({model:l.d,team:l.d},{history:"push"}),r=(0,s.useCallback)(e=>{a({model:e,team:null})},[a]);return{modelId:e,teamId:t,openModel:r,openTeam:(0,s.useCallback)(e=>{a({model:null,team:e})},[a]),close:(0,s.useCallback)(()=>{a({model:null,team:null})},[a])}}function sy(){let{data:e,isLoading:t}=(0,y.e)(),a=(0,s.useMemo)(()=>Array.from(new Set(e?.data?.map(e=>e.model_name)??[])).sort(),[e?.data]);return{availableModelGroups:a,availableModelAccessGroups:(0,s.useMemo)(()=>Array.from(new Set(e?.data?.flatMap(e=>e.model_info?.access_groups??[])??[])),[e?.data]),allModelsOnProxy:(0,s.useMemo)(()=>e?.data?.map(e=>e.model_name)??[],[e?.data]),isLoading:t}}var sN=e.i(243652);let sk=(0,sN.f)("credentials"),sw=({enabled:e=!0}={})=>{let{accessToken:t}=(0,i.f)();return(0,eP.f)({queryKey:sk.list({}),queryFn:async()=>await (0,em.lg)(t),enabled:e&&!!t})};var sC=e.i(153472),sS=e.i(954616);let sM=async(e,t)=>{let s=(0,em._h)(),a=s?`${s}/config/field/update`:"/config/field/update",l=await fetch(a,{method:"POST",headers:{[(0,em.kR)()]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({field_name:"store_model_in_db",field_value:t.store_model_in_db,config_type:"general_settings"})});if(!l.ok){let e=await l.json().catch(()=>({}));throw Error(e?.error?.message||e?.message||e?.detail||"Failed to update model storage settings")}return await l.json()};var sE=e.i(190702),sT=e.i(302747);let sA=({isVisible:e,onCancel:a,onSuccess:l})=>{let r,{mutateAsync:n,isPending:o}=(()=>{let{accessToken:e}=(0,i.f)();return(0,sS.f)({mutationFn:async t=>{if(!e)throw Error("Access token is required");return await sM(e,t)}})})(),{data:d,isLoading:c,refetch:u}=(0,sC._)(sC.e.GENERAL_SETTINGS);(0,s.useEffect)(()=>{e&&u()},[e,u]);let m=(0,s.useMemo)(()=>{if(!d)return{store_model_in_db:!1};let e=d.find(e=>"store_model_in_db"===e.field_name);return{store_model_in_db:e?.field_value??!1}},[d]),h=(0,tD.G)({defaultValues:m,values:m}),p=async e=>{try{await n(e,{onSuccess:()=>{eH.f.success("Model storage settings updated successfully"),u(),l?.()},onError:e=>{eH.f.fromError("Failed to save model storage settings: "+(0,sE.f)(e))}})}catch(e){eH.f.fromError("Failed to save model storage settings: "+(0,sE.f)(e))}},f=()=>{h.reset(m),a()};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&f(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{className:"text-base",children:"Model Settings"})}),(0,t.jsx)(A.g,{children:(0,t.jsx)("form",{onSubmit:e=>e.preventDefault(),children:(0,t.jsx)(eJ.e,{children:(0,t.jsx)(eY.f,{control:h.control,name:"store_model_in_db",label:(r=d?.find(e=>"store_model_in_db"===e.field_name)?.field_description||"If enabled, models and config are stored in and loaded from the database.",(0,t.jsxs)(t.Fragment,{children:["Store Model in DB",(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)(e6.f,{className:"size-3.5 shrink-0 cursor-help text-muted-foreground"})}),(0,t.jsx)(A.Y,{children:r})]})]})),children:({id:e,value:s,onChange:a,onBlur:l})=>c?(0,t.jsx)(sT.f,{role:"status","aria-label":"Loading model settings",className:"h-[18.4px] w-8 rounded-full"}):(0,t.jsx)(tY.f,{id:e,checked:!!s,onCheckedChange:a,onBlur:l,className:"w-fit"})})})})}),(0,t.jsxs)(eh.c,{children:[(0,t.jsx)(g.K,{variant:"outline",onClick:f,disabled:o||c,children:"Cancel"}),(0,t.jsx)(g.K,{disabled:o||c,"aria-busy":o,onClick:()=>void h.handleSubmit(p)(),children:o?"Saving...":"Save Settings"})]})]})})};var sP=e.i(655063),sI=e.i(682830);let sz="model_info_blocked";var sO=e.i(555436),sL=e.i(239616);e.i(707701);var sR=e.i(807235),sq=e.i(981080),sF=e.i(531649),sK=e.i(554134),sD=e.i(174886),sV=e.i(531278),sU=e.i(788699),sB=e.i(418371),s$=e.i(494862);e.i(622826);var sG=e.i(581070),sH=e.i(200208),sW=e.i(399536),sJ=e.i(112179),sY=e.i(436589);let sX="model_name",sQ="model_info_created_by",sZ="model_info_updated_at",s0="input_cost",s1="model_info_access_groups",s2="model_info_db_model",s4=[sX,sQ,sZ,s0,s2],s5={[s0]:"costs",[s2]:"status",[sQ]:"created_at",[sZ]:"updated_at"};function s6({model:e,displayName:s}){let a=e.litellm_model_name||"-";return(0,t.jsxs)(sY.c,{children:[(0,t.jsxs)(sY.b,{render:(0,t.jsx)("div",{className:"flex min-w-0 items-center gap-2.5","data-testid":`model-information-${e.model_info.id}`}),children:[e.provider?(0,t.jsx)(sB.f,{provider:e.provider,className:"size-6 shrink-0"}):(0,t.jsx)("span",{className:"flex size-6 shrink-0 items-center justify-center rounded-md bg-muted text-xs text-muted-foreground",children:"-"}),(0,t.jsxs)("span",{className:"flex min-w-0 flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"max-w-60 truncate text-sm font-medium text-foreground",title:s,children:s}),(0,t.jsx)("span",{className:"max-w-60 truncate font-mono text-xs text-muted-foreground",title:a,children:a})]})]}),(0,t.jsx)(sY.P,{align:"start",className:"w-80",children:(0,t.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[e.provider?(0,t.jsx)(sB.f,{provider:e.provider,className:"size-4 shrink-0"}):null,(0,t.jsx)("span",{className:"truncate text-xs text-muted-foreground",children:e.provider||"Unknown provider"})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"Public Model Name"}),(0,t.jsx)("span",{className:"truncate text-sm font-medium text-foreground",title:s,children:s})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"LiteLLM Model Name"}),(0,t.jsxs)("span",{className:"flex min-w-0 items-center gap-1.5",children:[(0,t.jsx)("span",{className:"truncate font-mono text-sm text-foreground",title:a,children:a}),(0,t.jsx)("button",{type:"button","aria-label":"Copy LiteLLM model name","data-testid":`copy-litellm-model-name-${e.model_info.id}`,className:"shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",onClick:()=>void(0,es.W)(a,"LiteLLM model name copied"),children:(0,t.jsx)(sD.f,{className:"size-3.5"})})]})]})]})})]})}function s3(){return(0,t.jsxs)("span",{className:"flex items-center gap-1",children:["Credentials",(0,t.jsxs)(sY.c,{children:[(0,t.jsx)(sY.b,{render:(0,t.jsx)("button",{type:"button","aria-label":"About credential types","data-testid":"credentials-header-info",className:"cursor-pointer text-muted-foreground hover:text-foreground"}),children:(0,t.jsx)(et.f,{className:"size-3.5"})}),(0,t.jsx)(sY.P,{align:"start",className:"w-80",children:(0,t.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,t.jsx)("span",{className:"text-sm font-medium text-foreground",children:"Credential types"}),(0,t.jsxs)("div",{className:"flex flex-col gap-1",children:[(0,t.jsxs)("span",{className:"flex items-center gap-1.5 text-sm font-medium text-info",children:[(0,t.jsx)(a.f,{className:"size-3.5"}),"Reusable"]}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"Credentials saved in LiteLLM that can be added to models repeatedly."})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-1",children:[(0,t.jsxs)("span",{className:"flex items-center gap-1.5 text-sm font-medium text-foreground",children:[(0,t.jsx)(sU.f,{className:"size-3.5"}),"Manual"]}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"Credentials added directly during model creation or defined in the config file."})]})]})})]})]})}function s7({credentialName:e,label:s}){return e?(0,t.jsx)(tS,{credentialName:e,label:s,icon:(0,t.jsx)(a.f,{className:"size-3 shrink-0"}),className:"text-xs font-medium text-info"}):(0,t.jsxs)(e8.f,{variant:"outline",className:"gap-1 font-normal text-muted-foreground",children:[(0,t.jsx)(sU.f,{className:"size-3"}),"Manual"]})}function s8({model:e}){let s=!e.model_info?.db_model,a=(e=>{if(!e)return null;let t=new Date(e);return Number.isNaN(t.getTime())?null:(0,sH.y)(t,"date")})(e.model_info.created_at),l=s?"Defined in config":e.model_info.created_by||"Unknown";return(0,t.jsxs)("div",{className:"flex min-w-0 flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"max-w-44 truncate text-sm text-foreground",title:l,children:l}),(0,t.jsx)("span",{className:"truncate text-xs text-muted-foreground",children:s?"-":a??"Unknown date"})]})}function s9({label:e,value:s}){return(0,t.jsxs)("span",{className:"flex items-baseline gap-1.5",children:[(0,t.jsx)("span",{className:"text-[10px] font-semibold tracking-wider text-muted-foreground",children:e}),(0,t.jsx)("span",{className:"text-xs font-medium tabular-nums text-foreground",children:s})]})}function ae({model:e}){let{input_cost:s,output_cost:a,output_cost_per_second:l}=e,r=null!=l,i=null!=s&&(!r||Number(s)>0),n=null!=a&&(!r||Number(a)>0);return i||n||r?(0,t.jsx)(sG.f,{content:r?"Cost per 1M tokens; /s is cost per second of output":"Cost per 1M tokens",trigger:(0,t.jsxs)("div",{className:"flex flex-col gap-0.5 whitespace-nowrap",children:[i&&(0,t.jsx)(s9,{label:"IN",value:`$${s}`}),n&&(0,t.jsx)(s9,{label:"OUT",value:`$${a}`}),r&&(0,t.jsx)(s9,{label:"OUT",value:(0,es.b)(l)})]})}):(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"})}function at({accessGroups:e}){if(!e||0===e.length)return(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"});let[s,...a]=e;return(0,t.jsxs)("div",{className:"flex min-w-0 items-center gap-1",children:[(0,t.jsx)(e8.f,{variant:"outline",className:"max-w-36 truncate border-info/20 bg-info/10 font-normal text-info",children:s}),a.length>0&&(0,t.jsx)(sG.f,{content:(0,t.jsx)("div",{className:"flex max-w-[280px] flex-col gap-0.5",children:a.map(e=>(0,t.jsx)("span",{children:e},e))}),trigger:(0,t.jsxs)(e8.f,{variant:"outline",className:"shrink-0 cursor-default font-normal",children:["+",a.length," more"]})})]})}function as({model:e,userRole:s,userID:a,isViewOnly:l,isPausing:r,onDeleteClick:i,onTogglePauseClick:n}){let o=e.model_info?.id,d=!e.model_info?.db_model,c="Admin"===s&&!l,u=!l&&(c||e.model_info?.created_by===a),m=e.model_info?.blocked===!0,h=!d&&c&&!!n;return(0,t.jsxs)("div",{className:"flex items-center justify-end gap-1.5",children:[(0,t.jsx)("span",{className:"flex w-8 shrink-0 items-center justify-center",children:r?(0,t.jsx)(sV.f,{className:"size-4 animate-spin text-muted-foreground","data-testid":`model-pause-pending-${o}`}):(0,t.jsx)(sG.f,{content:d?"Config models cannot be paused from the dashboard. Pause is DB-backed.":c?m?"Resume model — restore normal routing.":"Pause model — stop routing requests until resumed.":"Only proxy admins can pause or resume a model.",trigger:(0,t.jsx)("span",{className:"inline-flex",children:(0,t.jsx)(tY.f,{size:"sm",checked:!m,disabled:!h,"aria-label":m?"Resume model":"Pause model","data-testid":`model-pause-toggle-${o}`,onCheckedChange:e=>{h&&n&&o&&n(o,!e)}})})})}),(0,t.jsx)(sG.f,{content:d?"Config model cannot be deleted on the dashboard. Please delete it from the config file.":"Delete model",trigger:(0,t.jsx)("span",{className:"inline-flex",children:(0,t.jsx)(g.K,{variant:"ghost",size:"icon-sm","aria-label":"Delete model","data-testid":`model-delete-${o}`,disabled:d||!u,className:"text-muted-foreground hover:bg-destructive/10 hover:text-destructive",onClick:()=>{i&&o&&i(o)},children:(0,t.jsx)(e7.f,{className:"size-4"})})})})]})}let aa="personal",al="wildcard",ar="All Proxy Models",ai={[sX]:"Public Model Name",[s1]:"Model Access Group",[sz]:"Status"},an={all:"All",active:"Active",paused:"Paused"},ao={current_team:"Current Team Models",all:ar};function ad(){return(0,t.jsxs)("div",{className:"flex flex-col items-center gap-1 py-6",children:[(0,t.jsx)("div",{className:"mb-1 flex size-11 items-center justify-center rounded-xl bg-muted",children:(0,t.jsx)(sO.f,{className:"size-5 text-muted-foreground"})}),(0,t.jsx)("div",{className:"text-base font-semibold text-foreground",children:"No models found"}),(0,t.jsx)("div",{className:"max-w-80 text-sm text-muted-foreground",children:"No models match your search or filters. Try resetting them."})]})}function ac({data:e,rowCount:a,isLoading:l,isRefreshing:r,onRefresh:i,sorting:n,onSortingChange:o,pagination:d,onPaginationChange:c,columnFilters:u,onColumnFiltersChange:m,onResetFilters:h,searchValue:p,onSearchChange:f,teamOptions:x,selectedTeamValue:_,onTeamChange:j,isLoadingTeams:v,viewMode:b,onViewModeChange:y,onOpenModelSettings:N,availableModelGroups:k,availableModelAccessGroups:w,userRole:C,userID:S,isViewOnly:M,onModelIdClick:E,onTeamIdClick:T,onDeleteClick:A,onTogglePauseClick:P,pausingModelId:I,credentialLabels:z}){let[O,L]=(0,s.useState)(!1),R=(0,s.useMemo)(()=>(({userRole:e,userID:s,isViewOnly:a,onModelIdClick:l,onTeamIdClick:r,onDeleteClick:i,onTogglePauseClick:n,pausingModelId:o,credentialLabels:d})=>[{id:"model_info_id",accessorFn:e=>e.model_info.id,meta:{title:"Model ID"},header:"Model ID",enableSorting:!1,size:140,minSize:90,cell:({row:e})=>(0,t.jsx)(sW.f,{value:e.original.model_info.id,onClick:l,dataTestId:`model-id-${e.original.model_info.id}`})},{id:sX,accessorFn:e=>e.model_name??"",meta:{title:"Model Information",skeleton:"twoLine"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Model Information"}),enableSorting:!0,size:280,minSize:160,cell:({row:e})=>(0,t.jsx)(s6,{model:e.original,displayName:sf(e.original)||"-"})},{id:"litellm_credential_name",accessorFn:e=>e.litellm_params?.litellm_credential_name??"",meta:{title:"Credentials"},header:()=>(0,t.jsx)(s3,{}),enableSorting:!1,size:180,minSize:110,cell:({row:e})=>{let s=e.original.litellm_params?.litellm_credential_name;return(0,t.jsx)(s7,{credentialName:s,label:s?d?.get(s):void 0})}},{id:sQ,accessorFn:e=>e.model_info.created_by??"",meta:{title:"Created By",skeleton:"twoLine"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Created By"}),enableSorting:!0,size:180,minSize:110,cell:({row:e})=>(0,t.jsx)(s8,{model:e.original})},{id:sZ,accessorFn:e=>e.model_info.updated_at??"",meta:{title:"Updated At"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Updated At"}),enableSorting:!0,size:140,minSize:100,cell:({row:e})=>(0,t.jsx)(sH.S,{value:e.original.model_info.updated_at,precision:"date"})},{id:s0,accessorFn:e=>e.input_cost,meta:{title:"Costs",numeric:!0},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Costs"}),enableSorting:!0,size:130,minSize:90,cell:({row:e})=>(0,t.jsx)(ae,{model:e.original})},{id:"model_info_team_id",accessorFn:e=>e.model_info.team_id??"",meta:{title:"Team ID"},header:"Team ID",enableSorting:!1,size:140,minSize:90,cell:({row:e})=>(0,t.jsx)(sW.f,{value:e.original.model_info.team_id,onClick:r,dataTestId:`model-team-id-${e.original.model_info.id}`})},{id:s1,accessorFn:e=>e.model_info.access_groups??[],meta:{title:"Model Access Group",skeleton:"chips"},header:"Model Access Group",enableSorting:!1,size:200,minSize:120,cell:({row:e})=>(0,t.jsx)(at,{accessGroups:e.original.model_info.access_groups})},{id:s2,accessorFn:e=>e.model_info.db_model,meta:{title:"Source",skeleton:"badge"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Source"}),enableSorting:!0,size:140,minSize:100,cell:({row:e})=>e.original.model_info.db_model?(0,t.jsx)(sJ.f,{tone:"info",label:"DB Model"}):(0,t.jsx)(sJ.f,{tone:"neutral",label:"Config Model"})},{id:"actions",meta:{title:"Actions",className:"text-right",headerClassName:"text-right"},header:"Actions",enableSorting:!1,enableHiding:!1,enableResizing:!1,size:110,minSize:110,cell:({row:l})=>(0,t.jsx)(as,{model:l.original,userRole:e,userID:s,isViewOnly:a,isPausing:o===l.original.model_info?.id,onDeleteClick:i,onTogglePauseClick:n})}])({userRole:C,userID:S,isViewOnly:M,onModelIdClick:E,onTeamIdClick:T,onDeleteClick:A,onTogglePauseClick:P,pausingModelId:I,credentialLabels:z}),[C,S,M,E,T,A,P,I,z]),q=(0,s.useMemo)(()=>[{label:ar,value:"all"},{label:"Wildcard Models (*)",value:al},...k.map(e=>({label:e,value:e}))],[k]),F=(0,s.useMemo)(()=>[{label:"All Model Access Groups",value:"all"},...w.map(e=>({label:e,value:e}))],[w]),K=(e,t)=>{let s=String(t);return e===sX&&s===al?"Wildcard Models (*)":e===sz?an[s]??s:s},D=x.find(e=>e.value===_)?.label??x[0]?.label??"";return(0,t.jsx)(sR.f,{data:e,columns:R,getRowId:(e,t)=>e.model_info?.id??String(t),sortingMode:"server",sorting:n,onSortingChange:o,enableSortingRemoval:!0,paginationMode:"server",pagination:d,onPaginationChange:c,rowCount:a,pageSizeOptions:[10,25,50],filterMode:"server",columnFilters:u,onColumnFiltersChange:m,defaultColumnVisibility:{[s2]:!1},enableColumnResizing:!0,maxBodyHeight:600,isLoading:l,loadingMessage:"Loading models…",noDataMessage:(0,t.jsx)(ad,{}),size:"compact",toolbar:e=>(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(sF.f,{table:e,searchValue:p,onSearchChange:f,searchPlaceholder:"Search model names…",onOpenFilters:()=>L(!0),onRefresh:i,isRefreshing:r,filterLabels:ai,formatFilterValue:K,children:[(0,t.jsxs)(tJ.d,{value:_,onValueChange:e=>j(String(e)),children:[(0,t.jsxs)(tJ.P,{size:"sm","aria-label":"Current team","data-testid":"models-team-select",className:"gap-2 bg-secondary",children:[(0,t.jsx)("span",{className:(0,tC.c)("size-2 shrink-0 rounded-full",_===aa?"bg-info":"bg-success")}),(0,t.jsx)("span",{className:"text-muted-foreground",children:"Team"}),(0,t.jsx)("span",{className:"truncate font-semibold",children:D})]}),(0,t.jsx)(tJ.r,{children:x.map(e=>(0,t.jsx)(tJ.T,{value:e.value,disabled:v,className:"[&>div]:min-w-0",children:(0,t.jsx)("span",{"data-slot":"select-item-label",className:"min-w-0 truncate",title:e.label,children:e.label})},e.value))})]}),(0,t.jsxs)(tJ.d,{value:b,onValueChange:e=>y(e),children:[(0,t.jsxs)(tJ.P,{size:"sm","aria-label":"View","data-testid":"models-view-select",className:"gap-2",children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"View"}),(0,t.jsx)("span",{className:"truncate",children:ao[b]})]}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:"current_team",children:ao.current_team}),(0,t.jsx)(tJ.T,{value:"all",children:ao.all})]})]}),(0,t.jsx)(sK.f,{className:"mx-0.5"}),(0,t.jsx)(g.K,{variant:"outline",size:"icon-sm","aria-label":"Model Settings",title:"Model Settings","data-testid":"models-settings-trigger",onClick:N,children:(0,t.jsx)(sL.f,{})})]}),(0,t.jsx)(sq.q,{table:e,open:O,onOpenChange:L,title:"Filters",description:"Narrow down models + endpoints",resetLabel:"Reset Filters",onReset:h,children:({get:e,set:s})=>(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(sq.Q,{label:"Public Model Name",children:(0,t.jsx)(eI.f,{options:q,value:e(sX)??"all",onValueChange:e=>s(sX,"all"===e?void 0:e??void 0),placeholder:"Filter by Public Model Name",emptyText:"No models found"})}),(0,t.jsx)(sq.Q,{label:"Status",children:(0,t.jsxs)(tJ.d,{value:e(sz)??"all",onValueChange:e=>s(sz,"all"===e?void 0:e),children:[(0,t.jsx)(tJ.P,{"aria-label":"Filter by status",className:"w-full",children:an[e(sz)??"all"]??an.all}),(0,t.jsx)(tJ.r,{children:Object.keys(an).map(e=>(0,t.jsx)(tJ.T,{value:e,children:an[e]},e))})]})}),(0,t.jsx)(sq.Q,{label:"Model Access Group",children:(0,t.jsx)(eI.f,{options:F,value:e(s1)??"all",onValueChange:e=>s(s1,"all"===e?void 0:e??void 0),placeholder:"Filter by Model Access Group",emptyText:"No model access groups found"})})]})})]})})}let au=(e,t,s)=>(0,l.k)({parse:s=>{let a=l.w.parse(s);return null===a?null:Math.min(Math.max(a,e),t)},serialize:String}).withDefault(s),am={model_search:l.d.withDefault(""),view_mode:(0,l.b)(["current_team","all"]).withDefault("current_team"),filter_team:l.d.withDefault(aa),access_group:l.d.withDefault(""),status:l.d.withDefault(""),sort_by:(0,l.b)(s4),sort_order:(0,l.b)(["asc","desc"]).withDefault("asc"),page:au(1,1e5,1),page_size:au(1,100,50)},ah=({selectedModelGroup:e,setSelectedModelGroup:a,availableModelGroups:o,availableModelAccessGroups:d,setSelectedModelId:u,setSelectedTeamId:m})=>{let{data:h,isLoading:p}=(0,b.X)(),{accessToken:f,userId:x,userRole:g,isViewOnly:j}=(0,i.f)(),{data:v,isLoading:N}=(0,n.n)(),{data:k}=sw({enabled:(0,c.u)(g??"")}),C=(0,s.useMemo)(()=>(0,tw.N)(k?.credentials??[]),[k]),S=(0,r.d)(),[M,E]=(0,l.i)(am),T=M.model_search,[A]=(0,sP.f)(T,{wait:200}),P=M.view_mode,I=M.filter_team,z=M.access_group||null,O="active"===M.status||"paused"===M.status?M.status:null,L=null===O?void 0:"paused"===O,R=(0,s.useMemo)(()=>({pageIndex:M.page-1,pageSize:M.page_size}),[M.page,M.page_size]),q=(0,s.useMemo)(()=>M.sort_by?[{id:M.sort_by,desc:"desc"===M.sort_order}]:[],[M.sort_by,M.sort_order]),[F,K]=(0,s.useState)(!1),[D,V]=(0,s.useState)(null),[U,B]=(0,s.useState)(!1),[$,G]=(0,s.useState)(null),H=I===aa?void 0:I,W=e&&"all"!==e&&e!==al?e??void 0:void 0,J=z&&"all"!==z?z:void 0,Y=e===al,X=(0,s.useMemo)(()=>{if(0!==q.length){let e;return s5[e=q[0].id]??e}},[q]),Q=(0,s.useMemo)(()=>{if(0!==q.length)return q[0].desc?"desc":"asc"},[q]),{data:Z,isLoading:ee,isFetching:es,refetch:ea}=(0,y.e)(R.pageIndex+1,R.pageSize,A||void 0,void 0,H,X,Q,!0,W,J,Y,L),el=(0,s.useCallback)(e=>null!=h&&"object"==typeof h&&e in h?h[e].litellm_provider:"openai",[h]),er=(0,s.useMemo)(()=>Z?w(Z,el):{data:[]},[Z,el]),ei=(0,s.useMemo)(()=>[e&&"all"!==e?{id:sX,value:e}:null,z?{id:s1,value:z}:null,O?{id:sz,value:O}:null].filter(e=>null!==e),[e,z,O]),en=(0,s.useCallback)(e=>{E({model_search:e||null,page:null})},[E]),eo=(0,s.useCallback)(e=>{let t=(0,sI.b)(e,R);E({page:t.pageIndex+1,page_size:t.pageSize})},[R,E]),ed=(0,s.useMemo)(()=>[{value:aa,label:"Personal"},...(v??[]).filter(e=>e.team_id).map(e=>({value:e.team_id,label:e.team_alias?e.team_alias:e.team_id}))],[v]),ec=(0,s.useMemo)(()=>(v??[]).find(e=>e.team_id===I)??null,[v,I]),eu=(0,s.useMemo)(()=>D&&er?.data?er.data.find(e=>e.model_info.id===D):null,[D,er]),eh=async()=>{if(f&&D)try{B(!0),await (0,em.o2)(f,D),eH.f.success("Model deleted successfully"),S.invalidateQueries({queryKey:["models","list"]}),ea()}catch(e){console.error("Error deleting model:",e),eH.f.fromError(e)}finally{B(!1),V(null)}},ep=(0,s.useCallback)(async(e,t)=>{if(f)try{G(e),await (0,em.Gp)(f,{blocked:t},e),eH.f.success(t?"Model paused":"Model resumed"),S.invalidateQueries({queryKey:["models","list"]})}catch(e){console.error("Error toggling model pause state:",e),eH.f.fromError(e)}finally{G(null)}},[f,S]),ef=(0,s.useCallback)(()=>{ea()},[ea]),ex=(0,s.useCallback)(e=>{V(e)},[]),e_=(0,s.useCallback)(()=>{K(!0)},[]),eg=ec?.team_alias||ec?.team_id||"";return(0,t.jsxs)("div",{className:"w-full",children:[(0,t.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,t.jsx)(ac,{data:er.data,rowCount:Z?.total_count??0,isLoading:ee||p,isRefreshing:es,onRefresh:ef,sorting:q,onSortingChange:e=>{let t,s=(0,sI.b)(e,q)[0];E({sort_by:s&&(t=s.id,s4.includes(t))?s.id:null,sort_order:s?.desc?"desc":null,page:null})},pagination:R,onPaginationChange:eo,columnFilters:ei,onColumnFiltersChange:e=>{let t=(0,sI.b)(e,ei),s=t.find(e=>e.id===sX)?.value,l=t.find(e=>e.id===s1)?.value,r=t.find(e=>e.id===sz)?.value;a("string"==typeof s?s:"all"),E({access_group:"string"==typeof l?l:null,status:"string"==typeof r?r:null,page:null})},onResetFilters:()=>{a("all"),E(null)},searchValue:T,onSearchChange:en,teamOptions:ed,selectedTeamValue:I,onTeamChange:e=>{E({filter_team:e,page:null})},isLoadingTeams:N,viewMode:P,onViewModeChange:e=>{E({view_mode:e})},onOpenModelSettings:e_,availableModelGroups:o,availableModelAccessGroups:d,userRole:g,userID:x??"",isViewOnly:j,onModelIdClick:u,onTeamIdClick:m,onDeleteClick:ex,onTogglePauseClick:ep,pausingModelId:$,credentialLabels:C}),"current_team"===P&&(0,t.jsxs)("div",{className:"flex items-start gap-2 px-1 text-xs text-muted-foreground",children:[(0,t.jsx)(et.f,{className:"mt-0.5 size-3.5 shrink-0"}),I===aa?(0,t.jsxs)("span",{children:["To access these models, create a Virtual Key without selecting a team on the"," ",(0,t.jsx)("a",{href:(0,_.B)("api-keys"),className:"font-medium text-info hover:underline",children:"Virtual Keys page"}),"."]}):(0,t.jsxs)("span",{children:['To access these models, create a Virtual Key and select Team as "',eg,'" on the'," ",(0,t.jsx)("a",{href:(0,_.B)("api-keys"),className:"font-medium text-info hover:underline",children:"Virtual Keys page"}),"."]})]})]}),(0,t.jsx)(eA.f,{isOpen:!!D,title:"Delete Model",alertMessage:"This action cannot be undone.",message:"Are you sure you want to delete this model?",resourceInformationTitle:"Model Information",resourceInformation:eu?[{label:"Model Name",value:eu.model_name||"Not Set"},{label:"LiteLLM Model Name",value:eu.litellm_model_name||"Not Set"},{label:"Provider",value:eu.provider||"Not Set"},{label:"Created By",value:eu.model_info?.created_by||"Not Set"}]:[],onCancel:()=>V(null),onOk:eh,confirmLoading:U}),(0,t.jsx)(sA,{isVisible:F,onCancel:()=>K(!1),onSuccess:()=>K(!1)})]})};function ap(){let{modelGroup:e,setModelGroup:a}=function(){let[e,t]=(0,l.o)("model_group",l.d);return{modelGroup:e,setModelGroup:(0,s.useCallback)(e=>{t(e)},[t])}}(),{availableModelGroups:r,availableModelAccessGroups:i}=sy(),{openModel:n,openTeam:o}=sb();return(0,t.jsx)(ah,{selectedModelGroup:e,setSelectedModelGroup:e=>a("all"===e?null:e),availableModelGroups:r,availableModelAccessGroups:i,setSelectedModelId:n,setSelectedTeamId:o})}var af=e.i(112392);function ax({selectedPreset:e,presets:a,presetAvailability:l,onPresetChange:r,pending:i,unavailable:n,onRetry:o}){let d=s.default.useMemo(()=>a.map(e=>({preset:e,availability:l(e)})).sort((e,t)=>Number("available"===t.availability.kind)-Number("available"===e.availability.kind)),[a,l]),c=s.default.useMemo(()=>[...d.map(({preset:e})=>({value:e.key,label:e.label})),{value:"custom",label:"Start from scratch"}],[d]);return(0,t.jsx)("div",{className:"mb-4 w-full space-y-2",children:(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)(tJ.d,{items:c,value:e??null,onValueChange:e=>r(e??void 0),children:[(0,t.jsx)(tJ.P,{"aria-label":"Use a template","data-testid":"template-selector",className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Use a template"})}),(0,t.jsxs)(tJ.r,{className:"[&_[data-slot=select-item]>div]:min-w-0 [&_[data-slot=select-item]>div]:shrink [&_[data-slot=select-item]>div]:whitespace-normal [&_[data-slot=select-item]>div]:break-words",children:[d.map(({preset:e,availability:s})=>{let a=(e=>{switch(e.kind){case"available":return null;case"loading":return"Checking model availability...";case"unverifiable":return"Cannot verify these models are available";case"missing_models":return`Missing: ${e.models.join(", ")}`}})(s),l="missing_models"===s.kind?"text-destructive":"text-muted-foreground",r="available"===s.kind&&s.viaDeployments?"Matches your deployments":null;return(0,t.jsx)(tJ.T,{value:e.key,label:e.label,disabled:null!==a,title:a??e.description,children:(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"font-medium",children:e.label}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:e.description}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:"Replaces classifier and model choices"}),a&&(0,t.jsx)("div",{className:`text-xs mt-1 ${l}`,children:a}),r&&(0,t.jsx)("div",{className:"text-xs mt-1 text-success",children:r})]})},e.key)}),(0,t.jsx)(tJ.H,{className:"mx-0"}),(0,t.jsx)(tJ.T,{value:"custom",label:"Start from scratch",children:(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"font-medium",children:"Start from scratch"}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:"Clears tier models, switches to Heuristics, and resets routing settings"})]})})]})]}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground",children:"Replaces classifier and model choices"}),i&&(0,t.jsx)("div",{className:"text-xs mt-1 text-muted-foreground",children:"Loading templates..."}),n&&(0,t.jsxs)("div",{className:"text-xs mt-1 text-destructive",children:["Could not load templates, so only Start from scratch is shown."," ",(0,t.jsx)("button",{type:"button",className:"underline",onClick:o,children:"Retry"})]})]})})}var a_=e.i(663435);let ag=async(e,t,s,a)=>{try{let l={model_name:e.auto_router_name,litellm_params:{model:"auto_router/complexity_router",complexity_router_config:e.complexity_router_config,complexity_router_default_model:e.auto_router_default_model,...void 0===e.auto_router_routing_compression?{}:{auto_router_routing_compression:e.auto_router_routing_compression},...void 0===e.auto_router_model_compression?{}:{auto_router_model_compression:e.auto_router_model_compression}},model_info:{...e.team_id?{team_id:e.team_id}:{},...e.model_access_group?.length?{access_groups:e.model_access_group}:{}}};await (0,em.jO)(t,l),eH.f.success(`Successfully created Auto Router: ${e.auto_router_name}`),s(),a&&a()}catch(e){console.error("Failed to add auto router:",e),eH.f.fromError("Failed to add auto router: "+e)}};var aj=e.i(491115),av=e.i(240461);let ab=({accessToken:e,config:a,defaultModel:l,routerName:r,teamId:i})=>{let[n,o]=s.default.useState(""),[d,c]=s.default.useState({status:"idle"}),u=(0,ti.e)(a.heuristic_v2_success_threshold),m=async()=>{if(u)return;c({status:"running"});let t=eN({prompt:n,config:a,defaultModel:l,routerName:r,teamId:i}),s=await (0,em.b)(e,t);c("success"===s.status?{status:"done",result:s.result}:{status:"failed",error:s.error})};return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"Send a prompt through this router's classifier to see which model it would pick, and why. The prompt is only classified: nothing is sent to the model it routes to."}),(0,t.jsx)(tt.f,{value:n,onChange:e=>o(e.target.value),placeholder:"Paste a prompt an end user would send",rows:4,"data-testid":"auto-router-routing-test-prompt"}),(0,t.jsx)("div",{className:"flex justify-end",children:(0,t.jsx)(g.K,{onClick:m,disabled:0===n.trim().length||"running"===d.status||!!u,"data-testid":"auto-router-routing-test-send",children:"running"===d.status?"Routing...":"Send Test Prompt"})}),u&&(0,t.jsx)("p",{className:"text-sm text-destructive",children:u}),"failed"===d.status&&(0,t.jsxs)("div",{className:"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive","data-testid":"auto-router-routing-test-error",children:[(0,t.jsx)("p",{className:"font-medium",children:"Could not route this prompt"}),(0,t.jsx)("p",{children:d.error})]}),"done"===d.status&&(0,t.jsxs)("div",{"data-testid":"auto-router-routing-test-result",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 py-2 text-sm",children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Routed to"}),(0,t.jsx)(e8.f,{variant:"secondary","data-testid":"auto-router-routing-test-routed-model",children:d.result.routed_model}),!d.result.routed_model_configured&&(0,t.jsxs)("span",{className:"flex items-center gap-1 text-warning","data-testid":"auto-router-routing-test-unconfigured",children:[(0,t.jsx)(tI.f,{className:"size-3.5"}),"This proxy has no model group by that name"]})]}),(0,t.jsx)(av.U,{decision:d.result.routing_decision})]})]})};var ay=e.i(176754);let aN=(0,sN.f)("autoRouterPresets"),ak={claude:"Claude",openai:"OpenAI",gemini:"Gemini",grok:"Grok",glm:"GLM",deepseek:"DeepSeek"},aw={cheapest:"Cheapest",balanced:"Balanced",quality:"Best quality"},aC=(e,t)=>{let s=e.match(/[-.](\d{8})$/);return{version:(s?e.slice(0,-9):e).split(/[.-]/).map(Number),snapshot:t||s?Number((t??s[1]).replaceAll("-","")):Number.MAX_SAFE_INTEGER}},aS=e=>{let t=e.toLowerCase().split("/").at(-1).replace(/^(?:us|eu|apac|global|au|jp|us-gov)\./,"").replace(/^(?:anthropic|openai|zai|deepseek)\./,"").replace(/^databricks-/,"").replace(/@default$/,"").replace(/-v\d+(?::\d+)?$/,""),s=t.match(/^claude-(\d+(?:[.-]\d+)*)-(haiku|sonnet|opus)(?:[-@]([0-9]{8}))?$/),a=t.match(/^claude-(haiku|sonnet|opus)-(\d+(?:[.-]\d+)*)(?:@([0-9]+))?$/)??(s?[s[0],s[2],s[1],s[3]]:null);if(a)return{family:"claude",line:a[1],rank:["haiku","sonnet","opus"].indexOf(a[1]),...aC(a[2],a[3]),model:t};let l=t.match(/^gpt-(\d+(?:[.-]\d+)*)-(luna|terra|sol|astra)(?:-(\d{4}-\d{2}-\d{2}))?$/);if(l)return{family:"openai",line:l[2],rank:"terra"===l[2]?.5:["luna","sol","astra"].indexOf(l[2]),...aC(l[1],l[3]),model:t};let r=t.match(/^gemini-(\d+(?:[.-]\d+)*)-(flash-lite|flash|pro)(?:-preview)?$/);if(r)return{family:"gemini",line:r[2],rank:["flash-lite","flash","pro"].indexOf(r[2]),...aC(r[1]),model:t};let i=t.match(/^grok-(\d+(?:[.-]\d+)*?)(?:-(\d{4}))?$/);if(i)return{family:"grok",line:"grok",rank:2,...aC(i[1],i[2]),model:t};let n=t.match(/^glm-(\d+(?:[.-]\d+)*)(-flash)?$/);if(n)return{family:"glm",line:n[2]?"flash":"glm",rank:2*!n[2],...aC(n[1]),model:t};let o=t.match(/^deepseek-v(\d+(?:[.-]\d+)*)-(flash|pro)$/);return o?{family:"deepseek",line:o[2],rank:2*("flash"!==o[2]),...aC(o[1]),model:t}:null},aM=e=>aS(e.litellm_params?.model??"")??aS(e.model_info?.base_model??e.litellm_params?.base_model??""),aE=(e,t,s)=>{let a=e.litellm_params?.model??"",l=e.litellm_params?.custom_llm_provider||(a.includes("/")?a.split("/")[0]:t.providers?.join(", "))||(s?({claude:"anthropic",glm:"zai",openai:"openai",gemini:"gemini",grok:"xai",deepseek:"deepseek"})[s]:"");return l.startsWith("bedrock")?"Bedrock":({anthropic:"Anthropic",openai:"OpenAI",gemini:"Google AI",xai:"xAI",azure:"Azure",azure_ai:"Azure AI",databricks:"Databricks",github_copilot:"GitHub Copilot","vertex_ai-anthropic_models":"Vertex AI",vertex_ai:"Vertex AI",zai:"Z.ai",deepseek:"DeepSeek"})[l]??l},aT=(e,t)=>{var s,a;let l;return s=e.version,a=t.version,(void 0===(l=Array.from({length:Math.max(s.length,a.length)},(e,t)=>t).find(e=>(s[e]??0)!==(a[e]??0)))?0:(s[l]??0)-(a[l]??0))||e.snapshot-t.snapshot},aA=(e,t,s)=>{let a,l=(a=e.filter(e=>void 0!==e.family)).filter(e=>!a.some(t=>t.family===e.family&&t.line===e.line&&aT(t,e)>0)),[r,i]={cheapest:[0,1],quality:[1,2],balanced:[0,2]}[t],n=l.flatMap(e=>l.filter(t=>{let a="auto"===s||e.family===s||t.family===s,l=t.rank>e.rank,r=t.rank===e.rank&&t.family!==e.family;return(l||r)&&a}).map(t=>({everyday:e,hard:t}))),o=({everyday:e,hard:t})=>100*(e.family!==t.family)+10*(e.rank===t.rank)+Math.abs(e.rank-r)+Math.abs(t.rank-i),d=n.toSorted((e,t)=>o(e)-o(t)||e.everyday.name.localeCompare(t.everyday.name)||e.hard.name.localeCompare(t.hard.name))[0];if(!d)return null;let c=d.everyday.family!==d.hard.family,u=d.everyday.rank!==r||d.hard.rank!==i;return{...d,notice:(c?"A complete pair is unavailable in one family. Using two model families.":null)??(u?"Using the closest available pair in this family.":null)}},aP=e=>[e.model!==e.name?e.model:null,e.provider].filter(Boolean).join(" · ");function aI({customized:e,hasSuggestions:s,onReset:a,goal:l,family:r,models:i,everyday:n,hard:o,waitingForTeam:d,loading:c,error:u,notice:m,onGoalChange:h,onFamilyChange:p,onModelChange:f,onAdvanced:x,onRetry:_}){let j=!d&&!c,v=!j||u||s,b=n?.family&&n.family===o?.family?ak[n.family]:null,y=[{value:"auto",label:b?`Auto (${b})`:"Auto"},...Object.entries(ak).map(([e,t])=>({value:e,label:t}))];return(0,t.jsxs)("div",{className:"space-y-4",children:[v&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{children:"Optimize for"}),(0,t.jsx)("div",{className:"grid grid-cols-3 gap-2",role:"group","aria-label":"Routing goal",children:Object.entries(aw).map(([e,s])=>(0,t.jsx)(g.K,{type:"button",className:"w-full",variant:l===e?"default":"outline","aria-pressed":l===e,onClick:()=>h(e),children:s},e))})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{htmlFor:"auto-router-family",children:"Model family"}),(0,t.jsxs)(tJ.d,{items:y,value:r,onValueChange:e=>{("auto"===e||e&&e in ak)&&p(e)},children:[(0,t.jsx)(tJ.P,{id:"auto-router-family","aria-label":"Model family",className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:y.map(({value:e,label:s})=>(0,t.jsx)(tJ.T,{value:e,children:s},e))})]})]})]}),d&&(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"Select a team to see available models."}),!d&&c&&(0,t.jsxs)("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",role:"status",children:[(0,t.jsx)(eQ.f,{className:"size-4"}),"Loading deployed models"]}),j&&u&&(0,t.jsxs)("p",{role:"alert",className:"text-sm text-destructive",children:["Could not load deployed models."," ",(0,t.jsx)(g.K,{type:"button",variant:"link",onClick:_,children:"Retry"})]}),j&&!u&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,t.jsx)(ez.f,{children:"Chosen models"}),e&&s&&(0,t.jsx)(g.K,{type:"button",variant:"link",className:"h-auto p-0 text-xs",onClick:a,children:"Use suggested models"})]}),(0,t.jsx)("div",{className:"grid gap-3 sm:grid-cols-2",children:["everyday","hard"].map(e=>{let s="everyday"===e?n:o,a="everyday"===e?o:n,l=i.filter(e=>e.name!==a?.name),r=l.map(e=>({value:e.name,label:e.name})),d="everyday"===e?"Everyday":"Hard tasks";return(0,t.jsxs)("div",{className:"min-w-0 space-y-3 rounded-lg border bg-muted/20 p-4",children:[(0,t.jsxs)("div",{className:"space-y-1",children:[(0,t.jsx)(ez.f,{htmlFor:`auto-router-${e}`,children:d}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground",children:"everyday"===e?"Your cheaper model":"Your stronger model"})]}),(0,t.jsxs)(tJ.d,{items:r,value:s?.name??null,onValueChange:t=>{t&&f(e,t)},children:[(0,t.jsx)(tJ.P,{id:`auto-router-${e}`,"aria-label":`${d} model`,className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Select a deployed model"})}),(0,t.jsx)(tJ.r,{children:l.map(e=>(0,t.jsx)(tJ.T,{value:e.name,label:e.name,children:(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{children:e.name}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:aP(e)})]})},e.name))})]}),s&&(0,t.jsx)("p",{className:"break-words text-xs text-muted-foreground",children:aP(s)})]},e)})})]}),(!n||!o)&&(0,t.jsx)("p",{role:"status",className:"text-sm text-muted-foreground",children:i.length<2?"Two deployed models are needed. Add a model or use Advanced configuration.":"Choose two models to get started."}),m&&!e&&(0,t.jsx)("p",{role:"status",className:"text-xs text-muted-foreground",children:m})]}),(0,t.jsx)(g.K,{type:"button",variant:"link",className:"px-0",onClick:x,children:"Advanced configuration"})]})}let az=[],aO=(e,t,s,...a)=>{let[l,r=[]]=a;return(e.custom_tier_set?(0,tr.O)(e.custom_tier_set):(0,ti.w)(e.tier_labels))??((0,eF.K)(e.classifier_type)?(0,eF.J)(e):(0,ti.k)((0,tr.X)(e)))??(0,ti.C)(e.plan_mode_min_tier,(0,tr.X)(e))??(0,ti.f)(t,(0,tr.X)(e))??("jev"!==(0,tu.t)(e)||e.jev_classifier_config?.deployment_name?null:"Please select a decision model")??(0,ti.b)(e)??(0,ti.e)(e.heuristic_v2_success_threshold)??(0,ti._)(e.reminder_markers)??(0,ti.r)(e.classifier_type,e.classifier_plugin_timeout_ms)??("decides"===(0,tu.H)(e)?(0,tc.R)(e.custom_dimensions):null)??(0,ti.I)(e,r)??(0,ay.U)(s,l)},aL={auto_router_name:"auto-router",team_id:null,model_access_group:void 0},aR=({reason:e,children:s})=>null===e?s:(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:s}),(0,t.jsx)(A.Y,{children:e})]}),aq=({handleOk:e,accessToken:a,userRole:l,userId:r,createScope:i="unscoped-ok",teams:n=null})=>{let o,d,m,h="team-required"===i,p=(0,eZ.f)(ex.z.object({auto_router_name:ej.z.string().min(1,"Auto router name is required"),team_id:ej.z.string().nullable().refine(e=>!h||!!e,"Please select a team to continue"),model_access_group:eK.z.array(ej.z.string()).optional()}),{defaultValues:aL}),f=(0,tD.h)({control:p.control,name:"auto_router_name"}),x=(0,tD.h)({control:p.control,name:"team_id"}),_={userRole:l,userID:r??null,isViewOnly:!1},j=h&&!(0,u.d)(_,n,{teamId:x,isDbModel:!0}),[v,b]=(0,s.useState)([]),[N,k]=(0,s.useState)({tiers:{SIMPLE:[],MEDIUM:[],COMPLEX:[],REASONING:[]},classifier_type:"heuristic",classification_mode:"user_turn"}),[w,C]=(0,s.useState)(!1),[S,M]=(0,s.useState)(!1),[T,P]=(0,s.useState)("balanced"),[I,z]=(0,s.useState)("auto"),[O,L]=(0,s.useState)({}),[R,q]=(0,s.useState)([]),[F,K]=(0,s.useState)([]),[D,V]=(0,s.useState)(!1),[U,B]=(0,s.useState)(void 0),[$,G]=(0,s.useState)(tn.h),[H,W]=(0,s.useState)(aj.S),[J,Y]=(0,s.useState)(to.p),[X,Q]=(0,s.useState)(!1),[Z,ee]=(0,s.useState)(!1),[et,es]=(0,s.useState)(!1),[ea,el]=(0,s.useState)(void 0),[er,ei]=(0,s.useState)(!1),[en,eo]=(0,s.useState)(!1),[ed,ec]=(0,s.useState)(!1),[eu,ep]=(0,s.useState)(0),[e_,eg]=(0,s.useState)([]);(0,s.useEffect)(()=>{(async()=>{b((await (0,em.SL)(a,"","",!1,null,!0,!0)).data.map(e=>e.id))})()},[a]);let{data:ev,isLoading:ek,isError:eC,refetch:eS}=(0,eP.f)({queryKey:["availableModels","autoRouter",a,...h?[x]:[]],queryFn:()=>h?(0,e4.a)(a,x):(0,e4.X)(a),enabled:!!(a&&(!h||x))}),{data:eM,isLoading:eE,isError:eT,refetch:eA}=(0,eP.f)({queryKey:(0,y.Z)(r??"",l),queryFn:()=>(0,y.G)(a,r??"",l),enabled:!!a}),eI=ek||eE;(0,s.useEffect)(()=>{if(eM&&!p.getFieldState("auto_router_name").isDirty){var e;p.setValue("auto_router_name",["auto-router",...Array.from({length:(e=eM.flatMap(e=>e.model_name?[e.model_name]:[])).length+1},(e,t)=>`auto-router-${t+2}`)].find(t=>!e.includes(t)))}},[eM,p]);let ez=s.default.useMemo(()=>ev??[],[ev]),{data:eD,isPending:eV,isError:eU,refetch:eB}=(o={queryKey:aN.list({}),queryFn:async()=>(0,ay.m)(await (0,em.nA)()),staleTime:864e5,gcTime:864e5},(0,eP.f)(o)),e$=eD??az,eG=eC&&void 0===ev,e0=eG||eT&&void 0===eM,e2=c.G.includes(l),e5=s.default.useMemo(()=>(0,ay.J)(ez.map(e=>e.model_group),(0,ay.h)(eM??[])),[ez,eM]),e6=s.default.useMemo(()=>(0,ay.J)(ez.map(e=>e.model_group),[]),[ez]),e3=s.default.useMemo(()=>{let e;return e=eM??[],ez.flatMap(t=>{if(t.mode&&"chat"!==t.mode)return[];let s=e.filter(e=>e.model_name===t.model_group);if(s.some(y.a)||t.model_group.includes("*")||t.model_group.startsWith("auto_router/"))return[];let a=s.filter(e=>!e.model_info?.blocked);if(s.length>0&&0===a.length||a.some(e=>e.model_info?.mode&&"chat"!==e.model_info.mode)||a.some(e=>e.litellm_params?.model?.includes("*")))return[];let l=a.length>0?a.map(aM):[aS(t.model_group)],r=l[0],i=r&&l.every(e=>!!e&&e.family===r.family&&e.line===r.line&&0===aT(e,r))?r:void 0,n=a.length>0?a.map(e=>aE(e,t,i?.family)):[aE({},t,i?.family)];return[{...i,name:t.model_group,model:i?.model??t.model_group,provider:[...new Set(n)].toSorted().join(", ")}]}).toSorted((e,t)=>e.name.localeCompare(t.name))},[ez,eM]),e7=s.default.useMemo(()=>aA(e3,T,I),[e3,T,I]),e8=O.everyday?e3.find(e=>e.name===O.everyday):e7?.everyday,e9=O.hard?e3.find(e=>e.name===O.hard):e7?.hard,te=e8&&e9?{classifier_type:"heuristic",classification_mode:"user_turn",tiers:{SIMPLE:[d=e8.name],MEDIUM:[d],COMPLEX:[m=e9.name],REASONING:[m]}}:null,tt=w?N:te??{classifier_type:"heuristic",classification_mode:"user_turn",tiers:{SIMPLE:[],MEDIUM:[],COMPLEX:[],REASONING:[]}},ts=s.default.useCallback(e=>{if(eI)return{kind:"loading"};if(eG)return{kind:"unverifiable"};let t=(0,ay.u)(e,e5);return t.length>0?{kind:"missing_models",models:t}:{kind:"available",viaDeployments:(0,ay.u)(e,e6).length>0}},[eI,eG,e5,e6]),ta=e=>{ee(!1),k(e.complexityRouterConfig),q(e.customTechnicalKeywords),K(e.keywordTierRules),V(e.semanticMatchingEnabled),B(e.embeddingModel),G(e.matchThreshold),W(e.escalationKeywords)};w&&!S&&!eI&&te&&(M(!0),k(e=>!e.custom_tier_set&&!(0,eF.K)(e.classifier_type)&&(0,tr.X)(e).every(e=>0===e.models.length)?{...e,tiers:te.tiers}:e));let tl={tiers:Object.fromEntries((0,tr.X)(tt).map(e=>[(0,tr.P)(e),e.models])),classifierType:(0,tu.t)(tt),classifierLlmConfig:tt.classifier_llm_config,decisionDeploymentName:(0,eb.n)(tt.jev_classifier_config),semanticMatchingEnabled:D,embeddingModel:U,defaultModel:tt.default_model},td=aO(tt,F,tl,e6,ez),tc={...tm(tt),customTechnicalKeywords:R,keywordTierRules:F,semanticMatchingEnabled:D,embeddingModel:U,matchThreshold:$,escalationKeywords:H},th=(0,eL.v)(a,{team_id:h?x:void 0,complexity_router_config:null===td?{...(0,ti.j)(tc)}:null},!h||!!x),tp=w?null:eI?"Loading deployed models":e0?"Could not verify deployed models":e8&&e9&&e8.name!==e9.name?null:"Select two different deployed models",tf=w||!h||x?tp??td??th.saveBlockedReason:"Select a team to see available models.",tx="jev"===(0,tu.t)(tt)?{prompt:ey,config:(0,ti.j)(tc),defaultModel:(0,tr.H)(tt,tt.default_model),routerName:f,teamId:h?x??void 0:void 0}:void 0,t_=tx?eN(tx):void 0,tg=async t=>{let s,l=tf??aO(tt,F,tl,e6,ez)??(0,ti.q)({semanticMatchingEnabled:D,embeddingModel:U,keywordTierRules:F});if(l){Q(!0),eH.f.fromError(l);return}let r=(0,tr.H)(tt,tt.default_model),i=h?["auto_router_name","team_id"]:["auto_router_name"];if(!await p.trigger(i))return void eH.f.fromError("Please fill in all required fields");let n=(0,ti.j)(tc),o=await (0,em.Ms)(a,n,h?p.getValues("team_id")??void 0:void 0),d=(0,ti.c)(o);if(d){Q(!0),eH.f.fromError(d);return}let c={auto_router_name:t,...(s=p.getValues("team_id"),h&&s?{team_id:s}:{}),auto_router_default_model:r,model_type:"complexity_router",complexity_router_config:n,...j?{}:{model_access_group:p.getValues("model_access_group"),...(0,to.S)(J)}};await ag(c,a,()=>p.reset(aL),e)},tj=async()=>{if(et)return;let e=p.getValues("auto_router_name");if(!e){Q(!0),p.trigger("auto_router_name"),eH.f.fromError("Please enter an Auto Router Name");return}es(!0);try{await tg(e)}finally{es(!1)}},tv=(0,t.jsx)(tu.U,{creationFlow:!0,tierSetup:(0,t.jsx)(ax,{selectedPreset:ea,presets:e$,presetAvailability:ts,onPresetChange:e=>{if(M(!0),!e||"custom"===e){el(e),ta((0,ay.k)());return}let t=e$.find(t=>t.key===e);t&&"available"===ts(t).kind&&(el(e),ta((0,ay.D)(t.complexity_router_config,e5)))},pending:eV,unavailable:eU&&void 0===eD,onRetry:()=>void eB()}),editingTiers:Z,onEditingTiersChange:ee,modelInfo:ez,value:tt,onChange:k,customTechnicalKeywords:R,onCustomTechnicalKeywordsChange:q,keywordTierRules:F,onKeywordTierRulesChange:K,keywordRulesError:(0,ti.f)(F,(0,tr.X)(tt)),semanticMatchingEnabled:D,onSemanticMatchingEnabledChange:V,embeddingModel:U,onEmbeddingModelChange:B,matchThreshold:$,onMatchThresholdChange:G,escalationKeywords:H,onEscalationKeywordsChange:W,autoRouterCompression:J,onAutoRouterCompressionChange:j?void 0:Y,showValidationErrors:X});return(0,t.jsx)(eL.R.Provider,{value:th,children:(0,t.jsxs)(A.g,{children:[(0,t.jsx)(E.N,{children:(0,t.jsx)(E.O,{children:(0,t.jsxs)("form",{onSubmit:p.handleSubmit(()=>tj()),noValidate:!0,children:[(0,t.jsx)("div",{className:"mb-4",children:(0,t.jsx)(eY.f,{control:p.control,name:"auto_router_name",label:(0,eW.q)("Auto Router Name","Unique name for this auto router configuration"),children:({ref:e,...s})=>(0,t.jsx)(eX.f,{...s,ref:e,placeholder:"e.g., smart_router, auto_router_1"})})}),(0,t.jsx)("div",{className:w?"mb-6 border-b pb-6":"",children:e2&&w&&(0,t.jsx)("div",{children:(0,t.jsx)(eY.f,{control:p.control,name:"model_access_group",label:(0,eW.q)("Model Access Group","Use model access groups to control who can access this auto router"),children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e1,{id:e,value:s,onChange:a,options:v,ariaInvalid:l,ariaDescribedBy:r})})})}),h&&(0,t.jsx)(eY.f,{control:p.control,name:"team_id",label:(0,eW.q)("Select Team","Select the team this auto router belongs to. Only keys for this team will be able to call it."),children:({id:e,value:s,onChange:a})=>(0,t.jsx)(a_.f,{id:e,value:s,onChange:a,filterTeam:e=>(0,u.E)(_,e)})}),!w&&(0,t.jsx)(aI,{customized:!!(O.everyday||O.hard),hasSuggestions:!!(e7||aA(e3,T,"auto")),onReset:()=>L({}),goal:T,family:I,models:e3,everyday:e8,hard:e9,waitingForTeam:h&&!x,loading:eI,error:e0,notice:Object.keys(O).length>0?"Your model choices are kept.":e7?.notice??null,onGoalChange:P,onFamilyChange:e=>{z(e),L({})},onModelChange:(e,t)=>L({everyday:e8?.name,hard:e9?.name,[e]:t}),onAdvanced:()=>{k(tt),M(null!==te),C(!0)},onRetry:()=>{eS(),eA()}}),w&&(0,t.jsx)(eR.U,{value:tt,onChange:e=>{el(void 0),k(e)},decisionModel:(0,t.jsx)(eO,{value:tt,onChange:k,modelInfo:ez,deployments:eM}),judgeModel:(0,t.jsx)(af.f,{section:"judge",value:tt,onChange:k,modelOptions:ez.filter(e=>"embedding"!==e.mode).map(e=>({value:e.model_group,label:e.model_group})),showValidationErrors:X}),children:(0,t.jsxs)(eJ.e,{children:[eG&&(0,t.jsxs)("p",{className:"text-sm text-destructive",children:["Could not load available models."," ",(0,t.jsx)("button",{type:"button",className:"underline",onClick:()=>void eS(),children:"Retry"})]}),tv]})}),!w&&th.isError&&(0,t.jsxs)("p",{className:"mt-3 text-sm text-destructive",role:"alert",children:["Could not check availability."," ",(0,t.jsx)(g.K,{type:"button",variant:"link",onClick:()=>void th.refetch(),children:"Retry"})]}),!w&&th.data?.error&&(0,t.jsx)("p",{className:"mt-3 text-sm text-destructive",role:"alert",children:th.data.error}),(0,t.jsxs)("div",{className:"mt-5 flex flex-wrap items-center justify-between gap-3",children:[(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/issues",className:"text-sm text-primary underline-offset-4 hover:underline",children:"Need Help?"})}),(0,t.jsx)(A.Y,{children:"Get help on our github"})]}),(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,t.jsx)(aR,{reason:td,children:(0,t.jsx)(g.K,{type:"button",variant:"outline","data-testid":"auto-router-test-routing-btn",disabled:null!==td||et,onClick:()=>ei(!0),children:"Test Routing"})}),(0,t.jsxs)(g.K,{type:"button",variant:"outline","data-testid":"auto-router-test-connect-btn",onClick:()=>{let e=ew({tiers:(0,tr.X)(tt).map(e=>[(0,tr.P)(e),e.models]),semanticMatchingEnabled:D,embeddingModel:U,defaultModel:(0,tr.H)(tt,tt.default_model),classifier:(0,eq.n)((0,tu.t)(tt))?{model:tt.classifier_llm_config?.model??"",reasoningEffort:tt.classifier_llm_config?.reasoning_effort}:void 0});0===e.length?eH.f.fromError("Please select at least one model for a complexity tier"):(eg(e),ep(e=>e+1),ec(!0),eo(!0))},disabled:ed,children:[ed&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Test Connection"]}),(0,t.jsx)(aR,{reason:tf,children:(0,t.jsx)(g.K,{type:"button",disabled:null!==tf||et,onClick:()=>{tj()},children:"Add Auto Router"})})]})]})]})})}),(0,t.jsx)(eh.N,{open:er,onOpenChange:e=>!e&&ei(!1),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[760px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Test Routing"})}),er&&(0,t.jsx)(ab,{accessToken:a,config:(0,ti.j)(tc),defaultModel:(0,tr.H)(tt,tt.default_model),routerName:f,teamId:h?x??void 0:void 0}),(0,t.jsxs)(eh.c,{children:[" ",(0,t.jsx)(g.K,{variant:"outline",onClick:()=>ei(!1),children:"Close"})]})]})}),(0,t.jsx)(ef,{open:en,onClose:()=>{eo(!1),ec(!1)},testId:eu,accessToken:a,targets:e_,jevRequest:t_,onTestComplete:()=>ec(!1)})]})})};var aF=e.i(548151),aK=e.i(541071),aD=e.i(997422),aV=e.i(755146);let aU=e=>6.5*e.length+18;function aB({row:e}){return(0,t.jsx)(e8.f,{variant:"secondary",className:"font-normal",children:e.typeLabel})}function a$({targets:e}){let a=(0,s.useRef)(null),[l,r]=(0,s.useState)(0);(0,s.useEffect)(()=>{let e=a.current;if(!e||"u"{let t=e[0]?.contentRect.width;"number"==typeof t&&r(t)});return t.observe(e),()=>t.disconnect()},[]);let{visible:i,overflow:n}=(0,s.useMemo)(()=>((e,t)=>{if(0===e.length)return{visible:[],overflow:0};if(t<=0)return{visible:e.slice(0,1),overflow:e.length-1};let s=[],a=0;for(let[l,r]of e.entries()){let i=e.length-l-1,n=4*(0!==s.length),o=32*(i>0);if(a+n+aU(r)+o>t)break;a+=n+aU(r),s.push(r)}return 0===s.length?{visible:e.slice(0,1),overflow:e.length-1}:{visible:s,overflow:e.length-s.length}})(e,l),[e,l]);return 0===e.length?(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"}):(0,t.jsxs)("div",{ref:a,className:"flex w-full min-w-0 flex-nowrap items-center gap-1 overflow-hidden",children:[i.map(e=>(0,t.jsx)(e8.f,{variant:"secondary",className:"max-w-full shrink truncate font-normal",children:e},e)),n>0&&(0,t.jsxs)("span",{className:"shrink-0 text-xs text-muted-foreground",title:e.join(", "),children:["+",n]})]})}function aG({row:e,onDeleteClick:s}){return(0,t.jsxs)(aV.G,{children:[(0,t.jsx)(aV.X,{"aria-label":`Open actions for ${e.name}`,"data-testid":`auto-router-actions-${e.id}`,className:(0,tC.c)((0,g.i)({variant:"ghost",size:"icon-sm"}),"text-muted-foreground"),children:(0,t.jsx)(aK.f,{className:"size-4"})}),(0,t.jsx)(aV.L,{align:"end",className:"w-44",children:(0,t.jsxs)(aV.r,{variant:"destructive","data-testid":"auto-router-action-delete",onClick:()=>s(e),children:[(0,t.jsx)(e7.f,{}),"Delete auto router"]})})]})}let aH=[10,25,50],aW=[{id:"createdAt",desc:!0},{id:"name",desc:!1}];function aJ({canModify:e}){return(0,t.jsxs)("div",{className:"flex flex-col items-center gap-1 py-6",children:[(0,t.jsx)("div",{className:"mb-1 flex size-10 items-center justify-center rounded-lg bg-muted",children:(0,t.jsx)(aF.Y,{size:20,className:"text-muted-foreground"})}),(0,t.jsx)("div",{className:"text-sm font-medium text-foreground",children:"No auto routers yet"}),(0,t.jsx)("div",{className:"text-sm text-muted-foreground",children:e?"Create an auto router to pick the right model per request instead of pinning one.":"An auto router picks the right model per request instead of pinning one."})]})}function aY({routers:e,isLoading:a,canModify:l,onRouterClick:r,onDeleteClick:i}){let n=(0,s.useMemo)(()=>(({canModify:e,onRouterClick:s,onDeleteClick:a})=>[{id:"name",accessorKey:"name",meta:{title:"Name"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Name"}),size:260,enableSorting:!0,cell:({row:e})=>(0,t.jsx)(aD.f,{title:e.original.name||"-",onClick:()=>s(e.original)})},{id:"kind",accessorKey:"kind",meta:{title:"Type"},header:"Type",size:180,enableSorting:!1,cell:({row:e})=>(0,t.jsx)(aB,{row:e.original})},{id:"targets",meta:{title:"Routes to"},header:"Routes to",size:320,enableSorting:!1,cell:({row:e})=>(0,t.jsx)(a$,{targets:e.original.targets})},{id:"defaultModel",accessorKey:"defaultModel",meta:{title:"Default model"},header:"Default model",size:200,enableSorting:!1,cell:({row:e})=>e.original.defaultModel?(0,t.jsx)(e8.f,{variant:"secondary",className:"max-w-full truncate font-normal",title:e.original.defaultModel,children:e.original.defaultModel}):(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"})},{id:"createdAt",accessorKey:"createdAt",meta:{title:"Created"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Created"}),size:150,enableSorting:!0,sortingFn:"datetime",sortUndefined:"last",cell:({row:e})=>(0,t.jsx)(sH.S,{value:e.original.createdAt,precision:"date"})},...e?[{id:"actions",meta:{title:""},header:"",size:60,enableSorting:!1,cell:({row:e})=>e.original.canDelete?(0,t.jsx)(aG,{row:e.original,onDeleteClick:a}):null}]:[]])({canModify:l,onRouterClick:r,onDeleteClick:i}),[l,r,i]);return(0,t.jsx)(sR.f,{data:e,columns:n,getRowId:e=>e.id,sortingMode:"client",defaultSorting:aW,paginationMode:"client",pageSizeOptions:aH,isLoading:a,loadingMessage:"Loading auto routers…",noDataMessage:(0,t.jsx)(aJ,{canModify:l}),size:"compact"})}let aX=e=>{let t="string"==typeof e?(e=>{try{return JSON.parse(e)}catch{return null}})(e):e;return"object"!=typeof t||null===t||Array.isArray(t)?{}:t},aQ=e=>Array.from(new Set(e)),aZ={llm:"LLM Classifier",jev:"OSS Classifier",oss_classifier:"OSS Classifier",capability:"Capability",llm_v2:"Fuse v2",heuristic_first:"Heuristic first",hybrid:"Hybrid",custom:"Custom classifier"},a0=(e,t)=>{let s;return{typeLabel:e,targets:Array.isArray(s=t.available_models)?s.filter(e=>"string"==typeof e):[]}},a1={complexity:e=>({typeLabel:"string"==typeof e.classifier_type&&aZ[e.classifier_type]||"Heuristic",targets:aQ(Object.values(aX(e.tiers)).flatMap(ek.I))}),semantic:e=>({typeLabel:"Semantic",targets:aQ((Array.isArray(e.routes)?e.routes:[]).map(e=>aX(e).name).filter(e=>"string"==typeof e&&e.length>0))}),adaptive:e=>a0("Adaptive",e),quality:e=>a0("Quality",e)};function a2({accessToken:e,userRole:a,userID:l,isViewOnly:r,teams:i,createScope:n}){let o="forbidden"!==n,{data:d,isLoading:c}=(0,y.v)(),m=(0,y.g)(),{openModel:h}=sb(),[p,f]=(0,s.useState)(!1),[x,_]=(0,s.useState)(null),[j,v]=(0,s.useState)(!1),b=(0,s.useMemo)(()=>{let e,t;return e=d??[],t={userRole:a,userID:l,isViewOnly:r},e.map((e,s)=>((e,t,s,a)=>{let l,r,i=e.litellm_params??{},n=e.model_info??{},o=e.model_name??"",d=eM(i),{canEdit:c,canDelete:m,editBlockedReason:h}=(l=n?.db_model!==!0,r=eM(i).hasEditor,{isConfigManaged:l,canEdit:!l&&r,canDelete:!l,editBlockedReason:l?"config-managed":r?null:"no-editor"}),p={teamId:n.team_id,isDbModel:!0===n.db_model,createdBy:n.created_by,model:i.model},f=(0,u.d)(s,a,p),x=(0,u.F)(s,a,p);return{id:n.id??`${o}-${t}`,name:o,kind:d.kind,canEdit:c&&x,canDelete:m&&f,editBlockedReason:h,createdAt:n.created_at??void 0,defaultModel:i[d.defaultModelKey]??null,deployment:e,...a1[d.kind](aX(i[d.configKey]))}})(e,s,t,i))},[d,a,l,r,i]),N=async()=>{if(x){v(!0);try{await (0,em.o2)(e,x.id),eH.f.success(`Deleted auto router: ${x.name}`),_(null),await m()}catch(e){eH.f.fromError(`Failed to delete auto router: ${e}`)}finally{v(!1)}}};return(0,t.jsxs)("div",{className:"w-full space-y-4",children:[(0,t.jsxs)("div",{className:"flex items-start justify-between gap-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h2",{className:"text-base font-semibold text-foreground",children:"Auto routers"}),(0,t.jsx)("p",{className:"mt-1 text-sm text-muted-foreground",children:"Auto routers sit above your deployments and pick a model per request. They are called like any other model, so clients keep using a single model name."})]}),o&&(0,t.jsxs)(g.K,{onClick:()=>f(!0),className:"shrink-0",children:[(0,t.jsx)(e3.f,{}),"Add Auto Router"]})]}),(0,t.jsx)(aY,{routers:b,isLoading:c,canModify:o,onRouterClick:e=>h(e.id),onDeleteClick:_}),(0,t.jsx)(eh.N,{open:p,onOpenChange:f,children:(0,t.jsxs)(eh.d,{overlayClassName:"bg-black/40 backdrop-blur-sm",className:"max-h-[90vh] overflow-y-auto sm:max-w-4xl",children:[(0,t.jsxs)(eh.s,{children:[(0,t.jsx)(eh.F,{children:"Add Auto Router"}),(0,t.jsx)(eh.C,{children:"Choose models for your auto router."})]}),(0,t.jsx)(aq,{handleOk:()=>{f(!1),m()},accessToken:e,userRole:a,userId:l,createScope:n,teams:i})]})}),x&&(0,t.jsx)(eA.f,{isOpen:!0,title:"Delete Auto Router",message:`Are you sure you want to delete "${x.name}"? Any client still calling this model name will start failing.`,resourceInformationTitle:"Auto router",resourceInformation:[{label:"Name",value:x.name},{label:"Type",value:x.typeLabel},{label:"ID",value:x.id}],onCancel:()=>_(null),onOk:N,confirmLoading:j})]})}function a4(){let{accessToken:e,userRole:s,userId:a,isViewOnly:l}=(0,i.f)(),{data:r}=(0,n.n)(),{data:d}=(0,o.f)(),m=null!=s&&c.t.includes(s),h=(0,u.n)({userRole:s,userID:a,isViewOnly:l},{teams:r??null,disabledForInternalUsers:m&&d?.values?.disable_model_add_for_internal_users===!0});return(0,t.jsx)(a2,{accessToken:e,userRole:s??"",userID:a??null,isViewOnly:l,teams:r??null,createScope:h})}var a5=e.i(803099),a6=e.i(838932),a3=e.i(109034),a7=e.i(630468),a8=e.i(181349),a9=e.i(916925);let le=[],lt="github_copilot_auth_type",ls="per_user_oauth",la={GITHUB_COPILOT:[{id:"shared_device_login",label:"Shared device login",description:"One GitHub device login on the proxy host, stored in its token file, is used for every caller of models on this credential.",fieldKeys:["api_base","api_key"],requiredFieldKeys:[]},{id:ls,label:"Per-user GitHub OAuth",credentialOnly:!0,description:"Each LiteLLM user connects their own GitHub account from LLM Credentials, and their requests use their own GitHub Copilot access. Users who have not connected get a 401.",fieldKeys:[lt,"github_copilot_host"],requiredFieldKeys:[lt],fixedValues:{[lt]:ls}}],MICROSOFT_365_COPILOT:[{id:"oauth_token_exchange",label:"OAuth token exchange (on-behalf-of)",credentialOnly:!0,description:"LiteLLM exchanges each caller's IdP-issued JWT at your IdP's token endpoint for a delegated token. Microsoft Graph only accepts Microsoft Entra tokens, so for Microsoft 365 Copilot the token endpoint must be Entra and callers must send an Entra-issued JWT for this app. Users can still sign in through any IdP federated with Entra.",fieldKeys:["token_exchange_endpoint","token_exchange_profile","client_id","client_secret","token_exchange_scope","token_exchange_audience"],requiredFieldKeys:["token_exchange_endpoint","client_id","client_secret"]},{id:"static_token",label:"Static delegated access token",description:"Sends one pre-acquired delegated Microsoft Graph token for every caller.",fieldKeys:["api_key"],requiredFieldKeys:["api_key"]}]},ll=e=>{let t=Object.keys(a9.g),s=null===e?void 0:t.find(t=>t===e||a9.g[t]===e);return void 0===s?le:la[s]??le};var lr=e.i(569074);let li=e=>{let t="password"===e.field_type?"password":"select"===e.field_type?"select":"upload"===e.field_type?"upload":"textarea"===e.field_type?"textarea":"text";return{key:e.key,label:e.label,placeholder:e.placeholder??void 0,tooltip:e.tooltip??void 0,required:e.required??!1,type:t,options:e.options??void 0,defaultValue:e.default_value??void 0}},ln={},lo=({selectedProvider:e,hiddenFieldKeys:a,context:l="credential",onCreateCredential:r,initialAuthTypeId:i,onAuthTypeChange:n,fieldValidators:o})=>{let d=a9.g[e],c=(0,tD.M)(),u=ll(e),m=s.default.useMemo(()=>u.filter(({credentialOnly:e})=>"model"!==l||void 0!==r||!e),[u,l,r]),[h,p]=s.default.useState(()=>{let e;return i&&m.some(({id:e})=>e===i)?i:(e=c.getValues(),m.find(({requiredFieldKeys:t})=>t.some(t=>void 0!==e[t]&&null!==e[t]&&""!==e[t]))?.id??m[0]?.id??"")}),f=m.find(({id:e})=>e===h)??m[0],x="model"===l&&f?.credentialOnly===!0,_=s.default.useId(),j=s.default.useRef(null);s.default.useEffect(()=>{f&&n?.(f.id)},[n,f]);let{data:v,isLoading:b,error:y}=(0,a5.f)(),N=s.default.useMemo(()=>{if(!v)return null;let e={};return v.forEach(t=>{let s=t.provider_display_name,a=t.credential_fields.map(li);e[s]=a,t.provider&&(e[t.provider]=a),t.litellm_provider&&(e[t.litellm_provider]=a)}),e},[v]);s.default.useEffect(()=>{N&&Object.assign(ln,N)},[N]);let k=s.default.useMemo(()=>{if(null===e)return[];let t=ln[d]??ln[e];if(t)return t;if(!v)return[];let s=v.find(t=>t.provider_display_name===d||t.provider===e||t.litellm_provider===e);if(!s)return[];let a=s.credential_fields.map(li);return ln[s.provider_display_name]=a,s.provider&&(ln[s.provider]=a),s.litellm_provider&&(ln[s.litellm_provider]=a),a},[d,e,v]),w=s.default.useMemo(()=>{var e;let t;return e=f?.id??"",t=u.find(({id:t})=>t===e)?.fieldKeys??[],u.filter(({id:t})=>t!==e).flatMap(({fieldKeys:e})=>e).filter((e,s,a)=>!t.includes(e)&&a.indexOf(e)===s)},[u,f?.id]),C=s.default.useMemo(()=>{if(x)return[];if(0===m.length)return a?k.filter(e=>!a.includes(e.key)):k;let e=[...a??[],...w];return k.filter(t=>!e.includes(t.key)).map(e=>f?.requiredFieldKeys.includes(e.key)?{...e,required:!0}:e)},[k,a,m,w,f,x]),S=s.default.useMemo(()=>C.some(e=>"api_version"===e.key),[C]),M=s.default.useRef(null),E=s.default.useCallback(e=>{if(!S)return;let t=(e=>{let t=e.indexOf("?");if(-1===t)return null;let s=new URLSearchParams(e.slice(t+1).split("#")[0]);return s.get("api_version")||s.get("api-version")})(e.target.value);if(t){M.current=t,c.setValue("api_version",t);return}c.getValues("api_version")===M.current&&c.setValue("api_version",""),M.current=null},[c,S]);return(0,t.jsxs)(t.Fragment,{children:[m.length>0&&f&&(0,t.jsxs)("div",{className:"mb-4 flex flex-col gap-2",children:[(0,t.jsx)("label",{htmlFor:_,className:"text-sm font-medium",children:(0,eW.q)("Auth Type:","Select how LiteLLM authenticates to this provider.")}),(0,t.jsxs)(tJ.d,{items:m.map(({id:e,label:t})=>({value:e,label:t})),value:f.id,onValueChange:e=>p(e??""),children:[(0,t.jsx)(tJ.P,{id:_,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:m.map(e=>(0,t.jsx)(tJ.T,{value:e.id,children:e.label},e.id))})]}),(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:f.description})]}),x?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"mb-4 text-sm",children:"This auth type is saved as an LLM credential and attached to this model."}),(0,t.jsx)(g.K,{type:"button",onClick:()=>r?.(f.id),children:"Create credential"})]}):Object.entries(f?.fixedValues??{}).map(([s,a])=>(0,t.jsx)(a8.I,{name:s,defaultValue:a,bare:!0,children:()=>null},`${e}:${s}`)),b&&0===C.length&&(0,t.jsx)("p",{className:"text-sm mb-2",children:"Loading provider fields..."}),y&&0===C.length&&(0,t.jsx)("p",{className:"text-sm mb-2 text-destructive",children:y instanceof Error?y.message:"Failed to load provider credential fields"}),C.map(a=>(0,t.jsxs)(s.default.Fragment,{children:[(0,t.jsx)(a8.I,{label:a.tooltip?(0,eW.q)(a.label,a.tooltip):a.label,name:a.key,required:a.required,rules:{validate:{...a.required?{required:(0,a7.B)("Required")}:{},...o?.[a.key]?{provider:o[a.key]}:{}}},className:"vertex_credentials"===a.key?"mb-0":"mb-4",children:e=>((e,s)=>{if("select"===e.type)return(0,t.jsxs)(tJ.d,{items:(e.options??[]).map(e=>({value:e,label:e})),value:s.value??e.defaultValue??null,onValueChange:s.onChange,children:[(0,t.jsx)(tJ.P,{id:s.id,onBlur:s.onBlur,className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:e.placeholder})}),(0,t.jsx)(tJ.r,{children:e.options?.map(e=>(0,t.jsx)(tJ.T,{value:e,children:e},e))})]});if("upload"===e.type){let e;return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(g.K,{type:"button",variant:"outline",className:"w-fit",onClick:()=>j.current?.click(),children:[(0,t.jsx)(lr.f,{}),"Click to Upload"]}),(0,t.jsx)("input",{ref:j,id:s.id,type:"file",accept:".json",className:"sr-only",onBlur:s.onBlur,onChange:(e=s.onChange,t=>{let s,a=t.target.files?.[0];t.target.value="",a?.type==="application/json"&&((s=new FileReader).onload=t=>{t.target&&e(t.target.result)},s.readAsText(a))})})]})}return"textarea"===e.type?(0,t.jsx)(tt.f,{id:s.id,value:s.value??e.defaultValue??"",onChange:s.onChange,onBlur:s.onBlur,placeholder:e.placeholder,rows:6,className:"font-mono text-xs"}):"password"===e.type?(0,t.jsx)(tL.f,{id:s.id,value:s.value??e.defaultValue??"",onChange:s.onChange,onBlur:s.onBlur,placeholder:e.placeholder}):(0,t.jsx)(eX.f,{id:s.id,value:s.value??e.defaultValue??"",onBlur:s.onBlur,placeholder:e.placeholder,type:"text",onChange:t=>{s.onChange(t),"api_base"===e.key&&E(t)}})})(a,e)}),"vertex_credentials"===a.key&&(0,t.jsx)("p",{className:"text-sm mb-3 mt-1",children:"Give a gcp service account(.json file)"}),"base_model"===a.key&&(0,t.jsx)("div",{className:"grid grid-cols-24",children:(0,t.jsxs)("p",{className:"col-start-11 col-span-10 text-sm mb-2",children:["The actual model your azure deployment uses. Used for accurate cost tracking. Select name from"," ",(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline-offset-4 hover:underline",children:"here"})]})})]},`${e}:${a.key}`))]})},ld=e=>(0,t.jsx)(lo,{...e},e.selectedProvider??"no-provider"),lc=["credential_name","display_name","custom_llm_provider"],lu=(e,t)=>({credential_name:e.credential_name,...void 0!==e.display_name?{display_name:e.display_name}:{},credential_values:t,credential_info:{custom_llm_provider:e.custom_llm_provider}}),lm=e=>Object.fromEntries(Object.entries(e).filter(([e])=>!lc.includes(e))),lh=e=>"string"==typeof e?""===e.trim():null==e,lp=e=>!lh(e)||"Required",lf="anthropic_identity_source",lx=[{key:"anthropic_federation_rule_id",label:"Federation Rule ID",tooltip:"The fdrl_ id of the federation rule, from Settings > Workload identity in the Claude Console. Leave empty when the proxy sets ANTHROPIC_FEDERATION_RULE_ID in its environment.",placeholder:"fdrl_...",required:!1,control:"text"},{key:"anthropic_organization_id",label:"Organization ID",tooltip:"The Anthropic organization the federation rule belongs to, shown on the rule's detail page. Leave empty when the proxy sets ANTHROPIC_ORGANIZATION_ID in its environment.",required:!1,control:"text"},{key:"anthropic_service_account_id",label:"Service Account ID",tooltip:"The svac_ id the federation rule targets. Anthropic's reference lists it as required.",placeholder:"svac_...",required:!1,control:"text"},{key:"anthropic_federation_workspace_id",label:"Workspace ID",tooltip:"Set this when the federation rule is enabled in more than one workspace: the wrkspc_ id to mint tokens for, or 'default'.",placeholder:"wrkspc_...",required:!1,control:"text"}],l_=[{id:"token_file",label:"Identity token file",fixedValues:{},fields:[{key:"anthropic_identity_token_file",label:"Identity Token File",tooltip:"Absolute path on the proxy host of a file holding the identity token, for example a projected Kubernetes service account token. It must sit under an allowed credential directory.",placeholder:"/var/run/secrets/anthropic/token",required:!0,control:"text"}]},{id:"secret_reference",label:"Identity token secret reference",fixedValues:{},fields:[{key:"anthropic_identity_token",label:"Identity Token Reference",tooltip:"An oidc/ secret reference the proxy resolves on each exchange, such as oidc/env/VAR_NAME, oidc/github/, or oidc/google/. Raw tokens are not accepted.",placeholder:"oidc/env/ANTHROPIC_IDENTITY_TOKEN",required:!0,control:"text"}]},{id:"internal_issuer",label:"Token signed by LiteLLM (internal issuer)",fixedValues:{[lf]:"internal_issuer"},fields:[{key:"anthropic_issuer_url",label:"Issuer URL",tooltip:"The issuer registered on the federation rule. The proxy puts it in the token's iss claim.",placeholder:"https://litellm.example.com",required:!0,control:"text"},{key:"anthropic_issuer_subject",label:"Subject",tooltip:"The sub claim the federation rule matches.",required:!0,control:"text"},{key:"anthropic_issuer_audience",label:"Audience",tooltip:"Optional aud claim, when the federation rule checks one.",required:!1,control:"text"},{key:"anthropic_issuer_ttl_seconds",label:"Token Lifetime (seconds)",tooltip:"Optional. How long each signed token is valid, from 1 to 3600 seconds. The proxy uses its default when this is empty.",required:!1,control:"integer"},{key:"anthropic_issuer_signing_key_ref",label:"Signing Key Reference",tooltip:"A secret reference to the PEM private key the proxy signs with, such as os.environ/VAR_NAME. Enter the reference, never the key itself.",placeholder:"os.environ/ANTHROPIC_ISSUER_SIGNING_KEY",required:!0,control:"text"}]},{id:"keycloak",label:"Keycloak client credentials",fixedValues:{[lf]:"keycloak"},fields:[{key:"anthropic_keycloak_token_url",label:"Keycloak Token URL",tooltip:"The realm's token endpoint the proxy requests an identity token from.",placeholder:"https://keycloak.example.com/realms//protocol/openid-connect/token",required:!0,control:"text"},{key:"anthropic_keycloak_client_id",label:"Keycloak Client ID",tooltip:"The client the proxy authenticates as.",required:!0,control:"text"},{key:"anthropic_keycloak_client_secret_ref",label:"Client Secret Reference",tooltip:"A secret reference to the client secret, such as os.environ/VAR_NAME. Enter the reference, never the secret itself.",placeholder:"os.environ/KEYCLOAK_CLIENT_SECRET",required:!0,control:"text"},{key:"anthropic_keycloak_auth_method",label:"Client Authentication Method",tooltip:"Optional. How the client secret is sent to Keycloak. The proxy uses client_secret_basic when unset.",required:!1,control:"select",options:["client_secret_basic","client_secret_post"]},{key:"anthropic_keycloak_scope",label:"Scope",tooltip:"Optional scope to request with the token.",required:!1,control:"text"}]},{id:"environment",label:"Proxy environment variables",fixedValues:{},fields:[]}],lg="token_file",lj=[lf,...l_.flatMap(e=>e.fields.map(e=>e.key))],lv=[...lx,...l_.flatMap(e=>e.fields)],lb=[...lx.map(e=>e.key),...lj],ly={id:"unrecognized",label:"",fixedValues:{},fields:[]},lN=e=>l_.find(t=>t.id===e)??ly,lk=e=>null!=e&&"anthropic"===e.toLowerCase(),lw=e=>{let t=e??{},s=t[lf];return lh(s)?lh(t.anthropic_identity_token_file)?lh(t.anthropic_identity_token)?"environment":"secret_reference":"token_file":l_.find(e=>e.fixedValues[lf]===s)?.id??"unrecognized"},lC=e=>!!("string"!=typeof e||lh(e)||ea(e))||!(!e.startsWith("oidc/")||e.startsWith("oidc/env_path/"))||"Enter an oidc/ secret reference such as oidc/env/VAR_NAME. Raw tokens and oidc/env_path/ references are not accepted",lS=e=>{if(lh(e))return!0;let t=Number(e);return!!Number.isInteger(t)&&t>=1&&t<=3600||"Enter a whole number of seconds from 1 to 3600"},lM="api.openai.com",lE=[{key:"openai_identity_provider_id",label:"Identity Provider ID",tooltip:"The workload identity provider registered in your OpenAI organization that trusts the token's issuer. Leave empty when the proxy sets OPENAI_IDENTITY_PROVIDER_ID in its environment.",required:!1,control:"text"},{key:"openai_service_account_id",label:"Service Account ID",tooltip:"The OpenAI service account the verified identity acts as. Its project decides what the model can reach. Leave empty when the proxy sets OPENAI_SERVICE_ACCOUNT_ID in its environment.",required:!1,control:"text"},{key:"openai_identity_token_file",label:"Identity Token File",tooltip:"Absolute path on the proxy host of a file holding the identity token, for example a projected Kubernetes service account token. Leave empty when the proxy sets OPENAI_IDENTITY_TOKEN_FILE in its environment.",placeholder:"/var/run/secrets/kubernetes.io/serviceaccount/token",required:!1,control:"text"}],lT="anthropic_federation_identity_source",lA=lx[0].key;function lP({field:e,storedValue:s,validators:a}){return(0,t.jsx)(a8.I,{label:(0,eW.q)(e.label,e.tooltip),name:e.key,required:e.required,rules:{validate:{...e.required?{required:lp}:{},...a,masked:e=>!ea(e)||e===s||"This stored value is hidden. Replace the whole value to change it"}},className:"mb-4",children:s=>((e,s)=>{if("select"===e.control){let a,l=[...ea(a=s.value)?[{value:a,label:`Stored: ${a}`}]:[],...(e.options??[]).map(e=>({value:e,label:e}))];return(0,t.jsxs)(tJ.d,{items:l,value:"string"==typeof s.value&&""!==s.value?s.value:null,onValueChange:e=>s.onChange(e??""),children:[(0,t.jsx)(tJ.P,{id:s.id,onBlur:s.onBlur,className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Proxy default"})}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:null,children:"Proxy default"}),l.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))]})]})}return(0,t.jsx)(eX.f,{id:s.id,value:void 0===s.value||null===s.value?"":String(s.value),onChange:s.onChange,onBlur:s.onBlur,placeholder:e.placeholder,inputMode:"integer"===e.control?"numeric":void 0,"aria-invalid":s["aria-invalid"]})})(e,s)})}function lI({identitySource:e,onIdentitySourceChange:s,storedValues:a}){let l=[..."unrecognized"===lw(a)?[{value:"unrecognized",label:`Stored: ${String(a[lf])}`}]:[],...l_.map(e=>({value:e.id,label:e.label}))],r=s=>(0,t.jsx)(lP,{field:s,storedValue:a[s.key],validators:{...s.key===lA?{stored:(t,s)=>!("environment"===e&&lx.every(e=>lh(s[e.key])))||"Enter at least one of these ids, or pick an identity source that stores a token. The proxy rejects a credential with no values"}:{},..."anthropic_identity_token"===s.key?{reference:lC}:{},..."integer"===s.control?{ttl:lS}:{}}},s.key);return(0,t.jsxs)(t.Fragment,{children:[lx.map(r),(0,t.jsxs)("div",{className:"mb-4 flex flex-col gap-2",children:[(0,t.jsx)("label",{htmlFor:lT,className:"text-sm font-medium",children:(0,eW.q)("Identity Source","Where the proxy gets the identity token it exchanges with Anthropic for an access token.")}),(0,t.jsxs)(tJ.d,{items:l,value:e,onValueChange:e=>s(e),children:[(0,t.jsx)(tJ.P,{id:lT,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:l.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]}),"unrecognized"===e&&(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"This form does not offer the stored identity source. Saving keeps it and its settings as stored. Pick another source to replace it."}),"environment"===e&&(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"The proxy reads ANTHROPIC_IDENTITY_TOKEN_FILE or ANTHROPIC_IDENTITY_TOKEN from its own environment."})]}),lN(e).fields.map(r)]})}function lz({storedValues:e}){return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"mb-4 text-sm text-muted-foreground",children:"The proxy exchanges the identity token for an OpenAI access token only when OPENAI_API_KEY is unset in its environment. Otherwise it sends that key instead."}),lE.map(s=>(0,t.jsx)(lP,{field:s,storedValue:e[s.key]},s.key))]})}function lO({selection:e,onIdentitySourceChange:s,storedValues:a}){switch(e.provider){case"anthropic":return(0,t.jsx)(lI,{identitySource:e.identitySource,onIdentitySourceChange:s,storedValues:a});case"openai":return(0,t.jsx)(lz,{storedValues:a})}}var lL=e.i(922407),lR=e.i(431703);let lq=({credentialName:e})=>{let s=sx.q.useQuery("get","/credentials/{credential_name}/jwks",{params:{path:{credential_name:e}}});if(s.isPending||!s.isFetchedAfterMount)return(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"Loading JWKS..."});if(s.isError)return(0,t.jsx)("p",{role:"alert",className:"text-sm text-destructive",children:(0,lR.U)(s.error)});let a=JSON.stringify(s.data,null,2);return(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsx)("pre",{"aria-label":"Public JWKS",className:"max-h-48 overflow-auto rounded-md border bg-muted p-3 text-xs",children:a}),(0,t.jsx)(lL.f,{value:a,label:"Copy JWKS",variant:"action",className:"self-start"})]})};function lF({panel:e}){switch(e.kind){case"hidden":return null;case"after_save":return(0,t.jsx)("p",{className:"mb-4 text-sm text-muted-foreground",children:"Once saved, reopen this credential from LLM Credentials to copy the public JWKS you register in the Claude Console."});case"saved":return(0,t.jsxs)(eJ.G,{className:"mb-4 gap-2",children:[(0,t.jsx)(eJ.f,{variant:"label",className:"mb-0",children:"Public JWKS"}),(0,t.jsx)(eJ.H,{children:"Register this JWKS with the Issuer URL and Subject above as a federation rule under Settings > Workload identity in the Claude Console. Then fill in its Federation Rule ID and Organization ID at the top of this form and update the credential. The JWKS comes from the saved signing key, so update after changing the key and before copying."}),(0,t.jsx)(lq,{credentialName:e.credentialName})]})}}let lK="api_key",lD=[...lb,...lE.map(e=>e.key)],lV=new Map([...lv,...lE].map(e=>[e.key,e])),lU={api_base:e=>{let t,s;return!!("string"!=typeof e||lh(e)||(t=URL.canParse(e)?new URL(e):null,t?.protocol==="https:"&&((s=t.hostname)===lM||s.endsWith(`.${lM}`))))||`Workload identity federation only reaches the OpenAI API. Enter https://${lM}/v1 or a regional *.${lM} URL, or leave this empty`}},lB={},l$=e=>lk(e)?"anthropic":e?.toLowerCase()==="openai"?"openai":null,lG=(e,t,s)=>null===e||"api_key"===t?{authMethod:"api_key"}:"anthropic"===e?{authMethod:"federation",provider:e,identitySource:s}:{authMethod:"federation",provider:e},lH=e=>lD.some(t=>!lh(e?.[t])),lW=e=>lh(e?.[lK])&&lH(e)?"federation":"api_key",lJ=e=>"federation"===e.authMethod&&"openai"===e.provider?lU:lB,lY=e=>"federation"===e.authMethod&&"anthropic"===e.provider?e.identitySource:null,lX=e=>{let t=lY(e);return null===t?{}:lN(t).fixedValues},lQ=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>{var s;return[e,(s=lV.get(e),void 0===s||lh(t)?void 0===s?t:"":"integer"===s.control?Number(t):"string"==typeof t?t.trim():t)]}).filter(([,e])=>""!==e&&null!=e)),lZ=(e,t)=>Object.fromEntries(Object.entries(t).filter(([t,s])=>!ea(s)&&s!==e[t])),l0=Object.entries(a9.g).map(([e,s])=>({label:s,value:e,icon:(0,t.jsx)(tT.f,{provider:e,label:s,className:"w-5 h-5"})})),l1="credential_auth_method",l2=["api_key"],l4=[],l5=[{value:"api_key",label:"API key"},{value:"federation",label:"Workload identity federation"}],l6=(e,t)=>(e??"").toLowerCase()===(t??"").toLowerCase();function l3({open:e,onCancel:a,onSubmit:l,mode:r,existingCredential:i=null,initialProvider:n=null,initialAuthMethod:o,initialAuthTypeId:d,providerLocked:c=!1}){let u="edit"===r,[m,h]=(0,s.useState)(i?.credential_info.custom_llm_provider??n??a9.g.OpenAI),p=i?.credential_info.custom_llm_provider??null,f=i?.credential_values??{},x=lW(f),_=lH(f)?lw(f):lg,j=lG(l$(p),x,_),[v,b]=(0,s.useState)(i?x:o??"api_key"),[y,N]=(0,s.useState)(_),k=lG(l$(m),v,y),w=i?{...Object.fromEntries(Object.entries(i.credential_values||{}).map(([e,t])=>[e,t??null])),credential_name:i.credential_name,display_name:i.display_name??"",custom_llm_provider:i.credential_info.custom_llm_provider}:n?{custom_llm_provider:n}:void 0,C=(0,tD.G)({mode:"onChange",defaultValues:w}),S=(0,a8.T)(),M=async()=>{var e;let t,s,a,r,n;if(!await C.trigger(S.mountedNames()))return;let o=(0,a8.$)(S,C.getValues),d={credential_name:String(o.credential_name),custom_llm_provider:String(o.custom_llm_provider),...(e=o.display_name,t="string"==typeof e?e:"",!i?t?{display_name:t}:{}:t===(i.display_name??"")?{}:{display_name:t||null})};if(!u){let e;return void l({...d,credential_values:(e=lm(o),{...lQ(e),...lX(k)})},[])}let c=l6(m,p),h=lm(o),x=c?(s=lZ(f,{...lQ(h),...lX(k)}),a=Object.keys(h).filter(e=>lh(h[e])&&!lh(f[e])),r=[...((e,t)=>{let s,a;if(t.authMethod!==e.authMethod)return"federation"===t.authMethod?[lK]:lD;let l=lY(t);return null===l||l===lY(e)?[]:(a=new Set([...(s=lN(l)).fields.map(e=>e.key),...Object.keys(s.fixedValues)]),lj.filter(e=>!a.has(e)))})(j,k),...a].filter(e=>e in f&&!(e in s)),{credential_values:s,credential_values_to_delete:Array.from(new Set(r))}):{credential_values:lZ(f,n={...lQ(h),...lX(k)}),credential_values_to_delete:Object.keys(f).filter(e=>!(e in n))},_=c?ll(m).flatMap(({fieldKeys:e})=>e).filter((e,t,s)=>s.indexOf(e)===t).filter(e=>e in f&&!(e in h)):[],g=Array.from(new Set([...x.credential_values_to_delete,..._]));l({...d,credential_values:x.credential_values},g)},E=()=>{a(),C.reset()};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&E(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[600px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:u?"Edit Credential":"Add New Credential"})}),(0,t.jsx)(tD.p,{...C,children:(0,t.jsx)(a8.R,{value:{control:C.control,registry:S},children:(0,t.jsxs)("form",{onSubmit:e=>{e.preventDefault(),M()},children:[(0,t.jsx)(a8.I,{label:"Credential Name:",name:"credential_name",required:!0,rules:{validate:{required:(0,a7.B)("Credential name is required")}},className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:"string"==typeof e.value?e.value:"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Unique name that models reference this credential by",disabled:u})}),(0,t.jsx)(a8.I,{label:"Display Name:",name:"display_name",className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:"string"==typeof e.value?e.value:"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"e.g. Production OpenAI"})}),(0,t.jsx)(a8.I,{label:(0,eW.q)("Provider:","Helper to auto-populate provider specific fields"),name:"custom_llm_provider",required:!0,rules:{validate:{required:(0,a7.B)("Required")}},className:"mb-4",children:e=>(0,t.jsx)(eI.f,{inputId:e.id,placeholder:"Select a provider",options:l0,value:"string"==typeof e.value?e.value:null,disabled:c,onValueChange:t=>{var s;let a,l,r;e.onChange(t),b((a=u&&l6(t,p))?x:"api_key"),N(a?_:lg),s={getFieldValue:e=>C.getValues(e),resetFields:()=>C.reset(u&&!l6(t,p)?{}:w),setFieldValue:(e,t)=>C.setValue(e,t)},l=s.getFieldValue("credential_name"),r=s.getFieldValue("display_name"),s.resetFields(),void 0!==l&&s.setFieldValue("credential_name",l),void 0!==r&&s.setFieldValue("display_name",r),h(t),s.setFieldValue("custom_llm_provider",t)}})}),null!==l$(m)&&(0,t.jsxs)("div",{className:"mb-4 flex flex-col gap-2",children:[(0,t.jsx)("label",{htmlFor:l1,className:"text-sm font-medium",children:(0,eW.q)("Authentication:","Workload identity federation exchanges an identity token for a short-lived access token from the provider, so no API key is stored.")}),(0,t.jsxs)(tJ.d,{items:l5,value:v,onValueChange:e=>{C.clearErrors(Object.keys(lJ(k))),b(e)},children:[(0,t.jsx)(tJ.P,{id:l1,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:l5.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})]}),(0,t.jsx)(ld,{selectedProvider:m,hiddenFieldKeys:"federation"===k.authMethod?l2:l4,initialAuthTypeId:d,fieldValidators:lJ(k)}),"federation"===k.authMethod&&(0,t.jsx)(lO,{selection:k,onIdentitySourceChange:N,storedValues:f}),(0,t.jsx)(lF,{panel:"internal_issuer"!==lY(k)?{kind:"hidden"}:null!==i&&lk(i.credential_info.custom_llm_provider)&&"internal_issuer"===lw(i.credential_values)?{kind:"saved",credentialName:i.credential_name}:{kind:"after_save"}}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)(A.x,{content:"Get help on our github",children:(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/issues",className:"text-sm text-primary hover:underline",children:"Need Help?"})}),(0,t.jsxs)("div",{children:[(0,t.jsx)(g.K,{variant:"outline",className:"mr-2.5",onClick:E,children:"Cancel"}),(0,t.jsx)(g.K,{type:"submit",children:u?"Update Credential":"Add Credential"})]})]})]})})})]})})}var l7=e.i(845150);let l8=[R,q,"input_cost_per_token","output_cost_per_token","cache_read_input_token_cost","cache_creation_input_token_cost","cache_creation_input_token_cost_above_1hr","input_cost_per_second"],l9=[{value:"per_token",label:"Per Million Tokens"},{value:"per_second",label:"Per Second"}],re=(e,t)=>t&&(isNaN(Number(t))||0>Number(t))?Promise.reject("Please enter a valid positive number"):Promise.resolve(),rt={deps:[L],validate:(0,a7.W)({validator:re},({getFieldValue:e,isFieldTouched:t})=>({validator:(t,s)=>K(e(L))&&K(s)&&0!==Number(s)?Promise.reject(Error("A PTU deployment bills by reserved capacity, so this cost must be 0 or blank")):Promise.resolve()}))},rs=({showAdvancedSettings:e,setShowAdvancedSettings:a,teams:l,guardrailsList:r,tagsList:i,accessToken:n})=>{let[o,d]=s.default.useState(!1),[c,u]=s.default.useState("per_token"),[m,h]=s.default.useState(!1),p=X();return(0,t.jsx)(t.Fragment,{children:(0,t.jsxs)(e9.Y,{className:"mt-2 mb-4 overflow-hidden rounded-lg border",children:[(0,t.jsxs)(e9.v,{className:"group/section flex w-full items-center justify-between px-4 py-3 text-left",children:[(0,t.jsx)("b",{children:"Advanced Settings"}),(0,t.jsx)(e5.f,{className:"size-5 shrink-0 text-muted-foreground transition-transform group-data-[panel-open]/section:rotate-180"})]}),(0,t.jsx)(e9.C,{className:"px-4 pb-3",children:(0,t.jsxs)("div",{className:"rounded-lg",children:[(0,t.jsx)(a8.I,{name:"custom_pricing",label:"Custom Pricing",className:"mb-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:t=>{e.onChange(t),d(t)}})}),(0,t.jsx)(a8.I,{name:"vector_store_ids",label:(0,t.jsxs)("span",{children:["Attached Knowledge Bases (RAG)"," ",(0,t.jsx)(A.x,{content:"Vector stores to use for RAG. Every request to this model will automatically retrieve context from these knowledge bases.",children:(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/completion/knowledgebase",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,t.jsx)(et.f,{className:"ml-1 inline size-3.5 align-text-bottom"})})})]}),className:"mt-4",help:"Select vector stores to attach. Requests to this model will automatically use these for RAG. Set up vector stores in Tools > Vector Stores.",children:e=>(0,t.jsx)(t7.f,{onChange:e.onChange,value:e.value,accessToken:n,placeholder:"Select knowledge bases (optional)"})}),(0,t.jsx)(a8.I,{name:"guardrails",label:(0,t.jsxs)("span",{children:["Guardrails"," ",(0,t.jsx)(A.x,{content:"Apply safety guardrails to this key to filter content or enforce policies",children:(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,t.jsx)(et.f,{className:"ml-1 inline size-3.5 align-text-bottom"})})})]}),className:"mt-4",help:"Select existing guardrails. Go to 'Guardrails' tab to create new guardrails.",children:e=>(0,t.jsx)(l7.f,{id:e.id,placeholder:"Select or enter guardrails",emptyText:"Type to add a guardrail",value:e.value??[],onValueChange:e.onChange,options:r.map(e=>({value:e,label:e})),allowCustomValues:!0})}),(0,t.jsx)(a8.I,{name:"tags",label:"Tags",className:"mb-4",children:e=>(0,t.jsx)(l7.f,{id:e.id,placeholder:"Select or enter tags",emptyText:"Type to add a tag",value:e.value??[],onValueChange:e.onChange,options:Object.values(i).map(e=>({value:e.name,label:e.name,description:e.description||void 0})),allowCustomValues:!0})}),p&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a8.I,{name:L,label:(0,eW.q)("PTU Count","Provisioned throughput units for this deployment. Set together with Cost per PTU / Hour and a Team to attribute a flat daily cost."),rules:{deps:l8,validate:(0,a7.W)({validator:re},...V,$(R))},className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"e.g. 15"})}),(0,t.jsx)(a8.I,{name:R,label:(0,eW.q)("Calculated Cost per PTU / Hour (USD)","Flat cost = PTU count * this rate * active hours, attributed to the deployment's team."),rules:{deps:[L],validate:(0,a7.W)({validator:re},...B,$(L))},className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"e.g. 2.00"})}),(0,t.jsx)(a8.I,{name:q,label:(0,eW.q)("PTU Effective From (UTC)","Start of the PTU window, required when PTU Count is set. Flat cost accrues by the hour within the window; a window opening at 23:00 charges one hour that day."),rules:{deps:[F],validate:(0,a7.W)(({getFieldValue:e})=>({validator:(t,s)=>K(s)||!K(e(L))?Promise.resolve():Promise.reject(Error("PTU Effective From is required when PTU Count is set"))}),W(F,"start"))},className:"mb-4",children:e=>(0,t.jsx)(tW.f,{id:e.id,value:e.value,onChange:e.onChange,onBlur:e.onBlur})}),(0,t.jsx)(a8.I,{name:F,label:(0,eW.q)("PTU Effective To (UTC)","Optional end of the PTU window (exclusive). Leave blank for open-ended."),rules:{deps:[q],validate:(0,a7.W)(W(q,"end"))},className:"mb-4",children:e=>(0,t.jsx)(tW.f,{id:e.id,value:e.value,onChange:e.onChange,onBlur:e.onBlur})})]}),o&&(0,t.jsxs)("div",{className:"ml-6 pl-4 border-l-2 border-border",children:[(0,t.jsx)(a8.I,{name:"pricing_model",label:"Pricing Model",className:"mb-4",children:e=>{let s;return(0,t.jsxs)(tJ.d,{items:l9,value:e.value??"per_token",onValueChange:(s=e.onChange,e=>{null!==e&&(s(e),u(e))}),children:[(0,t.jsx)(tJ.P,{id:e.id,onBlur:e.onBlur,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:l9.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})}}),"per_token"===c?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a8.I,{name:"input_cost_per_token",label:"Input Cost (per 1M tokens)",rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur})}),(0,t.jsx)(a8.I,{name:"output_cost_per_token",label:"Output Cost (per 1M tokens)",rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur})}),(0,t.jsx)(a8.I,{name:"cache_read_input_token_cost",label:(0,eW.q)("Cache Read Cost (per 1M tokens)","If left blank, defaults to Input Cost."),rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Defaults to Input Cost if blank"})}),(0,t.jsx)(a8.I,{name:"cache_creation_input_token_cost",label:(0,eW.q)("Cache Write Cost (per 1M tokens)","If left blank, defaults to Input Cost (the backend falls back to input_cost_per_token when no cache-write rate is set)."),rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Defaults to Input Cost if blank"})}),(0,t.jsx)(a8.I,{name:"cache_creation_input_token_cost_above_1hr",label:(0,eW.q)("Cache Write Cost (1 hour, per 1M tokens)","Rate for prompt cache writes with a 1 hour TTL (Anthropic's cache_control ttl 1h). If left blank, known models use their cost map 1 hour rate, otherwise Cache Write Cost."),rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Defaults to the cost map 1 hour rate, else Cache Write Cost"})})]}):(0,t.jsx)(a8.I,{name:"input_cost_per_second",label:"Cost Per Second",rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur})})]}),(0,t.jsx)(a8.I,{name:"use_in_pass_through",label:(0,eW.q)("Use in pass through routes",(0,t.jsxs)("span",{children:["Allow using these credentials in pass through routes."," ",(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/pass_through/vertex_ai",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline-offset-4 hover:underline",children:"Learn more"})]})),className:"mb-4 mt-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:e.onChange})}),(0,t.jsx)(a8.I,{name:"kubernetes_pod_discovery",label:(0,eW.q)("Kubernetes pod discovery","Treat the API Base hostname as a Kubernetes headless service: resolve it to its ready pod IPs and spread requests across the pods. LiteLLM must run inside the same cluster."),className:"mb-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:e.onChange})}),(0,t.jsx)(a8.I,{name:"cache_control",label:(0,eW.q)(tZ,t0),className:"mb-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:t=>{e.onChange(t),h(t)}})}),m&&(0,t.jsx)(a8.I,{name:"cache_control_injection_points",defaultValue:[t1],bare:!0,children:e=>(0,t.jsx)(t6,{value:e.value,onChange:e.onChange})}),(0,t.jsx)(a8.I,{name:"litellm_extra_params",label:(0,eW.q)("LiteLLM Params","Optional litellm params used for making a litellm.completion() call."),className:"mb-4 mt-4",rules:{validate:(0,a7.W)({validator:eo.C})},children:e=>(0,t.jsx)(tt.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,rows:4,placeholder:'{\n "rpm": 100,\n "timeout": 0,\n "stream_timeout": 0\n }'})}),(0,t.jsx)("div",{className:"grid grid-cols-24 mb-4",children:(0,t.jsxs)("p",{className:"col-start-11 col-span-10 text-muted-foreground text-sm",children:["Pass JSON of litellm supported params"," ",(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline-offset-4 hover:underline",children:"litellm.completion() call"})]})}),(0,t.jsx)(a8.I,{name:"model_info_params",label:(0,eW.q)("Model Info","Optional model info params. Returned when calling `/model/info` endpoint."),className:"mb-0",rules:{validate:(0,a7.W)({validator:eo.C})},children:e=>(0,t.jsx)(tt.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,rows:4,placeholder:'{\n "mode": "chat"\n }'})})]})})]})})},ra={validator:async(e,t)=>{if(!t||0===t.length)throw Error("At least one model mapping is required");if(t.filter(e=>!e.public_name||""===e.public_name.trim()).length>0)throw Error("All model mappings must have valid public names")}},rl="rounded-sm bg-background/20 px-1 py-0.5 font-mono text-xs",rr=JSON.stringify({extra_headers:{"anthropic-beta":"context-1m-2025-08-07"}},null,2),ri=(0,t.jsxs)("div",{className:"flex flex-col gap-2 text-left font-normal",children:[(0,t.jsx)("div",{children:"The name you specify in your API calls to LiteLLM Proxy"}),(0,t.jsxs)("div",{children:[(0,t.jsx)("strong",{children:"Example:"})," If you name your public model ",(0,t.jsx)("code",{className:rl,children:"example-name"}),", and choose ",(0,t.jsx)("code",{className:rl,children:"openai/qwen-plus-latest"})," as the LiteLLM model"]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("strong",{children:"Usage:"})," You make an API call to the LiteLLM proxy with"," ",(0,t.jsx)("code",{className:rl,children:'model = "example-name"'})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("strong",{children:"Result:"})," LiteLLM sends ",(0,t.jsx)("code",{className:rl,children:"qwen-plus-latest"})," to the provider"]})]}),rn=({index:e,value:s})=>{let a=(0,tD.M)(),l=(0,tD.h)({control:a.control,name:"custom_llm_provider"});return(0,t.jsx)(eX.f,{value:s,onChange:t=>{let s=t.target.value,r=a.getValues("litellm_extra_params"),i=l===a9.g.Anthropic&&s.endsWith("-1m")&&""===(r??"").trim();i&&a.setValue("litellm_extra_params",rr);let n=i?s.slice(0,-3):s,o=a.getValues("model_mappings")??[];a.setValue("model_mappings",o.map((t,s)=>s===e?{...t,public_name:n}:t))}})},ro=[{id:"public_name",accessorKey:"public_name",header:()=>(0,t.jsxs)("span",{className:"flex items-center",children:["Public Model Name",(0,t.jsx)(A.x,{content:ri,width:"500px"})]}),cell:({row:e})=>(0,t.jsx)(rn,{index:e.index,value:e.original.public_name})},{id:"litellm_model",accessorKey:"litellm_model",header:()=>(0,t.jsxs)("span",{className:"flex items-center",children:["LiteLLM Model Name",(0,t.jsx)(A.x,{content:(0,t.jsx)("div",{children:"The model name LiteLLM will send to the LLM API"}),width:"360px"})]})}],rd=()=>{let e=(0,tD.M)(),a=(0,tD.h)({control:e.control,name:"model"})||[],l=JSON.stringify(Array.isArray(a)?a:[a]),r=(0,s.useMemo)(()=>JSON.parse(l),[l]),i=(0,tD.h)({control:e.control,name:"custom_model_name"}),n=!r.includes("all-wildcard"),o=(0,tD.h)({control:e.control,name:"custom_llm_provider"});return((0,s.useEffect)(()=>{if(i&&r.includes("custom")){let t=e.getValues("model_mappings")||[],s=t.map(e=>"custom"===e.public_name||"custom"===e.litellm_model?o===a9.g.Azure?{public_name:i,litellm_model:`azure/${i}`}:{public_name:i,litellm_model:i}:e);t.length===s.length&&t.every((e,t)=>e.public_name===s[t].public_name&&e.litellm_model===s[t].litellm_model)||e.setValue("model_mappings",s)}},[i,r,o,e]),(0,s.useEffect)(()=>{if(r.length>0&&!r.includes("all-wildcard")){let t=e.getValues("model_mappings")||[];if(t.length!==r.length||!r.every(e=>t.some(t=>"custom"===e?"custom"===t.litellm_model||t.litellm_model===i:o===a9.g.Azure?t.litellm_model===`azure/${e}`:t.litellm_model===e))){let t=r.map(e=>"custom"===e&&i?o===a9.g.Azure?{public_name:i,litellm_model:`azure/${i}`}:{public_name:i,litellm_model:i}:o===a9.g.Azure?{public_name:e,litellm_model:`azure/${e}`}:{public_name:e,litellm_model:e});e.setValue("model_mappings",t)}}},[r,i,o,e]),n)?(0,t.jsx)(a8.I,{name:"model_mappings",label:(0,t.jsxs)("span",{className:"flex items-center",children:["Model Mappings",(0,t.jsx)(A.x,{content:"Map public model names to LiteLLM model names for load balancing"})]}),required:!0,rules:{validate:(0,a7.W)(ra)},className:"mb-4",children:e=>(0,t.jsx)(sR.f,{data:e.value??[],columns:ro,getRowId:e=>e.litellm_model,size:"compact"})}):null},rc=({selectedProvider:e,providerModels:s,getPlaceholder:a})=>{let l=(0,tD.M)(),r=(0,tD.h)({control:l.control,name:"model"}),i=Array.isArray(r)?r:[r];return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a8.I,{name:"model",label:(0,eW.q)("LiteLLM Model Name(s)","The model name LiteLLM will send to the LLM API"),required:!0,rules:{validate:{required:(0,a7.B)(`Please enter ${e===a9.g.Azure?"a deployment name":"at least one model"}.`)}},className:"mb-0",children:r=>e===a9.g.Azure||e===a9.g.OpenAI_Compatible||e===a9.g.Ollama?(0,t.jsx)(eX.f,{id:r.id,value:r.value??"",onBlur:r.onBlur,placeholder:null===e?"Select a provider first":a(e),onChange:t=>{let s,a;r.onChange(t),e===a9.g.Azure&&(a=(s=t.target.value)?[{public_name:s,litellm_model:`azure/${s}`}]:[],l.setValue("model",s),l.setValue("model_mappings",a))}}):s.length>0&&("string"!=typeof r.value||""===r.value)?(0,t.jsx)(l7.f,{id:r.id,placeholder:"Select models",emptyText:"No models found",value:Array.isArray(r.value)?r.value:[],onValueChange:t=>{r.onChange(t);let s=Array.isArray(t)?t:[t];if(s.includes("all-wildcard"))l.setValue("model_name",void 0),l.setValue("model_mappings",[]);else if(JSON.stringify(l.getValues("model"))!==JSON.stringify(s)){let t=s.map(t=>e===a9.g.Azure?{public_name:t,litellm_model:`azure/${t}`}:{public_name:t,litellm_model:t});l.setValue("model",s),l.setValue("model_mappings",t)}},options:[{label:"Custom Model Name (Enter below)",value:"custom"},{label:`All ${e??"provider"} Models (Wildcard)`,value:"all-wildcard"},...s.map(e=>({label:e,value:e}))],className:"w-full"}):(0,t.jsx)(eX.f,{id:r.id,value:r.value??"",onChange:r.onChange,onBlur:r.onBlur,placeholder:null===e?"Select a provider first":a(e)})}),i.includes("custom")&&(0,t.jsx)(a8.I,{name:"custom_model_name",required:!0,rules:{validate:{required:(0,a7.B)("Please enter a custom model name.")}},className:"mt-2",children:s=>(0,t.jsx)(eX.f,{id:s.id,value:s.value??"",onBlur:s.onBlur,placeholder:e===a9.g.Azure?"Enter Azure deployment name":"Enter custom model name",onChange:t=>{let a,r;s.onChange(t),a=t.target.value,r=(l.getValues("model_mappings")||[]).map(t=>"custom"===t.public_name||"custom"===t.litellm_model?e===a9.g.Azure?{public_name:a,litellm_model:`azure/${a}`}:{public_name:a,litellm_model:a}:t),l.setValue("model_mappings",r)}})}),(0,t.jsx)("div",{className:"grid grid-cols-24",children:(0,t.jsx)("p",{className:"col-start-11 col-span-14 text-sm mb-3 mt-1",children:e===a9.g.Azure?"Your deployment name will be saved as the public model name, and LiteLLM will use 'azure/deployment-name' internally":"The model name LiteLLM will send to the LLM API"})})]})};var ru=e.i(878894),rm=e.i(778917);let rh=async(e,t,s)=>{try{let t=e.model_mappings||[];if("model_mappings"in e&&delete e.model_mappings,e.model&&e.model.includes("all-wildcard")){let s=e.custom_llm_provider,a=(0,a9.C)(s)+"/*";e.model_name=a,t.push({public_name:a,litellm_model:a}),e.model=a}void 0!==e.input_cost_per_token&&null!==e.input_cost_per_token&&""!==e.input_cost_per_token&&(e.input_cost_per_token=Number(e.input_cost_per_token)/1e6),void 0!==e.output_cost_per_token&&null!==e.output_cost_per_token&&""!==e.output_cost_per_token&&(e.output_cost_per_token=Number(e.output_cost_per_token)/1e6),void 0!==e.cache_read_input_token_cost&&null!==e.cache_read_input_token_cost&&""!==e.cache_read_input_token_cost?e.cache_read_input_token_cost=Number(e.cache_read_input_token_cost)/1e6:void 0!==e.input_cost_per_token&&null!==e.input_cost_per_token&&""!==e.input_cost_per_token?e.cache_read_input_token_cost=Number(e.input_cost_per_token):delete e.cache_read_input_token_cost,void 0!==e.cache_creation_input_token_cost&&null!==e.cache_creation_input_token_cost&&""!==e.cache_creation_input_token_cost?e.cache_creation_input_token_cost=Number(e.cache_creation_input_token_cost)/1e6:delete e.cache_creation_input_token_cost,void 0!==e.cache_creation_input_token_cost_above_1hr&&null!==e.cache_creation_input_token_cost_above_1hr&&""!==e.cache_creation_input_token_cost_above_1hr?e.cache_creation_input_token_cost_above_1hr=Number(e.cache_creation_input_token_cost_above_1hr)/1e6:delete e.cache_creation_input_token_cost_above_1hr;let s=[];for(let a of t){let t={},l={},r=a.public_name;for(let[s,r]of(t.model=a.litellm_model,t.model=a.litellm_model,Object.entries(e)))if(""!==r&&("litellm_credential_name"!==s||null!=r)&&"custom_pricing"!==s&&"pricing_model"!==s&&"cache_control"!==s)if("model_name"==s)t.model=r;else if("custom_llm_provider"==s)t.custom_llm_provider=(0,a9.C)(r);else if("model"==s)continue;else if("base_model"===s)l[s]=r;else if("team_id"===s)l.team_id=r;else if("model_access_group"===s)l.access_groups=r;else if("mode"==s)l.mode=r,delete t.mode;else if("custom_model_name"===s)t.model=r;else if("litellm_extra_params"==s){let s={};if(r&&void 0!=r){try{s=JSON.parse(r)}catch(e){throw eH.f.fromError("Failed to parse LiteLLM Extra Params: "+e),Error("Failed to parse litellm_extra_params: "+e)}for(let[a,l]of("litellm_credential_name"in s&&e.litellm_credential_name&&delete s.litellm_credential_name,Object.entries(s)))t[a]=l}}else if("model_info_params"==s){let e={};if(r&&void 0!=r){try{e=JSON.parse(r)}catch(e){throw eH.f.fromError("Failed to parse LiteLLM Extra Params: "+e),Error("Failed to parse litellm_extra_params: "+e)}for(let[t,s]of Object.entries(e))l[t]=s}}else if("input_cost_per_token"===s||"output_cost_per_token"===s||"input_cost_per_second"===s||"cache_read_input_token_cost"===s||"cache_creation_input_token_cost"===s||"cache_creation_input_token_cost_above_1hr"===s){null!=r&&""!==r&&(t[s]=Number(r));continue}else if("ptu_count"===s||"cost_per_ptu_per_hour"===s){null!=r&&""!==r&&(l[s]=Number(r));continue}else if("ptu_effective_from"===s||"ptu_effective_to"===s){let e=z(r);null!==e&&(l[s]=e);continue}else t[s]=r;s.push({litellmParamsObj:t,modelInfoObj:l,modelName:r})}return s}catch(e){eH.f.fromError("Failed to create model: "+e)}},rp=async(e,t,s,a)=>{try{let l=await rh(e,t,s);if(!l||0===l.length)return;for(let e of l){let{litellmParamsObj:s,modelInfoObj:a,modelName:l}=e,r={model_name:l,litellm_params:s,model_info:a};await (0,em.jO)(t,r)}a&&a(),s.resetFields()}catch(e){eH.f.fromError("Failed to add model: "+e)}},rf=({formValues:e,accessToken:a,testMode:l,modelName:r="this model",onClose:i,onTestComplete:n})=>{var o,d,c;let u,m,[h,p]=s.default.useState(null),[f,x]=s.default.useState(null),[_,j]=s.default.useState(!0),[v,b]=s.default.useState(!1),[y,N]=s.default.useState(!1),k=async()=>{j(!0),N(!1),p(null),x(null),b(!1),await new Promise(e=>setTimeout(e,100));try{let t=await rh(e,a,null);if(!t?.length){p(t?"Required fields are not filled in. Fill them in and test the connection again.":"Failed to prepare model data. Please check your form inputs."),b(!1),j(!1);return}let{litellmParamsObj:s,modelInfoObj:l}=t[0],r=await (0,em.ym)(a,s,l,l?.mode);if("success"===r.status)eH.f.success("Connection test successful!"),p(null),b(!0);else{let e=r.result?.error||r.message||"Unknown error";p(e),x(r.result?.raw_request_typed_dict),b(!1)}}catch(e){console.error("Test connection error:",e),p(e instanceof Error?e.message:String(e)),b(!1)}finally{j(!1),n?.()}};s.default.useEffect(()=>{let e=setTimeout(()=>{k()},200);return()=>clearTimeout(e)},[]);let w=e=>e?e.split("stack trace:")[0].trim().replace(/^litellm\.(.*?)Error: /,""):"Unknown error",C="string"==typeof h?w(h):h?.message?w(h.message):"Unknown error",S=f?(o=f.raw_request_api_base,d=f.raw_request_body,c=f.raw_request_headers||{},u=JSON.stringify(d,null,2).split("\n").map(e=>` ${e}`).join("\n"),m=Object.entries(c).map(([e,t])=>`-H '${e}: ${t}'`).join(" \\\n "),`curl -X POST \\ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,664307,e=>{"use strict";var t=e.i(843476),s=e.i(271645),a=e.i(16715),l=e.i(438847),r=e.i(912598),i=e.i(135214),n=e.i(785242),o=e.i(292639),d=e.i(802954),c=e.i(708347),u=e.i(707728),m=e.i(218842),h=e.i(972520),p=e.i(283086),f=e.i(37727),x=e.i(735450),_=e.i(782066),g=e.i(519455);let j="hideDecisionModelsBanner",v=()=>{let[e,a]=(0,s.useState)(()=>"true"===localStorage.getItem(j));return e?null:(0,t.jsxs)("div",{className:"mb-4 flex items-center gap-4 rounded-lg border bg-muted/40 px-4 py-3",children:[(0,t.jsx)("div",{className:"flex size-10 shrink-0 items-center justify-center rounded-full border bg-background",children:(0,t.jsx)(p.f,{className:"size-4 text-muted-foreground"})}),(0,t.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,t.jsx)("h4",{className:"m-0 text-sm font-semibold text-foreground",children:"Decision models are now supported"}),(0,t.jsxs)("p",{className:"m-0 mt-0.5 text-xs text-muted-foreground",children:["Call them at ",(0,t.jsx)("code",{children:"/v1/decisions"})," or ",(0,t.jsx)("code",{children:"/v1/systemone"}),", or try them in the Decisions playground."," ",(0,t.jsx)("a",{href:x.O,target:"_blank",rel:"noopener noreferrer",className:"underline",children:"How to call them"})]})]}),(0,t.jsx)(g.K,{variant:"outline",className:"shrink-0",nativeButton:!1,role:"link",render:(0,t.jsx)("a",{href:x.Z,target:"_blank",rel:"noopener noreferrer"}),children:"Supported providers"}),(0,t.jsxs)(g.K,{className:"shrink-0",nativeButton:!1,role:"link",render:(0,t.jsx)("a",{href:(0,_.B)(x.B)}),children:["Try decision models",(0,t.jsx)(h.f,{})]}),(0,t.jsx)(g.K,{type:"button",variant:"ghost",size:"icon-sm",onClick:()=>{a(!0),localStorage.setItem(j,"true")},className:"shrink-0","aria-label":"Dismiss banner",children:(0,t.jsx)(f.X,{})})]})};var b=e.i(368670),y=e.i(625901);let N=/^output_cost_per_second_(.+)$/,k=e=>null==e?null:(1e6*Number(e)).toFixed(2),w=(e,t)=>e?.data?{data:e.data.map(e=>{var s,a;let l,r,i;return s=e,a=t,r=(l=JSON.parse(JSON.stringify(s))).litellm_params,i=l.model_info,{...l,provider:((e,t,s)=>{if(!e)return"-";if(t)return t;let a=e.split("/");return 1===a.length?s(e):a[0]})(r.model,r.custom_llm_provider,a),input_cost:k(i?.input_cost_per_token),output_cost:k(i?.output_cost_per_token),output_cost_per_second:r.output_cost_per_second??i?.output_cost_per_second??null,output_cost_per_second_tiers:Object.entries(i??{}).flatMap(([e,t])=>{let s=N.exec(e)?.[1];return void 0!==s&&"number"==typeof t?[{resolution:s,cost:t}]:[]}),litellm_model_name:r.model,max_tokens:i?.max_tokens,max_input_tokens:i?.max_input_tokens,api_base:r.api_base,cleanedLitellmParams:Object.fromEntries(Object.entries(r).filter(([e])=>"model"!==e&&"api_base"!==e))}})}:{data:[]},C=s.forwardRef(function(e,t){return s.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),s.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"}))});var S=e.i(278587),M=e.i(68155),E=e.i(515288),T=e.i(677572),A=e.i(746798),P=e.i(822315),I=e.i(895751);P.default.extend(I.default);let z=e=>e&&"function"==typeof e.format?"function"==typeof e.isUTC&&e.isUTC()?e.toISOString():P.default.utc(e.format("YYYY-MM-DDTHH:mm:ss")).toISOString():null,O=e=>{if(!e)return null;let t=P.default.utc(e);return t.isValid()?t:null},L="ptu_count",R="cost_per_ptu_per_hour",q="ptu_effective_from",F="ptu_effective_to",K=e=>null!=e&&""!==e,D=e=>{if(!K(e))return!0;let t=Number(e);return Number.isInteger(t)&&t>0&&t<=1e6},V=[{validator:(e,t)=>D(t)?Promise.resolve():Promise.reject(Error(`PTU Count must be a whole number between 1 and ${1e6.toLocaleString()}`))}],U=e=>{if(!K(e))return!0;let t=Number(e);return Number.isFinite(t)&&t>=0&&t<=1e6},B=[{validator:(e,t)=>U(t)?Promise.resolve():Promise.reject(Error(`Cost per PTU / Hour must be between 0 and ${1e6.toLocaleString()}`))}],$=e=>({getFieldValue:t})=>({validator:(s,a)=>K(a)===K(t(e))?Promise.resolve():Promise.reject(Error("PTU Count and Cost per PTU / Hour must be set together"))}),G=e=>{let t=Number(e?.valueOf?.());return Number.isFinite(t)?t:new Date(String(e)).getTime()},H=(e,t)=>{if(!K(e)||!K(t))return!0;let s=G(e),a=G(t);return Number.isNaN(s)||Number.isNaN(a)||a>s},W=(e,t)=>({getFieldValue:s})=>({validator:(a,l)=>{let r=s(e);return H("start"===t?l:r,"start"===t?r:l)?Promise.resolve():Promise.reject(Error("PTU Effective To must be after PTU Effective From"))}}),J=[L,R,"ptu_effective_from","ptu_effective_to"],Y=e=>null!=e&&""!==e?Number(e):null,X=()=>{let{data:e}=(0,o.f)(),t=e?.values?.enable_ptu_cost_attribution===!0;return(0,o.f)(t?{staleTime:3e4,refetchInterval:3e4}:void 0),t};var Q=e.i(871689),Z=e.i(678784),ee=e.i(118366),et=e.i(952571),es=e.i(500330);let ea=e=>"string"==typeof e&&/\*{2,}/.test(e),el=e=>Object.fromEntries(Object.entries(e).filter(([,e])=>!ea(e))),er=new Set(["api_base","custom_llm_provider","organization","tpm","rpm","max_retries","timeout","stream_timeout","model","input_cost_per_token","output_cost_per_token","cache_read_input_token_cost","cache_creation_input_token_cost","cache_creation_input_token_cost_above_1hr","litellm_credential_name","cache_control_injection_points","vector_store_ids","guardrails","tags"]),ei=e=>Object.fromEntries(Object.entries(e).filter(([e,t])=>!er.has(e)&&!ea(t))),en=e=>{try{let t=JSON.parse(e?.trim()||"{}");return null===t||"object"!=typeof t||Array.isArray(t)?null:t}catch{return null}};var eo=e.i(122550),ed=e.i(101048),ec=e.i(832724),eu=e.i(164668),em=e.i(602869),eh=e.i(776639);let ep=({accessToken:e,targets:a,jevRequest:l,onTestComplete:r})=>{let[i,n]=s.default.useState(()=>a.map(()=>({status:"pending"}))),[o,d]=s.default.useState({status:"pending"});return(s.default.useEffect(()=>{let t=!1,s=async()=>{if(!l)return;let s=await (0,em.b)(e,l);if(t)return;if("error"===s.status)return void d(s);let a=s.result.routing_decision;d("jev_classifier"===a.cause?{status:"success"}:{status:"error",error:`OSS classifier was not reached successfully (routing cause: ${a.cause??"unknown"})`})};return(async()=>{await Promise.all([s(),...a.map(async(s,a)=>{let l=s.requestParams?await (0,em.EA)(e,s.modelGroup,s.mode,s.requestParams):await (0,em.EA)(e,s.modelGroup,s.mode);if(t)return;let r="error"===l.status?{status:"error",error:l.error.split("stack trace:")[0].trim().replace(/^litellm\.(.*?)Error: /,"")}:l;n(e=>e.map((e,t)=>t===a?r:e))})]),!t&&r&&r()})(),()=>{t=!0}},[]),0!==a.length||l)?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)("p",{className:"mb-2 text-sm text-muted-foreground",children:"Test Connection sends a minimal request to every configured tier, classifier, default, and embedding model. The classifier probe includes its reasoning effort override."}),l&&(0,t.jsxs)("div",{role:"status","aria-label":"OSS classifier connection",className:"rounded-lg border p-3 text-sm",children:[(0,t.jsx)("strong",{children:"OSS Classifier"}),(0,t.jsxs)("p",{children:["pending"===o.status&&"Testing OSS classification","success"===o.status&&"OSS classification succeeded","error"===o.status&&o.error]})]}),a.map((e,s)=>{let a=i[s]??{status:"pending"};return(0,t.jsxs)("div",{"data-testid":"auto-router-test-row",className:"flex items-start gap-3 rounded-lg border p-3",children:[(0,t.jsxs)("div",{className:"pt-0.5",children:["pending"===a.status&&(0,t.jsx)(eu.f,{className:"size-5 animate-spin text-muted-foreground","data-testid":"test-status-pending"}),"success"===a.status&&(0,t.jsx)(ed.f,{className:"size-5 text-primary","data-testid":"test-status-success"}),"error"===a.status&&(0,t.jsx)(ec.f,{className:"size-5 text-destructive","data-testid":"test-status-error"})]}),(0,t.jsxs)("div",{className:"min-w-0 flex-1 text-sm",children:[(0,t.jsx)("span",{className:"font-medium",children:e.labels.join(", ")})," ",(0,t.jsxs)("span",{className:"text-muted-foreground",children:["->"," ",e.modelGroup,"embedding"===e.mode?" (embedding)":""]}),"error"===a.status&&(0,t.jsx)("p",{className:"mt-1 text-xs text-destructive","data-testid":"test-error-message",children:a.error})]})]},`${e.labels.join("-")}-${e.modelGroup}-${e.mode}`)})]}):(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"No complexity tiers are configured yet, so there is nothing to test."})};function ef({open:e,onClose:s,testId:a,...l}){return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&s(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[700px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Connection Test Results"})}),e&&(0,t.jsx)(ep,{...l},a),(0,t.jsx)(eh.c,{children:(0,t.jsx)(g.K,{variant:"outline",onClick:s,children:"Close"})})]})})}var ex=e.i(411382),e_=e.i(282492),eg=e.i(240192),ej=e.i(54105),ev=e.i(138620),eb=e.i(996389);let ey="What is 2 plus 2?",eN=({prompt:e,config:t,defaultModel:s,routerName:a,teamId:l})=>({prompt:e,complexity_router_config:t,...s?{default_model:s}:{},...a?.trim()?{router_name:a.trim()}:{},...l?{team_id:l}:{}});var ek=e.i(869255);let ew=({tiers:e,semanticMatchingEnabled:t,embeddingModel:s,defaultModel:a,classifier:l})=>{let r=e.reduce((e,[t,s])=>s.reduce((e,s)=>{let a=s?.trim();return a?{...e,[a]:[...e[a]??[],t]}:e},e),{}),i=a?.trim(),n=Object.entries(!i||i in r?r:{...r,[i]:["Default"]}).map(([e,t])=>({labels:t,modelGroup:e,mode:"chat"})),o=t&&s?.trim()?[{labels:["Embedding"],modelGroup:s.trim(),mode:"embedding"}]:[],d=l?.model.trim();return[...n,...o,...d?[{labels:["Classifier"],modelGroup:d,mode:"chat",...l?.reasoningEffort&&{requestParams:{reasoning_effort:l.reasoningEffort}}}]:[]]},eC=(e,t)=>e.model?.startsWith(t)===!0,eS=[{kind:"complexity",label:"Complexity",configKey:"complexity_router_config",defaultModelKey:"complexity_router_default_model",hasEditor:!0,matches:e=>eC(e,"auto_router/complexity_router")||null!=e.complexity_router_config},{kind:"adaptive",label:"Adaptive",configKey:"adaptive_router_config",defaultModelKey:"adaptive_router_default_model",hasEditor:!1,matches:e=>eC(e,"auto_router/adaptive_router")},{kind:"quality",label:"Quality",configKey:"quality_router_config",defaultModelKey:"quality_router_default_model",hasEditor:!1,matches:e=>eC(e,"auto_router/quality_router")},{kind:"semantic",label:"Semantic",configKey:"auto_router_config",defaultModelKey:"auto_router_default_model",hasEditor:!0,matches:()=>!0}],eM=e=>eS.find(t=>t.matches(e??{})),eE=e=>"complexity"===eM(e).kind,eT=e=>e?.model?.startsWith("auto_router/")===!0||e?.complexity_router_config!=null||e?.auto_router_config!=null;var eA=e.i(127952),eP=e.i(266027),eI=e.i(552546),ez=e.i(110204);function eO({value:e,onChange:a,modelInfo:l,deployments:r}){let i=s.default.useId(),{data:n}=(0,b.X)(!0,!0),o=s.default.useMemo(()=>(0,x.F)(n),[n]),d=l.filter(e=>(0,x._)(e.mode)||(r??[]).some(t=>t.model_name===e.model_group&&(0,x.r)(o,t.litellm_params?.custom_llm_provider??t.litellm_params?.model?.split("/")[0],[t.litellm_params?.model??"",t.litellm_params?.base_model??""])));return(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{htmlFor:i,children:"Decision model"}),(0,t.jsx)(eI.f,{inputId:i,"aria-label":"Decision model",options:d.map(e=>({value:e.model_group,label:e.model_group})),value:e.jev_classifier_config?.deployment_name??"",placeholder:"Select the decision model",allowClear:!1,onValueChange:t=>{t&&a({...e,jev_classifier_config:{...e.jev_classifier_config??(0,eb.c)(),deployment_name:t}})}})]})}var eL=e.i(372339),eR=e.i(100372),eq=e.i(131688),eF=e.i(961540),eK=e.i(772325);let eD={auto_router_name:ej.z.string().min(1,"Auto router name is required"),model_access_group:eK.z.array(ej.z.string())},eV={...eD,auto_router_default_model:ej.z.string().nullable().transform(e=>e??""),auto_router_embedding_model:ej.z.string().nullable().transform(e=>e??"")},eU={...eD,auto_router_default_model:ej.z.string().nullable().pipe(ej.z.string({error:"Default model is required"}).min(1,"Default model is required")),auto_router_embedding_model:ej.z.string().nullable().pipe(ej.z.string({error:"Embedding model is required"}).min(1,"Embedding model is required"))},eB=ex.z.object(eV),e$=ex.z.object(eU),eG={auto_router_name:"",auto_router_default_model:null,auto_router_embedding_model:null,model_access_group:[]};var eH=e.i(417385),eW=e.i(547756),eJ=e.i(542450),eY=e.i(182668),eX=e.i(793479),eQ=e.i(571303),eZ=e.i(991326),e0=e.i(131792);let e1=({id:e,value:a,onChange:l,options:r,ariaInvalid:i,ariaDescribedBy:n})=>{let o=(0,e0.d)(),[d,c]=(0,s.useState)(""),u=a??[],m=d.trim(),h=m&&!r.includes(m)?[...r,m]:r,p=e=>{l(Array.from(new Set(e))),c("")};return(0,t.jsxs)(e0.x,{multiple:!0,autoHighlight:!0,items:h,value:u,onValueChange:p,inputValue:d,onInputValueChange:e=>{e.includes(",")?p([...u,...e.split(",").map(e=>e.trim()).filter(Boolean)]):c(e)},children:[(0,t.jsx)(e0.V,{render:(0,t.jsx)("div",{ref:o}),children:(0,t.jsx)(e0.l,{children:s=>(0,t.jsxs)(t.Fragment,{children:[s.map(e=>(0,t.jsx)(e0.Q,{"aria-label":e,children:e},e)),(0,t.jsx)(e0.z,{id:e,"aria-invalid":i,"aria-describedby":n,placeholder:"Select existing groups or type to create new ones"})]})})}),(0,t.jsxs)(e0.R,{anchor:o,children:[(0,t.jsx)(e0.S,{children:"No access groups found"}),(0,t.jsx)(e0.k,{children:e=>(0,t.jsx)(e0.T,{value:e,children:e},e)})]})]})},e2=({id:e,value:s,onChange:a,choices:l,placeholder:r,ariaInvalid:i,ariaDescribedBy:n})=>{let o=s?l.find(e=>e.value===s)??{value:s,label:s}:null;return(0,t.jsxs)(e0.x,{items:l,value:o,onValueChange:e=>a(e?.value??null),itemToStringLabel:e=>e.label,isItemEqualToValue:(e,t)=>e.value===t.value,children:[(0,t.jsx)(e0.c,{id:e,"aria-invalid":i,"aria-describedby":n,placeholder:r,className:"w-full",showClear:null!=s&&""!==s}),(0,t.jsxs)(e0.R,{children:[(0,t.jsx)(e0.S,{children:"No models found"}),(0,t.jsx)(e0.k,{children:e=>(0,t.jsx)(e0.T,{value:e,children:e.label},e.value)})]})]})};var e4=e.i(695411),e5=e.i(664659),e6=e.i(359360),e3=e.i(107233),e7=e.i(727612),e8=e.i(487486),e9=e.i(204258),te=e.i(772436),tt=e.i(624687);let ts=({value:e,onChange:a})=>{let[l,r]=(0,s.useState)(""),i=t=>{let s=Array.from(new Set([...e,...t.split("\n").map(e=>e.trim()).filter(e=>""!==e)]));s.length>e.length&&a(s),r("")};return(0,t.jsxs)("div",{className:"flex min-h-9 w-full flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2.5 py-1.5 shadow-xs transition-[color,box-shadow] focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 dark:bg-input/30",children:[e.map(s=>(0,t.jsxs)(e8.f,{variant:"secondary",className:"max-w-full gap-1 pr-1",children:[(0,t.jsx)("span",{className:"truncate",children:s}),(0,t.jsx)("button",{type:"button","aria-label":`Remove ${s}`,className:"rounded-full p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",onClick:()=>a(e.filter(e=>e!==s)),children:(0,t.jsx)(f.X,{className:"size-3"})})]},s)),(0,t.jsx)("input",{"aria-label":"Example Utterances",value:l,onChange:e=>r(e.target.value),onBlur:()=>l.trim()&&i(l),onKeyDown:t=>{"Enter"===t.key&&l.trim()?(t.preventDefault(),i(l)):"Backspace"===t.key&&""===l&&e.length>0&&a(e.slice(0,-1))},onPaste:e=>{let t=e.clipboardData.getData("text");t.includes("\n")&&(e.preventDefault(),i(t))},placeholder:0===e.length?"Type an utterance and press Enter...":void 0,className:"min-w-48 flex-1 bg-transparent py-0.5 text-sm outline-none placeholder:text-muted-foreground"})]})},ta=({content:e})=>(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("button",{type:"button","aria-label":e,className:"inline-flex rounded-sm text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"}),children:(0,t.jsx)(e6.f,{className:"size-4"})}),(0,t.jsx)(A.Y,{children:e})]}),tl=({modelInfo:e,value:a,onChange:l})=>{let[r,i]=(0,s.useState)([]),[n,o]=(0,s.useState)(!1),[d,c]=(0,s.useState)([]);(0,s.useEffect)(()=>{let e=a?.routes;if(e){let t=[];i(s=>e.map((e,a)=>{let l=s[a],r=l?.id||e.id||`route-${a}-${Date.now()}`;return t.push(r),{id:r,model:e.name||e.model||null,utterances:e.utterances||[],description:e.description||"",score_threshold:e.score_threshold??.5}})),c(t)}else i([]),c([])},[a]);let u=e=>{l?.({routes:e.map(e=>({name:e.model,utterances:e.utterances,description:e.description,score_threshold:e.score_threshold}))})},m=(e,t,s)=>{let a=r.map(a=>a.id===e?{...a,[t]:s}:a);i(a),u(a)},h=e.map(e=>({value:e.model_group,label:e.model_group})),p={routes:r.map(e=>({name:e.model,utterances:e.utterances,description:e.description,score_threshold:e.score_threshold}))};return(0,t.jsx)(A.g,{children:(0,t.jsxs)("div",{className:"w-full space-y-6",children:[(0,t.jsxs)("div",{className:"flex w-full flex-wrap items-center justify-between gap-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold",children:"Routes Configuration"}),(0,t.jsx)(ta,{content:"Configure routing logic to automatically select the best model based on user input patterns"})]}),(0,t.jsxs)(g.K,{type:"button",onClick:()=>{let e=`route-${Date.now()}`,t=[...r,{id:e,model:null,utterances:[],description:"",score_threshold:.5}];i(t),u(t),c(t=>[...t,e])},children:[(0,t.jsx)(e3.f,{"data-icon":"inline-start"}),"Add Route"]})]}),0===r.length?(0,t.jsx)(E.N,{children:(0,t.jsx)(E.O,{className:"py-8 text-center text-muted-foreground",children:'No routes configured. Click "Add Route" to get started.'})}):(0,t.jsx)("div",{className:"space-y-3",children:r.map((e,s)=>{let a=d.includes(e.id);return(0,t.jsxs)(e9.Y,{open:a,onOpenChange:t=>c(s=>t?[...s,e.id]:s.filter(t=>t!==e.id)),className:"overflow-hidden rounded-xl border bg-card shadow-xs",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 px-4 py-3",children:[(0,t.jsxs)(e9.v,{render:(0,t.jsx)("button",{type:"button",className:"flex min-w-0 flex-1 items-center gap-2 text-left"}),children:[(0,t.jsx)(e5.f,{className:`size-4 shrink-0 text-muted-foreground transition-transform ${a?"rotate-180":""}`}),(0,t.jsxs)("span",{className:"truncate text-base font-medium",children:["Route ",s+1,": ",e.model||"Unnamed"]})]}),(0,t.jsx)(g.K,{type:"button","aria-label":"delete",variant:"ghost",size:"icon-sm",onClick:()=>{var t;let s;return t=e.id,void(i(s=r.filter(e=>e.id!==t)),u(s),c(e=>e.filter(e=>e!==t)))},children:(0,t.jsx)(e7.f,{className:"text-destructive"})})]}),(0,t.jsxs)(e9.C,{children:[(0,t.jsx)(te.f,{}),(0,t.jsxs)("div",{className:"space-y-4 p-4",children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{children:"Model"}),(0,t.jsx)(eI.f,{value:e.model,onValueChange:t=>m(e.id,"model",t),placeholder:"Select model",options:h})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{htmlFor:`${e.id}-description`,children:"Description"}),(0,t.jsx)(tt.f,{id:`${e.id}-description`,value:e.description,onChange:t=>m(e.id,"description",t.target.value),placeholder:"Describe when this route should be used...",rows:2})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(ez.f,{htmlFor:`${e.id}-threshold`,children:"Score Threshold"}),(0,t.jsx)(ta,{content:"Minimum similarity score to route to this model (0-1)"})]}),(0,t.jsx)(eX.f,{id:`${e.id}-threshold`,type:"number",value:e.score_threshold,onChange:t=>m(e.id,"score_threshold",Number(t.target.value)||0),min:0,max:1,step:.1,placeholder:"0.5"})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(ez.f,{children:"Example Utterances"}),(0,t.jsx)(ta,{content:"Training examples for this route. Type an utterance and press Enter to add it."})]}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground",children:"Type an utterance and press Enter to add it. You can also paste multiple lines."}),(0,t.jsx)(ts,{value:e.utterances,onChange:t=>m(e.id,"utterances",t)})]})]})]})]},e.id)})}),(0,t.jsx)(te.f,{}),(0,t.jsxs)("div",{className:"flex w-full items-center justify-between gap-3",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold",children:"JSON Preview"}),(0,t.jsx)(g.K,{type:"button",variant:"link",onClick:()=>o(e=>!e),children:n?"Hide":"Show"})]}),n&&(0,t.jsx)(E.N,{className:"bg-muted/40",children:(0,t.jsx)(E.O,{children:(0,t.jsx)("pre",{className:"max-h-64 w-full overflow-auto text-sm",children:JSON.stringify(p,null,2)})})})]})})};var tr=e.i(257e3),ti=e.i(848573),tn=e.i(304720),to=e.i(670264),td=e.i(430597),tc=e.i(568142),tu=e.i(731417);let tm=e=>({tiers:e.tiers,enableNonReasoningTier:e.enable_non_reasoning_tier,customTierSet:e.custom_tier_set,defaultModel:e.default_model,planModeMinTier:e.plan_mode_min_tier,classificationPrompt:e.classification_prompt,classificationExamples:e.classification_examples,heuristicFirstMaxTier:e.heuristic_first_max_tier,hybridBoundaryMargin:e.hybrid_boundary_margin,classificationMode:e.classification_mode,tierLabels:e.tier_labels,classifierType:e.classifier_type,localHeuristic:e.local_heuristic,jevClassifierConfig:e.jev_classifier_config,heuristicV2SuccessThreshold:e.heuristic_v2_success_threshold,capabilityClassifierConfig:e.capability_classifier_config,llmV2Config:e.llm_v2_config,classifierLlmConfig:e.classifier_llm_config,classifierContextWindowSize:e.classifier_context_window_size,classifierContextBudgetChars:e.classifier_context_budget_chars,classifierContextPerTurnChars:e.classifier_context_per_turn_chars,classifierContextIncludeAssistantTurns:e.classifier_context_include_assistant_turns,classifierFallback:e.classifier_fallback,sessionAffinity:e.session_affinity??tu.K,sessionAffinityTtlSeconds:e.session_affinity_ttl_seconds,modalityRouting:e.modality_routing??!1,modalityPinOverride:e.modality_pin_override??!1,deploymentAffinity:e.deployment_affinity??tu.$,adaptive:e.adaptive??!1,adaptiveWeights:e.adaptive_weights??tu.l,tierDistancePenalty:e.tier_distance_penalty??tu.B,adaptiveEligible:e.adaptive_eligible??"all",returnRawModelName:e.return_raw_model_name??!1,tierBoundaries:e.tier_boundaries,tokenThresholds:e.token_thresholds,dimensionWeights:e.dimension_weights,customDimensions:e.custom_dimensions,reasoningOverrideMinScore:e.reasoning_override_min_score,tierModelParams:e.tier_model_params,enableContextWindowEscalation:e.enable_context_window_escalation,contextWindowEscalationBuffer:e.context_window_escalation_buffer,cacheAwareRouting:e.cache_aware_routing,cacheAwareRoutingOutputTokens:e.cache_aware_routing_output_tokens,cacheAwareRoutingTimeoutMs:e.cache_aware_routing_timeout_ms,stallEscalationEnabled:e.stall_escalation_enabled,stallEscalationWindow:e.stall_escalation_window,stallEscalationRepeatThreshold:e.stall_escalation_repeat_threshold,codeKeywords:e.code_keywords,reasoningKeywords:e.reasoning_keywords,technicalKeywords:e.technical_keywords,simpleKeywords:e.simple_keywords,planModePatterns:e.plan_mode_patterns,routeHousekeepingToCheapestTier:e.route_housekeeping_to_cheapest_tier,housekeepingPatterns:e.housekeeping_patterns,reminderMarkers:e.reminder_markers,maxTokensFromTierModel:e.max_tokens_from_tier_model,classifierPluginTimeoutMs:e.classifier_plugin_timeout_ms});var th=e.i(233820);let tp=e=>"object"==typeof e&&null!==e&&"open"in e&&"close"in e&&"string"==typeof e.open&&"string"==typeof e.close,tf=e=>Array.isArray(e)?e.filter(e=>"string"==typeof e):void 0,tx=(e,t)=>{let s=(0,eb.E)(e),a=(0,ti.Q)(e.tiers,e.enable_non_reasoning_tier),{tiers:l,enable_non_reasoning_tier:r}=a,i=(0,ti.y)(e),n={...a,custom_tier_set:i};return{tiers:l,enable_non_reasoning_tier:r,custom_tier_set:i,tier_model_params:(0,tr.K)((0,ek.q)(e.tiers,e.tier_model_configs),(0,tr.X)(n)),default_model:((e,t,s)=>{if("string"==typeof e&&e.trim())return e;let a=(0,tr.H)(s),l=t?.trim();return l&&l!==a?l:void 0})(e.default_model,t,n),plan_mode_min_tier:(0,ti.i)(e.plan_mode_min_tier,i),tier_labels:(0,ti.W)(e.tier_labels),...s,local_heuristic:"heuristic"===e.local_heuristic||"heuristic_v2"===e.local_heuristic?e.local_heuristic:void 0,heuristic_v2_success_threshold:"number"==typeof e.heuristic_v2_success_threshold?e.heuristic_v2_success_threshold:void 0,capability_classifier_config:eF.h.safeParse(e.capability_classifier_config).data,llm_v2_config:eF.S.safeParse(e.llm_v2_config).data,classifier_llm_config:"jev"===s.classifier_type?void 0:e.classifier_llm_config,classifier_context_window_size:"number"==typeof e.classifier_context_window_size?e.classifier_context_window_size:void 0,classifier_context_budget_chars:"number"==typeof e.classifier_context_budget_chars?e.classifier_context_budget_chars:void 0,classifier_context_per_turn_chars:"number"==typeof e.classifier_context_per_turn_chars?e.classifier_context_per_turn_chars:void 0,classifier_context_include_assistant_turns:"boolean"==typeof e.classifier_context_include_assistant_turns?e.classifier_context_include_assistant_turns:void 0,classifier_fallback:"default_model"===e.classifier_fallback||"heuristic"===e.classifier_fallback?e.classifier_fallback:void 0,classification_prompt:"string"==typeof e.classification_prompt&&""!==e.classification_prompt.trim()?e.classification_prompt:void 0,classification_examples:"string"==typeof e.classification_examples&&""!==e.classification_examples.trim()?e.classification_examples:void 0,heuristic_first_max_tier:"string"==typeof e.heuristic_first_max_tier&&""!==e.heuristic_first_max_tier.trim()?e.heuristic_first_max_tier:void 0,hybrid_boundary_margin:"number"==typeof e.hybrid_boundary_margin?e.hybrid_boundary_margin:void 0,classification_mode:"user_turn"===e.classification_mode||"every_request"===e.classification_mode?e.classification_mode:void 0,tier_boundaries:(0,th.E)(e.tier_boundaries),token_thresholds:(0,th.F)(e.token_thresholds),dimension_weights:(0,th.A)(e.dimension_weights),custom_dimensions:(0,tc.f)(e.custom_dimensions),reasoning_override_min_score:(0,th.m)(e.reasoning_override_min_score),session_affinity:"boolean"==typeof e.session_affinity?e.session_affinity:tu.K,session_affinity_ttl_seconds:"number"==typeof e.session_affinity_ttl_seconds&&Number.isFinite(e.session_affinity_ttl_seconds)?e.session_affinity_ttl_seconds:void 0,modality_routing:"boolean"==typeof e.modality_routing&&e.modality_routing,modality_pin_override:"boolean"==typeof e.modality_pin_override&&e.modality_pin_override,deployment_affinity:"boolean"==typeof e.deployment_affinity?e.deployment_affinity:tu.$,adaptive:e.adaptive||!1,adaptive_weights:e.adaptive_weights,tier_distance_penalty:e.tier_distance_penalty,adaptive_eligible:e.adaptive_eligible||"all",return_raw_model_name:e.return_raw_model_name||!1,enable_context_window_escalation:"boolean"==typeof e.enable_context_window_escalation?e.enable_context_window_escalation:void 0,context_window_escalation_buffer:"number"==typeof e.context_window_escalation_buffer?e.context_window_escalation_buffer:void 0,cache_aware_routing:"boolean"==typeof e.cache_aware_routing?e.cache_aware_routing:void 0,cache_aware_routing_output_tokens:"number"==typeof e.cache_aware_routing_output_tokens?e.cache_aware_routing_output_tokens:void 0,cache_aware_routing_timeout_ms:"number"==typeof e.cache_aware_routing_timeout_ms?e.cache_aware_routing_timeout_ms:void 0,stall_escalation_enabled:!0===e.stall_escalation_enabled||void 0,stall_escalation_window:"number"==typeof e.stall_escalation_window?e.stall_escalation_window:void 0,stall_escalation_repeat_threshold:"number"==typeof e.stall_escalation_repeat_threshold?e.stall_escalation_repeat_threshold:void 0,code_keywords:tf(e.code_keywords),reasoning_keywords:tf(e.reasoning_keywords),technical_keywords:tf(e.technical_keywords),simple_keywords:tf(e.simple_keywords),plan_mode_patterns:tf(e.plan_mode_patterns),route_housekeeping_to_cheapest_tier:"boolean"==typeof e.route_housekeeping_to_cheapest_tier?e.route_housekeeping_to_cheapest_tier:void 0,housekeeping_patterns:tf(e.housekeeping_patterns),reminder_markers:Array.isArray(e.reminder_markers)?e.reminder_markers.filter(tp):void 0,max_tokens_from_tier_model:"boolean"==typeof e.max_tokens_from_tier_model||"clamp"===e.max_tokens_from_tier_model?e.max_tokens_from_tier_model:void 0,classifier_plugin_timeout_ms:"number"==typeof e.classifier_plugin_timeout_ms&&Number.isFinite(e.classifier_plugin_timeout_ms)?e.classifier_plugin_timeout_ms:void 0}},t_=new Set(["tiers","enable_non_reasoning_tier","tier_definitions","fallback_tier","tier_model_configs","default_model","plan_mode_min_tier","tier_labels","classifier_type","local_heuristic","capability_classifier_config","llm_v2_config","classifier_llm_config","jev_classifier_config","opensource_classifier_config","classifier_context_window_size","classifier_context_budget_chars","classifier_context_include_assistant_turns","classifier_fallback","classification_prompt","classification_examples","heuristic_first_max_tier","hybrid_boundary_margin","heuristic_v2_success_threshold","classification_mode","session_affinity","session_affinity_ttl_seconds","modality_routing","modality_pin_override","deployment_affinity","adaptive","adaptive_weights","tier_distance_penalty","adaptive_eligible","return_raw_model_name","tier_boundaries","token_thresholds","dimension_weights","custom_dimensions","reasoning_override_min_score","enable_context_window_escalation","context_window_escalation_buffer","cache_aware_routing","cache_aware_routing_output_tokens","cache_aware_routing_timeout_ms","stall_escalation_enabled","stall_escalation_window","stall_escalation_repeat_threshold","code_keywords","reasoning_keywords","technical_keywords","simple_keywords","plan_mode_patterns","route_housekeeping_to_cheapest_tier","housekeeping_patterns","reminder_markers","max_tokens_from_tier_model","classifier_plugin_timeout_ms"]),tg=new Set(["keyword_tier_rules","escalation_keywords","semantic_keyword_matching","embedding_model","match_threshold"]),tj=["route_housekeeping_to_cheapest_tier","reminder_markers","max_tokens_from_tier_model"],tv=(e,t,s,a)=>{let l,r="object"!=typeof(l="string"==typeof e?JSON.parse(e):e)||null===l||Array.isArray(l)?{}:l,i=tx(r,void 0),n=new Set(tj.filter(e=>e in r&&JSON.stringify(t[e])===JSON.stringify(i[e]))),o=e=>!n.has(e)&&("classifier_context_per_turn_chars"===e?!(0,eq.h)((0,tu.t)(t))||Object.prototype.hasOwnProperty.call(t,e):!!(t_.has(e)||"escalation_keywords"===e&&(0,eF.K)((0,tu.t)(t))||void 0!==a&&tg.has(e))||void 0!==s&&"custom_technical_keywords"===e),d=t.custom_tier_set?tr.I:[],c=Object.fromEntries(Object.entries(r).filter(([e])=>!o(e)&&!d.includes(e))),u={...tm(t),customTechnicalKeywords:s??[],keywordTierRules:a?.keywordTierRules??[],semanticMatchingEnabled:a?.semanticMatchingEnabled??!1,embeddingModel:a?.embeddingModel,matchThreshold:a?.matchThreshold??tn.h,escalationKeywords:a?.escalationKeywords??[]},m=(0,ti.j)(u),h=[...void 0===a?[...tg].filter(e=>!o(e)):[],...void 0===s?["custom_technical_keywords"]:[],...n];return{...c,...Object.fromEntries(Object.entries(m).filter(([e])=>!h.includes(e)))}},tb=({value:e,onChange:s,children:a,modelInfo:l,accessToken:r,userRole:n,isVisible:o})=>{let{userId:d}=(0,i.f)(),c=!!e.jev_classifier_config?.deployment_name,{data:u}=(0,eP.f)({queryKey:(0,y.Z)(d??"",n),queryFn:()=>(0,y.G)(r,d??"",n),enabled:!!(o&&r&&c)});return(0,t.jsx)(eR.U,{value:e,onChange:s,decisionModel:c?(0,t.jsx)(eO,{value:e,onChange:s,modelInfo:l,deployments:u}):void 0,children:a})},ty=({isVisible:e,onCancel:a,onSuccess:l,modelData:r,accessToken:i,userRole:n,isMemberManaged:o=!1})=>{let[d,c]=(0,s.useState)(!1),[u,m]=(0,s.useState)([]),[h,p]=(0,s.useState)([]),[f,x]=(0,s.useState)(!1),[_,j]=(0,s.useState)(!1),[v,b]=(0,s.useState)(null),[y,N]=(0,s.useState)([]),[k,w]=(0,s.useState)([]),[C,S]=(0,s.useState)([]),[M,E]=(0,s.useState)(!1),[T,P]=(0,s.useState)(void 0),[I,z]=(0,s.useState)(tn.h),[O,L]=(0,s.useState)(to.p),[R,q]=(0,s.useState)({tiers:{SIMPLE:[],MEDIUM:[],COMPLEX:[],REASONING:[]},classifier_type:"heuristic"}),F=eE(r?.litellm_params),K=(0,eL.v)(i,{saved_model_id:r?.model_info?.id,team_id:r?.model_info?.team_id,complexity_router_config:tv(r?.litellm_params?.complexity_router_config,R,y,{keywordTierRules:k,escalationKeywords:C,semanticMatchingEnabled:M,embeddingModel:T,matchThreshold:I})},e&&F),D=(0,s.useMemo)(()=>F?eB:e$,[F]),V=(0,eZ.f)(D,{defaultValues:eG}),U=(F?(R.custom_tier_set?(0,tr.O)(R.custom_tier_set)??(0,ti.k)((0,tr.X)(R)):(Object.values(R.tiers).every(e=>0===e.length)?"Please select at least one model for a complexity tier":null)??(0,ti.w)(R.tier_labels))??(0,ti.C)(R.plan_mode_min_tier,(0,tr.X)(R))??(0,ti.f)(k,(0,tr.X)(R))??(0,ti.b)(R)??(0,ti.e)(R.heuristic_v2_success_threshold)??(0,eF.J)(R)??("decides"===(0,tu.H)(R)?(0,tc.R)(R.custom_dimensions):null):null)??K.saveBlockedReason;(0,s.useEffect)(()=>{e&&r&&B()},[e,r]),(0,s.useEffect)(()=>{let t=!0,s=async()=>{if(i)try{let e=await (0,em.SL)(i,"","",!1,null,!0,!0);m(e.data.map(e=>e.id))}catch(e){console.error("Error fetching model access groups:",e)}},a=async()=>{if(i){p([]);try{let e=o?await (0,e4.a)(i,r?.model_info?.team_id):await (0,e4.X)(i);t&&p(e)}catch(e){console.error("Error fetching model info:",e)}}};return e&&(s(),a()),()=>{t=!1}},[e,i,o,r?.model_info?.team_id]);let B=()=>{j(!1);try{if(F){let e=r.litellm_params?.complexity_router_config||{};"string"==typeof e&&(e=JSON.parse(e));let t=tx(e,r.litellm_params?.complexity_router_default_model);q(t),N(Array.isArray(e.custom_technical_keywords)?e.custom_technical_keywords:[]),w((0,td.f)(e.keyword_tier_rules)),S(Array.isArray(e.escalation_keywords)?e.escalation_keywords.filter(e=>"string"==typeof e):[]),E(!0===e.semantic_keyword_matching),P("string"==typeof e.embedding_model?e.embedding_model:void 0),z("number"==typeof e.match_threshold?e.match_threshold:tn.h),L((0,to.a)({auto_router_routing_compression:r.litellm_params?.auto_router_routing_compression,auto_router_model_compression:r.litellm_params?.auto_router_model_compression})),V.reset({...eG,auto_router_name:r.model_name,model_access_group:r.model_info?.access_groups||[]});return}let e=null;r.litellm_params?.auto_router_config&&(e="string"==typeof r.litellm_params.auto_router_config?JSON.parse(r.litellm_params.auto_router_config):r.litellm_params.auto_router_config),b(e);let t={auto_router_name:r.model_name,auto_router_default_model:r.litellm_params?.auto_router_default_model||null,auto_router_embedding_model:r.litellm_params?.auto_router_embedding_model||null,model_access_group:r.model_info?.access_groups||[]};V.reset(t)}catch(e){console.error("Error parsing auto router config:",e),eH.f.fromError("Error loading auto router configuration")}},$=async e=>{if(K.saveBlockedReason)return void eH.f.fromError(K.saveBlockedReason);if(F){let{tiers:t,custom_tier_set:s,classifier_llm_config:n}=R,d=(0,tr.X)(R),c=Object.values(t).every(e=>0===e.length),u=s?(0,tr.O)(s)??(0,ti.k)(d):c&&"Please select at least one model for a complexity tier";if(u){x(!0),eH.f.fromError(u);return}let m=(0,ti.b)(R)??(0,ti.e)(R.heuristic_v2_success_threshold)??(0,ti._)(R.reminder_markers)??(0,ti.r)(R.classifier_type,R.classifier_plugin_timeout_ms)??(0,eF.J)(R)??("decides"===(0,tu.H)(R)?(0,tc.R)(R.custom_dimensions):null);if(m){x(!0),eH.f.fromError(m);return}let p=(0,ti.I)(R,h);if(p){x(!0),eH.f.fromError(p);return}let f=(0,ti.f)(k,d);if(f){x(!0),eH.f.fromError(f);return}let _=(0,ti.q)({semanticMatchingEnabled:M,embeddingModel:T,keywordTierRules:k});if(_){x(!0),eH.f.fromError(_);return}let g=(0,tr.H)(R,R.default_model);if(!g){x(!0),eH.f.fromError("Add a model to the Simple or Medium tier, or pin a default model, so requests have somewhere to route.");return}let j=tv(r.litellm_params?.complexity_router_config,R,y,{keywordTierRules:k,escalationKeywords:C,semanticMatchingEnabled:M,embeddingModel:T,matchThreshold:I}),v=await (0,em.Ms)(i,j,r?.model_info?.team_id),b=(0,ti.c)(v);if(b){x(!0),eH.f.fromError(b);return}let N={...r.litellm_params,complexity_router_config:j,complexity_router_default_model:g,...o?{}:(0,to.I)(O,r.litellm_params??{})},w={...r.model_info,access_groups:e.model_access_group||[]};await (0,em.Gp)(i,o?{litellm_params:{complexity_router_config:j,complexity_router_default_model:g}}:{model_name:e.auto_router_name,litellm_params:N,model_info:w},r.model_info.id),eH.f.success("Auto router configuration updated successfully"),l({...r,model_name:e.auto_router_name,litellm_params:N,model_info:w}),a();return}let t={...r.litellm_params,auto_router_config:function(e){if(e?.routes?.some(e=>!(e.name??e.model)))throw Error("Please select a model for every route");return JSON.stringify(e)}(v),auto_router_default_model:e.auto_router_default_model,auto_router_embedding_model:e.auto_router_embedding_model||void 0},s={...r.model_info,access_groups:e.model_access_group||[]},n={model_name:e.auto_router_name,litellm_params:t,model_info:s};await (0,em.Gp)(i,n,r.model_info.id);let d={...r,model_name:e.auto_router_name,litellm_params:t,model_info:s};eH.f.success("Auto router configuration updated successfully"),l(d),a()},G=async()=>{try{c(!0),await V.handleSubmit($,()=>{eH.f.fromError("Failed to update auto router configuration")})()}catch(e){console.error("Error updating auto router:",e),eH.f.fromError(e)}finally{c(!1)}},H=[...h.map(e=>({value:e.model_group,label:e.model_group})),{value:"custom",label:"Enter custom model name"}],W=(0,t.jsx)(eY.f,{control:V.control,name:"auto_router_name",label:"Auto Router Name",children:({ref:e,...s})=>(0,t.jsx)(eX.f,{...s,ref:e,readOnly:o,placeholder:"e.g., auto_router_1, smart_routing"})});return(0,t.jsx)(eL.R.Provider,{value:K,children:(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&a(),children:(0,t.jsx)(eh.d,{className:"max-h-[90vh] overflow-y-auto sm:max-w-4xl",children:(0,t.jsxs)(A.g,{children:[(0,t.jsxs)(eh.s,{children:[(0,t.jsx)(eh.F,{children:"Edit Auto Router Configuration"}),(0,t.jsx)(eh.C,{children:"Edit the auto router configuration including routing logic, default models, and access settings."})]}),(0,t.jsx)("form",{onSubmit:e=>e.preventDefault(),noValidate:!0,children:(0,t.jsxs)(eJ.e,{children:[W,F?(0,t.jsx)("div",{className:"w-full",children:(0,t.jsx)(tb,{value:R,onChange:q,modelInfo:h,accessToken:i,userRole:n,isVisible:e,children:(0,t.jsx)(tu.U,{editingTiers:_,onEditingTiersChange:j,showValidationErrors:f,modelInfo:h,value:R,onChange:e=>{q(e)},customTechnicalKeywords:y,onCustomTechnicalKeywordsChange:N,keywordTierRules:k,onKeywordTierRulesChange:w,keywordRulesError:(0,ti.f)(k,(0,tr.X)(R)),semanticMatchingEnabled:M,onSemanticMatchingEnabledChange:E,embeddingModel:T,onEmbeddingModelChange:P,matchThreshold:I,onMatchThresholdChange:z,escalationKeywords:C,onEscalationKeywordsChange:S,autoRouterCompression:O,onAutoRouterCompressionChange:o?void 0:L})})}):(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"w-full",children:(0,t.jsx)(tl,{modelInfo:h,value:v,onChange:e=>{b(e)}})}),(0,t.jsx)(eY.f,{control:V.control,name:"auto_router_default_model",label:"Default Model",children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e2,{id:e,value:s,onChange:a,choices:H,placeholder:"Select a default model",ariaInvalid:l,ariaDescribedBy:r})}),(0,t.jsx)(eY.f,{control:V.control,name:"auto_router_embedding_model",label:"Embedding Model",children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e2,{id:e,value:s,onChange:a,choices:H,placeholder:"Select an embedding model",ariaInvalid:l,ariaDescribedBy:r})})]}),"Admin"===n&&!o&&(0,t.jsx)(eY.f,{control:V.control,name:"model_access_group",label:(0,eW.q)("Model Access Groups","Control who can access this auto router"),children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e1,{id:e,value:s,onChange:a,options:u,ariaInvalid:l,ariaDescribedBy:r})})]})}),(0,t.jsxs)(eh.c,{children:[(0,t.jsx)(g.K,{variant:"outline",onClick:a,children:"Cancel"}),null===U?(0,t.jsxs)(g.K,{disabled:d,onClick:G,children:[d&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Save Changes"]}):(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)(g.K,{disabled:!0,onClick:G,children:"Save Changes"})}),(0,t.jsx)(A.Y,{children:U})]})]})]})})})})},tN=ex.z.object({credential_name:ej.z.string().min(1,"Credential name is required")}),tk=({isVisible:e,onCancel:a,onAddCredential:l,existingCredential:r,setIsCredentialModalOpen:i})=>{let n,o=s.default.useId(),d="object"==typeof(n=r?.credential_values)&&null!==n?n:{},c=(0,eZ.f)(tN,{defaultValues:{credential_name:r?.credential_name??""}}),u=()=>{a(),c.reset()};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&u(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[600px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Reuse Credentials"})}),(0,t.jsx)(A.g,{children:(0,t.jsx)("form",{onSubmit:c.handleSubmit(e=>{l({...d,...e}),c.reset(),i(!1)}),noValidate:!0,children:(0,t.jsxs)(eJ.e,{children:[(0,t.jsx)(eY.f,{control:c.control,name:"credential_name",label:"Credential Name:",children:({ref:e,...s})=>(0,t.jsx)(eX.f,{...s,ref:e,placeholder:"Enter a friendly name for these credentials"})}),Object.entries(d).map(([e,s])=>(0,t.jsxs)(eJ.N,{children:[(0,t.jsx)(eJ.u,{htmlFor:`${o}-${e}`,children:e}),(0,t.jsx)(eX.f,{id:`${o}-${e}`,value:String(s),placeholder:`Enter ${e}`,disabled:!0,readOnly:!0})]},e)),(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/issues",className:"text-sm text-primary underline-offset-4 hover:underline",children:"Need Help?"})}),(0,t.jsx)(A.Y,{children:"Get help on our github"})]}),(0,t.jsxs)("div",{className:"flex gap-2.5",children:[(0,t.jsx)(g.K,{type:"button",variant:"outline",onClick:u,children:"Cancel"}),(0,t.jsx)(g.K,{type:"submit",children:"Reuse Credentials"})]})]})]})})})]})})};var tw=e.i(492688),tC=e.i(196631);function tS({credentialName:e,label:s,icon:a,className:l}){let r=s??e;return(0,t.jsxs)("span",{className:(0,tC.c)("flex min-w-0 flex-col gap-0.5",l),title:e,children:[(0,t.jsxs)("span",{className:"flex min-w-0 items-center gap-1.5",children:[a,(0,t.jsx)("span",{className:"truncate",children:r})]}),r!==e&&(0,t.jsx)("span",{className:"truncate font-mono text-xs font-normal text-muted-foreground",children:e})]})}function tM({credentialName:e,credentials:s}){return e?(0,t.jsx)(tS,{credentialName:e,label:(0,tw.N)(s).get(e)}):(0,t.jsx)(t.Fragment,{children:"Manual"})}function tE({credentialName:e,credentials:s}){let a=e?(0,tw.N)(s).get(e):void 0;return e&&void 0!==a&&a!==e?(0,t.jsx)("p",{className:"mt-1 truncate font-mono text-xs text-muted-foreground",children:e}):null}var tT=e.i(174553);function tA({overrides:e}){return void 0===e?null:0===e.length?(0,t.jsx)("p",{className:"mt-2 text-xs text-muted-foreground",children:"Follows the model cost map"}):(0,t.jsxs)("p",{className:"mt-2 text-xs text-muted-foreground",children:[(0,t.jsx)(e8.f,{variant:"outline",className:"mr-1",children:"Custom pricing"}),"Overrides the model cost map for ",e.join(", ")]})}function tP({model:e}){let s=e.output_cost_per_second,a=null!=s,l=null!=e.input_cost&&(!a||Number(e.input_cost)>0),r=null!=e.output_cost&&(!a||Number(e.output_cost)>0);return l||r||a?(0,t.jsxs)("div",{className:"mt-2",children:[l&&(0,t.jsxs)("p",{className:"text-sm",children:["Input: $",e.input_cost,"/1M tokens"]}),r&&(0,t.jsxs)("p",{className:"text-sm",children:["Output: $",e.output_cost,"/1M tokens"]}),a&&(0,t.jsxs)("p",{className:"text-sm",children:["Output: ",(0,es.b)(s)]}),(e.output_cost_per_second_tiers??[]).map(({resolution:e,cost:s})=>(0,t.jsxs)("p",{className:"text-sm",children:["Output (",e,"): ",(0,es.b)(s)]},e)),(0,t.jsx)(tA,{overrides:e.model_info?.pricing_overrides})]}):(0,t.jsx)("p",{className:"mt-2 text-sm text-muted-foreground",children:"-"})}var tI=e.i(89128),tz=e.i(204290),tO=e.i(929592),tL=e.i(450240);let tR=ex.z.object({api_key:ej.z.string().min(1,"Enter a new API key")}),tq={api_key:""};function tF({open:e,onCancel:a,accessToken:l,modelId:r,onUpdated:i}){let n=(0,eZ.f)(tR,{defaultValues:tq}),[o,d]=(0,s.useState)(!1),c=()=>{n.reset(tq),a()},u=async e=>{let t=e.api_key?.trim();if(!t)return void eH.f.fromError("Enter a new API key");d(!0);try{await (0,em.Gp)(l,{litellm_params:{api_key:t},model_info:{id:r}},r),eH.f.success("API key updated"),n.reset(tq),i(),a()}catch(e){console.error("Error updating API key:",e),eH.f.fromError("Failed to update API key")}finally{d(!1)}};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&c(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[520px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Update API Key"})}),(0,t.jsx)("span",{className:"block mb-4 text-sm text-muted-foreground",children:"Update this model's API key. Only the new key is sent; the rest of the deployment configuration is left untouched."}),(0,t.jsxs)(tz.f,{variant:"warning",className:"mb-4",children:[(0,t.jsx)(tI.f,{}),(0,t.jsx)(tO.s,{children:"Only the API key is rotated here. Models that authenticate with an Azure AD token, AWS credentials, or a Vertex service-account JSON aren't supported yet; update those from the model's LiteLLM Params for now."})]}),(0,t.jsxs)("form",{onSubmit:n.handleSubmit(u),children:[(0,t.jsx)(eJ.e,{children:(0,t.jsx)(eY.f,{control:n.control,name:"api_key",label:"New API Key",children:({ref:e,...s})=>(0,t.jsx)(tL.f,{...s,ref:e,placeholder:"Enter the new API key",autoComplete:"new-password"})})}),(0,t.jsxs)("div",{className:"flex justify-end items-center mt-4 gap-2.5",children:[(0,t.jsx)(g.K,{type:"button",variant:"outline",onClick:c,children:"Cancel"}),(0,t.jsxs)(g.K,{type:"submit",disabled:o,children:[o&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Update API Key"]})]})]})]})})}var tK=e.i(972165),tD=e.i(653145),tV=e.i(488826),tU=e.i(978056),tB=e.i(158321),t$=e.i(563458),tG=e.i(213056),tH=e.i(421436),tW=e.i(418276),tJ=e.i(967489),tY=e.i(699375),tX=e.i(299023),tQ=e.i(435451);let tZ="Cache Control Injection Points",t0="Tell litellm where to inject cache control checkpoints. You can specify either by role (to apply to all messages of that role) or by specific message index.",t1={location:"message"},t2=[{value:"message",label:"Message"}],t4=[{value:"user",label:"User"},{value:"system",label:"System"},{value:"assistant",label:"Assistant"}],t5=({label:e,hint:s})=>(0,t.jsxs)("div",{className:"flex items-center",children:[(0,t.jsx)(ez.f,{children:e}),(0,t.jsx)(A.g,{children:(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("button",{type:"button","aria-label":`${e} help`,className:"ml-1 inline-flex cursor-help items-center rounded-sm text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"}),children:(0,t.jsx)(e6.f,{"aria-hidden":!0,className:"size-4"})}),(0,t.jsx)(A.Y,{className:"max-w-xs whitespace-normal",children:s})]})})]}),t6=({value:e,onChange:s})=>{let a=e??[],l=(e,t)=>s?.(a.map((s,a)=>a===e?t:s));return(0,t.jsxs)("div",{className:"ml-6 border-l-2 border-border pl-4",children:[(0,t.jsx)("p",{className:"mb-4 block text-sm text-muted-foreground",children:"Providers like Anthropic, Bedrock API require users to specify where to inject cache control checkpoints, litellm can automatically add them for you as a cost saving feature."}),a.map((e,r)=>(0,t.jsxs)("div",{className:"mb-4 flex items-end gap-4",children:[(0,t.jsxs)("div",{className:"w-[180px] space-y-1",children:[(0,t.jsx)(ez.f,{children:"Type"}),(0,t.jsxs)(tJ.d,{items:t2,value:e.location,disabled:!0,children:[(0,t.jsx)(tJ.P,{className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:t2.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})]}),(0,t.jsxs)("div",{className:"w-[180px] space-y-1",children:[(0,t.jsx)(t5,{label:"Role",hint:"LiteLLM will mark all messages of this role as cacheable"}),(0,t.jsxs)(tJ.d,{items:t4,value:e.role??null,onValueChange:t=>l(r,{...e,role:t??void 0}),children:[(0,t.jsx)(tJ.P,{className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Select a role"})}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:null,children:"None"}),t4.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))]})]})]}),(0,t.jsxs)("div",{className:"w-[180px] space-y-1",children:[(0,t.jsx)(t5,{label:"Index",hint:"(Optional) If set litellm will mark the message at this index as cacheable"}),(0,t.jsx)(tQ.f,{type:"number",placeholder:"Optional",step:1,value:e.index??"",onChange:t=>l(r,{...e,index:""===t.target.value?void 0:t.target.value})})]}),a.length>1&&(0,t.jsx)(g.K,{type:"button",variant:"ghost",size:"icon","aria-label":`Remove injection point ${r+1}`,className:"text-destructive",onClick:()=>s?.(a.filter((e,t)=>t!==r)),children:(0,t.jsx)(tX.f,{className:"size-4"})})]},r)),(0,t.jsxs)(g.K,{type:"button",variant:"outline",className:"w-full border-dashed",onClick:()=>s?.([...a,t1]),children:[(0,t.jsx)(e3.f,{className:"mr-2 size-4"}),"Add Injection Point"]})]})},t3=({id:e,value:s,onChange:a,onBlur:l,teams:r})=>{let i=(r??[]).map(e=>({value:e.team_id,label:e.team_alias?`${e.team_alias} (${e.team_id})`:e.team_id}));return(0,t.jsxs)(tJ.d,{items:i,value:s||null,onValueChange:e=>a(e??""),children:[(0,t.jsx)(tJ.P,{id:e,className:"w-full",onBlur:l,children:(0,t.jsx)(tJ.U,{placeholder:"Select a team"})}),(0,t.jsx)(tJ.r,{children:i.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})};var t7=e.i(916940);let t8=[{name:L,label:"PTU Count",input:"number",placeholder:"e.g. 15",isCount:!0},{name:R,label:"Cost per PTU / Hour (USD)",input:"number",placeholder:"e.g. 2.00"},{name:q,label:"PTU Effective From (UTC)",input:"datetime"},{name:F,label:"PTU Effective To (UTC)",input:"datetime"}],t9=["input_cost","output_cost","cache_read_cost","cache_write_cost","cache_write_cost_1h"],se={input_cost:"input_cost_per_token",output_cost:"output_cost_per_token",cache_read_cost:"cache_read_input_token_cost",cache_write_cost:"cache_creation_input_token_cost",cache_write_cost_1h:"cache_creation_input_token_cost_above_1hr"},st=tV.z.union([ej.z.string(),tU.z.number(),tB.z.null()]).optional(),ss=ej.z.string().optional(),sa=e=>null==e||""===String(e).trim(),sl=st.refine(e=>sa(e)||Number.isFinite(Number(e))&&Number(e)>=0,"Enter a price of 0 or more").transform(e=>sa(e)?null:Number(e)/1e6),sr={model_name:ss,litellm_model_name:ss,api_base:ss,custom_llm_provider:ss,organization:ss,tpm:st,rpm:st,max_retries:st,timeout:st,stream_timeout:st,input_cost:sl,output_cost:sl,cache_read_cost:sl,cache_write_cost:sl,cache_write_cost_1h:sl,ptu_count:st,cost_per_ptu_per_hour:st,ptu_effective_from:t$.z.custom().nullish(),ptu_effective_to:t$.z.custom().nullish(),cache_control:tG.z.boolean().optional(),cache_control_injection_points:eK.z.array(t$.z.custom()).optional(),model_access_group:eK.z.array(ej.z.string()).optional(),guardrails:eK.z.array(ej.z.string()).optional(),vector_store_ids:eK.z.array(ej.z.string()).optional(),tags:eK.z.array(ej.z.string()).optional(),health_check_model:ej.z.string().nullish(),litellm_credential_name:ej.z.string().nullish(),litellm_extra_params:ss,model_info:ss,team_id:ss},si=(...e)=>{let t=e.find(e=>null!=e);return null==t?null:1e6*t},sn=(e,t)=>({model_name:e.model_name,litellm_model_name:e.litellm_model_name,api_base:e.litellm_params.api_base,custom_llm_provider:e.litellm_params.custom_llm_provider,organization:e.litellm_params.organization,tpm:e.litellm_params.tpm,rpm:e.litellm_params.rpm,max_retries:e.litellm_params.max_retries,timeout:e.litellm_params.timeout,stream_timeout:e.litellm_params.stream_timeout,input_cost:si(e.litellm_params.input_cost_per_token,e.model_info?.input_cost_per_token),output_cost:si(e.litellm_params?.output_cost_per_token,e.model_info?.output_cost_per_token),ptu_count:e.model_info?.ptu_count??null,cost_per_ptu_per_hour:e.model_info?.cost_per_ptu_per_hour??null,ptu_effective_from:O(e.model_info?.ptu_effective_from),ptu_effective_to:O(e.model_info?.ptu_effective_to),cache_read_cost:si(e.litellm_params?.cache_read_input_token_cost,e.model_info?.cache_read_input_token_cost),cache_write_cost:si(e.litellm_params?.cache_creation_input_token_cost,e.model_info?.cache_creation_input_token_cost),cache_write_cost_1h:si(e.litellm_params?.cache_creation_input_token_cost_above_1hr,e.model_info?.cache_creation_input_token_cost_above_1hr),cache_control:!!e.litellm_params?.cache_control_injection_points,cache_control_injection_points:e.litellm_params?.cache_control_injection_points||[],model_access_group:Array.isArray(e.model_info?.access_groups)?e.model_info.access_groups:[],guardrails:Array.isArray(e.litellm_params?.guardrails)?e.litellm_params.guardrails:[],vector_store_ids:Array.isArray(e.litellm_params?.vector_store_ids)&&e.litellm_params.vector_store_ids.length>0?e.litellm_params.vector_store_ids:void 0,tags:Array.isArray(e.litellm_params?.tags)?e.litellm_params.tags:[],...t?{health_check_model:e.model_info?.health_check_model}:{},litellm_credential_name:e.litellm_params?.litellm_credential_name??null,litellm_extra_params:JSON.stringify(ei(e.litellm_params??{}),null,2),team_id:e.model_info?.team_id??void 0}),so=({children:e})=>(0,t.jsx)("div",{className:"mt-1 rounded-sm bg-muted p-2",children:e}),sd="text-sm font-medium text-foreground",sc=({htmlFor:e,children:s})=>void 0===e?(0,t.jsx)("p",{className:sd,children:s}):(0,t.jsx)("label",{htmlFor:e,className:sd,children:s}),su=({text:e})=>(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)(e6.f,{className:"ml-1 inline size-3.5 shrink-0 cursor-help text-muted-foreground"})}),(0,t.jsx)(A.Y,{className:"max-w-xs",children:e})]}),sm=({text:e,href:s})=>(0,t.jsx)("a",{href:s,target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,t.jsx)(su,{text:e})}),sh=({values:e,emptyLabel:s})=>e?Array.isArray(e)?0===e.length?(0,t.jsx)(t.Fragment,{children:s}):(0,t.jsx)("div",{className:"flex flex-wrap gap-1",children:e.map((e,s)=>(0,t.jsx)(e8.f,{variant:"secondary",children:e},s))}):(0,t.jsx)(t.Fragment,{children:String(e)}):(0,t.jsx)(t.Fragment,{children:"Not Set"}),sp=({localModelData:e,modelData:a,teamAlias:l,accessToken:r,isEditing:i,isSaving:n,isWildcardModel:o,ptuCostAttributionEnabled:d,showCacheControl:c,setShowCacheControl:u,onCancel:m,onSubmit:h,modelAccessGroups:p,guardrailsList:f,tagsList:x,credentialsList:_,healthCheckModelOptions:j,teams:v})=>{let b=s.useRef(new Set),y=s.useCallback(e=>b.current.has(e),[]),N=(0,tD.G)({resolver:(e,t,s)=>(0,tK.f)(ex.z.object(sr).superRefine((e,t)=>{let s=(e,s)=>t.addIssue({code:"custom",path:[e],message:s});if(null===en(e.litellm_extra_params)&&s("litellm_extra_params","Please enter a valid JSON object"),d){if(D(e.ptu_count)||s("ptu_count",`PTU Count must be a whole number between 1 and ${1e6.toLocaleString()}`),U(e.cost_per_ptu_per_hour)||s("cost_per_ptu_per_hour",`Cost per PTU / Hour must be between 0 and ${1e6.toLocaleString()}`),K(e.ptu_count)!==K(e.cost_per_ptu_per_hour)){let e="PTU Count and Cost per PTU / Hour must be set together";s("ptu_count",e),s("cost_per_ptu_per_hour",e)}if(K(e.ptu_count)&&!K(e.ptu_effective_from)&&s("ptu_effective_from","PTU Effective From is required when PTU Count is set"),!H(e.ptu_effective_from,e.ptu_effective_to)){let e="PTU Effective To must be after PTU Effective From";s("ptu_effective_from",e),s("ptu_effective_to",e)}for(let t of t9){let a=e[t];y(t)&&K(e.ptu_count)&&K(a)&&0!==Number(a)&&s(t,"A PTU deployment bills by reserved capacity, so this cost must be 0 or blank")}}}))(e,t,s),defaultValues:sn(e,o)}),k=(e,s,a,l)=>(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:s}),i?(0,t.jsx)(eY.f,{control:N.control,name:e,children:({value:e,...s})=>(0,t.jsx)(eX.f,{...s,value:e??"",placeholder:a})}):(0,t.jsx)(so,{children:l||"Not Set"})]}),w=(e,s,a,l)=>(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:s}),i?(0,t.jsx)(eY.f,{control:N.control,name:e,children:({value:e,...s})=>(0,t.jsx)(tQ.f,{...s,value:e??"",placeholder:a})}):(0,t.jsx)(so,{children:l||"Not Set"})]}),C=(s,a,l,r)=>{let n,o;return i?(0,t.jsx)(eY.f,{control:N.control,name:s,label:a,description:r,children:({value:e,onChange:a,...r})=>(0,t.jsx)(tQ.f,{...r,value:e??"",placeholder:l,onChange:e=>{b.current=new Set([...b.current,s]),a(e)}})}):(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:a}),(0,t.jsx)(so,{children:(n=se[s],null!=(o=e?.litellm_params?.[n]??e?.model_info?.[n])?(1e6*Number(o)).toFixed(4):"Not Set")})]})},S=(e,s,a)=>(0,t.jsx)(eY.f,{control:N.control,name:e,children:({id:e,value:l,onChange:r})=>(0,t.jsx)(tH.f,{id:e,value:l??[],onValueChange:r,options:s,placeholder:a,tokenSeparators:[","]})});return(0,t.jsx)(A.g,{children:(0,t.jsx)("form",{onSubmit:e=>N.handleSubmit(async e=>{await h(e,y)})(e),children:(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("div",{className:"space-y-4",children:[k("model_name","Model Name","Enter model name",e.model_name),k("litellm_model_name","LiteLLM Model Name","Enter LiteLLM model name",e.litellm_model_name),C("input_cost","Input Cost (per 1M tokens)","Enter input cost"),C("output_cost","Output Cost (per 1M tokens)","Enter output cost"),d&&t8.map(s=>(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{htmlFor:s.name,children:s.label}),i?(0,t.jsx)(eY.f,{control:N.control,name:s.name,children:({value:e,onChange:a,...l})=>"number"===s.input?(0,t.jsx)(tQ.f,{...l,id:s.name,onChange:a,value:e??"",placeholder:s.placeholder,step:s.isCount?1:void 0,min:+!!s.isCount}):(0,t.jsx)(tW.f,{...l,id:s.name,value:e,onChange:a})}):(0,t.jsx)(so,{children:("datetime"===s.input?(e=>{if(!e)return null;let t=P.default.utc(e);return t.isValid()?`${t.format("YYYY-MM-DD HH:mm:ss")} UTC`:String(e)})(e?.model_info?.[s.name]):e?.model_info?.[s.name])??"Not Set"})]},s.name)),C("cache_read_cost","Cache Read Cost (per 1M tokens)","Defaults to Input Cost if blank","If left blank on save, defaults to Input Cost."),C("cache_write_cost","Cache Write Cost (per 1M tokens)","Defaults to Input Cost if blank","If left blank on save, defaults to Input Cost (backend falls back to input_cost_per_token)."),C("cache_write_cost_1h","Cache Write Cost (1 hour, per 1M tokens)","Defaults to the cost map 1 hour rate, else Cache Write Cost","Rate for prompt cache writes with a 1 hour TTL. If left blank on save, known models use their cost map 1 hour rate, otherwise Cache Write Cost."),k("api_base","API Base","Enter API base",e.litellm_params?.api_base),k("custom_llm_provider","Custom LLM Provider","Enter custom LLM provider",e.litellm_params?.custom_llm_provider),k("organization","Organization","Enter organization",e.litellm_params?.organization),w("tpm","TPM (Tokens per Minute)","Enter TPM",e.litellm_params?.tpm),w("rpm","RPM (Requests per Minute)","Enter RPM",e.litellm_params?.rpm),w("max_retries","Max Retries","Enter max retries",e.litellm_params?.max_retries),w("timeout","Timeout (seconds)","Enter timeout",e.litellm_params?.timeout),w("stream_timeout","Stream Timeout (seconds)","Enter stream timeout",e.litellm_params?.stream_timeout),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Model Access Groups"}),i?S("model_access_group",(p??[]).map(e=>({value:e,label:e})),"Select existing groups or type to create new ones"):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.model_info?.access_groups,emptyLabel:"No groups assigned"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(sc,{children:["Guardrails",(0,t.jsx)(sm,{text:"Apply safety guardrails to this model to filter content or enforce policies",href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start"})]}),i?S("guardrails",f.map(e=>({value:e,label:e})),"Select existing guardrails or type to create new ones"):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.litellm_params?.guardrails,emptyLabel:"No guardrails assigned"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(sc,{children:["Attached Knowledge Bases (RAG)",(0,t.jsx)(sm,{text:"Vector stores used for RAG. Every request to this model will automatically retrieve context from these knowledge bases.",href:"https://docs.litellm.ai/docs/completion/knowledgebase"})]}),i?(0,t.jsx)(eY.f,{control:N.control,name:"vector_store_ids",children:({value:e,onChange:s})=>(0,t.jsx)(t7.f,{value:e,onChange:s,accessToken:r||"",placeholder:"Select knowledge bases (optional)"})}):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.litellm_params?.vector_store_ids,emptyLabel:"No knowledge bases attached"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Tags"}),i?S("tags",Object.values(x).map(e=>({value:e.name,label:e.name})),"Select existing tags or type to create new ones"):(0,t.jsx)(so,{children:(0,t.jsx)(sh,{values:e.litellm_params?.tags,emptyLabel:"No tags assigned"})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Existing Credentials"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"litellm_credential_name",children:({id:e,value:s,onChange:a})=>(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(eI.f,{inputId:e,placeholder:"Select or search for existing credentials",options:(0,tw.H)(_),value:s??"",allowClear:!1,onValueChange:e=>{null!==e&&a(""===e?null:e)}}),(0,t.jsx)(tE,{credentialName:s,credentials:_})]})}):(0,t.jsx)(so,{children:(0,t.jsx)(tM,{credentialName:e.litellm_params?.litellm_credential_name,credentials:_})})]}),o&&(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Health Check Model"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"health_check_model",children:({id:e,value:s,onChange:a,onBlur:l})=>(0,t.jsxs)(tJ.d,{items:j,value:s??null,onValueChange:a,children:[(0,t.jsx)(tJ.P,{id:e,className:"w-full",onBlur:l,children:(0,t.jsx)(tJ.U,{placeholder:"Select existing health check model"})}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:null,children:"None"}),j.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))]})]})}):(0,t.jsx)(so,{children:e.model_info?.health_check_model||"Not Set"})]}),i?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(eY.f,{control:N.control,name:"cache_control",label:(0,t.jsxs)(t.Fragment,{children:[tZ,(0,t.jsx)(su,{text:t0})]}),orientation:"horizontal",children:({id:e,value:s,onChange:a,onBlur:l})=>(0,t.jsx)(tY.f,{id:e,onBlur:l,checked:!!s,onCheckedChange:e=>{a(e),u(e)}})}),c&&(0,t.jsx)(eY.f,{control:N.control,name:"cache_control_injection_points",children:({value:e,onChange:s})=>(0,t.jsx)(t6,{value:e??[],onChange:s})})]}):(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Cache Control"}),(0,t.jsx)(so,{children:e.litellm_params?.cache_control_injection_points?(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{children:"Enabled"}),(0,t.jsx)("div",{className:"mt-2",children:e.litellm_params.cache_control_injection_points.map((e,s)=>(0,t.jsxs)("div",{className:"mb-1 text-sm text-muted-foreground",children:["Location: ",e.location,",",e.role&&(0,t.jsxs)("span",{children:[" Role: ",e.role]}),void 0!==e.index&&(0,t.jsxs)("span",{children:[" Index: ",e.index]})]},s))})]}):"Disabled"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Model Info"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"model_info",children:({value:e,...s})=>(0,t.jsx)(tt.f,{...s,rows:4,placeholder:'{"gpt-4": 100, "claude-v1": 200}',defaultValue:JSON.stringify(a.model_info,null,2)})}):(0,t.jsx)(so,{children:(0,t.jsx)("pre",{className:"mt-1 overflow-auto rounded-sm bg-muted p-2 text-xs",children:JSON.stringify(e.model_info,null,2)})})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(sc,{children:["LiteLLM Params",(0,t.jsx)(sm,{text:"Additional parameters for model requests. Settings with dedicated fields above are edited there. Remove a key here to delete its saved value.",href:"https://docs.litellm.ai/docs/completion/input"})]}),i?(0,t.jsx)(eY.f,{control:N.control,name:"litellm_extra_params",children:({value:e,...s})=>(0,t.jsx)(tt.f,{...s,"aria-label":"LiteLLM Params",value:e??"",rows:4,placeholder:'{\n "drop_params": true\n}'})}):(0,t.jsx)(so,{children:(0,t.jsx)("pre",{className:"mt-1 overflow-auto rounded-sm bg-muted p-2 text-xs",children:JSON.stringify(e.litellm_params,null,2)})})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)(sc,{children:"Team"}),i?(0,t.jsx)(eY.f,{control:N.control,name:"team_id",children:({id:e,value:s,onChange:a,onBlur:l})=>(0,t.jsx)(t3,{id:e,value:s,onChange:a,onBlur:l,teams:v})}):(0,t.jsx)(so,{children:l?`${l} (${e.model_info?.team_id})`:e.model_info?.team_id||"Not Set"})]})]}),i&&(0,t.jsxs)("div",{className:"mt-6 flex justify-end gap-2",children:[(0,t.jsx)(g.K,{type:"submit",variant:"secondary",onClick:()=>{N.reset(sn(e,o)),b.current=new Set,m()},disabled:n,children:"Cancel"}),(0,t.jsxs)(g.K,{type:"submit",disabled:n,"aria-busy":n,children:[n&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Save Changes"]})]})]})})})},sf=e=>e?.model_info?.team_public_model_name?e.model_info.team_public_model_name:e?.model_name||"-";var sx=e.i(768371);function s_({data:e,isError:s,isPending:a,apiErrorMessage:l}){let r=void 0!==e&&!s,i=r&&null!==e.error,n=r&&null===e.error&&0===e.pod_ips.length,o=r&&null===e.error&&e.pod_ips.length>0,d=r&&!i?e.pod_count:null;return(0,t.jsxs)(t.Fragment,{children:[null!==d&&d>0&&(0,t.jsxs)("p",{className:"mt-4 text-sm",children:[d," ready pods"]}),a&&(0,t.jsx)("p",{className:"mt-4 text-sm text-muted-foreground",role:"status",children:"Loading Kubernetes pods"}),s&&(0,t.jsx)("p",{className:"mt-4 text-sm text-destructive",role:"alert",children:l}),e&&i&&(0,t.jsx)("p",{className:"mt-4 text-sm text-destructive",role:"alert",children:e.error}),e&&n&&(0,t.jsx)("p",{className:"mt-4 text-sm text-muted-foreground",children:"No ready pods"}),e&&o&&(0,t.jsx)("ul",{"aria-label":"Ready Kubernetes pod IPs",className:"mt-3 space-y-1 font-mono text-sm",children:e.pod_ips.map(e=>(0,t.jsx)("li",{children:e},e))})]})}function sg({modelId:e}){let{data:s,error:a,isError:l,isPending:r,refetch:i}=sx.q.useQuery("get","/model/{model_id}/kubernetes_pods",{params:{path:{model_id:e}}},{refetchInterval:1e4}),n=a instanceof Error?a.message:JSON.stringify(a)??"Failed to load Kubernetes pods";return(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsxs)("div",{className:"flex items-start justify-between gap-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Kubernetes pods"}),s&&(0,t.jsx)("p",{className:"mt-1 text-sm text-muted-foreground",children:null===s.port?s.service_host:`${s.service_host}:${s.port}`})]}),(0,t.jsx)(g.K,{type:"button",variant:"outline",onClick:()=>void i(),children:"Refresh"})]}),(0,t.jsx)(s_,{data:s,isError:l,isPending:r,apiErrorMessage:n})]})}function sj({modelId:e,onClose:a,accessToken:l,userID:i,userRole:o,isViewOnly:d,onModelUpdate:m,modelAccessGroups:h}){let p,f=(0,r.d)(),[x,_]=(0,s.useState)(null),[j,v]=(0,s.useState)(!1),[N,k]=(0,s.useState)(!1),[P,I]=(0,s.useState)(!1),[O,L]=(0,s.useState)(!1),[R,q]=(0,s.useState)(!1),[F,K]=(0,s.useState)(!1),[D,V]=(0,s.useState)(null),[U,B]=(0,s.useState)(!1),[$,G]=(0,s.useState)({}),[H,W]=(0,s.useState)(!1),[ea,er]=(0,s.useState)(!1),[ed,ec]=(0,s.useState)(0),[eu,ef]=(0,s.useState)([]),[eN,eC]=(0,s.useState)([]),[eS,eP]=(0,s.useState)({}),[eI,ez]=(0,s.useState)([]),{data:eO,isLoading:eL}=(0,y.e)(1,50,void 0,e,void 0,void 0,void 0,!1,void 0,void 0,!1,void 0,{useStoredParams:!0}),{data:eR}=(0,b.X)(),{data:eq}=(0,y.x)(),{data:eF}=(0,n.n)(),eK=X(),eD=e=>null!=eR&&"object"==typeof eR&&e in eR?eR[e].litellm_provider:"openai",eV=(0,s.useMemo)(()=>eO?.data&&0!==eO.data.length&&w(eO,eD).data[0]||null,[eO,eR]),eU=e=>eF?.find(t=>t.team_id===e)?.team_alias||null,eB=eU(eV?.model_info?.team_id),e$=Object.entries(eV?.model_info??{}).flatMap(e=>"team_id"===e[0]&&eB?[e,["team_alias",eB]]:[e]),eG=eV&&{...eV,model_info:Object.fromEntries(e$)},eW="Admin"===o,eJ={userRole:o,userID:i,isViewOnly:d},eY={teamId:eV?.model_info?.team_id,isDbModel:eV?.model_info?.db_model===!0,createdBy:eV?.model_info?.created_by,model:eV?.litellm_params?.model},eX=(0,u.d)(eJ,eF??null,eY),eQ=(0,u.F)(eJ,eF??null,eY),eZ=(0,s.useMemo)(()=>(0,c.d)(eF??null,o,i),[eF,o,i]),e0=eT(p=eV?.litellm_params)&&eM(p).hasEditor,e1=eT(eV?.litellm_params),e2=e1?"Delete Auto-Router":"Delete Model",e4=eE(eV?.litellm_params),e5=eV?.litellm_params?.litellm_credential_name!=null&&eV?.litellm_params?.litellm_credential_name!=void 0,e6=x?.model_info?.id!==eV?.model_info?.id;(0,s.useEffect)(()=>{if(eV&&(!x||e6)){let e=eV;e.litellm_model_name||(e={...e,litellm_model_name:e?.litellm_params?.litellm_model_name??e?.litellm_params?.model??e?.model_info?.key??null}),_(e),B(!!e?.litellm_params?.cache_control_injection_points)}},[eV,x,e6]),(0,s.useEffect)(()=>{let t=async()=>{if(l)try{let e=(await (0,em.gx)(l)).guardrails.map(e=>e.guardrail_name);eC(e)}catch(e){console.error("Failed to fetch guardrails:",e)}},s=async()=>{if(l)try{let e=await (0,em.M3)(l);eP(e)}catch(e){console.error("Failed to fetch tags:",e)}},a=async()=>{if(l)try{let e=await (0,em.lg)(l);ez(e.credentials||[])}catch(e){console.error("Failed to fetch credentials:",e)}};(async()=>{if(!l||e5)return;let t=await (0,em.lm)(l,null,e);V({credential_name:t.credential_name,credential_values:t.credential_values,credential_info:t.credential_info})})(),t(),s(),a()},[l,e]);let e3=async t=>{if(!l)return;let s={credential_name:t.credential_name,model_id:e,credential_info:{custom_llm_provider:x.litellm_params?.custom_llm_provider}};eH.f.info("Storing credential.."),await (0,em.E6)(l,s),eH.f.success("Credential stored successfully")},e7=async(t,s)=>{try{let r;if(!l)return;q(!0);let i=en(t.litellm_extra_params);if(null===i)return void eH.f.fromError("LiteLLM Params must be a valid JSON object");let n={...ei(i),model:t.litellm_model_name,api_base:t.api_base,custom_llm_provider:t.custom_llm_provider,organization:t.organization,tpm:t.tpm,rpm:t.rpm,max_retries:t.max_retries,timeout:t.timeout,stream_timeout:t.stream_timeout,tags:t.tags};if(s("input_cost")&&(n.input_cost_per_token=t.input_cost),s("output_cost")&&(n.output_cost_per_token=t.output_cost),s("cache_read_cost"))n.cache_read_input_token_cost=t.cache_read_cost;else if(s("input_cost")){let e=t.cache_read_cost??t.input_cost;null!==e&&(n.cache_read_input_token_cost=e)}s("cache_write_cost")&&(n.cache_creation_input_token_cost=t.cache_write_cost),s("cache_write_cost_1h")&&(n.cache_creation_input_token_cost_above_1hr=t.cache_write_cost_1h);let o=x?.litellm_params?.litellm_credential_name??null,d=t.litellm_credential_name??null;d!==o?n.litellm_credential_name=d:delete n.litellm_credential_name,t.guardrails&&(n.guardrails=t.guardrails),(t.vector_store_ids?.length??0)>0?n.vector_store_ids=t.vector_store_ids:void 0!==t.vector_store_ids?n.vector_store_ids=[]:delete n.vector_store_ids;let c=!!x?.litellm_params?.cache_control_injection_points;t.cache_control&&(t.cache_control_injection_points?.length??0)>0?n.cache_control_injection_points=t.cache_control_injection_points:c?n.cache_control_injection_points=null:delete n.cache_control_injection_points;try{var a;r=t.model_info?JSON.parse(t.model_info):eV?.model_info,t.model_access_group&&(r={...r,access_groups:t.model_access_group}),void 0!==t.health_check_model&&(r={...r,health_check_model:t.health_check_model}),t.team_id&&(r={...r,team_id:t.team_id}),a=r,r=eK?{...a,ptu_count:Y(t.ptu_count),cost_per_ptu_per_hour:Y(t.cost_per_ptu_per_hour),ptu_effective_from:z(t.ptu_effective_from),ptu_effective_to:z(t.ptu_effective_to)}:Object.fromEntries(Object.entries(a).filter(([e])=>!J.includes(e)))}catch(e){eH.f.fromError("Invalid JSON in Model Info");return}let u=Object.keys(ei(x?.litellm_params??{})).filter(e=>!Object.prototype.hasOwnProperty.call(i,e)),h=el(n),p=Object.fromEntries(Object.entries({...x?.litellm_params,...h}).filter(([e])=>"litellm_credential_name"!==e&&!u.includes(e))),f={model_name:t.model_name,litellm_params:h,...u.length>0&&{litellm_params_to_remove:u},model_info:r};await (0,em.Gp)(l,f,e);let g={...x,model_name:t.model_name,litellm_model_name:t.litellm_model_name,litellm_params:null===d?p:{...p,litellm_credential_name:d},model_info:r};_(g),m&&m(g),eH.f.success("Model settings updated successfully"),K(!1)}catch(e){console.error("Error updating model:",e),eH.f.fromError("Failed to update model settings")}finally{q(!1)}};if(eL)return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)(g.K,{variant:"ghost",onClick:a,className:"mb-4",children:[(0,t.jsx)(Q.f,{className:"size-4"}),"Back to Models"]}),(0,t.jsx)("p",{className:"text-sm",children:"Loading..."})]});if(!eV)return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)(g.K,{variant:"ghost",onClick:a,className:"mb-4",children:[(0,t.jsx)(Q.f,{className:"size-4"}),"Back to Models"]}),(0,t.jsx)("p",{className:"text-sm",children:"Model not found"})]});let e8=async()=>{if(l){if(e4){let e=(e=>{let t=e?.litellm_params?.complexity_router_config,s={};if("string"==typeof t)try{s=JSON.parse(t)}catch{s={}}else t&&(s=t);let a=s.tiers&&"object"==typeof s.tiers?Object.entries(s.tiers).map(([e,t])=>[e,(0,ek.I)(t)]):[],l=e?.litellm_params?.complexity_router_default_model||void 0;return ew({tiers:a,semanticMatchingEnabled:!!s.semantic_keyword_matching,embeddingModel:s.embedding_model,defaultModel:l})})(x??eV);return 0===e.length?void eH.f.warning("No complexity tiers are configured yet, so there is nothing to test."):(ef(e),ec(e=>e+1),void er(!0))}try{eH.f.info("Testing connection...");let e=await (0,em.ym)(l,{custom_llm_provider:x.litellm_params.custom_llm_provider,litellm_credential_name:x.litellm_params.litellm_credential_name,model:x.litellm_model_name},{id:x.model_info?.id});if("success"===e.status)eH.f.success("Connection test successful!");else throw Error(e?.result?.error||e?.message||"Unknown error")}catch(e){e instanceof Error?eH.f.error("Error testing connection: "+(0,eo.I)(e.message,100)):eH.f.error("Error testing connection: "+String(e))}}},e9=async()=>{try{if(k(!0),!l)return;await (0,em.o2)(l,e),eH.f.success("Model deleted successfully"),m&&m({deleted:!0,model_info:{id:e}}),a()}catch(e){console.error("Error deleting the model:",e),eH.f.fromError("Failed to delete model")}finally{k(!1),v(!1)}},te=async(e,t)=>{await (0,es.W)(e)&&(G(e=>({...e,[t]:!0})),setTimeout(()=>{G(e=>({...e,[t]:!1}))},2e3))},tt=eV.litellm_model_name.includes("*"),ts=eV.litellm_model_name.split("/")[0],ta=eq?.data?.filter(e=>e.providers?.includes(ts)&&e.model_group!==eV.litellm_model_name).map(e=>({value:e.model_group,label:e.model_group}))||[];return(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-6",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)(g.K,{variant:"ghost",onClick:a,className:"mb-4",children:[(0,t.jsx)(Q.f,{className:"size-4"}),"Back to Models"]}),(0,t.jsxs)("h2",{className:"text-xl font-semibold",children:["Public Model Name: ",sf(eV)]}),(0,t.jsxs)("div",{className:"flex items-center cursor-pointer",children:[(0,t.jsx)("span",{className:"text-sm text-muted-foreground font-mono",children:eV.model_info.id}),(0,t.jsx)(g.K,{variant:"ghost",size:"icon-xs","aria-label":"Copy model ID",onClick:()=>te(eV.model_info.id,"model-id"),className:`left-2 z-raised transition-all duration-200 ${$["model-id"]?"text-success bg-success/10 border-success/20":"text-muted-foreground hover:text-foreground hover:bg-muted"}`,children:$["model-id"]?(0,t.jsx)(Z.f,{size:12}):(0,t.jsx)(ee.f,{size:12})})]})]}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(!e1||e4)&&(0,t.jsxs)(g.K,{variant:"outline",onClick:e8,className:"flex items-center gap-2","data-testid":"test-connection-button",children:[(0,t.jsx)(S.f,{className:"h-4 w-4"}),"Test Connection"]}),!e1&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(g.K,{variant:"outline",onClick:()=>L(!0),className:"flex items-center",disabled:!eX,"data-testid":"update-api-key-button",children:[(0,t.jsx)(C,{className:"h-4 w-4"}),"Update API Key"]}),(0,t.jsxs)(g.K,{variant:"outline",onClick:()=>I(!0),className:"flex items-center",disabled:!eW,"data-testid":"reuse-credentials-button",children:[(0,t.jsx)(C,{className:"h-4 w-4"}),"Re-use Credentials"]})]}),(0,t.jsxs)(g.K,{variant:"destructive",onClick:()=>v(!0),className:"flex items-center",disabled:!eX,"data-testid":"delete-model-button",children:[(0,t.jsx)(M.f,{className:"h-4 w-4"}),e2]})]})]}),(0,t.jsxs)(T.i,{defaultValue:"overview",children:[(0,t.jsxs)(T.U,{variant:"line",className:"mb-6 h-auto w-full justify-start rounded-none border-b p-0",children:[(0,t.jsx)(T.k,{value:"overview",className:"flex-none rounded-none px-4 py-2",children:"Overview"}),(0,t.jsx)(T.k,{value:"raw",className:"flex-none rounded-none px-4 py-2",children:"Raw JSON"})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)(T.S,{value:"overview",keepMounted:!0,children:[(0,t.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mb-6",children:[(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsx)("p",{className:"text-sm",children:"Provider"}),(0,t.jsxs)("div",{className:"mt-2 flex items-center space-x-2",children:[eV.provider&&(0,t.jsx)(tT.f,{provider:eV.provider,className:"w-4 h-4"}),(0,t.jsx)("h3",{className:"text-lg font-medium",children:eV.provider||"Not Set"})]})]}),(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsx)("p",{className:"text-sm",children:"LiteLLM Model"}),(0,t.jsx)("div",{className:"mt-2 overflow-hidden",children:(0,t.jsx)(A.x,{content:eV.litellm_model_name||"Not Set",className:"w-full min-w-0",children:(0,t.jsx)("div",{className:"break-all text-sm font-medium leading-relaxed cursor-pointer",children:eV.litellm_model_name||"Not Set"})})})]}),(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsx)("p",{className:"text-sm",children:"Pricing"}),(0,t.jsx)(tP,{model:eV})]})]}),(0,t.jsxs)("div",{className:"mb-6 text-sm text-muted-foreground flex items-center gap-x-6",children:[(0,t.jsxs)("div",{className:"flex items-center gap-x-2",children:[(0,t.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})}),"Created At"," ",eV.model_info.created_at?new Date(eV.model_info.created_at).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}):"Not Set"]}),(0,t.jsxs)("div",{className:"flex items-center gap-x-2",children:[(0,t.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,t.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"})}),"Created By ",eV.model_info.created_by||"Not Set"]})]}),eV?.litellm_params?.kubernetes_pod_discovery===!0&&(0,c.v)(o??"")&&(0,t.jsx)("div",{className:"mb-6",children:(0,t.jsx)(sg,{modelId:e})}),(0,t.jsxs)(E.N,{className:"block p-6",children:[(0,t.jsxs)("div",{className:"flex justify-between items-center mb-4",children:[(0,t.jsx)("h3",{className:"text-lg font-medium",children:"Model Settings"}),(0,t.jsxs)("div",{className:"flex gap-2",children:[e0&&eQ&&!F&&(0,t.jsx)(g.K,{onClick:()=>W(!0),className:"flex items-center",children:"Edit Auto Router"}),eX?!F&&(0,t.jsx)(g.K,{onClick:()=>K(!0),className:"flex items-center",children:"Edit Settings"}):(0,t.jsx)(A.x,{content:"Only DB models can be edited. You must be an admin or the creator of the model to edit it.",children:(0,t.jsx)(et.f,{className:"size-4 text-muted-foreground"})})]})]}),x?(0,t.jsx)(sp,{localModelData:x,modelData:eV,teamAlias:eU(x.model_info?.team_id),accessToken:l,isEditing:F,isSaving:R,isWildcardModel:tt,ptuCostAttributionEnabled:eK,showCacheControl:U,setShowCacheControl:B,onCancel:()=>K(!1),onSubmit:e7,modelAccessGroups:h,guardrailsList:eN,tagsList:eS,credentialsList:eI,healthCheckModelOptions:ta,teams:eZ},x.model_info?.id):(0,t.jsx)("p",{className:"text-sm",children:"Loading..."})]})]}),(0,t.jsx)(T.S,{value:"raw",keepMounted:!0,children:(0,t.jsx)(E.N,{className:"block p-6",children:(0,t.jsx)("pre",{className:"bg-muted p-4 rounded-sm text-xs overflow-auto",children:JSON.stringify(eG,null,2)})})})]})]}),(0,t.jsx)(eA.f,{isOpen:j,title:e2,alertMessage:"This action cannot be undone.",message:`Are you sure you want to delete this ${e1?"auto-router":"model"}?`,resourceInformationTitle:"Model Information",resourceInformation:[{label:"Model Name",value:eV?.model_name||"Not Set"},{label:"LiteLLM Model Name",value:eV?.litellm_model_name||"Not Set"},{label:"Provider",value:eV?.provider||"Not Set"},{label:"Created By",value:eV?.model_info?.created_by||"Not Set"}],onCancel:()=>v(!1),onOk:e9,confirmLoading:N}),P&&!e5?(0,t.jsx)(tk,{isVisible:P,onCancel:()=>I(!1),onAddCredential:e3,existingCredential:D,setIsCredentialModalOpen:I}):(0,t.jsx)(eh.N,{open:P,onOpenChange:e=>!e&&I(!1),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Using Existing Credential"})}),(0,t.jsx)(tS,{className:"text-sm",credentialName:eV.litellm_params.litellm_credential_name??"",label:(0,tw.N)(eI).get(eV.litellm_params.litellm_credential_name??"")}),(0,t.jsx)(eh.c,{children:(0,t.jsx)(g.K,{variant:"outline",onClick:()=>I(!1),children:"Cancel"})})]})}),O&&l&&(0,t.jsx)(tF,{open:O,onCancel:()=>L(!1),accessToken:l,modelId:e,onUpdated:()=>{f.invalidateQueries({queryKey:["models","list"]})}}),(0,t.jsx)(ty,{isVisible:H,onCancel:()=>W(!1),onSuccess:e=>{_(e),m&&m(e)},modelData:x||eV,accessToken:l||"",userRole:o||"",isMemberManaged:!eX}),(0,t.jsx)(eh.N,{open:ea,onOpenChange:e=>!e&&er(!1),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[700px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Connection Test Results"})}),ea&&l&&(0,t.jsx)(ep,{accessToken:l,targets:eu,jevRequest:((e,t,s)=>{if(!t)return;let a="string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return}})():e,l=ex.z.object({classifier_type:e_.z.enum(["jev","oss_classifier"]),tiers:eg.z.record(ej.z.string(),ev.z.unknown()),jev_classifier_config:eb.j.optional(),opensource_classifier_config:eb.j.optional()}).loose().safeParse(a);if(!l.success)return;let{jev_classifier_config:r,opensource_classifier_config:i,...n}=l.data,o=(0,eb.E)({...n,jev_classifier_config:r,opensource_classifier_config:i});return{prompt:ey,complexity_router_config:{...n,classifier_type:"oss_classifier",opensource_classifier_config:(0,eb.L)(o.jev_classifier_config)},saved_model_id:t,...s&&{team_id:s}}})((x??eV)?.litellm_params?.complexity_router_config,(x??eV)?.model_info?.id,(x??eV)?.model_info?.team_id)},ed),(0,t.jsx)(eh.c,{children:(0,t.jsx)(g.K,{variant:"outline",onClick:()=>er(!1),children:"Close"})})]})})]})}var sv=e.i(56567);function sb(){let[{model:e,team:t},a]=(0,l.i)({model:l.d,team:l.d},{history:"push"}),r=(0,s.useCallback)(e=>{a({model:e,team:null})},[a]);return{modelId:e,teamId:t,openModel:r,openTeam:(0,s.useCallback)(e=>{a({model:null,team:e})},[a]),close:(0,s.useCallback)(()=>{a({model:null,team:null})},[a])}}function sy(){let{data:e,isLoading:t}=(0,y.e)(),a=(0,s.useMemo)(()=>Array.from(new Set(e?.data?.map(e=>e.model_name)??[])).sort(),[e?.data]);return{availableModelGroups:a,availableModelAccessGroups:(0,s.useMemo)(()=>Array.from(new Set(e?.data?.flatMap(e=>e.model_info?.access_groups??[])??[])),[e?.data]),allModelsOnProxy:(0,s.useMemo)(()=>e?.data?.map(e=>e.model_name)??[],[e?.data]),isLoading:t}}var sN=e.i(243652);let sk=(0,sN.f)("credentials"),sw=({enabled:e=!0}={})=>{let{accessToken:t}=(0,i.f)();return(0,eP.f)({queryKey:sk.list({}),queryFn:async()=>await (0,em.lg)(t),enabled:e&&!!t})};var sC=e.i(153472),sS=e.i(954616);let sM=async(e,t)=>{let s=(0,em._h)(),a=s?`${s}/config/field/update`:"/config/field/update",l=await fetch(a,{method:"POST",headers:{[(0,em.kR)()]:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({field_name:"store_model_in_db",field_value:t.store_model_in_db,config_type:"general_settings"})});if(!l.ok){let e=await l.json().catch(()=>({}));throw Error(e?.error?.message||e?.message||e?.detail||"Failed to update model storage settings")}return await l.json()};var sE=e.i(190702),sT=e.i(302747);let sA=({isVisible:e,onCancel:a,onSuccess:l})=>{let r,{mutateAsync:n,isPending:o}=(()=>{let{accessToken:e}=(0,i.f)();return(0,sS.f)({mutationFn:async t=>{if(!e)throw Error("Access token is required");return await sM(e,t)}})})(),{data:d,isLoading:c,refetch:u}=(0,sC._)(sC.e.GENERAL_SETTINGS);(0,s.useEffect)(()=>{e&&u()},[e,u]);let m=(0,s.useMemo)(()=>{if(!d)return{store_model_in_db:!1};let e=d.find(e=>"store_model_in_db"===e.field_name);return{store_model_in_db:e?.field_value??!1}},[d]),h=(0,tD.G)({defaultValues:m,values:m}),p=async e=>{try{await n(e,{onSuccess:()=>{eH.f.success("Model storage settings updated successfully"),u(),l?.()},onError:e=>{eH.f.fromError("Failed to save model storage settings: "+(0,sE.f)(e))}})}catch(e){eH.f.fromError("Failed to save model storage settings: "+(0,sE.f)(e))}},f=()=>{h.reset(m),a()};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&f(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{className:"text-base",children:"Model Settings"})}),(0,t.jsx)(A.g,{children:(0,t.jsx)("form",{onSubmit:e=>e.preventDefault(),children:(0,t.jsx)(eJ.e,{children:(0,t.jsx)(eY.f,{control:h.control,name:"store_model_in_db",label:(r=d?.find(e=>"store_model_in_db"===e.field_name)?.field_description||"If enabled, models and config are stored in and loaded from the database.",(0,t.jsxs)(t.Fragment,{children:["Store Model in DB",(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)(e6.f,{className:"size-3.5 shrink-0 cursor-help text-muted-foreground"})}),(0,t.jsx)(A.Y,{children:r})]})]})),children:({id:e,value:s,onChange:a,onBlur:l})=>c?(0,t.jsx)(sT.f,{role:"status","aria-label":"Loading model settings",className:"h-[18.4px] w-8 rounded-full"}):(0,t.jsx)(tY.f,{id:e,checked:!!s,onCheckedChange:a,onBlur:l,className:"w-fit"})})})})}),(0,t.jsxs)(eh.c,{children:[(0,t.jsx)(g.K,{variant:"outline",onClick:f,disabled:o||c,children:"Cancel"}),(0,t.jsx)(g.K,{disabled:o||c,"aria-busy":o,onClick:()=>void h.handleSubmit(p)(),children:o?"Saving...":"Save Settings"})]})]})})};var sP=e.i(655063),sI=e.i(682830);let sz="model_info_blocked";var sO=e.i(555436),sL=e.i(239616);e.i(707701);var sR=e.i(807235),sq=e.i(981080),sF=e.i(531649),sK=e.i(554134),sD=e.i(174886),sV=e.i(531278),sU=e.i(788699),sB=e.i(418371),s$=e.i(494862);e.i(622826);var sG=e.i(581070),sH=e.i(200208),sW=e.i(399536),sJ=e.i(112179),sY=e.i(436589);let sX="model_name",sQ="model_info_created_by",sZ="model_info_updated_at",s0="input_cost",s1="model_info_access_groups",s2="model_info_db_model",s4=[sX,sQ,sZ,s0,s2],s5={[s0]:"costs",[s2]:"status",[sQ]:"created_at",[sZ]:"updated_at"};function s6({model:e,displayName:s}){let a=e.litellm_model_name||"-";return(0,t.jsxs)(sY.c,{children:[(0,t.jsxs)(sY.b,{render:(0,t.jsx)("div",{className:"flex min-w-0 items-center gap-2.5","data-testid":`model-information-${e.model_info.id}`}),children:[e.provider?(0,t.jsx)(sB.f,{provider:e.provider,className:"size-6 shrink-0"}):(0,t.jsx)("span",{className:"flex size-6 shrink-0 items-center justify-center rounded-md bg-muted text-xs text-muted-foreground",children:"-"}),(0,t.jsxs)("span",{className:"flex min-w-0 flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"max-w-60 truncate text-sm font-medium text-foreground",title:s,children:s}),(0,t.jsx)("span",{className:"max-w-60 truncate font-mono text-xs text-muted-foreground",title:a,children:a})]})]}),(0,t.jsx)(sY.P,{align:"start",className:"w-80",children:(0,t.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[e.provider?(0,t.jsx)(sB.f,{provider:e.provider,className:"size-4 shrink-0"}):null,(0,t.jsx)("span",{className:"truncate text-xs text-muted-foreground",children:e.provider||"Unknown provider"})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"Public Model Name"}),(0,t.jsx)("span",{className:"truncate text-sm font-medium text-foreground",title:s,children:s})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"LiteLLM Model Name"}),(0,t.jsxs)("span",{className:"flex min-w-0 items-center gap-1.5",children:[(0,t.jsx)("span",{className:"truncate font-mono text-sm text-foreground",title:a,children:a}),(0,t.jsx)("button",{type:"button","aria-label":"Copy LiteLLM model name","data-testid":`copy-litellm-model-name-${e.model_info.id}`,className:"shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",onClick:()=>void(0,es.W)(a,"LiteLLM model name copied"),children:(0,t.jsx)(sD.f,{className:"size-3.5"})})]})]})]})})]})}function s3(){return(0,t.jsxs)("span",{className:"flex items-center gap-1",children:["Credentials",(0,t.jsxs)(sY.c,{children:[(0,t.jsx)(sY.b,{render:(0,t.jsx)("button",{type:"button","aria-label":"About credential types","data-testid":"credentials-header-info",className:"cursor-pointer text-muted-foreground hover:text-foreground"}),children:(0,t.jsx)(et.f,{className:"size-3.5"})}),(0,t.jsx)(sY.P,{align:"start",className:"w-80",children:(0,t.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,t.jsx)("span",{className:"text-sm font-medium text-foreground",children:"Credential types"}),(0,t.jsxs)("div",{className:"flex flex-col gap-1",children:[(0,t.jsxs)("span",{className:"flex items-center gap-1.5 text-sm font-medium text-info",children:[(0,t.jsx)(a.f,{className:"size-3.5"}),"Reusable"]}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"Credentials saved in LiteLLM that can be added to models repeatedly."})]}),(0,t.jsxs)("div",{className:"flex flex-col gap-1",children:[(0,t.jsxs)("span",{className:"flex items-center gap-1.5 text-sm font-medium text-foreground",children:[(0,t.jsx)(sU.f,{className:"size-3.5"}),"Manual"]}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:"Credentials added directly during model creation or defined in the config file."})]})]})})]})]})}function s7({credentialName:e,label:s}){return e?(0,t.jsx)(tS,{credentialName:e,label:s,icon:(0,t.jsx)(a.f,{className:"size-3 shrink-0"}),className:"text-xs font-medium text-info"}):(0,t.jsxs)(e8.f,{variant:"outline",className:"gap-1 font-normal text-muted-foreground",children:[(0,t.jsx)(sU.f,{className:"size-3"}),"Manual"]})}function s8({model:e}){let s=!e.model_info?.db_model,a=(e=>{if(!e)return null;let t=new Date(e);return Number.isNaN(t.getTime())?null:(0,sH.y)(t,"date")})(e.model_info.created_at),l=s?"Defined in config":e.model_info.created_by||"Unknown";return(0,t.jsxs)("div",{className:"flex min-w-0 flex-col gap-0.5",children:[(0,t.jsx)("span",{className:"max-w-44 truncate text-sm text-foreground",title:l,children:l}),(0,t.jsx)("span",{className:"truncate text-xs text-muted-foreground",children:s?"-":a??"Unknown date"})]})}function s9({label:e,value:s}){return(0,t.jsxs)("span",{className:"flex items-baseline gap-1.5",children:[(0,t.jsx)("span",{className:"text-[10px] font-semibold tracking-wider text-muted-foreground",children:e}),(0,t.jsx)("span",{className:"text-xs font-medium tabular-nums text-foreground",children:s})]})}function ae({model:e}){let{input_cost:s,output_cost:a,output_cost_per_second:l}=e,r=null!=l,i=null!=s&&(!r||Number(s)>0),n=null!=a&&(!r||Number(a)>0);return i||n||r?(0,t.jsx)(sG.f,{content:r?"Cost per 1M tokens; /s is cost per second of output":"Cost per 1M tokens",trigger:(0,t.jsxs)("div",{className:"flex flex-col gap-0.5 whitespace-nowrap",children:[i&&(0,t.jsx)(s9,{label:"IN",value:`$${s}`}),n&&(0,t.jsx)(s9,{label:"OUT",value:`$${a}`}),r&&(0,t.jsx)(s9,{label:"OUT",value:(0,es.b)(l)})]})}):(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"})}function at({accessGroups:e}){if(!e||0===e.length)return(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"});let[s,...a]=e;return(0,t.jsxs)("div",{className:"flex min-w-0 items-center gap-1",children:[(0,t.jsx)(e8.f,{variant:"outline",className:"max-w-36 truncate border-info/20 bg-info/10 font-normal text-info",children:s}),a.length>0&&(0,t.jsx)(sG.f,{content:(0,t.jsx)("div",{className:"flex max-w-[280px] flex-col gap-0.5",children:a.map(e=>(0,t.jsx)("span",{children:e},e))}),trigger:(0,t.jsxs)(e8.f,{variant:"outline",className:"shrink-0 cursor-default font-normal",children:["+",a.length," more"]})})]})}function as({model:e,userRole:s,userID:a,isViewOnly:l,isPausing:r,onDeleteClick:i,onTogglePauseClick:n}){let o=e.model_info?.id,d=!e.model_info?.db_model,c="Admin"===s&&!l,u=!l&&(c||e.model_info?.created_by===a),m=e.model_info?.blocked===!0,h=!d&&c&&!!n;return(0,t.jsxs)("div",{className:"flex items-center justify-end gap-1.5",children:[(0,t.jsx)("span",{className:"flex w-8 shrink-0 items-center justify-center",children:r?(0,t.jsx)(sV.f,{className:"size-4 animate-spin text-muted-foreground","data-testid":`model-pause-pending-${o}`}):(0,t.jsx)(sG.f,{content:d?"Config models cannot be paused from the dashboard. Pause is DB-backed.":c?m?"Resume model — restore normal routing.":"Pause model — stop routing requests until resumed.":"Only proxy admins can pause or resume a model.",trigger:(0,t.jsx)("span",{className:"inline-flex",children:(0,t.jsx)(tY.f,{size:"sm",checked:!m,disabled:!h,"aria-label":m?"Resume model":"Pause model","data-testid":`model-pause-toggle-${o}`,onCheckedChange:e=>{h&&n&&o&&n(o,!e)}})})})}),(0,t.jsx)(sG.f,{content:d?"Config model cannot be deleted on the dashboard. Please delete it from the config file.":"Delete model",trigger:(0,t.jsx)("span",{className:"inline-flex",children:(0,t.jsx)(g.K,{variant:"ghost",size:"icon-sm","aria-label":"Delete model","data-testid":`model-delete-${o}`,disabled:d||!u,className:"text-muted-foreground hover:bg-destructive/10 hover:text-destructive",onClick:()=>{i&&o&&i(o)},children:(0,t.jsx)(e7.f,{className:"size-4"})})})})]})}let aa="personal",al="wildcard",ar="All Proxy Models",ai={[sX]:"Public Model Name",[s1]:"Model Access Group",[sz]:"Status"},an={all:"All",active:"Active",paused:"Paused"},ao={current_team:"Current Team Models",all:ar};function ad(){return(0,t.jsxs)("div",{className:"flex flex-col items-center gap-1 py-6",children:[(0,t.jsx)("div",{className:"mb-1 flex size-11 items-center justify-center rounded-xl bg-muted",children:(0,t.jsx)(sO.f,{className:"size-5 text-muted-foreground"})}),(0,t.jsx)("div",{className:"text-base font-semibold text-foreground",children:"No models found"}),(0,t.jsx)("div",{className:"max-w-80 text-sm text-muted-foreground",children:"No models match your search or filters. Try resetting them."})]})}function ac({data:e,rowCount:a,isLoading:l,isRefreshing:r,onRefresh:i,sorting:n,onSortingChange:o,pagination:d,onPaginationChange:c,columnFilters:u,onColumnFiltersChange:m,onResetFilters:h,searchValue:p,onSearchChange:f,teamOptions:x,selectedTeamValue:_,onTeamChange:j,isLoadingTeams:v,viewMode:b,onViewModeChange:y,onOpenModelSettings:N,availableModelGroups:k,availableModelAccessGroups:w,userRole:C,userID:S,isViewOnly:M,onModelIdClick:E,onTeamIdClick:T,onDeleteClick:A,onTogglePauseClick:P,pausingModelId:I,credentialLabels:z}){let[O,L]=(0,s.useState)(!1),R=(0,s.useMemo)(()=>(({userRole:e,userID:s,isViewOnly:a,onModelIdClick:l,onTeamIdClick:r,onDeleteClick:i,onTogglePauseClick:n,pausingModelId:o,credentialLabels:d})=>[{id:"model_info_id",accessorFn:e=>e.model_info.id,meta:{title:"Model ID"},header:"Model ID",enableSorting:!1,size:140,minSize:90,cell:({row:e})=>(0,t.jsx)(sW.f,{value:e.original.model_info.id,onClick:l,dataTestId:`model-id-${e.original.model_info.id}`})},{id:sX,accessorFn:e=>e.model_name??"",meta:{title:"Model Information",skeleton:"twoLine"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Model Information"}),enableSorting:!0,size:280,minSize:160,cell:({row:e})=>(0,t.jsx)(s6,{model:e.original,displayName:sf(e.original)||"-"})},{id:"litellm_credential_name",accessorFn:e=>e.litellm_params?.litellm_credential_name??"",meta:{title:"Credentials"},header:()=>(0,t.jsx)(s3,{}),enableSorting:!1,size:180,minSize:110,cell:({row:e})=>{let s=e.original.litellm_params?.litellm_credential_name;return(0,t.jsx)(s7,{credentialName:s,label:s?d?.get(s):void 0})}},{id:sQ,accessorFn:e=>e.model_info.created_by??"",meta:{title:"Created By",skeleton:"twoLine"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Created By"}),enableSorting:!0,size:180,minSize:110,cell:({row:e})=>(0,t.jsx)(s8,{model:e.original})},{id:sZ,accessorFn:e=>e.model_info.updated_at??"",meta:{title:"Updated At"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Updated At"}),enableSorting:!0,size:140,minSize:100,cell:({row:e})=>(0,t.jsx)(sH.S,{value:e.original.model_info.updated_at,precision:"date"})},{id:s0,accessorFn:e=>e.input_cost,meta:{title:"Costs",numeric:!0},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Costs"}),enableSorting:!0,size:130,minSize:90,cell:({row:e})=>(0,t.jsx)(ae,{model:e.original})},{id:"model_info_team_id",accessorFn:e=>e.model_info.team_id??"",meta:{title:"Team ID"},header:"Team ID",enableSorting:!1,size:140,minSize:90,cell:({row:e})=>(0,t.jsx)(sW.f,{value:e.original.model_info.team_id,onClick:r,dataTestId:`model-team-id-${e.original.model_info.id}`})},{id:s1,accessorFn:e=>e.model_info.access_groups??[],meta:{title:"Model Access Group",skeleton:"chips"},header:"Model Access Group",enableSorting:!1,size:200,minSize:120,cell:({row:e})=>(0,t.jsx)(at,{accessGroups:e.original.model_info.access_groups})},{id:s2,accessorFn:e=>e.model_info.db_model,meta:{title:"Source",skeleton:"badge"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Source"}),enableSorting:!0,size:140,minSize:100,cell:({row:e})=>e.original.model_info.db_model?(0,t.jsx)(sJ.f,{tone:"info",label:"DB Model"}):(0,t.jsx)(sJ.f,{tone:"neutral",label:"Config Model"})},{id:"actions",meta:{title:"Actions",className:"text-right",headerClassName:"text-right"},header:"Actions",enableSorting:!1,enableHiding:!1,enableResizing:!1,size:110,minSize:110,cell:({row:l})=>(0,t.jsx)(as,{model:l.original,userRole:e,userID:s,isViewOnly:a,isPausing:o===l.original.model_info?.id,onDeleteClick:i,onTogglePauseClick:n})}])({userRole:C,userID:S,isViewOnly:M,onModelIdClick:E,onTeamIdClick:T,onDeleteClick:A,onTogglePauseClick:P,pausingModelId:I,credentialLabels:z}),[C,S,M,E,T,A,P,I,z]),q=(0,s.useMemo)(()=>[{label:ar,value:"all"},{label:"Wildcard Models (*)",value:al},...k.map(e=>({label:e,value:e}))],[k]),F=(0,s.useMemo)(()=>[{label:"All Model Access Groups",value:"all"},...w.map(e=>({label:e,value:e}))],[w]),K=(e,t)=>{let s=String(t);return e===sX&&s===al?"Wildcard Models (*)":e===sz?an[s]??s:s},D=x.find(e=>e.value===_)?.label??x[0]?.label??"";return(0,t.jsx)(sR.f,{data:e,columns:R,getRowId:(e,t)=>e.model_info?.id??String(t),sortingMode:"server",sorting:n,onSortingChange:o,enableSortingRemoval:!0,paginationMode:"server",pagination:d,onPaginationChange:c,rowCount:a,pageSizeOptions:[10,25,50],filterMode:"server",columnFilters:u,onColumnFiltersChange:m,defaultColumnVisibility:{[s2]:!1},enableColumnResizing:!0,maxBodyHeight:600,isLoading:l,loadingMessage:"Loading models…",noDataMessage:(0,t.jsx)(ad,{}),size:"compact",toolbar:e=>(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(sF.f,{table:e,searchValue:p,onSearchChange:f,searchPlaceholder:"Search model names…",onOpenFilters:()=>L(!0),onRefresh:i,isRefreshing:r,filterLabels:ai,formatFilterValue:K,children:[(0,t.jsxs)(tJ.d,{value:_,onValueChange:e=>j(String(e)),children:[(0,t.jsxs)(tJ.P,{size:"sm","aria-label":"Current team","data-testid":"models-team-select",className:"gap-2 bg-secondary",children:[(0,t.jsx)("span",{className:(0,tC.c)("size-2 shrink-0 rounded-full",_===aa?"bg-info":"bg-success")}),(0,t.jsx)("span",{className:"text-muted-foreground",children:"Team"}),(0,t.jsx)("span",{className:"truncate font-semibold",children:D})]}),(0,t.jsx)(tJ.r,{children:x.map(e=>(0,t.jsx)(tJ.T,{value:e.value,disabled:v,className:"[&>div]:min-w-0",children:(0,t.jsx)("span",{"data-slot":"select-item-label",className:"min-w-0 truncate",title:e.label,children:e.label})},e.value))})]}),(0,t.jsxs)(tJ.d,{value:b,onValueChange:e=>y(e),children:[(0,t.jsxs)(tJ.P,{size:"sm","aria-label":"View","data-testid":"models-view-select",className:"gap-2",children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"View"}),(0,t.jsx)("span",{className:"truncate",children:ao[b]})]}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:"current_team",children:ao.current_team}),(0,t.jsx)(tJ.T,{value:"all",children:ao.all})]})]}),(0,t.jsx)(sK.f,{className:"mx-0.5"}),(0,t.jsx)(g.K,{variant:"outline",size:"icon-sm","aria-label":"Model Settings",title:"Model Settings","data-testid":"models-settings-trigger",onClick:N,children:(0,t.jsx)(sL.f,{})})]}),(0,t.jsx)(sq.q,{table:e,open:O,onOpenChange:L,title:"Filters",description:"Narrow down models + endpoints",resetLabel:"Reset Filters",onReset:h,children:({get:e,set:s})=>(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(sq.Q,{label:"Public Model Name",children:(0,t.jsx)(eI.f,{options:q,value:e(sX)??"all",onValueChange:e=>s(sX,"all"===e?void 0:e??void 0),placeholder:"Filter by Public Model Name",emptyText:"No models found"})}),(0,t.jsx)(sq.Q,{label:"Status",children:(0,t.jsxs)(tJ.d,{value:e(sz)??"all",onValueChange:e=>s(sz,"all"===e?void 0:e),children:[(0,t.jsx)(tJ.P,{"aria-label":"Filter by status",className:"w-full",children:an[e(sz)??"all"]??an.all}),(0,t.jsx)(tJ.r,{children:Object.keys(an).map(e=>(0,t.jsx)(tJ.T,{value:e,children:an[e]},e))})]})}),(0,t.jsx)(sq.Q,{label:"Model Access Group",children:(0,t.jsx)(eI.f,{options:F,value:e(s1)??"all",onValueChange:e=>s(s1,"all"===e?void 0:e??void 0),placeholder:"Filter by Model Access Group",emptyText:"No model access groups found"})})]})})]})})}let au=(e,t,s)=>(0,l.k)({parse:s=>{let a=l.w.parse(s);return null===a?null:Math.min(Math.max(a,e),t)},serialize:String}).withDefault(s),am={model_search:l.d.withDefault(""),view_mode:(0,l.b)(["current_team","all"]).withDefault("current_team"),filter_team:l.d.withDefault(aa),access_group:l.d.withDefault(""),status:l.d.withDefault(""),sort_by:(0,l.b)(s4),sort_order:(0,l.b)(["asc","desc"]).withDefault("asc"),page:au(1,1e5,1),page_size:au(1,100,50)},ah=({selectedModelGroup:e,setSelectedModelGroup:a,availableModelGroups:o,availableModelAccessGroups:d,setSelectedModelId:u,setSelectedTeamId:m})=>{let{data:h,isLoading:p}=(0,b.X)(),{accessToken:f,userId:x,userRole:g,isViewOnly:j}=(0,i.f)(),{data:v,isLoading:N}=(0,n.n)(),{data:k}=sw({enabled:(0,c.u)(g??"")}),C=(0,s.useMemo)(()=>(0,tw.N)(k?.credentials??[]),[k]),S=(0,r.d)(),[M,E]=(0,l.i)(am),T=M.model_search,[A]=(0,sP.f)(T,{wait:200}),P=M.view_mode,I=M.filter_team,z=M.access_group||null,O="active"===M.status||"paused"===M.status?M.status:null,L=null===O?void 0:"paused"===O,R=(0,s.useMemo)(()=>({pageIndex:M.page-1,pageSize:M.page_size}),[M.page,M.page_size]),q=(0,s.useMemo)(()=>M.sort_by?[{id:M.sort_by,desc:"desc"===M.sort_order}]:[],[M.sort_by,M.sort_order]),[F,K]=(0,s.useState)(!1),[D,V]=(0,s.useState)(null),[U,B]=(0,s.useState)(!1),[$,G]=(0,s.useState)(null),H=I===aa?void 0:I,W=e&&"all"!==e&&e!==al?e??void 0:void 0,J=z&&"all"!==z?z:void 0,Y=e===al,X=(0,s.useMemo)(()=>{if(0!==q.length){let e;return s5[e=q[0].id]??e}},[q]),Q=(0,s.useMemo)(()=>{if(0!==q.length)return q[0].desc?"desc":"asc"},[q]),{data:Z,isLoading:ee,isFetching:es,refetch:ea}=(0,y.e)(R.pageIndex+1,R.pageSize,A||void 0,void 0,H,X,Q,!0,W,J,Y,L),el=(0,s.useCallback)(e=>null!=h&&"object"==typeof h&&e in h?h[e].litellm_provider:"openai",[h]),er=(0,s.useMemo)(()=>Z?w(Z,el):{data:[]},[Z,el]),ei=(0,s.useMemo)(()=>[e&&"all"!==e?{id:sX,value:e}:null,z?{id:s1,value:z}:null,O?{id:sz,value:O}:null].filter(e=>null!==e),[e,z,O]),en=(0,s.useCallback)(e=>{E({model_search:e||null,page:null})},[E]),eo=(0,s.useCallback)(e=>{let t=(0,sI.b)(e,R);E({page:t.pageIndex+1,page_size:t.pageSize})},[R,E]),ed=(0,s.useMemo)(()=>[{value:aa,label:"Personal"},...(v??[]).filter(e=>e.team_id).map(e=>({value:e.team_id,label:e.team_alias?e.team_alias:e.team_id}))],[v]),ec=(0,s.useMemo)(()=>(v??[]).find(e=>e.team_id===I)??null,[v,I]),eu=(0,s.useMemo)(()=>D&&er?.data?er.data.find(e=>e.model_info.id===D):null,[D,er]),eh=async()=>{if(f&&D)try{B(!0),await (0,em.o2)(f,D),eH.f.success("Model deleted successfully"),S.invalidateQueries({queryKey:["models","list"]}),ea()}catch(e){console.error("Error deleting model:",e),eH.f.fromError(e)}finally{B(!1),V(null)}},ep=(0,s.useCallback)(async(e,t)=>{if(f)try{G(e),await (0,em.Gp)(f,{blocked:t},e),eH.f.success(t?"Model paused":"Model resumed"),S.invalidateQueries({queryKey:["models","list"]})}catch(e){console.error("Error toggling model pause state:",e),eH.f.fromError(e)}finally{G(null)}},[f,S]),ef=(0,s.useCallback)(()=>{ea()},[ea]),ex=(0,s.useCallback)(e=>{V(e)},[]),e_=(0,s.useCallback)(()=>{K(!0)},[]),eg=ec?.team_alias||ec?.team_id||"";return(0,t.jsxs)("div",{className:"w-full",children:[(0,t.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,t.jsx)(ac,{data:er.data,rowCount:Z?.total_count??0,isLoading:ee||p,isRefreshing:es,onRefresh:ef,sorting:q,onSortingChange:e=>{let t,s=(0,sI.b)(e,q)[0];E({sort_by:s&&(t=s.id,s4.includes(t))?s.id:null,sort_order:s?.desc?"desc":null,page:null})},pagination:R,onPaginationChange:eo,columnFilters:ei,onColumnFiltersChange:e=>{let t=(0,sI.b)(e,ei),s=t.find(e=>e.id===sX)?.value,l=t.find(e=>e.id===s1)?.value,r=t.find(e=>e.id===sz)?.value;a("string"==typeof s?s:"all"),E({access_group:"string"==typeof l?l:null,status:"string"==typeof r?r:null,page:null})},onResetFilters:()=>{a("all"),E(null)},searchValue:T,onSearchChange:en,teamOptions:ed,selectedTeamValue:I,onTeamChange:e=>{E({filter_team:e,page:null})},isLoadingTeams:N,viewMode:P,onViewModeChange:e=>{E({view_mode:e})},onOpenModelSettings:e_,availableModelGroups:o,availableModelAccessGroups:d,userRole:g,userID:x??"",isViewOnly:j,onModelIdClick:u,onTeamIdClick:m,onDeleteClick:ex,onTogglePauseClick:ep,pausingModelId:$,credentialLabels:C}),"current_team"===P&&(0,t.jsxs)("div",{className:"flex items-start gap-2 px-1 text-xs text-muted-foreground",children:[(0,t.jsx)(et.f,{className:"mt-0.5 size-3.5 shrink-0"}),I===aa?(0,t.jsxs)("span",{children:["To access these models, create a Virtual Key without selecting a team on the"," ",(0,t.jsx)("a",{href:(0,_.B)("api-keys"),className:"font-medium text-info hover:underline",children:"Virtual Keys page"}),"."]}):(0,t.jsxs)("span",{children:['To access these models, create a Virtual Key and select Team as "',eg,'" on the'," ",(0,t.jsx)("a",{href:(0,_.B)("api-keys"),className:"font-medium text-info hover:underline",children:"Virtual Keys page"}),"."]})]})]}),(0,t.jsx)(eA.f,{isOpen:!!D,title:"Delete Model",alertMessage:"This action cannot be undone.",message:"Are you sure you want to delete this model?",resourceInformationTitle:"Model Information",resourceInformation:eu?[{label:"Model Name",value:eu.model_name||"Not Set"},{label:"LiteLLM Model Name",value:eu.litellm_model_name||"Not Set"},{label:"Provider",value:eu.provider||"Not Set"},{label:"Created By",value:eu.model_info?.created_by||"Not Set"}]:[],onCancel:()=>V(null),onOk:eh,confirmLoading:U}),(0,t.jsx)(sA,{isVisible:F,onCancel:()=>K(!1),onSuccess:()=>K(!1)})]})};function ap(){let{modelGroup:e,setModelGroup:a}=function(){let[e,t]=(0,l.o)("model_group",l.d);return{modelGroup:e,setModelGroup:(0,s.useCallback)(e=>{t(e)},[t])}}(),{availableModelGroups:r,availableModelAccessGroups:i}=sy(),{openModel:n,openTeam:o}=sb();return(0,t.jsx)(ah,{selectedModelGroup:e,setSelectedModelGroup:e=>a("all"===e?null:e),availableModelGroups:r,availableModelAccessGroups:i,setSelectedModelId:n,setSelectedTeamId:o})}var af=e.i(112392);function ax({selectedPreset:e,presets:a,presetAvailability:l,onPresetChange:r,pending:i,unavailable:n,onRetry:o}){let d=s.default.useMemo(()=>a.map(e=>({preset:e,availability:l(e)})).sort((e,t)=>Number("available"===t.availability.kind)-Number("available"===e.availability.kind)),[a,l]),c=s.default.useMemo(()=>[...d.map(({preset:e})=>({value:e.key,label:e.label})),{value:"custom",label:"Start from scratch"}],[d]);return(0,t.jsx)("div",{className:"mb-4 w-full space-y-2",children:(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)(tJ.d,{items:c,value:e??null,onValueChange:e=>r(e??void 0),children:[(0,t.jsx)(tJ.P,{"aria-label":"Use a template","data-testid":"template-selector",className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Use a template"})}),(0,t.jsxs)(tJ.r,{className:"[&_[data-slot=select-item]>div]:min-w-0 [&_[data-slot=select-item]>div]:shrink [&_[data-slot=select-item]>div]:whitespace-normal [&_[data-slot=select-item]>div]:break-words",children:[d.map(({preset:e,availability:s})=>{let a=(e=>{switch(e.kind){case"available":return null;case"loading":return"Checking model availability...";case"unverifiable":return"Cannot verify these models are available";case"missing_models":return`Missing: ${e.models.join(", ")}`}})(s),l="missing_models"===s.kind?"text-destructive":"text-muted-foreground",r="available"===s.kind&&s.viaDeployments?"Matches your deployments":null;return(0,t.jsx)(tJ.T,{value:e.key,label:e.label,disabled:null!==a,title:a??e.description,children:(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"font-medium",children:e.label}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:e.description}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:"Replaces classifier and model choices"}),a&&(0,t.jsx)("div",{className:`text-xs mt-1 ${l}`,children:a}),r&&(0,t.jsx)("div",{className:"text-xs mt-1 text-success",children:r})]})},e.key)}),(0,t.jsx)(tJ.H,{className:"mx-0"}),(0,t.jsx)(tJ.T,{value:"custom",label:"Start from scratch",children:(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"font-medium",children:"Start from scratch"}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:"Clears tier models, switches to Heuristics, and resets routing settings"})]})})]})]}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground",children:"Replaces classifier and model choices"}),i&&(0,t.jsx)("div",{className:"text-xs mt-1 text-muted-foreground",children:"Loading templates..."}),n&&(0,t.jsxs)("div",{className:"text-xs mt-1 text-destructive",children:["Could not load templates, so only Start from scratch is shown."," ",(0,t.jsx)("button",{type:"button",className:"underline",onClick:o,children:"Retry"})]})]})})}var a_=e.i(663435);let ag=async(e,t,s,a)=>{try{let l={model_name:e.auto_router_name,litellm_params:{model:"auto_router/complexity_router",complexity_router_config:e.complexity_router_config,complexity_router_default_model:e.auto_router_default_model,...void 0===e.auto_router_routing_compression?{}:{auto_router_routing_compression:e.auto_router_routing_compression},...void 0===e.auto_router_model_compression?{}:{auto_router_model_compression:e.auto_router_model_compression}},model_info:{...e.team_id?{team_id:e.team_id}:{},...e.model_access_group?.length?{access_groups:e.model_access_group}:{}}};await (0,em.jO)(t,l),eH.f.success(`Successfully created Auto Router: ${e.auto_router_name}`),s(),a&&a()}catch(e){console.error("Failed to add auto router:",e),eH.f.fromError("Failed to add auto router: "+e)}};var aj=e.i(491115),av=e.i(240461);let ab=({accessToken:e,config:a,defaultModel:l,routerName:r,teamId:i})=>{let[n,o]=s.default.useState(""),[d,c]=s.default.useState({status:"idle"}),u=(0,ti.e)(a.heuristic_v2_success_threshold),m=async()=>{if(u)return;c({status:"running"});let t=eN({prompt:n,config:a,defaultModel:l,routerName:r,teamId:i}),s=await (0,em.b)(e,t);c("success"===s.status?{status:"done",result:s.result}:{status:"failed",error:s.error})};return(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"Send a prompt through this router's classifier to see which model it would pick, and why. The prompt is only classified: nothing is sent to the model it routes to."}),(0,t.jsx)(tt.f,{value:n,onChange:e=>o(e.target.value),placeholder:"Paste a prompt an end user would send",rows:4,"data-testid":"auto-router-routing-test-prompt"}),(0,t.jsx)("div",{className:"flex justify-end",children:(0,t.jsx)(g.K,{onClick:m,disabled:0===n.trim().length||"running"===d.status||!!u,"data-testid":"auto-router-routing-test-send",children:"running"===d.status?"Routing...":"Send Test Prompt"})}),u&&(0,t.jsx)("p",{className:"text-sm text-destructive",children:u}),"failed"===d.status&&(0,t.jsxs)("div",{className:"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive","data-testid":"auto-router-routing-test-error",children:[(0,t.jsx)("p",{className:"font-medium",children:"Could not route this prompt"}),(0,t.jsx)("p",{children:d.error})]}),"done"===d.status&&(0,t.jsxs)("div",{"data-testid":"auto-router-routing-test-result",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 py-2 text-sm",children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Routed to"}),(0,t.jsx)(e8.f,{variant:"secondary","data-testid":"auto-router-routing-test-routed-model",children:d.result.routed_model}),!d.result.routed_model_configured&&(0,t.jsxs)("span",{className:"flex items-center gap-1 text-warning","data-testid":"auto-router-routing-test-unconfigured",children:[(0,t.jsx)(tI.f,{className:"size-3.5"}),"This proxy has no model group by that name"]})]}),(0,t.jsx)(av.U,{decision:d.result.routing_decision})]})]})};var ay=e.i(176754);let aN=(0,sN.f)("autoRouterPresets"),ak={claude:"Claude",openai:"OpenAI",gemini:"Gemini",grok:"Grok",glm:"GLM",deepseek:"DeepSeek"},aw={cheapest:"Cheapest",balanced:"Balanced",quality:"Best quality"},aC=(e,t)=>{let s=e.match(/[-.](\d{8})$/);return{version:(s?e.slice(0,-9):e).split(/[.-]/).map(Number),snapshot:t||s?Number((t??s[1]).replaceAll("-","")):Number.MAX_SAFE_INTEGER}},aS=e=>{let t=e.toLowerCase().split("/").at(-1).replace(/^(?:us|eu|apac|global|au|jp|us-gov)\./,"").replace(/^(?:anthropic|openai|zai|deepseek)\./,"").replace(/^databricks-/,"").replace(/@default$/,"").replace(/-v\d+(?::\d+)?$/,""),s=t.match(/^claude-(\d+(?:[.-]\d+)*)-(haiku|sonnet|opus)(?:[-@]([0-9]{8}))?$/),a=t.match(/^claude-(haiku|sonnet|opus)-(\d+(?:[.-]\d+)*)(?:@([0-9]+))?$/)??(s?[s[0],s[2],s[1],s[3]]:null);if(a)return{family:"claude",line:a[1],rank:["haiku","sonnet","opus"].indexOf(a[1]),...aC(a[2],a[3]),model:t};let l=t.match(/^gpt-(\d+(?:[.-]\d+)*)-(luna|terra|sol|astra)(?:-(\d{4}-\d{2}-\d{2}))?$/);if(l)return{family:"openai",line:l[2],rank:"terra"===l[2]?.5:["luna","sol","astra"].indexOf(l[2]),...aC(l[1],l[3]),model:t};let r=t.match(/^gemini-(\d+(?:[.-]\d+)*)-(flash-lite|flash|pro)(?:-preview)?$/);if(r)return{family:"gemini",line:r[2],rank:["flash-lite","flash","pro"].indexOf(r[2]),...aC(r[1]),model:t};let i=t.match(/^grok-(\d+(?:[.-]\d+)*?)(?:-(\d{4}))?$/);if(i)return{family:"grok",line:"grok",rank:2,...aC(i[1],i[2]),model:t};let n=t.match(/^glm-(\d+(?:[.-]\d+)*)(-flash)?$/);if(n)return{family:"glm",line:n[2]?"flash":"glm",rank:2*!n[2],...aC(n[1]),model:t};let o=t.match(/^deepseek-v(\d+(?:[.-]\d+)*)-(flash|pro)$/);return o?{family:"deepseek",line:o[2],rank:2*("flash"!==o[2]),...aC(o[1]),model:t}:null},aM=e=>aS(e.litellm_params?.model??"")??aS(e.model_info?.base_model??e.litellm_params?.base_model??""),aE=(e,t,s)=>{let a=e.litellm_params?.model??"",l=e.litellm_params?.custom_llm_provider||(a.includes("/")?a.split("/")[0]:t.providers?.join(", "))||(s?({claude:"anthropic",glm:"zai",openai:"openai",gemini:"gemini",grok:"xai",deepseek:"deepseek"})[s]:"");return l.startsWith("bedrock")?"Bedrock":({anthropic:"Anthropic",openai:"OpenAI",gemini:"Google AI",xai:"xAI",azure:"Azure",azure_ai:"Azure AI",databricks:"Databricks",github_copilot:"GitHub Copilot","vertex_ai-anthropic_models":"Vertex AI",vertex_ai:"Vertex AI",zai:"Z.ai",deepseek:"DeepSeek"})[l]??l},aT=(e,t)=>{var s,a;let l;return s=e.version,a=t.version,(void 0===(l=Array.from({length:Math.max(s.length,a.length)},(e,t)=>t).find(e=>(s[e]??0)!==(a[e]??0)))?0:(s[l]??0)-(a[l]??0))||e.snapshot-t.snapshot},aA=(e,t,s)=>{let a,l=(a=e.filter(e=>void 0!==e.family)).filter(e=>!a.some(t=>t.family===e.family&&t.line===e.line&&aT(t,e)>0)),[r,i]={cheapest:[0,1],quality:[1,2],balanced:[0,2]}[t],n=l.flatMap(e=>l.filter(t=>{let a="auto"===s||e.family===s||t.family===s,l=t.rank>e.rank,r=t.rank===e.rank&&t.family!==e.family;return(l||r)&&a}).map(t=>({everyday:e,hard:t}))),o=({everyday:e,hard:t})=>100*(e.family!==t.family)+10*(e.rank===t.rank)+Math.abs(e.rank-r)+Math.abs(t.rank-i),d=n.toSorted((e,t)=>o(e)-o(t)||e.everyday.name.localeCompare(t.everyday.name)||e.hard.name.localeCompare(t.hard.name))[0];if(!d)return null;let c=d.everyday.family!==d.hard.family,u=d.everyday.rank!==r||d.hard.rank!==i;return{...d,notice:(c?"A complete pair is unavailable in one family. Using two model families.":null)??(u?"Using the closest available pair in this family.":null)}},aP=e=>[e.model!==e.name?e.model:null,e.provider].filter(Boolean).join(" · ");function aI({customized:e,hasSuggestions:s,onReset:a,goal:l,family:r,models:i,everyday:n,hard:o,waitingForTeam:d,loading:c,error:u,notice:m,onGoalChange:h,onFamilyChange:p,onModelChange:f,onAdvanced:x,onRetry:_}){let j=!d&&!c,v=!j||u||s,b=n?.family&&n.family===o?.family?ak[n.family]:null,y=[{value:"auto",label:b?`Auto (${b})`:"Auto"},...Object.entries(ak).map(([e,t])=>({value:e,label:t}))];return(0,t.jsxs)("div",{className:"space-y-4",children:[v&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{children:"Optimize for"}),(0,t.jsx)("div",{className:"grid grid-cols-3 gap-2",role:"group","aria-label":"Routing goal",children:Object.entries(aw).map(([e,s])=>(0,t.jsx)(g.K,{type:"button",className:"w-full",variant:l===e?"default":"outline","aria-pressed":l===e,onClick:()=>h(e),children:s},e))})]}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(ez.f,{htmlFor:"auto-router-family",children:"Model family"}),(0,t.jsxs)(tJ.d,{items:y,value:r,onValueChange:e=>{("auto"===e||e&&e in ak)&&p(e)},children:[(0,t.jsx)(tJ.P,{id:"auto-router-family","aria-label":"Model family",className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:y.map(({value:e,label:s})=>(0,t.jsx)(tJ.T,{value:e,children:s},e))})]})]})]}),d&&(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"Select a team to see available models."}),!d&&c&&(0,t.jsxs)("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",role:"status",children:[(0,t.jsx)(eQ.f,{className:"size-4"}),"Loading deployed models"]}),j&&u&&(0,t.jsxs)("p",{role:"alert",className:"text-sm text-destructive",children:["Could not load deployed models."," ",(0,t.jsx)(g.K,{type:"button",variant:"link",onClick:_,children:"Retry"})]}),j&&!u&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,t.jsx)(ez.f,{children:"Chosen models"}),e&&s&&(0,t.jsx)(g.K,{type:"button",variant:"link",className:"h-auto p-0 text-xs",onClick:a,children:"Use suggested models"})]}),(0,t.jsx)("div",{className:"grid gap-3 sm:grid-cols-2",children:["everyday","hard"].map(e=>{let s="everyday"===e?n:o,a="everyday"===e?o:n,l=i.filter(e=>e.name!==a?.name),r=l.map(e=>({value:e.name,label:e.name})),d="everyday"===e?"Everyday":"Hard tasks";return(0,t.jsxs)("div",{className:"min-w-0 space-y-3 rounded-lg border bg-muted/20 p-4",children:[(0,t.jsxs)("div",{className:"space-y-1",children:[(0,t.jsx)(ez.f,{htmlFor:`auto-router-${e}`,children:d}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground",children:"everyday"===e?"Your cheaper model":"Your stronger model"})]}),(0,t.jsxs)(tJ.d,{items:r,value:s?.name??null,onValueChange:t=>{t&&f(e,t)},children:[(0,t.jsx)(tJ.P,{id:`auto-router-${e}`,"aria-label":`${d} model`,className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Select a deployed model"})}),(0,t.jsx)(tJ.r,{children:l.map(e=>(0,t.jsx)(tJ.T,{value:e.name,label:e.name,children:(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{children:e.name}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:aP(e)})]})},e.name))})]}),s&&(0,t.jsx)("p",{className:"break-words text-xs text-muted-foreground",children:aP(s)})]},e)})})]}),(!n||!o)&&(0,t.jsx)("p",{role:"status",className:"text-sm text-muted-foreground",children:i.length<2?"Two deployed models are needed. Add a model or use Advanced configuration.":"Choose two models to get started."}),m&&!e&&(0,t.jsx)("p",{role:"status",className:"text-xs text-muted-foreground",children:m})]}),(0,t.jsx)(g.K,{type:"button",variant:"link",className:"px-0",onClick:x,children:"Advanced configuration"})]})}let az=[],aO=(e,t,s,...a)=>{let[l,r=[]]=a;return(e.custom_tier_set?(0,tr.O)(e.custom_tier_set):(0,ti.w)(e.tier_labels))??((0,eF.K)(e.classifier_type)?(0,eF.J)(e):(0,ti.k)((0,tr.X)(e)))??(0,ti.C)(e.plan_mode_min_tier,(0,tr.X)(e))??(0,ti.f)(t,(0,tr.X)(e))??("jev"!==(0,tu.t)(e)||e.jev_classifier_config?.deployment_name?null:"Please select a decision model")??(0,ti.b)(e)??(0,ti.e)(e.heuristic_v2_success_threshold)??(0,ti._)(e.reminder_markers)??(0,ti.r)(e.classifier_type,e.classifier_plugin_timeout_ms)??("decides"===(0,tu.H)(e)?(0,tc.R)(e.custom_dimensions):null)??(0,ti.I)(e,r)??(0,ay.U)(s,l)},aL={auto_router_name:"auto-router",team_id:null,model_access_group:void 0},aR=({reason:e,children:s})=>null===e?s:(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:s}),(0,t.jsx)(A.Y,{children:e})]}),aq=({handleOk:e,accessToken:a,userRole:l,userId:r,createScope:i="unscoped-ok",teams:n=null})=>{let o,d,m,h="team-required"===i,p=(0,eZ.f)(ex.z.object({auto_router_name:ej.z.string().min(1,"Auto router name is required"),team_id:ej.z.string().nullable().refine(e=>!h||!!e,"Please select a team to continue"),model_access_group:eK.z.array(ej.z.string()).optional()}),{defaultValues:aL}),f=(0,tD.h)({control:p.control,name:"auto_router_name"}),x=(0,tD.h)({control:p.control,name:"team_id"}),_={userRole:l,userID:r??null,isViewOnly:!1},j=h&&!(0,u.d)(_,n,{teamId:x,isDbModel:!0}),[v,b]=(0,s.useState)([]),[N,k]=(0,s.useState)({tiers:{SIMPLE:[],MEDIUM:[],COMPLEX:[],REASONING:[]},classifier_type:"heuristic",classification_mode:"user_turn"}),[w,C]=(0,s.useState)(!1),[S,M]=(0,s.useState)(!1),[T,P]=(0,s.useState)("balanced"),[I,z]=(0,s.useState)("auto"),[O,L]=(0,s.useState)({}),[R,q]=(0,s.useState)([]),[F,K]=(0,s.useState)([]),[D,V]=(0,s.useState)(!1),[U,B]=(0,s.useState)(void 0),[$,G]=(0,s.useState)(tn.h),[H,W]=(0,s.useState)(aj.S),[J,Y]=(0,s.useState)(to.p),[X,Q]=(0,s.useState)(!1),[Z,ee]=(0,s.useState)(!1),[et,es]=(0,s.useState)(!1),[ea,el]=(0,s.useState)(void 0),[er,ei]=(0,s.useState)(!1),[en,eo]=(0,s.useState)(!1),[ed,ec]=(0,s.useState)(!1),[eu,ep]=(0,s.useState)(0),[e_,eg]=(0,s.useState)([]);(0,s.useEffect)(()=>{(async()=>{b((await (0,em.SL)(a,"","",!1,null,!0,!0)).data.map(e=>e.id))})()},[a]);let{data:ev,isLoading:ek,isError:eC,refetch:eS}=(0,eP.f)({queryKey:["availableModels","autoRouter",a,...h?[x]:[]],queryFn:()=>h?(0,e4.a)(a,x):(0,e4.X)(a),enabled:!!(a&&(!h||x))}),{data:eM,isLoading:eE,isError:eT,refetch:eA}=(0,eP.f)({queryKey:(0,y.Z)(r??"",l),queryFn:()=>(0,y.G)(a,r??"",l),enabled:!!a}),eI=ek||eE;(0,s.useEffect)(()=>{if(eM&&!p.getFieldState("auto_router_name").isDirty){var e;p.setValue("auto_router_name",["auto-router",...Array.from({length:(e=eM.flatMap(e=>e.model_name?[e.model_name]:[])).length+1},(e,t)=>`auto-router-${t+2}`)].find(t=>!e.includes(t)))}},[eM,p]);let ez=s.default.useMemo(()=>ev??[],[ev]),{data:eD,isPending:eV,isError:eU,refetch:eB}=(o={queryKey:aN.list({}),queryFn:async()=>(0,ay.m)(await (0,em.nA)()),staleTime:864e5,gcTime:864e5},(0,eP.f)(o)),e$=eD??az,eG=eC&&void 0===ev,e0=eG||eT&&void 0===eM,e2=c.G.includes(l),e5=s.default.useMemo(()=>(0,ay.J)(ez.map(e=>e.model_group),(0,ay.h)(eM??[])),[ez,eM]),e6=s.default.useMemo(()=>(0,ay.J)(ez.map(e=>e.model_group),[]),[ez]),e3=s.default.useMemo(()=>{let e;return e=eM??[],ez.flatMap(t=>{if(t.mode&&"chat"!==t.mode)return[];let s=e.filter(e=>e.model_name===t.model_group);if(s.some(y.a)||t.model_group.includes("*")||t.model_group.startsWith("auto_router/"))return[];let a=s.filter(e=>!e.model_info?.blocked);if(s.length>0&&0===a.length||a.some(e=>e.model_info?.mode&&"chat"!==e.model_info.mode)||a.some(e=>e.litellm_params?.model?.includes("*")))return[];let l=a.length>0?a.map(aM):[aS(t.model_group)],r=l[0],i=r&&l.every(e=>!!e&&e.family===r.family&&e.line===r.line&&0===aT(e,r))?r:void 0,n=a.length>0?a.map(e=>aE(e,t,i?.family)):[aE({},t,i?.family)];return[{...i,name:t.model_group,model:i?.model??t.model_group,provider:[...new Set(n)].toSorted().join(", ")}]}).toSorted((e,t)=>e.name.localeCompare(t.name))},[ez,eM]),e7=s.default.useMemo(()=>aA(e3,T,I),[e3,T,I]),e8=O.everyday?e3.find(e=>e.name===O.everyday):e7?.everyday,e9=O.hard?e3.find(e=>e.name===O.hard):e7?.hard,te=e8&&e9?{classifier_type:"heuristic",classification_mode:"user_turn",tiers:{SIMPLE:[d=e8.name],MEDIUM:[d],COMPLEX:[m=e9.name],REASONING:[m]}}:null,tt=w?N:te??{classifier_type:"heuristic",classification_mode:"user_turn",tiers:{SIMPLE:[],MEDIUM:[],COMPLEX:[],REASONING:[]}},ts=s.default.useCallback(e=>{if(eI)return{kind:"loading"};if(eG)return{kind:"unverifiable"};let t=(0,ay.u)(e,e5);return t.length>0?{kind:"missing_models",models:t}:{kind:"available",viaDeployments:(0,ay.u)(e,e6).length>0}},[eI,eG,e5,e6]),ta=e=>{ee(!1),k(e.complexityRouterConfig),q(e.customTechnicalKeywords),K(e.keywordTierRules),V(e.semanticMatchingEnabled),B(e.embeddingModel),G(e.matchThreshold),W(e.escalationKeywords)};w&&!S&&!eI&&te&&(M(!0),k(e=>!e.custom_tier_set&&!(0,eF.K)(e.classifier_type)&&(0,tr.X)(e).every(e=>0===e.models.length)?{...e,tiers:te.tiers}:e));let tl={tiers:Object.fromEntries((0,tr.X)(tt).map(e=>[(0,tr.P)(e),e.models])),classifierType:(0,tu.t)(tt),classifierLlmConfig:tt.classifier_llm_config,decisionDeploymentName:(0,eb.n)(tt.jev_classifier_config),semanticMatchingEnabled:D,embeddingModel:U,defaultModel:tt.default_model},td=aO(tt,F,tl,e6,ez),tc={...tm(tt),customTechnicalKeywords:R,keywordTierRules:F,semanticMatchingEnabled:D,embeddingModel:U,matchThreshold:$,escalationKeywords:H},th=(0,eL.v)(a,{team_id:h?x:void 0,complexity_router_config:null===td?{...(0,ti.j)(tc)}:null},!h||!!x),tp=w?null:eI?"Loading deployed models":e0?"Could not verify deployed models":e8&&e9&&e8.name!==e9.name?null:"Select two different deployed models",tf=w||!h||x?tp??td??th.saveBlockedReason:"Select a team to see available models.",tx="jev"===(0,tu.t)(tt)?{prompt:ey,config:(0,ti.j)(tc),defaultModel:(0,tr.H)(tt,tt.default_model),routerName:f,teamId:h?x??void 0:void 0}:void 0,t_=tx?eN(tx):void 0,tg=async t=>{let s,l=tf??aO(tt,F,tl,e6,ez)??(0,ti.q)({semanticMatchingEnabled:D,embeddingModel:U,keywordTierRules:F});if(l){Q(!0),eH.f.fromError(l);return}let r=(0,tr.H)(tt,tt.default_model),i=h?["auto_router_name","team_id"]:["auto_router_name"];if(!await p.trigger(i))return void eH.f.fromError("Please fill in all required fields");let n=(0,ti.j)(tc),o=await (0,em.Ms)(a,n,h?p.getValues("team_id")??void 0:void 0),d=(0,ti.c)(o);if(d){Q(!0),eH.f.fromError(d);return}let c={auto_router_name:t,...(s=p.getValues("team_id"),h&&s?{team_id:s}:{}),auto_router_default_model:r,model_type:"complexity_router",complexity_router_config:n,...j?{}:{model_access_group:p.getValues("model_access_group"),...(0,to.S)(J)}};await ag(c,a,()=>p.reset(aL),e)},tj=async()=>{if(et)return;let e=p.getValues("auto_router_name");if(!e){Q(!0),p.trigger("auto_router_name"),eH.f.fromError("Please enter an Auto Router Name");return}es(!0);try{await tg(e)}finally{es(!1)}},tv=(0,t.jsx)(tu.U,{creationFlow:!0,tierSetup:(0,t.jsx)(ax,{selectedPreset:ea,presets:e$,presetAvailability:ts,onPresetChange:e=>{if(M(!0),!e||"custom"===e){el(e),ta((0,ay.k)());return}let t=e$.find(t=>t.key===e);t&&"available"===ts(t).kind&&(el(e),ta((0,ay.D)(t.complexity_router_config,e5)))},pending:eV,unavailable:eU&&void 0===eD,onRetry:()=>void eB()}),editingTiers:Z,onEditingTiersChange:ee,modelInfo:ez,value:tt,onChange:k,customTechnicalKeywords:R,onCustomTechnicalKeywordsChange:q,keywordTierRules:F,onKeywordTierRulesChange:K,keywordRulesError:(0,ti.f)(F,(0,tr.X)(tt)),semanticMatchingEnabled:D,onSemanticMatchingEnabledChange:V,embeddingModel:U,onEmbeddingModelChange:B,matchThreshold:$,onMatchThresholdChange:G,escalationKeywords:H,onEscalationKeywordsChange:W,autoRouterCompression:J,onAutoRouterCompressionChange:j?void 0:Y,showValidationErrors:X});return(0,t.jsx)(eL.R.Provider,{value:th,children:(0,t.jsxs)(A.g,{children:[(0,t.jsx)(E.N,{children:(0,t.jsx)(E.O,{children:(0,t.jsxs)("form",{onSubmit:p.handleSubmit(()=>tj()),noValidate:!0,children:[(0,t.jsx)("div",{className:"mb-4",children:(0,t.jsx)(eY.f,{control:p.control,name:"auto_router_name",label:(0,eW.q)("Auto Router Name","Unique name for this auto router configuration"),children:({ref:e,...s})=>(0,t.jsx)(eX.f,{...s,ref:e,placeholder:"e.g., smart_router, auto_router_1"})})}),(0,t.jsx)("div",{className:w?"mb-6 border-b pb-6":"",children:e2&&w&&(0,t.jsx)("div",{children:(0,t.jsx)(eY.f,{control:p.control,name:"model_access_group",label:(0,eW.q)("Model Access Group","Use model access groups to control who can access this auto router"),children:({id:e,value:s,onChange:a,"aria-invalid":l,"aria-describedby":r})=>(0,t.jsx)(e1,{id:e,value:s,onChange:a,options:v,ariaInvalid:l,ariaDescribedBy:r})})})}),h&&(0,t.jsx)(eY.f,{control:p.control,name:"team_id",label:(0,eW.q)("Select Team","Select the team this auto router belongs to. Only keys for this team will be able to call it."),children:({id:e,value:s,onChange:a})=>(0,t.jsx)(a_.f,{id:e,value:s,onChange:a,filterTeam:e=>(0,u.E)(_,e)})}),!w&&(0,t.jsx)(aI,{customized:!!(O.everyday||O.hard),hasSuggestions:!!(e7||aA(e3,T,"auto")),onReset:()=>L({}),goal:T,family:I,models:e3,everyday:e8,hard:e9,waitingForTeam:h&&!x,loading:eI,error:e0,notice:Object.keys(O).length>0?"Your model choices are kept.":e7?.notice??null,onGoalChange:P,onFamilyChange:e=>{z(e),L({})},onModelChange:(e,t)=>L({everyday:e8?.name,hard:e9?.name,[e]:t}),onAdvanced:()=>{k(tt),M(null!==te),C(!0)},onRetry:()=>{eS(),eA()}}),w&&(0,t.jsx)(eR.U,{value:tt,onChange:e=>{el(void 0),k(e)},decisionModel:(0,t.jsx)(eO,{value:tt,onChange:k,modelInfo:ez,deployments:eM}),judgeModel:(0,t.jsx)(af.f,{section:"judge",value:tt,onChange:k,modelOptions:ez.filter(e=>"embedding"!==e.mode).map(e=>({value:e.model_group,label:e.model_group})),showValidationErrors:X}),children:(0,t.jsxs)(eJ.e,{children:[eG&&(0,t.jsxs)("p",{className:"text-sm text-destructive",children:["Could not load available models."," ",(0,t.jsx)("button",{type:"button",className:"underline",onClick:()=>void eS(),children:"Retry"})]}),tv]})}),!w&&th.isError&&(0,t.jsxs)("p",{className:"mt-3 text-sm text-destructive",role:"alert",children:["Could not check availability."," ",(0,t.jsx)(g.K,{type:"button",variant:"link",onClick:()=>void th.refetch(),children:"Retry"})]}),!w&&th.data?.error&&(0,t.jsx)("p",{className:"mt-3 text-sm text-destructive",role:"alert",children:th.data.error}),(0,t.jsxs)("div",{className:"mt-5 flex flex-wrap items-center justify-between gap-3",children:[(0,t.jsxs)(A.W,{children:[(0,t.jsx)(A.y,{render:(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/issues",className:"text-sm text-primary underline-offset-4 hover:underline",children:"Need Help?"})}),(0,t.jsx)(A.Y,{children:"Get help on our github"})]}),(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,t.jsx)(aR,{reason:td,children:(0,t.jsx)(g.K,{type:"button",variant:"outline","data-testid":"auto-router-test-routing-btn",disabled:null!==td||et,onClick:()=>ei(!0),children:"Test Routing"})}),(0,t.jsxs)(g.K,{type:"button",variant:"outline","data-testid":"auto-router-test-connect-btn",onClick:()=>{let e=ew({tiers:(0,tr.X)(tt).map(e=>[(0,tr.P)(e),e.models]),semanticMatchingEnabled:D,embeddingModel:U,defaultModel:(0,tr.H)(tt,tt.default_model),classifier:(0,eq.n)((0,tu.t)(tt))?{model:tt.classifier_llm_config?.model??"",reasoningEffort:tt.classifier_llm_config?.reasoning_effort}:void 0});0===e.length?eH.f.fromError("Please select at least one model for a complexity tier"):(eg(e),ep(e=>e+1),ec(!0),eo(!0))},disabled:ed,children:[ed&&(0,t.jsx)(eQ.f,{className:"size-4"}),"Test Connection"]}),(0,t.jsx)(aR,{reason:tf,children:(0,t.jsx)(g.K,{type:"button",disabled:null!==tf||et,onClick:()=>{tj()},children:"Add Auto Router"})})]})]})]})})}),(0,t.jsx)(eh.N,{open:er,onOpenChange:e=>!e&&ei(!1),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[760px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:"Test Routing"})}),er&&(0,t.jsx)(ab,{accessToken:a,config:(0,ti.j)(tc),defaultModel:(0,tr.H)(tt,tt.default_model),routerName:f,teamId:h?x??void 0:void 0}),(0,t.jsxs)(eh.c,{children:[" ",(0,t.jsx)(g.K,{variant:"outline",onClick:()=>ei(!1),children:"Close"})]})]})}),(0,t.jsx)(ef,{open:en,onClose:()=>{eo(!1),ec(!1)},testId:eu,accessToken:a,targets:e_,jevRequest:t_,onTestComplete:()=>ec(!1)})]})})};var aF=e.i(548151),aK=e.i(541071),aD=e.i(997422),aV=e.i(755146);let aU=e=>6.5*e.length+18;function aB({row:e}){return(0,t.jsx)(e8.f,{variant:"secondary",className:"font-normal",children:e.typeLabel})}function a$({targets:e}){let a=(0,s.useRef)(null),[l,r]=(0,s.useState)(0);(0,s.useEffect)(()=>{let e=a.current;if(!e||"u"{let t=e[0]?.contentRect.width;"number"==typeof t&&r(t)});return t.observe(e),()=>t.disconnect()},[]);let{visible:i,overflow:n}=(0,s.useMemo)(()=>((e,t)=>{if(0===e.length)return{visible:[],overflow:0};if(t<=0)return{visible:e.slice(0,1),overflow:e.length-1};let s=[],a=0;for(let[l,r]of e.entries()){let i=e.length-l-1,n=4*(0!==s.length),o=32*(i>0);if(a+n+aU(r)+o>t)break;a+=n+aU(r),s.push(r)}return 0===s.length?{visible:e.slice(0,1),overflow:e.length-1}:{visible:s,overflow:e.length-s.length}})(e,l),[e,l]);return 0===e.length?(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"}):(0,t.jsxs)("div",{ref:a,className:"flex w-full min-w-0 flex-nowrap items-center gap-1 overflow-hidden",children:[i.map(e=>(0,t.jsx)(e8.f,{variant:"secondary",className:"max-w-full shrink truncate font-normal",children:e},e)),n>0&&(0,t.jsxs)("span",{className:"shrink-0 text-xs text-muted-foreground",title:e.join(", "),children:["+",n]})]})}function aG({row:e,onDeleteClick:s}){return(0,t.jsxs)(aV.G,{children:[(0,t.jsx)(aV.X,{"aria-label":`Open actions for ${e.name}`,"data-testid":`auto-router-actions-${e.id}`,className:(0,tC.c)((0,g.i)({variant:"ghost",size:"icon-sm"}),"text-muted-foreground"),children:(0,t.jsx)(aK.f,{className:"size-4"})}),(0,t.jsx)(aV.L,{align:"end",className:"w-44",children:(0,t.jsxs)(aV.r,{variant:"destructive","data-testid":"auto-router-action-delete",onClick:()=>s(e),children:[(0,t.jsx)(e7.f,{}),"Delete auto router"]})})]})}let aH=[10,25,50],aW=[{id:"createdAt",desc:!0},{id:"name",desc:!1}];function aJ({canModify:e}){return(0,t.jsxs)("div",{className:"flex flex-col items-center gap-1 py-6",children:[(0,t.jsx)("div",{className:"mb-1 flex size-10 items-center justify-center rounded-lg bg-muted",children:(0,t.jsx)(aF.Y,{size:20,className:"text-muted-foreground"})}),(0,t.jsx)("div",{className:"text-sm font-medium text-foreground",children:"No auto routers yet"}),(0,t.jsx)("div",{className:"text-sm text-muted-foreground",children:e?"Create an auto router to pick the right model per request instead of pinning one.":"An auto router picks the right model per request instead of pinning one."})]})}function aY({routers:e,isLoading:a,canModify:l,onRouterClick:r,onDeleteClick:i}){let n=(0,s.useMemo)(()=>(({canModify:e,onRouterClick:s,onDeleteClick:a})=>[{id:"name",accessorKey:"name",meta:{title:"Name"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Name"}),size:260,enableSorting:!0,cell:({row:e})=>(0,t.jsx)(aD.f,{title:e.original.name||"-",onClick:()=>s(e.original)})},{id:"kind",accessorKey:"kind",meta:{title:"Type"},header:"Type",size:180,enableSorting:!1,cell:({row:e})=>(0,t.jsx)(aB,{row:e.original})},{id:"targets",meta:{title:"Routes to"},header:"Routes to",size:320,enableSorting:!1,cell:({row:e})=>(0,t.jsx)(a$,{targets:e.original.targets})},{id:"defaultModel",accessorKey:"defaultModel",meta:{title:"Default model"},header:"Default model",size:200,enableSorting:!1,cell:({row:e})=>e.original.defaultModel?(0,t.jsx)(e8.f,{variant:"secondary",className:"max-w-full truncate font-normal",title:e.original.defaultModel,children:e.original.defaultModel}):(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"-"})},{id:"createdAt",accessorKey:"createdAt",meta:{title:"Created"},header:({column:e})=>(0,t.jsx)(s$.v,{column:e,title:"Created"}),size:150,enableSorting:!0,sortingFn:"datetime",sortUndefined:"last",cell:({row:e})=>(0,t.jsx)(sH.S,{value:e.original.createdAt,precision:"date"})},...e?[{id:"actions",meta:{title:""},header:"",size:60,enableSorting:!1,cell:({row:e})=>e.original.canDelete?(0,t.jsx)(aG,{row:e.original,onDeleteClick:a}):null}]:[]])({canModify:l,onRouterClick:r,onDeleteClick:i}),[l,r,i]);return(0,t.jsx)(sR.f,{data:e,columns:n,getRowId:e=>e.id,sortingMode:"client",defaultSorting:aW,paginationMode:"client",pageSizeOptions:aH,isLoading:a,loadingMessage:"Loading auto routers…",noDataMessage:(0,t.jsx)(aJ,{canModify:l}),size:"compact"})}let aX=e=>{let t="string"==typeof e?(e=>{try{return JSON.parse(e)}catch{return null}})(e):e;return"object"!=typeof t||null===t||Array.isArray(t)?{}:t},aQ=e=>Array.from(new Set(e)),aZ={llm:"LLM Classifier",jev:"OSS Classifier",oss_classifier:"OSS Classifier",capability:"Capability",llm_v2:"Fuse v2",heuristic_first:"Heuristic first",hybrid:"Hybrid",custom:"Custom classifier"},a0=(e,t)=>{let s;return{typeLabel:e,targets:Array.isArray(s=t.available_models)?s.filter(e=>"string"==typeof e):[]}},a1={complexity:e=>({typeLabel:"string"==typeof e.classifier_type&&aZ[e.classifier_type]||"Heuristic",targets:aQ(Object.values(aX(e.tiers)).flatMap(ek.I))}),semantic:e=>({typeLabel:"Semantic",targets:aQ((Array.isArray(e.routes)?e.routes:[]).map(e=>aX(e).name).filter(e=>"string"==typeof e&&e.length>0))}),adaptive:e=>a0("Adaptive",e),quality:e=>a0("Quality",e)};function a2({accessToken:e,userRole:a,userID:l,isViewOnly:r,teams:i,createScope:n}){let o="forbidden"!==n,{data:d,isLoading:c}=(0,y.v)(),m=(0,y.g)(),{openModel:h}=sb(),[p,f]=(0,s.useState)(!1),[x,_]=(0,s.useState)(null),[j,v]=(0,s.useState)(!1),b=(0,s.useMemo)(()=>{let e,t;return e=d??[],t={userRole:a,userID:l,isViewOnly:r},e.map((e,s)=>((e,t,s,a)=>{let l,r,i=e.litellm_params??{},n=e.model_info??{},o=e.model_name??"",d=eM(i),{canEdit:c,canDelete:m,editBlockedReason:h}=(l=n?.db_model!==!0,r=eM(i).hasEditor,{isConfigManaged:l,canEdit:!l&&r,canDelete:!l,editBlockedReason:l?"config-managed":r?null:"no-editor"}),p={teamId:n.team_id,isDbModel:!0===n.db_model,createdBy:n.created_by,model:i.model},f=(0,u.d)(s,a,p),x=(0,u.F)(s,a,p);return{id:n.id??`${o}-${t}`,name:o,kind:d.kind,canEdit:c&&x,canDelete:m&&f,editBlockedReason:h,createdAt:n.created_at??void 0,defaultModel:i[d.defaultModelKey]??null,deployment:e,...a1[d.kind](aX(i[d.configKey]))}})(e,s,t,i))},[d,a,l,r,i]),N=async()=>{if(x){v(!0);try{await (0,em.o2)(e,x.id),eH.f.success(`Deleted auto router: ${x.name}`),_(null),await m()}catch(e){eH.f.fromError(`Failed to delete auto router: ${e}`)}finally{v(!1)}}};return(0,t.jsxs)("div",{className:"w-full space-y-4",children:[(0,t.jsxs)("div",{className:"flex items-start justify-between gap-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h2",{className:"text-base font-semibold text-foreground",children:"Auto routers"}),(0,t.jsx)("p",{className:"mt-1 text-sm text-muted-foreground",children:"Auto routers sit above your deployments and pick a model per request. They are called like any other model, so clients keep using a single model name."})]}),o&&(0,t.jsxs)(g.K,{onClick:()=>f(!0),className:"shrink-0",children:[(0,t.jsx)(e3.f,{}),"Add Auto Router"]})]}),(0,t.jsx)(aY,{routers:b,isLoading:c,canModify:o,onRouterClick:e=>h(e.id),onDeleteClick:_}),(0,t.jsx)(eh.N,{open:p,onOpenChange:f,children:(0,t.jsxs)(eh.d,{overlayClassName:"bg-black/40 backdrop-blur-sm",className:"max-h-[90vh] overflow-y-auto sm:max-w-4xl",children:[(0,t.jsxs)(eh.s,{children:[(0,t.jsx)(eh.F,{children:"Add Auto Router"}),(0,t.jsx)(eh.C,{children:"Choose models for your auto router."})]}),(0,t.jsx)(aq,{handleOk:()=>{f(!1),m()},accessToken:e,userRole:a,userId:l,createScope:n,teams:i})]})}),x&&(0,t.jsx)(eA.f,{isOpen:!0,title:"Delete Auto Router",message:`Are you sure you want to delete "${x.name}"? Any client still calling this model name will start failing.`,resourceInformationTitle:"Auto router",resourceInformation:[{label:"Name",value:x.name},{label:"Type",value:x.typeLabel},{label:"ID",value:x.id}],onCancel:()=>_(null),onOk:N,confirmLoading:j})]})}function a4(){let{accessToken:e,userRole:s,userId:a,isViewOnly:l}=(0,i.f)(),{data:r}=(0,n.n)(),{data:d}=(0,o.f)(),m=null!=s&&c.t.includes(s),h=(0,u.n)({userRole:s,userID:a,isViewOnly:l},{teams:r??null,disabledForInternalUsers:m&&d?.values?.disable_model_add_for_internal_users===!0});return(0,t.jsx)(a2,{accessToken:e,userRole:s??"",userID:a??null,isViewOnly:l,teams:r??null,createScope:h})}var a5=e.i(803099),a6=e.i(838932),a3=e.i(109034),a7=e.i(630468),a8=e.i(181349),a9=e.i(916925);let le=[],lt="github_copilot_auth_type",ls="per_user_oauth",la={GITHUB_COPILOT:[{id:"shared_device_login",label:"Shared device login",description:"One GitHub device login on the proxy host, stored in its token file, is used for every caller of models on this credential.",fieldKeys:["api_base","api_key"],requiredFieldKeys:[]},{id:ls,label:"Per-user GitHub OAuth",credentialOnly:!0,description:"Each LiteLLM user connects their own GitHub account from LLM Credentials, and their requests use their own GitHub Copilot access. Users who have not connected get a 401.",fieldKeys:[lt,"github_copilot_host"],requiredFieldKeys:[lt],fixedValues:{[lt]:ls}}],MICROSOFT_365_COPILOT:[{id:"oauth_token_exchange",label:"OAuth token exchange (on-behalf-of)",credentialOnly:!0,description:"LiteLLM exchanges each caller's IdP-issued JWT at your IdP's token endpoint for a delegated token. Microsoft Graph only accepts Microsoft Entra tokens, so for Microsoft 365 Copilot the token endpoint must be Entra and callers must send an Entra-issued JWT for this app. Users can still sign in through any IdP federated with Entra.",fieldKeys:["token_exchange_endpoint","token_exchange_profile","client_id","client_secret","token_exchange_scope","token_exchange_audience"],requiredFieldKeys:["token_exchange_endpoint","client_id","client_secret"]},{id:"static_token",label:"Static delegated access token",description:"Sends one pre-acquired delegated Microsoft Graph token for every caller.",fieldKeys:["api_key"],requiredFieldKeys:["api_key"]}]},ll=e=>{let t=Object.keys(a9.g),s=null===e?void 0:t.find(t=>t===e||a9.g[t]===e);return void 0===s?le:la[s]??le};var lr=e.i(569074);let li=e=>{let t="password"===e.field_type?"password":"select"===e.field_type?"select":"upload"===e.field_type?"upload":"textarea"===e.field_type?"textarea":"text";return{key:e.key,label:e.label,placeholder:e.placeholder??void 0,tooltip:e.tooltip??void 0,required:e.required??!1,type:t,options:e.options??void 0,defaultValue:e.default_value??void 0}},ln={},lo=({selectedProvider:e,hiddenFieldKeys:a,context:l="credential",onCreateCredential:r,initialAuthTypeId:i,onAuthTypeChange:n,fieldValidators:o})=>{let d=a9.g[e],c=(0,tD.M)(),u=ll(e),m=s.default.useMemo(()=>u.filter(({credentialOnly:e})=>"model"!==l||void 0!==r||!e),[u,l,r]),[h,p]=s.default.useState(()=>{let e;return i&&m.some(({id:e})=>e===i)?i:(e=c.getValues(),m.find(({requiredFieldKeys:t})=>t.some(t=>void 0!==e[t]&&null!==e[t]&&""!==e[t]))?.id??m[0]?.id??"")}),f=m.find(({id:e})=>e===h)??m[0],x="model"===l&&f?.credentialOnly===!0,_=s.default.useId(),j=s.default.useRef(null);s.default.useEffect(()=>{f&&n?.(f.id)},[n,f]);let{data:v,isLoading:b,error:y}=(0,a5.f)(),N=s.default.useMemo(()=>{if(!v)return null;let e={};return v.forEach(t=>{let s=t.provider_display_name,a=t.credential_fields.map(li);e[s]=a,t.provider&&(e[t.provider]=a),t.litellm_provider&&(e[t.litellm_provider]=a)}),e},[v]);s.default.useEffect(()=>{N&&Object.assign(ln,N)},[N]);let k=s.default.useMemo(()=>{if(null===e)return[];let t=ln[d]??ln[e];if(t)return t;if(!v)return[];let s=v.find(t=>t.provider_display_name===d||t.provider===e||t.litellm_provider===e);if(!s)return[];let a=s.credential_fields.map(li);return ln[s.provider_display_name]=a,s.provider&&(ln[s.provider]=a),s.litellm_provider&&(ln[s.litellm_provider]=a),a},[d,e,v]),w=s.default.useMemo(()=>{var e;let t;return e=f?.id??"",t=u.find(({id:t})=>t===e)?.fieldKeys??[],u.filter(({id:t})=>t!==e).flatMap(({fieldKeys:e})=>e).filter((e,s,a)=>!t.includes(e)&&a.indexOf(e)===s)},[u,f?.id]),C=s.default.useMemo(()=>{if(x)return[];if(0===m.length)return a?k.filter(e=>!a.includes(e.key)):k;let e=[...a??[],...w];return k.filter(t=>!e.includes(t.key)).map(e=>f?.requiredFieldKeys.includes(e.key)?{...e,required:!0}:e)},[k,a,m,w,f,x]),S=s.default.useMemo(()=>C.some(e=>"api_version"===e.key),[C]),M=s.default.useRef(null),E=s.default.useCallback(e=>{if(!S)return;let t=(e=>{let t=e.indexOf("?");if(-1===t)return null;let s=new URLSearchParams(e.slice(t+1).split("#")[0]);return s.get("api_version")||s.get("api-version")})(e.target.value);if(t){M.current=t,c.setValue("api_version",t);return}c.getValues("api_version")===M.current&&c.setValue("api_version",""),M.current=null},[c,S]);return(0,t.jsxs)(t.Fragment,{children:[m.length>0&&f&&(0,t.jsxs)("div",{className:"mb-4 flex flex-col gap-2",children:[(0,t.jsx)("label",{htmlFor:_,className:"text-sm font-medium",children:(0,eW.q)("Auth Type:","Select how LiteLLM authenticates to this provider.")}),(0,t.jsxs)(tJ.d,{items:m.map(({id:e,label:t})=>({value:e,label:t})),value:f.id,onValueChange:e=>p(e??""),children:[(0,t.jsx)(tJ.P,{id:_,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:m.map(e=>(0,t.jsx)(tJ.T,{value:e.id,children:e.label},e.id))})]}),(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:f.description})]}),x?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"mb-4 text-sm",children:"This auth type is saved as an LLM credential and attached to this model."}),(0,t.jsx)(g.K,{type:"button",onClick:()=>r?.(f.id),children:"Create credential"})]}):Object.entries(f?.fixedValues??{}).map(([s,a])=>(0,t.jsx)(a8.I,{name:s,defaultValue:a,bare:!0,children:()=>null},`${e}:${s}`)),b&&0===C.length&&(0,t.jsx)("p",{className:"text-sm mb-2",children:"Loading provider fields..."}),y&&0===C.length&&(0,t.jsx)("p",{className:"text-sm mb-2 text-destructive",children:y instanceof Error?y.message:"Failed to load provider credential fields"}),C.map(a=>(0,t.jsxs)(s.default.Fragment,{children:[(0,t.jsx)(a8.I,{label:a.tooltip?(0,eW.q)(a.label,a.tooltip):a.label,name:a.key,required:a.required,rules:{validate:{...a.required?{required:(0,a7.B)("Required")}:{},...o?.[a.key]?{provider:o[a.key]}:{}}},className:"vertex_credentials"===a.key?"mb-0":"mb-4",children:e=>((e,s)=>{if("select"===e.type)return(0,t.jsxs)(tJ.d,{items:(e.options??[]).map(e=>({value:e,label:e})),value:s.value??e.defaultValue??null,onValueChange:s.onChange,children:[(0,t.jsx)(tJ.P,{id:s.id,onBlur:s.onBlur,className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:e.placeholder})}),(0,t.jsx)(tJ.r,{children:e.options?.map(e=>(0,t.jsx)(tJ.T,{value:e,children:e},e))})]});if("upload"===e.type){let e;return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(g.K,{type:"button",variant:"outline",className:"w-fit",onClick:()=>j.current?.click(),children:[(0,t.jsx)(lr.f,{}),"Click to Upload"]}),(0,t.jsx)("input",{ref:j,id:s.id,type:"file",accept:".json",className:"sr-only",onBlur:s.onBlur,onChange:(e=s.onChange,t=>{let s,a=t.target.files?.[0];t.target.value="",a?.type==="application/json"&&((s=new FileReader).onload=t=>{t.target&&e(t.target.result)},s.readAsText(a))})})]})}return"textarea"===e.type?(0,t.jsx)(tt.f,{id:s.id,value:s.value??e.defaultValue??"",onChange:s.onChange,onBlur:s.onBlur,placeholder:e.placeholder,rows:6,className:"font-mono text-xs"}):"password"===e.type?(0,t.jsx)(tL.f,{id:s.id,value:s.value??e.defaultValue??"",onChange:s.onChange,onBlur:s.onBlur,placeholder:e.placeholder}):(0,t.jsx)(eX.f,{id:s.id,value:s.value??e.defaultValue??"",onBlur:s.onBlur,placeholder:e.placeholder,type:"text",onChange:t=>{s.onChange(t),"api_base"===e.key&&E(t)}})})(a,e)}),"vertex_credentials"===a.key&&(0,t.jsx)("p",{className:"text-sm mb-3 mt-1",children:"Give a gcp service account(.json file)"}),"base_model"===a.key&&(0,t.jsx)("div",{className:"grid grid-cols-24",children:(0,t.jsxs)("p",{className:"col-start-11 col-span-10 text-sm mb-2",children:["The actual model your azure deployment uses. Used for accurate cost tracking. Select name from"," ",(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/blob/main/litellm/data/model_prices_and_context_window.json",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline-offset-4 hover:underline",children:"here"})]})})]},`${e}:${a.key}`))]})},ld=e=>(0,t.jsx)(lo,{...e},e.selectedProvider??"no-provider"),lc=["credential_name","display_name","custom_llm_provider"],lu=(e,t)=>({credential_name:e.credential_name,...void 0!==e.display_name?{display_name:e.display_name}:{},credential_values:t,credential_info:{custom_llm_provider:e.custom_llm_provider}}),lm=e=>Object.fromEntries(Object.entries(e).filter(([e])=>!lc.includes(e))),lh=e=>"string"==typeof e?""===e.trim():null==e,lp=e=>!lh(e)||"Required",lf="anthropic_identity_source",lx=[{key:"anthropic_federation_rule_id",label:"Federation Rule ID",tooltip:"The fdrl_ id of the federation rule, from Settings > Workload identity in the Claude Console. Leave empty when the proxy sets ANTHROPIC_FEDERATION_RULE_ID in its environment.",placeholder:"fdrl_...",required:!1,control:"text"},{key:"anthropic_organization_id",label:"Organization ID",tooltip:"The Anthropic organization the federation rule belongs to, shown on the rule's detail page. Leave empty when the proxy sets ANTHROPIC_ORGANIZATION_ID in its environment.",required:!1,control:"text"},{key:"anthropic_service_account_id",label:"Service Account ID",tooltip:"The svac_ id the federation rule targets. Anthropic's reference lists it as required.",placeholder:"svac_...",required:!1,control:"text"},{key:"anthropic_federation_workspace_id",label:"Workspace ID",tooltip:"Set this when the federation rule is enabled in more than one workspace: the wrkspc_ id to mint tokens for, or 'default'.",placeholder:"wrkspc_...",required:!1,control:"text"}],l_=[{id:"token_file",label:"Identity token file",fixedValues:{},fields:[{key:"anthropic_identity_token_file",label:"Identity Token File",tooltip:"Absolute path on the proxy host of a file holding the identity token, for example a projected Kubernetes service account token. It must sit under an allowed credential directory.",placeholder:"/var/run/secrets/anthropic/token",required:!0,control:"text"}]},{id:"secret_reference",label:"Identity token secret reference",fixedValues:{},fields:[{key:"anthropic_identity_token",label:"Identity Token Reference",tooltip:"An oidc/ secret reference the proxy resolves on each exchange, such as oidc/env/VAR_NAME, oidc/github/, or oidc/google/. Raw tokens are not accepted.",placeholder:"oidc/env/ANTHROPIC_IDENTITY_TOKEN",required:!0,control:"text"}]},{id:"internal_issuer",label:"Token signed by LiteLLM (internal issuer)",fixedValues:{[lf]:"internal_issuer"},fields:[{key:"anthropic_issuer_url",label:"Issuer URL",tooltip:"The issuer registered on the federation rule. The proxy puts it in the token's iss claim.",placeholder:"https://litellm.example.com",required:!0,control:"text"},{key:"anthropic_issuer_subject",label:"Subject",tooltip:"The sub claim the federation rule matches.",required:!0,control:"text"},{key:"anthropic_issuer_audience",label:"Audience",tooltip:"Optional aud claim, when the federation rule checks one.",required:!1,control:"text"},{key:"anthropic_issuer_ttl_seconds",label:"Token Lifetime (seconds)",tooltip:"Optional. How long each signed token is valid, from 1 to 3600 seconds. The proxy uses its default when this is empty.",required:!1,control:"integer"},{key:"anthropic_issuer_signing_key_ref",label:"Signing Key Reference",tooltip:"A secret reference to the PEM private key the proxy signs with, such as os.environ/VAR_NAME. Enter the reference, never the key itself.",placeholder:"os.environ/ANTHROPIC_ISSUER_SIGNING_KEY",required:!0,control:"text"}]},{id:"keycloak",label:"Keycloak client credentials",fixedValues:{[lf]:"keycloak"},fields:[{key:"anthropic_keycloak_token_url",label:"Keycloak Token URL",tooltip:"The realm's token endpoint the proxy requests an identity token from.",placeholder:"https://keycloak.example.com/realms//protocol/openid-connect/token",required:!0,control:"text"},{key:"anthropic_keycloak_client_id",label:"Keycloak Client ID",tooltip:"The client the proxy authenticates as.",required:!0,control:"text"},{key:"anthropic_keycloak_client_secret_ref",label:"Client Secret Reference",tooltip:"A secret reference to the client secret, such as os.environ/VAR_NAME. Enter the reference, never the secret itself.",placeholder:"os.environ/KEYCLOAK_CLIENT_SECRET",required:!0,control:"text"},{key:"anthropic_keycloak_auth_method",label:"Client Authentication Method",tooltip:"Optional. How the client secret is sent to Keycloak. The proxy uses client_secret_basic when unset.",required:!1,control:"select",options:["client_secret_basic","client_secret_post"]},{key:"anthropic_keycloak_scope",label:"Scope",tooltip:"Optional scope to request with the token.",required:!1,control:"text"}]},{id:"environment",label:"Proxy environment variables",fixedValues:{},fields:[]}],lg="token_file",lj=[lf,...l_.flatMap(e=>e.fields.map(e=>e.key))],lv=[...lx,...l_.flatMap(e=>e.fields)],lb=[...lx.map(e=>e.key),...lj],ly={id:"unrecognized",label:"",fixedValues:{},fields:[]},lN=e=>l_.find(t=>t.id===e)??ly,lk=e=>null!=e&&"anthropic"===e.toLowerCase(),lw=e=>{let t=e??{},s=t[lf];return lh(s)?lh(t.anthropic_identity_token_file)?lh(t.anthropic_identity_token)?"environment":"secret_reference":"token_file":l_.find(e=>e.fixedValues[lf]===s)?.id??"unrecognized"},lC=e=>!!("string"!=typeof e||lh(e)||ea(e))||!(!e.startsWith("oidc/")||e.startsWith("oidc/env_path/"))||"Enter an oidc/ secret reference such as oidc/env/VAR_NAME. Raw tokens and oidc/env_path/ references are not accepted",lS=e=>{if(lh(e))return!0;let t=Number(e);return!!Number.isInteger(t)&&t>=1&&t<=3600||"Enter a whole number of seconds from 1 to 3600"},lM="api.openai.com",lE=[{key:"openai_identity_provider_id",label:"Identity Provider ID",tooltip:"The workload identity provider registered in your OpenAI organization that trusts the token's issuer. Leave empty when the proxy sets OPENAI_IDENTITY_PROVIDER_ID in its environment.",required:!1,control:"text"},{key:"openai_service_account_id",label:"Service Account ID",tooltip:"The OpenAI service account the verified identity acts as. Its project decides what the model can reach. Leave empty when the proxy sets OPENAI_SERVICE_ACCOUNT_ID in its environment.",required:!1,control:"text"},{key:"openai_identity_token_file",label:"Identity Token File",tooltip:"Absolute path on the proxy host of a file holding the identity token, for example a projected Kubernetes service account token. Leave empty when the proxy sets OPENAI_IDENTITY_TOKEN_FILE in its environment.",placeholder:"/var/run/secrets/kubernetes.io/serviceaccount/token",required:!1,control:"text"}],lT="anthropic_federation_identity_source",lA=lx[0].key;function lP({field:e,storedValue:s,validators:a}){return(0,t.jsx)(a8.I,{label:(0,eW.q)(e.label,e.tooltip),name:e.key,required:e.required,rules:{validate:{...e.required?{required:lp}:{},...a,masked:e=>!ea(e)||e===s||"This stored value is hidden. Replace the whole value to change it"}},className:"mb-4",children:s=>((e,s)=>{if("select"===e.control){let a,l=[...ea(a=s.value)?[{value:a,label:`Stored: ${a}`}]:[],...(e.options??[]).map(e=>({value:e,label:e}))];return(0,t.jsxs)(tJ.d,{items:l,value:"string"==typeof s.value&&""!==s.value?s.value:null,onValueChange:e=>s.onChange(e??""),children:[(0,t.jsx)(tJ.P,{id:s.id,onBlur:s.onBlur,className:"w-full",children:(0,t.jsx)(tJ.U,{placeholder:"Proxy default"})}),(0,t.jsxs)(tJ.r,{children:[(0,t.jsx)(tJ.T,{value:null,children:"Proxy default"}),l.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))]})]})}return(0,t.jsx)(eX.f,{id:s.id,value:void 0===s.value||null===s.value?"":String(s.value),onChange:s.onChange,onBlur:s.onBlur,placeholder:e.placeholder,inputMode:"integer"===e.control?"numeric":void 0,"aria-invalid":s["aria-invalid"]})})(e,s)})}function lI({identitySource:e,onIdentitySourceChange:s,storedValues:a}){let l=[..."unrecognized"===lw(a)?[{value:"unrecognized",label:`Stored: ${String(a[lf])}`}]:[],...l_.map(e=>({value:e.id,label:e.label}))],r=s=>(0,t.jsx)(lP,{field:s,storedValue:a[s.key],validators:{...s.key===lA?{stored:(t,s)=>!("environment"===e&&lx.every(e=>lh(s[e.key])))||"Enter at least one of these ids, or pick an identity source that stores a token. The proxy rejects a credential with no values"}:{},..."anthropic_identity_token"===s.key?{reference:lC}:{},..."integer"===s.control?{ttl:lS}:{}}},s.key);return(0,t.jsxs)(t.Fragment,{children:[lx.map(r),(0,t.jsxs)("div",{className:"mb-4 flex flex-col gap-2",children:[(0,t.jsx)("label",{htmlFor:lT,className:"text-sm font-medium",children:(0,eW.q)("Identity Source","Where the proxy gets the identity token it exchanges with Anthropic for an access token.")}),(0,t.jsxs)(tJ.d,{items:l,value:e,onValueChange:e=>s(e),children:[(0,t.jsx)(tJ.P,{id:lT,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:l.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]}),"unrecognized"===e&&(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"This form does not offer the stored identity source. Saving keeps it and its settings as stored. Pick another source to replace it."}),"environment"===e&&(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"The proxy reads ANTHROPIC_IDENTITY_TOKEN_FILE or ANTHROPIC_IDENTITY_TOKEN from its own environment."})]}),lN(e).fields.map(r)]})}function lz({storedValues:e}){return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"mb-4 text-sm text-muted-foreground",children:"The proxy exchanges the identity token for an OpenAI access token only when OPENAI_API_KEY is unset in its environment. Otherwise it sends that key instead."}),lE.map(s=>(0,t.jsx)(lP,{field:s,storedValue:e[s.key]},s.key))]})}function lO({selection:e,onIdentitySourceChange:s,storedValues:a}){switch(e.provider){case"anthropic":return(0,t.jsx)(lI,{identitySource:e.identitySource,onIdentitySourceChange:s,storedValues:a});case"openai":return(0,t.jsx)(lz,{storedValues:a})}}var lL=e.i(922407),lR=e.i(431703);let lq=({credentialName:e})=>{let s=sx.q.useQuery("get","/credentials/{credential_name}/jwks",{params:{path:{credential_name:e}}});if(s.isPending||!s.isFetchedAfterMount)return(0,t.jsx)("p",{className:"text-sm text-muted-foreground",children:"Loading JWKS..."});if(s.isError)return(0,t.jsx)("p",{role:"alert",className:"text-sm text-destructive",children:(0,lR.U)(s.error)});let a=JSON.stringify(s.data,null,2);return(0,t.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,t.jsx)("pre",{"aria-label":"Public JWKS",className:"max-h-48 overflow-auto rounded-md border bg-muted p-3 text-xs",children:a}),(0,t.jsx)(lL.f,{value:a,label:"Copy JWKS",variant:"action",className:"self-start"})]})};function lF({panel:e}){switch(e.kind){case"hidden":return null;case"after_save":return(0,t.jsx)("p",{className:"mb-4 text-sm text-muted-foreground",children:"Once saved, reopen this credential from LLM Credentials to copy the public JWKS you register in the Claude Console."});case"saved":return(0,t.jsxs)(eJ.G,{className:"mb-4 gap-2",children:[(0,t.jsx)(eJ.f,{variant:"label",className:"mb-0",children:"Public JWKS"}),(0,t.jsx)(eJ.H,{children:"Register this JWKS with the Issuer URL and Subject above as a federation rule under Settings > Workload identity in the Claude Console. Then fill in its Federation Rule ID and Organization ID at the top of this form and update the credential. The JWKS comes from the saved signing key, so update after changing the key and before copying."}),(0,t.jsx)(lq,{credentialName:e.credentialName})]})}}let lK="api_key",lD=[...lb,...lE.map(e=>e.key)],lV=new Map([...lv,...lE].map(e=>[e.key,e])),lU={api_base:e=>{let t,s;return!!("string"!=typeof e||lh(e)||(t=URL.canParse(e)?new URL(e):null,t?.protocol==="https:"&&((s=t.hostname)===lM||s.endsWith(`.${lM}`))))||`Workload identity federation only reaches the OpenAI API. Enter https://${lM}/v1 or a regional *.${lM} URL, or leave this empty`}},lB={},l$=e=>lk(e)?"anthropic":e?.toLowerCase()==="openai"?"openai":null,lG=(e,t,s)=>null===e||"api_key"===t?{authMethod:"api_key"}:"anthropic"===e?{authMethod:"federation",provider:e,identitySource:s}:{authMethod:"federation",provider:e},lH=e=>lD.some(t=>!lh(e?.[t])),lW=e=>lh(e?.[lK])&&lH(e)?"federation":"api_key",lJ=e=>"federation"===e.authMethod&&"openai"===e.provider?lU:lB,lY=e=>"federation"===e.authMethod&&"anthropic"===e.provider?e.identitySource:null,lX=e=>{let t=lY(e);return null===t?{}:lN(t).fixedValues},lQ=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>{var s;return[e,(s=lV.get(e),void 0===s||lh(t)?void 0===s?t:"":"integer"===s.control?Number(t):"string"==typeof t?t.trim():t)]}).filter(([,e])=>""!==e&&null!=e)),lZ=(e,t)=>Object.fromEntries(Object.entries(t).filter(([t,s])=>!ea(s)&&s!==e[t])),l0=Object.entries(a9.g).map(([e,s])=>({label:s,value:e,icon:(0,t.jsx)(tT.f,{provider:e,label:s,className:"w-5 h-5"})})),l1="credential_auth_method",l2=["api_key"],l4=[],l5=[{value:"api_key",label:"API key"},{value:"federation",label:"Workload identity federation"}],l6=(e,t)=>(e??"").toLowerCase()===(t??"").toLowerCase();function l3({open:e,onCancel:a,onSubmit:l,mode:r,existingCredential:i=null,initialProvider:n=null,initialAuthMethod:o,initialAuthTypeId:d,providerLocked:c=!1}){let u="edit"===r,[m,h]=(0,s.useState)(i?.credential_info.custom_llm_provider??n??a9.g.OpenAI),p=i?.credential_info.custom_llm_provider??null,f=i?.credential_values??{},x=lW(f),_=lH(f)?lw(f):lg,j=lG(l$(p),x,_),[v,b]=(0,s.useState)(i?x:o??"api_key"),[y,N]=(0,s.useState)(_),k=lG(l$(m),v,y),w=i?{...Object.fromEntries(Object.entries(i.credential_values||{}).map(([e,t])=>[e,t??null])),credential_name:i.credential_name,display_name:i.display_name??"",custom_llm_provider:i.credential_info.custom_llm_provider}:n?{custom_llm_provider:n}:void 0,C=(0,tD.G)({mode:"onChange",defaultValues:w}),S=(0,a8.T)(),M=async()=>{var e;let t,s,a,r,n;if(!await C.trigger(S.mountedNames()))return;let o=(0,a8.$)(S,C.getValues),d={credential_name:String(o.credential_name),custom_llm_provider:String(o.custom_llm_provider),...(e=o.display_name,t="string"==typeof e?e:"",!i?t?{display_name:t}:{}:t===(i.display_name??"")?{}:{display_name:t||null})};if(!u){let e;return void l({...d,credential_values:(e=lm(o),{...lQ(e),...lX(k)})},[])}let c=l6(m,p),h=lm(o),x=c?(s=lZ(f,{...lQ(h),...lX(k)}),a=Object.keys(h).filter(e=>lh(h[e])&&!lh(f[e])),r=[...((e,t)=>{let s,a;if(t.authMethod!==e.authMethod)return"federation"===t.authMethod?[lK]:lD;let l=lY(t);return null===l||l===lY(e)?[]:(a=new Set([...(s=lN(l)).fields.map(e=>e.key),...Object.keys(s.fixedValues)]),lj.filter(e=>!a.has(e)))})(j,k),...a].filter(e=>e in f&&!(e in s)),{credential_values:s,credential_values_to_delete:Array.from(new Set(r))}):{credential_values:lZ(f,n={...lQ(h),...lX(k)}),credential_values_to_delete:Object.keys(f).filter(e=>!(e in n))},_=c?ll(m).flatMap(({fieldKeys:e})=>e).filter((e,t,s)=>s.indexOf(e)===t).filter(e=>e in f&&!(e in h)):[],g=Array.from(new Set([...x.credential_values_to_delete,..._]));l({...d,credential_values:x.credential_values},g)},E=()=>{a(),C.reset()};return(0,t.jsx)(eh.N,{open:e,onOpenChange:e=>!e&&E(),children:(0,t.jsxs)(eh.d,{className:"max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-[600px]",children:[(0,t.jsx)(eh.s,{children:(0,t.jsx)(eh.F,{children:u?"Edit Credential":"Add New Credential"})}),(0,t.jsx)(tD.p,{...C,children:(0,t.jsx)(a8.R,{value:{control:C.control,registry:S},children:(0,t.jsxs)("form",{onSubmit:e=>{e.preventDefault(),M()},children:[(0,t.jsx)(a8.I,{label:"Credential Name:",name:"credential_name",required:!0,rules:{validate:{required:(0,a7.B)("Credential name is required")}},className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:"string"==typeof e.value?e.value:"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Unique name that models reference this credential by",disabled:u})}),(0,t.jsx)(a8.I,{label:"Display Name:",name:"display_name",className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:"string"==typeof e.value?e.value:"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"e.g. Production OpenAI"})}),(0,t.jsx)(a8.I,{label:(0,eW.q)("Provider:","Helper to auto-populate provider specific fields"),name:"custom_llm_provider",required:!0,rules:{validate:{required:(0,a7.B)("Required")}},className:"mb-4",children:e=>(0,t.jsx)(eI.f,{inputId:e.id,placeholder:"Select a provider",options:l0,value:"string"==typeof e.value?e.value:null,disabled:c,onValueChange:t=>{var s;let a,l,r;e.onChange(t),b((a=u&&l6(t,p))?x:"api_key"),N(a?_:lg),s={getFieldValue:e=>C.getValues(e),resetFields:()=>C.reset(u&&!l6(t,p)?{}:w),setFieldValue:(e,t)=>C.setValue(e,t)},l=s.getFieldValue("credential_name"),r=s.getFieldValue("display_name"),s.resetFields(),void 0!==l&&s.setFieldValue("credential_name",l),void 0!==r&&s.setFieldValue("display_name",r),h(t),s.setFieldValue("custom_llm_provider",t)}})}),null!==l$(m)&&(0,t.jsxs)("div",{className:"mb-4 flex flex-col gap-2",children:[(0,t.jsx)("label",{htmlFor:l1,className:"text-sm font-medium",children:(0,eW.q)("Authentication:","Workload identity federation exchanges an identity token for a short-lived access token from the provider, so no API key is stored.")}),(0,t.jsxs)(tJ.d,{items:l5,value:v,onValueChange:e=>{C.clearErrors(Object.keys(lJ(k))),b(e)},children:[(0,t.jsx)(tJ.P,{id:l1,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:l5.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})]}),(0,t.jsx)(ld,{selectedProvider:m,hiddenFieldKeys:"federation"===k.authMethod?l2:l4,initialAuthTypeId:d,fieldValidators:lJ(k)}),"federation"===k.authMethod&&(0,t.jsx)(lO,{selection:k,onIdentitySourceChange:N,storedValues:f}),(0,t.jsx)(lF,{panel:"internal_issuer"!==lY(k)?{kind:"hidden"}:null!==i&&lk(i.credential_info.custom_llm_provider)&&"internal_issuer"===lw(i.credential_values)?{kind:"saved",credentialName:i.credential_name}:{kind:"after_save"}}),(0,t.jsxs)("div",{className:"flex justify-between items-center",children:[(0,t.jsx)(A.x,{content:"Get help on our github",children:(0,t.jsx)("a",{href:"https://github.com/BerriAI/litellm/issues",className:"text-sm text-primary hover:underline",children:"Need Help?"})}),(0,t.jsxs)("div",{children:[(0,t.jsx)(g.K,{variant:"outline",className:"mr-2.5",onClick:E,children:"Cancel"}),(0,t.jsx)(g.K,{type:"submit",children:u?"Update Credential":"Add Credential"})]})]})]})})})]})})}var l7=e.i(845150);let l8=[R,q,"input_cost_per_token","output_cost_per_token","cache_read_input_token_cost","cache_creation_input_token_cost","cache_creation_input_token_cost_above_1hr","input_cost_per_second"],l9=[{value:"per_token",label:"Per Million Tokens"},{value:"per_second",label:"Per Second"}],re=(e,t)=>t&&(isNaN(Number(t))||0>Number(t))?Promise.reject("Please enter a valid positive number"):Promise.resolve(),rt={deps:[L],validate:(0,a7.W)({validator:re},({getFieldValue:e,isFieldTouched:t})=>({validator:(t,s)=>K(e(L))&&K(s)&&0!==Number(s)?Promise.reject(Error("A PTU deployment bills by reserved capacity, so this cost must be 0 or blank")):Promise.resolve()}))},rs=({showAdvancedSettings:e,setShowAdvancedSettings:a,teams:l,guardrailsList:r,tagsList:i,accessToken:n})=>{let[o,d]=s.default.useState(!1),[c,u]=s.default.useState("per_token"),[m,h]=s.default.useState(!1),p=X();return(0,t.jsx)(t.Fragment,{children:(0,t.jsxs)(e9.Y,{className:"mt-2 mb-4 overflow-hidden rounded-lg border",children:[(0,t.jsxs)(e9.v,{className:"group/section flex w-full items-center justify-between px-4 py-3 text-left",children:[(0,t.jsx)("b",{children:"Advanced Settings"}),(0,t.jsx)(e5.f,{className:"size-5 shrink-0 text-muted-foreground transition-transform group-data-[panel-open]/section:rotate-180"})]}),(0,t.jsx)(e9.C,{className:"px-4 pb-3",children:(0,t.jsxs)("div",{className:"rounded-lg",children:[(0,t.jsx)(a8.I,{name:"custom_pricing",label:"Custom Pricing",className:"mb-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:t=>{e.onChange(t),d(t)}})}),(0,t.jsx)(a8.I,{name:"vector_store_ids",label:(0,t.jsxs)("span",{children:["Attached Knowledge Bases (RAG)"," ",(0,t.jsx)(A.x,{content:"Vector stores to use for RAG. Every request to this model will automatically retrieve context from these knowledge bases.",children:(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/completion/knowledgebase",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,t.jsx)(et.f,{className:"ml-1 inline size-3.5 align-text-bottom"})})})]}),className:"mt-4",help:"Select vector stores to attach. Requests to this model will automatically use these for RAG. Set up vector stores in Tools > Vector Stores.",children:e=>(0,t.jsx)(t7.f,{onChange:e.onChange,value:e.value,accessToken:n,placeholder:"Select knowledge bases (optional)"})}),(0,t.jsx)(a8.I,{name:"guardrails",label:(0,t.jsxs)("span",{children:["Guardrails"," ",(0,t.jsx)(A.x,{content:"Apply safety guardrails to this key to filter content or enforce policies",children:(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/guardrails/quick_start",target:"_blank",rel:"noopener noreferrer",onClick:e=>e.stopPropagation(),children:(0,t.jsx)(et.f,{className:"ml-1 inline size-3.5 align-text-bottom"})})})]}),className:"mt-4",help:"Select existing guardrails. Go to 'Guardrails' tab to create new guardrails.",children:e=>(0,t.jsx)(l7.f,{id:e.id,placeholder:"Select or enter guardrails",emptyText:"Type to add a guardrail",value:e.value??[],onValueChange:e.onChange,options:r.map(e=>({value:e,label:e})),allowCustomValues:!0})}),(0,t.jsx)(a8.I,{name:"tags",label:"Tags",className:"mb-4",children:e=>(0,t.jsx)(l7.f,{id:e.id,placeholder:"Select or enter tags",emptyText:"Type to add a tag",value:e.value??[],onValueChange:e.onChange,options:Object.values(i).map(e=>({value:e.name,label:e.name,description:e.description||void 0})),allowCustomValues:!0})}),p&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a8.I,{name:L,label:(0,eW.q)("PTU Count","Provisioned throughput units for this deployment. Set together with Cost per PTU / Hour and a Team to attribute a flat daily cost."),rules:{deps:l8,validate:(0,a7.W)({validator:re},...V,$(R))},className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"e.g. 15"})}),(0,t.jsx)(a8.I,{name:R,label:(0,eW.q)("Calculated Cost per PTU / Hour (USD)","Flat cost = PTU count * this rate * active hours, attributed to the deployment's team."),rules:{deps:[L],validate:(0,a7.W)({validator:re},...B,$(L))},className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"e.g. 2.00"})}),(0,t.jsx)(a8.I,{name:q,label:(0,eW.q)("PTU Effective From (UTC)","Start of the PTU window, required when PTU Count is set. Flat cost accrues by the hour within the window; a window opening at 23:00 charges one hour that day."),rules:{deps:[F],validate:(0,a7.W)(({getFieldValue:e})=>({validator:(t,s)=>K(s)||!K(e(L))?Promise.resolve():Promise.reject(Error("PTU Effective From is required when PTU Count is set"))}),W(F,"start"))},className:"mb-4",children:e=>(0,t.jsx)(tW.f,{id:e.id,value:e.value,onChange:e.onChange,onBlur:e.onBlur})}),(0,t.jsx)(a8.I,{name:F,label:(0,eW.q)("PTU Effective To (UTC)","Optional end of the PTU window (exclusive). Leave blank for open-ended."),rules:{deps:[q],validate:(0,a7.W)(W(q,"end"))},className:"mb-4",children:e=>(0,t.jsx)(tW.f,{id:e.id,value:e.value,onChange:e.onChange,onBlur:e.onBlur})})]}),o&&(0,t.jsxs)("div",{className:"ml-6 pl-4 border-l-2 border-border",children:[(0,t.jsx)(a8.I,{name:"pricing_model",label:"Pricing Model",className:"mb-4",children:e=>{let s;return(0,t.jsxs)(tJ.d,{items:l9,value:e.value??"per_token",onValueChange:(s=e.onChange,e=>{null!==e&&(s(e),u(e))}),children:[(0,t.jsx)(tJ.P,{id:e.id,onBlur:e.onBlur,className:"w-full",children:(0,t.jsx)(tJ.U,{})}),(0,t.jsx)(tJ.r,{children:l9.map(e=>(0,t.jsx)(tJ.T,{value:e.value,children:e.label},e.value))})]})}}),"per_token"===c?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a8.I,{name:"input_cost_per_token",label:"Input Cost (per 1M tokens)",rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur})}),(0,t.jsx)(a8.I,{name:"output_cost_per_token",label:"Output Cost (per 1M tokens)",rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur})}),(0,t.jsx)(a8.I,{name:"cache_read_input_token_cost",label:(0,eW.q)("Cache Read Cost (per 1M tokens)","If left blank, defaults to Input Cost."),rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Defaults to Input Cost if blank"})}),(0,t.jsx)(a8.I,{name:"cache_creation_input_token_cost",label:(0,eW.q)("Cache Write Cost (per 1M tokens)","If left blank, defaults to Input Cost (the backend falls back to input_cost_per_token when no cache-write rate is set)."),rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Defaults to Input Cost if blank"})}),(0,t.jsx)(a8.I,{name:"cache_creation_input_token_cost_above_1hr",label:(0,eW.q)("Cache Write Cost (1 hour, per 1M tokens)","Rate for prompt cache writes with a 1 hour TTL (Anthropic's cache_control ttl 1h). If left blank, known models use their cost map 1 hour rate, otherwise Cache Write Cost."),rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,placeholder:"Defaults to the cost map 1 hour rate, else Cache Write Cost"})})]}):(0,t.jsx)(a8.I,{name:"input_cost_per_second",label:"Cost Per Second",rules:rt,className:"mb-4",children:e=>(0,t.jsx)(eX.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur})})]}),(0,t.jsx)(a8.I,{name:"use_in_pass_through",label:(0,eW.q)("Use in pass through routes",(0,t.jsxs)("span",{children:["Allow using these credentials in pass through routes."," ",(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/pass_through/vertex_ai",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline-offset-4 hover:underline",children:"Learn more"})]})),className:"mb-4 mt-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:e.onChange})}),(0,t.jsx)(a8.I,{name:"kubernetes_pod_discovery",label:(0,eW.q)("Kubernetes pod discovery","Treat the API Base hostname as a Kubernetes headless service: resolve it to its ready pod IPs and spread requests across the pods. LiteLLM must run inside the same cluster."),className:"mb-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:e.onChange})}),(0,t.jsx)(a8.I,{name:"cache_control",label:(0,eW.q)(tZ,t0),className:"mb-4",children:e=>(0,t.jsx)(tY.f,{id:e.id,checked:!0===e.value,onCheckedChange:t=>{e.onChange(t),h(t)}})}),m&&(0,t.jsx)(a8.I,{name:"cache_control_injection_points",defaultValue:[t1],bare:!0,children:e=>(0,t.jsx)(t6,{value:e.value,onChange:e.onChange})}),(0,t.jsx)(a8.I,{name:"litellm_extra_params",label:(0,eW.q)("LiteLLM Params","Optional litellm params used for making a litellm.completion() call."),className:"mb-4 mt-4",rules:{validate:(0,a7.W)({validator:eo.C})},children:e=>(0,t.jsx)(tt.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,rows:4,placeholder:'{\n "rpm": 100,\n "timeout": 0,\n "stream_timeout": 0\n }'})}),(0,t.jsx)("div",{className:"grid grid-cols-24 mb-4",children:(0,t.jsxs)("p",{className:"col-start-11 col-span-10 text-muted-foreground text-sm",children:["Pass JSON of litellm supported params"," ",(0,t.jsx)("a",{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline-offset-4 hover:underline",children:"litellm.completion() call"})]})}),(0,t.jsx)(a8.I,{name:"model_info_params",label:(0,eW.q)("Model Info","Optional model info params. Returned when calling `/model/info` endpoint."),className:"mb-0",rules:{validate:(0,a7.W)({validator:eo.C})},children:e=>(0,t.jsx)(tt.f,{id:e.id,value:e.value??"",onChange:e.onChange,onBlur:e.onBlur,rows:4,placeholder:'{\n "mode": "chat"\n }'})})]})})]})})},ra={validator:async(e,t)=>{if(!t||0===t.length)throw Error("At least one model mapping is required");if(t.filter(e=>!e.public_name||""===e.public_name.trim()).length>0)throw Error("All model mappings must have valid public names")}},rl="rounded-sm bg-background/20 px-1 py-0.5 font-mono text-xs",rr=JSON.stringify({extra_headers:{"anthropic-beta":"context-1m-2025-08-07"}},null,2),ri=(0,t.jsxs)("div",{className:"flex flex-col gap-2 text-left font-normal",children:[(0,t.jsx)("div",{children:"The name you specify in your API calls to LiteLLM Proxy"}),(0,t.jsxs)("div",{children:[(0,t.jsx)("strong",{children:"Example:"})," If you name your public model ",(0,t.jsx)("code",{className:rl,children:"example-name"}),", and choose ",(0,t.jsx)("code",{className:rl,children:"openai/qwen-plus-latest"})," as the LiteLLM model"]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("strong",{children:"Usage:"})," You make an API call to the LiteLLM proxy with"," ",(0,t.jsx)("code",{className:rl,children:'model = "example-name"'})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("strong",{children:"Result:"})," LiteLLM sends ",(0,t.jsx)("code",{className:rl,children:"qwen-plus-latest"})," to the provider"]})]}),rn=({index:e,value:s})=>{let a=(0,tD.M)(),l=(0,tD.h)({control:a.control,name:"custom_llm_provider"});return(0,t.jsx)(eX.f,{value:s,onChange:t=>{let s=t.target.value,r=a.getValues("litellm_extra_params"),i=l===a9.g.Anthropic&&s.endsWith("-1m")&&""===(r??"").trim();i&&a.setValue("litellm_extra_params",rr);let n=i?s.slice(0,-3):s,o=a.getValues("model_mappings")??[];a.setValue("model_mappings",o.map((t,s)=>s===e?{...t,public_name:n}:t))}})},ro=[{id:"public_name",accessorKey:"public_name",header:()=>(0,t.jsxs)("span",{className:"flex items-center",children:["Public Model Name",(0,t.jsx)(A.x,{content:ri,width:"500px"})]}),cell:({row:e})=>(0,t.jsx)(rn,{index:e.index,value:e.original.public_name})},{id:"litellm_model",accessorKey:"litellm_model",header:()=>(0,t.jsxs)("span",{className:"flex items-center",children:["LiteLLM Model Name",(0,t.jsx)(A.x,{content:(0,t.jsx)("div",{children:"The model name LiteLLM will send to the LLM API"}),width:"360px"})]})}],rd=()=>{let e=(0,tD.M)(),a=(0,tD.h)({control:e.control,name:"model"})||[],l=JSON.stringify(Array.isArray(a)?a:[a]),r=(0,s.useMemo)(()=>JSON.parse(l),[l]),i=(0,tD.h)({control:e.control,name:"custom_model_name"}),n=!r.includes("all-wildcard"),o=(0,tD.h)({control:e.control,name:"custom_llm_provider"});return((0,s.useEffect)(()=>{if(i&&r.includes("custom")){let t=e.getValues("model_mappings")||[],s=t.map(e=>"custom"===e.public_name||"custom"===e.litellm_model?o===a9.g.Azure?{public_name:i,litellm_model:`azure/${i}`}:{public_name:i,litellm_model:i}:e);t.length===s.length&&t.every((e,t)=>e.public_name===s[t].public_name&&e.litellm_model===s[t].litellm_model)||e.setValue("model_mappings",s)}},[i,r,o,e]),(0,s.useEffect)(()=>{if(r.length>0&&!r.includes("all-wildcard")){let t=e.getValues("model_mappings")||[];if(t.length!==r.length||!r.every(e=>t.some(t=>"custom"===e?"custom"===t.litellm_model||t.litellm_model===i:o===a9.g.Azure?t.litellm_model===`azure/${e}`:t.litellm_model===e))){let t=r.map(e=>"custom"===e&&i?o===a9.g.Azure?{public_name:i,litellm_model:`azure/${i}`}:{public_name:i,litellm_model:i}:o===a9.g.Azure?{public_name:e,litellm_model:`azure/${e}`}:{public_name:e,litellm_model:e});e.setValue("model_mappings",t)}}},[r,i,o,e]),n)?(0,t.jsx)(a8.I,{name:"model_mappings",label:(0,t.jsxs)("span",{className:"flex items-center",children:["Model Mappings",(0,t.jsx)(A.x,{content:"Map public model names to LiteLLM model names for load balancing"})]}),required:!0,rules:{validate:(0,a7.W)(ra)},className:"mb-4",children:e=>(0,t.jsx)(sR.f,{data:e.value??[],columns:ro,getRowId:e=>e.litellm_model,size:"compact"})}):null},rc=({selectedProvider:e,providerModels:s,getPlaceholder:a})=>{let l=(0,tD.M)(),r=(0,tD.h)({control:l.control,name:"model"}),i=Array.isArray(r)?r:[r];return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a8.I,{name:"model",label:(0,eW.q)("LiteLLM Model Name(s)","The model name LiteLLM will send to the LLM API"),required:!0,rules:{validate:{required:(0,a7.B)(`Please enter ${e===a9.g.Azure?"a deployment name":"at least one model"}.`)}},className:"mb-0",children:r=>e===a9.g.Azure||e===a9.g.OpenAI_Compatible||e===a9.g.Ollama?(0,t.jsx)(eX.f,{id:r.id,value:r.value??"",onBlur:r.onBlur,placeholder:null===e?"Select a provider first":a(e),onChange:t=>{let s,a;r.onChange(t),e===a9.g.Azure&&(a=(s=t.target.value)?[{public_name:s,litellm_model:`azure/${s}`}]:[],l.setValue("model",s),l.setValue("model_mappings",a))}}):s.length>0&&("string"!=typeof r.value||""===r.value)?(0,t.jsx)(l7.f,{id:r.id,placeholder:"Select models",emptyText:"No models found",value:Array.isArray(r.value)?r.value:[],onValueChange:t=>{r.onChange(t);let s=Array.isArray(t)?t:[t];if(s.includes("all-wildcard"))l.setValue("model_name",void 0),l.setValue("model_mappings",[]);else if(JSON.stringify(l.getValues("model"))!==JSON.stringify(s)){let t=s.map(t=>e===a9.g.Azure?{public_name:t,litellm_model:`azure/${t}`}:{public_name:t,litellm_model:t});l.setValue("model",s),l.setValue("model_mappings",t)}},options:[{label:"Custom Model Name (Enter below)",value:"custom"},{label:`All ${e??"provider"} Models (Wildcard)`,value:"all-wildcard"},...s.map(e=>({label:e,value:e}))],className:"w-full"}):(0,t.jsx)(eX.f,{id:r.id,value:r.value??"",onChange:r.onChange,onBlur:r.onBlur,placeholder:null===e?"Select a provider first":a(e)})}),i.includes("custom")&&(0,t.jsx)(a8.I,{name:"custom_model_name",required:!0,rules:{validate:{required:(0,a7.B)("Please enter a custom model name.")}},className:"mt-2",children:s=>(0,t.jsx)(eX.f,{id:s.id,value:s.value??"",onBlur:s.onBlur,placeholder:e===a9.g.Azure?"Enter Azure deployment name":"Enter custom model name",onChange:t=>{let a,r;s.onChange(t),a=t.target.value,r=(l.getValues("model_mappings")||[]).map(t=>"custom"===t.public_name||"custom"===t.litellm_model?e===a9.g.Azure?{public_name:a,litellm_model:`azure/${a}`}:{public_name:a,litellm_model:a}:t),l.setValue("model_mappings",r)}})}),(0,t.jsx)("div",{className:"grid grid-cols-24",children:(0,t.jsx)("p",{className:"col-start-11 col-span-14 text-sm mb-3 mt-1",children:e===a9.g.Azure?"Your deployment name will be saved as the public model name, and LiteLLM will use 'azure/deployment-name' internally":"The model name LiteLLM will send to the LLM API"})})]})};var ru=e.i(878894),rm=e.i(778917);let rh=async(e,t,s)=>{try{let t=e.model_mappings||[];if("model_mappings"in e&&delete e.model_mappings,e.model&&e.model.includes("all-wildcard")){let s=e.custom_llm_provider,a=(0,a9.C)(s)+"/*";e.model_name=a,t.push({public_name:a,litellm_model:a}),e.model=a}void 0!==e.input_cost_per_token&&null!==e.input_cost_per_token&&""!==e.input_cost_per_token&&(e.input_cost_per_token=Number(e.input_cost_per_token)/1e6),void 0!==e.output_cost_per_token&&null!==e.output_cost_per_token&&""!==e.output_cost_per_token&&(e.output_cost_per_token=Number(e.output_cost_per_token)/1e6),void 0!==e.cache_read_input_token_cost&&null!==e.cache_read_input_token_cost&&""!==e.cache_read_input_token_cost?e.cache_read_input_token_cost=Number(e.cache_read_input_token_cost)/1e6:void 0!==e.input_cost_per_token&&null!==e.input_cost_per_token&&""!==e.input_cost_per_token?e.cache_read_input_token_cost=Number(e.input_cost_per_token):delete e.cache_read_input_token_cost,void 0!==e.cache_creation_input_token_cost&&null!==e.cache_creation_input_token_cost&&""!==e.cache_creation_input_token_cost?e.cache_creation_input_token_cost=Number(e.cache_creation_input_token_cost)/1e6:delete e.cache_creation_input_token_cost,void 0!==e.cache_creation_input_token_cost_above_1hr&&null!==e.cache_creation_input_token_cost_above_1hr&&""!==e.cache_creation_input_token_cost_above_1hr?e.cache_creation_input_token_cost_above_1hr=Number(e.cache_creation_input_token_cost_above_1hr)/1e6:delete e.cache_creation_input_token_cost_above_1hr;let s=[];for(let a of t){let t={},l={},r=a.public_name;for(let[s,r]of(t.model=a.litellm_model,t.model=a.litellm_model,Object.entries(e)))if(""!==r&&("litellm_credential_name"!==s||null!=r)&&"custom_pricing"!==s&&"pricing_model"!==s&&"cache_control"!==s)if("model_name"==s)t.model=r;else if("custom_llm_provider"==s)t.custom_llm_provider=(0,a9.C)(r);else if("model"==s)continue;else if("base_model"===s)l[s]=r;else if("team_id"===s)l.team_id=r;else if("model_access_group"===s)l.access_groups=r;else if("mode"==s)l.mode=r,delete t.mode;else if("custom_model_name"===s)t.model=r;else if("litellm_extra_params"==s){let s={};if(r&&void 0!=r){try{s=JSON.parse(r)}catch(e){throw eH.f.fromError("Failed to parse LiteLLM Extra Params: "+e),Error("Failed to parse litellm_extra_params: "+e)}for(let[a,l]of("litellm_credential_name"in s&&e.litellm_credential_name&&delete s.litellm_credential_name,Object.entries(s)))t[a]=l}}else if("model_info_params"==s){let e={};if(r&&void 0!=r){try{e=JSON.parse(r)}catch(e){throw eH.f.fromError("Failed to parse LiteLLM Extra Params: "+e),Error("Failed to parse litellm_extra_params: "+e)}for(let[t,s]of Object.entries(e))l[t]=s}}else if("input_cost_per_token"===s||"output_cost_per_token"===s||"input_cost_per_second"===s||"cache_read_input_token_cost"===s||"cache_creation_input_token_cost"===s||"cache_creation_input_token_cost_above_1hr"===s){null!=r&&""!==r&&(t[s]=Number(r));continue}else if("ptu_count"===s||"cost_per_ptu_per_hour"===s){null!=r&&""!==r&&(l[s]=Number(r));continue}else if("ptu_effective_from"===s||"ptu_effective_to"===s){let e=z(r);null!==e&&(l[s]=e);continue}else t[s]=r;s.push({litellmParamsObj:t,modelInfoObj:l,modelName:r})}return s}catch(e){eH.f.fromError("Failed to create model: "+e)}},rp=async(e,t,s,a)=>{try{let l=await rh(e,t,s);if(!l||0===l.length)return;for(let e of l){let{litellmParamsObj:s,modelInfoObj:a,modelName:l}=e,r={model_name:l,litellm_params:s,model_info:a};await (0,em.jO)(t,r)}a&&a(),s.resetFields()}catch(e){eH.f.fromError("Failed to add model: "+e)}},rf=({formValues:e,accessToken:a,testMode:l,modelName:r="this model",onClose:i,onTestComplete:n})=>{var o,d,c;let u,m,[h,p]=s.default.useState(null),[f,x]=s.default.useState(null),[_,j]=s.default.useState(!0),[v,b]=s.default.useState(!1),[y,N]=s.default.useState(!1),k=async()=>{j(!0),N(!1),p(null),x(null),b(!1),await new Promise(e=>setTimeout(e,100));try{let t=await rh(e,a,null);if(!t?.length){p(t?"Required fields are not filled in. Fill them in and test the connection again.":"Failed to prepare model data. Please check your form inputs."),b(!1),j(!1);return}let{litellmParamsObj:s,modelInfoObj:l}=t[0],r=await (0,em.ym)(a,s,l,l?.mode);if("success"===r.status)eH.f.success("Connection test successful!"),p(null),b(!0);else{let e=r.result?.error||r.message||"Unknown error";p(e),x(r.result?.raw_request_typed_dict),b(!1)}}catch(e){console.error("Test connection error:",e),p(e instanceof Error?e.message:String(e)),b(!1)}finally{j(!1),n?.()}};s.default.useEffect(()=>{let e=setTimeout(()=>{k()},200);return()=>clearTimeout(e)},[]);let w=e=>e?e.split("stack trace:")[0].trim().replace(/^litellm\.(.*?)Error: /,""):"Unknown error",C="string"==typeof h?w(h):h?.message?w(h.message):"Unknown error",S=f?(o=f.raw_request_api_base,d=f.raw_request_body,c=f.raw_request_headers||{},u=JSON.stringify(d,null,2).split("\n").map(e=>` ${e}`).join("\n"),m=Object.entries(c).map(([e,t])=>`-H '${e}: ${t}'`).join(" \\\n "),`curl -X POST \\ ${o} \\ ${m?`${m} \\ `:""}-H 'Content-Type: application/json' \\ diff --git a/litellm/proxy/management_endpoints/policy_endpoints/endpoints.py b/litellm/proxy/management_endpoints/policy_endpoints/endpoints.py index 7cd36d51511..aece5d09e75 100644 --- a/litellm/proxy/management_endpoints/policy_endpoints/endpoints.py +++ b/litellm/proxy/management_endpoints/policy_endpoints/endpoints.py @@ -623,7 +623,9 @@ async def test_policy_matching( ) -POLICY_TEMPLATES_GITHUB_URL: Final = "https://raw.githubusercontent.com/BerriAI/litellm/main/policy_templates.json" +POLICY_TEMPLATES_GITHUB_URL: Final = ( + "https://raw.githubusercontent.com/BerriAI/litellm/main/litellm/data/policy_templates.json" +) def _load_policy_templates_from_local_backup() -> list: diff --git a/litellm/rust/crates/model-catalog-refresh/src/policy.rs b/litellm/rust/crates/model-catalog-refresh/src/policy.rs index 1cdb737ecd8..efb1be24c7a 100644 --- a/litellm/rust/crates/model-catalog-refresh/src/policy.rs +++ b/litellm/rust/crates/model-catalog-refresh/src/policy.rs @@ -14,7 +14,7 @@ pub const RETRYABLE_STATUSES: [u16; 5] = [429, 500, 502, 503, 504]; /// Main's default `LITELLM_MODEL_COST_MAP_URL` pub const DEFAULT_REGISTRY_URL: &str = - "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"; + "https://raw.githubusercontent.com/BerriAI/litellm/main/litellm/data/model_prices_and_context_window.json"; impl RetryPolicy { pub(crate) fn backoff(&self) -> ExponentialBackoff { diff --git a/litellm/rust/crates/model-catalog/AGENTS.md b/litellm/rust/crates/model-catalog/AGENTS.md index d74c206813f..c07502ad6d0 100644 --- a/litellm/rust/crates/model-catalog/AGENTS.md +++ b/litellm/rust/crates/model-catalog/AGENTS.md @@ -67,6 +67,6 @@ A new `N`, image size or resolution in an existing key shape parses with no Rust ## Tests -`BUNDLED_REGISTRY` embeds the root `model_prices_and_context_window.json`, so the tests over it fail a JSON change with a bad value or a key no type reads +`BUNDLED_REGISTRY` embeds `litellm/data/model_prices_and_context_window.json`, so the tests over it fail a JSON change with a bad value or a key no type reads `Catalog::problems` is the one definition of a mergeable cost map. The bundled test asserts it is empty, and the cost map guard workflow runs it on a pull request's JSON through `cargo run --bin check-registry ` diff --git a/litellm/rust/crates/model-catalog/src/bundled.rs b/litellm/rust/crates/model-catalog/src/bundled.rs index 78b30510484..94d20fbe773 100644 --- a/litellm/rust/crates/model-catalog/src/bundled.rs +++ b/litellm/rust/crates/model-catalog/src/bundled.rs @@ -1,3 +1,3 @@ /// The registry document this build serves when no other one is loaded. pub const BUNDLED_REGISTRY: &[u8] = - include_bytes!("../../../../../model_prices_and_context_window.json"); + include_bytes!("../../../../data/model_prices_and_context_window.json"); diff --git a/litellm/rust/crates/model-catalog/tests/generate_price_lookup_reference.py b/litellm/rust/crates/model-catalog/tests/generate_price_lookup_reference.py index e49b635ff4a..855dfc7ebf0 100644 --- a/litellm/rust/crates/model-catalog/tests/generate_price_lookup_reference.py +++ b/litellm/rust/crates/model-catalog/tests/generate_price_lookup_reference.py @@ -70,7 +70,7 @@ def checks(info: dict[str, object], inclusive: bool) -> list[list[object]]: def main() -> None: - registry: Final = json.loads((REPO_ROOT / "model_prices_and_context_window.json").read_text()) + registry: Final = json.loads((REPO_ROOT / "litellm/data/model_prices_and_context_window.json").read_text()) entries: Final = tuple( (token_rates(entry), entry.get("litellm_provider") in INCLUSIVE_PROVIDERS) for name, entry in registry.items() diff --git a/litellm/scripts/build_core_distribution.py b/litellm/scripts/build_core_distribution.py index 3f72c771ac8..ef241b4833c 100644 --- a/litellm/scripts/build_core_distribution.py +++ b/litellm/scripts/build_core_distribution.py @@ -12,7 +12,7 @@ ROOT: Final = Path(__file__).resolve().parents[2] SOURCES: Final = ( "litellm", "litellm/rust", - "model_prices_and_context_window.json", + "litellm/data/model_prices_and_context_window.json", "README.md", "LICENSE", ) @@ -57,7 +57,7 @@ def stage_core_distribution(source: Path, destination: Path, *, package: str = " workspace_sources: Final = ( { "enterprise", "proxy-extras", "packaging", "rust", "cli", "scripts", "runtime", - "schema.prisma", "ui", "vscode-extension", "deploy", + "schema.prisma", "ui", "vscode-extension", "deploy", "data", } if Path(directory) == source / "litellm" else set() @@ -75,6 +75,7 @@ def stage_core_distribution(source: Path, destination: Path, *, package: str = " ignore=ignored_sources, ) else: + (destination / name).parent.mkdir(parents=True, exist_ok=True) shutil.copy2(path, destination / name) template: Final = (source / "litellm" / "packaging" / package / "pyproject.toml").read_text() if package == "litellm-proxy" and IN_TREE_RUST_PATH not in template: diff --git a/litellm/scripts/ci_cd/check_files_match.py b/litellm/scripts/ci_cd/check_files_match.py index 18b6cf792a6..d373264d4f4 100644 --- a/litellm/scripts/ci_cd/check_files_match.py +++ b/litellm/scripts/ci_cd/check_files_match.py @@ -8,7 +8,7 @@ def main(argv=None): "Comparing model_prices_and_context_window and litellm/model_prices_and_context_window_backup.json files... checking if they match." ) - file1 = "model_prices_and_context_window.json" + file1 = "litellm/data/model_prices_and_context_window.json" file2 = "litellm/model_prices_and_context_window_backup.json" cmp_result = filecmp.cmp(file1, file2, shallow=False) diff --git a/litellm/scripts/ci_cd/cost_map_guard.py b/litellm/scripts/ci_cd/cost_map_guard.py index bf3995f7e81..5c239e052e8 100644 --- a/litellm/scripts/ci_cd/cost_map_guard.py +++ b/litellm/scripts/ci_cd/cost_map_guard.py @@ -25,8 +25,8 @@ from dataclasses import dataclass from types import MappingProxyType from typing import Final -COST_MAP_PATH: Final = "model_prices_and_context_window.json" -COST_MAP_PATHS: Final = ("litellm/data/model_prices_and_context_window.json", COST_MAP_PATH) +COST_MAP_PATH: Final = "litellm/data/model_prices_and_context_window.json" +COST_MAP_PATHS: Final = (COST_MAP_PATH, "model_prices_and_context_window.json") BACKUP_PATH: Final = "litellm/model_prices_and_context_window_backup.json" PINS_PATH: Final = "litellm/scripts/ci_cd/cost_map_pins.json" PINS_PATHS: Final = ( diff --git a/litellm/scripts/generate_provider_endpoints_support.py b/litellm/scripts/generate_provider_endpoints_support.py index d9b3706bcd3..5d83a3dcf30 100644 --- a/litellm/scripts/generate_provider_endpoints_support.py +++ b/litellm/scripts/generate_provider_endpoints_support.py @@ -12,8 +12,8 @@ from typing import Final from pydantic import JsonValue, TypeAdapter ROOT: Final = Path(__file__).resolve().parents[2] -COST_MAP_PATH: Final = ROOT / "model_prices_and_context_window.json" -SOURCE_PATH: Final = ROOT / "provider_endpoints_support.json" +COST_MAP_PATH: Final = ROOT / "litellm/data/model_prices_and_context_window.json" +SOURCE_PATH: Final = ROOT / "litellm/data/provider_endpoints_support.json" OUTPUT_PATHS: Final = ( SOURCE_PATH, ROOT / "litellm/provider_endpoints_support_backup.json", @@ -231,13 +231,13 @@ def main(argv: Sequence[str] | None = None, *, repo_root: Path = ROOT) -> int: parser: Final = argparse.ArgumentParser(description="Generate provider endpoint support from the model cost map") parser.add_argument("--check", action="store_true", help="fail if either generated file is stale") args: Final = parser.parse_args(argv) - cost_map: Final = JSON_OBJECT.validate_json((repo_root / COST_MAP_PATH.name).read_bytes()) - current_json: Final = JSON_OBJECT.validate_json((repo_root / SOURCE_PATH.name).read_bytes()) + cost_map: Final = JSON_OBJECT.validate_json((repo_root / COST_MAP_PATH.relative_to(ROOT)).read_bytes()) + current_json: Final = JSON_OBJECT.validate_json((repo_root / SOURCE_PATH.relative_to(ROOT)).read_bytes()) return generate_files( cost_map, current_json, ( - repo_root / SOURCE_PATH.name, + repo_root / SOURCE_PATH.relative_to(ROOT), repo_root / OUTPUT_PATHS[1].relative_to(ROOT), ), args.check, diff --git a/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.test.tsx b/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.test.tsx index 07e10ec2893..a313cd7874e 100644 --- a/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.test.tsx +++ b/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.test.tsx @@ -14,7 +14,7 @@ describe("recommended replacement", () => { expect(screen.getByText("new-model")).toBeInTheDocument(); expect(screen.getByRole("link", { name: "LiteLLM model cost map" })).toHaveAttribute( "href", - "https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json", + "https://github.com/BerriAI/litellm/blob/main/litellm/data/model_prices_and_context_window.json", ); expect(screen.getByRole("link", { name: /Provider deprecation notice/ })).toHaveAttribute( "href", diff --git a/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.tsx b/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.tsx index 504b2f2e7fb..41ef2bb181e 100644 --- a/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.tsx +++ b/litellm/ui/litellm-dashboard/src/components/ModelDeprecationAlerts/RecommendedReplacement.tsx @@ -37,7 +37,7 @@ export default function RecommendedReplacement({ recommendation }: { recommendat {t("alerts.recommendation.source")}{" "} {source === "model_cost_map" ? ( ); const catalog: Record = JSON.parse( - readFileSync(new URL("../../../../../../model_prices_and_context_window.json", import.meta.url), "utf8"), + readFileSync(new URL("../../../../../data/model_prices_and_context_window.json", import.meta.url), "utf8"), ); const catalogOpusModels = Object.entries(catalog).filter( ([id, metadata]) => metadata.mode === "chat" && /claude-opus-\d/.test(id) && !/-(?:fast|think)$/.test(id), diff --git a/litellm/ui/litellm-dashboard/src/components/add_model/provider_specific_fields.tsx b/litellm/ui/litellm-dashboard/src/components/add_model/provider_specific_fields.tsx index e787e9df20c..5f09bfe44c7 100644 --- a/litellm/ui/litellm-dashboard/src/components/add_model/provider_specific_fields.tsx +++ b/litellm/ui/litellm-dashboard/src/components/add_model/provider_specific_fields.tsx @@ -424,7 +424,7 @@ const ProviderSpecificFieldsContent: React.FC = ({ components={{ docs: ( = JSON.parse( - readFileSync(resolve(__dirname, "../../../../../model_prices_and_context_window.json"), "utf8"), + readFileSync(resolve(__dirname, "../../../../data/model_prices_and_context_window.json"), "utf8"), ); describe("provider_info_helpers", () => { diff --git a/litellm/utils.py b/litellm/utils.py index e48baab0542..f4d29ce2f1c 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -6659,7 +6659,7 @@ def get_max_tokens(model: str) -> int | None: return None except Exception: raise Exception( - f"Model {model} isn't mapped yet. Add it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json" + f"Model {model} isn't mapped yet. Add it here - https://github.com/BerriAI/litellm/blob/main/litellm/data/model_prices_and_context_window.json" ) @@ -7070,7 +7070,7 @@ _ABOVE_THRESHOLD_COST_KEY: Final = ABOVE_THRESHOLD_COST_KEY_PATTERN def _model_not_mapped_message(model: str, custom_llm_provider: str | None) -> str: return ( f"This model isn't mapped yet. model={model}, custom_llm_provider={custom_llm_provider}. " - "Add it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json." + "Add it here - https://github.com/BerriAI/litellm/blob/main/litellm/data/model_prices_and_context_window.json." ) diff --git a/pyproject.toml b/pyproject.toml index c1e11ddc2df..f26e5c165a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -351,9 +351,12 @@ include = [ "litellm/proxy/common_utils/codex_bundled_models_0.166.0.json", "litellm/proxy/common_utils/codex_bedrock_mantle_models_0.166.0.json", "litellm/proxy/common_utils/codex_bedrock_runtime_models_0.166.0.json", - { path = "model_prices_and_context_window.json", format = "sdist" }, + { path = "litellm/data/model_prices_and_context_window.json", format = "sdist" }, ] exclude = [ + { path = "litellm/data/model_prices_and_context_window.json", format = "wheel" }, + "litellm/data/policy_templates.json", + "litellm/data/provider_endpoints_support.json", "litellm/scripts", "litellm/scripts/**", "litellm/runtime", @@ -397,7 +400,7 @@ cache-keys = [ { file = "litellm/rust/Cargo.lock" }, { file = "litellm/rust/Cargo.toml" }, { file = "litellm/rust/crates/**/*" }, - { file = "model_prices_and_context_window.json" }, + { file = "litellm/data/model_prices_and_context_window.json" }, ] constraint-dependencies = [ "tornado>=6.5.8", diff --git a/tests/base_sdk_tests/test_core_distribution.py b/tests/base_sdk_tests/test_core_distribution.py index 82deb72bc9f..a9f88155263 100644 --- a/tests/base_sdk_tests/test_core_distribution.py +++ b/tests/base_sdk_tests/test_core_distribution.py @@ -102,7 +102,7 @@ def test_staging_stamps_release_version_without_modifying_sources( (stage / name).exists() for name in ( "litellm/rust", "litellm/rust/.cargo/config.toml", "litellm/rust/rust-toolchain.toml", - "model_prices_and_context_window.json", + "litellm/data/model_prices_and_context_window.json", ) ) assert manifest.read_bytes() == original @@ -206,7 +206,7 @@ def test_core_artifacts_exclude_local_configuration(distributions: tuple[Path, P @pytest.mark.parametrize( "relative_path", - ["litellm/rust/rust-toolchain.toml", "litellm/rust/.cargo/config.toml", "model_prices_and_context_window.json"], + ["litellm/rust/rust-toolchain.toml", "litellm/rust/.cargo/config.toml", "litellm/data/model_prices_and_context_window.json"], ) def test_core_sdist_preserves_native_build_configuration(distribution_directory: Path, relative_path: str) -> None: sdists: Final = tuple(distribution_directory.glob("litellm_core-*.tar.gz")) @@ -245,7 +245,7 @@ def test_staging_copies_sources_without_build_artifacts(tmp_path: Path, source_r source: Final = source_repository for name in SOURCES: - (source / name).mkdir() + (source / name).mkdir(parents=True, exist_ok=True) (source / name / "shared.txt").write_text("source payload") (source / name / "stale.so").write_text("old native extension") (source / name / "__pycache__").mkdir() @@ -267,7 +267,7 @@ def test_staging_preserves_gitignore_rules(tmp_path: Path, source_repository: Pa source: Final = source_repository for name in SOURCES: - (source / name).mkdir() + (source / name).mkdir(parents=True, exist_ok=True) (source / name / "shared.txt").write_text("shared payload") (source / "pyproject.toml").write_text('[project]\nname = "litellm"\nversion = "1.2.3"\n') manifest: Final = source / "litellm/packaging/litellm-core/pyproject.toml" diff --git a/tests/code_coverage_tests/check_endpoint_coverage.py b/tests/code_coverage_tests/check_endpoint_coverage.py index 2d46d1ab469..2ace9e87593 100644 --- a/tests/code_coverage_tests/check_endpoint_coverage.py +++ b/tests/code_coverage_tests/check_endpoint_coverage.py @@ -99,7 +99,7 @@ def extract_endpoints_from_sidebars() -> Dict[str, str]: def load_provider_endpoints_file() -> Dict: """Load the provider_endpoints_support.json file.""" repo_root = get_repo_root() - file_path = repo_root / "provider_endpoints_support.json" + file_path = repo_root / "litellm/data/provider_endpoints_support.json" if not file_path.exists(): print( diff --git a/tests/code_coverage_tests/check_provider_folders_documented.py b/tests/code_coverage_tests/check_provider_folders_documented.py index b4e60246774..4caa5b2de78 100644 --- a/tests/code_coverage_tests/check_provider_folders_documented.py +++ b/tests/code_coverage_tests/check_provider_folders_documented.py @@ -72,7 +72,7 @@ def get_llm_provider_folders() -> Set[str]: def load_provider_endpoints_file() -> Dict: """Load the provider_endpoints_support.json file.""" repo_root = get_repo_root() - file_path = repo_root / "provider_endpoints_support.json" + file_path = repo_root / "litellm/data/provider_endpoints_support.json" if not file_path.exists(): print( diff --git a/tests/code_coverage_tests/test_generate_provider_endpoints_support.py b/tests/code_coverage_tests/test_generate_provider_endpoints_support.py index 62782edb7f4..ed7232bbdd8 100644 --- a/tests/code_coverage_tests/test_generate_provider_endpoints_support.py +++ b/tests/code_coverage_tests/test_generate_provider_endpoints_support.py @@ -141,10 +141,11 @@ def test_cost_map_provider_without_file_entry_is_an_error() -> None: def test_check_reports_stale_output_without_writing(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None: + (tmp_path / "litellm/data").mkdir(parents=True) cost_map: Final = {"example/model": {"litellm_provider": "example", "mode": "chat"}} current_json: Final = _current_json({"example": _provider()}) - (tmp_path / "model_prices_and_context_window.json").write_text(json.dumps(cost_map), encoding="utf-8") - source_path: Final = tmp_path / "provider_endpoints_support.json" + (tmp_path / "litellm/data/model_prices_and_context_window.json").write_text(json.dumps(cost_map), encoding="utf-8") + source_path: Final = tmp_path / "litellm/data/provider_endpoints_support.json" source_content: Final = json.dumps(current_json) source_path.write_text(source_content, encoding="utf-8") @@ -159,16 +160,17 @@ def test_check_reports_stale_output_without_writing(tmp_path: Path, capsys: pyte def test_check_reports_stale_backup_without_writing(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None: + (tmp_path / "litellm/data").mkdir(parents=True) cost_map: Final = {"example/model": {"litellm_provider": "example", "mode": "chat"}} current_json: Final = _current_json({"example": _provider()}) generated: Final = generate_provider_endpoints_support(cost_map, current_json) generated_content: Final = json.dumps(generated, indent=2, ensure_ascii=False) + "\n" - source_path: Final = tmp_path / "provider_endpoints_support.json" + source_path: Final = tmp_path / "litellm/data/provider_endpoints_support.json" backup_path: Final = tmp_path / "litellm/provider_endpoints_support_backup.json" backup_content: Final = "stale\n" - (tmp_path / "model_prices_and_context_window.json").write_text(json.dumps(cost_map), encoding="utf-8") + (tmp_path / "litellm/data/model_prices_and_context_window.json").write_text(json.dumps(cost_map), encoding="utf-8") source_path.write_text(generated_content, encoding="utf-8") - backup_path.parent.mkdir() + backup_path.parent.mkdir(exist_ok=True) backup_path.write_text(backup_content, encoding="utf-8") result: Final = main(["--check"], repo_root=tmp_path) diff --git a/tests/integration/management/test_auto_router_databricks_classifier_writes.py b/tests/integration/management/test_auto_router_databricks_classifier_writes.py index ecb37261790..b4be60660bc 100644 --- a/tests/integration/management/test_auto_router_databricks_classifier_writes.py +++ b/tests/integration/management/test_auto_router_databricks_classifier_writes.py @@ -72,7 +72,7 @@ def _number(value: JsonValue) -> float: def _endpoint_cost() -> float: prices: Final = object_value( - json.loads(Path("model_prices_and_context_window.json").read_text())[f"databricks/{_ENDPOINT}"] + json.loads(Path("litellm/data/model_prices_and_context_window.json").read_text())[f"databricks/{_ENDPOINT}"] ) usage: Final = object_value(_ENDPOINT_ANSWER["usage"]) return _number(usage["input_tokens"]) * _number(prices["input_cost_per_token"]) + _number( diff --git a/tests/integration/providers/_coralbricks.py b/tests/integration/providers/_coralbricks.py index e6449df9591..467a4f5ab4a 100644 --- a/tests/integration/providers/_coralbricks.py +++ b/tests/integration/providers/_coralbricks.py @@ -28,7 +28,7 @@ CACHED_TOKENS: Final = 4352 CACHE_WRITE_TOKENS: Final = 5 COMPLETION_TOKENS: Final = 20 REASONING_TOKENS: Final = 12 -COST_MAP: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +COST_MAP: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" LEAK_FIELDS: Final = frozenset( {"litellm_params", "litellm_logging_obj", "litellm_call_id", "litellm_metadata", "proxy_server_request"} ) diff --git a/tests/integration/providers/_mantle_gpt_prompt_cache_support.py b/tests/integration/providers/_mantle_gpt_prompt_cache_support.py index 96261bab8b2..50478b466d7 100644 --- a/tests/integration/providers/_mantle_gpt_prompt_cache_support.py +++ b/tests/integration/providers/_mantle_gpt_prompt_cache_support.py @@ -133,7 +133,7 @@ CHAT_USAGE: Final[dict[str, JsonValue]] = { } -COST_MAP: Final = JSON.validate_json(Path("model_prices_and_context_window.json").read_bytes()) +COST_MAP: Final = JSON.validate_json(Path("litellm/data/model_prices_and_context_window.json").read_bytes()) RESPONSES_PATH: Final = "/openai/v1/responses" diff --git a/tests/integration/providers/test_bedrock_mantle_count_tokens_wire.py b/tests/integration/providers/test_bedrock_mantle_count_tokens_wire.py index 2a0508402ae..fa5c4720328 100644 --- a/tests/integration/providers/test_bedrock_mantle_count_tokens_wire.py +++ b/tests/integration/providers/test_bedrock_mantle_count_tokens_wire.py @@ -75,7 +75,7 @@ _SCRIPTED_STATUS: Final = re.compile(r"status=(\d{3})") _STARTED_WORKER: Final = re.compile(r"Started server process \[(\d+)\]") _JSON_OBJECT: Final = TypeAdapter(dict[str, JsonValue]) _JSON_LIST: Final = TypeAdapter(list[JsonValue]) -_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" _COST_MAP: Final = TypeAdapter(dict[str, dict[str, JsonValue]]) diff --git a/tests/integration/providers/test_cloudflare_clairic_extraction_wire.py b/tests/integration/providers/test_cloudflare_clairic_extraction_wire.py index 7b2a48c9676..75b2063dcdc 100644 --- a/tests/integration/providers/test_cloudflare_clairic_extraction_wire.py +++ b/tests/integration/providers/test_cloudflare_clairic_extraction_wire.py @@ -114,7 +114,7 @@ def _number(value: JsonValue) -> float: def _expected_spend() -> float: - cost_map: Final = JSON_OBJECT.validate_json(Path("model_prices_and_context_window.json").read_bytes()) + cost_map: Final = JSON_OBJECT.validate_json(Path("litellm/data/model_prices_and_context_window.json").read_bytes()) priced: Final = cost_map.get(_CLAIRIC) assert priced is not None, f"{_CLAIRIC} has no cost map entry" return _INPUT_TOKENS * _number(object_value(priced)["input_cost_per_token"]) diff --git a/tests/integration/providers/test_cloudflare_clef_images_wire.py b/tests/integration/providers/test_cloudflare_clef_images_wire.py index bf6d01b2455..27a42e4383a 100644 --- a/tests/integration/providers/test_cloudflare_clef_images_wire.py +++ b/tests/integration/providers/test_cloudflare_clef_images_wire.py @@ -178,7 +178,7 @@ def _number(value: JsonValue) -> float: def _expected_spend(cost_map_key: str) -> float: - cost_map: Final = _JSON_OBJECT.validate_json(Path("model_prices_and_context_window.json").read_bytes()) + cost_map: Final = _JSON_OBJECT.validate_json(Path("litellm/data/model_prices_and_context_window.json").read_bytes()) priced: Final = cost_map.get(cost_map_key) assert priced is not None, f"{cost_map_key} has no cost map entry" return _INPUT_TOKENS * _number(object_value(priced)["input_cost_per_token"]) diff --git a/tests/integration/providers/test_cloudflare_clef_omni_media_wire.py b/tests/integration/providers/test_cloudflare_clef_omni_media_wire.py index 12a8576c31a..4a474d26c98 100644 --- a/tests/integration/providers/test_cloudflare_clef_omni_media_wire.py +++ b/tests/integration/providers/test_cloudflare_clef_omni_media_wire.py @@ -177,7 +177,7 @@ def _answered_probability(route: Route, text: str) -> JsonValue: def _price() -> dict[str, JsonValue]: - cost_map: Final = _JSON_OBJECT.validate_json(Path("model_prices_and_context_window.json").read_bytes()) + cost_map: Final = _JSON_OBJECT.validate_json(Path("litellm/data/model_prices_and_context_window.json").read_bytes()) priced: Final = cost_map.get(_COST_MAP_KEY) assert priced is not None, f"{_COST_MAP_KEY} has no cost map entry" return object_value(priced) diff --git a/tests/integration/providers/test_count_tokens_model_wire.py b/tests/integration/providers/test_count_tokens_model_wire.py index f15545f4374..3ba398a76a4 100644 --- a/tests/integration/providers/test_count_tokens_model_wire.py +++ b/tests/integration/providers/test_count_tokens_model_wire.py @@ -32,7 +32,7 @@ _KIMI: Final = "us.moonshotai.kimi-k3" _KIMI_BASE: Final = "moonshotai.kimi-k3" _PROFILE_ID: Final = "lit9563count" _PROFILE_ARN: Final = f"arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/{_PROFILE_ID}" -_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" _REGION: Final = "us-west-2" _ACCESS_KEY: Final = "AKIAINTEGRATIONCOUNT" _SECRET_KEY: Final = "integration-count-secret" diff --git a/tests/integration/providers/test_databricks_decisions_wire.py b/tests/integration/providers/test_databricks_decisions_wire.py index 7b54895adaf..1f8385da341 100644 --- a/tests/integration/providers/test_databricks_decisions_wire.py +++ b/tests/integration/providers/test_databricks_decisions_wire.py @@ -97,7 +97,7 @@ def _number(value: JsonValue) -> float: def _endpoint_spend() -> float: prices: Final = object_value( - json.loads(Path("model_prices_and_context_window.json").read_text())[f"databricks/{_ENDPOINT}"] + json.loads(Path("litellm/data/model_prices_and_context_window.json").read_text())[f"databricks/{_ENDPOINT}"] ) return _number(_USAGE["input_tokens"]) * _number(prices["input_cost_per_token"]) + _number( _USAGE["output_tokens"] diff --git a/tests/integration/providers/test_decisions_openai_format_wire.py b/tests/integration/providers/test_decisions_openai_format_wire.py index 0c40fe06199..69d285f2142 100644 --- a/tests/integration/providers/test_decisions_openai_format_wire.py +++ b/tests/integration/providers/test_decisions_openai_format_wire.py @@ -292,7 +292,7 @@ def _expected_spend(provider: _Provider) -> float: return provider.provider_reported_cost if provider.cost_map_key is None: return 0.0 - cost_map: Final = _JSON_OBJECT.validate_json(Path("model_prices_and_context_window.json").read_bytes()) + cost_map: Final = _JSON_OBJECT.validate_json(Path("litellm/data/model_prices_and_context_window.json").read_bytes()) prices: Final = object_value(cost_map[provider.cost_map_key]) input_key: Final = ( "input_cost_per_token_decisions" if "input_cost_per_token_decisions" in prices else "input_cost_per_token" diff --git a/tests/integration/providers/test_decisions_wire.py b/tests/integration/providers/test_decisions_wire.py index 7381965f377..160bd38357e 100644 --- a/tests/integration/providers/test_decisions_wire.py +++ b/tests/integration/providers/test_decisions_wire.py @@ -205,7 +205,7 @@ def _expected_spend(provider: _Provider) -> float: if provider.cost_map_key is None: return 0.0 prices: Final = object_value( - json.loads(Path("model_prices_and_context_window.json").read_text())[provider.cost_map_key] + json.loads(Path("litellm/data/model_prices_and_context_window.json").read_text())[provider.cost_map_key] ) return _number(_USAGE["input_tokens"]) * _number(prices["input_cost_per_token"]) + _number( _USAGE["output_tokens"] diff --git a/tests/integration/providers/test_fal_ai_chat_wire.py b/tests/integration/providers/test_fal_ai_chat_wire.py index 8cfa51f4389..c7619426fc9 100644 --- a/tests/integration/providers/test_fal_ai_chat_wire.py +++ b/tests/integration/providers/test_fal_ai_chat_wire.py @@ -9,7 +9,7 @@ from pydantic import JsonValue, TypeAdapter _MODEL: Final = "fal-ai/moondream3-preview/query" _PROMPT: Final = "what is in this image?" -_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" _JSON_OBJECT: Final = TypeAdapter(dict[str, JsonValue]) _COST_MAP: Final = TypeAdapter(dict[str, dict[str, object]]) diff --git a/tests/integration/providers/test_fal_ai_image_wire.py b/tests/integration/providers/test_fal_ai_image_wire.py index a573aff8d03..7be9ff2e86a 100644 --- a/tests/integration/providers/test_fal_ai_image_wire.py +++ b/tests/integration/providers/test_fal_ai_image_wire.py @@ -22,7 +22,7 @@ _PNG_BYTES: Final = ( b"\x89\x99=\x1d\x00\x00\x00\x00IEND\xaeB`\x82" ) _PROMPT: Final = "a red circle on a blue background" -_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" _JSON_OBJECT: Final = TypeAdapter(dict[str, JsonValue]) _COST_MAP: Final = TypeAdapter(dict[str, dict[str, object]]) diff --git a/tests/integration/providers/test_fireworks_ai_router_slug_wire.py b/tests/integration/providers/test_fireworks_ai_router_slug_wire.py index f6262cc21f1..82648245455 100644 --- a/tests/integration/providers/test_fireworks_ai_router_slug_wire.py +++ b/tests/integration/providers/test_fireworks_ai_router_slug_wire.py @@ -14,7 +14,7 @@ _ROUTER_RESOURCE: Final = "accounts/fireworks/routers/glm-latest" _FIREROUTER_SLUGS: Final = ("firerouter", "firerouter/kimi-k3/deepseek-v4") _API_KEY: Final = "synthetic-fireworks-key" _PROMPT: Final = "route me through the router" -_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" _JSON_OBJECT: Final = TypeAdapter(dict[str, JsonValue]) _COST_MAP: Final = TypeAdapter(dict[str, dict[str, object]]) diff --git a/tests/integration/providers/test_inferenceapis_wire.py b/tests/integration/providers/test_inferenceapis_wire.py index 5f400d05957..70b88ea429f 100644 --- a/tests/integration/providers/test_inferenceapis_wire.py +++ b/tests/integration/providers/test_inferenceapis_wire.py @@ -29,7 +29,7 @@ _WEATHER_TOOL: Final[JsonValue] = { "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}, }, } -_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" _ENDPOINT_SUPPORT_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/provider_endpoints_support_backup.json" _COST_MAP: Final = TypeAdapter(dict[str, dict[str, JsonValue]]) _JSON_OBJECT: Final = TypeAdapter(dict[str, JsonValue]) diff --git a/tests/integration/providers/test_xiaomi_mimo_wire.py b/tests/integration/providers/test_xiaomi_mimo_wire.py index 2722e501c47..8f9ef31a363 100644 --- a/tests/integration/providers/test_xiaomi_mimo_wire.py +++ b/tests/integration/providers/test_xiaomi_mimo_wire.py @@ -27,7 +27,7 @@ _WEATHER_TOOL: Final[JsonValue] = { }, }, } -_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "model_prices_and_context_window.json" +_COST_MAP_PATH: Final = Path(__file__).resolve().parents[3] / "litellm/data/model_prices_and_context_window.json" _JSON_OBJECT: Final = TypeAdapter(dict[str, JsonValue]) _COST_MAP: Final = TypeAdapter(dict[str, dict[str, object]]) diff --git a/tests/integration/routing/test_complexity_router_databricks_classifier.py b/tests/integration/routing/test_complexity_router_databricks_classifier.py index 73a665cee7b..2bb652bde6a 100644 --- a/tests/integration/routing/test_complexity_router_databricks_classifier.py +++ b/tests/integration/routing/test_complexity_router_databricks_classifier.py @@ -797,7 +797,7 @@ def test_a_five_kilobyte_prompt_with_a_system_message_reaches_the_classifier_who def _typesafe_cost() -> float: prices: Final = object_value( - json.loads(Path("model_prices_and_context_window.json").read_text())[f"typesafe/{_TYPESAFE_MODEL}"] + json.loads(Path("litellm/data/model_prices_and_context_window.json").read_text())[f"typesafe/{_TYPESAFE_MODEL}"] ) return _number(_USAGE["input_tokens"]) * _number(prices["input_cost_per_token"]) + _number( _USAGE["output_tokens"] diff --git a/tests/unit/litellm_core_utils/test_fallback_generalizations.py b/tests/unit/litellm_core_utils/test_fallback_generalizations.py index b22edaa171a..597ebaf1c94 100644 --- a/tests/unit/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/unit/litellm_core_utils/test_fallback_generalizations.py @@ -402,7 +402,7 @@ def test_exact_entries_fill_only_missing_fields(restore_generalizations, monkeyp @pytest.mark.parametrize( "cost_map_path", - ["model_prices_and_context_window.json", "litellm/model_prices_and_context_window_backup.json"], + ["litellm/data/model_prices_and_context_window.json", "litellm/model_prices_and_context_window_backup.json"], ) def test_every_shipped_rule_installs_without_a_skip_warning( restore_generalizations: Callable[[list | None], None], warning_messages: list[str], cost_map_path: str diff --git a/tests/unit/llms/anthropic/messages/test_reasoning_effort_fields.py b/tests/unit/llms/anthropic/messages/test_reasoning_effort_fields.py index 7a26f403408..3eba6dffa4d 100644 --- a/tests/unit/llms/anthropic/messages/test_reasoning_effort_fields.py +++ b/tests/unit/llms/anthropic/messages/test_reasoning_effort_fields.py @@ -27,7 +27,7 @@ def _load_model_registry() -> Dict[str, Any]: """Load the root model_prices_and_context_window.json.""" json_path = os.path.join( os.path.dirname(__file__), - "../../../../../model_prices_and_context_window.json", + "../../../../../litellm/data/model_prices_and_context_window.json", ) with open(json_path) as f: return json.load(f) diff --git a/tests/unit/llms/azure_ai/test_azure_ai_foundry_catalog_model_metadata.py b/tests/unit/llms/azure_ai/test_azure_ai_foundry_catalog_model_metadata.py index 404b3240399..8a14aff0fa1 100644 --- a/tests/unit/llms/azure_ai/test_azure_ai_foundry_catalog_model_metadata.py +++ b/tests/unit/llms/azure_ai/test_azure_ai_foundry_catalog_model_metadata.py @@ -9,7 +9,7 @@ from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider from litellm.types.utils import TranscriptionResponse REPO_ROOT: Final = Path(__file__).parents[4] -MAIN_COST_MAP: Final = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_COST_MAP: Final = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_COST_MAP: Final = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" COST_MAP_ADAPTER: Final = TypeAdapter(dict[str, dict[str, object]]) A_MILLION: Final = 1_000_000 diff --git a/tests/unit/llms/clf_ai_gateway/test_clf_ai_gateway_chat_transformation.py b/tests/unit/llms/clf_ai_gateway/test_clf_ai_gateway_chat_transformation.py index bdaad6a8c2a..2af578c6c23 100644 --- a/tests/unit/llms/clf_ai_gateway/test_clf_ai_gateway_chat_transformation.py +++ b/tests/unit/llms/clf_ai_gateway/test_clf_ai_gateway_chat_transformation.py @@ -213,7 +213,7 @@ def test_reasoning_effort_is_advertised_only_for_reasoning_models(local_model_co def test_cost_map_rows_match_the_backup_and_resolve_their_effort_levels() -> None: - rows: Final = _clf_rows(REPO_ROOT / "model_prices_and_context_window.json") + rows: Final = _clf_rows(REPO_ROOT / "litellm/data/model_prices_and_context_window.json") assert rows assert rows == _clf_rows(REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json") for key, row in rows.items(): diff --git a/tests/unit/llms/dashscope/test_qwen_brand_aliases.py b/tests/unit/llms/dashscope/test_qwen_brand_aliases.py index 43ef8f90b39..83f2ea7c010 100644 --- a/tests/unit/llms/dashscope/test_qwen_brand_aliases.py +++ b/tests/unit/llms/dashscope/test_qwen_brand_aliases.py @@ -345,7 +345,7 @@ class TestQwenBrandUserFacingNames: "matrix_path", [ Path(litellm.__file__).parent / "provider_endpoints_support_backup.json", - Path(litellm.__file__).parent.parent / "provider_endpoints_support.json", + Path(litellm.__file__).parent.parent / "litellm/data/provider_endpoints_support.json", ], ids=["backup", "root"], ) diff --git a/tests/unit/llms/databricks/test_databricks_cost_calculator.py b/tests/unit/llms/databricks/test_databricks_cost_calculator.py index e9bc75119aa..d46a281ee7f 100644 --- a/tests/unit/llms/databricks/test_databricks_cost_calculator.py +++ b/tests/unit/llms/databricks/test_databricks_cost_calculator.py @@ -11,7 +11,7 @@ from litellm.llms.databricks.cost_calculator import cost_per_token from litellm.types.utils import ModelInfo, Usage REPO_ROOT: Final = Path(__file__).parents[4] -MAIN_PRICES: Final = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PRICES: Final = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PRICES: Final = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" NEW_MODELS: Final = ( "databricks/databricks-claude-opus-4-7", diff --git a/tests/unit/llms/edenai/chat/test_edenai_chat_transformation.py b/tests/unit/llms/edenai/chat/test_edenai_chat_transformation.py index 739ad144277..75236144d9f 100644 --- a/tests/unit/llms/edenai/chat/test_edenai_chat_transformation.py +++ b/tests/unit/llms/edenai/chat/test_edenai_chat_transformation.py @@ -431,7 +431,7 @@ class TestDashboardRegistration: @pytest.mark.parametrize( "matrix_path", [ - REPO_ROOT / "provider_endpoints_support.json", + REPO_ROOT / "litellm/data/provider_endpoints_support.json", REPO_ROOT / "litellm" / "provider_endpoints_support_backup.json", ], ids=["root", "backup"], diff --git a/tests/unit/llms/minimax/chat/test_transformation.py b/tests/unit/llms/minimax/chat/test_transformation.py index d289bdba9bf..d7cc889cdc3 100644 --- a/tests/unit/llms/minimax/chat/test_transformation.py +++ b/tests/unit/llms/minimax/chat/test_transformation.py @@ -181,7 +181,7 @@ def test_minimax_flash_cost_map_entry_is_a_priced_reasoning_model(local_model_co entries: Final = tuple( json.loads(path.read_text())["minimax/MiniMax-M3.1-Flash"] for path in ( - repo_root / "model_prices_and_context_window.json", + repo_root / "litellm/data/model_prices_and_context_window.json", repo_root / "litellm/model_prices_and_context_window_backup.json", ) ) diff --git a/tests/unit/llms/openai_like/test_coralbricks_provider.py b/tests/unit/llms/openai_like/test_coralbricks_provider.py index 6187c7aa466..a8c2c55fe1a 100644 --- a/tests/unit/llms/openai_like/test_coralbricks_provider.py +++ b/tests/unit/llms/openai_like/test_coralbricks_provider.py @@ -380,7 +380,7 @@ def test_coralbricks_rows_are_listed_for_wildcard_expansion(): def test_coralbricks_cost_map_backup_mirrors_main(): main_map: Final = json.loads( - (Path(litellm.__file__).parent.parent / "model_prices_and_context_window.json").read_text() + (Path(litellm.__file__).parent.parent / "litellm/data/model_prices_and_context_window.json").read_text() ) backup_map: Final = json.loads( (Path(litellm.__file__).parent / "model_prices_and_context_window_backup.json").read_text() @@ -398,7 +398,7 @@ def test_coralbricks_cost_map_rows_declare_same_endpoints_as_providers_json(): ) declared: Final = providers_json["coralbricks"]["supported_endpoints"] cost_map_paths: Final = ( - Path(litellm.__file__).parent.parent / "model_prices_and_context_window.json", + Path(litellm.__file__).parent.parent / "litellm/data/model_prices_and_context_window.json", Path(litellm.__file__).parent / "model_prices_and_context_window_backup.json", ) for cost_map_path in cost_map_paths: diff --git a/tests/unit/llms/openai_like/test_kyma_provider.py b/tests/unit/llms/openai_like/test_kyma_provider.py index c4bb36ef011..45665879292 100644 --- a/tests/unit/llms/openai_like/test_kyma_provider.py +++ b/tests/unit/llms/openai_like/test_kyma_provider.py @@ -17,7 +17,7 @@ from litellm.proxy.common_request_processing import cost_headers from litellm.types.utils import Delta, ModelResponseStream, StreamingChoices, Usage _REPO_ROOT: Final = Path(__file__).resolve().parents[4] -_PRIMARY_PRICES: Final = json.loads((_REPO_ROOT / "model_prices_and_context_window.json").read_text()) +_PRIMARY_PRICES: Final = json.loads((_REPO_ROOT / "litellm/data/model_prices_and_context_window.json").read_text()) _BACKUP_PRICES: Final = json.loads((_REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json").read_text()) _CATALOG_MODELS: Final = tuple( key for key, row in _PRIMARY_PRICES.items() if isinstance(row, dict) and row.get("litellm_provider") == "kyma" diff --git a/tests/unit/llms/openai_like/test_openinfer_provider.py b/tests/unit/llms/openai_like/test_openinfer_provider.py index 6e6e957df0b..d8ed2875d5c 100644 --- a/tests/unit/llms/openai_like/test_openinfer_provider.py +++ b/tests/unit/llms/openai_like/test_openinfer_provider.py @@ -10,7 +10,7 @@ from litellm.caching.llm_caching_handler import LLMClientCache from litellm.proxy.auth.model_checks import get_provider_models _REPO_ROOT: Final = Path(__file__).resolve().parents[4] -_PRIMARY_PRICES: Final = json.loads((_REPO_ROOT / "model_prices_and_context_window.json").read_text()) +_PRIMARY_PRICES: Final = json.loads((_REPO_ROOT / "litellm/data/model_prices_and_context_window.json").read_text()) _BACKUP_PRICES: Final = json.loads((_REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json").read_text()) _CATALOG_MODELS: Final = tuple( key for key, row in _PRIMARY_PRICES.items() if isinstance(row, dict) and row.get("litellm_provider") == "openinfer" diff --git a/tests/unit/llms/openai_like/test_prism_provider.py b/tests/unit/llms/openai_like/test_prism_provider.py index 9bf5cdbbbb4..7638911b650 100644 --- a/tests/unit/llms/openai_like/test_prism_provider.py +++ b/tests/unit/llms/openai_like/test_prism_provider.py @@ -75,7 +75,7 @@ def test_prism_model_cost_and_capabilities(model: str): def test_prism_backup_registry_mirrors_cost_map(): package_root = Path(litellm.__file__).parent - cost_map = json.loads((package_root.parent / "model_prices_and_context_window.json").read_text()) + cost_map = json.loads((package_root.parent / "litellm/data/model_prices_and_context_window.json").read_text()) backup = json.loads((package_root / "model_prices_and_context_window_backup.json").read_text()) prism_entries = {name: entry for name, entry in cost_map.items() if name.startswith("prism/")} diff --git a/tests/unit/llms/openai_like/test_scx_ai_provider.py b/tests/unit/llms/openai_like/test_scx_ai_provider.py index f1c05e13888..9a58813b2e2 100644 --- a/tests/unit/llms/openai_like/test_scx_ai_provider.py +++ b/tests/unit/llms/openai_like/test_scx_ai_provider.py @@ -159,7 +159,7 @@ class TestSCXAIModelMetadata: def test_scx_ai_models_synced_to_backup(self): - model_cost = self._load(("model_prices_and_context_window.json",)) + model_cost = self._load(("litellm/data/model_prices_and_context_window.json",)) backup = self._load(("litellm", "model_prices_and_context_window_backup.json")) for model in self.SCX_MODELS: assert model in backup, f"{model} missing from backup json" diff --git a/tests/unit/llms/openai_like/test_streamlake_provider.py b/tests/unit/llms/openai_like/test_streamlake_provider.py index f1a7b9edba5..8162d4700b8 100644 --- a/tests/unit/llms/openai_like/test_streamlake_provider.py +++ b/tests/unit/llms/openai_like/test_streamlake_provider.py @@ -252,7 +252,7 @@ def _streamlake_keys(cost_map: dict[str, object]) -> tuple[str, ...]: def test_root_and_backup_cost_maps_carry_the_same_streamlake_rows() -> None: - root: Final = json.loads((REPO_ROOT / "model_prices_and_context_window.json").read_text()) + root: Final = json.loads((REPO_ROOT / "litellm/data/model_prices_and_context_window.json").read_text()) backup: Final = json.loads((REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json").read_text()) assert _streamlake_keys(root) diff --git a/tests/unit/llms/openai_like/test_wally_provider.py b/tests/unit/llms/openai_like/test_wally_provider.py index ac730b5760f..e91c8fc3367 100644 --- a/tests/unit/llms/openai_like/test_wally_provider.py +++ b/tests/unit/llms/openai_like/test_wally_provider.py @@ -168,7 +168,7 @@ def test_wally_model_missing_from_cost_map_uses_provider_defaults(): def test_wally_backup_registry_mirrors_cost_map(): package_root: Final = Path(litellm.__file__).parent - cost_map: Final = json.loads((package_root.parent / "model_prices_and_context_window.json").read_text()) + cost_map: Final = json.loads((package_root.parent / "litellm/data/model_prices_and_context_window.json").read_text()) backup: Final = json.loads((package_root / "model_prices_and_context_window_backup.json").read_text()) wally_entries: Final = {name: entry for name, entry in cost_map.items() if name.startswith("wally/")} @@ -193,7 +193,7 @@ def test_wally_is_available_in_add_model_form(): def test_wally_supported_endpoints(): backup_path: Final = Path(litellm.__file__).parent / "provider_endpoints_support_backup.json" - root_path: Final = Path(litellm.__file__).parent.parent / "provider_endpoints_support.json" + root_path: Final = Path(litellm.__file__).parent.parent / "litellm/data/provider_endpoints_support.json" backup: Final = json.loads(backup_path.read_text())["providers"]["wally"]["endpoints"] root: Final = json.loads(root_path.read_text())["providers"]["wally"]["endpoints"] diff --git a/tests/unit/llms/perplexity/test_perplexity_cost_calculator.py b/tests/unit/llms/perplexity/test_perplexity_cost_calculator.py index 5e774b05207..d1a54461118 100644 --- a/tests/unit/llms/perplexity/test_perplexity_cost_calculator.py +++ b/tests/unit/llms/perplexity/test_perplexity_cost_calculator.py @@ -40,7 +40,7 @@ class TestPerplexityCostCalculator: # Load the model cost map try: - with open("model_prices_and_context_window.json", "r") as f: + with open("litellm/data/model_prices_and_context_window.json", "r") as f: model_cost_map = json.load(f) litellm.model_cost = model_cost_map except FileNotFoundError: diff --git a/tests/unit/llms/perplexity/test_perplexity_integration.py b/tests/unit/llms/perplexity/test_perplexity_integration.py index 670fe096278..b8a9f008468 100644 --- a/tests/unit/llms/perplexity/test_perplexity_integration.py +++ b/tests/unit/llms/perplexity/test_perplexity_integration.py @@ -31,7 +31,7 @@ class TestPerplexityIntegration: # Load the model cost map try: - with open("model_prices_and_context_window.json", "r") as f: + with open("litellm/data/model_prices_and_context_window.json", "r") as f: model_cost_map = json.load(f) litellm.model_cost = model_cost_map except FileNotFoundError: diff --git a/tests/unit/llms/vercel_ai_gateway/test_vercel_ai_gateway.py b/tests/unit/llms/vercel_ai_gateway/test_vercel_ai_gateway.py index 70b84c4d703..598551092c0 100755 --- a/tests/unit/llms/vercel_ai_gateway/test_vercel_ai_gateway.py +++ b/tests/unit/llms/vercel_ai_gateway/test_vercel_ai_gateway.py @@ -281,7 +281,7 @@ def test_vercel_ai_gateway_models_endpoint_failure(): def test_vercel_ai_gateway_glm46_cost_math(): """Test the cost math for glm-4.6""" - with open("model_prices_and_context_window.json", "r") as f: + with open("litellm/data/model_prices_and_context_window.json", "r") as f: litellm.model_cost = json.load(f) key = "vercel_ai_gateway/zai/glm-4.6" diff --git a/tests/unit/llms/vertex_ai/videos/test_vertex_video_transformation.py b/tests/unit/llms/vertex_ai/videos/test_vertex_video_transformation.py index ecf131f8215..87eb30ce53b 100644 --- a/tests/unit/llms/vertex_ai/videos/test_vertex_video_transformation.py +++ b/tests/unit/llms/vertex_ai/videos/test_vertex_video_transformation.py @@ -24,7 +24,7 @@ from litellm.types.videos.main import VideoObject VEO_31_LITE_VERTEX_MODEL = "vertex_ai/veo-3.1-lite-generate-001" ROOT_MODEL_COST_PATH = ( - Path(__file__).parents[5] / "model_prices_and_context_window.json" + Path(__file__).parents[5] / "litellm/data/model_prices_and_context_window.json" ) BACKUP_MODEL_COST_PATH = ( Path(__file__).parents[5] diff --git a/tests/unit/llms/xai/test_xai_cost_calculator.py b/tests/unit/llms/xai/test_xai_cost_calculator.py index 5219dba42ba..7b643593470 100644 --- a/tests/unit/llms/xai/test_xai_cost_calculator.py +++ b/tests/unit/llms/xai/test_xai_cost_calculator.py @@ -34,7 +34,7 @@ class TestXAICostCalculator: import json try: - with open("model_prices_and_context_window.json", "r") as f: + with open("litellm/data/model_prices_and_context_window.json", "r") as f: model_cost_map = json.load(f) litellm.model_cost = model_cost_map except FileNotFoundError: diff --git a/tests/unit/llms/xai/test_xai_model_registry.py b/tests/unit/llms/xai/test_xai_model_registry.py index a596afa963f..d64e13abd1f 100644 --- a/tests/unit/llms/xai/test_xai_model_registry.py +++ b/tests/unit/llms/xai/test_xai_model_registry.py @@ -10,7 +10,7 @@ from pathlib import Path import pytest REPO_ROOT = Path(__file__).parents[4] -PRICES_PATH = REPO_ROOT / "model_prices_and_context_window.json" +PRICES_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PRICES_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" # https://docs.x.ai/developers/model-capabilities/text/multi-agent diff --git a/tests/unit/proxy/common_utils/test_token_count_settings.py b/tests/unit/proxy/common_utils/test_token_count_settings.py index 68910f52b02..9b7e1a14f14 100644 --- a/tests/unit/proxy/common_utils/test_token_count_settings.py +++ b/tests/unit/proxy/common_utils/test_token_count_settings.py @@ -19,7 +19,7 @@ _DEFAULT: Final = { "token_count_framing": 97, "token_count_model": {"model": "anthropic.claude-opus-5-5", "region": "us-east-1"}, } -_COST_MAP: Final = Path(__file__).parents[4] / "model_prices_and_context_window.json" +_COST_MAP: Final = Path(__file__).parents[4] / "litellm/data/model_prices_and_context_window.json" def _in_us_west_2() -> str: diff --git a/tests/unit/proxy/guardrails/test_content_filter_path_traversal.py b/tests/unit/proxy/guardrails/test_content_filter_path_traversal.py index b796c2d3a6d..ea12cff1644 100644 --- a/tests/unit/proxy/guardrails/test_content_filter_path_traversal.py +++ b/tests/unit/proxy/guardrails/test_content_filter_path_traversal.py @@ -60,7 +60,7 @@ class TestContentFilterPathTraversal: def test_every_category_file_published_in_policy_templates_resolves(self, monkeypatch, tmp_path): """The proxy fetches policy_templates.json from main, so every path in it must exist in the package.""" monkeypatch.chdir(tmp_path) - published = os.path.join(os.path.dirname(os.path.dirname(litellm.__file__)), "policy_templates.json") + published = os.path.join(os.path.dirname(os.path.dirname(litellm.__file__)), "litellm/data/policy_templates.json") category_files = re.findall(r'"category_file":\s*"([^"]+)"', open(published).read()) assert category_files guardrail = self._get_guardrail() diff --git a/tests/unit/proxy/proxy_server/test_routes_model_cost_map.py b/tests/unit/proxy/proxy_server/test_routes_model_cost_map.py index 0c4c5d82c18..43e3ae1a204 100644 --- a/tests/unit/proxy/proxy_server/test_routes_model_cost_map.py +++ b/tests/unit/proxy/proxy_server/test_routes_model_cost_map.py @@ -29,7 +29,7 @@ from .conftest import VOLATILE_KEYS, normalize _VOLATILE = VOLATILE_KEYS | frozenset({"timestamp"}) _SERVED_ETAG = 'W/"cost-map-etag"' -_ROOT_COST_MAP = Path(__file__).resolve().parents[4] / "model_prices_and_context_window.json" +_ROOT_COST_MAP = Path(__file__).resolve().parents[4] / "litellm/data/model_prices_and_context_window.json" # --------------------------------------------------------------------------- diff --git a/tests/unit/rust_bridge/test_verify_linux_native_wheel.py b/tests/unit/rust_bridge/test_verify_linux_native_wheel.py index 9d9ebb6e6c0..395d1f4970c 100644 --- a/tests/unit/rust_bridge/test_verify_linux_native_wheel.py +++ b/tests/unit/rust_bridge/test_verify_linux_native_wheel.py @@ -149,6 +149,9 @@ def test_accepts_expected_release_wheel_tags(tmp_path: Path) -> None: "litellm/runtime/backend/main.py", "litellm/runtime/gateway/launch.py", "litellm/schema.prisma", + "litellm/data/model_prices_and_context_window.json", + "litellm/data/policy_templates.json", + "litellm/data/provider_endpoints_support.json", ), ) def test_rejects_repository_sources_in_the_wheel( diff --git a/tests/unit/test_azure_ai_grok_4_3_model_metadata.py b/tests/unit/test_azure_ai_grok_4_3_model_metadata.py index 9d9f392a149..008e053cb0b 100644 --- a/tests/unit/test_azure_ai_grok_4_3_model_metadata.py +++ b/tests/unit/test_azure_ai_grok_4_3_model_metadata.py @@ -18,7 +18,7 @@ def _load_model_cost(path: Path) -> dict: @pytest.fixture(autouse=True) def reload_model_costs(): original_model_cost = litellm.model_cost - json_path = Path(__file__).parents[2] / "model_prices_and_context_window.json" + json_path = Path(__file__).parents[2] / "litellm/data/model_prices_and_context_window.json" litellm.model_cost = _load_model_cost(json_path) get_model_info.cache_clear() yield @@ -28,7 +28,7 @@ def reload_model_costs(): def test_azure_ai_grok_4_3_backup_matches_main(): repo_root = Path(__file__).parents[2] - main_path = repo_root / "model_prices_and_context_window.json" + main_path = repo_root / "litellm/data/model_prices_and_context_window.json" backup_path = repo_root / "litellm" / "model_prices_and_context_window_backup.json" main_cost = _load_model_cost(main_path) diff --git a/tests/unit/test_azure_ai_grok_4_6_model_metadata.py b/tests/unit/test_azure_ai_grok_4_6_model_metadata.py index 43df9a648c2..70d7a856586 100644 --- a/tests/unit/test_azure_ai_grok_4_6_model_metadata.py +++ b/tests/unit/test_azure_ai_grok_4_6_model_metadata.py @@ -38,7 +38,7 @@ def test_azure_ai_grok_4_6_is_priced_and_routed() -> None: def test_azure_ai_grok_4_6_entry_source_and_backup_match() -> None: - main_entry = _cost_map_entry(REPO_ROOT / "model_prices_and_context_window.json") + main_entry = _cost_map_entry(REPO_ROOT / "litellm/data/model_prices_and_context_window.json") backup_entry = _cost_map_entry(REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json") assert backup_entry == main_entry diff --git a/tests/unit/test_baseten_glm_5_3_model_metadata.py b/tests/unit/test_baseten_glm_5_3_model_metadata.py index f573c79434a..14c2290f8ca 100644 --- a/tests/unit/test_baseten_glm_5_3_model_metadata.py +++ b/tests/unit/test_baseten_glm_5_3_model_metadata.py @@ -6,7 +6,7 @@ import pytest import litellm REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" MODEL = "baseten/zai-org/GLM-5.3" diff --git a/tests/unit/test_bedrock_marengo_embed_3_model_metadata.py b/tests/unit/test_bedrock_marengo_embed_3_model_metadata.py index 21e9b26d996..44c5da3f4e5 100644 --- a/tests/unit/test_bedrock_marengo_embed_3_model_metadata.py +++ b/tests/unit/test_bedrock_marengo_embed_3_model_metadata.py @@ -6,7 +6,7 @@ import pytest from litellm.constants import bedrock_embedding_models REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" BASE_MODEL = "twelvelabs.marengo-embed-3-0-v1:0" diff --git a/tests/unit/test_cerebras_llama_model_metadata.py b/tests/unit/test_cerebras_llama_model_metadata.py index 5b51e9e2f24..7d4780fd815 100644 --- a/tests/unit/test_cerebras_llama_model_metadata.py +++ b/tests/unit/test_cerebras_llama_model_metadata.py @@ -20,7 +20,7 @@ import litellm @pytest.fixture(scope="module") def model_cost_maps(): root = Path(__file__).resolve().parents[2] - main_path = root / "model_prices_and_context_window.json" + main_path = root / "litellm/data/model_prices_and_context_window.json" backup_path = root / "litellm" / "model_prices_and_context_window_backup.json" with open(main_path, "r", encoding="utf-8") as f: diff --git a/tests/unit/test_ci_path_filter.py b/tests/unit/test_ci_path_filter.py index bd90c40524d..3ce734d68a9 100644 --- a/tests/unit/test_ci_path_filter.py +++ b/tests/unit/test_ci_path_filter.py @@ -94,21 +94,21 @@ CI = [".github/workflows/test-unit.yml"] ("backend", BACKEND + CLIENT, "run"), ("client", BACKEND + CLIENT, "run"), ("ui", BACKEND + CLIENT, "run"), - ("cost-map-only", ["model_prices_and_context_window.json"], "run"), + ("cost-map-only", ["litellm/data/model_prices_and_context_window.json"], "run"), ("cost-map-only", ["litellm/model_prices_and_context_window_backup.json"], "run"), ( "cost-map-only", - ["model_prices_and_context_window.json", "tests/unit/proxy/test_y.py"], + ["litellm/data/model_prices_and_context_window.json", "tests/unit/proxy/test_y.py"], "run", ), ( "cost-map-only", - ["model_prices_and_context_window.json", "litellm/utils.py"], + ["litellm/data/model_prices_and_context_window.json", "litellm/utils.py"], "skip", ), ("cost-map-only", ["tests/unit/proxy/test_y.py"], "skip"), - ("cost-map-only", ["model_prices_and_context_window.json", "docs/pricing.md"], "skip"), - ("cost-map-only", ["model_prices_and_context_window.json", "docs/foo.mdx"], "skip"), + ("cost-map-only", ["litellm/data/model_prices_and_context_window.json", "docs/pricing.md"], "skip"), + ("cost-map-only", ["litellm/data/model_prices_and_context_window.json", "docs/foo.mdx"], "skip"), ("cost-map-only", [], "skip"), ("cost-map-only", DOCS, "skip"), ], diff --git a/tests/unit/test_claude_fable_5_config.py b/tests/unit/test_claude_fable_5_config.py index 2157364efb3..b5e1b29df6f 100644 --- a/tests/unit/test_claude_fable_5_config.py +++ b/tests/unit/test_claude_fable_5_config.py @@ -23,7 +23,7 @@ REPO_ROOT = os.path.join(os.path.dirname(__file__), "../..") def _load_root_cost_map() -> dict: - json_path = os.path.join(REPO_ROOT, "model_prices_and_context_window.json") + json_path = os.path.join(REPO_ROOT, "litellm/data/model_prices_and_context_window.json") with open(json_path) as f: return json.load(f) diff --git a/tests/unit/test_claude_haiku_5_5_config.py b/tests/unit/test_claude_haiku_5_5_config.py index 99c7d167df4..0f5b6783cf3 100644 --- a/tests/unit/test_claude_haiku_5_5_config.py +++ b/tests/unit/test_claude_haiku_5_5_config.py @@ -45,7 +45,7 @@ def local_model_cost_map(monkeypatch: pytest.MonkeyPatch) -> Iterator[None]: def _load_root_cost_map() -> dict[str, dict[str, object]]: - json_path: Final = os.path.join(REPO_ROOT, "model_prices_and_context_window.json") + json_path: Final = os.path.join(REPO_ROOT, "litellm/data/model_prices_and_context_window.json") with open(json_path) as f: return cast(dict[str, dict[str, object]], json.load(f)) diff --git a/tests/unit/test_claude_opus_5_config.py b/tests/unit/test_claude_opus_5_config.py index bac4beb494c..7823c8bad04 100644 --- a/tests/unit/test_claude_opus_5_config.py +++ b/tests/unit/test_claude_opus_5_config.py @@ -26,7 +26,7 @@ REPO_ROOT = os.path.join(os.path.dirname(__file__), "../..") def _load_root_cost_map() -> dict: - json_path = os.path.join(REPO_ROOT, "model_prices_and_context_window.json") + json_path = os.path.join(REPO_ROOT, "litellm/data/model_prices_and_context_window.json") with open(json_path) as f: return json.load(f) diff --git a/tests/unit/test_claude_sonnet_5_config.py b/tests/unit/test_claude_sonnet_5_config.py index eb040ceae1b..c9c00d1e004 100644 --- a/tests/unit/test_claude_sonnet_5_config.py +++ b/tests/unit/test_claude_sonnet_5_config.py @@ -26,7 +26,7 @@ REPO_ROOT = os.path.join(os.path.dirname(__file__), "../..") def _load_root_cost_map() -> dict: - json_path = os.path.join(REPO_ROOT, "model_prices_and_context_window.json") + json_path = os.path.join(REPO_ROOT, "litellm/data/model_prices_and_context_window.json") with open(json_path) as f: return json.load(f) diff --git a/tests/unit/test_cloudflare_workers_ai_model_metadata.py b/tests/unit/test_cloudflare_workers_ai_model_metadata.py index 4e770be7c3e..dfbd6373a67 100644 --- a/tests/unit/test_cloudflare_workers_ai_model_metadata.py +++ b/tests/unit/test_cloudflare_workers_ai_model_metadata.py @@ -19,7 +19,7 @@ import litellm ROOT_MAP = os.path.join( os.path.dirname(os.path.dirname(litellm.__file__)), - "model_prices_and_context_window.json", + "litellm/data/model_prices_and_context_window.json", ) BACKUP_MAP = os.path.join( os.path.dirname(litellm.__file__), diff --git a/tests/unit/test_daybreak_model_metadata.py b/tests/unit/test_daybreak_model_metadata.py index 79149b84f0b..b46474f2c36 100644 --- a/tests/unit/test_daybreak_model_metadata.py +++ b/tests/unit/test_daybreak_model_metadata.py @@ -4,7 +4,7 @@ from pathlib import Path import pytest REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" DAYBREAK_MODELS = ( diff --git a/tests/unit/test_elevenlabs_tts_pricing.py b/tests/unit/test_elevenlabs_tts_pricing.py index 16f726b9d6c..0d78aa8db08 100644 --- a/tests/unit/test_elevenlabs_tts_pricing.py +++ b/tests/unit/test_elevenlabs_tts_pricing.py @@ -34,7 +34,7 @@ def local_model_cost_map(monkeypatch): @pytest.mark.parametrize("model, per_character", PRICES.items()) def test_metadata_and_backup(model, per_character): - main = json.loads((REPO_ROOT / "model_prices_and_context_window.json").read_text()) + main = json.loads((REPO_ROOT / "litellm/data/model_prices_and_context_window.json").read_text()) backup = json.loads((REPO_ROOT / "litellm/model_prices_and_context_window_backup.json").read_text()) assert main[model] == backup[model] info = litellm.get_model_info(model) diff --git a/tests/unit/test_fireworks_serverless_model_costs.py b/tests/unit/test_fireworks_serverless_model_costs.py index 164f32fec1c..3e4fc16d118 100644 --- a/tests/unit/test_fireworks_serverless_model_costs.py +++ b/tests/unit/test_fireworks_serverless_model_costs.py @@ -19,7 +19,7 @@ from litellm.utils import get_model_info @pytest.fixture(scope="module") def model_data(): - json_path = os.path.join(os.path.dirname(__file__), "../../model_prices_and_context_window.json") + json_path = os.path.join(os.path.dirname(__file__), "../../litellm/data/model_prices_and_context_window.json") with open(json_path) as f: return json.load(f) diff --git a/tests/unit/test_gemini_3_1_flash_lite_image_pricing.py b/tests/unit/test_gemini_3_1_flash_lite_image_pricing.py index 250b587aaf1..40bd726346e 100644 --- a/tests/unit/test_gemini_3_1_flash_lite_image_pricing.py +++ b/tests/unit/test_gemini_3_1_flash_lite_image_pricing.py @@ -6,7 +6,7 @@ import pytest from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" UNPREFIXED = "gemini-3.1-flash-lite-image" diff --git a/tests/unit/test_gemini_4_argon_model_metadata.py b/tests/unit/test_gemini_4_argon_model_metadata.py index d4c3a69ca20..cf1af8ba7aa 100644 --- a/tests/unit/test_gemini_4_argon_model_metadata.py +++ b/tests/unit/test_gemini_4_argon_model_metadata.py @@ -36,7 +36,7 @@ def test_gemini_4_argon_routes_to_its_provider_on_the_thinking_level_path( @pytest.mark.parametrize("model", [row[0] for row in MODELS]) def test_gemini_4_argon_entry_source_and_backup_match(model: str) -> None: - main_entry = _cost_map_entry(REPO_ROOT / "model_prices_and_context_window.json", model) + main_entry = _cost_map_entry(REPO_ROOT / "litellm/data/model_prices_and_context_window.json", model) backup_entry = _cost_map_entry(REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json", model) assert backup_entry == main_entry diff --git a/tests/unit/test_gemini_tts_native_audio_pricing.py b/tests/unit/test_gemini_tts_native_audio_pricing.py index 3dcb18c1466..697e20c4adb 100644 --- a/tests/unit/test_gemini_tts_native_audio_pricing.py +++ b/tests/unit/test_gemini_tts_native_audio_pricing.py @@ -8,7 +8,7 @@ import pytest import litellm REPO_ROOT: Final = Path(__file__).parents[2] -MAIN_PATH: Final = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH: Final = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH: Final = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" FLASH_TTS_KEYS: Final = ("gemini-2.5-flash-preview-tts", "gemini/gemini-2.5-flash-preview-tts") diff --git a/tests/unit/test_gpt_5_4_model_metadata.py b/tests/unit/test_gpt_5_4_model_metadata.py index 294d0757069..f3dbef1a0c8 100644 --- a/tests/unit/test_gpt_5_4_model_metadata.py +++ b/tests/unit/test_gpt_5_4_model_metadata.py @@ -5,7 +5,7 @@ from pathlib import Path import pytest REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" DOCUMENTED_MAX_INPUT_TOKENS = 272000 diff --git a/tests/unit/test_gpt_5_5_model_metadata.py b/tests/unit/test_gpt_5_5_model_metadata.py index 6a64627f1a2..73fade0dd94 100644 --- a/tests/unit/test_gpt_5_5_model_metadata.py +++ b/tests/unit/test_gpt_5_5_model_metadata.py @@ -5,7 +5,7 @@ from pathlib import Path def test_azure_ai_gpt_5_5_backup_matches_main(): """Ensure the bundled model cost map stays in sync with the canonical file.""" repo_root = Path(__file__).parents[2] - main_path = repo_root / "model_prices_and_context_window.json" + main_path = repo_root / "litellm/data/model_prices_and_context_window.json" backup_path = repo_root / "litellm" / "model_prices_and_context_window_backup.json" with open(main_path) as f: diff --git a/tests/unit/test_gpt_realtime_mode.py b/tests/unit/test_gpt_realtime_mode.py index c6f6d68dcc9..ce9e1712ed5 100644 --- a/tests/unit/test_gpt_realtime_mode.py +++ b/tests/unit/test_gpt_realtime_mode.py @@ -46,7 +46,7 @@ def test_realtime_is_a_valid_mode_literal(): def test_backup_matches_main_for_realtime_models(): repo_root = Path(__file__).parents[2] - with open(repo_root / "model_prices_and_context_window.json") as f: + with open(repo_root / "litellm/data/model_prices_and_context_window.json") as f: main_cost = json.load(f) with open(repo_root / "litellm" / "model_prices_and_context_window_backup.json") as f: backup_cost = json.load(f) diff --git a/tests/unit/test_mistral_large_4_model_metadata.py b/tests/unit/test_mistral_large_4_model_metadata.py index bfcd6690890..873a29a85da 100644 --- a/tests/unit/test_mistral_large_4_model_metadata.py +++ b/tests/unit/test_mistral_large_4_model_metadata.py @@ -26,7 +26,7 @@ def local_model_cost_map(monkeypatch): @pytest.mark.parametrize("model", MODELS) def test_metadata_and_backup(model): - main = json.loads((REPO_ROOT / "model_prices_and_context_window.json").read_text()) + main = json.loads((REPO_ROOT / "litellm/data/model_prices_and_context_window.json").read_text()) backup = json.loads((REPO_ROOT / "litellm/model_prices_and_context_window_backup.json").read_text()) assert main[model] == backup[model] == main[MODELS[0]] info = litellm.get_model_info(model) diff --git a/tests/unit/test_mistral_medium_3_5_model_metadata.py b/tests/unit/test_mistral_medium_3_5_model_metadata.py index ab38d8a9118..887c7a6598c 100644 --- a/tests/unit/test_mistral_medium_3_5_model_metadata.py +++ b/tests/unit/test_mistral_medium_3_5_model_metadata.py @@ -4,7 +4,7 @@ from pathlib import Path import pytest REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" MEDIUM_3_5_MODELS = ( diff --git a/tests/unit/test_mistral_small_4_0_model_metadata.py b/tests/unit/test_mistral_small_4_0_model_metadata.py index 182c444bac9..8ccfc5a45fa 100644 --- a/tests/unit/test_mistral_small_4_0_model_metadata.py +++ b/tests/unit/test_mistral_small_4_0_model_metadata.py @@ -4,7 +4,7 @@ from pathlib import Path import pytest REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" SMALL_4_0_MODELS = ( diff --git a/tests/unit/test_mistral_zai_glm_5_2_model_metadata.py b/tests/unit/test_mistral_zai_glm_5_2_model_metadata.py index c5fe247aa51..18463572f8f 100644 --- a/tests/unit/test_mistral_zai_glm_5_2_model_metadata.py +++ b/tests/unit/test_mistral_zai_glm_5_2_model_metadata.py @@ -6,7 +6,7 @@ import pytest import litellm REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" GLM_5_2_MODELS = ("mistral/zai-glm-5-2", "mistral/glm-5-2") diff --git a/tests/unit/test_model_prices_and_context_window.py b/tests/unit/test_model_prices_and_context_window.py index e195b970fd5..a707250bf73 100644 --- a/tests/unit/test_model_prices_and_context_window.py +++ b/tests/unit/test_model_prices_and_context_window.py @@ -18,7 +18,7 @@ from litellm.llms.openai_like.json_loader import JSONProviderRegistry from litellm.types.utils import SearchFreeRequests REPO_ROOT = Path(__file__).parents[2] -PRICES_PATH = REPO_ROOT / "model_prices_and_context_window.json" +PRICES_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PRICES_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" diff --git a/tests/unit/test_muse_ember_1_0_model_metadata.py b/tests/unit/test_muse_ember_1_0_model_metadata.py index a018c88c36d..7ebe7584d42 100644 --- a/tests/unit/test_muse_ember_1_0_model_metadata.py +++ b/tests/unit/test_muse_ember_1_0_model_metadata.py @@ -11,7 +11,7 @@ MUSE_EMBER = "meta/muse-ember-1.0" LONG_CONTEXT_THRESHOLD = 200_000 -def _load_cost_map(filename: str = "model_prices_and_context_window.json") -> dict: +def _load_cost_map(filename: str = "litellm/data/model_prices_and_context_window.json") -> dict: with open(Path(__file__).parents[2] / filename) as f: return json.load(f) diff --git a/tests/unit/test_muse_spark_1_1_model_metadata.py b/tests/unit/test_muse_spark_1_1_model_metadata.py index f55266a78d7..b249b30d362 100644 --- a/tests/unit/test_muse_spark_1_1_model_metadata.py +++ b/tests/unit/test_muse_spark_1_1_model_metadata.py @@ -16,7 +16,7 @@ def test_muse_spark_1_1_model_info(): def test_muse_spark_1_1_backup_matches_main(): """Ensure the bundled model cost map stays in sync with the canonical file.""" repo_root = Path(__file__).parents[2] - main_path = repo_root / "model_prices_and_context_window.json" + main_path = repo_root / "litellm/data/model_prices_and_context_window.json" backup_path = repo_root / "litellm" / "model_prices_and_context_window_backup.json" with open(main_path) as f: diff --git a/tests/unit/test_muse_spark_1_2_model_metadata.py b/tests/unit/test_muse_spark_1_2_model_metadata.py index 877fef456de..340e4dfff6d 100644 --- a/tests/unit/test_muse_spark_1_2_model_metadata.py +++ b/tests/unit/test_muse_spark_1_2_model_metadata.py @@ -15,7 +15,7 @@ PRICING = ( ) -def _load_cost_map(filename: str = "model_prices_and_context_window.json") -> dict: +def _load_cost_map(filename: str = "litellm/data/model_prices_and_context_window.json") -> dict: with open(Path(__file__).parents[2] / filename) as f: return json.load(f) diff --git a/tests/unit/test_muse_spark_1_3_model_metadata.py b/tests/unit/test_muse_spark_1_3_model_metadata.py index 468294ba91c..1db139d9e95 100644 --- a/tests/unit/test_muse_spark_1_3_model_metadata.py +++ b/tests/unit/test_muse_spark_1_3_model_metadata.py @@ -19,7 +19,7 @@ PRICING = ( ) -def _load_cost_map(filename: str = "model_prices_and_context_window.json") -> dict: +def _load_cost_map(filename: str = "litellm/data/model_prices_and_context_window.json") -> dict: with open(Path(__file__).parents[2] / filename) as f: return json.load(f) diff --git a/tests/unit/test_openai_service_tier_long_context_pricing.py b/tests/unit/test_openai_service_tier_long_context_pricing.py index 9777af1af70..ab4cdaccf9e 100644 --- a/tests/unit/test_openai_service_tier_long_context_pricing.py +++ b/tests/unit/test_openai_service_tier_long_context_pricing.py @@ -10,7 +10,7 @@ from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_toke from litellm.types.utils import PromptTokensDetailsWrapper, Usage REPO_ROOT = Path(__file__).parents[2] -MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" +MAIN_PATH = REPO_ROOT / "litellm/data/model_prices_and_context_window.json" BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" FLEX_LONG_CONTEXT = { diff --git a/tests/unit/test_replicate_model_key_format.py b/tests/unit/test_replicate_model_key_format.py index 77ae5e1b069..870a5f1ba18 100644 --- a/tests/unit/test_replicate_model_key_format.py +++ b/tests/unit/test_replicate_model_key_format.py @@ -7,7 +7,7 @@ import pytest @pytest.fixture() def model_cost() -> dict[str, Any]: - json_path = Path(__file__).parents[2] / "model_prices_and_context_window.json" + json_path = Path(__file__).parents[2] / "litellm/data/model_prices_and_context_window.json" with open(json_path, encoding="utf-8") as f: return json.load(f) @@ -22,7 +22,7 @@ def test_replicate_models_have_valid_key_prefix(model_cost: dict[str, Any]) -> N def test_replicate_backup_matches_main() -> None: repo_root = Path(__file__).parents[2] - main_path = repo_root / "model_prices_and_context_window.json" + main_path = repo_root / "litellm/data/model_prices_and_context_window.json" backup_path = repo_root / "litellm" / "model_prices_and_context_window_backup.json" with open(main_path, encoding="utf-8") as f: diff --git a/tests/unit/test_sambanova_model_metadata.py b/tests/unit/test_sambanova_model_metadata.py index 20f34f9f3cc..b46f60a7092 100644 --- a/tests/unit/test_sambanova_model_metadata.py +++ b/tests/unit/test_sambanova_model_metadata.py @@ -6,7 +6,7 @@ from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider def test_sambanova_minimax_m27_model_info(): model = "sambanova/MiniMax-M2.7" - json_path = Path(__file__).parents[2] / "model_prices_and_context_window.json" + json_path = Path(__file__).parents[2] / "litellm/data/model_prices_and_context_window.json" with open(json_path) as f: model_cost = json.load(f) diff --git a/tests/unit/test_together_ai_model_metadata.py b/tests/unit/test_together_ai_model_metadata.py index 8246277d475..bd991c7f1a2 100644 --- a/tests/unit/test_together_ai_model_metadata.py +++ b/tests/unit/test_together_ai_model_metadata.py @@ -70,7 +70,7 @@ DEPRECATED_MODELS: Final = { @pytest.fixture(scope="module") def cost_map() -> CostMap: - with open(REPO_ROOT / "model_prices_and_context_window.json") as f: + with open(REPO_ROOT / "litellm/data/model_prices_and_context_window.json") as f: return COST_MAP_ADAPTER.validate_python(json.load(f)) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index eaa0b3970bd..bc27ec20d17 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -1432,7 +1432,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid(): If this test fails after you update the json, you need to update the schema or correct the change you made. """ - prod_json = os.path.join(os.path.dirname(__file__), "..", "..", "model_prices_and_context_window.json") + prod_json = os.path.join(os.path.dirname(__file__), "..", "..", "litellm/data/model_prices_and_context_window.json") with open(prod_json, "r") as model_prices_file: actual_json = json.load(model_prices_file) assert isinstance(actual_json, dict) @@ -1512,7 +1512,7 @@ def test_max_tokens_consistency(): from pathlib import Path # Load the model configuration - config_path = Path(__file__).parent.parent.parent / "model_prices_and_context_window.json" + config_path = Path(__file__).parent.parent.parent / "litellm/data/model_prices_and_context_window.json" with open(config_path, "r") as f: models = json.load(f) diff --git a/tests/unit/test_xai_grok_4_3_model_metadata.py b/tests/unit/test_xai_grok_4_3_model_metadata.py index 50be24ba63d..4f290bf5477 100644 --- a/tests/unit/test_xai_grok_4_3_model_metadata.py +++ b/tests/unit/test_xai_grok_4_3_model_metadata.py @@ -5,7 +5,7 @@ from pathlib import Path def test_xai_grok_4_3_backup_matches_main(): """Ensure the bundled model cost map stays in sync with the canonical file.""" repo_root = Path(__file__).parents[2] - main_path = repo_root / "model_prices_and_context_window.json" + main_path = repo_root / "litellm/data/model_prices_and_context_window.json" backup_path = repo_root / "litellm" / "model_prices_and_context_window_backup.json" with open(main_path) as f: