mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
test(mcp): build immutable lifecycle updates and replica results
This commit is contained in:
parent
1625f8e7f5
commit
42385177a3
3 changed files with 22 additions and 14 deletions
|
|
@ -136,14 +136,14 @@ async def update_mcp_toolset(
|
|||
tool list, so a null ``toolset_name`` or ``tools`` is a no-op rather than a clear;
|
||||
emptying the tool selection is an explicit ``[]``, which cannot be mistaken for a
|
||||
caller that left the field out."""
|
||||
data_dict: Final = data.model_dump(exclude_unset=True, exclude={"toolset_id"})
|
||||
if data_dict.get("toolset_name", "") is None:
|
||||
_ = data_dict.pop("toolset_name")
|
||||
if data_dict.get("tools", "") is None:
|
||||
_ = data_dict.pop("tools")
|
||||
if "tools" in data_dict:
|
||||
data_dict["tools"] = json.dumps(data_dict["tools"])
|
||||
data_dict["updated_by"] = touched_by
|
||||
data_dict: Final = dict( # mutable-ok: Prisma requires a plain dict for JSON query serialization
|
||||
(
|
||||
(field, json.dumps(value) if field == "tools" else value)
|
||||
for field, value in data.model_dump(exclude_unset=True).items()
|
||||
if field != "toolset_id" and (field not in ("toolset_name", "tools") or value is not None)
|
||||
),
|
||||
updated_by=touched_by,
|
||||
)
|
||||
try:
|
||||
row: Final = await _toolset_table(prisma_client).update(
|
||||
where={"toolset_id": data.toolset_id},
|
||||
|
|
|
|||
|
|
@ -607,7 +607,7 @@ class ToolsetRow(BaseModel):
|
|||
toolset_id: str
|
||||
toolset_name: str
|
||||
description: str | None = None
|
||||
tools: list[ToolsetTool] = []
|
||||
tools: list[ToolsetTool] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ToolsetListResponse(RootModel[list[ToolsetRow]]):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import time
|
|||
import warnings
|
||||
from collections.abc import Callable, Mapping
|
||||
from dataclasses import dataclass
|
||||
from functools import reduce
|
||||
from datetime import datetime
|
||||
from types import MappingProxyType
|
||||
from typing import Final
|
||||
|
|
@ -296,9 +297,14 @@ def await_everywhere[T](
|
|||
"""`_last_answer` against every replica in turn, each with the full budget, so a
|
||||
write counts as visible only once the last replica reflects it, and stop at the
|
||||
first replica that never converges. Clock and sleep are injected."""
|
||||
answers: dict[str, T] = {}
|
||||
for replica, read in reads.items():
|
||||
answer = _last_answer(
|
||||
def read_replica(
|
||||
outcome: EverywhereConverged[T] | NeverConvergedOn[T],
|
||||
item: tuple[str, ReplicaRead[T]],
|
||||
) -> EverywhereConverged[T] | NeverConvergedOn[T]:
|
||||
if isinstance(outcome, NeverConvergedOn):
|
||||
return outcome
|
||||
replica, read = item
|
||||
answer: Final = _last_answer(
|
||||
read,
|
||||
settled=settled,
|
||||
timeout=timeout,
|
||||
|
|
@ -309,8 +315,10 @@ def await_everywhere[T](
|
|||
)
|
||||
if not settled(answer):
|
||||
return NeverConvergedOn(replica=replica, last=answer)
|
||||
answers[replica] = answer
|
||||
return EverywhereConverged(answers=MappingProxyType(answers))
|
||||
return EverywhereConverged(answers=MappingProxyType({**outcome.answers, replica: answer}))
|
||||
|
||||
initial: Final[EverywhereConverged[T] | NeverConvergedOn[T]] = EverywhereConverged(answers=MappingProxyType({}))
|
||||
return reduce(read_replica, reads.items(), initial)
|
||||
|
||||
|
||||
def _is_not_found[R: BaseModel](result: Result[R]) -> bool:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue