- Clearly separate the two tool formats: advisor_20260301 (native/proxy)
vs litellm_advisor function tool (chat completions with callback)
- Answer "how do I configure the stronger model?" inline where the user
first encounters each format
- Add supported providers table with native vs orchestration distinction
- Show AdvisorInterceptionLogger setup is required for litellm_advisor
function format in SDK usage
- Update proxy config example to use model_list deployment names
- Document provider_specific_fields.advisor_tool_results for chat completions
- Document server_tool_use + advisor_tool_result response blocks for messages
- Add max_uses, cost, and streaming behavior notes
- Remove tool_choice="required" from all examples (causes forced loops)
Made-with: Cursor
- Test Anthropic executor + OpenAI advisor via orchestration loop
- Test native Anthropic path preserved for claude-opus-4-6 advisor
- Test tool_choice is stripped from follow-up executor turns
- Test provider_specific_fields contains advisor_tool_results blocks
- Test _advisor_interception_converted_stream stays in litellm_params
- Test wildcard router deployment lookup for order fallback
Made-with: Cursor
Use get_model_list() instead of _get_all_deployments() so pattern-routed
model groups (e.g. openai/* -> openai/gpt-4.1-mini) are included when
computing the deployment order set for fallback logic.
Made-with: Cursor
Initialize AdvisorInterceptionLogger via initialize_from_proxy_config()
so default_advisor_model and enabled_providers from
litellm_settings.advisor_interception_params are picked up automatically
when using the proxy.
Add advisor_interception_config.yaml example showing the minimal config
needed to wire an advisor model to the proxy.
Made-with: Cursor
Propagate _advisor_interception_converted_stream from litellm_params into
model_call_details and convert the agentic non-streaming response back to a
fake stream when the flag is set, mirroring the existing websearch path.
Made-with: Cursor
- Skip agentic loop for Anthropic executor only when advisor is the
native-compatible claude-opus-4-6; all other advisor models use the
LiteLLM orchestration loop regardless of executor provider
- Convert litellm_advisor function tools to provider-native format only
when executor is Anthropic and advisor is claude-opus-4-6; otherwise
keep as OpenAI-compatible function tool for the orchestration loop
- Add _is_native_anthropic_advisor_model() to resolve proxy aliases
before checking native compatibility
- Inject server_tool_use + advisor_tool_result into provider_specific_fields
of the final ModelResponse to match Anthropic native response structure
- Move _advisor_interception_converted_stream flag into litellm_params
so it is never forwarded to the upstream LLM provider
- Strip tool_choice from optional_params on follow-up executor turns to
prevent forced advisor re-invocation loops
- Initialize AdvisorInterceptionLogger with default_advisor_model and
enabled_providers from proxy config via initialize_from_proxy_config()
Made-with: Cursor
- Run MessagesInterceptor checks before pre-request hooks so the
synthetic advisor tool is registered before any tool conversion pass
- AdvisorOrchestrationHandler resolves default_advisor_model from
litellm.advisor_interception_params when the tool definition omits it
- Sub-calls route through llm_router.acompletion() for proper credential
resolution across any provider
- Native Anthropic path preserved: if executor is Anthropic and advisor
is claude-opus-4-6 the request passes through unchanged
- Any other combination (Anthropic executor + non-Opus advisor, or
non-Anthropic executor) uses the LiteLLM orchestration loop
- Final response always includes server_tool_use and advisor_tool_result
content blocks matching Anthropic native format
- FakeAnthropicMessagesStreamIterator emits correct SSE events for those
new block types in streaming responses
- Normalize proxy aliases → canonical Anthropic model IDs before
native passthrough so tools.0.model is never a proxy alias
Made-with: Cursor
Ensure mixed advisor/non-advisor tool-call batches are detected and skipped safely, and prevent follow-up executor calls from reusing the parent litellm_call_id.
Made-with: Cursor
The data-testid attributes added to React components are not present
in the CI-built UI output. Switch to using getByRole and getByText
selectors which work with the rendered DOM regardless of build cache.
Add E2E tests covering:
- Test connection with bad credentials shows failure modal
- Adding a specific model and verifying it appears in All Models table
- Adding a wildcard route and verifying it appears in All Models table
- Verifying model dropdown shows provider-specific models (existing test updated)
Added data-testid attributes to UI components to support stable test selectors.
Tests verified passing 3/3 consecutive runs with zero flakiness.
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Waiting to run
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 30, 8) (push) Waiting to run
Reviewer flagged that cleanup failures were silently swallowed and
suggested asserting `delete.ok()`. While thinking through the fix, the
actual question turned out to be "does the cleanup matter at all?" —
and the answer is no.
The e2e runner (`run_e2e.sh`) spins up a fresh postgres container per
invocation and tears it down at the end, so every local and CI run
starts with an empty DB. Playwright retries share the same DB but each
attempt creates a new model with a unique `Date.now()` name and only
queries its own model, so orphans from failed attempts never collide
with later attempts or other tests. Nothing else in the suite reads
the all-models table.
Keeping the cleanup would also turn every write test into an implicit
delete test, coupling responsibilities and inflating runtime — which
is probably why `teams.spec.ts` (create a team), `keys.spec.ts`
(update key limits), etc. all leave their entities in place. Matching
that convention, drop the try/finally block and the `createdModelId`
tracking. 12 lines removed, no behavior change.
Covers the full write-path flow for team-scoped models on the Models +
Endpoints page: create via /model/new, click the row to open the detail
view, click Edit Settings, change TPM/RPM, click Save Changes, assert
the new values render back. Cleans up via /model/delete in finally so
reruns stay deterministic.
Requires store_model_in_db: true in the fixture general_settings so the
proxy accepts /model/new and /model/delete. No existing test in the
dashboard e2e suite reads the all-models table or hits the model CRUD
endpoints, so enabling the flag has no cross-test impact.
The suite was superseded by ui/litellm-dashboard/e2e_tests/ on 2026-04-08
and is no longer referenced by CircleCI, docs, or Makefile targets. Drop
the directory wholesale and remove the orphaned e2e:psql npm script that
pointed at its runner.
Updates the expected header text to "Guardrails Settings" to match
GuardrailSettingsView's rendering, and moves the mock guardrails
from team_info.guardrails (legacy top-level path that nothing
reads) to team_info.metadata.guardrails where the component
actually looks. Also tightens the assertion to verify the
individual guardrail names appear, not just the section header.
Previously these were silently dropped with a verbose warning, which
could break observability integrations without surfacing a clear error.
Now raises ValueError with remediation steps (configure server-side
or pass the resolved value) so callers get immediate, actionable feedback.
Converts GuardrailSettingsView from @tremor/react (Badge, Text) to
antd (Tag, plain spans) as part of the Tremor migration. Also
captures the "no new Tremor imports" rule in CLAUDE.md and expands
the existing note in AGENTS.md with the specific antd equivalents
and the yellow→gold gotcha.
Pulls the Global / Team-specific subsection rendering out of
TeamInfo.tsx into a shared GuardrailSettingsView component with
card and inline variants, used on both the team Overview tab
(inside the existing Tremor Card) and the Team Settings tab read
view. The Global subsection header now carries a GlobalOutlined
icon, and since the icon is load-bearing the edit-form chip
coloring is simplified to a single blue instead of green/blue.
The Team Settings tab's read view listed every team field except
guardrails. Adds a Guardrails entry after Status with the same
Global / Team-specific subsections used on the Overview tab, so
the kill switch state and per-section membership are visible
without entering edit mode.
Replaces the flat guardrails list with two subsections under the
Guardrails card, so the global vs. team-specific distinction is
carried by the section headers instead of per-badge markers. The
kill-switch state now renders in place of the Global subsection as
"Bypassed for this team", and the separate "Disable Global
Guardrails" field with its confusing "Disabled - Global guardrails
active" badge is removed.
Addresses a11y feedback — global vs. non-global guardrails were
distinguished only by color (green vs. blue). Adds GlobalOutlined
next to global guardrails in (1) the selected-chip tagRender, (2)
the dropdown OptGroup label, and (3) the team info read view badge.
The blog CSS selectors for dark mode used descendant selectors like
[data-theme='dark'] .blog-wrapper which never matched because both
data-theme and .blog-wrapper are applied to the same <html> element
by Docusaurus. Fixed by using compound selectors (no space):
[data-theme='dark'].blog-wrapper.
Also added missing dark-mode overrides for:
- pre/code blocks in blog posts
- link colors in blog posts
- marquee items, separators, and labels on blog list page
- pagination links on blog list page
- meta text and author separators on blog list page
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Krrish Dholakia <krrish-berri-2@users.noreply.github.com>
Brings the date-range branch in line with the non-date-range branch which
already hashes sk- prefixed tokens before querying. Adds coverage for
filter-combination behavior in view_spend_logs.
- Add LITELLM_OIDC_ALLOWED_CREDENTIAL_DIRS to the environment variables
reference so the documentation test passes.
- Annotate the values variable in _reject_os_environ_references so it
accepts both dict.values() and list iterables.
- Log a warning when dropping callback params that carry os.environ/
references so operators notice the misconfiguration.
- Require absolute paths in oidc/file/ and correct the documented
example to use the leading-slash form.
- Drop the unused return value from _reject_os_environ_references.