diff --git a/crates/agent/src/agent_diff.rs b/crates/agent/src/agent_diff.rs index d83b2cf80df1a57bc9ad3444eadf196d10112a7f..cb6934bb4088c048e23513709c1262cd98095a84 100644 --- a/crates/agent/src/agent_diff.rs +++ b/crates/agent/src/agent_diff.rs @@ -1348,6 +1348,7 @@ impl AgentDiff { ThreadEvent::NewRequest | ThreadEvent::Stopped(Ok(StopReason::EndTurn)) | ThreadEvent::Stopped(Ok(StopReason::MaxTokens)) + | ThreadEvent::Stopped(Ok(StopReason::Refusal)) | ThreadEvent::Stopped(Err(_)) | ThreadEvent::ShowError(_) | ThreadEvent::CompletionCanceled => { diff --git a/crates/agent/src/thread.rs b/crates/agent/src/thread.rs index b73e102444ae1641bdd6ee5bea065d25c18da537..2e61cf3cfccb89d6793b1527a3209409d18643cc 100644 --- a/crates/agent/src/thread.rs +++ b/crates/agent/src/thread.rs @@ -1693,6 +1693,16 @@ impl Thread { project.set_agent_location(None, cx); }); } + StopReason::Refusal => { + thread.project.update(cx, |project, cx| { + project.set_agent_location(None, cx); + }); + + cx.emit (ThreadEvent::ShowError(ThreadError::Message { + header: "Language model refusal".into(), + message: "Model refused to generate content for safety reasons.".into(), + })); + } }, Err(error) => { thread.project.update(cx, |project, cx| { diff --git a/crates/assistant_context_editor/src/context.rs b/crates/assistant_context_editor/src/context.rs index 0ee475f100ef4174477649f95a8ed057bfacced3..99092775d0175c59b8c53d1ff5fa2f30a0befe4c 100644 --- a/crates/assistant_context_editor/src/context.rs +++ b/crates/assistant_context_editor/src/context.rs @@ -2204,6 +2204,7 @@ impl AssistantContext { StopReason::ToolUse => {} StopReason::EndTurn => {} StopReason::MaxTokens => {} + StopReason::Refusal => {} } } }) diff --git a/crates/eval/src/example.rs b/crates/eval/src/example.rs index 033efd67aa98ca22e05e402099210e9c97d59706..ed7f139d28365d7ecbf4189d724693262c25a30f 100644 --- a/crates/eval/src/example.rs +++ b/crates/eval/src/example.rs @@ -231,6 +231,10 @@ impl ExampleContext { Ok(StopReason::MaxTokens) => { tx.try_send(Err(anyhow!("Exceeded maximum tokens"))).ok(); } + Ok(StopReason::Refusal) => { + tx.try_send(Err(anyhow!("Model refused to generate content"))) + .ok(); + } Err(err) => { tx.try_send(Err(anyhow!(err.clone()))).ok(); } diff --git a/crates/language_model/src/language_model.rs b/crates/language_model/src/language_model.rs index 124e8cda1e51761a8b15e29a453e0ffa72c3eed9..51b53ada227a05efddf93e80b84d8e168730117f 100644 --- a/crates/language_model/src/language_model.rs +++ b/crates/language_model/src/language_model.rs @@ -100,6 +100,7 @@ pub enum StopReason { EndTurn, MaxTokens, ToolUse, + Refusal, } #[derive(Debug, Clone, Copy)] diff --git a/crates/language_models/src/provider/anthropic.rs b/crates/language_models/src/provider/anthropic.rs index c6a9a808bdeff04ae2168a82ff9d516ede21510a..f9dc7af3dcb5559bbf056c1681cb49c4cd9b3d15 100644 --- a/crates/language_models/src/provider/anthropic.rs +++ b/crates/language_models/src/provider/anthropic.rs @@ -825,6 +825,7 @@ impl AnthropicEventMapper { "end_turn" => StopReason::EndTurn, "max_tokens" => StopReason::MaxTokens, "tool_use" => StopReason::ToolUse, + "refusal" => StopReason::Refusal, _ => { log::error!("Unexpected anthropic stop_reason: {stop_reason}"); StopReason::EndTurn