Commit graph

6 commits

Author SHA1 Message Date
devin-ai-integration[bot]
da2f5a498f
feat(agents): support Databricks Agent Platform agents in the agent gateway (#45681)
* feat(agents): support Databricks Agent Platform agents in the agent gateway

Add a databricks_agent provider that speaks the MLflow ResponsesAgent wire
(Responses-shaped input, output_text items, output_text.delta SSE) to Model
Serving endpoints (/invocations or the unified /serving-endpoints/responses)
and Databricks Apps (/responses), with a PAT or OAuth M2M client credentials

Register it through the agents config block or the Admin UI agent catalog and
call it through /a2a/<agent> (message/send, message/stream) or model:
a2a/<agent> chat completions. The chat route now runs every completion-bridge
agent through its own provider, and attaches the minted Databricks OAuth token
for both bridge and URL agents. Consumed OAuth settings never reach the
provider call

* fix(agents): harden databricks_agent input, output, and OAuth handling

Non-text content parts answer 400 unless drop_params is set, a reply without
an output list answers 502, flat OAuth fields resolve an os.environ api_base,
the bridge debug log no longer echoes the request model, routing tests stub
only the HTTP boundary, and the catalog description fits the dropdown

* fix(agents): merge agent and client extra_headers on the a2a chat route, and reject an empty databricks_oauth block

* fix(agents): bridge only databricks_agent agents on the a2a chat route, keep the card url over a client api_base, and require workspace_url for a Databricks App

* refactor(agents): read the a2a chat bridge providers from a constants set instead of branching on a provider name

* fix(databricks_agent): let the configured credential win, reject malformed client extra_headers, and keep a missing endpoint name empty

* test(agents): drive the flat OAuth a2a send through the real bridge

* fix(agents): keep an empty databricks_oauth block ignored on url agents, as before this change

* fix(agents): accept bare App hosts, env service principals, and os.environ refs on Databricks agents

* fix(databricks_agent): address review caveats on chat bridging, params, and auth

Map max_tokens and max_completion_tokens to max_output_tokens and pass
temperature, top_p, and user, so /v1/messages works without drop_params.
Send A2A message metadata only with string values, answering 400 or
dropping the rest under drop_params. Join message items with a blank line
in both stream and non-stream replies. Cache the env service principal
token until shortly before it expires. Keep databricks_agent replies out
of the response cache.

On the chat bridge, let request fields win over the agent's stored params
while pinning the agent's api_base and api_key, and apply the agent's
static_headers between client and agent extra_headers, as /a2a does.
Resolve os.environ/ only for databricks_agent api_base and api_key instead
of every bridge provider. Ignore an unusable databricks_oauth block on URL
agents on chat, as at the merge base, instead of answering 400.

* test(internal_context): list the databricks agent token cache as process-local

* fix(databricks_agent): keep the agent's endpoint, input, and target out of client control

extra_body model and input answer 400, or are dropped under drop_params.
A client api_base or base_url never replaces the agent's card URL on the
bridge. Chat to a URL agent keeps its merge-base call, and an incomplete
databricks_oauth block on a URL agent keeps its merge-base ValueError.

* test(databricks): expect the merge-base 400 for a client api_base on agent chat

* fix(databricks): keep agent-owned inputs and identity headers out of a chat caller's reach

* fix(databricks): bound the agent-over-caller merge to two levels so it needs no recursion

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-15 12:42:06 -07:00
nate-berri
ebf2156ec4
refactor(anthropic): move prompt cache observation lookup out of the proxy hook (#45748)
* refactor(anthropic): move prompt cache observation lookup out of the proxy hook

Part of LIT-9423

* test(internal_context): exempt moved prompt cache lookup helper from key-family check
2026-10-10 19:06:16 +00:00
Yassin Kortam
d36b66e19e
feat(github_copilot): per-user GitHub OAuth connections for Copilot credentials (#45241)
* feat(github_copilot): per-user GitHub OAuth connections for Copilot credentials

Related to LIT-9306

* fix(ui): make per-user GitHub Copilot OAuth credential-only in Add Model

* fix(proxy): render LiteLLM_UserProviderCredentials prisma spans

* style(ui): prettier-format add_model tests

* fix(lint): annotate connection endpoints and narrow per-user credential excepts

* fix(lint): satisfy type-discipline gate for per-user copilot code

* fix(types): clear basedpyright and strict-lint gate regressions

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(types): keep runtime guards on untyped responses input

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* style: ruff format per-user Copilot files

* fix(lint): keep type-discipline suppressions on flagged lines

* fix(github_copilot): resolve team and deployment-id per-user routes, share token cache invalidation

* test(github_copilot): scope response-cache mutation via monkeypatch, assert route allowlist

* fix(github_copilot): fall back to the database on Redis errors and skip worker-local token caching

* fix(lint): suppress mutable return annotation after base merge

* style: shorten rebind-ok reason so the dispatch line stays formatted

* fix(github_copilot): harden per-user token cache, overrides, fallbacks, headers and device flow

* fix(lint): suppress MutableMapping param on session auth pinning

* test(github_copilot): narrow pytest.raises to HTTPException for service-key override

* fix(github_copilot): fail closed on revoke errors, strip caller auth headers, widen fallback discovery

* fix(github_copilot): verify revoke tombstone, bound fallback discovery, cover aliased fallbacks

* fix(github_copilot): make fallback discovery a router superset and guard credential override at deployment

* style(router): drop explanatory comment on per-user credential guard

* fix(github_copilot): gate fallback discovery on per-user credentials and bound aggregate targets

* fix(github_copilot): count every fallback mapping toward the discovery limit

* fix(github_copilot): suppress banned typing cast imports with per-line reasons

* test(github_copilot): cover per-user 401 cooldown skip through the router failure callback

* test(github_copilot): cover per-user 401 cooldown skip through router and fallback paths

* fix(github_copilot): cover auto-router discovery, per-user fallback cooldown and connect cache race

* fix(github_copilot): cover every strategy router kind and verify the connect cache write

* fix merge conflict marker remnant in credential endpoint tests

* fix(github_copilot): do not purge user connections on label-only credential updates

* fix(github_copilot): read user provider credentials from the writer engine

* test(github_copilot): move per-user auth type form test to the integration tier

* test(github_copilot): annotate new credential regression test locals as Final

* fix(github_copilot): type per-user OAuth JSON and DB boundaries

* fix(github_copilot): validate per-user OAuth boundaries and restore truncated comments

* style(github_copilot): complete cut-off suppression reasons on new casts

* refactor(github_copilot): annotate new boundary-typing locals as Final

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-09 15:19:07 -07:00
Yassin Kortam
fbf4af301c
feat(microsoft_365_copilot): add Microsoft 365 Copilot chat provider with OAuth token exchange (#45158)
* feat(microsoft_365_copilot): add Microsoft 365 Copilot chat provider with OAuth token exchange

* fix(ui): create a credential for credential-only auth types in Add Model

* fix(microsoft_365_copilot): accept max_tokens and list the chat model

* fix(microsoft_365_copilot): register provider model set

* fix(ui): hide other auth types' fields when credential-only types are filtered

* fix(health): do not inherit stored auth settings when a connection test brings its own api_key

* docs(health): restore connection-test inheritance docstrings

* fix(lint): suppress justified provider boundary casts

* fix(lint): satisfy M365 type-discipline gate

* fix(types): eliminate type-check gate regressions

* style: shorten suppression reasons so ruff format leaves them on one line

* refactor(types): drop shared-file type widening unrelated to the Copilot provider

* fix(health): pass caller headers as secret_fields to connection-test probes

* fix(types): type connection-test probe and token counter locally

* fix(lint): drop cast import from connection-test header getter

* chore: remove explanatory comments flagged by review

* fix(proxy): gate OAuth client credentials behind proxy admin

* fix(router): skip cooldown on caller-scoped OAuth auth failures

* fix(router): skip fallback cooldown on caller-scoped OAuth auth failures

* fix(router): type caller-scoped cooldown lookups

* fix(ci): include Microsoft 365 Copilot tests in unit shard

* fix(proxy): keep saved endpoint when test_connection retests a deployment by id

* fix(m365): collapse doubled Graph replies

* fix(m365): preserve trailing system messages

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-09 15:19:07 -07:00
joshua-berri
6498bef8db
fix(mcp): honor scoped cache freshness (#45165)
* fix(mcp): honor upstream freshness and caller scope in discovery caches

* test(mcp): type scoped freshness regression helpers

* fix(mcp): age discovery freshness through cleanup

* fix(mcp): preserve keyless discovery caller isolation

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
2026-10-07 17:19:24 -07:00
devin-ai-integration[bot]
564d236985
fix(otel): nest cache spans under their operation and name service spans by purpose (#44150)
Response cache reads and writes open cache.get llm_response and cache.set llm_response phase spans with their Redis spans nested underneath, on the Python path and on the native Rust path, and deployment selection runs inside a route {model_group} phase so the cooldown, usage and model-id reads the router issues nest under it before chat {model}. The autorouter classifier call nests under that route phase as well and carries its typed internal origin on litellm.request.purpose, so it is told apart from the provider attempt. Service spans are named {service}.{verb} {target} from a low-cardinality key family the producer declares (llm_response, auth_objects, spend_counters, router_cooldowns, claude_code_session_router_binding, rate_limits, pod_lock, budget_reset, ...) instead of the raw method or a per-request pipeline length; a pipeline flush is targeted by the one family its ops share or by mixed with the sorted families on litellm.redis.families, a batch op keeps the family it was declared under whichever pipeline or standalone read settles it, and the ambient family labels Redis spans only, never the DB write-back a task spawned inside that context performs later. The raw method stays on litellm.service.call_type and on the Prometheus and Datadog labels. Caller attribution is carried across asyncio task boundaries on a ContextVar so forwarder-only chains no longer surface, the raw cache key is dropped from Redis span metadata, pipeline op counts land as an integer attribute, every call_type the Redis cache layer emits maps to a verb, and a scan over litellm/ and enterprise/ fails when a Redis producer, batch reservation included, declares no key family.

A V2 logger built for a key or team logging entry while the operator's V2 logger is already registered keeps only the exporters its own preset contributed, whether or not the operator holds credentials for that backend, so every chat span no longer reaches the operator's collector twice. A span the success callback has to open itself, with no pre-call carrier, starts at the provider handoff (api_call_start_time) instead of the logging object's creation.

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-03 09:20:27 -07:00