mirror of
https://github.com/openai/codex.git
synced 2026-11-05 16:29:31 +00:00
Use the originating model when recording conversation history (#44243)
## Why History recording used the model captured at turn start, so switching models within a turn could apply stale image preparation and tool-output truncation rules. ## What changed Pass explicit model metadata through conversation recording. Record model responses and tool results using their originating step's settings, and capture the current model for pending input recorded during startup interruption or task completion. ## Testing Add regression coverage for tool results across a model switch, explicit model selection for plain and annotated history, and image input retained during interruption and completion. Extend model-switching tests to verify that prepared media and item identity survive switching back to a multimodal model in live, resumed, and forked threads. GitOrigin-RevId: 5bc750c30c334acb9b802cb80fdea01daffa84a1
This commit is contained in:
1 parent
205f3671e1
commit
b64de2f3ad
28 files changed
+721
-123
No files matched your search
@@ -12,6 +12,7 @@ use tokio_util::sync::CancellationToken;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::parse_turn_item;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::parallel::ToolCallRuntime;
|
||||
use crate::tools::router::ToolRouter;
|
||||
@@ -77,12 +78,12 @@ pub(crate) fn raw_assistant_output_text_from_item(item: &ResponseItem) -> Option
|
||||
/// Persist a completed model response item and record any cited memory usage.
|
||||
pub(crate) async fn record_completed_response_item(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
item: &ResponseItem,
|
||||
) {
|
||||
record_completed_response_item_with_finalized_facts(
|
||||
sess,
|
||||
turn_context,
|
||||
step_context,
|
||||
item,
|
||||
/*finalized_facts*/ None,
|
||||
)
|
||||
@@ -91,12 +92,17 @@ pub(crate) async fn record_completed_response_item(
|
||||
|
||||
pub(crate) async fn record_completed_response_item_with_finalized_facts(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
item: &ResponseItem,
|
||||
finalized_facts: Option<&FinalizedTurnItemFacts>,
|
||||
) {
|
||||
sess.record_conversation_items(turn_context, std::slice::from_ref(item))
|
||||
.await;
|
||||
let turn_context = &step_context.turn;
|
||||
sess.record_conversation_items(
|
||||
turn_context,
|
||||
&step_context.settings.model_info,
|
||||
std::slice::from_ref(item),
|
||||
)
|
||||
.await;
|
||||
let defers_mailbox_delivery = finalized_facts.map_or_else(
|
||||
|| {
|
||||
completed_item_defers_mailbox_delivery_to_next_turn(
|
||||
@@ -206,7 +212,7 @@ pub(crate) struct OutputItemResult {
|
||||
|
||||
pub(crate) struct HandleOutputCtx {
|
||||
pub sess: Arc<Session>,
|
||||
pub turn_context: Arc<TurnContext>,
|
||||
pub step_context: Arc<StepContext>,
|
||||
pub turn_store: Arc<ExtensionData>,
|
||||
pub tool_runtime: ToolCallRuntime,
|
||||
pub cancellation_token: CancellationToken,
|
||||
@@ -296,7 +302,7 @@ pub(crate) async fn handle_output_item_done(
|
||||
previously_active_item: Option<TurnItem>,
|
||||
) -> Result<OutputItemResult> {
|
||||
let mut output = OutputItemResult::default();
|
||||
let plan_mode = ctx.turn_context.mode() == ModeKind::Plan;
|
||||
let plan_mode = ctx.step_context.turn.mode() == ModeKind::Plan;
|
||||
|
||||
match ToolRouter::build_tool_call(item.clone()) {
|
||||
// The model emitted a tool call; log it, persist the item immediately, and queue the tool execution.
|
||||
@@ -305,7 +311,7 @@ pub(crate) async fn handle_output_item_done(
|
||||
.input_queue
|
||||
.accept_mailbox_delivery_for_current_turn(
|
||||
&ctx.sess.active_turn,
|
||||
&ctx.turn_context.sub_id,
|
||||
&ctx.step_context.turn.sub_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -317,7 +323,7 @@ pub(crate) async fn handle_output_item_done(
|
||||
payload_preview
|
||||
);
|
||||
|
||||
record_completed_response_item(ctx.sess.as_ref(), ctx.turn_context.as_ref(), &item)
|
||||
record_completed_response_item(ctx.sess.as_ref(), ctx.step_context.as_ref(), &item)
|
||||
.await;
|
||||
|
||||
let cancellation_token = ctx.cancellation_token.child_token();
|
||||
@@ -345,17 +351,20 @@ pub(crate) async fn handle_output_item_done(
|
||||
if let Some(finalized_turn_item) = finalized_turn_item {
|
||||
if previously_active_item.is_none() {
|
||||
ctx.sess
|
||||
.emit_turn_item_started(&ctx.turn_context, &finalized_turn_item.turn_item)
|
||||
.emit_turn_item_started(
|
||||
&ctx.step_context.turn,
|
||||
&finalized_turn_item.turn_item,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
ctx.sess
|
||||
.emit_turn_item_completed(&ctx.turn_context, finalized_turn_item.turn_item)
|
||||
.emit_turn_item_completed(&ctx.step_context.turn, finalized_turn_item.turn_item)
|
||||
.await;
|
||||
}
|
||||
record_completed_response_item_with_finalized_facts(
|
||||
ctx.sess.as_ref(),
|
||||
ctx.turn_context.as_ref(),
|
||||
ctx.step_context.as_ref(),
|
||||
&item,
|
||||
finalized_facts.as_ref(),
|
||||
)
|
||||
@@ -372,12 +381,13 @@ pub(crate) async fn handle_output_item_done(
|
||||
..Default::default()
|
||||
},
|
||||
};
|
||||
record_completed_response_item(ctx.sess.as_ref(), ctx.turn_context.as_ref(), &item)
|
||||
record_completed_response_item(ctx.sess.as_ref(), ctx.step_context.as_ref(), &item)
|
||||
.await;
|
||||
if let Some(response_item) = response_input_to_response_item(&response) {
|
||||
ctx.sess
|
||||
.record_conversation_items(
|
||||
&ctx.turn_context,
|
||||
&ctx.step_context.turn,
|
||||
&ctx.step_context.settings.model_info,
|
||||
std::slice::from_ref(&response_item),
|
||||
)
|
||||
.await;
|
||||
|
||||
Reference in new issue
Block a user