mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Accept user input when starting idle turns (#36947)
## What changed - Generalize `CodexThread::try_start_turn_if_idle` to accept exported `TurnInput` values, preserving user content and client IDs in the first model request. - Allow non-empty user input to start an idle turn in Plan mode while retaining the Plan-mode rejection for automatic response items and empty user input. - Process idle user input through the normal user-turn path so connector selections are cleared, prompt telemetry is recorded, and referenced skill instructions are included. ## Testing - Cover idle user input in Default and Plan modes, response-item mailbox merging, empty-input rejection, and skill instruction injection. GitOrigin-RevId: 116667d160d4464b525d9e4c7e8cc05d23a94008
This commit is contained in:
1 parent
ceaa818898
commit
989a0b053e
9 files changed
+309
-34
No files matched your search
@@ -36,27 +36,31 @@ impl Session {
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts a regular turn with the provided items only if automatic idle work
|
||||
/// Starts a regular turn with the provided input only if automatic idle work
|
||||
/// is allowed for the current session state.
|
||||
///
|
||||
/// This is the shared gate for extension-initiated idle work. It refuses to
|
||||
/// start a turn when user/client-triggered work is queued, any task is still
|
||||
/// active, or the session is currently in Plan mode. Active Review tasks are
|
||||
/// covered by the active-task check because Review turns are not steerable.
|
||||
/// start a turn when user/client-triggered work is queued or any task is
|
||||
/// still active. Work without user input is also rejected in Plan mode.
|
||||
/// Active Review tasks are covered by the active-task check because Review
|
||||
/// turns are not steerable.
|
||||
pub(crate) async fn try_start_turn_if_idle(
|
||||
self: &Arc<Self>,
|
||||
input: Vec<ResponseItem>,
|
||||
input: Vec<TurnInput>,
|
||||
) -> Result<(), TryStartTurnIfIdleError> {
|
||||
if input.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let has_user_input = input.iter().any(
|
||||
|item| matches!(item, TurnInput::UserInput { content, .. } if !content.is_empty()),
|
||||
);
|
||||
if self.input_queue.has_trigger_turn_mailbox_items().await {
|
||||
return Err(TryStartTurnIfIdleError::new(
|
||||
TryStartTurnIfIdleRejectionReason::PendingTriggerTurn,
|
||||
input,
|
||||
));
|
||||
}
|
||||
if self.collaboration_mode().await.mode == ModeKind::Plan {
|
||||
if !has_user_input && self.collaboration_mode().await.mode == ModeKind::Plan {
|
||||
return Err(TryStartTurnIfIdleError::new(
|
||||
TryStartTurnIfIdleRejectionReason::PlanMode,
|
||||
input,
|
||||
@@ -87,7 +91,7 @@ impl Session {
|
||||
let turn_context = self
|
||||
.new_default_turn_with_sub_id(uuid::Uuid::new_v4().to_string())
|
||||
.await;
|
||||
if turn_context.mode == ModeKind::Plan {
|
||||
if !has_user_input && turn_context.mode == ModeKind::Plan {
|
||||
self.clear_reserved_idle_turn(&turn_state).await;
|
||||
self.maybe_start_turn_for_pending_work().await;
|
||||
return Err(TryStartTurnIfIdleError::new(
|
||||
@@ -119,15 +123,23 @@ impl Session {
|
||||
));
|
||||
}
|
||||
|
||||
self.input_queue
|
||||
.extend_pending_input_for_turn_state(
|
||||
turn_state.as_ref(),
|
||||
input.into_iter().map(TurnInput::ResponseItem).collect(),
|
||||
)
|
||||
.await;
|
||||
let task_input = if has_user_input {
|
||||
self.clear_connector_selection().await;
|
||||
for item in &input {
|
||||
if let TurnInput::UserInput { content, .. } = item {
|
||||
turn_context.session_telemetry.user_prompt(content);
|
||||
}
|
||||
}
|
||||
input
|
||||
} else {
|
||||
self.input_queue
|
||||
.extend_pending_input_for_turn_state(turn_state.as_ref(), input)
|
||||
.await;
|
||||
Vec::new()
|
||||
};
|
||||
self.start_task(
|
||||
turn_context,
|
||||
Vec::new(),
|
||||
task_input,
|
||||
RegularTask::new(),
|
||||
MailboxParentProvenance::Ignore,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user