feat: ActionRequired (#5897)
This commit is contained in:
@@ -73,7 +73,7 @@ impl Agent {
|
||||
});
|
||||
|
||||
let confirmation = Message::assistant()
|
||||
.with_tool_confirmation_request(
|
||||
.with_action_required(
|
||||
request.id.clone(),
|
||||
tool_call.name.to_string().clone(),
|
||||
tool_call.arguments.clone().unwrap_or_default(),
|
||||
|
||||
@@ -375,6 +375,14 @@ fn format_message_for_compacting(msg: &Message) -> String {
|
||||
MessageContent::ToolConfirmationRequest(req) => {
|
||||
format!("tool_confirmation_request: {}", req.tool_name)
|
||||
}
|
||||
MessageContent::ActionRequired(action) => match &action.data {
|
||||
crate::conversation::message::ActionRequiredData::ToolConfirmation {
|
||||
tool_name,
|
||||
..
|
||||
} => {
|
||||
format!("action_required(tool_confirmation): {}", tool_name)
|
||||
}
|
||||
},
|
||||
MessageContent::FrontendToolRequest(req) => {
|
||||
if let Ok(call) = &req.tool_call {
|
||||
format!("frontend_tool_request: {}", call.name)
|
||||
|
||||
@@ -101,6 +101,24 @@ pub struct ToolConfirmationRequest {
|
||||
pub prompt: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(tag = "actionType", rename_all = "camelCase")]
|
||||
pub enum ActionRequiredData {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
ToolConfirmation {
|
||||
id: String,
|
||||
tool_name: String,
|
||||
arguments: JsonObject,
|
||||
prompt: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ActionRequired {
|
||||
pub data: ActionRequiredData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ThinkingContent {
|
||||
pub thinking: String,
|
||||
@@ -144,6 +162,7 @@ pub enum MessageContent {
|
||||
ToolRequest(ToolRequest),
|
||||
ToolResponse(ToolResponse),
|
||||
ToolConfirmationRequest(ToolConfirmationRequest),
|
||||
ActionRequired(ActionRequired),
|
||||
FrontendToolRequest(FrontendToolRequest),
|
||||
Thinking(ThinkingContent),
|
||||
RedactedThinking(RedactedThinkingContent),
|
||||
@@ -169,6 +188,11 @@ impl fmt::Display for MessageContent {
|
||||
MessageContent::ToolConfirmationRequest(r) => {
|
||||
write!(f, "[ToolConfirmationRequest: {}]", r.tool_name)
|
||||
}
|
||||
MessageContent::ActionRequired(a) => match &a.data {
|
||||
ActionRequiredData::ToolConfirmation { tool_name, .. } => {
|
||||
write!(f, "[ActionRequired: ToolConfirmation for {}]", tool_name)
|
||||
}
|
||||
},
|
||||
MessageContent::FrontendToolRequest(r) => match &r.tool_call {
|
||||
Ok(tool_call) => write!(f, "[FrontendToolRequest: {}]", tool_call.name),
|
||||
Err(e) => write!(f, "[FrontendToolRequest: Error: {}]", e),
|
||||
@@ -234,17 +258,19 @@ impl MessageContent {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn tool_confirmation_request<S: Into<String>>(
|
||||
pub fn action_required<S: Into<String>>(
|
||||
id: S,
|
||||
tool_name: String,
|
||||
arguments: JsonObject,
|
||||
prompt: Option<String>,
|
||||
) -> Self {
|
||||
MessageContent::ToolConfirmationRequest(ToolConfirmationRequest {
|
||||
id: id.into(),
|
||||
tool_name,
|
||||
arguments,
|
||||
prompt,
|
||||
MessageContent::ActionRequired(ActionRequired {
|
||||
data: ActionRequiredData::ToolConfirmation {
|
||||
id: id.into(),
|
||||
tool_name,
|
||||
arguments,
|
||||
prompt,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -303,9 +329,9 @@ impl MessageContent {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_tool_confirmation_request(&self) -> Option<&ToolConfirmationRequest> {
|
||||
if let MessageContent::ToolConfirmationRequest(ref tool_confirmation_request) = self {
|
||||
Some(tool_confirmation_request)
|
||||
pub fn as_action_required(&self) -> Option<&ActionRequired> {
|
||||
if let MessageContent::ActionRequired(ref action_required) = self {
|
||||
Some(action_required)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -582,15 +608,15 @@ impl Message {
|
||||
self.with_content(MessageContent::tool_response(id, result))
|
||||
}
|
||||
|
||||
/// Add a tool confirmation request to the message
|
||||
pub fn with_tool_confirmation_request<S: Into<String>>(
|
||||
/// Add an action required message for tool confirmation
|
||||
pub fn with_action_required<S: Into<String>>(
|
||||
self,
|
||||
id: S,
|
||||
tool_name: String,
|
||||
arguments: JsonObject,
|
||||
prompt: Option<String>,
|
||||
) -> Self {
|
||||
self.with_content(MessageContent::tool_confirmation_request(
|
||||
self.with_content(MessageContent::action_required(
|
||||
id, tool_name, arguments, prompt,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -91,6 +91,9 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
MessageContent::ToolConfirmationRequest(_tool_confirmation_request) => {
|
||||
// Skip tool confirmation requests
|
||||
}
|
||||
MessageContent::ActionRequired(_action_required) => {
|
||||
// Skip action required messages - they're for UI only
|
||||
}
|
||||
MessageContent::SystemNotification(_) => {
|
||||
// Skip
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@ pub fn to_bedrock_message_content(content: &MessageContent) -> Result<bedrock::C
|
||||
MessageContent::ToolConfirmationRequest(_tool_confirmation_request) => {
|
||||
bedrock::ContentBlock::Text("".to_string())
|
||||
}
|
||||
MessageContent::ActionRequired(_action_required) => {
|
||||
bedrock::ContentBlock::Text("".to_string())
|
||||
}
|
||||
MessageContent::Image(image) => {
|
||||
bedrock::ContentBlock::Image(to_bedrock_image(&image.data, &image.mime_type)?)
|
||||
}
|
||||
|
||||
@@ -208,9 +208,8 @@ fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<Data
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageContent::ToolConfirmationRequest(_) => {
|
||||
// Skip tool confirmation requests
|
||||
}
|
||||
MessageContent::ToolConfirmationRequest(_) => {}
|
||||
MessageContent::ActionRequired(_) => {}
|
||||
MessageContent::Image(image) => {
|
||||
content_array.push(convert_image(image, image_format));
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
.iter()
|
||||
.filter(|m| m.is_agent_visible())
|
||||
.filter(|message| {
|
||||
message
|
||||
.content
|
||||
.iter()
|
||||
.any(|content| !matches!(content, MessageContent::ToolConfirmationRequest(_)))
|
||||
message.content.iter().any(|content| {
|
||||
!matches!(
|
||||
content,
|
||||
MessageContent::ToolConfirmationRequest(_) | MessageContent::ActionRequired(_)
|
||||
)
|
||||
})
|
||||
})
|
||||
.map(|message| {
|
||||
let role = if message.role == Role::User {
|
||||
@@ -408,11 +410,11 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
fn set_up_tool_confirmation_message(id: &str, tool_call: CallToolRequestParam) -> Message {
|
||||
fn set_up_action_required_message(id: &str, tool_call: CallToolRequestParam) -> Message {
|
||||
Message::new(
|
||||
Role::User,
|
||||
0,
|
||||
vec![MessageContent::tool_confirmation_request(
|
||||
vec![MessageContent::action_required(
|
||||
id.to_string(),
|
||||
tool_call.name.to_string().clone(),
|
||||
tool_call.arguments.unwrap_or_default().clone(),
|
||||
@@ -474,7 +476,7 @@ mod tests {
|
||||
arguments: Some(object(arguments.clone())),
|
||||
},
|
||||
),
|
||||
set_up_tool_confirmation_message(
|
||||
set_up_action_required_message(
|
||||
"id2",
|
||||
CallToolRequestParam {
|
||||
name: "tool_name_2".into(),
|
||||
|
||||
@@ -198,9 +198,8 @@ pub fn format_messages(messages: &[Message], image_format: &ImageFormat) -> Vec<
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageContent::ToolConfirmationRequest(_) => {
|
||||
// Skip tool confirmation requests
|
||||
}
|
||||
MessageContent::ToolConfirmationRequest(_) => {}
|
||||
MessageContent::ActionRequired(_) => {}
|
||||
MessageContent::Image(image) => {
|
||||
content_array.push(convert_image(image, image_format));
|
||||
}
|
||||
|
||||
@@ -50,9 +50,8 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageContent::ToolConfirmationRequest(_) => {
|
||||
// Skip tool confirmation requests
|
||||
}
|
||||
MessageContent::ToolConfirmationRequest(_) => {}
|
||||
MessageContent::ActionRequired(_) => {}
|
||||
MessageContent::SystemNotification(_) => {
|
||||
// Skip
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user