litellm/scripts
ishaan-berri 5ed7ec8511
fix(lens): price agent traces by joining gen_ai.response.id to spend logs (#44738)
* fix(lens): price agent traces by joining gen_ai.response.id to spend logs

Trace spend now joins each model call to spend_logs on one key: the
span's response id (gen_ai.response.id or the id the normalizers read
from OpenInference/LangChain output) against spend_logs.response_id or
the upstream id embedded in a managed resp_ id. The litellm.call_id and
traceparent transport join paths and the per-row ownership gate are
removed; the spend SQL still restricts rows to what the reader can see.

A run with some unpriced calls now reports the sum of its priced calls
plus priced_calls, instead of an unknown total.

* test(lens): cover response id spend join and partial trace totals

* chore(lens): regenerate trace types for priced_calls

* feat(lens): show partial run cost as a lower bound with priced call count

* fix(lens): treat litellm.call_id as the same assigned call id for spend joins

The id LiteLLM assigned to a call is either the response id it returned
(gen_ai.response.id -> spend_logs.response_id) or its gateway call id
(litellm.call_id -> spend_logs.litellm_call_id). Both are exact ids the
gateway mints and logs, so the join stays one rule. Transport span
matching and the ownership gate stay removed.

* test(lens): cover litellm.call_id spend joins and restore captured totals

* feat(lens): link each priced model call to its spend log

Spans gain spend_log_request_id, the spend_logs.request_id the call was
priced from, and spend_match, which says whether a model call matched or
why not (no assigned id on the span, no spend log with that id, or an
ambiguous match). A model call span is priced from the same ids as the
run total, so its cost and the total agree.

* test(lens): cover spend log links on model call spans

* chore(lens): regenerate trace types for spend log links

* feat(lens): open the matched spend log from an LLM step

An LLM step's header now shows a Spend log chip with the matched
request id and cost; clicking it opens the request log drawer over the
run, fetched by the exact spend_logs.request_id instead of the span's
own response id. Unpriced steps say why (no assigned id on the span, or
no spend log with it). Tree rows show each model call's cost, and a
partial run cost shows its priced call count inline.

* test(lens): cover the spend log link and unmatched cost reasons

* feat(lens): show the spend log link as a bordered LiteLLM Spend Log button

* feat(lens): add a back link from the spend log drawer to the agent trace

* feat(lens): label the spend log back link Back to Lens trace with the Lens icon

* fix(lens): ignore assigned ids that name no spend log when pricing a call

An id that names no row no longer vetoes the call, so a span carrying
both a response id and a call id still prices from a spend row logged
before litellm_call_id existed. An id naming two or more rows makes the
call ambiguous, and the match reason comes from the same per-id result,
so a single matched row with no cost is reported as matched.

* fix(lens): price a trace only from spend logs in its own team

A reader with several teams could see the same assigned id in another
team's spend log; only rows from the trace's team now price it. The
user and key ownership gate stays removed.

* perf(lens): resolve each model call's spend once per trace

Model call matches are computed once when the trace is resolved and
looked up by span index, instead of scanning the model call list for
every span and walking the graph again for spans, agents and the run
total.

* fix(lens): hide a step's Cost fact only when its spend log link shows the cost

* chore(lens): drop narrative doc comments from the spend join

* fix(lens): price a model call only when its ids agree on one spend log per span

* fix(lens): keep pricing spend logs written before litellm_call_id by their request id

* fix(lens): price every attempt a model call's ids name when they agree
2026-10-06 19:55:26 +00:00
..
adaptive_router_demo fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
health_check fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
trace_codegen fix(lens): price agent traces by joining gen_ai.response.id to spend logs (#44738) 2026-10-06 19:55:26 +00:00
auto-close-duplicates.test.ts fix(ci): keep earlier objections when the duplicate notice is re-posted 2026-08-29 17:30:39 -04:00
auto-close-duplicates.ts ci: classify new issues into domain, provider, kind, priority and lift labels 2026-09-18 11:37:55 -07:00
benchmark_anthropic_messages_perf.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
benchmark_chat_completions_perf.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
benchmark_mock.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
benchmark_model_response_creator.py
benchmark_ocr_callbacks.py refactor(ocr): complete native lifecycle and preserve Azure auth (#40734) 2026-09-12 11:56:49 -07:00
benchmark_proxy_vs_provider.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
benchmark_streaming_chunk_overhead.py
budget_ratchet_check.py test(ci): prove RULE_CODES by running every checker rule 2026-09-20 08:27:02 +00:00
check_mcp_operation_boundary.py refactor(mcp): extract explicit operation context and dispatch 2026-09-21 12:24:15 -07:00
check_mcp_sdk_install.py fix(mcp): preserve legacy behavior on SDK2 and streamline verification 2026-09-18 22:28:31 -07:00
check_test_quality.py fix(ci): excuse retired test-quality rules in the budget ratchet 2026-09-20 08:12:39 +00:00
check_type_discipline.py chore(lint): remove the LIT002 mutable-construction rule (#43971) 2026-10-01 12:24:02 -07:00
classify-issue.test.ts fix(issue-classifier): queue runs per issue and judge edits by live labels 2026-09-18 11:37:55 -07:00
classify-issue.ts fix(issue-classifier): queue runs per issue and judge edits by live labels 2026-09-18 11:37:55 -07:00
comment-fixed-issue.test.ts chore(ci): drop litellm_internal_staging and litellm_oss_staging references, main is the only trunk (#42745) 2026-09-23 08:14:11 -07:00
comment-fixed-issue.ts feat(ci): close open pull requests superseded by a merged fix on their linked issue (#42609) 2026-09-22 18:24:35 -07:00
create_litellm_branch.ps1
create_litellm_branch.sh
create_team_key_and_submit_guardrail.sh
default_branch.py ci: follow the default branch in development tooling 2026-09-07 14:34:45 -07:00
eval_compression.py
flag-duplicate-issue.test.ts ci(duplicate-check): drop the unused considered field from the verdict schema 2026-09-13 15:41:30 -07:00
flag-duplicate-issue.ts ci(duplicate-check): only warn about the auto close the sweep will actually do 2026-09-12 20:27:37 -07:00
gate_slot_lock.py refactor(make): stop queueing bootstrap for a machine-wide gate slot 2026-08-15 21:53:28 +00:00
generate_trace_types.py perf(types): defer pydantic schema builds via shared LiteLLMBaseModel (#44720) 2026-10-05 22:10:08 -07:00
install-cli.sh
install.sh
install_git_hooks.sh build(lint): rename make pre-commit to make check with a working-tree fallback 2026-08-08 03:25:35 -07:00
issue-labels.ts ci(issue-classifier): name every workflow, script and job after the issue it works on 2026-09-18 11:37:55 -07:00
label-issue.test.ts ci(issue-classifier): parse only form headings and keep the claude code label 2026-09-18 11:37:55 -07:00
label-issue.ts ci(issue-classifier): name every workflow, script and job after the issue it works on 2026-09-18 11:37:55 -07:00
lens_dev.sh fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
mock_bedrock_passthrough_target.py
mock_grayswan_timeout_server.py
mutation_report.py fix: address cross-version CI failures 2026-09-02 14:17:19 -07:00
pre_commit_lint.sh refactor(mcp): extract explicit operation context and dispatch 2026-09-21 12:24:15 -07:00
prisma_generate_if_needed.py fix(lint): generate the prisma client into the gate-owned venv 2026-08-06 01:54:26 -07:00
quickstart.ps1 feat(docker): add a Windows quickstart in PowerShell, and a styled terminal for both quickstarts (#44310) 2026-10-03 13:35:32 -07:00
quickstart.sh feat(docker): add a Windows quickstart in PowerShell, and a styled terminal for both quickstarts (#44310) 2026-10-03 13:35:32 -07:00
ruff_strict_gate.py ci: follow the default branch in development tooling 2026-09-07 14:34:45 -07:00
run_tracing_proxy_local.sh feat: improve Lens dev seeding and live UI (#44468) 2026-10-04 01:03:11 +00:00
seed_request_logs.py refactor(lens): storage-independent trace reads, shared keyset pager, typed read failures (#44422) 2026-10-04 12:39:47 -07:00
seed_tracing_fixtures.py fix(ci): namespace claude session ids in tracing seeds and allowlist /v1/logs on backend (#44761) 2026-10-05 19:39:12 -07:00
sync-issue-labels.test.ts ci(issue-classifier): name every workflow, script and job after the issue it works on 2026-09-18 11:37:55 -07:00
sync-issue-labels.ts ci(issue-classifier): name every workflow, script and job after the issue it works on 2026-09-18 11:37:55 -07:00
sync_together_ai_models.py fix(together_ai): stop writing context_length as max_output_tokens in the serverless sync 2026-08-29 15:26:44 -07:00
test_agent_mcp_endpoints.sh
test_guardrails_register_endpoints.sh
test_quality_gate.py ci: follow the default branch in development tooling 2026-09-07 14:34:45 -07:00
test_tool_allowlist_script.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
tpm_headline_test.sh
type_check_gate.py chore(ci): drop litellm_internal_staging and litellm_oss_staging references, main is the only trunk (#42745) 2026-09-23 08:14:11 -07:00
type_discipline_gate.py chore(lint): remove the LIT002 mutable-construction rule (#43971) 2026-10-01 12:24:02 -07:00
verify_adaptive_router.py
with_dashboard_node.sh fix(bootstrap): fail fast when nvm cannot activate the pinned node 2026-08-04 21:18:58 -07:00