mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
fix(chat-ui): fix MCPEvent layering, batch localStorage writes, module-level test imports
- Move MCPEvent interface definition into chat/types.ts (single source of truth) - MCPEventsDisplay.tsx now imports MCPEvent from types.ts instead of defining it locally - Batch MCP event localStorage writes: accumulate during stream, persist once in finally - Move test imports to module level per PEP 8 convention
This commit is contained in:
parent
90b7e32332
commit
712c15ee68
4 changed files with 39 additions and 46 deletions
|
|
@ -6,11 +6,15 @@ Verifies that:
|
|||
2. Absence of previous_response_id does not break the call
|
||||
3. The aresponses function signature exposes the expected parameters
|
||||
"""
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import unittest.mock as mock
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../.."))
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
import litellm
|
||||
|
|
@ -21,8 +25,6 @@ class TestResponsesSessionChaining:
|
|||
|
||||
def test_responses_api_signature_accepts_previous_response_id(self):
|
||||
"""aresponses must accept previous_response_id and onResponseId-like params."""
|
||||
import inspect
|
||||
|
||||
sig = inspect.signature(litellm.aresponses)
|
||||
assert "previous_response_id" in sig.parameters, (
|
||||
"aresponses must accept previous_response_id for multi-turn session chaining"
|
||||
|
|
@ -33,13 +35,9 @@ class TestResponsesSessionChaining:
|
|||
@pytest.mark.asyncio
|
||||
async def test_previous_response_id_included_in_request_body(self):
|
||||
"""previous_response_id must appear in the outgoing HTTP request body."""
|
||||
import httpx
|
||||
|
||||
captured_body: dict = {}
|
||||
|
||||
async def mock_send(self_transport, request: httpx.Request, **kwargs):
|
||||
import json
|
||||
|
||||
try:
|
||||
captured_body.update(json.loads(request.content))
|
||||
except Exception:
|
||||
|
|
@ -68,8 +66,6 @@ class TestResponsesSessionChaining:
|
|||
request=request,
|
||||
)
|
||||
|
||||
import unittest.mock as mock
|
||||
|
||||
with mock.patch("httpx.AsyncClient.send", mock_send):
|
||||
try:
|
||||
await litellm.aresponses(
|
||||
|
|
@ -88,13 +84,9 @@ class TestResponsesSessionChaining:
|
|||
@pytest.mark.asyncio
|
||||
async def test_no_previous_response_id_omitted_from_request(self):
|
||||
"""When previous_response_id is None, it must not appear in the request body."""
|
||||
import httpx
|
||||
|
||||
captured_body: dict = {}
|
||||
|
||||
async def mock_send(self_transport, request: httpx.Request, **kwargs):
|
||||
import json
|
||||
|
||||
try:
|
||||
captured_body.update(json.loads(request.content))
|
||||
except Exception:
|
||||
|
|
@ -118,8 +110,6 @@ class TestResponsesSessionChaining:
|
|||
}
|
||||
return httpx.Response(200, json=response_json, request=request)
|
||||
|
||||
import unittest.mock as mock
|
||||
|
||||
with mock.patch("httpx.AsyncClient.send", mock_send):
|
||||
try:
|
||||
await litellm.aresponses(
|
||||
|
|
|
|||
|
|
@ -304,10 +304,9 @@ const ChatPage: React.FC<ChatPageProps> = ({ accessToken, userRole, userId, user
|
|||
previousResponseId,
|
||||
(id: string) => setResponsesSessionId(id),
|
||||
(event: MCPEvent) => {
|
||||
// Accumulate locally only — persisted once in finally to avoid
|
||||
// one full localStorage write per MCP event during streaming.
|
||||
accumulatedMCPEvents.push(event);
|
||||
// Persist a snapshot to the assistant message so events survive
|
||||
// across turns instead of disappearing when the next send starts.
|
||||
updateLastAssistantMessage(convId!, { mcpEvents: [...accumulatedMCPEvents] });
|
||||
},
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
|
|
@ -321,6 +320,10 @@ const ChatPage: React.FC<ChatPageProps> = ({ accessToken, userRole, userId, user
|
|||
});
|
||||
}
|
||||
} finally {
|
||||
// Persist MCP events once after the turn ends (single localStorage write).
|
||||
if (accumulatedMCPEvents.length > 0) {
|
||||
updateLastAssistantMessage(convId!, { mcpEvents: accumulatedMCPEvents });
|
||||
}
|
||||
setIsStreaming(false);
|
||||
abortControllerRef.current = null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,29 @@
|
|||
import type { MCPEvent } from "../playground/chat_ui/MCPEventsDisplay";
|
||||
|
||||
export type { MCPEvent };
|
||||
/** Represents a single MCP tool event emitted during an assistant turn. */
|
||||
export interface MCPEvent {
|
||||
type: string;
|
||||
sequence_number?: number;
|
||||
output_index?: number;
|
||||
item_id?: string;
|
||||
item?: {
|
||||
id?: string;
|
||||
type?: string;
|
||||
server_label?: string;
|
||||
tools?: Array<{
|
||||
name: string;
|
||||
description: string;
|
||||
annotations?: {
|
||||
read_only?: boolean;
|
||||
};
|
||||
input_schema?: unknown;
|
||||
}>;
|
||||
name?: string;
|
||||
arguments?: string;
|
||||
output?: string;
|
||||
};
|
||||
delta?: string;
|
||||
arguments?: string;
|
||||
timestamp?: number;
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -1,35 +1,12 @@
|
|||
import React from "react";
|
||||
import { Typography, Collapse } from "antd";
|
||||
import type { MCPEvent } from "../../chat/types";
|
||||
|
||||
export type { MCPEvent };
|
||||
|
||||
const { Text } = Typography;
|
||||
const { Panel } = Collapse;
|
||||
|
||||
export interface MCPEvent {
|
||||
type: string;
|
||||
sequence_number?: number;
|
||||
output_index?: number;
|
||||
item_id?: string;
|
||||
item?: {
|
||||
id?: string;
|
||||
type?: string;
|
||||
server_label?: string;
|
||||
tools?: Array<{
|
||||
name: string;
|
||||
description: string;
|
||||
annotations?: {
|
||||
read_only?: boolean;
|
||||
};
|
||||
input_schema?: any;
|
||||
}>;
|
||||
name?: string;
|
||||
arguments?: string;
|
||||
output?: string;
|
||||
};
|
||||
delta?: string;
|
||||
arguments?: string;
|
||||
timestamp?: number;
|
||||
}
|
||||
|
||||
interface MCPEventsDisplayProps {
|
||||
events: MCPEvent[];
|
||||
className?: string;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue