[model-gateway] move all responses api event from oai to proto (#14446)
Co-authored-by: key4ng <rukeyang@gmail.com>
This commit is contained in:
@@ -0,0 +1,175 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// Response lifecycle events
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum ResponseEvent {
|
||||||
|
Created,
|
||||||
|
InProgress,
|
||||||
|
Completed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseEvent {
|
||||||
|
pub const CREATED: &'static str = "response.created";
|
||||||
|
pub const IN_PROGRESS: &'static str = "response.in_progress";
|
||||||
|
pub const COMPLETED: &'static str = "response.completed";
|
||||||
|
|
||||||
|
pub const fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Created => Self::CREATED,
|
||||||
|
Self::InProgress => Self::IN_PROGRESS,
|
||||||
|
Self::Completed => Self::COMPLETED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ResponseEvent {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Output item events for streaming
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum OutputItemEvent {
|
||||||
|
Added,
|
||||||
|
Done,
|
||||||
|
Delta,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputItemEvent {
|
||||||
|
pub const ADDED: &'static str = "response.output_item.added";
|
||||||
|
pub const DONE: &'static str = "response.output_item.done";
|
||||||
|
pub const DELTA: &'static str = "response.output_item.delta";
|
||||||
|
|
||||||
|
pub const fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Added => Self::ADDED,
|
||||||
|
Self::Done => Self::DONE,
|
||||||
|
Self::Delta => Self::DELTA,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for OutputItemEvent {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function call argument streaming events
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum FunctionCallEvent {
|
||||||
|
ArgumentsDelta,
|
||||||
|
ArgumentsDone,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionCallEvent {
|
||||||
|
pub const ARGUMENTS_DELTA: &'static str = "response.function_call_arguments.delta";
|
||||||
|
pub const ARGUMENTS_DONE: &'static str = "response.function_call_arguments.done";
|
||||||
|
|
||||||
|
pub const fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::ArgumentsDelta => Self::ARGUMENTS_DELTA,
|
||||||
|
Self::ArgumentsDone => Self::ARGUMENTS_DONE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FunctionCallEvent {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// MCP Events
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// MCP (Model Context Protocol) call events
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum McpEvent {
|
||||||
|
CallArgumentsDelta,
|
||||||
|
CallArgumentsDone,
|
||||||
|
CallInProgress,
|
||||||
|
CallCompleted,
|
||||||
|
ListToolsInProgress,
|
||||||
|
ListToolsCompleted,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl McpEvent {
|
||||||
|
pub const CALL_ARGUMENTS_DELTA: &'static str = "response.mcp_call_arguments.delta";
|
||||||
|
pub const CALL_ARGUMENTS_DONE: &'static str = "response.mcp_call_arguments.done";
|
||||||
|
pub const CALL_IN_PROGRESS: &'static str = "response.mcp_call.in_progress";
|
||||||
|
pub const CALL_COMPLETED: &'static str = "response.mcp_call.completed";
|
||||||
|
pub const LIST_TOOLS_IN_PROGRESS: &'static str = "response.mcp_list_tools.in_progress";
|
||||||
|
pub const LIST_TOOLS_COMPLETED: &'static str = "response.mcp_list_tools.completed";
|
||||||
|
|
||||||
|
pub const fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::CallArgumentsDelta => Self::CALL_ARGUMENTS_DELTA,
|
||||||
|
Self::CallArgumentsDone => Self::CALL_ARGUMENTS_DONE,
|
||||||
|
Self::CallInProgress => Self::CALL_IN_PROGRESS,
|
||||||
|
Self::CallCompleted => Self::CALL_COMPLETED,
|
||||||
|
Self::ListToolsInProgress => Self::LIST_TOOLS_IN_PROGRESS,
|
||||||
|
Self::ListToolsCompleted => Self::LIST_TOOLS_COMPLETED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for McpEvent {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Item type discriminators used in output items
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum ItemType {
|
||||||
|
FunctionCall,
|
||||||
|
FunctionToolCall,
|
||||||
|
McpCall,
|
||||||
|
Function,
|
||||||
|
McpListTools,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemType {
|
||||||
|
pub const FUNCTION_CALL: &'static str = "function_call";
|
||||||
|
pub const FUNCTION_TOOL_CALL: &'static str = "function_tool_call";
|
||||||
|
pub const MCP_CALL: &'static str = "mcp_call";
|
||||||
|
pub const FUNCTION: &'static str = "function";
|
||||||
|
pub const MCP_LIST_TOOLS: &'static str = "mcp_list_tools";
|
||||||
|
|
||||||
|
pub const fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::FunctionCall => Self::FUNCTION_CALL,
|
||||||
|
Self::FunctionToolCall => Self::FUNCTION_TOOL_CALL,
|
||||||
|
Self::McpCall => Self::MCP_CALL,
|
||||||
|
Self::Function => Self::FUNCTION,
|
||||||
|
Self::McpListTools => Self::MCP_LIST_TOOLS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if this is a function call variant (FunctionCall or FunctionToolCall)
|
||||||
|
pub const fn is_function_call(&self) -> bool {
|
||||||
|
matches!(self, Self::FunctionCall | Self::FunctionToolCall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ItemType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if an event type string matches any response lifecycle event
|
||||||
|
pub fn is_response_event(event_type: &str) -> bool {
|
||||||
|
matches!(
|
||||||
|
event_type,
|
||||||
|
ResponseEvent::CREATED | ResponseEvent::IN_PROGRESS | ResponseEvent::COMPLETED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if an item type string is a function call variant
|
||||||
|
pub fn is_function_call_type(item_type: &str) -> bool {
|
||||||
|
item_type == ItemType::FUNCTION_CALL || item_type == ItemType::FUNCTION_TOOL_CALL
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ pub mod classify;
|
|||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod completion;
|
pub mod completion;
|
||||||
pub mod embedding;
|
pub mod embedding;
|
||||||
|
pub mod event_types;
|
||||||
pub mod generate;
|
pub mod generate;
|
||||||
pub mod rerank;
|
pub mod rerank;
|
||||||
pub mod responses;
|
pub mod responses;
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ use serde_json::{json, to_value, Value};
|
|||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use super::utils::event_types;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mcp,
|
mcp,
|
||||||
protocols::responses::{
|
protocols::{
|
||||||
generate_id, ResponseInput, ResponseTool, ResponseToolType, ResponsesRequest,
|
event_types::{is_function_call_type, ItemType, McpEvent, OutputItemEvent},
|
||||||
|
responses::{generate_id, ResponseInput, ResponseTool, ResponseToolType, ResponsesRequest},
|
||||||
},
|
},
|
||||||
routers::header_utils::apply_request_headers,
|
routers::header_utils::apply_request_headers,
|
||||||
};
|
};
|
||||||
@@ -76,7 +76,7 @@ impl ToolLoopState {
|
|||||||
) {
|
) {
|
||||||
// Add function_call item to history
|
// Add function_call item to history
|
||||||
let func_item = json!({
|
let func_item = json!({
|
||||||
"type": event_types::ITEM_TYPE_FUNCTION_CALL,
|
"type": ItemType::FUNCTION_CALL,
|
||||||
"call_id": call_id,
|
"call_id": call_id,
|
||||||
"name": tool_name,
|
"name": tool_name,
|
||||||
"arguments": args_json_str
|
"arguments": args_json_str
|
||||||
@@ -285,7 +285,7 @@ pub(super) fn prepare_mcp_payload_for_streaming(
|
|||||||
arr.retain(|item| {
|
arr.retain(|item| {
|
||||||
item.get("type")
|
item.get("type")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.map(|s| s == event_types::ITEM_TYPE_FUNCTION)
|
.map(|s| s == ItemType::FUNCTION)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ pub(super) fn prepare_mcp_payload_for_streaming(
|
|||||||
for t in tools {
|
for t in tools {
|
||||||
let parameters = Value::Object((*t.input_schema).clone());
|
let parameters = Value::Object((*t.input_schema).clone());
|
||||||
let tool = serde_json::json!({
|
let tool = serde_json::json!({
|
||||||
"type": event_types::ITEM_TYPE_FUNCTION,
|
"type": ItemType::FUNCTION,
|
||||||
"name": t.name,
|
"name": t.name,
|
||||||
"description": t.description,
|
"description": t.description,
|
||||||
"parameters": parameters
|
"parameters": parameters
|
||||||
@@ -399,7 +399,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
|
|
||||||
// Event 1: response.output_item.added with empty tools
|
// Event 1: response.output_item.added with empty tools
|
||||||
let event1_payload = json!({
|
let event1_payload = json!({
|
||||||
"type": event_types::OUTPUT_ITEM_ADDED,
|
"type": OutputItemEvent::ADDED,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": output_index,
|
"output_index": output_index,
|
||||||
"item": tools_item_empty
|
"item": tools_item_empty
|
||||||
@@ -407,7 +407,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
*sequence_number += 1;
|
*sequence_number += 1;
|
||||||
let event1 = format!(
|
let event1 = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::OUTPUT_ITEM_ADDED,
|
OutputItemEvent::ADDED,
|
||||||
event1_payload
|
event1_payload
|
||||||
);
|
);
|
||||||
if tx.send(Ok(Bytes::from(event1))).is_err() {
|
if tx.send(Ok(Bytes::from(event1))).is_err() {
|
||||||
@@ -416,7 +416,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
|
|
||||||
// Event 2: response.mcp_list_tools.in_progress
|
// Event 2: response.mcp_list_tools.in_progress
|
||||||
let event2_payload = json!({
|
let event2_payload = json!({
|
||||||
"type": event_types::MCP_LIST_TOOLS_IN_PROGRESS,
|
"type": McpEvent::LIST_TOOLS_IN_PROGRESS,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": output_index,
|
"output_index": output_index,
|
||||||
"item_id": item_id
|
"item_id": item_id
|
||||||
@@ -424,7 +424,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
*sequence_number += 1;
|
*sequence_number += 1;
|
||||||
let event2 = format!(
|
let event2 = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::MCP_LIST_TOOLS_IN_PROGRESS,
|
McpEvent::LIST_TOOLS_IN_PROGRESS,
|
||||||
event2_payload
|
event2_payload
|
||||||
);
|
);
|
||||||
if tx.send(Ok(Bytes::from(event2))).is_err() {
|
if tx.send(Ok(Bytes::from(event2))).is_err() {
|
||||||
@@ -433,7 +433,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
|
|
||||||
// Event 3: response.mcp_list_tools.completed
|
// Event 3: response.mcp_list_tools.completed
|
||||||
let event3_payload = json!({
|
let event3_payload = json!({
|
||||||
"type": event_types::MCP_LIST_TOOLS_COMPLETED,
|
"type": McpEvent::LIST_TOOLS_COMPLETED,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": output_index,
|
"output_index": output_index,
|
||||||
"item_id": item_id
|
"item_id": item_id
|
||||||
@@ -441,7 +441,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
*sequence_number += 1;
|
*sequence_number += 1;
|
||||||
let event3 = format!(
|
let event3 = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::MCP_LIST_TOOLS_COMPLETED,
|
McpEvent::LIST_TOOLS_COMPLETED,
|
||||||
event3_payload
|
event3_payload
|
||||||
);
|
);
|
||||||
if tx.send(Ok(Bytes::from(event3))).is_err() {
|
if tx.send(Ok(Bytes::from(event3))).is_err() {
|
||||||
@@ -450,7 +450,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
|
|
||||||
// Event 4: response.output_item.done with full tools list
|
// Event 4: response.output_item.done with full tools list
|
||||||
let event4_payload = json!({
|
let event4_payload = json!({
|
||||||
"type": event_types::OUTPUT_ITEM_DONE,
|
"type": OutputItemEvent::DONE,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": output_index,
|
"output_index": output_index,
|
||||||
"item": tools_item_full
|
"item": tools_item_full
|
||||||
@@ -458,7 +458,7 @@ pub(super) fn send_mcp_list_tools_events(
|
|||||||
*sequence_number += 1;
|
*sequence_number += 1;
|
||||||
let event4 = format!(
|
let event4 = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::OUTPUT_ITEM_DONE,
|
OutputItemEvent::DONE,
|
||||||
event4_payload
|
event4_payload
|
||||||
);
|
);
|
||||||
tx.send(Ok(Bytes::from(event4))).is_ok()
|
tx.send(Ok(Bytes::from(event4))).is_ok()
|
||||||
@@ -495,7 +495,7 @@ pub(super) fn send_mcp_call_completion_events_with_error(
|
|||||||
|
|
||||||
// Event 1: response.mcp_call.completed
|
// Event 1: response.mcp_call.completed
|
||||||
let completed_payload = json!({
|
let completed_payload = json!({
|
||||||
"type": event_types::MCP_CALL_COMPLETED,
|
"type": McpEvent::CALL_COMPLETED,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": effective_output_index,
|
"output_index": effective_output_index,
|
||||||
"item_id": item_id
|
"item_id": item_id
|
||||||
@@ -504,7 +504,7 @@ pub(super) fn send_mcp_call_completion_events_with_error(
|
|||||||
|
|
||||||
let completed_event = format!(
|
let completed_event = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::MCP_CALL_COMPLETED,
|
McpEvent::CALL_COMPLETED,
|
||||||
completed_payload
|
completed_payload
|
||||||
);
|
);
|
||||||
if tx.send(Ok(Bytes::from(completed_event))).is_err() {
|
if tx.send(Ok(Bytes::from(completed_event))).is_err() {
|
||||||
@@ -513,7 +513,7 @@ pub(super) fn send_mcp_call_completion_events_with_error(
|
|||||||
|
|
||||||
// Event 2: response.output_item.done (with completed mcp_call)
|
// Event 2: response.output_item.done (with completed mcp_call)
|
||||||
let done_payload = json!({
|
let done_payload = json!({
|
||||||
"type": event_types::OUTPUT_ITEM_DONE,
|
"type": OutputItemEvent::DONE,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": effective_output_index,
|
"output_index": effective_output_index,
|
||||||
"item": mcp_call_item
|
"item": mcp_call_item
|
||||||
@@ -522,7 +522,7 @@ pub(super) fn send_mcp_call_completion_events_with_error(
|
|||||||
|
|
||||||
let done_event = format!(
|
let done_event = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::OUTPUT_ITEM_DONE,
|
OutputItemEvent::DONE,
|
||||||
done_payload
|
done_payload
|
||||||
);
|
);
|
||||||
tx.send(Ok(Bytes::from(done_event))).is_ok()
|
tx.send(Ok(Bytes::from(done_event))).is_ok()
|
||||||
@@ -541,7 +541,7 @@ pub(super) fn inject_mcp_metadata_streaming(
|
|||||||
) {
|
) {
|
||||||
if let Some(output_array) = response.get_mut("output").and_then(|v| v.as_array_mut()) {
|
if let Some(output_array) = response.get_mut("output").and_then(|v| v.as_array_mut()) {
|
||||||
output_array.retain(|item| {
|
output_array.retain(|item| {
|
||||||
item.get("type").and_then(|t| t.as_str()) != Some(event_types::ITEM_TYPE_MCP_LIST_TOOLS)
|
item.get("type").and_then(|t| t.as_str()) != Some(ItemType::MCP_LIST_TOOLS)
|
||||||
});
|
});
|
||||||
|
|
||||||
let list_tools_item = build_mcp_list_tools_item(mcp, server_label);
|
let list_tools_item = build_mcp_list_tools_item(mcp, server_label);
|
||||||
@@ -782,9 +782,7 @@ pub(super) fn build_incomplete_response(
|
|||||||
let mut mcp_call_items = Vec::new();
|
let mut mcp_call_items = Vec::new();
|
||||||
for item in output_array.iter() {
|
for item in output_array.iter() {
|
||||||
let item_type = item.get("type").and_then(|t| t.as_str());
|
let item_type = item.get("type").and_then(|t| t.as_str());
|
||||||
if item_type == Some(event_types::ITEM_TYPE_FUNCTION_TOOL_CALL)
|
if item_type.is_some_and(is_function_call_type) {
|
||||||
|| item_type == Some(event_types::ITEM_TYPE_FUNCTION_CALL)
|
|
||||||
{
|
|
||||||
let tool_name = item.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
let tool_name = item.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
let args = item
|
let args = item
|
||||||
.get("arguments")
|
.get("arguments")
|
||||||
@@ -870,7 +868,7 @@ pub(super) fn build_mcp_list_tools_item(mcp: &Arc<mcp::McpManager>, server_label
|
|||||||
|
|
||||||
json!({
|
json!({
|
||||||
"id": generate_id("mcpl"),
|
"id": generate_id("mcpl"),
|
||||||
"type": event_types::ITEM_TYPE_MCP_LIST_TOOLS,
|
"type": ItemType::MCP_LIST_TOOLS,
|
||||||
"server_label": server_label,
|
"server_label": server_label,
|
||||||
"tools": tools_json
|
"tools": tools_json
|
||||||
})
|
})
|
||||||
@@ -887,7 +885,7 @@ pub(super) fn build_mcp_call_item(
|
|||||||
) -> Value {
|
) -> Value {
|
||||||
json!({
|
json!({
|
||||||
"id": generate_id("mcp"),
|
"id": generate_id("mcp"),
|
||||||
"type": event_types::ITEM_TYPE_MCP_CALL,
|
"type": ItemType::MCP_CALL,
|
||||||
"status": if success { "completed" } else { "failed" },
|
"status": if success { "completed" } else { "failed" },
|
||||||
"approval_request_id": Value::Null,
|
"approval_request_id": Value::Null,
|
||||||
"arguments": arguments,
|
"arguments": arguments,
|
||||||
@@ -906,7 +904,7 @@ pub(super) fn build_executed_mcp_call_items(
|
|||||||
let mut mcp_call_items = Vec::new();
|
let mut mcp_call_items = Vec::new();
|
||||||
|
|
||||||
for item in conversation_history {
|
for item in conversation_history {
|
||||||
if item.get("type").and_then(|t| t.as_str()) == Some(event_types::ITEM_TYPE_FUNCTION_CALL) {
|
if item.get("type").and_then(|t| t.as_str()) == Some(ItemType::FUNCTION_CALL) {
|
||||||
let call_id = item.get("call_id").and_then(|v| v.as_str()).unwrap_or("");
|
let call_id = item.get("call_id").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
let tool_name = item.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
let tool_name = item.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
let args = item
|
let args = item
|
||||||
@@ -958,9 +956,7 @@ pub(super) fn extract_function_call(resp: &Value) -> Option<(String, String, Str
|
|||||||
for item in output {
|
for item in output {
|
||||||
let obj = item.as_object()?;
|
let obj = item.as_object()?;
|
||||||
let t = obj.get("type")?.as_str()?;
|
let t = obj.get("type")?.as_str()?;
|
||||||
if t == event_types::ITEM_TYPE_FUNCTION_TOOL_CALL
|
if is_function_call_type(t) {
|
||||||
|| t == event_types::ITEM_TYPE_FUNCTION_CALL
|
|
||||||
{
|
|
||||||
let call_id = obj
|
let call_id = obj
|
||||||
.get("call_id")
|
.get("call_id")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ use std::collections::HashMap;
|
|||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use super::utils::event_types;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data_connector::{ResponseId, StoredResponse},
|
data_connector::{ResponseId, StoredResponse},
|
||||||
protocols::responses::{ResponseToolType, ResponsesRequest},
|
protocols::{
|
||||||
|
event_types::is_response_event,
|
||||||
|
responses::{ResponseToolType, ResponsesRequest},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -201,12 +203,7 @@ pub(super) fn rewrite_streaming_block(
|
|||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let should_patch = matches!(
|
let should_patch = is_response_event(event_type);
|
||||||
event_type,
|
|
||||||
event_types::RESPONSE_CREATED
|
|
||||||
| event_types::RESPONSE_IN_PROGRESS
|
|
||||||
| event_types::RESPONSE_COMPLETED
|
|
||||||
);
|
|
||||||
|
|
||||||
if !should_patch {
|
if !should_patch {
|
||||||
return None;
|
return None;
|
||||||
|
|||||||
@@ -31,10 +31,16 @@ use super::{
|
|||||||
send_mcp_list_tools_events, McpLoopConfig, ToolLoopState,
|
send_mcp_list_tools_events, McpLoopConfig, ToolLoopState,
|
||||||
},
|
},
|
||||||
responses::{mask_tools_as_mcp, patch_streaming_response_json, rewrite_streaming_block},
|
responses::{mask_tools_as_mcp, patch_streaming_response_json, rewrite_streaming_block},
|
||||||
utils::{event_types, FunctionCallInProgress, OutputIndexMapper, StreamAction},
|
utils::{FunctionCallInProgress, OutputIndexMapper, StreamAction},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
protocols::responses::{ResponseToolType, ResponsesRequest},
|
protocols::{
|
||||||
|
event_types::{
|
||||||
|
is_function_call_type, is_response_event, FunctionCallEvent, ItemType, McpEvent,
|
||||||
|
OutputItemEvent, ResponseEvent,
|
||||||
|
},
|
||||||
|
responses::{ResponseToolType, ResponsesRequest},
|
||||||
|
},
|
||||||
routers::header_utils::{apply_request_headers, preserve_response_headers},
|
routers::header_utils::{apply_request_headers, preserve_response_headers},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -161,19 +167,19 @@ impl StreamingResponseAccumulator {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
match event_type.as_str() {
|
match event_type.as_str() {
|
||||||
event_types::RESPONSE_CREATED => {
|
ResponseEvent::CREATED => {
|
||||||
if self.initial_response.is_none() {
|
if self.initial_response.is_none() {
|
||||||
if let Some(response) = parsed.get("response") {
|
if let Some(response) = parsed.get("response") {
|
||||||
self.initial_response = Some(response.clone());
|
self.initial_response = Some(response.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event_types::RESPONSE_COMPLETED => {
|
ResponseEvent::COMPLETED => {
|
||||||
if let Some(response) = parsed.get("response") {
|
if let Some(response) = parsed.get("response") {
|
||||||
self.completed_response = Some(response.clone());
|
self.completed_response = Some(response.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event_types::OUTPUT_ITEM_DONE => {
|
OutputItemEvent::DONE => {
|
||||||
if let (Some(index), Some(item)) = (
|
if let (Some(index), Some(item)) = (
|
||||||
parsed
|
parsed
|
||||||
.get("output_index")
|
.get("output_index")
|
||||||
@@ -292,7 +298,7 @@ impl StreamingToolHandler {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
match event_type.as_str() {
|
match event_type.as_str() {
|
||||||
event_types::RESPONSE_CREATED => {
|
ResponseEvent::CREATED => {
|
||||||
if self.original_response_id.is_none() {
|
if self.original_response_id.is_none() {
|
||||||
if let Some(response_obj) = parsed.get("response").and_then(|v| v.as_object()) {
|
if let Some(response_obj) = parsed.get("response").and_then(|v| v.as_object()) {
|
||||||
if let Some(id) = response_obj.get("id").and_then(|v| v.as_str()) {
|
if let Some(id) = response_obj.get("id").and_then(|v| v.as_str()) {
|
||||||
@@ -302,8 +308,8 @@ impl StreamingToolHandler {
|
|||||||
}
|
}
|
||||||
StreamAction::Forward
|
StreamAction::Forward
|
||||||
}
|
}
|
||||||
event_types::RESPONSE_COMPLETED => StreamAction::Forward,
|
ResponseEvent::COMPLETED => StreamAction::Forward,
|
||||||
event_types::OUTPUT_ITEM_ADDED => {
|
OutputItemEvent::ADDED => {
|
||||||
if let Some(idx) = parsed.get("output_index").and_then(|v| v.as_u64()) {
|
if let Some(idx) = parsed.get("output_index").and_then(|v| v.as_u64()) {
|
||||||
self.ensure_output_index(idx as usize);
|
self.ensure_output_index(idx as usize);
|
||||||
}
|
}
|
||||||
@@ -311,9 +317,7 @@ impl StreamingToolHandler {
|
|||||||
// Check if this is a function_call item being added
|
// Check if this is a function_call item being added
|
||||||
if let Some(item) = parsed.get("item") {
|
if let Some(item) = parsed.get("item") {
|
||||||
if let Some(item_type) = item.get("type").and_then(|v| v.as_str()) {
|
if let Some(item_type) = item.get("type").and_then(|v| v.as_str()) {
|
||||||
if item_type == event_types::ITEM_TYPE_FUNCTION_CALL
|
if is_function_call_type(item_type) {
|
||||||
|| item_type == event_types::ITEM_TYPE_FUNCTION_TOOL_CALL
|
|
||||||
{
|
|
||||||
match parsed.get("output_index").and_then(|v| v.as_u64()) {
|
match parsed.get("output_index").and_then(|v| v.as_u64()) {
|
||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
let output_index = idx as usize;
|
let output_index = idx as usize;
|
||||||
@@ -343,7 +347,7 @@ impl StreamingToolHandler {
|
|||||||
}
|
}
|
||||||
StreamAction::Forward
|
StreamAction::Forward
|
||||||
}
|
}
|
||||||
event_types::FUNCTION_CALL_ARGUMENTS_DELTA => {
|
FunctionCallEvent::ARGUMENTS_DELTA => {
|
||||||
// Accumulate arguments for the function call
|
// Accumulate arguments for the function call
|
||||||
if let Some(output_index) = parsed
|
if let Some(output_index) = parsed
|
||||||
.get("output_index")
|
.get("output_index")
|
||||||
@@ -371,7 +375,7 @@ impl StreamingToolHandler {
|
|||||||
}
|
}
|
||||||
StreamAction::Forward
|
StreamAction::Forward
|
||||||
}
|
}
|
||||||
event_types::FUNCTION_CALL_ARGUMENTS_DONE => {
|
FunctionCallEvent::ARGUMENTS_DONE => {
|
||||||
// Function call arguments complete - check if ready to execute
|
// Function call arguments complete - check if ready to execute
|
||||||
if let Some(output_index) = parsed
|
if let Some(output_index) = parsed
|
||||||
.get("output_index")
|
.get("output_index")
|
||||||
@@ -396,8 +400,8 @@ impl StreamingToolHandler {
|
|||||||
StreamAction::Forward
|
StreamAction::Forward
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event_types::OUTPUT_ITEM_DELTA => self.process_output_delta(&parsed),
|
OutputItemEvent::DELTA => self.process_output_delta(&parsed),
|
||||||
event_types::OUTPUT_ITEM_DONE => {
|
OutputItemEvent::DONE => {
|
||||||
// Check if we have complete function calls ready to execute
|
// Check if we have complete function calls ready to execute
|
||||||
if let Some(output_index) = parsed
|
if let Some(output_index) = parsed
|
||||||
.get("output_index")
|
.get("output_index")
|
||||||
@@ -435,9 +439,7 @@ impl StreamingToolHandler {
|
|||||||
// Check if this is a function call delta
|
// Check if this is a function call delta
|
||||||
let item_type = delta.get("type").and_then(|v| v.as_str());
|
let item_type = delta.get("type").and_then(|v| v.as_str());
|
||||||
|
|
||||||
if item_type == Some(event_types::ITEM_TYPE_FUNCTION_TOOL_CALL)
|
if item_type.is_some_and(is_function_call_type) {
|
||||||
|| item_type == Some(event_types::ITEM_TYPE_FUNCTION_CALL)
|
|
||||||
{
|
|
||||||
self.in_function_call = true;
|
self.in_function_call = true;
|
||||||
|
|
||||||
// Get or create function call for this output index
|
// Get or create function call for this output index
|
||||||
@@ -561,12 +563,7 @@ pub(super) fn apply_event_transformations_inplace(
|
|||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let should_patch = matches!(
|
let should_patch = is_response_event(event_type.as_str());
|
||||||
event_type.as_str(),
|
|
||||||
event_types::RESPONSE_CREATED
|
|
||||||
| event_types::RESPONSE_IN_PROGRESS
|
|
||||||
| event_types::RESPONSE_COMPLETED
|
|
||||||
);
|
|
||||||
|
|
||||||
if should_patch {
|
if should_patch {
|
||||||
if let Some(response_obj) = parsed_data
|
if let Some(response_obj) = parsed_data
|
||||||
@@ -622,13 +619,11 @@ pub(super) fn apply_event_transformations_inplace(
|
|||||||
|
|
||||||
// 2. Apply transform_streaming_event logic (function_call → mcp_call)
|
// 2. Apply transform_streaming_event logic (function_call → mcp_call)
|
||||||
match event_type.as_str() {
|
match event_type.as_str() {
|
||||||
event_types::OUTPUT_ITEM_ADDED | event_types::OUTPUT_ITEM_DONE => {
|
OutputItemEvent::ADDED | OutputItemEvent::DONE => {
|
||||||
if let Some(item) = parsed_data.get_mut("item") {
|
if let Some(item) = parsed_data.get_mut("item") {
|
||||||
if let Some(item_type) = item.get("type").and_then(|v| v.as_str()) {
|
if let Some(item_type) = item.get("type").and_then(|v| v.as_str()) {
|
||||||
if item_type == event_types::ITEM_TYPE_FUNCTION_CALL
|
if is_function_call_type(item_type) {
|
||||||
|| item_type == event_types::ITEM_TYPE_FUNCTION_TOOL_CALL
|
item["type"] = json!(ItemType::MCP_CALL);
|
||||||
{
|
|
||||||
item["type"] = json!(event_types::ITEM_TYPE_MCP_CALL);
|
|
||||||
item["server_label"] = json!(ctx.server_label);
|
item["server_label"] = json!(ctx.server_label);
|
||||||
|
|
||||||
// Transform ID from fc_* to mcp_*
|
// Transform ID from fc_* to mcp_*
|
||||||
@@ -644,8 +639,8 @@ pub(super) fn apply_event_transformations_inplace(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event_types::FUNCTION_CALL_ARGUMENTS_DONE => {
|
FunctionCallEvent::ARGUMENTS_DONE => {
|
||||||
parsed_data["type"] = json!(event_types::MCP_CALL_ARGUMENTS_DONE);
|
parsed_data["type"] = json!(McpEvent::CALL_ARGUMENTS_DONE);
|
||||||
|
|
||||||
// Transform item_id from fc_* to mcp_*
|
// Transform item_id from fc_* to mcp_*
|
||||||
if let Some(item_id) = parsed_data.get("item_id").and_then(|v| v.as_str()) {
|
if let Some(item_id) = parsed_data.get("item_id").and_then(|v| v.as_str()) {
|
||||||
@@ -691,7 +686,7 @@ pub(super) fn forward_streaming_event(
|
|||||||
sequence_number: &mut u64,
|
sequence_number: &mut u64,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Skip individual function_call_arguments.delta events - we'll send them as one
|
// Skip individual function_call_arguments.delta events - we'll send them as one
|
||||||
if event_name == Some(event_types::FUNCTION_CALL_ARGUMENTS_DELTA) {
|
if event_name == Some(FunctionCallEvent::ARGUMENTS_DELTA) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,14 +704,14 @@ pub(super) fn forward_streaming_event(
|
|||||||
.or_else(|| parsed_data.get("type").and_then(|v| v.as_str()))
|
.or_else(|| parsed_data.get("type").and_then(|v| v.as_str()))
|
||||||
.unwrap_or("");
|
.unwrap_or("");
|
||||||
|
|
||||||
if event_type == event_types::RESPONSE_COMPLETED {
|
if event_type == ResponseEvent::COMPLETED {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is function_call_arguments.done - need to send buffered args first
|
// Check if this is function_call_arguments.done - need to send buffered args first
|
||||||
let mut mapped_output_index: Option<usize> = None;
|
let mut mapped_output_index: Option<usize> = None;
|
||||||
|
|
||||||
if event_name == Some(event_types::FUNCTION_CALL_ARGUMENTS_DONE) {
|
if event_name == Some(FunctionCallEvent::ARGUMENTS_DONE) {
|
||||||
if let Some(output_index) = parsed_data
|
if let Some(output_index) = parsed_data
|
||||||
.get("output_index")
|
.get("output_index")
|
||||||
.and_then(|v| v.as_u64())
|
.and_then(|v| v.as_u64())
|
||||||
@@ -754,7 +749,7 @@ pub(super) fn forward_streaming_event(
|
|||||||
|
|
||||||
// Emit a synthetic MCP arguments delta event before the done event
|
// Emit a synthetic MCP arguments delta event before the done event
|
||||||
let mut delta_event = json!({
|
let mut delta_event = json!({
|
||||||
"type": event_types::MCP_CALL_ARGUMENTS_DELTA,
|
"type": McpEvent::CALL_ARGUMENTS_DELTA,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": assigned_index,
|
"output_index": assigned_index,
|
||||||
"item_id": mcp_item_id,
|
"item_id": mcp_item_id,
|
||||||
@@ -776,7 +771,7 @@ pub(super) fn forward_streaming_event(
|
|||||||
|
|
||||||
let delta_block = format!(
|
let delta_block = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::MCP_CALL_ARGUMENTS_DELTA,
|
McpEvent::CALL_ARGUMENTS_DELTA,
|
||||||
delta_event
|
delta_event
|
||||||
);
|
);
|
||||||
if tx.send(Ok(Bytes::from(delta_block))).is_err() {
|
if tx.send(Ok(Bytes::from(delta_block))).is_err() {
|
||||||
@@ -835,16 +830,10 @@ pub(super) fn forward_streaming_event(
|
|||||||
let mut final_block = String::new();
|
let mut final_block = String::new();
|
||||||
if let Some(evt) = event_name {
|
if let Some(evt) = event_name {
|
||||||
// Update event name for function_call_arguments events
|
// Update event name for function_call_arguments events
|
||||||
if evt == event_types::FUNCTION_CALL_ARGUMENTS_DELTA {
|
if evt == FunctionCallEvent::ARGUMENTS_DELTA {
|
||||||
final_block.push_str(&format!(
|
final_block.push_str(&format!("event: {}\n", McpEvent::CALL_ARGUMENTS_DELTA));
|
||||||
"event: {}\n",
|
} else if evt == FunctionCallEvent::ARGUMENTS_DONE {
|
||||||
event_types::MCP_CALL_ARGUMENTS_DELTA
|
final_block.push_str(&format!("event: {}\n", McpEvent::CALL_ARGUMENTS_DONE));
|
||||||
));
|
|
||||||
} else if evt == event_types::FUNCTION_CALL_ARGUMENTS_DONE {
|
|
||||||
final_block.push_str(&format!(
|
|
||||||
"event: {}\n",
|
|
||||||
event_types::MCP_CALL_ARGUMENTS_DONE
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
final_block.push_str(&format!("event: {}\n", evt));
|
final_block.push_str(&format!("event: {}\n", evt));
|
||||||
}
|
}
|
||||||
@@ -857,16 +846,16 @@ pub(super) fn forward_streaming_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// After sending output_item.added for mcp_call, inject mcp_call.in_progress event
|
// After sending output_item.added for mcp_call, inject mcp_call.in_progress event
|
||||||
if event_name == Some(event_types::OUTPUT_ITEM_ADDED) {
|
if event_name == Some(OutputItemEvent::ADDED) {
|
||||||
if let Some(item) = parsed_data.get("item") {
|
if let Some(item) = parsed_data.get("item") {
|
||||||
if item.get("type").and_then(|v| v.as_str()) == Some(event_types::ITEM_TYPE_MCP_CALL) {
|
if item.get("type").and_then(|v| v.as_str()) == Some(ItemType::MCP_CALL) {
|
||||||
// Already transformed to mcp_call
|
// Already transformed to mcp_call
|
||||||
if let (Some(item_id), Some(output_index)) = (
|
if let (Some(item_id), Some(output_index)) = (
|
||||||
item.get("id").and_then(|v| v.as_str()),
|
item.get("id").and_then(|v| v.as_str()),
|
||||||
parsed_data.get("output_index").and_then(|v| v.as_u64()),
|
parsed_data.get("output_index").and_then(|v| v.as_u64()),
|
||||||
) {
|
) {
|
||||||
let in_progress_event = json!({
|
let in_progress_event = json!({
|
||||||
"type": event_types::MCP_CALL_IN_PROGRESS,
|
"type": McpEvent::CALL_IN_PROGRESS,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"output_index": output_index,
|
"output_index": output_index,
|
||||||
"item_id": item_id
|
"item_id": item_id
|
||||||
@@ -874,7 +863,7 @@ pub(super) fn forward_streaming_event(
|
|||||||
*sequence_number += 1;
|
*sequence_number += 1;
|
||||||
let in_progress_block = format!(
|
let in_progress_block = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::MCP_CALL_IN_PROGRESS,
|
McpEvent::CALL_IN_PROGRESS,
|
||||||
in_progress_event
|
in_progress_event
|
||||||
);
|
);
|
||||||
if tx.send(Ok(Bytes::from(in_progress_block))).is_err() {
|
if tx.send(Ok(Bytes::from(in_progress_block))).is_err() {
|
||||||
@@ -928,7 +917,7 @@ pub(super) fn send_final_response_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let completed_payload = json!({
|
let completed_payload = json!({
|
||||||
"type": event_types::RESPONSE_COMPLETED,
|
"type": ResponseEvent::COMPLETED,
|
||||||
"sequence_number": *sequence_number,
|
"sequence_number": *sequence_number,
|
||||||
"response": final_response
|
"response": final_response
|
||||||
});
|
});
|
||||||
@@ -936,7 +925,7 @@ pub(super) fn send_final_response_event(
|
|||||||
|
|
||||||
let completed_event = format!(
|
let completed_event = format!(
|
||||||
"event: {}\ndata: {}\n\n",
|
"event: {}\ndata: {}\n\n",
|
||||||
event_types::RESPONSE_COMPLETED,
|
ResponseEvent::COMPLETED,
|
||||||
completed_payload
|
completed_payload
|
||||||
);
|
);
|
||||||
tx.send(Ok(Bytes::from(completed_event))).is_ok()
|
tx.send(Ok(Bytes::from(completed_event))).is_ok()
|
||||||
@@ -1241,8 +1230,8 @@ pub(super) async fn handle_streaming_with_tool_interception(
|
|||||||
{
|
{
|
||||||
matches!(
|
matches!(
|
||||||
parsed.get("type").and_then(|v| v.as_str()),
|
parsed.get("type").and_then(|v| v.as_str()),
|
||||||
Some(event_types::RESPONSE_CREATED)
|
Some(ResponseEvent::CREATED)
|
||||||
| Some(event_types::RESPONSE_IN_PROGRESS)
|
| Some(ResponseEvent::IN_PROGRESS)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -1273,7 +1262,7 @@ pub(super) async fn handle_streaming_with_tool_interception(
|
|||||||
serde_json::from_str::<Value>(data.as_ref())
|
serde_json::from_str::<Value>(data.as_ref())
|
||||||
{
|
{
|
||||||
if parsed.get("type").and_then(|v| v.as_str())
|
if parsed.get("type").and_then(|v| v.as_str())
|
||||||
== Some(event_types::RESPONSE_IN_PROGRESS)
|
== Some(ResponseEvent::IN_PROGRESS)
|
||||||
{
|
{
|
||||||
seen_in_progress = true;
|
seen_in_progress = true;
|
||||||
if !mcp_list_tools_sent {
|
if !mcp_list_tools_sent {
|
||||||
|
|||||||
@@ -1,43 +1,7 @@
|
|||||||
//! Utility types and constants for OpenAI router
|
//! Utility types for OpenAI router
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// SSE Event Type Constants
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/// SSE event type constants - single source of truth for event type strings
|
|
||||||
pub(crate) mod event_types {
|
|
||||||
// Response lifecycle events
|
|
||||||
pub const RESPONSE_CREATED: &str = "response.created";
|
|
||||||
pub const RESPONSE_IN_PROGRESS: &str = "response.in_progress";
|
|
||||||
pub const RESPONSE_COMPLETED: &str = "response.completed";
|
|
||||||
|
|
||||||
// Output item events
|
|
||||||
pub const OUTPUT_ITEM_ADDED: &str = "response.output_item.added";
|
|
||||||
pub const OUTPUT_ITEM_DONE: &str = "response.output_item.done";
|
|
||||||
pub const OUTPUT_ITEM_DELTA: &str = "response.output_item.delta";
|
|
||||||
|
|
||||||
// Function call events
|
|
||||||
pub const FUNCTION_CALL_ARGUMENTS_DELTA: &str = "response.function_call_arguments.delta";
|
|
||||||
pub const FUNCTION_CALL_ARGUMENTS_DONE: &str = "response.function_call_arguments.done";
|
|
||||||
|
|
||||||
// MCP call events
|
|
||||||
pub const MCP_CALL_ARGUMENTS_DELTA: &str = "response.mcp_call_arguments.delta";
|
|
||||||
pub const MCP_CALL_ARGUMENTS_DONE: &str = "response.mcp_call_arguments.done";
|
|
||||||
pub const MCP_CALL_IN_PROGRESS: &str = "response.mcp_call.in_progress";
|
|
||||||
pub const MCP_CALL_COMPLETED: &str = "response.mcp_call.completed";
|
|
||||||
pub const MCP_LIST_TOOLS_IN_PROGRESS: &str = "response.mcp_list_tools.in_progress";
|
|
||||||
pub const MCP_LIST_TOOLS_COMPLETED: &str = "response.mcp_list_tools.completed";
|
|
||||||
|
|
||||||
// Item types
|
|
||||||
pub const ITEM_TYPE_FUNCTION_CALL: &str = "function_call";
|
|
||||||
pub const ITEM_TYPE_FUNCTION_TOOL_CALL: &str = "function_tool_call";
|
|
||||||
pub const ITEM_TYPE_MCP_CALL: &str = "mcp_call";
|
|
||||||
pub const ITEM_TYPE_FUNCTION: &str = "function";
|
|
||||||
pub const ITEM_TYPE_MCP_LIST_TOOLS: &str = "mcp_list_tools";
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Stream Action Enum
|
// Stream Action Enum
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user