fix: 8531 - elicitation fixes (#8999)
Signed-off-by: Alex Hancock <alexhancock@block.xyz>
This commit is contained in:
@@ -11,9 +11,25 @@ pub fn collect_elicitation_input(
|
||||
println!("\n{}", style(message).cyan());
|
||||
}
|
||||
|
||||
let properties = match schema.get("properties").and_then(|p| p.as_object()) {
|
||||
Some(props) => props,
|
||||
None => return Ok(Some(HashMap::new())),
|
||||
let properties = schema.get("properties").and_then(|p| p.as_object());
|
||||
|
||||
// Schema-less (or empty-schema) elicitations are pure approval prompts —
|
||||
// offer an explicit Y/N confirmation instead of silently auto-accepting.
|
||||
let properties = match properties {
|
||||
Some(props) if !props.is_empty() => props,
|
||||
_ => {
|
||||
let prompt = if message.is_empty() {
|
||||
"Approve this action?"
|
||||
} else {
|
||||
"Approve?"
|
||||
};
|
||||
return match cliclack::confirm(prompt).initial_value(true).interact() {
|
||||
Ok(true) => Ok(Some(HashMap::new())),
|
||||
Ok(false) => Ok(None),
|
||||
Err(e) if e.kind() == io::ErrorKind::Interrupted => Ok(None),
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let required: Vec<&str> = schema
|
||||
|
||||
@@ -313,6 +313,38 @@ pub async fn session_reply(
|
||||
}
|
||||
}
|
||||
|
||||
let user_message = request.user_message;
|
||||
let override_conversation = request.override_conversation;
|
||||
|
||||
// An elicitation response unblocks an in-flight tool call that is already
|
||||
// streaming on another request_id — don't register a new active request or
|
||||
// open a new SSE stream; route it to the agent's short-circuit path.
|
||||
let is_elicitation_response = user_message.content.iter().any(|c| {
|
||||
matches!(
|
||||
c,
|
||||
goose::conversation::message::MessageContent::ActionRequired(ar)
|
||||
if matches!(
|
||||
ar.data,
|
||||
goose::conversation::message::ActionRequiredData::ElicitationResponse { .. }
|
||||
)
|
||||
)
|
||||
});
|
||||
|
||||
if is_elicitation_response {
|
||||
let agent = state.get_agent_for_route(session_id.clone()).await?;
|
||||
let session_config = goose::agents::types::SessionConfig {
|
||||
id: session_id.clone(),
|
||||
schedule_id: session_data.schedule_id.clone(),
|
||||
max_turns: None,
|
||||
retry_config: None,
|
||||
};
|
||||
let _ = agent
|
||||
.reply(user_message, session_config, None)
|
||||
.await
|
||||
.map_err(|e| ErrorResponse::internal(e.to_string()))?;
|
||||
return Ok(Json(SessionReplyResponse { request_id }));
|
||||
}
|
||||
|
||||
let bus = state.get_or_create_event_bus(&session_id).await;
|
||||
|
||||
let cancel_token = bus
|
||||
@@ -322,9 +354,6 @@ pub async fn session_reply(
|
||||
ErrorResponse::bad_request("Session already has an active request. Cancel it first.")
|
||||
})?;
|
||||
|
||||
let user_message = request.user_message;
|
||||
let override_conversation = request.override_conversation;
|
||||
|
||||
let task_state = state.clone();
|
||||
let task_session_id = session_id.clone();
|
||||
let task_request_id = request_id.clone();
|
||||
|
||||
@@ -1042,18 +1042,19 @@ impl Agent {
|
||||
if let ActionRequiredData::ElicitationResponse { id, user_data } =
|
||||
&action_required.data
|
||||
{
|
||||
if let Err(e) = ActionRequiredManager::global()
|
||||
// Surface stale/cancelled/timed-out elicitations as a hard
|
||||
// error so callers (e.g. the HTTP handler) can propagate
|
||||
// failure to the client instead of silently reporting
|
||||
// success while the blocked tool call stays unblocked.
|
||||
// The success path returns an empty stream; an Err here
|
||||
// makes the contract: Ok(empty) on accept, Err on reject.
|
||||
ActionRequiredManager::global()
|
||||
.submit_response(id.clone(), user_data.clone())
|
||||
.await
|
||||
{
|
||||
let error_text = format!("Failed to submit elicitation response: {}", e);
|
||||
error!(error_text);
|
||||
return Ok(Box::pin(stream::once(async {
|
||||
Ok(AgentEvent::Message(
|
||||
Message::assistant().with_text(error_text),
|
||||
))
|
||||
})));
|
||||
}
|
||||
.map_err(|e| {
|
||||
error!("Failed to submit elicitation response: {}", e);
|
||||
anyhow!("Failed to submit elicitation response: {}", e)
|
||||
})?;
|
||||
session_manager
|
||||
.add_message(&session_config.id, &user_message)
|
||||
.await?;
|
||||
|
||||
Reference in New Issue
Block a user