Fixing bug where canceled tool calls may cause terminal to freeze
This commit is contained in:
@@ -500,7 +500,7 @@ fn build_tool_call_message(
|
|||||||
api::message::tool_call::RunShellCommand {
|
api::message::tool_call::RunShellCommand {
|
||||||
command,
|
command,
|
||||||
is_read_only: false,
|
is_read_only: false,
|
||||||
uses_pager: false,
|
uses_pager: true,
|
||||||
citations: vec![],
|
citations: vec![],
|
||||||
is_risky: false,
|
is_risky: false,
|
||||||
risk_category: 0,
|
risk_category: 0,
|
||||||
|
|||||||
@@ -236,9 +236,16 @@ impl ShellCommandExecutor {
|
|||||||
.active_block()
|
.active_block()
|
||||||
.is_active_and_long_running()
|
.is_active_and_long_running()
|
||||||
{
|
{
|
||||||
// If there is an active block, we can't execute another command.
|
// Another command is still running (e.g. stuck in a pager). Return an error
|
||||||
|
// result so the model receives feedback and can adapt. Using Completed with a
|
||||||
|
// non-zero exit code ensures a follow-up request is triggered.
|
||||||
return ActionExecution::Sync(AIAgentActionResultType::RequestCommandOutput(
|
return ActionExecution::Sync(AIAgentActionResultType::RequestCommandOutput(
|
||||||
RequestCommandOutputResult::CancelledBeforeExecution,
|
RequestCommandOutputResult::Completed {
|
||||||
|
command: command.clone(),
|
||||||
|
block_id: model.block_list().active_block().id().clone(),
|
||||||
|
output: "Error: Cannot execute command because another command is still running in the terminal.".to_string(),
|
||||||
|
exit_code: ExitCode::from(1),
|
||||||
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// If the command might use pager and can't be interacted with,
|
// If the command might use pager and can't be interacted with,
|
||||||
|
|||||||
@@ -2417,7 +2417,11 @@ impl BlocklistAIController {
|
|||||||
log::warn!("Conversation not found.");
|
log::warn!("Conversation not found.");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let new_exchange_ids = conversation.new_exchange_ids_for_response(&stream_id);
|
let new_exchange_ids: Vec<_> = conversation.new_exchange_ids_for_response(&stream_id).collect();
|
||||||
|
log::info!(
|
||||||
|
"[bedrock-debug] AfterStreamFinished: stream_id={:?}, conversation_id={:?}, new_exchange_ids count={}",
|
||||||
|
stream_id, conversation_id, new_exchange_ids.len()
|
||||||
|
);
|
||||||
let mut was_passive_request = false;
|
let mut was_passive_request = false;
|
||||||
let mut is_any_exchange_unfinished = false;
|
let mut is_any_exchange_unfinished = false;
|
||||||
let mut actions_to_queue = vec![];
|
let mut actions_to_queue = vec![];
|
||||||
@@ -2429,12 +2433,30 @@ impl BlocklistAIController {
|
|||||||
};
|
};
|
||||||
was_passive_request |= exchange.has_passive_request();
|
was_passive_request |= exchange.has_passive_request();
|
||||||
is_any_exchange_unfinished |= !exchange.output_status.is_finished();
|
is_any_exchange_unfinished |= !exchange.output_status.is_finished();
|
||||||
|
log::info!(
|
||||||
|
"[bedrock-debug] AfterStreamFinished: exchange_id={:?}, is_finished={}, output_status={:?}",
|
||||||
|
new_exchange_id,
|
||||||
|
exchange.output_status.is_finished(),
|
||||||
|
std::mem::discriminant(&exchange.output_status)
|
||||||
|
);
|
||||||
|
|
||||||
if let AIAgentOutputStatus::Finished {
|
if let AIAgentOutputStatus::Finished {
|
||||||
finished_output: FinishedAIAgentOutput::Success { output },
|
finished_output: FinishedAIAgentOutput::Success { output },
|
||||||
..
|
..
|
||||||
} = &exchange.output_status
|
} = &exchange.output_status
|
||||||
{
|
{
|
||||||
|
let action_count = output.get().actions().count();
|
||||||
|
let msg_count = output.get().messages.len();
|
||||||
|
log::info!(
|
||||||
|
"[bedrock-debug] AfterStreamFinished: output has {} messages, {} actions",
|
||||||
|
msg_count, action_count
|
||||||
|
);
|
||||||
|
for msg in output.get().messages.iter() {
|
||||||
|
log::info!(
|
||||||
|
"[bedrock-debug] AfterStreamFinished: msg type={:?}",
|
||||||
|
std::mem::discriminant(&msg.message)
|
||||||
|
);
|
||||||
|
}
|
||||||
actions_to_queue.extend(output.get().actions().cloned());
|
actions_to_queue.extend(output.get().actions().cloned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2484,9 +2506,18 @@ impl BlocklistAIController {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else if !actions_to_queue.is_empty() {
|
} else if !actions_to_queue.is_empty() {
|
||||||
|
log::info!(
|
||||||
|
"[bedrock-debug] AfterStreamFinished: queuing {} actions",
|
||||||
|
actions_to_queue.len()
|
||||||
|
);
|
||||||
self.action_model.update(ctx, |action_model, ctx| {
|
self.action_model.update(ctx, |action_model, ctx| {
|
||||||
action_model.queue_actions(actions_to_queue, conversation_id, ctx);
|
action_model.queue_actions(actions_to_queue, conversation_id, ctx);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
log::warn!(
|
||||||
|
"[bedrock-debug] AfterStreamFinished: NO actions to queue, was_passive={}, is_any_unfinished={}",
|
||||||
|
was_passive_request, is_any_exchange_unfinished
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancelled streams will handle pending_response_stream updates synchronously.
|
// Cancelled streams will handle pending_response_stream updates synchronously.
|
||||||
|
|||||||
Reference in New Issue
Block a user