feat: introduce ClientRequest::SendUserTurn (#2345)
This adds a new request type, `SendUserTurn`, that makes it possible to submit a `Op::UserTurn` operation (introduced in #2329) to a conversation. This PR also adds a new integration test that verifies that changing from `AskForApproval::UnlessTrusted` to `AskForApproval::Never` mid-conversation ensures that an elicitation is no longer sent for running `python3 -c print(42)`. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2345). * __->__ #2345 * #2329 * #2343 * #2340 * #2338
This commit is contained in:
@@ -42,6 +42,8 @@ use crate::wire_format::RemoveConversationListenerParams;
|
||||
use crate::wire_format::RemoveConversationSubscriptionResponse;
|
||||
use crate::wire_format::SendUserMessageParams;
|
||||
use crate::wire_format::SendUserMessageResponse;
|
||||
use crate::wire_format::SendUserTurnParams;
|
||||
use crate::wire_format::SendUserTurnResponse;
|
||||
use codex_core::protocol::InputItem as CoreInputItem;
|
||||
use codex_core::protocol::Op;
|
||||
|
||||
@@ -78,6 +80,9 @@ impl CodexMessageProcessor {
|
||||
ClientRequest::SendUserMessage { request_id, params } => {
|
||||
self.send_user_message(request_id, params).await;
|
||||
}
|
||||
ClientRequest::SendUserTurn { request_id, params } => {
|
||||
self.send_user_turn(request_id, params).await;
|
||||
}
|
||||
ClientRequest::InterruptConversation { request_id, params } => {
|
||||
self.interrupt_conversation(request_id, params).await;
|
||||
}
|
||||
@@ -169,6 +174,58 @@ impl CodexMessageProcessor {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn send_user_turn(&self, request_id: RequestId, params: SendUserTurnParams) {
|
||||
let SendUserTurnParams {
|
||||
conversation_id,
|
||||
items,
|
||||
cwd,
|
||||
approval_policy,
|
||||
sandbox_policy,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
} = params;
|
||||
|
||||
let Ok(conversation) = self
|
||||
.conversation_manager
|
||||
.get_conversation(conversation_id.0)
|
||||
.await
|
||||
else {
|
||||
let error = JSONRPCErrorError {
|
||||
code: INVALID_REQUEST_ERROR_CODE,
|
||||
message: format!("conversation not found: {conversation_id}"),
|
||||
data: None,
|
||||
};
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let mapped_items: Vec<CoreInputItem> = items
|
||||
.into_iter()
|
||||
.map(|item| match item {
|
||||
WireInputItem::Text { text } => CoreInputItem::Text { text },
|
||||
WireInputItem::Image { image_url } => CoreInputItem::Image { image_url },
|
||||
WireInputItem::LocalImage { path } => CoreInputItem::LocalImage { path },
|
||||
})
|
||||
.collect();
|
||||
|
||||
let _ = conversation
|
||||
.submit(Op::UserTurn {
|
||||
items: mapped_items,
|
||||
cwd,
|
||||
approval_policy,
|
||||
sandbox_policy,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
})
|
||||
.await;
|
||||
|
||||
self.outgoing
|
||||
.send_response(request_id, SendUserTurnResponse {})
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn interrupt_conversation(
|
||||
&mut self,
|
||||
request_id: RequestId,
|
||||
|
||||
Reference in New Issue
Block a user